Add convAI plugin
This commit is contained in:
193
ConvAI/Convai/Source/Convai/Convai.Build.cs
Normal file
193
ConvAI/Convai/Source/Convai/Convai.Build.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
// using Tools.DotNETCommon;
|
||||
|
||||
|
||||
|
||||
public class Convai : ModuleRules
|
||||
{
|
||||
private static ConvaiPlatform ConvaiPlatformInstance;
|
||||
|
||||
private string ModulePath
|
||||
{
|
||||
get { return ModuleDirectory; }
|
||||
}
|
||||
|
||||
private string ThirdPartyPath
|
||||
{
|
||||
get { return Path.GetFullPath(Path.Combine(ModulePath, "../ThirdParty/")); }
|
||||
}
|
||||
|
||||
private ConvaiPlatform GetConvaiPlatformInstance(ReadOnlyTargetRules Target)
|
||||
{
|
||||
var ConvaiPlatformType = System.Type.GetType("ConvaiPlatform_" + Target.Platform.ToString());
|
||||
if (ConvaiPlatformType == null)
|
||||
{
|
||||
throw new BuildException("Convai does not support platform " + Target.Platform.ToString());
|
||||
}
|
||||
|
||||
var PlatformInstance = Activator.CreateInstance(ConvaiPlatformType) as ConvaiPlatform;
|
||||
if (PlatformInstance == null)
|
||||
{
|
||||
throw new BuildException("Convai could not instantiate platform " + Target.Platform.ToString());
|
||||
}
|
||||
|
||||
return PlatformInstance;
|
||||
}
|
||||
|
||||
private bool ConfigurePlatform(ReadOnlyTargetRules Target, UnrealTargetConfiguration Configuration)
|
||||
{
|
||||
//Convai thirdparty libraries root path
|
||||
string root = ThirdPartyPath;
|
||||
foreach (var arch in ConvaiPlatformInstance.Architectures())
|
||||
{
|
||||
string grpcPath = root + "gRPC/" + "lib/" + ConvaiPlatformInstance.LibrariesPath + arch;
|
||||
|
||||
// Add files that end with .lib
|
||||
PublicAdditionalLibraries.AddRange(Directory.GetFiles(grpcPath, "*.lib"));
|
||||
|
||||
// Add files that end with .a
|
||||
PublicAdditionalLibraries.AddRange(Directory.GetFiles(grpcPath, "*.a"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Convai(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
// Common Settings
|
||||
DefaultBuildSettings = BuildSettingsVersion.Latest;
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
PrecompileForTargets = PrecompileTargetsType.Any;
|
||||
ConvaiPlatformInstance = GetConvaiPlatformInstance(Target);
|
||||
|
||||
PrivateIncludePaths.Add("Convai/Private");
|
||||
|
||||
if (Target.Platform == UnrealTargetPlatform.Mac || Target.Platform == UnrealTargetPlatform.IOS)
|
||||
{
|
||||
// Include .mm file only for Mac
|
||||
PrivateIncludePaths.Add("Convai/Private/Mac");
|
||||
}
|
||||
|
||||
const bool bEnableConvaiHTTP = false;
|
||||
PublicDefinitions.AddRange(new string[] { "USE_CONVAI_HTTP=0" + (bEnableConvaiHTTP ? "1" : "0")});
|
||||
if (bEnableConvaiHTTP)
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "CONVAIHTTP", "HTTP" });
|
||||
}
|
||||
else
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "HTTP" });
|
||||
}
|
||||
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Json", "JsonUtilities", "AudioMixer", "AudioCaptureCore", "AudioCapture", "Voice", "SignalProcessing", "libOpus", "OpenSSL", "zlib", "SSL" });
|
||||
PrivateDependencyModuleNames.AddRange(new string[] {"Projects"});
|
||||
PublicDefinitions.AddRange(new string[] { "ConvaiDebugMode=1", "GOOGLE_PROTOBUF_NO_RTTI", "GPR_FORBID_UNREACHABLE_CODE", "GRPC_ALLOW_EXCEPTIONS=0" });
|
||||
|
||||
// Target Platform Specific Settings
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
bUsePrecompiled = false;
|
||||
}
|
||||
|
||||
if (Target.Platform == UnrealTargetPlatform.Android)
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "ApplicationCore", "AndroidPermission" });
|
||||
string BuildPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
|
||||
AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(BuildPath, "Convai_AndroidAPL.xml"));
|
||||
}
|
||||
|
||||
if (Target.Platform == UnrealTargetPlatform.Mac || Target.Platform == UnrealTargetPlatform.IOS || Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
PublicDefinitions.AddRange(new string[] { "GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0", "GOOGLE_PROTOBUF_USE_UNALIGNED=0", "PROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII=0" });
|
||||
PrivateIncludePaths.AddRange(new string[] { Path.Combine(ThirdPartyPath, "gRPC", "Include_1.50.x") });
|
||||
}
|
||||
else
|
||||
{
|
||||
PrivateIncludePaths.AddRange(new string[] { Path.Combine(ThirdPartyPath, "gRPC", "Include") });
|
||||
}
|
||||
|
||||
// ThirdParty Libraries
|
||||
AddEngineThirdPartyPrivateStaticDependencies(Target, "libOpus");
|
||||
AddEngineThirdPartyPrivateStaticDependencies(Target, "OpenSSL");
|
||||
AddEngineThirdPartyPrivateStaticDependencies(Target, "zlib");
|
||||
|
||||
ConfigurePlatform(Target, Target.Configuration);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ConvaiPlatform
|
||||
{
|
||||
public virtual string ConfigurationDir(UnrealTargetConfiguration Configuration)
|
||||
{
|
||||
if (Configuration == UnrealTargetConfiguration.Debug || Configuration == UnrealTargetConfiguration.DebugGame)
|
||||
{
|
||||
return "Debug/";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Release/";
|
||||
}
|
||||
}
|
||||
public abstract string LibrariesPath { get; }
|
||||
public abstract List<string> Architectures();
|
||||
public abstract string LibraryPrefixName { get; }
|
||||
public abstract string LibraryPostfixName { get; }
|
||||
}
|
||||
|
||||
public class ConvaiPlatform_Win64 : ConvaiPlatform
|
||||
{
|
||||
public override string LibrariesPath { get { return "win64/"; } }
|
||||
public override List<string> Architectures() { return new List<string> { "" }; }
|
||||
public override string LibraryPrefixName { get { return ""; } }
|
||||
public override string LibraryPostfixName { get { return ".lib"; } }
|
||||
}
|
||||
|
||||
public class ConvaiPlatform_Android : ConvaiPlatform
|
||||
{
|
||||
public override string LibrariesPath { get { return "android/"; } }
|
||||
public override List<string> Architectures() { return new List<string> { "armeabi-v7a/", "arm64-v8a/", "x86_64/" }; }
|
||||
public override string LibraryPrefixName { get { return "lib"; } }
|
||||
public override string LibraryPostfixName { get { return ".a"; } }
|
||||
}
|
||||
|
||||
public class ConvaiPlatform_Mac : ConvaiPlatform
|
||||
{
|
||||
public override string LibrariesPath { get { return "mac/"; } }
|
||||
public override List<string> Architectures() { return new List<string> { "" }; }
|
||||
public override string LibraryPrefixName { get { return "lib"; } }
|
||||
public override string LibraryPostfixName { get { return ".a"; } }
|
||||
}
|
||||
|
||||
|
||||
public class ConvaiPlatform_Linux : ConvaiPlatform
|
||||
{
|
||||
public override string LibrariesPath { get { return "linux/"; } }
|
||||
public override List<string> Architectures() { return new List<string> { "" }; }
|
||||
public override string LibraryPrefixName { get { return "lib"; } }
|
||||
public override string LibraryPostfixName { get { return ".a"; } }
|
||||
}
|
||||
|
||||
//public class ConvaiPlatform_PS5 : ConvaiPlatform
|
||||
//{
|
||||
// public override string LibrariesPath { get { return "ps5/"; } }
|
||||
// public override List<string> Architectures() { return new List<string> { "" }; }
|
||||
// public override string LibraryPrefixName { get { return "lib"; } }
|
||||
// public override string LibraryPostfixName { get { return ".a"; } }
|
||||
//}
|
||||
|
||||
//public class ConvaiPlatform_IOS : ConvaiPlatform
|
||||
//{
|
||||
// public override string ConfigurationDir(UnrealTargetConfiguration Configuration)
|
||||
// {
|
||||
// return "";
|
||||
// }
|
||||
// public override string LibrariesPath { get { return "ios/"; } }
|
||||
// public override List<string> Architectures() { return new List<string> { "" }; }
|
||||
// public override string LibraryPrefixName { get { return "lib"; } }
|
||||
// public override string LibraryPostfixName { get { return ".a"; } }
|
||||
//}
|
||||
50
ConvAI/Convai/Source/Convai/Convai.cpp
Normal file
50
ConvAI/Convai/Source/Convai/Convai.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#include "Convai.h"
|
||||
#include "Developer/Settings/Public/ISettingsModule.h"
|
||||
#include "UObject/UObjectGlobals.h"
|
||||
#include "UObject/Package.h"
|
||||
|
||||
IMPLEMENT_MODULE(Convai, Convai);
|
||||
|
||||
#define LOCTEXT_NAMESPACE "Convai"
|
||||
|
||||
void Convai::StartupModule()
|
||||
{
|
||||
ConvaiSettings = NewObject<UConvaiSettings>(GetTransientPackage(), "ConvaiSettings", RF_Standalone);
|
||||
ConvaiSettings->AddToRoot();
|
||||
|
||||
// Register settings
|
||||
if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
|
||||
{
|
||||
SettingsModule->RegisterSettings("Project", "Plugins", "Convai",
|
||||
LOCTEXT("RuntimeSettingsName", "Convai"),
|
||||
LOCTEXT("RuntimeSettingsDescription", "Configure Convai settings"),
|
||||
ConvaiSettings);
|
||||
}
|
||||
}
|
||||
|
||||
void Convai::ShutdownModule()
|
||||
{
|
||||
if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
|
||||
{
|
||||
SettingsModule->UnregisterSettings("Project", "Plugins", "Convai");
|
||||
}
|
||||
|
||||
if (!GExitPurge)
|
||||
{
|
||||
ConvaiSettings->RemoveFromRoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvaiSettings = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
UConvaiSettings* Convai::GetConvaiSettings() const
|
||||
{
|
||||
check(ConvaiSettings);
|
||||
return ConvaiSettings;
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
108
ConvAI/Convai/Source/Convai/Convai.h
Normal file
108
ConvAI/Convai/Source/Convai/Convai.h
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "Public/ConvaiDefinitions.h"
|
||||
#include "Convai.generated.h"
|
||||
|
||||
UCLASS(config = Engine, defaultconfig)
|
||||
class CONVAI_API UConvaiSettings : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UConvaiSettings(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
API_Key = "";
|
||||
EnableNewActionSystem = false;
|
||||
}
|
||||
/* API Key Issued from the website */
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Convai API")
|
||||
FString API_Key;
|
||||
|
||||
/* Enable new actions system */
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Convai API", meta = (DisplayName = "Enable New Action System (Experimental)"))
|
||||
bool EnableNewActionSystem;
|
||||
|
||||
/* Authentication token used for Convai Connect */
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "Convai API")
|
||||
FString AuthToken;
|
||||
|
||||
/* Custom Server URL (Used for debugging) */
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "Convai API")
|
||||
FString CustomURL;
|
||||
|
||||
/* Custom Beta API URL (Used for debugging) */
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "Convai API")
|
||||
FString CustomBetaURL;
|
||||
|
||||
/* Custom Production API URL (Used for debugging) */
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "Convai API")
|
||||
FString CustomProdURL;
|
||||
|
||||
/* Test Character ID (Used for debugging) */
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "Convai API")
|
||||
FString TestCharacterID;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "Convai API")
|
||||
bool AllowInsecureConnection;
|
||||
|
||||
/* Use both hardcoded and system SSL certificates on Windows */
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "Convai API")
|
||||
bool UseSystemCertificates;
|
||||
|
||||
/* Extra Parameters (Used for debugging) */
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "Convai API")
|
||||
FString ExtraParams;
|
||||
|
||||
UPROPERTY(Config, VisibleAnywhere, Category = "Long Term Memory")
|
||||
TArray<FConvaiSpeakerInfo> SpeakerIDs;
|
||||
};
|
||||
|
||||
|
||||
class CONVAI_API Convai : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
void StartupModule();
|
||||
void ShutdownModule();
|
||||
|
||||
|
||||
/**
|
||||
* Singleton-like access to this module's interface. This is just for convenience!
|
||||
* Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.
|
||||
*
|
||||
* @return Returns singleton instance, loading the module on demand if needed
|
||||
*/
|
||||
static inline Convai& Get()
|
||||
{
|
||||
return FModuleManager::LoadModuleChecked<Convai>("Convai");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true.
|
||||
*
|
||||
* @return True if the module is loaded and ready to use
|
||||
*/
|
||||
static inline bool IsAvailable()
|
||||
{
|
||||
return FModuleManager::Get().IsModuleLoaded("Convai");
|
||||
}
|
||||
|
||||
virtual bool IsGameModule() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Getter for internal settings object to support runtime configuration changes */
|
||||
UConvaiSettings* GetConvaiSettings() const;
|
||||
|
||||
|
||||
protected:
|
||||
/** Module settings */
|
||||
UConvaiSettings* ConvaiSettings;
|
||||
};
|
||||
301
ConvAI/Convai/Source/Convai/Convai_AndroidAPL.xml
Normal file
301
ConvAI/Convai/Source/Convai/Convai_AndroidAPL.xml
Normal file
@@ -0,0 +1,301 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- // Copyright 2022 Convai Inc. All Rights Reserved. -->
|
||||
<root xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- init section is always evaluated once per architecture -->
|
||||
<trace enable="true"/>
|
||||
<init>
|
||||
<log text="AndroidAPITemplate init"/>
|
||||
</init>
|
||||
|
||||
<androidManifestUpdates>
|
||||
|
||||
<addPermission android:name="android.permission.RECORD_AUDIO" />
|
||||
|
||||
</androidManifestUpdates>
|
||||
|
||||
<!-- optional additions to proguard -->
|
||||
<proguardAdditions>
|
||||
<insert><![CDATA[
|
||||
-keepattributes Signature
|
||||
-dontskipnonpubliclibraryclassmembers
|
||||
|
||||
-keepclassmembers class com.epicgames.ue4.GameActivity {
|
||||
public <methods>;
|
||||
public <fields>;
|
||||
}
|
||||
]]></insert>
|
||||
</proguardAdditions>
|
||||
|
||||
<gradleProperties>
|
||||
<insert>
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
</insert>
|
||||
</gradleProperties>
|
||||
|
||||
<buildscriptGradleAdditions>
|
||||
<insert>
|
||||
dependencies
|
||||
{
|
||||
repositories {
|
||||
// Check that you have the following line (if not, add it):
|
||||
google() // Google's Maven repository
|
||||
}
|
||||
classpath 'com.google.gms:google-services:4.3.3' // google-services plugin
|
||||
}
|
||||
</insert>
|
||||
</buildscriptGradleAdditions>
|
||||
|
||||
<buildGradleAdditions>
|
||||
<!-- Needs to be same version number as play-services -->
|
||||
<insert>
|
||||
|
||||
dependencies
|
||||
{
|
||||
implementation 'com.google.android.play:app-update:2.1.0'
|
||||
implementation 'com.google.android.play:review:2.0.1'
|
||||
}
|
||||
|
||||
allprojects {
|
||||
def mappings = [
|
||||
'android.support.annotation': 'androidx.annotation',
|
||||
'android.arch.lifecycle': 'androidx.lifecycle',
|
||||
'android.support.v4.app.NotificationCompat': 'androidx.core.app.NotificationCompat',
|
||||
'android.support.v4.app.ActivityCompat': 'androidx.core.app.ActivityCompat',
|
||||
'android.support.v4.content.ContextCompat': 'androidx.core.content.ContextCompat',
|
||||
'android.support.v13.app.FragmentCompat': 'androidx.legacy.app.FragmentCompat',
|
||||
'android.arch.lifecycle.Lifecycle': 'androidx.lifecycle.Lifecycle',
|
||||
'android.arch.lifecycle.LifecycleObserver': 'androidx.lifecycle.LifecycleObserver',
|
||||
'android.arch.lifecycle.OnLifecycleEvent': 'androidx.lifecycle.OnLifecycleEvent',
|
||||
'android.arch.lifecycle.ProcessLifecycleOwner': 'androidx.lifecycle.ProcessLifecycleOwner',
|
||||
]
|
||||
|
||||
beforeEvaluate { project ->
|
||||
project.rootProject.projectDir.traverse(type: groovy.io.FileType.FILES, nameFilter: ~/.*\.java$/) { f ->
|
||||
mappings.each { entry ->
|
||||
if (f.getText('UTF-8').contains(entry.key)) {
|
||||
println "Updating ${entry.key} to ${entry.value} in file ${f}"
|
||||
ant.replace(file: f, token: entry.key, value: entry.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</insert>
|
||||
</buildGradleAdditions>
|
||||
|
||||
<resourceCopies>
|
||||
<!-- Copy the generated resource file to be packaged -->
|
||||
</resourceCopies>
|
||||
|
||||
<AARImports>
|
||||
</AARImports>
|
||||
|
||||
<!-- optional additions to the GameActivity imports in GameActivity.java -->
|
||||
<gameActivityImportAdditions>
|
||||
<insert>
|
||||
import java.util.HashSet;
|
||||
import java.util.Arrays;
|
||||
import android.os.Handler;
|
||||
|
||||
import android.util.Log;
|
||||
import android.media.AudioRecord;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.MediaRecorder;
|
||||
import android.media.AudioTrack;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.Manifest;
|
||||
import android.media.audiofx.AcousticEchoCanceler;
|
||||
</insert>
|
||||
</gameActivityImportAdditions>
|
||||
|
||||
|
||||
<!-- optional additions to the GameActivity class in GameActivity.java -->
|
||||
<gameActivityClassAdditions>
|
||||
<insert>
|
||||
<![CDATA[
|
||||
|
||||
/* JNI UE4 Native */
|
||||
private static native void dataMicPayload(short[] dataMic, int readSize);
|
||||
|
||||
/* VAR */
|
||||
AudioRecord microphone = null;
|
||||
Thread threadMicro = null;
|
||||
AudioTrack audioplayback;
|
||||
RunnableVoice runableVoice;
|
||||
|
||||
private boolean isPermissionAllowedMic = false;
|
||||
|
||||
|
||||
/* FUNC */
|
||||
|
||||
public void AndroidThunkJava_AndroidAskPermissionMicrophone(){
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 1);
|
||||
}
|
||||
|
||||
public boolean AndroidThunkJava_AndroidHasPermissionMicrophone(){
|
||||
boolean res = false;
|
||||
res = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;
|
||||
android.util.Log.d("AndroidRateApp","UPL permission " + res);
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean AndroidThunkJava_AndroidStartMicrophone(int sampleRateToUse) {
|
||||
|
||||
android.util.Log.d("AndroidRateApp","UPL microphone sampleRateToUse " + sampleRateToUse);
|
||||
|
||||
if(!isPermissionAllowedMic){
|
||||
isPermissionAllowedMic = AndroidThunkJava_AndroidHasPermissionMicrophone();
|
||||
if(!isPermissionAllowedMic) return false;
|
||||
}
|
||||
|
||||
|
||||
if(microphone == null){
|
||||
final int sampleRate = sampleRateToUse;
|
||||
final int channelConfig = AudioFormat.CHANNEL_IN_MONO;
|
||||
final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
|
||||
|
||||
final int minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
|
||||
microphone = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, sampleRate, channelConfig, audioFormat, minBufferSize );
|
||||
|
||||
if(AcousticEchoCanceler.isAvailable()){
|
||||
AcousticEchoCanceler aec = AcousticEchoCanceler.create(microphone.getAudioSessionId());
|
||||
if (aec != null) {
|
||||
aec.setEnabled(true);
|
||||
android.util.Log.d("AndroidRateApp","echo cancelation ok VOICE_COMMUNICATION");
|
||||
} else {
|
||||
android.util.Log.d("AndroidRateApp","echo cancelation not ok VOICE_COMMUNICATION");
|
||||
}
|
||||
}
|
||||
microphone.startRecording();
|
||||
|
||||
runableVoice = new RunnableVoice(minBufferSize);
|
||||
runableVoice.microphoneThread = microphone;
|
||||
|
||||
threadMicro = new Thread(runableVoice);
|
||||
|
||||
|
||||
threadMicro.start();
|
||||
}
|
||||
|
||||
microphone.startRecording();
|
||||
runableVoice.setthreadMicroRunning(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AndroidThunkJava_AndroidStopMicrophone() {
|
||||
android.util.Log.d("AndroidRateApp","UPL AndroidThunkJava_AndroidStopMicrophone setthreadMicroRunning");
|
||||
runableVoice.setthreadMicroRunning(false);
|
||||
//threadMicro.stop();
|
||||
microphone.stop();
|
||||
runableVoice.setthreadMicroRunning(false);
|
||||
//microphone.release();
|
||||
}
|
||||
|
||||
|
||||
public class RunnableVoice implements Runnable {
|
||||
public volatile boolean threadMicroRunning = false;
|
||||
public AudioRecord microphoneThread = null;
|
||||
int minBufferSize;
|
||||
|
||||
public RunnableVoice(int minBufferSize){
|
||||
this.minBufferSize = minBufferSize;
|
||||
}
|
||||
|
||||
public void setthreadMicroRunning(boolean threadMicroRunning){
|
||||
this.threadMicroRunning = threadMicroRunning;
|
||||
android.util.Log.d("AndroidRateApp","UPL setthreadMicroRunning " + this.threadMicroRunning);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
short[] buffer = new short[minBufferSize / 2];
|
||||
while (true) {
|
||||
if(threadMicroRunning){
|
||||
int readSize = microphoneThread.read(buffer, 0, buffer.length);
|
||||
android.util.Log.d("AndroidRateApp","UPL microphone data / 2 " + readSize +" "+buffer[0]);
|
||||
dataMicPayload(buffer, readSize);
|
||||
}
|
||||
}
|
||||
} catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
]]>
|
||||
</insert>
|
||||
</gameActivityClassAdditions>
|
||||
|
||||
<!-- optional additions to GameActivity onCreate metadata reading in GameActivity.java -->
|
||||
<gameActivityReadMetadataAdditions>
|
||||
<insert>
|
||||
|
||||
</insert>
|
||||
</gameActivityReadMetadataAdditions>
|
||||
|
||||
<!-- optional additions to GameActivity onCreate in GameActivity.java -->
|
||||
<gameActivityOnCreateAdditions>
|
||||
<insert>
|
||||
<![CDATA[
|
||||
|
||||
]]>
|
||||
</insert>
|
||||
</gameActivityOnCreateAdditions>
|
||||
|
||||
<!-- optional additions to GameActivity onDestroy in GameActivity.java -->
|
||||
<gameActivityOnDestroyAdditions>
|
||||
<insert>
|
||||
|
||||
</insert>
|
||||
</gameActivityOnDestroyAdditions>
|
||||
|
||||
|
||||
<!-- optional additions to GameActivity onStart in GameActivity.java -->
|
||||
<gameActivityOnStartAdditions>
|
||||
<insert>
|
||||
|
||||
</insert>
|
||||
</gameActivityOnStartAdditions>
|
||||
|
||||
<!-- optional additions to GameActivity onStop in GameActivity.java -->
|
||||
<gameActivityOnStopAdditions>
|
||||
<insert>
|
||||
|
||||
</insert>
|
||||
</gameActivityOnStopAdditions>
|
||||
|
||||
|
||||
<!-- optional additions to GameActivity onPause in GameActivity.java -->
|
||||
<gameActivityOnPauseAdditions>
|
||||
<insert>
|
||||
<![CDATA[
|
||||
]]>
|
||||
</insert>
|
||||
</gameActivityOnPauseAdditions>
|
||||
|
||||
|
||||
<!-- optional additions to GameActivity onResume in GameActivity.java -->
|
||||
<gameActivityOnResumeAdditions>
|
||||
<insert>
|
||||
</insert>
|
||||
</gameActivityOnResumeAdditions>
|
||||
|
||||
|
||||
<!-- optional additions to GameActivity onActivityResult in GameActivity.java -->
|
||||
<gameActivityOnActivityResultAdditions>
|
||||
<insert>
|
||||
</insert>
|
||||
</gameActivityOnActivityResultAdditions>
|
||||
|
||||
|
||||
<!-- optional libraries to load in GameActivity.java before libUE4.so -->
|
||||
<soLoadLibrary>
|
||||
<!-- need this if plugin enabled and supported architecture, even if not packaged for GearVR -->
|
||||
</soLoadLibrary>
|
||||
</root>
|
||||
445
ConvAI/Convai/Source/Convai/Private/ConvaiActionUtils.cpp
Normal file
445
ConvAI/Convai/Source/Convai/Private/ConvaiActionUtils.cpp
Normal file
@@ -0,0 +1,445 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
|
||||
#include "ConvaiActionUtils.h"
|
||||
#include "ConvaiUtils.h"
|
||||
#include "Internationalization/Regex.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiActionUtilsLog);
|
||||
|
||||
namespace
|
||||
{
|
||||
bool FindCharAfterIndex(const FString& SearchString, const char Search, int32& OutIndex, const int32& AfterIndex)
|
||||
{
|
||||
return SearchString.Left(AfterIndex).FindChar(Search, OutIndex);
|
||||
}
|
||||
|
||||
FString RemoveQuotedWords(const FString& Input)
|
||||
{
|
||||
|
||||
int32 QuoteStartIndex = -1;
|
||||
if (!Input.FindChar('"', QuoteStartIndex))
|
||||
{
|
||||
return Input;
|
||||
}
|
||||
|
||||
FString Result = Input;
|
||||
|
||||
while (Result.FindChar('"', QuoteStartIndex))
|
||||
{
|
||||
int32 QuoteEndIndex = -1;
|
||||
|
||||
// Start searching for the end quote after the start quote
|
||||
if (Result.Left(QuoteStartIndex + 1).FindChar('"', QuoteEndIndex) && QuoteEndIndex > QuoteStartIndex)
|
||||
{
|
||||
// Remove the quoted string, including the quotes
|
||||
Result.RemoveAt(QuoteStartIndex, QuoteEndIndex - QuoteStartIndex + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No closing quote found after this point, break the loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
int32 CountWords(const FString& str)
|
||||
{
|
||||
if (str.Len() == 0) return 0;
|
||||
|
||||
TArray<FString> words;
|
||||
str.ParseIntoArray(words, TEXT(" "), true);
|
||||
|
||||
return words.Num();
|
||||
}
|
||||
|
||||
FString KeepNWords(const FString& StringToBeParsed, const FString& CandidateString)
|
||||
{
|
||||
TArray<FString> words;
|
||||
StringToBeParsed.ParseIntoArray(words, TEXT(" "), true);
|
||||
|
||||
int32 N = CountWords(CandidateString);
|
||||
|
||||
FString result;
|
||||
for (int32 i = 0; i < FMath::Min(N, words.Num()); i++)
|
||||
{
|
||||
result += words[i] + " ";
|
||||
}
|
||||
|
||||
// Trim trailing space
|
||||
result = result.LeftChop(1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FString FindClosestString(FString Input, const TArray<FString>& StringArray)
|
||||
{
|
||||
FString ClosestString;
|
||||
int32 MinDistance = MAX_int32;
|
||||
|
||||
for (auto& String : StringArray)
|
||||
{
|
||||
int32 Distance = UConvaiUtils::LevenshteinDistance(Input, String);
|
||||
if (Distance < MinDistance)
|
||||
{
|
||||
MinDistance = Distance;
|
||||
ClosestString = String;
|
||||
}
|
||||
}
|
||||
|
||||
return ClosestString;
|
||||
}
|
||||
|
||||
// Helper function to check if a substring is found outside of quotes.
|
||||
bool FindSubstringOutsideQuotes(const FString& SearchString, const FString& SubstringToFind)
|
||||
{
|
||||
bool bInsideQuotes = false;
|
||||
int32 SubstringLength = SubstringToFind.Len();
|
||||
int32 SearchStringLength = SearchString.Len();
|
||||
|
||||
if (SubstringLength > SearchStringLength || SubstringLength == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i <= SearchStringLength - SubstringLength; ++i)
|
||||
{
|
||||
// Toggle the inside quotes flag if a quote is found
|
||||
if (SearchString[i] == '"')
|
||||
{
|
||||
bInsideQuotes = !bInsideQuotes;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we are not inside quotes, perform the search
|
||||
if (!bInsideQuotes && SearchString.Mid(i, SubstringLength).Equals(SubstringToFind, ESearchCase::IgnoreCase))
|
||||
{
|
||||
// Make sure the match is not part of a larger string
|
||||
if ((i == 0 || !FChar::IsAlnum(SearchString[i - 1])) &&
|
||||
(i + SubstringLength == SearchStringLength || !FChar::IsAlnum(SearchString[i + SubstringLength])))
|
||||
{
|
||||
return true; // Substring found outside of quotes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false; // Substring not found or is within quotes
|
||||
}
|
||||
|
||||
bool FindClosePhraseOutsideQuotes(const FString& SearchString, const FString& PhraseToFind, int& OutBestDistance, int NumWordsToSkip = 0)
|
||||
{
|
||||
if (PhraseToFind.IsEmpty())
|
||||
{
|
||||
return false; // Can't find an empty phrase.
|
||||
}
|
||||
|
||||
int32 MaxLevenshteinDistance = FMath::Clamp(PhraseToFind.Len() / 2, 2, 4);
|
||||
TArray<FString> Words;
|
||||
FString CurrentWord;
|
||||
bool bInsideQuotes = false;
|
||||
OutBestDistance = MaxLevenshteinDistance + 1; // Initialize with a value above the limit
|
||||
|
||||
// Collect words outside quotes
|
||||
for (TCHAR Char : SearchString)
|
||||
{
|
||||
if (Char == '"')
|
||||
{
|
||||
bInsideQuotes = !bInsideQuotes;
|
||||
if (!CurrentWord.IsEmpty())
|
||||
{
|
||||
Words.Add(CurrentWord);
|
||||
CurrentWord.Empty();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!bInsideQuotes && (Char == ' ' || Char == '\t'))
|
||||
{
|
||||
if (!CurrentWord.IsEmpty())
|
||||
{
|
||||
Words.Add(CurrentWord);
|
||||
CurrentWord.Empty();
|
||||
}
|
||||
}
|
||||
else if (!bInsideQuotes)
|
||||
{
|
||||
CurrentWord.AppendChar(Char);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the last word if there is one
|
||||
if (!CurrentWord.IsEmpty())
|
||||
{
|
||||
Words.Add(CurrentWord);
|
||||
}
|
||||
|
||||
// Number of words in the phrase to find
|
||||
TArray<FString> PhraseWords;
|
||||
PhraseToFind.ParseIntoArray(PhraseWords, TEXT(" "), true);
|
||||
int32 NumWordsInPhrase = PhraseWords.Num();
|
||||
|
||||
// Sliding window of words to check for the phrase
|
||||
for (int32 i = NumWordsToSkip; i <= Words.Num() - NumWordsInPhrase; ++i)
|
||||
{
|
||||
FString WindowString;
|
||||
for (int32 j = 0; j < NumWordsInPhrase; ++j)
|
||||
{
|
||||
WindowString += (j > 0 ? TEXT(" ") : TEXT("")) + Words[i + j];
|
||||
}
|
||||
|
||||
if (WindowString.Len() - PhraseToFind.Len() >= MaxLevenshteinDistance || PhraseToFind.Len() - WindowString.Len() >= MaxLevenshteinDistance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int32 Distance = UConvaiUtils::LevenshteinDistance(WindowString, PhraseToFind);
|
||||
if (Distance <= MaxLevenshteinDistance && Distance < OutBestDistance)
|
||||
{
|
||||
OutBestDistance = Distance;
|
||||
}
|
||||
}
|
||||
|
||||
// The function returns true if we found a match within the acceptable Levenshtein distance
|
||||
return OutBestDistance <= MaxLevenshteinDistance;
|
||||
}
|
||||
|
||||
static bool FindNearestObjectByName(FString SearchString, TArray<FConvaiObjectEntry> Objects, FConvaiObjectEntry& ObjectMatch)
|
||||
{
|
||||
FString SearchStringLower = SearchString.ToLower();
|
||||
bool Found = false;
|
||||
int BestDistance = 100;
|
||||
for (auto o : Objects)
|
||||
{
|
||||
FString ObjectNameLower = o.Name.ToLower();
|
||||
int Distance = 0;
|
||||
if (FindClosePhraseOutsideQuotes(SearchStringLower, ObjectNameLower, Distance))
|
||||
{
|
||||
if (Distance < BestDistance)
|
||||
{
|
||||
ObjectMatch = o;
|
||||
BestDistance = Distance;
|
||||
Found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to search in objects using each word in the SearchString
|
||||
if (!Found)
|
||||
{
|
||||
TArray<FString> words;
|
||||
FString SearchStringWithoutQuotes = RemoveQuotedWords(SearchStringLower);
|
||||
SearchStringWithoutQuotes.ParseIntoArray(words, TEXT(" "), true);
|
||||
bool breakFromLoop = false;
|
||||
for (auto o : Objects)
|
||||
{
|
||||
if (breakFromLoop)
|
||||
break;
|
||||
if (CountWords(o.Name) <= 1)
|
||||
continue; // consider only names consisting of 1+ words
|
||||
|
||||
FString ObjectNameLower = o.Name.ToLower();
|
||||
for (auto w : words)
|
||||
{
|
||||
if (w.Len() <= 3)
|
||||
continue; // consider only words greater than 3 letters
|
||||
|
||||
int Distance = 0;
|
||||
if (FindClosePhraseOutsideQuotes(ObjectNameLower, w, Distance))
|
||||
{
|
||||
ObjectMatch = o;
|
||||
BestDistance = Distance;
|
||||
Found = true;
|
||||
breakFromLoop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Found;
|
||||
}
|
||||
|
||||
TArray<FConvaiObjectEntry> BubbleSortEntriesByNumberOfWords(TArray<FConvaiObjectEntry> Entries)
|
||||
{
|
||||
bool swapped;
|
||||
int n = Entries.Num();
|
||||
for (int i = 0; i < n - 1; i++) {
|
||||
swapped = false;
|
||||
for (int j = 0; j < n - i - 1; j++) {
|
||||
if (CountWords(Entries[j].Name) > CountWords(Entries[j+1].Name)) {
|
||||
Entries.Swap(j, j + 1);
|
||||
swapped = true;
|
||||
}
|
||||
}
|
||||
// If no two elements were swapped by inner loop, then break
|
||||
if (!swapped) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Entries;
|
||||
}
|
||||
};
|
||||
|
||||
TArray<FString> UConvaiActions::SmartSplit(const FString& SequenceString)
|
||||
{
|
||||
TArray<FString> Result;
|
||||
FString CurrentString = "";
|
||||
bool InQuotes = false;
|
||||
|
||||
for (int i = 0; i < SequenceString.Len(); ++i)
|
||||
{
|
||||
TCHAR CurrentChar = SequenceString[i];
|
||||
|
||||
if (CurrentChar == '\"')
|
||||
{
|
||||
InQuotes = !InQuotes;
|
||||
}
|
||||
|
||||
if (CurrentChar == ',' && !InQuotes)
|
||||
{
|
||||
Result.Add(CurrentString.TrimStartAndEnd());
|
||||
CurrentString = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentString += CurrentChar;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CurrentString.IsEmpty())
|
||||
{
|
||||
Result.Add(CurrentString.TrimStartAndEnd());
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FString UConvaiActions::ExtractText(FString Action, FString ActionResult)
|
||||
{
|
||||
FString ExtraText = "";
|
||||
FRegexPattern TextPattern(TEXT("\".*\""));
|
||||
FRegexMatcher StringMatcher = FRegexMatcher(TextPattern, ActionResult);
|
||||
if (StringMatcher.FindNext())
|
||||
{
|
||||
//CONVAI_LOG(ConvaiUtilsLog, Warning, TEXT("*StringMatcher.GetCaptureGroup(0):%s"), *StringMatcher.GetCaptureGroup(0));
|
||||
ExtraText = *StringMatcher.GetCaptureGroup(0).LeftChop(1).RightChop(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = ActionResult.Find(Action);
|
||||
index += Action.Len();
|
||||
ExtraText = ActionResult.RightChop(index + 1);
|
||||
//ExtraText = ActionResult;
|
||||
}
|
||||
return ExtraText;
|
||||
}
|
||||
|
||||
float UConvaiActions::ExtractNumber(FString ActionResult)
|
||||
{
|
||||
float ExtraNumber = 0;
|
||||
FRegexPattern NumericPattern(TEXT("\\d+"));
|
||||
FRegexMatcher NumberMatcher = FRegexMatcher(NumericPattern, ActionResult);
|
||||
if (NumberMatcher.FindNext())
|
||||
{
|
||||
//CONVAI_LOG(ConvaiGetActionHttpLog, Warning, TEXT("*NumberMatcher.GetCaptureGroup(0):%s"), *NumberMatcher.GetCaptureGroup(0));
|
||||
ExtraNumber = FCString::Atof(*NumberMatcher.GetCaptureGroup(0));
|
||||
}
|
||||
return ExtraNumber;
|
||||
}
|
||||
|
||||
FString UConvaiActions::RemoveDesc(FString str)
|
||||
{
|
||||
FRegexPattern DescPattern(TEXT("<.*>"));
|
||||
FRegexMatcher DescMatcher = FRegexMatcher(DescPattern, str);
|
||||
int i = 0;
|
||||
while (DescMatcher.FindNext())
|
||||
{
|
||||
int start = DescMatcher.GetMatchBeginning();
|
||||
str.ReplaceInline(*DescMatcher.GetCaptureGroup(i++), *FString(""));
|
||||
str.TrimEndInline();
|
||||
str.TrimStartInline();
|
||||
}
|
||||
//CONVAI_LOG(ConvaiActionUtilsLog, Warning, TEXT("str:%s"), *str);
|
||||
return str;
|
||||
}
|
||||
|
||||
FString UConvaiActions::FindAction(FString ActionToBeParsed, TArray<FString> Actions)
|
||||
{
|
||||
FString ClosestAction = "None";
|
||||
int32 MinDistance = 4;
|
||||
for (auto a : Actions)
|
||||
{
|
||||
FString TrimmedAction = ActionToBeParsed;
|
||||
a = RemoveDesc(a);
|
||||
TrimmedAction = KeepNWords(ActionToBeParsed, a);
|
||||
int32 Distance = UConvaiUtils::LevenshteinDistance(TrimmedAction, a);
|
||||
if (Distance < MinDistance)
|
||||
{
|
||||
MinDistance = Distance;
|
||||
ClosestAction = a;
|
||||
}
|
||||
}
|
||||
return ClosestAction;
|
||||
}
|
||||
|
||||
bool UConvaiActions::ParseAction(UConvaiEnvironment* Environment, FString ActionToBeParsed, FConvaiResultAction& ConvaiResultAction)
|
||||
{
|
||||
FString ActionToAdd;
|
||||
FConvaiObjectEntry RelatedObjOrChar;
|
||||
ConvaiResultAction.ActionString = ActionToBeParsed;
|
||||
|
||||
// find actions
|
||||
ActionToAdd = FindAction(ActionToBeParsed, Environment->Actions);
|
||||
|
||||
TArray<FConvaiObjectEntry> AllCharsAndObjs;
|
||||
AllCharsAndObjs.Append(Environment->Characters);
|
||||
AllCharsAndObjs.Append(Environment->Objects);
|
||||
|
||||
// find objects or characters
|
||||
FindNearestObjectByName(ActionToBeParsed, AllCharsAndObjs, RelatedObjOrChar);
|
||||
|
||||
// find objects
|
||||
//FindNearestObjectByName(ActionToBeParsed, Environment->Objects, RelatedObjOrChar);
|
||||
|
||||
// Find extra numeric param
|
||||
float ExtraNumber = ExtractNumber(ActionToBeParsed);
|
||||
|
||||
// Find extra textual param
|
||||
FString ExtraText = ExtractText(ActionToAdd, ActionToBeParsed);
|
||||
|
||||
// Add to result action sequence array
|
||||
if (ActionToAdd != "")
|
||||
{
|
||||
ConvaiResultAction.Action = ActionToAdd;
|
||||
ConvaiResultAction.RelatedObjectOrCharacter = RelatedObjOrChar;
|
||||
ConvaiResultAction.ConvaiExtraParams.Number = ExtraNumber;
|
||||
ConvaiResultAction.ConvaiExtraParams.Text = ExtraText;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UConvaiActions::ValidateEnvironment(UConvaiEnvironment* Environment, FString& Error)
|
||||
{
|
||||
if (!IsValid(Environment))
|
||||
{
|
||||
Error = "ConvaiActions: Environment object is invalid or not set! You can create it using \"Create Environemnt Object\" function";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Environment->MainCharacter.Ref.IsValid())
|
||||
{
|
||||
Error = "ConvaiActions: Main Character in the Environment object is invalid or not set! Please set it using \"Set Main Character\" function and use the player pawn as input";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Environment->Actions.Num() == 0)
|
||||
{
|
||||
Error = "ConvaiActions: The Environment object does not have any actions added, please add some actions using \"Add Action\" or \"Add Actions\" function";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
31
ConvAI/Convai/Source/Convai/Private/ConvaiAndroid.cpp
Normal file
31
ConvAI/Convai/Source/Convai/Private/ConvaiAndroid.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#include "ConvaiAndroid.h"
|
||||
|
||||
//#define PLATFORM_ANDROID 1
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include "AndroidPermissionFunctionLibrary.h"
|
||||
#endif
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiAndroidLog);
|
||||
|
||||
|
||||
void UConvaiAndroid::ConvaiAndroidAskMicrophonePermission()
|
||||
{
|
||||
#if PLATFORM_ANDROID
|
||||
TArray<FString> Permissions;
|
||||
Permissions.Add((FString("android.permission.RECORD_AUDIO")));
|
||||
UAndroidPermissionFunctionLibrary::AcquirePermissions(Permissions);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UConvaiAndroid::ConvaiAndroidHasMicrophonePermission()
|
||||
{
|
||||
#if PLATFORM_ANDROID
|
||||
return UAndroidPermissionFunctionLibrary::CheckPermission("android.permission.RECORD_AUDIO");
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,454 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
|
||||
#include "ConvaiAudioCaptureComponent.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "Utility/Log/ConvaiLogger.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiAudioLog);
|
||||
|
||||
|
||||
namespace Audio
|
||||
{
|
||||
FConvaiAudioCaptureSynth::FConvaiAudioCaptureSynth()
|
||||
: NumSamplesEnqueued(0)
|
||||
, bInitialized(false)
|
||||
, bIsCapturing(false)
|
||||
{
|
||||
}
|
||||
|
||||
FConvaiAudioCaptureSynth::~FConvaiAudioCaptureSynth()
|
||||
{
|
||||
}
|
||||
|
||||
TArray<FCaptureDeviceInfo> FConvaiAudioCaptureSynth::GetCaptureDevicesAvailable()
|
||||
{
|
||||
TArray<FCaptureDeviceInfo> CaptureDevicesInfo;
|
||||
AudioCapture.GetCaptureDevicesAvailable(CaptureDevicesInfo);
|
||||
for (int i = CaptureDevicesInfo.Num()-1; i>=0; i--)
|
||||
{
|
||||
if (CaptureDevicesInfo[i].InputChannels <= 0)
|
||||
CaptureDevicesInfo.RemoveAt(i);
|
||||
}
|
||||
return CaptureDevicesInfo;
|
||||
}
|
||||
|
||||
int32 FConvaiAudioCaptureSynth::MapInputDeviceIDToDeviceID(int32 InputDeviceID)
|
||||
{
|
||||
uint32 NumInputDevices = 0;
|
||||
TArray<FCaptureDeviceInfo> CaptureDevicesInfo;
|
||||
AudioCapture.GetCaptureDevicesAvailable(CaptureDevicesInfo);
|
||||
uint32 NumDevices = CaptureDevicesInfo.Num();
|
||||
|
||||
Audio::FCaptureDeviceInfo DeviceInfo;
|
||||
for (uint32 DeviceIndex = 0; AudioCapture.GetCaptureDeviceInfo(DeviceInfo, DeviceIndex); DeviceIndex++)
|
||||
{
|
||||
//CONVAI_LOG(ConvaiAudioLog, Log, TEXT("DeviceIndex: %d, InputDeviceID: %d - name: %s - channels:%d - NumDevices:%d"), DeviceIndex, InputDeviceID, *DeviceInfo.DeviceName, DeviceInfo.InputChannels, NumDevices);
|
||||
bool IsInput = DeviceInfo.InputChannels > 0;
|
||||
if (!IsInput)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//CONVAI_LOG(ConvaiAudioLog, Log, TEXT("DeviceIndex: %d, is an input - name: %s"), DeviceIndex, *DeviceInfo.DeviceName);
|
||||
if (NumInputDevices == InputDeviceID)
|
||||
{
|
||||
return DeviceIndex;
|
||||
}
|
||||
NumInputDevices++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool FConvaiAudioCaptureSynth::GetDefaultCaptureDeviceInfo(FCaptureDeviceInfo& OutInfo)
|
||||
{
|
||||
return AudioCapture.GetCaptureDeviceInfo(OutInfo);
|
||||
}
|
||||
|
||||
bool FConvaiAudioCaptureSynth::GetCaptureDeviceInfo(FCaptureDeviceInfo& OutInfo, int32 DeviceIndex)
|
||||
{
|
||||
DeviceIndex = MapInputDeviceIDToDeviceID(DeviceIndex);
|
||||
return AudioCapture.GetCaptureDeviceInfo(OutInfo, DeviceIndex);
|
||||
}
|
||||
|
||||
bool FConvaiAudioCaptureSynth::OpenDefaultStream()
|
||||
{
|
||||
bool bSuccess = true;
|
||||
if (!AudioCapture.IsStreamOpen())
|
||||
{
|
||||
FOnCaptureFunction OnCapture = [this](const float* AudioData, int32 NumFrames, int32 NumChannels, int32 SampleRate, double StreamTime, bool bOverFlow)
|
||||
{
|
||||
int32 NumSamples = NumChannels * NumFrames;
|
||||
|
||||
FScopeLock Lock(&CaptureCriticalSection);
|
||||
|
||||
if (bIsCapturing)
|
||||
{
|
||||
// Append the audio memory to the capture data buffer
|
||||
int32 Index = AudioCaptureData.AddUninitialized(NumSamples);
|
||||
float* AudioCaptureDataPtr = AudioCaptureData.GetData();
|
||||
FMemory::Memcpy(&AudioCaptureDataPtr[Index], AudioData, NumSamples * sizeof(float));
|
||||
}
|
||||
};
|
||||
|
||||
// Prepare the audio buffer memory for 2 seconds of stereo audio at 48k SR to reduce chance for allocation in callbacks
|
||||
AudioCaptureData.Reserve(2 * 2 * 48000);
|
||||
|
||||
FAudioCaptureDeviceParams Params = FAudioCaptureDeviceParams();
|
||||
|
||||
// Start the stream here to avoid hitching the audio render thread.
|
||||
if (AudioCapture.OpenCaptureStream(Params, MoveTemp(OnCapture), 1024))
|
||||
{
|
||||
AudioCapture.StartStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
bSuccess = false;
|
||||
}
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
bool FConvaiAudioCaptureSynth::OpenStream(int32 DeviceIndex)
|
||||
{
|
||||
bool bSuccess = true;
|
||||
if (!AudioCapture.IsStreamOpen())
|
||||
{
|
||||
FOnCaptureFunction OnCapture = [this](const float* AudioData, int32 NumFrames, int32 NumChannels, int32 SampleRate, double StreamTime, bool bOverFlow)
|
||||
{
|
||||
int32 NumSamples = NumChannels * NumFrames;
|
||||
|
||||
FScopeLock Lock(&CaptureCriticalSection);
|
||||
|
||||
if (bIsCapturing)
|
||||
{
|
||||
// Append the audio memory to the capture data buffer
|
||||
int32 Index = AudioCaptureData.AddUninitialized(NumSamples);
|
||||
float* AudioCaptureDataPtr = AudioCaptureData.GetData();
|
||||
FMemory::Memcpy(&AudioCaptureDataPtr[Index], AudioData, NumSamples * sizeof(float));
|
||||
}
|
||||
};
|
||||
|
||||
// Prepare the audio buffer memory for 2 seconds of stereo audio at 48k SR to reduce chance for allocation in callbacks
|
||||
AudioCaptureData.Reserve(2 * 2 * 48000);
|
||||
|
||||
FAudioCaptureDeviceParams Params = FAudioCaptureDeviceParams();
|
||||
Params.DeviceIndex = DeviceIndex;
|
||||
// Start the stream here to avoid hitching the audio render thread.
|
||||
if (AudioCapture.OpenCaptureStream(Params, MoveTemp(OnCapture), 1024))
|
||||
{
|
||||
AudioCapture.StartStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
bSuccess = false;
|
||||
}
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
void FConvaiAudioCaptureSynth::CloseStream()
|
||||
{
|
||||
if (AudioCapture.IsStreamOpen())
|
||||
{
|
||||
AudioCapture.CloseStream();
|
||||
}
|
||||
}
|
||||
|
||||
bool FConvaiAudioCaptureSynth::StartCapturing()
|
||||
{
|
||||
FScopeLock Lock(&CaptureCriticalSection);
|
||||
|
||||
AudioCaptureData.Reset();
|
||||
|
||||
check(AudioCapture.IsStreamOpen());
|
||||
|
||||
bIsCapturing = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FConvaiAudioCaptureSynth::StopCapturing()
|
||||
{
|
||||
check(AudioCapture.IsStreamOpen());
|
||||
check(AudioCapture.IsCapturing());
|
||||
FScopeLock Lock(&CaptureCriticalSection);
|
||||
bIsCapturing = false;
|
||||
}
|
||||
|
||||
void FConvaiAudioCaptureSynth::AbortCapturing()
|
||||
{
|
||||
AudioCapture.AbortStream();
|
||||
AudioCapture.CloseStream();
|
||||
}
|
||||
|
||||
bool FConvaiAudioCaptureSynth::IsStreamOpen() const
|
||||
{
|
||||
return AudioCapture.IsStreamOpen();
|
||||
}
|
||||
|
||||
bool FConvaiAudioCaptureSynth::IsCapturing() const
|
||||
{
|
||||
return bIsCapturing;
|
||||
}
|
||||
|
||||
int32 FConvaiAudioCaptureSynth::GetNumSamplesEnqueued()
|
||||
{
|
||||
FScopeLock Lock(&CaptureCriticalSection);
|
||||
return AudioCaptureData.Num();
|
||||
}
|
||||
|
||||
FAudioCapture* FConvaiAudioCaptureSynth::GetAudioCapture()
|
||||
{
|
||||
return &AudioCapture;
|
||||
}
|
||||
|
||||
bool FConvaiAudioCaptureSynth::GetAudioData(TArray<float>& OutAudioData)
|
||||
{
|
||||
FScopeLock Lock(&CaptureCriticalSection);
|
||||
|
||||
int32 CaptureDataSamples = AudioCaptureData.Num();
|
||||
if (CaptureDataSamples > 0)
|
||||
{
|
||||
// Append the capture audio to the output buffer
|
||||
int32 OutIndex = OutAudioData.AddUninitialized(CaptureDataSamples);
|
||||
float* OutDataPtr = OutAudioData.GetData();
|
||||
FMemory::Memcpy(&OutDataPtr[OutIndex], AudioCaptureData.GetData(), CaptureDataSamples * sizeof(float));
|
||||
|
||||
// Reset the capture data buffer since we copied the audio out
|
||||
AudioCaptureData.Reset();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
UConvaiAudioCaptureComponent::UConvaiAudioCaptureComponent(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
bSuccessfullyInitialized = false;
|
||||
bIsCapturing = false;
|
||||
CapturedAudioDataSamples = 0;
|
||||
ReadSampleIndex = 0;
|
||||
bIsDestroying = false;
|
||||
bIsNotReadyForForFinishDestroy = false;
|
||||
bIsStreamOpen = false;
|
||||
CaptureAudioData.Reserve(2 * 48000 * 5);
|
||||
SelectedDeviceIndex = -1;
|
||||
}
|
||||
|
||||
bool UConvaiAudioCaptureComponent::Init(int32& SampleRate)
|
||||
{
|
||||
|
||||
Audio::FCaptureDeviceInfo DeviceInfo;
|
||||
bool FoundDevice = false;
|
||||
if (SelectedDeviceIndex == -1)
|
||||
{
|
||||
FoundDevice = CaptureSynth.GetDefaultCaptureDeviceInfo(DeviceInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
FoundDevice = CaptureSynth.GetCaptureDeviceInfo(DeviceInfo, SelectedDeviceIndex);
|
||||
if (!FoundDevice)
|
||||
{
|
||||
FoundDevice = CaptureSynth.GetDefaultCaptureDeviceInfo(DeviceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
CONVAI_LOG(ConvaiAudioLog, Log, TEXT("Using %s as Audio capture device with NumChannels:%d and SampleRate:%d"), *DeviceInfo.DeviceName, DeviceInfo.InputChannels, DeviceInfo.PreferredSampleRate);
|
||||
|
||||
if (FoundDevice)
|
||||
{
|
||||
SampleRate = DeviceInfo.PreferredSampleRate;
|
||||
NumChannels = DeviceInfo.InputChannels;
|
||||
|
||||
// Only support mono and stereo mic inputs for now...
|
||||
if (NumChannels == 1 || NumChannels == 2)
|
||||
{
|
||||
// This may fail if capture synths aren't supported on a given platform or if something went wrong with the capture device
|
||||
bIsStreamOpen = CaptureSynth.OpenStream(SelectedDeviceIndex);
|
||||
if (!bIsStreamOpen)
|
||||
{
|
||||
CONVAI_LOG(ConvaiAudioLog, Warning, TEXT("OpenStream returned false."));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiAudioLog, Warning, TEXT("Audio capture components only support mono and stereo mic input - Audio might be mangeled."));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UConvaiAudioCaptureComponent::BeginDestroy()
|
||||
{
|
||||
Super::BeginDestroy();
|
||||
|
||||
// Flag that we're beginning to be destroyed
|
||||
// This is so that if a mic capture is open, we shut it down on the render thread
|
||||
bIsDestroying = true;
|
||||
|
||||
// Make sure stop is kicked off
|
||||
Stop();
|
||||
}
|
||||
|
||||
bool UConvaiAudioCaptureComponent::IsReadyForFinishDestroy()
|
||||
{
|
||||
return !bIsNotReadyForForFinishDestroy;
|
||||
}
|
||||
|
||||
void UConvaiAudioCaptureComponent::FinishDestroy()
|
||||
{
|
||||
if (CaptureSynth.IsStreamOpen())
|
||||
{
|
||||
CaptureSynth.AbortCapturing();
|
||||
}
|
||||
|
||||
check(!CaptureSynth.IsStreamOpen());
|
||||
|
||||
Super::FinishDestroy();
|
||||
bSuccessfullyInitialized = false;
|
||||
bIsCapturing = false;
|
||||
bIsDestroying = false;
|
||||
bIsStreamOpen = false;
|
||||
}
|
||||
|
||||
bool UConvaiAudioCaptureComponent::GetDefaultCaptureDeviceInfo(Audio::FCaptureDeviceInfo& OutInfo)
|
||||
{
|
||||
return CaptureSynth.GetDefaultCaptureDeviceInfo(OutInfo);
|
||||
}
|
||||
|
||||
bool UConvaiAudioCaptureComponent::GetCaptureDeviceInfo(Audio::FCaptureDeviceInfo& OutInfo, int32 DeviceIndex)
|
||||
{
|
||||
return CaptureSynth.GetCaptureDeviceInfo(OutInfo, DeviceIndex);
|
||||
}
|
||||
|
||||
TArray<Audio::FCaptureDeviceInfo> UConvaiAudioCaptureComponent::GetCaptureDevicesAvailable()
|
||||
{
|
||||
return CaptureSynth.GetCaptureDevicesAvailable();
|
||||
}
|
||||
|
||||
int32 UConvaiAudioCaptureComponent::GetActiveCaptureDevice(Audio::FCaptureDeviceInfo& OutInfo)
|
||||
{
|
||||
if (SelectedDeviceIndex == -1)
|
||||
GetDefaultCaptureDeviceInfo(OutInfo);
|
||||
else
|
||||
GetCaptureDeviceInfo(OutInfo, SelectedDeviceIndex);
|
||||
return SelectedDeviceIndex;
|
||||
}
|
||||
|
||||
bool UConvaiAudioCaptureComponent::SetCaptureDevice(int32 DeviceIndex)
|
||||
{
|
||||
Audio::FCaptureDeviceInfo OutInfo;
|
||||
if (GetCaptureDeviceInfo(OutInfo, DeviceIndex))
|
||||
{
|
||||
CaptureSynth.CloseStream();
|
||||
SelectedDeviceIndex = DeviceIndex;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Audio::FConvaiAudioCaptureSynth* UConvaiAudioCaptureComponent::GetCaptureSynth()
|
||||
{
|
||||
return &CaptureSynth;
|
||||
}
|
||||
|
||||
void UConvaiAudioCaptureComponent::OnBeginGenerate()
|
||||
{
|
||||
CapturedAudioDataSamples = 0;
|
||||
ReadSampleIndex = 0;
|
||||
CaptureAudioData.Reset();
|
||||
|
||||
if (!bIsStreamOpen)
|
||||
{
|
||||
bIsStreamOpen = CaptureSynth.OpenDefaultStream();
|
||||
}
|
||||
|
||||
if (bIsStreamOpen)
|
||||
{
|
||||
CaptureSynth.StartCapturing();
|
||||
check(CaptureSynth.IsCapturing());
|
||||
|
||||
// Don't allow this component to be destroyed until the stream is closed again
|
||||
bIsNotReadyForForFinishDestroy = true;
|
||||
FramesSinceStarting = 0;
|
||||
ReadSampleIndex = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UConvaiAudioCaptureComponent::OnEndGenerate()
|
||||
{
|
||||
if (bIsStreamOpen)
|
||||
{
|
||||
check(CaptureSynth.IsStreamOpen());
|
||||
CaptureSynth.StopCapturing();
|
||||
bIsStreamOpen = false;
|
||||
|
||||
bIsNotReadyForForFinishDestroy = false;
|
||||
}
|
||||
}
|
||||
|
||||
int32 UConvaiAudioCaptureComponent::OnGenerateAudio(float* OutAudio, int32 NumSamples)
|
||||
{
|
||||
// Don't do anything if the stream isn't open
|
||||
if (!bIsStreamOpen || !CaptureSynth.IsStreamOpen() || !CaptureSynth.IsCapturing())
|
||||
{
|
||||
// Just return NumSamples, which uses zero'd buffer
|
||||
return NumSamples;
|
||||
}
|
||||
|
||||
int32 OutputSamplesGenerated = 0;
|
||||
|
||||
if (CapturedAudioDataSamples > 0 || CaptureSynth.GetNumSamplesEnqueued() > 1024)
|
||||
{
|
||||
// Check if we need to read more audio data from capture synth
|
||||
if (ReadSampleIndex + NumSamples > CaptureAudioData.Num())
|
||||
{
|
||||
// but before we do, copy off the remainder of the capture audio data buffer if there's data in it
|
||||
int32 SamplesLeft = FMath::Max(0, CaptureAudioData.Num() - ReadSampleIndex);
|
||||
if (SamplesLeft > 0)
|
||||
{
|
||||
float* CaptureDataPtr = CaptureAudioData.GetData();
|
||||
FMemory::Memcpy(OutAudio, &CaptureDataPtr[ReadSampleIndex], SamplesLeft * sizeof(float));
|
||||
|
||||
// Track samples generated
|
||||
OutputSamplesGenerated += SamplesLeft;
|
||||
}
|
||||
|
||||
// Get another block of audio from the capture synth
|
||||
CaptureAudioData.Reset();
|
||||
CaptureSynth.GetAudioData(CaptureAudioData);
|
||||
|
||||
// Reset the read sample index since we got a new buffer of audio data
|
||||
ReadSampleIndex = 0;
|
||||
}
|
||||
|
||||
// note it's possible we didn't get any more audio in our last attempt to get it
|
||||
if (CaptureAudioData.Num() > 0)
|
||||
{
|
||||
// Compute samples to copy
|
||||
int32 NumSamplesToCopy = FMath::Min(NumSamples - OutputSamplesGenerated, CaptureAudioData.Num() - ReadSampleIndex);
|
||||
|
||||
float* CaptureDataPtr = CaptureAudioData.GetData();
|
||||
FMemory::Memcpy(&OutAudio[OutputSamplesGenerated], &CaptureDataPtr[ReadSampleIndex], NumSamplesToCopy * sizeof(float));
|
||||
ReadSampleIndex += NumSamplesToCopy;
|
||||
OutputSamplesGenerated += NumSamplesToCopy;
|
||||
}
|
||||
|
||||
CapturedAudioDataSamples += OutputSamplesGenerated;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Say we generated the full samples, this will result in silence
|
||||
OutputSamplesGenerated = NumSamples;
|
||||
}
|
||||
|
||||
return OutputSamplesGenerated;
|
||||
}
|
||||
|
||||
1679
ConvAI/Convai/Source/Convai/Private/ConvaiAudioStreamer.cpp
Normal file
1679
ConvAI/Convai/Source/Convai/Private/ConvaiAudioStreamer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1764
ConvAI/Convai/Source/Convai/Private/ConvaiChatBotProxy.cpp
Normal file
1764
ConvAI/Convai/Source/Convai/Private/ConvaiChatBotProxy.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1357
ConvAI/Convai/Source/Convai/Private/ConvaiChatbotComponent.cpp
Normal file
1357
ConvAI/Convai/Source/Convai/Private/ConvaiChatbotComponent.cpp
Normal file
File diff suppressed because it is too large
Load Diff
12
ConvAI/Convai/Source/Convai/Private/ConvaiDefinitions.cpp
Normal file
12
ConvAI/Convai/Source/Convai/Private/ConvaiDefinitions.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
|
||||
#include "ConvaiDefinitions.h"
|
||||
|
||||
const TMap<EEmotionIntensity, float> FConvaiEmotionState::ScoreMultipliers =
|
||||
{
|
||||
{EEmotionIntensity::None, 0.0},
|
||||
{EEmotionIntensity::LessIntense, 0.25},
|
||||
{EEmotionIntensity::Basic, 0.6},
|
||||
{EEmotionIntensity::MoreIntense, 1}
|
||||
};
|
||||
346
ConvAI/Convai/Source/Convai/Private/ConvaiFaceSync.cpp
Normal file
346
ConvAI/Convai/Source/Convai/Private/ConvaiFaceSync.cpp
Normal file
@@ -0,0 +1,346 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#include "ConvaiFaceSync.h"
|
||||
#include "Misc/ScopeLock.h"
|
||||
#include "ConvaiUtils.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiFaceSyncLog);
|
||||
|
||||
namespace
|
||||
{
|
||||
// Helper function: Creates a zero blendshapes map
|
||||
TMap<FName, float> CreateZeroBlendshapes()
|
||||
{
|
||||
TMap<FName, float> ZeroBlendshapes;
|
||||
for (const auto& BlendShapeName : ConvaiConstants::BlendShapesNames)
|
||||
{
|
||||
ZeroBlendshapes.Add(*BlendShapeName, 0.0);
|
||||
}
|
||||
return ZeroBlendshapes;
|
||||
}
|
||||
|
||||
// Helper function: Creates a zero visemes map
|
||||
TMap<FName, float> CreateZeroVisemes()
|
||||
{
|
||||
TMap<FName, float> ZeroVisemes;
|
||||
for (const auto& VisemeName : ConvaiConstants::VisemeNames)
|
||||
{
|
||||
ZeroVisemes.Add(*VisemeName, 0.0);
|
||||
}
|
||||
ZeroVisemes["sil"] = 1;
|
||||
return ZeroVisemes;
|
||||
}
|
||||
|
||||
|
||||
float Calculate1DBezierCurve(float t, float P0, float P1, float P2, float P3)
|
||||
{
|
||||
// Make sure t is in the range [0, 1]
|
||||
t = FMath::Clamp(t, 0.0f, 1.0f);
|
||||
|
||||
// Calculate the 1D Bezier curve value at time t
|
||||
float result = FMath::Pow(1.0f - t, 3.0f) * P0 + 3.0f * FMath::Pow(1.0f - t, 2.0f) * t * P1 +
|
||||
3.0f * (1.0f - t) * FMath::Pow(t, 2.0f) * P2 + FMath::Pow(t, 3.0f) * P3;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const TMap<FName, float> UConvaiFaceSyncComponent::ZeroBlendshapeFrame = CreateZeroBlendshapes();
|
||||
const TMap<FName, float> UConvaiFaceSyncComponent::ZeroVisemeFrame = CreateZeroVisemes();
|
||||
|
||||
UConvaiFaceSyncComponent::UConvaiFaceSyncComponent()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
CurrentSequenceTimePassed = 0;
|
||||
bAutoActivate = true;
|
||||
//CurrentBlendShapesMap = ZeroBlendshapeFrame;
|
||||
}
|
||||
|
||||
UConvaiFaceSyncComponent::~UConvaiFaceSyncComponent() // Implement destructor
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UConvaiFaceSyncComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
CurrentBlendShapesMap = GenerateZeroFrame();
|
||||
}
|
||||
|
||||
void UConvaiFaceSyncComponent::TickComponent(float DeltaTime, ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
// Interpolate blendshapes and advance animation sequence
|
||||
if (IsValidSequence(MainSequenceBuffer))
|
||||
{
|
||||
SequenceCriticalSection.Lock();
|
||||
|
||||
// Calculate time passed since ConvaiProcessLipSyncAdvanced was called
|
||||
double CurrentTime = FPlatformTime::Seconds();
|
||||
CurrentSequenceTimePassed = CurrentTime - StartTime;
|
||||
|
||||
if (CurrentSequenceTimePassed > MainSequenceBuffer.Duration)
|
||||
{
|
||||
ConvaiStopLipSync();
|
||||
SequenceCriticalSection.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
bIsPlaying = true;
|
||||
|
||||
// Calculate frame duration and offsets
|
||||
float FrameDuration = MainSequenceBuffer.Duration / MainSequenceBuffer.AnimationFrames.Num();
|
||||
float FrameOffset = FrameDuration * 0.5f;
|
||||
int32 FrameIndex;
|
||||
int32 BufferIndex;
|
||||
|
||||
TMap<FName, float> StartFrame;
|
||||
TMap<FName, float> EndFrame;
|
||||
float Alpha;
|
||||
|
||||
// Choose the current and next BlendShapes
|
||||
if (CurrentSequenceTimePassed <= FrameOffset)
|
||||
{
|
||||
//StartFrame = ZeroBlendshapeFrame;
|
||||
StartFrame = GetCurrentFrame();
|
||||
EndFrame = MainSequenceBuffer.AnimationFrames[0].BlendShapes;
|
||||
Alpha = CurrentSequenceTimePassed / FrameOffset + 0.5;
|
||||
FrameIndex = MainSequenceBuffer.AnimationFrames[0].FrameIndex;
|
||||
BufferIndex = 0;
|
||||
}
|
||||
else if (CurrentSequenceTimePassed >= MainSequenceBuffer.Duration - FrameOffset)
|
||||
{
|
||||
int LastFrameIdx = MainSequenceBuffer.AnimationFrames.Num() - 1;
|
||||
StartFrame = MainSequenceBuffer.AnimationFrames[LastFrameIdx].BlendShapes;
|
||||
EndFrame = GenerateZeroFrame();
|
||||
Alpha = (CurrentSequenceTimePassed - (MainSequenceBuffer.Duration - FrameOffset)) / FrameOffset;
|
||||
FrameIndex = MainSequenceBuffer.AnimationFrames[LastFrameIdx].FrameIndex;
|
||||
BufferIndex = LastFrameIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
int CurrentFrameIndex = FMath::FloorToInt((CurrentSequenceTimePassed - FrameOffset) / FrameDuration);
|
||||
CurrentFrameIndex = FMath::Min(CurrentFrameIndex, MainSequenceBuffer.AnimationFrames.Num() - 1);
|
||||
int NextFrameIndex = FMath::Min(CurrentFrameIndex + 1, MainSequenceBuffer.AnimationFrames.Num() - 1);
|
||||
StartFrame = MainSequenceBuffer.AnimationFrames[CurrentFrameIndex].BlendShapes;
|
||||
EndFrame = MainSequenceBuffer.AnimationFrames[NextFrameIndex].BlendShapes;
|
||||
Alpha = (CurrentSequenceTimePassed - FrameOffset - (CurrentFrameIndex * FrameDuration)) / FrameDuration;
|
||||
|
||||
Apply_StartEndFrames_PostProcessing(CurrentFrameIndex, NextFrameIndex, Alpha, StartFrame, EndFrame);
|
||||
|
||||
FrameIndex = MainSequenceBuffer.AnimationFrames[CurrentFrameIndex].FrameIndex;
|
||||
BufferIndex = CurrentFrameIndex;
|
||||
}
|
||||
SequenceCriticalSection.Unlock();
|
||||
|
||||
// CONVAI_LOG(ConvaiFaceSyncLog, Log, TEXT("Evaluate: FrameIndex:%d Alpha: %f FramesLeft: %d"), FrameIndex, Alpha, MainSequenceBuffer.AnimationFrames.Num() - BufferIndex);
|
||||
|
||||
//CurrentBlendShapesMap = StartFrame;
|
||||
CurrentBlendShapesMap = InterpolateFrames(StartFrame, EndFrame, Alpha);
|
||||
|
||||
ApplyPostProcessing();
|
||||
|
||||
// Trigger the blueprint event
|
||||
OnVisemesDataReady.ExecuteIfBound();
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiFaceSyncComponent::ConvaiApplyPrecomputedFacialAnimation(uint8* InPCMData, uint32 InPCMDataSize, uint32 InSampleRate, uint32 InNumChannels, FAnimationSequence FaceSequence)
|
||||
{
|
||||
SequenceCriticalSection.Lock();
|
||||
MainSequenceBuffer.AnimationFrames.Append(FaceSequence.AnimationFrames);
|
||||
MainSequenceBuffer.Duration += FaceSequence.Duration;
|
||||
MainSequenceBuffer.FrameRate = FaceSequence.FrameRate;
|
||||
CalculateStartingTime();
|
||||
SequenceCriticalSection.Unlock();
|
||||
|
||||
if (IsRecordingLipSync)
|
||||
{
|
||||
FScopeLock ScopeLock(&RecordingCriticalSection);
|
||||
RecordedSequenceBuffer.AnimationFrames.Append(FaceSequence.AnimationFrames);
|
||||
RecordedSequenceBuffer.Duration += FaceSequence.Duration;
|
||||
RecordedSequenceBuffer.FrameRate = FaceSequence.FrameRate;
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiFaceSyncComponent::ConvaiApplyFacialFrame(FAnimationFrame FaceFrame, float Duration)
|
||||
{
|
||||
SequenceCriticalSection.Lock();
|
||||
if (!GeneratesVisemesAsBlendshapes())
|
||||
{
|
||||
float* sil = FaceFrame.BlendShapes.Find("sil");
|
||||
if (sil != nullptr && *sil < 0)
|
||||
{
|
||||
ClearMainSequence();
|
||||
Stopping = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MainSequenceBuffer.AnimationFrames.Add(FaceFrame);
|
||||
MainSequenceBuffer.Duration += Duration;
|
||||
MainSequenceBuffer.FrameRate = Duration==0? -1 : 1.0/Duration;
|
||||
SequenceCriticalSection.Unlock();
|
||||
|
||||
if (IsRecordingLipSync)
|
||||
{
|
||||
FScopeLock ScopeLock(&RecordingCriticalSection);
|
||||
RecordedSequenceBuffer.AnimationFrames.Add(FaceFrame);
|
||||
RecordedSequenceBuffer.Duration += Duration;
|
||||
RecordedSequenceBuffer.FrameRate = Duration == 0 ? -1 : 1.0 / Duration;
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiFaceSyncComponent::StartRecordingLipSync()
|
||||
{
|
||||
if (IsRecordingLipSync)
|
||||
{
|
||||
CONVAI_LOG(ConvaiFaceSyncLog, Warning, TEXT("Cannot start Recording LipSync while already recording LipSync"));
|
||||
return;
|
||||
}
|
||||
|
||||
CONVAI_LOG(ConvaiFaceSyncLog, Log, TEXT("Started Recording LipSync"));
|
||||
IsRecordingLipSync = true;
|
||||
}
|
||||
|
||||
FAnimationSequenceBP UConvaiFaceSyncComponent::FinishRecordingLipSync()
|
||||
{
|
||||
CONVAI_LOG(ConvaiFaceSyncLog, Log, TEXT("Finished Recording LipSync - Total Frames: %d - Duration: %f"), RecordedSequenceBuffer.AnimationFrames.Num(), RecordedSequenceBuffer.Duration);
|
||||
|
||||
if (!IsRecordingLipSync)
|
||||
return FAnimationSequenceBP();
|
||||
|
||||
FScopeLock ScopeLock(&RecordingCriticalSection);
|
||||
IsRecordingLipSync = false;
|
||||
|
||||
FAnimationSequenceBP AnimationSequenceBP;
|
||||
AnimationSequenceBP.AnimationSequence = RecordedSequenceBuffer;
|
||||
RecordedSequenceBuffer.AnimationFrames.Empty();
|
||||
RecordedSequenceBuffer.Duration = 0;
|
||||
return AnimationSequenceBP;
|
||||
}
|
||||
|
||||
bool UConvaiFaceSyncComponent::PlayRecordedLipSync(FAnimationSequenceBP RecordedLipSync, int StartFrame, int EndFrame, float OverwriteDuration)
|
||||
{
|
||||
if (!IsValidSequence(RecordedLipSync.AnimationSequence))
|
||||
{
|
||||
CONVAI_LOG(ConvaiFaceSyncLog, Warning, TEXT("Recorded LipSync is not valid - Total Frames: %d - Duration: %f"), RecordedLipSync.AnimationSequence.AnimationFrames.Num(), RecordedLipSync.AnimationSequence.Duration);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsRecordingLipSync)
|
||||
{
|
||||
CONVAI_LOG(ConvaiFaceSyncLog, Warning, TEXT("Cannot Play Recorded LipSync while Recording LipSync"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsValidSequence(MainSequenceBuffer))
|
||||
{
|
||||
CONVAI_LOG(ConvaiFaceSyncLog, Warning, TEXT("Playing Recorded LipSync and stopping currently playing LipSync"));
|
||||
ConvaiStopLipSync();
|
||||
}
|
||||
|
||||
if (StartFrame > 0 && StartFrame > RecordedLipSync.AnimationSequence.AnimationFrames.Num() - 1)
|
||||
{
|
||||
CONVAI_LOG(ConvaiFaceSyncLog, Warning, TEXT("StartFrame is greater than the recorded LipSync - StartFrame: %d Total Frames: %d - Duration: %f"), StartFrame, RecordedLipSync.AnimationSequence.AnimationFrames.Num(), RecordedLipSync.AnimationSequence.Duration);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (EndFrame > 0 && EndFrame < StartFrame)
|
||||
{
|
||||
CONVAI_LOG(ConvaiFaceSyncLog, Warning, TEXT("StartFrame cannot be greater than the EndFrame"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//if (EndFrame > 0 && EndFrame > RecordedLipSync.AnimationSequence.AnimationFrames.Num() - 1)
|
||||
//{
|
||||
// CONVAI_LOG(ConvaiFaceSyncLog, Warning, TEXT("EndFrame is greater than the recorded LipSync - EndFrame: %d Total Frames: %d - Duration: %f"), EndFrame, RecordedLipSync.AnimationSequence.AnimationFrames.Num(), RecordedLipSync.AnimationSequence.Duration);
|
||||
// return false;
|
||||
//}
|
||||
|
||||
if (EndFrame > 0 && EndFrame < RecordedLipSync.AnimationSequence.AnimationFrames.Num()-1)
|
||||
{
|
||||
float FrameDuration = RecordedLipSync.AnimationSequence.Duration / RecordedLipSync.AnimationSequence.AnimationFrames.Num();
|
||||
int NumRemovedFrames = RecordedLipSync.AnimationSequence.AnimationFrames.Num() - EndFrame - 1;
|
||||
RecordedLipSync.AnimationSequence.AnimationFrames.RemoveAt(EndFrame + 1, NumRemovedFrames);
|
||||
float RemovedDuration = NumRemovedFrames * FrameDuration;
|
||||
RecordedLipSync.AnimationSequence.Duration -= RemovedDuration;
|
||||
}
|
||||
|
||||
if (StartFrame > 0)
|
||||
{
|
||||
float FrameDuration = RecordedLipSync.AnimationSequence.Duration / RecordedLipSync.AnimationSequence.AnimationFrames.Num();
|
||||
int NumRemovedFrames = StartFrame;
|
||||
RecordedLipSync.AnimationSequence.AnimationFrames.RemoveAt(0, NumRemovedFrames);
|
||||
float RemovedDuration = NumRemovedFrames * FrameDuration;
|
||||
RecordedLipSync.AnimationSequence.Duration -= RemovedDuration;
|
||||
}
|
||||
|
||||
if (OverwriteDuration > 0)
|
||||
{
|
||||
RecordedLipSync.AnimationSequence.Duration = OverwriteDuration;
|
||||
}
|
||||
|
||||
CONVAI_LOG(ConvaiFaceSyncLog, Log, TEXT("Playing Recorded LipSync - Total Frames: %d - Duration: %f"), RecordedLipSync.AnimationSequence.AnimationFrames.Num(), RecordedLipSync.AnimationSequence.Duration);
|
||||
ConvaiApplyPrecomputedFacialAnimation(nullptr, 0, 0, 0, RecordedLipSync.AnimationSequence);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UConvaiFaceSyncComponent::IsValidSequence(const FAnimationSequence& Sequence)
|
||||
{
|
||||
if (Sequence.Duration > 0 && Sequence.AnimationFrames.Num() > 0 && Sequence.AnimationFrames[0].BlendShapes.Num() > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UConvaiFaceSyncComponent::IsPlaying()
|
||||
{
|
||||
return bIsPlaying;
|
||||
}
|
||||
|
||||
void UConvaiFaceSyncComponent::CalculateStartingTime()
|
||||
{
|
||||
if (!bIsPlaying)
|
||||
StartTime = FPlatformTime::Seconds();
|
||||
}
|
||||
|
||||
void UConvaiFaceSyncComponent::ForceRecalculateStartTime()
|
||||
{
|
||||
StartTime = FPlatformTime::Seconds();
|
||||
}
|
||||
|
||||
void UConvaiFaceSyncComponent::ClearMainSequence()
|
||||
{
|
||||
SequenceCriticalSection.Lock();
|
||||
MainSequenceBuffer.AnimationFrames.Empty();
|
||||
MainSequenceBuffer.Duration = 0;
|
||||
SequenceCriticalSection.Unlock();
|
||||
}
|
||||
|
||||
TMap<FName, float> UConvaiFaceSyncComponent::InterpolateFrames(const TMap<FName, float>& StartFrame, const TMap<FName, float>& EndFrame, float Alpha)
|
||||
{
|
||||
const TArray<FString>& CurveNames = GeneratesVisemesAsBlendshapes() ? ConvaiConstants::BlendShapesNames : ConvaiConstants::VisemeNames;
|
||||
TMap<FName, float> Result;
|
||||
for (const auto& CurveName : CurveNames)
|
||||
{
|
||||
float StartValue = StartFrame.Contains(*CurveName) ? StartFrame[*CurveName] : 0.0;
|
||||
float EndValue = EndFrame.Contains(*CurveName) ? EndFrame[*CurveName] : 0.0;
|
||||
Result.Add(*CurveName, FMath::Lerp(StartValue, EndValue, Alpha));
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
void UConvaiFaceSyncComponent::ConvaiStopLipSync()
|
||||
{
|
||||
bIsPlaying = false;
|
||||
CurrentSequenceTimePassed = 0;
|
||||
ClearMainSequence();
|
||||
SetCurrentFrametoZero();
|
||||
OnVisemesDataReady.ExecuteIfBound();
|
||||
// CONVAI_LOG(ConvaiFaceSyncLog, Warning, TEXT("Stopping LipSync"));
|
||||
}
|
||||
1131
ConvAI/Convai/Source/Convai/Private/ConvaiGRPC.cpp
Normal file
1131
ConvAI/Convai/Source/Convai/Private/ConvaiGRPC.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,256 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#include "ConvaiNarrativeDesignProxy.h"
|
||||
#include "ConvaiUtils.h"
|
||||
#include "../Convai.h"
|
||||
#include "Engine.h"
|
||||
#include "RestAPI/ConvaiURL.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiNarrativeHTTP);
|
||||
|
||||
UFetchNarrativeSectionsProxy* UFetchNarrativeSectionsProxy::FetchNarrativeSections(UObject* WorldContextObject, FString InCharacterId)
|
||||
{
|
||||
UFetchNarrativeSectionsProxy* Proxy = NewObject<UFetchNarrativeSectionsProxy>();
|
||||
Proxy->WorldPtr = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
|
||||
Proxy->CharacterId = InCharacterId;
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
void UFetchNarrativeSectionsProxy::Activate()
|
||||
{
|
||||
|
||||
UWorld* World = WorldPtr.Get();
|
||||
|
||||
if (!World)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("Could not get a pointer to world!"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
FHttpModule* Http = &FHttpModule::Get();
|
||||
if (!Http)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("Could not get a pointer to http module!"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
TPair<FString, FString> AuthHeaderAndKey = UConvaiUtils::GetAuthHeaderAndKey();
|
||||
FString AuthKey = AuthHeaderAndKey.Value;
|
||||
FString AuthHeader = AuthHeaderAndKey.Key;
|
||||
|
||||
// Form Validation
|
||||
if (
|
||||
!UConvaiFormValidation::ValidateAuthKey(AuthKey)
|
||||
|| !UConvaiFormValidation::ValidateCharacterID(CharacterId)
|
||||
)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("UFetchNarrativeSectionsProxy::Activate Invalid Character or API key"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
FHttpModule* HttpModule = &FHttpModule::Get();
|
||||
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> HttpRequest = HttpModule->CreateRequest();
|
||||
HttpRequest->OnProcessRequestComplete().BindUObject(this, &UFetchNarrativeSectionsProxy::OnHttpRequestCompleted);
|
||||
HttpRequest->SetURL(UConvaiURL::GetFullURL(TEXT("character/narrative/list-sections"), false));
|
||||
HttpRequest->SetVerb(TEXT("POST"));
|
||||
HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
|
||||
HttpRequest->SetHeader(AuthHeader, AuthKey);
|
||||
HttpRequest->SetContentAsString(FString::Printf(TEXT("{\"character_id\": \"%s\"}"), *CharacterId));
|
||||
HttpRequest->ProcessRequest();
|
||||
}
|
||||
|
||||
void UFetchNarrativeSectionsProxy::OnHttpRequestCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
|
||||
{
|
||||
NarrativeSections.Empty();
|
||||
if (!Response)
|
||||
{
|
||||
if (bWasSuccessful)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("HTTP request succeded - But response pointer is invalid"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("HTTP request failed - Response pointer is invalid"));
|
||||
}
|
||||
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bWasSuccessful || Response->GetResponseCode() < 200 || Response->GetResponseCode() > 299)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("HTTP request failed with code %d"), Response->GetResponseCode());
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("Response:%s"), *Response->GetContentAsString());
|
||||
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<TSharedPtr<FJsonValue>> JsonArray;
|
||||
const TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString());
|
||||
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonArray)) // Deserialize into a JSON array
|
||||
{
|
||||
for (const TSharedPtr<FJsonValue>& Val : JsonArray)
|
||||
{
|
||||
FNarrativeSection Section;
|
||||
if (FJsonObjectConverter::JsonObjectToUStruct(Val->AsObject().ToSharedRef(), FNarrativeSection::StaticStruct(), &Section))
|
||||
{
|
||||
NarrativeSections.Add(Section);
|
||||
}
|
||||
}
|
||||
success();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UFetchNarrativeSectionsProxy::failed()
|
||||
{
|
||||
//auto InvocationList = OnFailure.GetAllObjects();
|
||||
//CONVAI_LOG(ConvaiNarrativeHTTP, Log, TEXT("OnFailure delegate is bound to %d functions before invokation."), InvocationList.Num());
|
||||
|
||||
OnFailure.Broadcast(NarrativeSections);
|
||||
//CONVAI_LOG(ConvaiNarrativeHTTP, Log, TEXT("OnFailure delegate is bound to %d functions after invokation."), InvocationList.Num());
|
||||
finish();
|
||||
}
|
||||
|
||||
void UFetchNarrativeSectionsProxy::success()
|
||||
{
|
||||
//auto InvocationList = OnSuccess.GetAllObjects();
|
||||
//CONVAI_LOG(ConvaiNarrativeHTTP, Log, TEXT("OnSuccess delegate is bound to %d functions before invokation."), InvocationList.Num());
|
||||
|
||||
OnSuccess.Broadcast(NarrativeSections);
|
||||
//CONVAI_LOG(ConvaiNarrativeHTTP, Log, TEXT("OnSuccess delegate is bound to %d functions after invokation."), InvocationList.Num());
|
||||
finish();
|
||||
}
|
||||
|
||||
void UFetchNarrativeSectionsProxy::finish()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
UFetchNarrativeTriggersProxy* UFetchNarrativeTriggersProxy::FetchNarrativeTriggers(UObject* WorldContextObject, FString InCharacterId)
|
||||
{
|
||||
UFetchNarrativeTriggersProxy* Proxy = NewObject<UFetchNarrativeTriggersProxy>();
|
||||
Proxy->WorldPtr = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
|
||||
Proxy->CharacterId = InCharacterId;
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
void UFetchNarrativeTriggersProxy::Activate()
|
||||
{
|
||||
|
||||
UWorld* World = WorldPtr.Get();
|
||||
|
||||
if (!World)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("Could not get a pointer to world!"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
FHttpModule* Http = &FHttpModule::Get();
|
||||
if (!Http)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("Could not get a pointer to http module!"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
TPair<FString, FString> AuthHeaderAndKey = UConvaiUtils::GetAuthHeaderAndKey();
|
||||
FString AuthKey = AuthHeaderAndKey.Value;
|
||||
FString AuthHeader = AuthHeaderAndKey.Key;
|
||||
|
||||
// Form Validation
|
||||
if (
|
||||
!UConvaiFormValidation::ValidateAuthKey(AuthKey)
|
||||
|| !UConvaiFormValidation::ValidateCharacterID(CharacterId)
|
||||
)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("UFetchNarrativeTriggersProxy::Activate Invalid Character or API key"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
FHttpModule* HttpModule = &FHttpModule::Get();
|
||||
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> HttpRequest = HttpModule->CreateRequest();
|
||||
HttpRequest->OnProcessRequestComplete().BindUObject(this, &UFetchNarrativeTriggersProxy::OnHttpRequestCompleted);
|
||||
HttpRequest->SetURL(UConvaiURL::GetFullURL(TEXT("character/narrative/list-triggers"), false));
|
||||
HttpRequest->SetVerb(TEXT("POST"));
|
||||
HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
|
||||
HttpRequest->SetHeader(AuthHeader, AuthKey);
|
||||
HttpRequest->SetContentAsString(FString::Printf(TEXT("{\"character_id\": \"%s\"}"), *CharacterId));
|
||||
HttpRequest->ProcessRequest();
|
||||
}
|
||||
|
||||
void UFetchNarrativeTriggersProxy::OnHttpRequestCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
|
||||
{
|
||||
NarrativeTriggers.Empty();
|
||||
if (!Response)
|
||||
{
|
||||
if (bWasSuccessful)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("HTTP request succeded - But response pointer is invalid"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("HTTP request failed - Response pointer is invalid"));
|
||||
}
|
||||
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bWasSuccessful || Response->GetResponseCode() < 200 || Response->GetResponseCode() > 299)
|
||||
{
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("HTTP request failed with code %d"), Response->GetResponseCode());
|
||||
CONVAI_LOG(ConvaiNarrativeHTTP, Warning, TEXT("Response:%s"), *Response->GetContentAsString());
|
||||
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<TSharedPtr<FJsonValue>> JsonArray;
|
||||
const TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString());
|
||||
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonArray)) // Deserialize into a JSON array
|
||||
{
|
||||
for (const TSharedPtr<FJsonValue>& Val : JsonArray)
|
||||
{
|
||||
FNarrativeTrigger Trigger;
|
||||
if (FJsonObjectConverter::JsonObjectToUStruct(Val->AsObject().ToSharedRef(), FNarrativeTrigger::StaticStruct(), &Trigger))
|
||||
{
|
||||
NarrativeTriggers.Add(Trigger);
|
||||
}
|
||||
}
|
||||
success();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UFetchNarrativeTriggersProxy::failed()
|
||||
{
|
||||
//auto InvocationList = OnFailure.GetAllObjects();
|
||||
//CONVAI_LOG(ConvaiNarrativeHTTP, Log, TEXT("OnFailure delegate is bound to %d functions before invokation."), InvocationList.Num());
|
||||
|
||||
OnFailure.Broadcast(NarrativeTriggers);
|
||||
//CONVAI_LOG(ConvaiNarrativeHTTP, Log, TEXT("OnFailure delegate is bound to %d functions after invokation."), InvocationList.Num());
|
||||
finish();
|
||||
}
|
||||
|
||||
void UFetchNarrativeTriggersProxy::success()
|
||||
{
|
||||
//auto InvocationList = OnSuccess.GetAllObjects();
|
||||
//CONVAI_LOG(ConvaiNarrativeHTTP, Log, TEXT("OnSuccess delegate is bound to %d functions before invokation."), InvocationList.Num());
|
||||
|
||||
OnSuccess.Broadcast(NarrativeTriggers);
|
||||
//CONVAI_LOG(ConvaiNarrativeHTTP, Log, TEXT("OnSuccess delegate is bound to %d functions after invokation."), InvocationList.Num());
|
||||
finish();
|
||||
}
|
||||
|
||||
void UFetchNarrativeTriggersProxy::finish()
|
||||
{
|
||||
}
|
||||
|
||||
984
ConvAI/Convai/Source/Convai/Private/ConvaiPlayerComponent.cpp
Normal file
984
ConvAI/Convai/Source/Convai/Private/ConvaiPlayerComponent.cpp
Normal file
@@ -0,0 +1,984 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
|
||||
#include "ConvaiPlayerComponent.h"
|
||||
#include "ConvaiAudioCaptureComponent.h"
|
||||
#include "ConvaiChatbotComponent.h"
|
||||
#include "ConvaiActionUtils.h"
|
||||
#include "ConvaiUtils.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Http.h"
|
||||
#include "ConvaiUtils.h"
|
||||
#include "Containers/UnrealString.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "AudioMixerBlueprintLibrary.h"
|
||||
#include "Engine/GameEngine.h"
|
||||
#include "Sound/SoundWave.h"
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioMixerDevice.h"
|
||||
#include "UObject/ConstructorHelpers.h"
|
||||
#include "ConvaiSubsystem.h"
|
||||
#include "Engine/GameInstance.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiPlayerLog);
|
||||
|
||||
static FAudioDevice* GetAudioDeviceFromWorldContext(const UObject* WorldContextObject)
|
||||
{
|
||||
UWorld* ThisWorld = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
|
||||
if (!ThisWorld || !ThisWorld->bAllowAudioPlayback || ThisWorld->GetNetMode() == NM_DedicatedServer)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ThisWorld->GetAudioDevice().GetAudioDevice();
|
||||
}
|
||||
|
||||
static Audio::FMixerDevice* GetAudioMixerDeviceFromWorldContext(const UObject* WorldContextObject)
|
||||
{
|
||||
if (FAudioDevice* AudioDevice = GetAudioDeviceFromWorldContext(WorldContextObject))
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 3
|
||||
bool Found = AudioDevice != nullptr;
|
||||
#else
|
||||
bool Found = AudioDevice != nullptr && AudioDevice->IsAudioMixerEnabled();
|
||||
#endif
|
||||
|
||||
if (!Found)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<Audio::FMixerDevice*>(AudioDevice);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UConvaiPlayerComponent::UConvaiPlayerComponent()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
//SetIsReplicated(true);
|
||||
bAutoActivate = true;
|
||||
PlayerName = "Guest";
|
||||
|
||||
IsInit = false;
|
||||
VoiceCaptureRingBuffer.Init(ConvaiConstants::VoiceCaptureRingBufferCapacity);
|
||||
VoiceCaptureBuffer.Empty(ConvaiConstants::VoiceCaptureBufferSize);
|
||||
UsePixelStreamingMicInput = true;
|
||||
|
||||
const FString FoundSubmixPath = "/ConvAI/Submixes/AudioInput.AudioInput";
|
||||
static ConstructorHelpers::FObjectFinder<USoundSubmixBase> SoundSubmixFinder(*FoundSubmixPath);
|
||||
if (SoundSubmixFinder.Succeeded())
|
||||
{
|
||||
_FoundSubmix = SoundSubmixFinder.Object;
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::OnComponentCreated()
|
||||
{
|
||||
Super::OnComponentCreated();
|
||||
|
||||
AudioCaptureComponent = NewObject<UConvaiAudioCaptureComponent>(this, UConvaiAudioCaptureComponent::StaticClass(), TEXT("ConvaiAudioCapture"));
|
||||
if (AudioCaptureComponent)
|
||||
{
|
||||
AudioCaptureComponent->RegisterComponent();
|
||||
}
|
||||
//AudioCaptureComponent->SetupAttachment(this);
|
||||
|
||||
if (_FoundSubmix != nullptr) {
|
||||
AudioCaptureComponent->SoundSubmix = _FoundSubmix;
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("UConvaiPlayerComponent: Found submix \"AudioInput\""));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("UConvaiPlayerComponent: Audio Submix was not found, please ensure an audio submix exists at this directory: \"/ConvAI/Submixes/AudioInput\" then restart Unreal Engine"));
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
DOREPLIFETIME(UConvaiPlayerComponent, PlayerName);
|
||||
}
|
||||
|
||||
bool UConvaiPlayerComponent::Init()
|
||||
{
|
||||
if (IsInit)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("AudioCaptureComponent is already init"));
|
||||
return true;
|
||||
}
|
||||
|
||||
FString commandMicNoiseGateThreshold = "voice.MicNoiseGateThreshold 0.01";
|
||||
FString commandSilenceDetectionThreshold = "voice.SilenceDetectionThreshold 0.001";
|
||||
|
||||
APlayerController* PController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
|
||||
if (PController)
|
||||
{
|
||||
PController->ConsoleCommand(*commandMicNoiseGateThreshold, true);
|
||||
PController->ConsoleCommand(*commandSilenceDetectionThreshold, true);
|
||||
}
|
||||
|
||||
AudioCaptureComponent = Cast<UConvaiAudioCaptureComponent>(GetOwner()->GetComponentByClass(UConvaiAudioCaptureComponent::StaticClass()));
|
||||
if (!IsValid(AudioCaptureComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("Init: AudioCaptureComponent is not valid"));
|
||||
return false;
|
||||
}
|
||||
|
||||
IsInit = true;
|
||||
Token = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::SetPlayerName(FString NewPlayerName)
|
||||
{
|
||||
PlayerName = NewPlayerName;
|
||||
|
||||
if (GetIsReplicated())
|
||||
{
|
||||
SetPlayerNameServer(PlayerName);
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::SetPlayerNameServer_Implementation(const FString& NewPlayerName)
|
||||
{
|
||||
PlayerName = NewPlayerName;
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::SetSpeakerID(FString NewSpeakerID)
|
||||
{
|
||||
SpeakerID = NewSpeakerID;
|
||||
|
||||
if (GetIsReplicated())
|
||||
{
|
||||
SetSpeakerIDServer(SpeakerID);
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::SetSpeakerIDServer_Implementation(const FString& NewSpeakerID)
|
||||
{
|
||||
SpeakerID = NewSpeakerID;
|
||||
}
|
||||
|
||||
bool UConvaiPlayerComponent::GetDefaultCaptureDeviceInfo(FCaptureDeviceInfoBP& OutInfo)
|
||||
{
|
||||
if (!IsValid(AudioCaptureComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("GetDefaultCaptureDeviceInfo: AudioCaptureComponent is not valid"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UConvaiPlayerComponent::GetCaptureDeviceInfo(FCaptureDeviceInfoBP& OutInfo, int DeviceIndex)
|
||||
{
|
||||
if (!IsValid(AudioCaptureComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("GetCaptureDeviceInfo: AudioCaptureComponent is not valid"));
|
||||
return false;
|
||||
}
|
||||
Audio::FCaptureDeviceInfo OutDeviceInfo;
|
||||
if (AudioCaptureComponent->GetCaptureDeviceInfo(OutDeviceInfo, DeviceIndex))
|
||||
{
|
||||
OutInfo.bSupportsHardwareAEC = OutDeviceInfo.bSupportsHardwareAEC;
|
||||
OutInfo.LongDeviceId = OutDeviceInfo.DeviceId;
|
||||
OutInfo.DeviceName = OutDeviceInfo.DeviceName;
|
||||
OutInfo.InputChannels = OutDeviceInfo.InputChannels;
|
||||
OutInfo.PreferredSampleRate = OutDeviceInfo.PreferredSampleRate;
|
||||
OutInfo.DeviceIndex = DeviceIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TArray<FCaptureDeviceInfoBP> UConvaiPlayerComponent::GetAvailableCaptureDeviceDetails()
|
||||
{
|
||||
TArray<FCaptureDeviceInfoBP> FCaptureDevicesInfoBP;
|
||||
if (!IsValid(AudioCaptureComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("GetAvailableCaptureDeviceDetails: AudioCaptureComponent is not valid"));
|
||||
return FCaptureDevicesInfoBP;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (auto DeviceInfo : AudioCaptureComponent->GetCaptureDevicesAvailable())
|
||||
{
|
||||
FCaptureDeviceInfoBP CaptureDeviceInfoBP;
|
||||
CaptureDeviceInfoBP.bSupportsHardwareAEC = DeviceInfo.bSupportsHardwareAEC;
|
||||
CaptureDeviceInfoBP.LongDeviceId = DeviceInfo.DeviceId;
|
||||
CaptureDeviceInfoBP.DeviceName = DeviceInfo.DeviceName;
|
||||
CaptureDeviceInfoBP.InputChannels = DeviceInfo.InputChannels;
|
||||
CaptureDeviceInfoBP.PreferredSampleRate = DeviceInfo.PreferredSampleRate;
|
||||
CaptureDeviceInfoBP.DeviceIndex = i++;
|
||||
FCaptureDevicesInfoBP.Add(CaptureDeviceInfoBP);
|
||||
}
|
||||
return FCaptureDevicesInfoBP;
|
||||
}
|
||||
|
||||
TArray<FString> UConvaiPlayerComponent::GetAvailableCaptureDeviceNames()
|
||||
{
|
||||
TArray<FString> AvailableDeviceNames;
|
||||
if (!IsValid(AudioCaptureComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("GetAvailableCaptureDeviceNames: AudioCaptureComponent is not valid"));
|
||||
return AvailableDeviceNames;
|
||||
}
|
||||
|
||||
for (auto CaptureDeviceInfo : GetAvailableCaptureDeviceDetails())
|
||||
{
|
||||
AvailableDeviceNames.Add(CaptureDeviceInfo.DeviceName);
|
||||
}
|
||||
|
||||
return AvailableDeviceNames;
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::GetActiveCaptureDevice(FCaptureDeviceInfoBP& OutInfo)
|
||||
{
|
||||
if (!IsValid(AudioCaptureComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("GetActiveCaptureDevice: AudioCaptureComponent is not valid"));
|
||||
return;
|
||||
}
|
||||
Audio::FCaptureDeviceInfo OutDeviceInfo;
|
||||
int SelectedDeviceIndex = AudioCaptureComponent->GetActiveCaptureDevice(OutDeviceInfo);
|
||||
OutInfo.bSupportsHardwareAEC = OutDeviceInfo.bSupportsHardwareAEC;
|
||||
OutInfo.LongDeviceId = OutDeviceInfo.DeviceId;
|
||||
OutInfo.DeviceName = OutDeviceInfo.DeviceName;
|
||||
OutInfo.InputChannels = OutDeviceInfo.InputChannels;
|
||||
OutInfo.PreferredSampleRate = OutDeviceInfo.PreferredSampleRate;
|
||||
OutInfo.DeviceIndex = SelectedDeviceIndex;
|
||||
}
|
||||
|
||||
bool UConvaiPlayerComponent::SetCaptureDeviceByIndex(int DeviceIndex)
|
||||
{
|
||||
if (!IsValid(AudioCaptureComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SetCaptureDeviceByIndex: AudioCaptureComponent is not valid"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DeviceIndex >= GetAvailableCaptureDeviceDetails().Num())
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SetCaptureDeviceByIndex: Invalid Device Index: %d - Max possible index: %d."), DeviceIndex, GetAvailableCaptureDeviceDetails().Num() - 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return AudioCaptureComponent->SetCaptureDevice(DeviceIndex);
|
||||
}
|
||||
|
||||
bool UConvaiPlayerComponent::SetCaptureDeviceByName(FString DeviceName)
|
||||
{
|
||||
if (!IsValid(AudioCaptureComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SetCaptureDeviceByName: AudioCaptureComponent is not valid"));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bDeviceFound = false;
|
||||
int DeviceIndex = -1;
|
||||
for (auto CaptureDeviceInfo : GetAvailableCaptureDeviceDetails())
|
||||
{
|
||||
if (CaptureDeviceInfo.DeviceName == DeviceName)
|
||||
{
|
||||
bDeviceFound = true;
|
||||
DeviceIndex = CaptureDeviceInfo.DeviceIndex;
|
||||
}
|
||||
}
|
||||
|
||||
TArray<FString> AvailableDeviceNames;
|
||||
|
||||
if (!bDeviceFound)
|
||||
{
|
||||
AvailableDeviceNames = GetAvailableCaptureDeviceNames();
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SetCaptureDeviceByName: Could not find Device name: %s - Available Device names are: [%s]."), *DeviceName, *FString::Join(AvailableDeviceNames, *FString(" - ")));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetCaptureDeviceByIndex(DeviceIndex))
|
||||
{
|
||||
AvailableDeviceNames = GetAvailableCaptureDeviceNames();
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SetCaptureDeviceByName: SetCaptureDeviceByIndex failed for index: %d and device name: %s - Available Device names are: [%s]."), DeviceIndex, *DeviceName, *FString::Join(AvailableDeviceNames, *FString(" - ")));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::SetMicrophoneVolumeMultiplier(float InVolumeMultiplier, bool& Success)
|
||||
{
|
||||
Success = false;
|
||||
if (IsValid(AudioCaptureComponent))
|
||||
{
|
||||
AudioCaptureComponent->SetVolumeMultiplier(InVolumeMultiplier);
|
||||
Success = true;
|
||||
}
|
||||
|
||||
if (PixelStreamingAudioComponent.IsValid())
|
||||
{
|
||||
AudioCaptureComponent->SetVolumeMultiplier(InVolumeMultiplier*2); // multiply by 2 because Pixel Streaming mic is usually very low
|
||||
Success = true;
|
||||
}
|
||||
|
||||
if (!IsValid(AudioCaptureComponent) && !PixelStreamingAudioComponent.IsValid())
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SetMicrophoneVolumeMultiplier: AudioCaptureComponent and PixelStreamingAudioComponent are not valid"));
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::GetMicrophoneVolumeMultiplier(float& OutVolumeMultiplier, bool& Success)
|
||||
{
|
||||
Success = false;
|
||||
if (!IsValid(AudioCaptureComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SetMicrophoneVolumeMultiplier: AudioCaptureComponent is not valid"));
|
||||
return;
|
||||
}
|
||||
auto InternalAudioComponent = AudioCaptureComponent->GetAudioComponent();
|
||||
if (!InternalAudioComponent)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("GetMicrophoneVolumeMultiplier: InternalAudioComponent is not valid"));
|
||||
}
|
||||
OutVolumeMultiplier = InternalAudioComponent->VolumeMultiplier;
|
||||
Success = true;
|
||||
}
|
||||
|
||||
// void UConvaiPlayerComponent::GetIfHardwareFeatureIsSupported(EHardwareInputFeatureBP FeatureType, bool& Success)
|
||||
// {
|
||||
// Success = false;
|
||||
// if (!IsValid(AudioCaptureComponent))
|
||||
// {
|
||||
// CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("GetIfHardwareFeatureIsSupported: AudioCaptureComponent is not valid"));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// auto CaptureSynth = AudioCaptureComponent->GetCaptureSynth();
|
||||
// if (CaptureSynth == nullptr)
|
||||
// {
|
||||
// CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("GetIfHardwareFeatureIsSupported: CaptureSynth is not valid"));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// auto AudioCapture = CaptureSynth->GetAudioCapture();
|
||||
// if (AudioCapture == nullptr)
|
||||
// {
|
||||
// CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("GetIfHardwareFeatureIsSupported: AudioCapture is not valid"));
|
||||
// return;
|
||||
// }
|
||||
// Success = AudioCapture->GetIfHardwareFeatureIsSupported((Audio::EHardwareInputFeature)FeatureType);
|
||||
// }
|
||||
|
||||
// void UConvaiPlayerComponent::SetHardwareFeatureEnabled(EHardwareInputFeatureBP FeatureType, bool bIsEnabled, bool& Success)
|
||||
// {
|
||||
// bool HardwareFeatureIsSupported;
|
||||
// GetIfHardwareFeatureIsSupported(FeatureType, HardwareFeatureIsSupported);
|
||||
// if (!HardwareFeatureIsSupported)
|
||||
// {
|
||||
// if (!bIsEnabled)
|
||||
// {
|
||||
// Success = true;
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Success = false;
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
// auto AudioCapture = AudioCaptureComponent->GetCaptureSynth()->GetAudioCapture();
|
||||
// AudioCapture->SetHardwareFeatureEnabled((Audio::EHardwareInputFeature)FeatureType, bIsEnabled);
|
||||
// Success = true;
|
||||
// }
|
||||
|
||||
void UConvaiPlayerComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
if (!IsInit || !IsValid(AudioCaptureComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateVoiceCapture(DeltaTime);
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
// Unregister from the ConvaiSubsystem
|
||||
if (UGameInstance* GameInstance = GetWorld()->GetGameInstance())
|
||||
{
|
||||
if (UConvaiSubsystem* ConvaiSubsystem = GameInstance->GetSubsystem<UConvaiSubsystem>())
|
||||
{
|
||||
if (IsValid(ConvaiSubsystem))
|
||||
{
|
||||
ConvaiSubsystem->UnregisterPlayerComponent(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsRecording)
|
||||
FinishRecording();
|
||||
|
||||
if (IsStreaming)
|
||||
FinishTalking();
|
||||
|
||||
Super::EndPlay(EndPlayReason);
|
||||
}
|
||||
|
||||
bool UConvaiPlayerComponent::IsPixelStreamingEnabledAndAllowed()
|
||||
{
|
||||
return UsePixelStreamingMicInput && PixelStreamingAudioComponent.IsValid();
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::UpdateVoiceCapture(float DeltaTime)
|
||||
{
|
||||
if (IsRecording || IsStreaming) {
|
||||
RemainingTimeUntilNextUpdate -= DeltaTime;
|
||||
if (RemainingTimeUntilNextUpdate <= 0)
|
||||
{
|
||||
float ExpectedRecordingTime = DeltaTime > TIME_BETWEEN_VOICE_UPDATES_SECS ? DeltaTime : TIME_BETWEEN_VOICE_UPDATES_SECS;
|
||||
FAudioThread::RunCommandOnAudioThread([this, ExpectedRecordingTime]()
|
||||
{
|
||||
StopVoiceChunkCapture();
|
||||
StartVoiceChunkCapture(ExpectedRecordingTime);
|
||||
});
|
||||
RemainingTimeUntilNextUpdate = TIME_BETWEEN_VOICE_UPDATES_SECS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RemainingTimeUntilNextUpdate = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::StartVoiceChunkCapture(float ExpectedRecordingTime)
|
||||
{
|
||||
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("StartVoiceChunkCapture() in VoiceCaptureComp.cpp")));
|
||||
//CONVAI_LOG(LogTemp, Warning, TEXT("StartVoiceChunkCapture() in VoiceCaptureComp.cpp"));
|
||||
UAudioMixerBlueprintLibrary::StartRecordingOutput(this, ExpectedRecordingTime, Cast<USoundSubmix>(AudioCaptureComponent->SoundSubmix));
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::ReadRecordedBuffer(Audio::AlignedFloatBuffer& RecordedBuffer, float& OutNumChannels, float& OutSampleRate)
|
||||
{
|
||||
if (Audio::FMixerDevice* MixerDevice = GetAudioMixerDeviceFromWorldContext(this))
|
||||
{
|
||||
// call the thing here.
|
||||
RecordedBuffer = MixerDevice->StopRecording(Cast<USoundSubmix>(AudioCaptureComponent->SoundSubmix), OutNumChannels, OutSampleRate);
|
||||
|
||||
if (RecordedBuffer.Num() == 0)
|
||||
{
|
||||
//CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("ReadRecordedBuffer: No audio data. Did you call Start Recording Output?"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("ReadRecordedBuffer: Could not get MixerDevice"));
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::StartAudioCaptureComponent()
|
||||
{
|
||||
if (IsPixelStreamingEnabledAndAllowed())
|
||||
{
|
||||
PixelStreamingAudioComponent->Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioCaptureComponent->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::StopAudioCaptureComponent()
|
||||
{
|
||||
if (IsPixelStreamingEnabledAndAllowed())
|
||||
{
|
||||
PixelStreamingAudioComponent->Stop();
|
||||
}
|
||||
AudioCaptureComponent->Stop();
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::StopVoiceChunkCapture()
|
||||
{
|
||||
//USoundWave* SoundWaveMic = UAudioMixerBlueprintLibrary::StopRecordingOutput(this, EAudioRecordingExportType::SoundWave, "Convsound", "ConvSound", Cast<USoundSubmix>(AudioCaptureComponent->SoundSubmix));
|
||||
|
||||
float NumChannels;
|
||||
float SampleRate;
|
||||
Audio::AlignedFloatBuffer RecordedBuffer = Audio::AlignedFloatBuffer();
|
||||
|
||||
ReadRecordedBuffer(RecordedBuffer, NumChannels, SampleRate);
|
||||
//NumChannels = 2;
|
||||
//SampleRate = ConvaiConstants::VoiceCaptureSampleRate;
|
||||
|
||||
if (RecordedBuffer.Num() == 0)
|
||||
return;
|
||||
|
||||
Audio::TSampleBuffer<int16> Int16Buffer = Audio::TSampleBuffer<int16>(RecordedBuffer, NumChannels, SampleRate);
|
||||
TArray<int16> OutConverted;
|
||||
|
||||
if (NumChannels > 1 || SampleRate != ConvaiConstants::VoiceCaptureSampleRate)
|
||||
{
|
||||
UConvaiUtils::ResampleAudio(SampleRate, ConvaiConstants::VoiceCaptureSampleRate, NumChannels, true, (TArray<int16>)Int16Buffer.GetArrayView(), Int16Buffer.GetNumSamples(), OutConverted);
|
||||
}
|
||||
else
|
||||
{
|
||||
OutConverted = (TArray<int16>)Int16Buffer.GetArrayView();
|
||||
}
|
||||
//OutConverted = (TArray<int16>)Int16Buffer.GetArrayView();
|
||||
//OutConverted = TArray<int16>(Int16Buffer.GetData(), Int16Buffer.GetNumSamples());
|
||||
|
||||
//CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("Int16Buffer.GetNumSamples() %i, NumChannels %f, SampleRate %f"), Int16Buffer.GetNumSamples(), NumChannels, SampleRate);
|
||||
//CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("OutConverted.Num() %i"), OutConverted.Num());
|
||||
|
||||
if (IsRecording)
|
||||
{
|
||||
VoiceCaptureBuffer.Append((uint8*)OutConverted.GetData(), OutConverted.Num() * sizeof(int16));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ReplicateVoiceToNetwork)
|
||||
{
|
||||
if (IsStreaming)
|
||||
VoiceCaptureRingBuffer.Enqueue((uint8*)OutConverted.GetData(), OutConverted.Num() * sizeof(int16));
|
||||
|
||||
onDataReceived_Delegate.ExecuteIfBound();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Stream voice data
|
||||
AddPCMDataToSend(TArray<uint8>((uint8*)OutConverted.GetData(), OutConverted.Num() * sizeof(int16)), false, ConvaiConstants::VoiceCaptureSampleRate, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::StartRecording()
|
||||
{
|
||||
if (IsRecording)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("StartRecording: already recording!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsStreaming)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("StartRecording: already talking!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsInit)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("StartRecording: Initializing..."));
|
||||
if (!Init())
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("StartRecording: Could not initialize"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("Started Recording "));
|
||||
StartAudioCaptureComponent(); //Start the AudioCaptureComponent
|
||||
|
||||
// reset audio buffers
|
||||
StartVoiceChunkCapture();
|
||||
StopVoiceChunkCapture();
|
||||
VoiceCaptureBuffer.Empty(ConvaiConstants::VoiceCaptureBufferSize);
|
||||
|
||||
IsRecording = true;
|
||||
}
|
||||
|
||||
USoundWave* UConvaiPlayerComponent::FinishRecording()
|
||||
{
|
||||
if (!IsRecording)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("FinishRecording: did not start recording"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("Stopped Recording "));
|
||||
StopVoiceChunkCapture();
|
||||
|
||||
USoundWave* OutSoundWave = UConvaiUtils::PCMDataToSoundWav(VoiceCaptureBuffer, 1, ConvaiConstants::VoiceCaptureSampleRate);
|
||||
StopAudioCaptureComponent(); //stop the AudioCaptureComponent
|
||||
if (IsValid(OutSoundWave))
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("OutSoundWave->GetDuration(): %f seconds "), OutSoundWave->GetDuration());
|
||||
IsRecording = false;
|
||||
return OutSoundWave;
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::StartTalking(
|
||||
UConvaiChatbotComponent* ConvaiChatbotComponent,
|
||||
UConvaiEnvironment* Environment,
|
||||
bool GenerateActions,
|
||||
bool VoiceResponse,
|
||||
bool RunOnServer,
|
||||
bool StreamPlayerMic,
|
||||
bool UseServerAPI_Key)
|
||||
{
|
||||
if (IsStreaming)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("StartTalking: already talking!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsRecording)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("StartTalking: already recording!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsInit)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("StartTalking Initializing..."));
|
||||
if (!Init())
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("StartTalking Could not initialize"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsValid(ConvaiChatbotComponent))
|
||||
{
|
||||
if (RunOnServer)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("StartTalking: ConvaiChatbotComponent is not valid, will still stream voice chat to network"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("StartTalking: ConvaiChatbotComponent is not valid"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("Started Talking"));
|
||||
|
||||
StartAudioCaptureComponent(); //Start the AudioCaptureComponent
|
||||
|
||||
// reset audio buffers
|
||||
StartVoiceChunkCapture();
|
||||
StopVoiceChunkCapture();
|
||||
|
||||
IsStreaming = true;
|
||||
VoiceCaptureRingBuffer.Empty();
|
||||
|
||||
ReplicateVoiceToNetwork = RunOnServer;
|
||||
|
||||
TPair<FString, FString> AuthHeaderAndKey = UConvaiUtils::GetAuthHeaderAndKey();
|
||||
FString AuthKey = AuthHeaderAndKey.Value;
|
||||
FString AuthHeader = AuthHeaderAndKey.Key;
|
||||
|
||||
FString ClientAuthKey = UseServerAPI_Key ? FString("") : AuthKey;
|
||||
|
||||
// Ensure that the local version of the chatbot component has the ReplicateVoiceToNetwork set properly
|
||||
ConvaiChatbotComponent->ReplicateVoiceToNetwork = RunOnServer;
|
||||
|
||||
if (RunOnServer)
|
||||
{
|
||||
if (IsValid(Environment))
|
||||
StartTalkingServer(ConvaiChatbotComponent, true, Environment->Actions, Environment->Objects, Environment->Characters, Environment->MainCharacter, GenerateActions, VoiceResponse, StreamPlayerMic, UseServerAPI_Key, ClientAuthKey, AuthHeader);
|
||||
else
|
||||
StartTalkingServer(ConvaiChatbotComponent, false, TArray<FString>(), TArray<FConvaiObjectEntry>(), TArray<FConvaiObjectEntry>(), FConvaiObjectEntry(), GenerateActions, VoiceResponse, StreamPlayerMic, UseServerAPI_Key, ClientAuthKey, AuthHeader);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool UseOverrideAuthKey = false;
|
||||
ConvaiChatbotComponent->StartGetResponseStream(this, FString(""), Environment, GenerateActions, VoiceResponse, false, UseOverrideAuthKey, FString(""), FString(""), Token, SpeakerID);
|
||||
CurrentConvaiChatbotComponent = ConvaiChatbotComponent;
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::FinishTalking()
|
||||
{
|
||||
if (!IsStreaming)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("FinishTalking did not start talking"));
|
||||
return;
|
||||
}
|
||||
|
||||
StopVoiceChunkCapture();
|
||||
StopAudioCaptureComponent(); //stop the AudioCaptureComponent
|
||||
IsStreaming = false;
|
||||
|
||||
if (ReplicateVoiceToNetwork)
|
||||
{
|
||||
FinishTalkingServer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalidate the token by generating a new one
|
||||
GenerateNewToken();
|
||||
|
||||
if (IsValid(CurrentConvaiChatbotComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("FinishTalking calling FinishGetResponseStream"));
|
||||
CurrentConvaiChatbotComponent->FinishGetResponseStream(this);
|
||||
CurrentConvaiChatbotComponent = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("FinishTalking failed to call FinishGetResponseStream"));
|
||||
}
|
||||
}
|
||||
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("Finished Talking"));
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::StartTalkingServer_Implementation(
|
||||
class UConvaiChatbotComponent* ConvaiChatbotComponent,
|
||||
bool EnvironemntSent,
|
||||
const TArray<FString>& Actions,
|
||||
const TArray<FConvaiObjectEntry>& Objects,
|
||||
const TArray<FConvaiObjectEntry>& Characters,
|
||||
FConvaiObjectEntry MainCharacter,
|
||||
bool GenerateActions,
|
||||
bool VoiceResponse,
|
||||
bool StreamPlayerMic,
|
||||
bool UseServerAPI_Key,
|
||||
const FString& ClientAuthKey,
|
||||
const FString& AuthHeader)
|
||||
{
|
||||
// if "StreamPlayerMic" is true then "bShouldMuteGlobal" should be false, meaning we will play the player's audio on other clients
|
||||
bShouldMuteGlobal = !StreamPlayerMic;
|
||||
|
||||
// Make sure the ring buffer is empty
|
||||
VoiceCaptureRingBuffer.Empty();
|
||||
|
||||
// if "ConvaiChatbotComponent" is valid then run StartGetResponseStream function
|
||||
if (IsValid(ConvaiChatbotComponent))
|
||||
{
|
||||
UConvaiEnvironment* Environment = nullptr;
|
||||
if (EnvironemntSent)
|
||||
{
|
||||
if (IsValid(ConvaiChatbotComponent->Environment))
|
||||
Environment = ConvaiChatbotComponent->Environment;
|
||||
else
|
||||
{
|
||||
Environment = UConvaiEnvironment::CreateConvaiEnvironment();
|
||||
}
|
||||
|
||||
Environment->Actions = Actions;
|
||||
Environment->Characters = Characters;
|
||||
Environment->Objects = Objects;
|
||||
Environment->MainCharacter = MainCharacter;
|
||||
}
|
||||
bool UseOverrideAuthKey = !UseServerAPI_Key;
|
||||
ConvaiChatbotComponent->StartGetResponseStream(this, FString(""), Environment, GenerateActions, VoiceResponse, true, UseOverrideAuthKey, ClientAuthKey, AuthHeader, Token, SpeakerID);
|
||||
CurrentConvaiChatbotComponent = ConvaiChatbotComponent;
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::FinishTalkingServer_Implementation()
|
||||
{
|
||||
// Invalidate the token by generating a new one
|
||||
GenerateNewToken();
|
||||
|
||||
if (IsValid(CurrentConvaiChatbotComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("FinishTalking calling FinishGetResponseStream"));
|
||||
CurrentConvaiChatbotComponent->FinishGetResponseStream(this);
|
||||
CurrentConvaiChatbotComponent = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("FinishTalking failed to call FinishGetResponseStream"));
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::SendText(UConvaiChatbotComponent* ConvaiChatbotComponent, FString Text, UConvaiEnvironment* Environment, bool GenerateActions, bool VoiceResponse, bool RunOnServer, bool UseServerAPI_Key)
|
||||
{
|
||||
//FString Error;
|
||||
//if (GenerateActions && !UConvaiActions::ValidateEnvironment(Environment, Error))
|
||||
//{
|
||||
// CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SendText: %s"), *Error);
|
||||
// CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("SendText: Environment object seems to have issues -> setting GenerateActions to false"));
|
||||
// GenerateActions = false;
|
||||
//}
|
||||
|
||||
|
||||
if (!IsValid(ConvaiChatbotComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SendText: ConvaiChatbotComponent is not valid"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Text.Len() == 0)
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SendText: Text is empty"));
|
||||
return;
|
||||
}
|
||||
|
||||
ReplicateVoiceToNetwork = RunOnServer;
|
||||
|
||||
TPair<FString, FString> AuthHeaderAndKey = UConvaiUtils::GetAuthHeaderAndKey();
|
||||
FString AuthKey = AuthHeaderAndKey.Value;
|
||||
FString AuthHeader = AuthHeaderAndKey.Key;
|
||||
|
||||
FString ClientAuthKey = UseServerAPI_Key ? FString("") : AuthKey;
|
||||
|
||||
// Ensure that the local version of the chatbot component has the ReplicateVoiceToNetwork set properly
|
||||
ConvaiChatbotComponent->ReplicateVoiceToNetwork = RunOnServer;
|
||||
|
||||
if (RunOnServer)
|
||||
{
|
||||
if (IsValid(Environment))
|
||||
SendTextServer(ConvaiChatbotComponent, Text, true, Environment->Actions, Environment->Objects, Environment->Characters, Environment->MainCharacter, GenerateActions, VoiceResponse, UseServerAPI_Key, ClientAuthKey, AuthHeader);
|
||||
else
|
||||
SendTextServer(ConvaiChatbotComponent, Text, false, TArray<FString>(), TArray<FConvaiObjectEntry>(), TArray<FConvaiObjectEntry>(), FConvaiObjectEntry(), GenerateActions, VoiceResponse, UseServerAPI_Key, ClientAuthKey, AuthHeader);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool UseOverrideAuthKey = false;
|
||||
ConvaiChatbotComponent->StartGetResponseStream(this, Text, Environment, GenerateActions, VoiceResponse, false, UseOverrideAuthKey, FString(""), FString(""), Token, SpeakerID);
|
||||
|
||||
// Invalidate the token by generating a new one
|
||||
GenerateNewToken();
|
||||
|
||||
CurrentConvaiChatbotComponent = ConvaiChatbotComponent;
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::SendTextServer_Implementation(
|
||||
UConvaiChatbotComponent* ConvaiChatbotComponent,
|
||||
const FString& Text,
|
||||
bool EnvironemntSent,
|
||||
const TArray<FString>& Actions,
|
||||
const TArray<FConvaiObjectEntry>& Objects,
|
||||
const TArray<FConvaiObjectEntry>& Characters,
|
||||
FConvaiObjectEntry MainCharacter,
|
||||
bool GenerateActions,
|
||||
bool VoiceResponse,
|
||||
bool UseServerAPI_Key,
|
||||
const FString& ClientAuthKey,
|
||||
const FString& AuthHeader)
|
||||
{
|
||||
if (!IsValid(ConvaiChatbotComponent))
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("SendTextServer: ConvaiChatbotComponent is not valid"));
|
||||
return;
|
||||
}
|
||||
|
||||
UConvaiEnvironment* Environment;
|
||||
if (IsValid(ConvaiChatbotComponent->Environment))
|
||||
Environment = ConvaiChatbotComponent->Environment;
|
||||
else
|
||||
{
|
||||
Environment = UConvaiEnvironment::CreateConvaiEnvironment();
|
||||
}
|
||||
|
||||
Environment->Actions = Actions;
|
||||
Environment->Characters = Characters;
|
||||
Environment->Objects = Objects;
|
||||
Environment->MainCharacter = MainCharacter;
|
||||
|
||||
bool UseOverrideAuthKey = !UseServerAPI_Key;
|
||||
ConvaiChatbotComponent->StartGetResponseStream(this, Text, Environment, GenerateActions, VoiceResponse, true, UseOverrideAuthKey, ClientAuthKey, AuthHeader, Token, SpeakerID);
|
||||
|
||||
// Invalidate the token by generating a new one
|
||||
GenerateNewToken();
|
||||
|
||||
CurrentConvaiChatbotComponent = ConvaiChatbotComponent;
|
||||
}
|
||||
|
||||
bool UConvaiPlayerComponent::ShouldMuteLocal()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UConvaiPlayerComponent::ShouldMuteGlobal()
|
||||
{
|
||||
return bShouldMuteGlobal;
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::OnServerAudioReceived(uint8* VoiceData, uint32 VoiceDataSize, bool ContainsHeaderData, uint32 SampleRate, uint32 NumChannels)
|
||||
{
|
||||
//if (IsRecording)
|
||||
// VoiceCaptureBuffer.Append(VoiceData, VoiceDataSize);
|
||||
|
||||
//if (IsStreaming)
|
||||
// VoiceCaptureRingBuffer.Enqueue(VoiceData, VoiceDataSize);
|
||||
|
||||
//CONVAI_LOG(ConvaiPlayerLog, Log, TEXT("OnServerAudioReceived received %d bytes"), VoiceDataSize);
|
||||
//onDataReceived_Delegate.ExecuteIfBound();
|
||||
|
||||
// Simply enque the data into the ring buffer
|
||||
VoiceCaptureRingBuffer.Enqueue(VoiceData, VoiceDataSize);
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
if (IsValid(AudioCaptureComponent))
|
||||
{
|
||||
AudioCaptureComponent->AttachToComponent(this, FAttachmentTransformRules::KeepRelativeTransform);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Error, TEXT("Could not attach AudioCaptureComponent"));
|
||||
}
|
||||
|
||||
if (!IsInit)
|
||||
{
|
||||
if (!Init())
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("Could not initialize Audio Decoder"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Register with the ConvaiSubsystem
|
||||
if (UGameInstance* GameInstance = GetWorld()->GetGameInstance())
|
||||
{
|
||||
if (UConvaiSubsystem* ConvaiSubsystem = GameInstance->GetSubsystem<UConvaiSubsystem>())
|
||||
{
|
||||
if (IsValid(ConvaiSubsystem))
|
||||
{
|
||||
ConvaiSubsystem->RegisterPlayerComponent(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiPlayerLog, Warning, TEXT("BeginPlay: ConvaiSubsystem is not valid"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UConvaiPlayerComponent::ConsumeStreamingBuffer(TArray<uint8>& Buffer)
|
||||
{
|
||||
int Datalength = VoiceCaptureRingBuffer.RingDataUsage();
|
||||
if (Datalength <= 0)
|
||||
return false;
|
||||
|
||||
Buffer.SetNumUninitialized(Datalength, false);
|
||||
VoiceCaptureRingBuffer.Dequeue(Buffer.GetData(), Datalength);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::SetIsStreamingServer_Implementation(bool value)
|
||||
{
|
||||
IsStreaming = value;
|
||||
if (IsStreaming == false)
|
||||
onDataReceived_Delegate.ExecuteIfBound(); // In case a consumer was waiting on this delegate
|
||||
}
|
||||
|
||||
void UConvaiPlayerComponent::BeginDestroy()
|
||||
{
|
||||
// Fallback unregistration in case EndPlay wasn't called
|
||||
if (UGameInstance* GameInstance = GetWorld() ? GetWorld()->GetGameInstance() : nullptr)
|
||||
{
|
||||
if (UConvaiSubsystem* ConvaiSubsystem = GameInstance->GetSubsystem<UConvaiSubsystem>())
|
||||
{
|
||||
if (IsValid(ConvaiSubsystem))
|
||||
{
|
||||
ConvaiSubsystem->UnregisterPlayerComponent(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Super::BeginDestroy();
|
||||
}
|
||||
232
ConvAI/Convai/Source/Convai/Private/ConvaiSpeechToTextProxy.cpp
Normal file
232
ConvAI/Convai/Source/Convai/Private/ConvaiSpeechToTextProxy.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
|
||||
#include "ConvaiSpeechToTextProxy.h"
|
||||
#include "ConvaiUtils.h"
|
||||
#include "Sound/SoundWave.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "AudioDecompress.h"
|
||||
#include "Engine.h"
|
||||
#include "JsonObjectConverter.h"
|
||||
#include "../Convai.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
static FString TextToSpeechURL() { return UConvaiURL::GetFullURL(TEXT("tts"), false); }
|
||||
static FString SpeechToTextURL() { return UConvaiURL::GetFullURL(TEXT("stt/"), false); }
|
||||
}
|
||||
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiS2THttpLog);
|
||||
|
||||
UConvaiSpeechToTextProxy* UConvaiSpeechToTextProxy::CreateSpeech2TextFromFileNameQueryProxy(UObject* WorldContextObject, FString filename)
|
||||
{
|
||||
UConvaiSpeechToTextProxy* Proxy = NewObject<UConvaiSpeechToTextProxy>();
|
||||
Proxy->WorldPtr = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
|
||||
Proxy->URL = SpeechToTextURL();
|
||||
|
||||
if (!FPaths::FileExists(filename))
|
||||
{
|
||||
// check if the file is relative to the save/BouncedWavFiles directory
|
||||
FString SaveDir = FPaths::ConvertRelativePathToFull(FPaths::ProjectSavedDir());
|
||||
filename = FPaths::Combine(SaveDir, FString("BouncedWavFiles"), filename);
|
||||
if (!FPaths::FileExists(filename))
|
||||
{
|
||||
//if (!FPaths::GameAgnosticSavedDir)
|
||||
CONVAI_LOG(ConvaiS2THttpLog, Warning, TEXT("File does not exist!, %s"), *filename);
|
||||
Proxy->failed();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the file into a byte array
|
||||
FFileHelper::LoadFileToArray(Proxy->Payload, *filename, 0);
|
||||
|
||||
Proxy->bStereo = true;
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
UConvaiSpeechToTextProxy* UConvaiSpeechToTextProxy::CreateSpeech2TextFromSoundWaveQueryProxy(UObject* WorldContextObject, USoundWave* SoundWave)
|
||||
{
|
||||
UConvaiSpeechToTextProxy* Proxy = NewObject<UConvaiSpeechToTextProxy>();
|
||||
Proxy->WorldPtr = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
|
||||
Proxy->URL = SpeechToTextURL();
|
||||
|
||||
if (SoundWave == nullptr)
|
||||
{
|
||||
CONVAI_LOG(ConvaiS2THttpLog, Warning, TEXT("Sound wave is invalid!"));
|
||||
Proxy->failed();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
//Proxy->Payload.SetNum(SoundWave->TotalSamples * 2);
|
||||
uint8* PCMData = nullptr;
|
||||
TArray<uint8> RawPCMData;
|
||||
int32 OutSampleRate = -1;
|
||||
int32 outNumChannels = -1;
|
||||
//int32 numBytes = SoundWave->GeneratePCMData(PCMData, SoundWave->TotalSamples);
|
||||
|
||||
if (SoundWave->RawPCMData == nullptr || SoundWave->RawPCMDataSize <= 0) {
|
||||
CONVAI_LOG(LogTemp, Display, TEXT("SoundWave PCM Data is compressed. Starting Decompressing....."));
|
||||
RawPCMData = UConvaiUtils::ExtractPCMDataFromSoundWave(SoundWave, OutSampleRate, outNumChannels);
|
||||
|
||||
if (RawPCMData.Num() > 0) {
|
||||
CONVAI_LOG(LogTemp, Display, TEXT("SoundWave PCM Data decompression successfully done....."));
|
||||
}
|
||||
else {
|
||||
CONVAI_LOG(LogTemp,Warning,TEXT("SoundWave couldn't be decompressed successuflly !!!"));
|
||||
}
|
||||
//CONVAI_LOG(ConvaiS2THttpLog, Warning, TEXT("RawPCMData is invalid!"));
|
||||
}
|
||||
else {
|
||||
RawPCMData = TArray<uint8>(SoundWave->RawPCMData, SoundWave->RawPCMDataSize);
|
||||
}
|
||||
|
||||
//TArray<uint8> AudioBuffer(SoundWave->RawPCMData, SoundWave->RawPCMDataSize);
|
||||
|
||||
SerializeWaveFile(Proxy->Payload, RawPCMData.GetData(), RawPCMData.Num(), SoundWave->NumChannels, SoundWave->GetSampleRateForCurrentPlatform());
|
||||
|
||||
//CONVAI_LOG(ConvaiS2THttpLog, Warning, TEXT("Sound wave sample rate: %f"), SoundWave->GetSampleRateForCurrentPlatform());
|
||||
Proxy->bStereo = SoundWave->NumChannels>1? true : false;
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
UConvaiSpeechToTextProxy* UConvaiSpeechToTextProxy::CreateSpeech2TextFromArrayQueryProxy(UObject* WorldContextObject, TArray<uint8> Payload)
|
||||
{
|
||||
UConvaiSpeechToTextProxy* Proxy = NewObject<UConvaiSpeechToTextProxy>();
|
||||
Proxy->WorldPtr = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
|
||||
Proxy->URL = SpeechToTextURL();
|
||||
Proxy->Payload = Payload;
|
||||
Proxy->bStereo = true;
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
|
||||
void UConvaiSpeechToTextProxy::Activate()
|
||||
{
|
||||
UWorld* World = WorldPtr.Get();
|
||||
|
||||
if (!World)
|
||||
{
|
||||
CONVAI_LOG(ConvaiS2THttpLog, Warning, TEXT("Could not get a pointer to world!"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
FHttpModule* Http = &FHttpModule::Get();
|
||||
if (!Http)
|
||||
{
|
||||
CONVAI_LOG(ConvaiS2THttpLog, Warning, TEXT("Could not get a pointer to http module!"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Payload.Num() <= 44)
|
||||
{
|
||||
CONVAI_LOG(ConvaiS2THttpLog, Warning, TEXT("Payload size is too small, %d bytes!"), Payload.Num());
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
TPair<FString, FString> AuthHeaderAndKey = UConvaiUtils::GetAuthHeaderAndKey();
|
||||
FString AuthKey = AuthHeaderAndKey.Value;
|
||||
FString AuthHeader = AuthHeaderAndKey.Key;
|
||||
|
||||
// Form Validation
|
||||
if (!UConvaiFormValidation::ValidateAuthKey(AuthKey) || !UConvaiFormValidation::ValidateInputVoice(Payload))
|
||||
{
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<uint8> monoWavBytes;
|
||||
if (bStereo)
|
||||
{
|
||||
// Change the wav file from 2 channels to 1 channel
|
||||
UConvaiUtils::StereoToMono(Payload, monoWavBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
monoWavBytes = Payload;
|
||||
}
|
||||
|
||||
// Create the request
|
||||
FHttpRequestRef Request = Http->CreateRequest();
|
||||
Request->OnProcessRequestComplete().BindUObject(this, &UConvaiSpeechToTextProxy::onHttpRequestComplete);
|
||||
|
||||
// Set request fields
|
||||
Request->SetURL(URL);
|
||||
Request->SetVerb("POST");
|
||||
Request->SetHeader(TEXT("User-Agent"), TEXT("X-UnrealEngine-Agent"));
|
||||
|
||||
Request->SetHeader("Content-Type", "multipart/form-data; boundary=blahblahsomeboundary");
|
||||
Request->SetHeader(AuthHeader, AuthKey);
|
||||
|
||||
// prepare request content data
|
||||
//FString a = "\r\n--blahblahsomeboundary\r\n";
|
||||
//FString b = "Content-Disposition: form-data; name=\"Request->SetHeader(AuthHeader, AuthKey);\"\r\n\r\n";
|
||||
// Request->SetHeader(AuthHeader, AuthKey);
|
||||
FString c = "\r\n--blahblahsomeboundary\r\n";
|
||||
FString d = "Content-Disposition: form-data; name=\"file\"; filename=\"out.wav\"\r\n\r\n";
|
||||
|
||||
// UpFileRawData
|
||||
FString e = "\r\n--blahblahsomeboundary--\r\n";
|
||||
|
||||
TArray<uint8> data;
|
||||
//data.Append((uint8*)TCHAR_TO_UTF8(*a), a.Len());
|
||||
//data.Append((uint8*)TCHAR_TO_UTF8(*b), b.Len());
|
||||
//data.Append((uint8*)TCHAR_TO_UTF8(*Request->SetHeader(AuthHeader, AuthKey);), Request->SetHeader(AuthHeader, AuthKey);.Len());
|
||||
data.Append((uint8*)TCHAR_TO_UTF8(*c), c.Len());
|
||||
data.Append((uint8*)TCHAR_TO_UTF8(*d), d.Len());
|
||||
data.Append(monoWavBytes);
|
||||
data.Append((uint8*)TCHAR_TO_UTF8(*e), e.Len());
|
||||
|
||||
|
||||
Request->SetContent(data);
|
||||
|
||||
// Run the request
|
||||
if (!Request->ProcessRequest()) failed();
|
||||
}
|
||||
|
||||
|
||||
void UConvaiSpeechToTextProxy::onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful)
|
||||
{
|
||||
if (!bWasSuccessful || ResponsePtr->GetResponseCode() < 200 || ResponsePtr->GetResponseCode() > 299)
|
||||
{
|
||||
CONVAI_LOG(ConvaiS2THttpLog, Warning, TEXT("HTTP request failed with code %d"), ResponsePtr->GetResponseCode());
|
||||
CONVAI_LOG(ConvaiS2THttpLog, Warning, TEXT("Response:%s"), *ResponsePtr->GetContentAsString());
|
||||
|
||||
this->Response = ResponsePtr->GetContentAsString();
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
this->Response = ResponsePtr->GetContentAsString();
|
||||
// Clean the string
|
||||
this->Response = this->Response.LeftChop(3);
|
||||
this->Response = this->Response.RightChop(12);
|
||||
success();
|
||||
}
|
||||
|
||||
|
||||
void UConvaiSpeechToTextProxy::failed()
|
||||
{
|
||||
OnFailure.Broadcast(Response);
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
void UConvaiSpeechToTextProxy::success()
|
||||
{
|
||||
OnSuccess.Broadcast(Response);
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
void UConvaiSpeechToTextProxy::finish()
|
||||
{
|
||||
}
|
||||
|
||||
481
ConvAI/Convai/Source/Convai/Private/ConvaiSubsystem.cpp
Normal file
481
ConvAI/Convai/Source/Convai/Private/ConvaiSubsystem.cpp
Normal file
@@ -0,0 +1,481 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#include "ConvaiSubsystem.h"
|
||||
#include "ConvaiAndroid.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "Async/Async.h"
|
||||
#include "../Convai.h"
|
||||
#include "ConvaiUtils.h"
|
||||
#include "HAL/PlatformProcess.h"
|
||||
#include "ConvaiChatbotComponent.h"
|
||||
#include "ConvaiPlayerComponent.h"
|
||||
|
||||
THIRD_PARTY_INCLUDES_START
|
||||
// grpc includes
|
||||
#include <grpc++/grpc++.h>
|
||||
#include <chrono>
|
||||
THIRD_PARTY_INCLUDES_END
|
||||
|
||||
|
||||
using grpc::Channel;
|
||||
using grpc::ClientAsyncResponseReader;
|
||||
using grpc::ClientContext;
|
||||
using grpc::CompletionQueue;
|
||||
using grpc::Status;
|
||||
using service::ConvaiService;
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiSubsystemLog);
|
||||
|
||||
using grpc::SslCredentialsOptions;
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include <wincrypt.h>
|
||||
namespace
|
||||
{
|
||||
|
||||
std::string utf8Encode(const std::wstring& wstr)
|
||||
{
|
||||
if (wstr.empty())
|
||||
return std::string();
|
||||
|
||||
int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(),
|
||||
NULL, 0, NULL, NULL);
|
||||
std::string strTo(sizeNeeded, 0);
|
||||
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(),
|
||||
&strTo[0], sizeNeeded, NULL, NULL);
|
||||
return strTo;
|
||||
}
|
||||
|
||||
|
||||
SslCredentialsOptions getSslOptions() {
|
||||
SslCredentialsOptions result;
|
||||
|
||||
std::string pem_root_certs = R"(-----BEGIN CERTIFICATE-----
|
||||
MIIFjDCCA3SgAwIBAgINAgCOsgIzNmWLZM3bmzANBgkqhkiG9w0BAQsFADBHMQsw
|
||||
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
|
||||
MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzMDAwMDQyWhcNMjcwOTMwMDAw
|
||||
MDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
|
||||
Y2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFENDCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||
ggEPADCCAQoCggEBAKvAqqPCE27l0w9zC8dTPIE89bA+xTmDaG7y7VfQ4c+mOWhl
|
||||
UebUQpK0yv2r678RJExK0HWDjeq+nLIHN1Em5j6rARZixmyRSjhIR0KOQPGBMUld
|
||||
saztIIJ7O0g/82qj/vGDl//3t4tTqxiRhLQnTLXJdeB+2DhkdU6IIgx6wN7E5NcU
|
||||
H3Rcsejcqj8p5Sj19vBm6i1FhqLGymhMFroWVUGO3xtIH91dsgy4eFKcfKVLWK3o
|
||||
2190Q0Lm/SiKmLbRJ5Au4y1euFJm2JM9eB84Fkqa3ivrXWUeVtye0CQdKvsY2Fka
|
||||
zvxtxvusLJzLWYHk55zcRAacDA2SeEtBbQfD1qsCAwEAAaOCAXYwggFyMA4GA1Ud
|
||||
DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0T
|
||||
AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUJeIYDrJXkZQq5dRdhpCD3lOzuJIwHwYD
|
||||
VR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4waAYIKwYBBQUHAQEEXDBaMCYG
|
||||
CCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHNyMTAwBggrBgEFBQcw
|
||||
AoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ3RzcjEuZGVyMDQGA1UdHwQt
|
||||
MCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ3RzcjEvZ3RzcjEuY3JsME0G
|
||||
A1UdIARGMEQwCAYGZ4EMAQIBMDgGCisGAQQB1nkCBQMwKjAoBggrBgEFBQcCARYc
|
||||
aHR0cHM6Ly9wa2kuZ29vZy9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAgEA
|
||||
IVToy24jwXUr0rAPc924vuSVbKQuYw3nLflLfLh5AYWEeVl/Du18QAWUMdcJ6o/q
|
||||
FZbhXkBH0PNcw97thaf2BeoDYY9Ck/b+UGluhx06zd4EBf7H9P84nnrwpR+4GBDZ
|
||||
K+Xh3I0tqJy2rgOqNDflr5IMQ8ZTWA3yltakzSBKZ6XpF0PpqyCRvp/NCGv2KX2T
|
||||
uPCJvscp1/m2pVTtyBjYPRQ+QuCQGAJKjtN7R5DFrfTqMWvYgVlpCJBkwlu7+7KY
|
||||
3cTIfzE7cmALskMKNLuDz+RzCcsYTsVaU7Vp3xL60OYhqFkuAOOxDZ6pHOj9+OJm
|
||||
YgPmOT4X3+7L51fXJyRH9KfLRP6nT31D5nmsGAOgZ26/8T9hsBW1uo9ju5fZLZXV
|
||||
VS5H0HyIBMEKyGMIPhFWrlt/hFS28N1zaKI0ZBGD3gYgDLbiDT9fGXstpk+Fmc4o
|
||||
lVlWPzXe81vdoEnFbr5M272HdgJWo+WhT9BYM0Ji+wdVmnRffXgloEoluTNcWzc4
|
||||
1dFpgJu8fF3LG0gl2ibSYiCi9a6hvU0TppjJyIWXhkJTcMJlPrWx1VytEUGrX2l0
|
||||
JDwRjW/656r0KVB02xHRKvm2ZKI03TglLIpmVCK3kBKkKNpBNkFt8rhafcCKOb9J
|
||||
x/9tpNFlQTl7B39rJlJWkR17QnZqVptFePFORoZmFzM=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
|
||||
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
|
||||
MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
|
||||
MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
|
||||
Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
|
||||
A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
|
||||
27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
|
||||
Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
|
||||
TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
|
||||
qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
|
||||
szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
|
||||
Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
|
||||
MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
|
||||
wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
|
||||
aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
|
||||
VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
|
||||
AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
|
||||
FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
|
||||
C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
|
||||
QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
|
||||
h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
|
||||
7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
|
||||
ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
|
||||
MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
|
||||
Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
|
||||
6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
|
||||
0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
|
||||
2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
|
||||
bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
|
||||
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
|
||||
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
|
||||
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
|
||||
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
|
||||
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
|
||||
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
|
||||
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
|
||||
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
|
||||
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
|
||||
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
|
||||
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
|
||||
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
|
||||
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
|
||||
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
|
||||
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
|
||||
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
|
||||
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
|
||||
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
|
||||
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
|
||||
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
|
||||
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
|
||||
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
|
||||
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
|
||||
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
|
||||
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
|
||||
-----END CERTIFICATE-----
|
||||
)";
|
||||
|
||||
result.pem_root_certs = pem_root_certs;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
SslCredentialsOptions getSslOptionsystem()
|
||||
{
|
||||
// Start with hardcoded certificates
|
||||
SslCredentialsOptions result = getSslOptions();
|
||||
|
||||
// Open root certificate store.
|
||||
HANDLE hRootCertStore = CertOpenSystemStoreW(NULL, L"ROOT");
|
||||
if (!hRootCertStore)
|
||||
return result;
|
||||
|
||||
// Get all root certificates and append them.
|
||||
PCCERT_CONTEXT pCert = NULL;
|
||||
while ((pCert = CertEnumCertificatesInStore(hRootCertStore, pCert)) != NULL)
|
||||
{
|
||||
// Append this certificate in PEM formatted data.
|
||||
DWORD size = 0;
|
||||
CryptBinaryToStringW(pCert->pbCertEncoded, pCert->cbCertEncoded,
|
||||
CRYPT_STRING_BASE64HEADER, NULL, &size);
|
||||
std::vector<WCHAR> pem(size);
|
||||
CryptBinaryToStringW(pCert->pbCertEncoded, pCert->cbCertEncoded,
|
||||
CRYPT_STRING_BASE64HEADER, pem.data(), &size);
|
||||
|
||||
result.pem_root_certs += utf8Encode(pem.data());
|
||||
}
|
||||
|
||||
CertCloseStore(hRootCertStore, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
const char* grpc_connectivity_state_str[] =
|
||||
{
|
||||
"GRPC_CHANNEL_IDLE",
|
||||
"GRPC_CHANNEL_CONNECTING",
|
||||
"GRPC_CHANNEL_READY",
|
||||
"GRPC_CHANNEL_TRANSIENT_FAILURE",
|
||||
"GRPC_CHANNEL_SHUTDOWN"
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
uint32 FgRPCClient::Run()
|
||||
{
|
||||
void* got_tag;
|
||||
bool ok = false;
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("Start Run"));
|
||||
|
||||
// Block until the next result is available in the completion queue "cq
|
||||
while (bIsRunning && cq_.Next(&got_tag, &ok)) {
|
||||
if (got_tag)
|
||||
{
|
||||
FgRPC_Delegate* gRPC_Delegate = static_cast<FgRPC_Delegate*>(got_tag);
|
||||
|
||||
if (bIsRunning)
|
||||
{
|
||||
gRPC_Delegate->ExecuteIfBound(ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("Could not run gRPC delegate due to thread closing down"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("Bad got_tag"));
|
||||
}
|
||||
|
||||
}
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("End Run"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FgRPCClient::StartStub()
|
||||
{
|
||||
OnStateChangeDelegate = FgRPC_Delegate::CreateRaw(this, &FgRPCClient::OnStateChange);
|
||||
CreateChannel();
|
||||
|
||||
bIsRunning = true;
|
||||
Thread.Reset(FRunnableThread::Create(this, TEXT("gRPC_Stub")));
|
||||
}
|
||||
|
||||
void FgRPCClient::CreateChannel()
|
||||
{
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("gRPC Creating Channel..."));
|
||||
grpc::ChannelArguments args;
|
||||
args.SetMaxReceiveMessageSize(2147483647);
|
||||
|
||||
args.SetInt(GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS, INT_MAX);
|
||||
|
||||
args.SetInt(GRPC_ARG_KEEPALIVE_TIME_MS, 30000); // Send keepalive ping every 30 seconds
|
||||
args.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 60000); // Wait 5 seconds for keepalive response
|
||||
args.SetInt(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1); // Allow keepalive even when no active calls
|
||||
|
||||
Channel = grpc::CreateCustomChannel(Target, Creds, args);
|
||||
|
||||
//Channel->NotifyOnStateChange(grpc_connectivity_state::GRPC_CHANNEL_CONNECTING, std::chrono::system_clock::time_point().max(), &cq_, (void*)&OnStateChangeDelegate);
|
||||
}
|
||||
|
||||
void FgRPCClient::OnStateChange(bool ok)
|
||||
{
|
||||
grpc_connectivity_state state;
|
||||
|
||||
if (Channel)
|
||||
state = Channel->GetState(true);
|
||||
else
|
||||
state = grpc_connectivity_state::GRPC_CHANNEL_SHUTDOWN;
|
||||
|
||||
|
||||
if (state == grpc_connectivity_state::GRPC_CHANNEL_SHUTDOWN)
|
||||
{
|
||||
if (!bIsRunning)
|
||||
{
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Warning, TEXT("gRPC channel state changed to %s... Attempting to reconnect"), *FString(grpc_connectivity_state_str[state]));
|
||||
CreateChannel();
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("gRPC channel state changed to %s... Closing"), *FString(grpc_connectivity_state_str[state]));
|
||||
}
|
||||
//Channel->NotifyOnStateChange(state, std::chrono::system_clock::time_point().max(), &cq_, (void*)&OnStateChangeDelegate);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("gRPC channel state changed to %s"), *FString(grpc_connectivity_state_str[state]));
|
||||
Channel->NotifyOnStateChange(state, std::chrono::system_clock::time_point().max(), &cq_, (void*)&OnStateChangeDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
void FgRPCClient::Exit()
|
||||
{
|
||||
if (!bIsRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bIsRunning = false;
|
||||
{
|
||||
FScopeLock Lock(&CriticalSection);
|
||||
cq_.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
FgRPCClient::FgRPCClient(std::string InTarget,
|
||||
const std::shared_ptr<grpc::ChannelCredentials>& InCreds)
|
||||
: bIsRunning(false),
|
||||
Creds(InCreds),
|
||||
Target(InTarget)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<ConvaiService::Stub> FgRPCClient::GetNewStub()
|
||||
{
|
||||
FScopeLock Lock(&CriticalSection);
|
||||
|
||||
// # TODO (Mohamed): Handling Mic permissions requires refactoring and a unified pipeline for all platforms
|
||||
// Delaying asking for permission for MacOS due to a crash
|
||||
#ifdef __APPLE__
|
||||
GetAppleMicPermission();
|
||||
#endif
|
||||
|
||||
grpc_connectivity_state state = Channel->GetState(false);
|
||||
|
||||
if (state != grpc_connectivity_state::GRPC_CHANNEL_READY)
|
||||
{
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Warning, TEXT("gRPC channel not ready yet.. Current State: %s"), *FString(grpc_connectivity_state_str[state]));
|
||||
}
|
||||
return ConvaiService::NewStub(Channel);
|
||||
}
|
||||
|
||||
CompletionQueue* FgRPCClient::GetCompletionQueue()
|
||||
{
|
||||
return &cq_;
|
||||
}
|
||||
|
||||
UConvaiSubsystem::UConvaiSubsystem()
|
||||
: UGameInstanceSubsystem()
|
||||
{
|
||||
}
|
||||
|
||||
void UConvaiSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
|
||||
//AsyncTask(ENamedThreads::GameThread, [WeakThis = MakeWeakObjectPtr(this)]
|
||||
// {
|
||||
// Check command line for insecure connection flag first, then fall back to settings
|
||||
bool AllowInsecureConnection = false;
|
||||
FString InsecureConnectionStr = UCommandLineUtils::GetCommandLineFlagValueAsString(TEXT("ConvaiAllowInsecure"), TEXT(""));
|
||||
if (!InsecureConnectionStr.IsEmpty())
|
||||
{
|
||||
// Convert string to bool
|
||||
AllowInsecureConnection = InsecureConnectionStr.ToBool();
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("Using insecure connection setting from command line: %s"),
|
||||
AllowInsecureConnection ? TEXT("true") : TEXT("false"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use setting from ConvaiSettings
|
||||
AllowInsecureConnection = Convai::Get().GetConvaiSettings()->AllowInsecureConnection;
|
||||
}
|
||||
|
||||
std::shared_ptr<grpc::ChannelCredentials> channel_creds;
|
||||
#if PLATFORM_WINDOWS
|
||||
if (AllowInsecureConnection)
|
||||
channel_creds = grpc::InsecureChannelCredentials();
|
||||
else
|
||||
{
|
||||
// Check if we should use system certificates (can be overridden by command line)
|
||||
bool UseSystemCerts = Convai::Get().GetConvaiSettings()->UseSystemCertificates;
|
||||
FString UseSystemCertsStr = UCommandLineUtils::GetCommandLineFlagValueAsString(TEXT("ConvaiUseSystemCerts"), TEXT(""));
|
||||
if (!UseSystemCertsStr.IsEmpty())
|
||||
{
|
||||
UseSystemCerts = UseSystemCertsStr.ToBool();
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("Using system certificates setting from command line: %s"),
|
||||
UseSystemCerts ? TEXT("true") : TEXT("false"));
|
||||
}
|
||||
|
||||
if (UseSystemCerts)
|
||||
{
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("Using both hardcoded and system SSL certificates"));
|
||||
channel_creds = grpc::SslCredentials(getSslOptionsystem());
|
||||
}
|
||||
else
|
||||
{
|
||||
channel_creds = grpc::SslCredentials(getSslOptions());
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (AllowInsecureConnection)
|
||||
channel_creds = grpc::InsecureChannelCredentials();
|
||||
else
|
||||
channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
|
||||
#endif
|
||||
|
||||
// Get URL from command line first, then settings, then default
|
||||
FString URL = Convai::Get().GetConvaiSettings()->CustomURL;
|
||||
URL.TrimEndInline();
|
||||
URL.TrimStartInline();
|
||||
|
||||
// Check for command line parameter
|
||||
FString CommandLineURL = UCommandLineUtils::GetCommandLineFlagValueAsString(TEXT("ConvaiStreamURL"), TEXT(""));
|
||||
if (!CommandLineURL.IsEmpty())
|
||||
{
|
||||
URL = CommandLineURL;
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("Using stream URL from command line: %s"), *URL);
|
||||
}
|
||||
// If settings URL is empty, use default
|
||||
else if (URL.IsEmpty())
|
||||
{
|
||||
URL = "stream.convai.com";
|
||||
}
|
||||
|
||||
gRPC_Runnable = MakeShareable(new FgRPCClient(TCHAR_TO_UTF8(*URL), channel_creds));
|
||||
|
||||
//gRPC_Runnable = MakeShareable(new FgRPCClient(std::string("0.tcp.us-cal-1.ngrok.io:13976"), channel_creds));
|
||||
|
||||
gRPC_Runnable->StartStub();
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("UConvaiSubsystem Started"));
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
GetAndroidMicPermission();
|
||||
#endif
|
||||
//});
|
||||
}
|
||||
|
||||
void UConvaiSubsystem::Deinitialize()
|
||||
{
|
||||
gRPC_Runnable->Exit();
|
||||
Super::Deinitialize();
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Log, TEXT("UConvaiSubsystem Stopped"));
|
||||
}
|
||||
|
||||
void UConvaiSubsystem::GetAndroidMicPermission()
|
||||
{
|
||||
if (!UConvaiAndroid::ConvaiAndroidHasMicrophonePermission())
|
||||
UConvaiAndroid::ConvaiAndroidAskMicrophonePermission();
|
||||
}
|
||||
|
||||
void UConvaiSubsystem::RegisterChatbotComponent(UConvaiChatbotComponent* ChatbotComponent)
|
||||
{
|
||||
if (IsValid(ChatbotComponent) && !RegisteredChatbotComponents.Contains(ChatbotComponent))
|
||||
{
|
||||
RegisteredChatbotComponents.Add(ChatbotComponent);
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiSubsystem::UnregisterChatbotComponent(UConvaiChatbotComponent* ChatbotComponent)
|
||||
{
|
||||
if (RegisteredChatbotComponents.Contains(ChatbotComponent))
|
||||
{
|
||||
RegisteredChatbotComponents.Remove(ChatbotComponent);
|
||||
}
|
||||
}
|
||||
|
||||
TArray<UConvaiChatbotComponent*> UConvaiSubsystem::GetAllChatbotComponents() const
|
||||
{
|
||||
return RegisteredChatbotComponents;
|
||||
}
|
||||
|
||||
void UConvaiSubsystem::RegisterPlayerComponent(UConvaiPlayerComponent* PlayerComponent)
|
||||
{
|
||||
if (IsValid(PlayerComponent) && !RegisteredPlayerComponents.Contains(PlayerComponent))
|
||||
{
|
||||
RegisteredPlayerComponents.Add(PlayerComponent);
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Verbose, TEXT("Registered player component: %s"), *PlayerComponent->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiSubsystem::UnregisterPlayerComponent(UConvaiPlayerComponent* PlayerComponent)
|
||||
{
|
||||
if (RegisteredPlayerComponents.Contains(PlayerComponent))
|
||||
{
|
||||
RegisteredPlayerComponents.Remove(PlayerComponent);
|
||||
CONVAI_LOG(ConvaiSubsystemLog, Verbose, TEXT("Unregistered player component: %s"), *PlayerComponent->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
TArray<UConvaiPlayerComponent*> UConvaiSubsystem::GetAllPlayerComponents() const
|
||||
{
|
||||
return RegisteredPlayerComponents;
|
||||
}
|
||||
155
ConvAI/Convai/Source/Convai/Private/ConvaiTextToSpeechProxy.cpp
Normal file
155
ConvAI/Convai/Source/Convai/Private/ConvaiTextToSpeechProxy.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#include "ConvaiTextToSpeechProxy.h"
|
||||
#include "ConvaiUtils.h"
|
||||
#include "Containers/UnrealString.h"
|
||||
#include "Sound/SoundWave.h"
|
||||
#include "Engine.h"
|
||||
#include "JsonObjectConverter.h"
|
||||
#include "RestAPI/ConvaiURL.h"
|
||||
|
||||
#include "../Convai.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiT2SHttpLog);
|
||||
|
||||
|
||||
namespace {
|
||||
const char* TTS_Voice_Type_str[] = {
|
||||
"MALE",
|
||||
"FEMALE",
|
||||
"WUKMale 1",
|
||||
"WUKFemale 1",
|
||||
"SUKMale 1",
|
||||
"WAFemale 1",
|
||||
"WAMale 1",
|
||||
"SIFemale 1",
|
||||
"SIMale 1",
|
||||
"SUFemale 1",
|
||||
"SUMale 1",
|
||||
"WUFemale 1",
|
||||
"WUMale 1",
|
||||
"Trixie",
|
||||
"Twilight Sparkle",
|
||||
"Celestia",
|
||||
"Spike",
|
||||
"Applejack"
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
UConvaiTextToSpeechProxy* UConvaiTextToSpeechProxy::CreateTextToSpeechQueryProxy(UObject* WorldContextObject, FString Transcript, FString Voice)
|
||||
{
|
||||
UConvaiTextToSpeechProxy* Proxy = NewObject<UConvaiTextToSpeechProxy>();
|
||||
Proxy->WorldPtr = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
|
||||
Proxy->URL = UConvaiURL::GetFullURL(TEXT("tts"), false);
|
||||
|
||||
Proxy->Transcript = Transcript;
|
||||
Proxy->VoiceStr = Voice;
|
||||
//Proxy->VoiceStr = FString(TTS_Voice_Type_str[uint8(Voice)]);
|
||||
|
||||
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UConvaiTextToSpeechProxy::Activate()
|
||||
{
|
||||
UWorld* World = WorldPtr.Get();
|
||||
|
||||
if (!World)
|
||||
{
|
||||
CONVAI_LOG(ConvaiT2SHttpLog, Warning, TEXT("Could not get a pointer to world!"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
FHttpModule* Http = &FHttpModule::Get();
|
||||
if (!Http)
|
||||
{
|
||||
CONVAI_LOG(ConvaiT2SHttpLog, Warning, TEXT("Could not get a pointer to http module!"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
TPair<FString, FString> AuthHeaderAndKey = UConvaiUtils::GetAuthHeaderAndKey();
|
||||
FString AuthKey = AuthHeaderAndKey.Value;
|
||||
FString AuthHeader = AuthHeaderAndKey.Key;
|
||||
|
||||
// Form Validation
|
||||
if (!UConvaiFormValidation::ValidateAuthKey(AuthKey) || !UConvaiFormValidation::ValidateInputText(Transcript) || !UConvaiFormValidation::ValidateVoiceType(VoiceStr))
|
||||
{
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the request
|
||||
FHttpRequestRef Request = Http->CreateRequest();
|
||||
Request->OnProcessRequestComplete().BindUObject(this, &UConvaiTextToSpeechProxy::onHttpRequestComplete);
|
||||
|
||||
// Set request fields
|
||||
Request->SetURL(URL);
|
||||
Request->SetVerb("POST");
|
||||
Request->SetHeader(TEXT("User-Agent"), TEXT("X-UnrealEngine-Agent"));
|
||||
Request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
|
||||
Request->SetHeader(AuthHeader, AuthKey);
|
||||
|
||||
// prepare json data
|
||||
FString JsonString;
|
||||
TSharedRef<TJsonWriter<TCHAR>> JsonWriter = TJsonWriterFactory<TCHAR>::Create(&JsonString);
|
||||
JsonWriter->WriteObjectStart();
|
||||
JsonWriter->WriteValue(AuthHeader, AuthKey);
|
||||
JsonWriter->WriteValue("transcript", Transcript);
|
||||
JsonWriter->WriteValue("voice", VoiceStr);
|
||||
JsonWriter->WriteValue("filename", FString("testAudio"));
|
||||
//JsonWriter->WriteValue("encoding", (VoiceStr.ToLower() == "female" || VoiceStr.ToLower() == "male")? FString("wav") : FString("mp3"));
|
||||
JsonWriter->WriteValue("encoding", FString("wav"));
|
||||
JsonWriter->WriteObjectEnd();
|
||||
JsonWriter->Close();
|
||||
// Insert the content into the request
|
||||
Request->SetContentAsString(JsonString);
|
||||
|
||||
// Debug
|
||||
//CONVAI_LOG(ConvaiT2SHttpLog, Warning, TEXT("%s"), *UConvaiUtils::ByteArrayToString(Request->GetContent()));
|
||||
|
||||
// Initiate the request
|
||||
if (!Request->ProcessRequest()) failed();
|
||||
}
|
||||
|
||||
void UConvaiTextToSpeechProxy::onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful)
|
||||
{
|
||||
if (!bWasSuccessful || ResponsePtr->GetResponseCode() < 200 || ResponsePtr->GetResponseCode() > 299)
|
||||
{
|
||||
CONVAI_LOG(ConvaiT2SHttpLog, Warning, TEXT("HTTP request failed with code %d, and with response:%s"),ResponsePtr->GetResponseCode(), *ResponsePtr->GetContentAsString());
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
|
||||
this->SoundWave = UConvaiUtils::WavDataToSoundWave(ResponsePtr->GetContent());
|
||||
|
||||
//this->SoundWave = UConvaiUtils::PCMDataToSoundWav(ResponsePtr->GetContent(), 1, 44100); // use this if in PCM format
|
||||
if (this->SoundWave == nullptr)
|
||||
{
|
||||
CONVAI_LOG(ConvaiT2SHttpLog, Warning, TEXT("Failed to decode response content to a sound wave"));
|
||||
failed();
|
||||
return;
|
||||
}
|
||||
success();
|
||||
}
|
||||
|
||||
void UConvaiTextToSpeechProxy::failed()
|
||||
{
|
||||
OnFailure.Broadcast(SoundWave);
|
||||
finish();
|
||||
}
|
||||
|
||||
void UConvaiTextToSpeechProxy::success()
|
||||
{
|
||||
OnSuccess.Broadcast(SoundWave);
|
||||
finish();
|
||||
}
|
||||
|
||||
void UConvaiTextToSpeechProxy::finish()
|
||||
{
|
||||
}
|
||||
|
||||
1272
ConvAI/Convai/Source/Convai/Private/ConvaiUtils.cpp
Normal file
1272
ConvAI/Convai/Source/Convai/Private/ConvaiUtils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
39
ConvAI/Convai/Source/Convai/Private/Mac/ConvaiApple.mm
Normal file
39
ConvAI/Convai/Source/Convai/Private/Mac/ConvaiApple.mm
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifdef __APPLE__
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
bool GetAppleMicPermission()
|
||||
{
|
||||
__block bool permissionGranted = false;
|
||||
|
||||
switch ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio])
|
||||
{
|
||||
case AVAuthorizationStatusAuthorized:
|
||||
// Already authorized
|
||||
permissionGranted = true;
|
||||
break;
|
||||
case AVAuthorizationStatusNotDetermined:
|
||||
{
|
||||
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
|
||||
// The user has not yet been asked to grant access to the audio capture device.
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted)
|
||||
{
|
||||
if (granted)
|
||||
{
|
||||
// Permission granted
|
||||
permissionGranted = true;
|
||||
}
|
||||
dispatch_semaphore_signal(sem);
|
||||
}];
|
||||
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
|
||||
break;
|
||||
}
|
||||
case AVAuthorizationStatusRestricted:
|
||||
case AVAuthorizationStatusDenied:
|
||||
// The user has previously denied access or can't grant access.
|
||||
permissionGranted = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return permissionGranted;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
#if defined(_WIN32) || defined(__ANDROID__)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning (disable:4018) // 'expression' : signed/unsigned mismatch
|
||||
#pragma warning (disable:4065) // switch statement contains 'default' but no 'case' labels
|
||||
#pragma warning (disable:4146) // unary minus operator applied to unsigned type, result still unsigned
|
||||
#pragma warning (disable:4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data
|
||||
#pragma warning (disable:4251) // 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
|
||||
#pragma warning (disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
|
||||
#pragma warning (disable:4305) // 'identifier' : truncation from 'type1' to 'type2'
|
||||
#pragma warning (disable:4307) // 'operator' : integral constant overflow
|
||||
#pragma warning (disable:4309) // 'conversion' : truncation of constant value
|
||||
#pragma warning (disable:4334) // 'operator' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
|
||||
#pragma warning (disable:4355) // 'this' : used in base member initializer list
|
||||
#pragma warning (disable:4506) // no definition for inline function 'function'
|
||||
#pragma warning (disable:4996) // The compiler encountered a deprecated declaration.
|
||||
#pragma warning (disable:4125) // decimal digit terminates octal escape sequence
|
||||
#pragma warning (disable:4800) // decimal digit terminates octal escape sequence
|
||||
#endif
|
||||
|
||||
// Generated by the gRPC C++ plugin.
|
||||
// If you make any local change, they will be lost.
|
||||
// source: arkit_blend_shapes.proto
|
||||
|
||||
#include "arkit_blend_shapes.pb.h"
|
||||
#include "arkit_blend_shapes.grpc.pb.h"
|
||||
|
||||
#include <functional>
|
||||
#include <grpcpp/impl/codegen/async_stream.h>
|
||||
#include <grpcpp/impl/codegen/async_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/channel_interface.h>
|
||||
#include <grpcpp/impl/codegen/client_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/client_callback.h>
|
||||
#include <grpcpp/impl/codegen/message_allocator.h>
|
||||
#include <grpcpp/impl/codegen/method_handler.h>
|
||||
#include <grpcpp/impl/codegen/rpc_service_method.h>
|
||||
#include <grpcpp/impl/codegen/server_callback.h>
|
||||
#include <grpcpp/impl/codegen/server_callback_handlers.h>
|
||||
#include <grpcpp/impl/codegen/server_context.h>
|
||||
#include <grpcpp/impl/codegen/service_type.h>
|
||||
#include <grpcpp/impl/codegen/sync_stream.h>
|
||||
namespace service {
|
||||
|
||||
} // namespace service
|
||||
|
||||
#else
|
||||
// Generated by the gRPC C++ plugin.
|
||||
// If you make any local change, they will be lost.
|
||||
// source: arkit_blend_shapes.proto
|
||||
|
||||
#include "arkit_blend_shapes.pb.h"
|
||||
#include "arkit_blend_shapes.grpc.pb.h"
|
||||
|
||||
#include <functional>
|
||||
#include <grpcpp/support/async_stream.h>
|
||||
#include <grpcpp/support/async_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/channel_interface.h>
|
||||
#include <grpcpp/impl/codegen/client_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/client_callback.h>
|
||||
#include <grpcpp/impl/codegen/message_allocator.h>
|
||||
#include <grpcpp/impl/codegen/method_handler.h>
|
||||
#include <grpcpp/impl/codegen/rpc_service_method.h>
|
||||
#include <grpcpp/impl/codegen/server_callback.h>
|
||||
#include <grpcpp/impl/codegen/server_callback_handlers.h>
|
||||
#include <grpcpp/impl/codegen/server_context.h>
|
||||
#include <grpcpp/impl/codegen/service_type.h>
|
||||
#include <grpcpp/impl/codegen/sync_stream.h>
|
||||
namespace service {
|
||||
|
||||
} // namespace service
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,89 @@
|
||||
#if defined(_WIN32) || defined(__ANDROID__)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning (disable:4018) // 'expression' : signed/unsigned mismatch
|
||||
#pragma warning (disable:4065) // switch statement contains 'default' but no 'case' labels
|
||||
#pragma warning (disable:4146) // unary minus operator applied to unsigned type, result still unsigned
|
||||
#pragma warning (disable:4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data
|
||||
#pragma warning (disable:4251) // 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
|
||||
#pragma warning (disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
|
||||
#pragma warning (disable:4305) // 'identifier' : truncation from 'type1' to 'type2'
|
||||
#pragma warning (disable:4307) // 'operator' : integral constant overflow
|
||||
#pragma warning (disable:4309) // 'conversion' : truncation of constant value
|
||||
#pragma warning (disable:4334) // 'operator' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
|
||||
#pragma warning (disable:4355) // 'this' : used in base member initializer list
|
||||
#pragma warning (disable:4506) // no definition for inline function 'function'
|
||||
#pragma warning (disable:4996) // The compiler encountered a deprecated declaration.
|
||||
#pragma warning (disable:4125) // decimal digit terminates octal escape sequence
|
||||
#pragma warning (disable:4800) // decimal digit terminates octal escape sequence
|
||||
#endif
|
||||
|
||||
// Generated by the gRPC C++ plugin.
|
||||
// If you make any local change, they will be lost.
|
||||
// source: arkit_blend_shapes.proto
|
||||
#ifndef GRPC_arkit_5fblend_5fshapes_2eproto__INCLUDED
|
||||
#define GRPC_arkit_5fblend_5fshapes_2eproto__INCLUDED
|
||||
|
||||
#include "arkit_blend_shapes.pb.h"
|
||||
|
||||
#include <functional>
|
||||
#include <grpc/impl/codegen/port_platform.h>
|
||||
#include <grpcpp/impl/codegen/async_generic_service.h>
|
||||
#include <grpcpp/impl/codegen/async_stream.h>
|
||||
#include <grpcpp/impl/codegen/async_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/client_callback.h>
|
||||
#include <grpcpp/impl/codegen/client_context.h>
|
||||
#include <grpcpp/impl/codegen/completion_queue.h>
|
||||
#include <grpcpp/impl/codegen/message_allocator.h>
|
||||
#include <grpcpp/impl/codegen/method_handler.h>
|
||||
#include <grpcpp/impl/codegen/proto_utils.h>
|
||||
#include <grpcpp/impl/codegen/rpc_method.h>
|
||||
#include <grpcpp/impl/codegen/server_callback.h>
|
||||
#include <grpcpp/impl/codegen/server_callback_handlers.h>
|
||||
#include <grpcpp/impl/codegen/server_context.h>
|
||||
#include <grpcpp/impl/codegen/service_type.h>
|
||||
#include <grpcpp/impl/codegen/status.h>
|
||||
#include <grpcpp/impl/codegen/stub_options.h>
|
||||
#include <grpcpp/impl/codegen/sync_stream.h>
|
||||
|
||||
namespace service {
|
||||
|
||||
} // namespace service
|
||||
|
||||
|
||||
#endif // GRPC_arkit_5fblend_5fshapes_2eproto__INCLUDED
|
||||
#else
|
||||
// Generated by the gRPC C++ plugin.
|
||||
// If you make any local change, they will be lost.
|
||||
// source: arkit_blend_shapes.proto
|
||||
#ifndef GRPC_arkit_5fblend_5fshapes_2eproto__INCLUDED
|
||||
#define GRPC_arkit_5fblend_5fshapes_2eproto__INCLUDED
|
||||
|
||||
#include "arkit_blend_shapes.pb.h"
|
||||
|
||||
#include <functional>
|
||||
#include <grpcpp/generic/async_generic_service.h>
|
||||
#include <grpcpp/support/async_stream.h>
|
||||
#include <grpcpp/support/async_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/client_callback.h>
|
||||
#include <grpcpp/impl/codegen/client_context.h>
|
||||
#include <grpcpp/impl/codegen/completion_queue.h>
|
||||
#include <grpcpp/impl/codegen/message_allocator.h>
|
||||
#include <grpcpp/impl/codegen/method_handler.h>
|
||||
#include <grpcpp/impl/codegen/proto_utils.h>
|
||||
#include <grpcpp/impl/codegen/rpc_method.h>
|
||||
#include <grpcpp/impl/codegen/server_callback.h>
|
||||
#include <grpcpp/impl/codegen/server_callback_handlers.h>
|
||||
#include <grpcpp/impl/codegen/server_context.h>
|
||||
#include <grpcpp/impl/codegen/service_type.h>
|
||||
#include <grpcpp/impl/codegen/status.h>
|
||||
#include <grpcpp/impl/codegen/stub_options.h>
|
||||
#include <grpcpp/impl/codegen/sync_stream.h>
|
||||
|
||||
namespace service {
|
||||
|
||||
} // namespace service
|
||||
|
||||
|
||||
#endif // GRPC_arkit_5fblend_5fshapes_2eproto__INCLUDED
|
||||
|
||||
#endif
|
||||
4193
ConvAI/Convai/Source/Convai/Private/Proto/arkit_blend_shapes.pb.cc
Normal file
4193
ConvAI/Convai/Source/Convai/Private/Proto/arkit_blend_shapes.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
4170
ConvAI/Convai/Source/Convai/Private/Proto/arkit_blend_shapes.pb.h
Normal file
4170
ConvAI/Convai/Source/Convai/Private/Proto/arkit_blend_shapes.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
552
ConvAI/Convai/Source/Convai/Private/Proto/service.grpc.pb.cc
Normal file
552
ConvAI/Convai/Source/Convai/Private/Proto/service.grpc.pb.cc
Normal file
@@ -0,0 +1,552 @@
|
||||
#if defined(_WIN32) || defined(__ANDROID__)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning (disable:4018) // 'expression' : signed/unsigned mismatch
|
||||
#pragma warning (disable:4065) // switch statement contains 'default' but no 'case' labels
|
||||
#pragma warning (disable:4146) // unary minus operator applied to unsigned type, result still unsigned
|
||||
#pragma warning (disable:4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data
|
||||
#pragma warning (disable:4251) // 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
|
||||
#pragma warning (disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
|
||||
#pragma warning (disable:4305) // 'identifier' : truncation from 'type1' to 'type2'
|
||||
#pragma warning (disable:4307) // 'operator' : integral constant overflow
|
||||
#pragma warning (disable:4309) // 'conversion' : truncation of constant value
|
||||
#pragma warning (disable:4334) // 'operator' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
|
||||
#pragma warning (disable:4355) // 'this' : used in base member initializer list
|
||||
#pragma warning (disable:4506) // no definition for inline function 'function'
|
||||
#pragma warning (disable:4996) // The compiler encountered a deprecated declaration.
|
||||
#pragma warning (disable:4125) // decimal digit terminates octal escape sequence
|
||||
#pragma warning (disable:4800) // decimal digit terminates octal escape sequence
|
||||
#endif
|
||||
|
||||
// Generated by the gRPC C++ plugin.
|
||||
// If you make any local change, they will be lost.
|
||||
// source: service.proto
|
||||
|
||||
#include "service.pb.h"
|
||||
#include "service.grpc.pb.h"
|
||||
|
||||
#include <functional>
|
||||
#include <grpcpp/impl/codegen/async_stream.h>
|
||||
#include <grpcpp/impl/codegen/async_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/channel_interface.h>
|
||||
#include <grpcpp/impl/codegen/client_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/client_callback.h>
|
||||
#include <grpcpp/impl/codegen/message_allocator.h>
|
||||
#include <grpcpp/impl/codegen/method_handler.h>
|
||||
#include <grpcpp/impl/codegen/rpc_service_method.h>
|
||||
#include <grpcpp/impl/codegen/server_callback.h>
|
||||
#include <grpcpp/impl/codegen/server_callback_handlers.h>
|
||||
#include <grpcpp/impl/codegen/server_context.h>
|
||||
#include <grpcpp/impl/codegen/service_type.h>
|
||||
#include <grpcpp/impl/codegen/sync_stream.h>
|
||||
namespace service {
|
||||
|
||||
static const char* ConvaiService_method_names[] = {
|
||||
"/service.ConvaiService/Hello",
|
||||
"/service.ConvaiService/HelloStream",
|
||||
"/service.ConvaiService/SpeechToText",
|
||||
"/service.ConvaiService/GetResponse",
|
||||
"/service.ConvaiService/GetResponseSingle",
|
||||
"/service.ConvaiService/SubmitFeedback",
|
||||
};
|
||||
|
||||
std::unique_ptr< ConvaiService::Stub> ConvaiService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {
|
||||
(void)options;
|
||||
std::unique_ptr< ConvaiService::Stub> stub(new ConvaiService::Stub(channel));
|
||||
return stub;
|
||||
}
|
||||
|
||||
ConvaiService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel)
|
||||
: channel_(channel), rpcmethod_Hello_(ConvaiService_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
|
||||
, rpcmethod_HelloStream_(ConvaiService_method_names[1], ::grpc::internal::RpcMethod::BIDI_STREAMING, channel)
|
||||
, rpcmethod_SpeechToText_(ConvaiService_method_names[2], ::grpc::internal::RpcMethod::BIDI_STREAMING, channel)
|
||||
, rpcmethod_GetResponse_(ConvaiService_method_names[3], ::grpc::internal::RpcMethod::BIDI_STREAMING, channel)
|
||||
, rpcmethod_GetResponseSingle_(ConvaiService_method_names[4], ::grpc::internal::RpcMethod::SERVER_STREAMING, channel)
|
||||
, rpcmethod_SubmitFeedback_(ConvaiService_method_names[5], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
|
||||
{}
|
||||
|
||||
::grpc::Status ConvaiService::Stub::Hello(::grpc::ClientContext* context, const ::service::HelloRequest& request, ::service::HelloResponse* response) {
|
||||
return ::grpc::internal::BlockingUnaryCall< ::service::HelloRequest, ::service::HelloResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Hello_, context, request, response);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::experimental_async::Hello(::grpc::ClientContext* context, const ::service::HelloRequest* request, ::service::HelloResponse* response, std::function<void(::grpc::Status)> f) {
|
||||
::grpc::internal::CallbackUnaryCall< ::service::HelloRequest, ::service::HelloResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Hello_, context, request, response, std::move(f));
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::experimental_async::Hello(::grpc::ClientContext* context, const ::service::HelloRequest* request, ::service::HelloResponse* response, ::grpc::experimental::ClientUnaryReactor* reactor) {
|
||||
::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Hello_, context, request, response, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncResponseReader< ::service::HelloResponse>* ConvaiService::Stub::PrepareAsyncHelloRaw(::grpc::ClientContext* context, const ::service::HelloRequest& request, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::service::HelloResponse, ::service::HelloRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Hello_, context, request);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncResponseReader< ::service::HelloResponse>* ConvaiService::Stub::AsyncHelloRaw(::grpc::ClientContext* context, const ::service::HelloRequest& request, ::grpc::CompletionQueue* cq) {
|
||||
auto* result =
|
||||
this->PrepareAsyncHelloRaw(context, request, cq);
|
||||
result->StartCall();
|
||||
return result;
|
||||
}
|
||||
|
||||
::grpc::ClientReaderWriter< ::service::HelloRequest, ::service::HelloResponse>* ConvaiService::Stub::HelloStreamRaw(::grpc::ClientContext* context) {
|
||||
return ::grpc::internal::ClientReaderWriterFactory< ::service::HelloRequest, ::service::HelloResponse>::Create(channel_.get(), rpcmethod_HelloStream_, context);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::experimental_async::HelloStream(::grpc::ClientContext* context, ::grpc::experimental::ClientBidiReactor< ::service::HelloRequest,::service::HelloResponse>* reactor) {
|
||||
::grpc::internal::ClientCallbackReaderWriterFactory< ::service::HelloRequest,::service::HelloResponse>::Create(stub_->channel_.get(), stub_->rpcmethod_HelloStream_, context, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::HelloRequest, ::service::HelloResponse>* ConvaiService::Stub::AsyncHelloStreamRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::HelloRequest, ::service::HelloResponse>::Create(channel_.get(), cq, rpcmethod_HelloStream_, context, true, tag);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::HelloRequest, ::service::HelloResponse>* ConvaiService::Stub::PrepareAsyncHelloStreamRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::HelloRequest, ::service::HelloResponse>::Create(channel_.get(), cq, rpcmethod_HelloStream_, context, false, nullptr);
|
||||
}
|
||||
|
||||
::grpc::ClientReaderWriter< ::service::STTRequest, ::service::STTResponse>* ConvaiService::Stub::SpeechToTextRaw(::grpc::ClientContext* context) {
|
||||
return ::grpc::internal::ClientReaderWriterFactory< ::service::STTRequest, ::service::STTResponse>::Create(channel_.get(), rpcmethod_SpeechToText_, context);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::experimental_async::SpeechToText(::grpc::ClientContext* context, ::grpc::experimental::ClientBidiReactor< ::service::STTRequest,::service::STTResponse>* reactor) {
|
||||
::grpc::internal::ClientCallbackReaderWriterFactory< ::service::STTRequest,::service::STTResponse>::Create(stub_->channel_.get(), stub_->rpcmethod_SpeechToText_, context, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::STTRequest, ::service::STTResponse>* ConvaiService::Stub::AsyncSpeechToTextRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::STTRequest, ::service::STTResponse>::Create(channel_.get(), cq, rpcmethod_SpeechToText_, context, true, tag);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::STTRequest, ::service::STTResponse>* ConvaiService::Stub::PrepareAsyncSpeechToTextRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::STTRequest, ::service::STTResponse>::Create(channel_.get(), cq, rpcmethod_SpeechToText_, context, false, nullptr);
|
||||
}
|
||||
|
||||
::grpc::ClientReaderWriter< ::service::GetResponseRequest, ::service::GetResponseResponse>* ConvaiService::Stub::GetResponseRaw(::grpc::ClientContext* context) {
|
||||
return ::grpc::internal::ClientReaderWriterFactory< ::service::GetResponseRequest, ::service::GetResponseResponse>::Create(channel_.get(), rpcmethod_GetResponse_, context);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::experimental_async::GetResponse(::grpc::ClientContext* context, ::grpc::experimental::ClientBidiReactor< ::service::GetResponseRequest,::service::GetResponseResponse>* reactor) {
|
||||
::grpc::internal::ClientCallbackReaderWriterFactory< ::service::GetResponseRequest,::service::GetResponseResponse>::Create(stub_->channel_.get(), stub_->rpcmethod_GetResponse_, context, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::GetResponseRequest, ::service::GetResponseResponse>* ConvaiService::Stub::AsyncGetResponseRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::GetResponseRequest, ::service::GetResponseResponse>::Create(channel_.get(), cq, rpcmethod_GetResponse_, context, true, tag);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::GetResponseRequest, ::service::GetResponseResponse>* ConvaiService::Stub::PrepareAsyncGetResponseRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::GetResponseRequest, ::service::GetResponseResponse>::Create(channel_.get(), cq, rpcmethod_GetResponse_, context, false, nullptr);
|
||||
}
|
||||
|
||||
::grpc::ClientReader< ::service::GetResponseResponse>* ConvaiService::Stub::GetResponseSingleRaw(::grpc::ClientContext* context, const ::service::GetResponseRequestSingle& request) {
|
||||
return ::grpc::internal::ClientReaderFactory< ::service::GetResponseResponse>::Create(channel_.get(), rpcmethod_GetResponseSingle_, context, request);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::experimental_async::GetResponseSingle(::grpc::ClientContext* context, ::service::GetResponseRequestSingle* request, ::grpc::experimental::ClientReadReactor< ::service::GetResponseResponse>* reactor) {
|
||||
::grpc::internal::ClientCallbackReaderFactory< ::service::GetResponseResponse>::Create(stub_->channel_.get(), stub_->rpcmethod_GetResponseSingle_, context, request, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReader< ::service::GetResponseResponse>* ConvaiService::Stub::AsyncGetResponseSingleRaw(::grpc::ClientContext* context, const ::service::GetResponseRequestSingle& request, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return ::grpc::internal::ClientAsyncReaderFactory< ::service::GetResponseResponse>::Create(channel_.get(), cq, rpcmethod_GetResponseSingle_, context, request, true, tag);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReader< ::service::GetResponseResponse>* ConvaiService::Stub::PrepareAsyncGetResponseSingleRaw(::grpc::ClientContext* context, const ::service::GetResponseRequestSingle& request, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncReaderFactory< ::service::GetResponseResponse>::Create(channel_.get(), cq, rpcmethod_GetResponseSingle_, context, request, false, nullptr);
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Stub::SubmitFeedback(::grpc::ClientContext* context, const ::service::FeedbackRequest& request, ::service::FeedbackResponse* response) {
|
||||
return ::grpc::internal::BlockingUnaryCall< ::service::FeedbackRequest, ::service::FeedbackResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_SubmitFeedback_, context, request, response);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::experimental_async::SubmitFeedback(::grpc::ClientContext* context, const ::service::FeedbackRequest* request, ::service::FeedbackResponse* response, std::function<void(::grpc::Status)> f) {
|
||||
::grpc::internal::CallbackUnaryCall< ::service::FeedbackRequest, ::service::FeedbackResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_SubmitFeedback_, context, request, response, std::move(f));
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::experimental_async::SubmitFeedback(::grpc::ClientContext* context, const ::service::FeedbackRequest* request, ::service::FeedbackResponse* response, ::grpc::experimental::ClientUnaryReactor* reactor) {
|
||||
::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_SubmitFeedback_, context, request, response, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncResponseReader< ::service::FeedbackResponse>* ConvaiService::Stub::PrepareAsyncSubmitFeedbackRaw(::grpc::ClientContext* context, const ::service::FeedbackRequest& request, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::service::FeedbackResponse, ::service::FeedbackRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_SubmitFeedback_, context, request);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncResponseReader< ::service::FeedbackResponse>* ConvaiService::Stub::AsyncSubmitFeedbackRaw(::grpc::ClientContext* context, const ::service::FeedbackRequest& request, ::grpc::CompletionQueue* cq) {
|
||||
auto* result =
|
||||
this->PrepareAsyncSubmitFeedbackRaw(context, request, cq);
|
||||
result->StartCall();
|
||||
return result;
|
||||
}
|
||||
|
||||
ConvaiService::Service::Service() {
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[0],
|
||||
::grpc::internal::RpcMethod::NORMAL_RPC,
|
||||
new ::grpc::internal::RpcMethodHandler< ConvaiService::Service, ::service::HelloRequest, ::service::HelloResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
const ::service::HelloRequest* req,
|
||||
::service::HelloResponse* resp) {
|
||||
return service->Hello(ctx, req, resp);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[1],
|
||||
::grpc::internal::RpcMethod::BIDI_STREAMING,
|
||||
new ::grpc::internal::BidiStreamingHandler< ConvaiService::Service, ::service::HelloRequest, ::service::HelloResponse>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
::grpc::ServerReaderWriter<::service::HelloResponse,
|
||||
::service::HelloRequest>* stream) {
|
||||
return service->HelloStream(ctx, stream);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[2],
|
||||
::grpc::internal::RpcMethod::BIDI_STREAMING,
|
||||
new ::grpc::internal::BidiStreamingHandler< ConvaiService::Service, ::service::STTRequest, ::service::STTResponse>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
::grpc::ServerReaderWriter<::service::STTResponse,
|
||||
::service::STTRequest>* stream) {
|
||||
return service->SpeechToText(ctx, stream);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[3],
|
||||
::grpc::internal::RpcMethod::BIDI_STREAMING,
|
||||
new ::grpc::internal::BidiStreamingHandler< ConvaiService::Service, ::service::GetResponseRequest, ::service::GetResponseResponse>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
::grpc::ServerReaderWriter<::service::GetResponseResponse,
|
||||
::service::GetResponseRequest>* stream) {
|
||||
return service->GetResponse(ctx, stream);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[4],
|
||||
::grpc::internal::RpcMethod::SERVER_STREAMING,
|
||||
new ::grpc::internal::ServerStreamingHandler< ConvaiService::Service, ::service::GetResponseRequestSingle, ::service::GetResponseResponse>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
const ::service::GetResponseRequestSingle* req,
|
||||
::grpc::ServerWriter<::service::GetResponseResponse>* writer) {
|
||||
return service->GetResponseSingle(ctx, req, writer);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[5],
|
||||
::grpc::internal::RpcMethod::NORMAL_RPC,
|
||||
new ::grpc::internal::RpcMethodHandler< ConvaiService::Service, ::service::FeedbackRequest, ::service::FeedbackResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
const ::service::FeedbackRequest* req,
|
||||
::service::FeedbackResponse* resp) {
|
||||
return service->SubmitFeedback(ctx, req, resp);
|
||||
}, this)));
|
||||
}
|
||||
|
||||
ConvaiService::Service::~Service() {
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::Hello(::grpc::ServerContext* context, const ::service::HelloRequest* request, ::service::HelloResponse* response) {
|
||||
(void) context;
|
||||
(void) request;
|
||||
(void) response;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::HelloStream(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::service::HelloResponse, ::service::HelloRequest>* stream) {
|
||||
(void) context;
|
||||
(void) stream;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::SpeechToText(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::service::STTResponse, ::service::STTRequest>* stream) {
|
||||
(void) context;
|
||||
(void) stream;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::GetResponse(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::service::GetResponseResponse, ::service::GetResponseRequest>* stream) {
|
||||
(void) context;
|
||||
(void) stream;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::GetResponseSingle(::grpc::ServerContext* context, const ::service::GetResponseRequestSingle* request, ::grpc::ServerWriter< ::service::GetResponseResponse>* writer) {
|
||||
(void) context;
|
||||
(void) request;
|
||||
(void) writer;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::SubmitFeedback(::grpc::ServerContext* context, const ::service::FeedbackRequest* request, ::service::FeedbackResponse* response) {
|
||||
(void) context;
|
||||
(void) request;
|
||||
(void) response;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
|
||||
} // namespace service
|
||||
|
||||
#else
|
||||
// Generated by the gRPC C++ plugin.
|
||||
// If you make any local change, they will be lost.
|
||||
// source: service.proto
|
||||
|
||||
#include "service.pb.h"
|
||||
#include "service.grpc.pb.h"
|
||||
|
||||
#include <functional>
|
||||
#include <grpcpp/support/async_stream.h>
|
||||
#include <grpcpp/support/async_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/channel_interface.h>
|
||||
#include <grpcpp/impl/codegen/client_unary_call.h>
|
||||
#include <grpcpp/impl/codegen/client_callback.h>
|
||||
#include <grpcpp/impl/codegen/message_allocator.h>
|
||||
#include <grpcpp/impl/codegen/method_handler.h>
|
||||
#include <grpcpp/impl/codegen/rpc_service_method.h>
|
||||
#include <grpcpp/impl/codegen/server_callback.h>
|
||||
#include <grpcpp/impl/codegen/server_callback_handlers.h>
|
||||
#include <grpcpp/impl/codegen/server_context.h>
|
||||
#include <grpcpp/impl/codegen/service_type.h>
|
||||
#include <grpcpp/impl/codegen/sync_stream.h>
|
||||
namespace service {
|
||||
|
||||
static const char* ConvaiService_method_names[] = {
|
||||
"/service.ConvaiService/Hello",
|
||||
"/service.ConvaiService/HelloStream",
|
||||
"/service.ConvaiService/SpeechToText",
|
||||
"/service.ConvaiService/GetResponse",
|
||||
"/service.ConvaiService/GetResponseSingle",
|
||||
"/service.ConvaiService/SubmitFeedback",
|
||||
};
|
||||
|
||||
std::unique_ptr< ConvaiService::Stub> ConvaiService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {
|
||||
(void)options;
|
||||
std::unique_ptr< ConvaiService::Stub> stub(new ConvaiService::Stub(channel, options));
|
||||
return stub;
|
||||
}
|
||||
|
||||
ConvaiService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options)
|
||||
: channel_(channel), rpcmethod_Hello_(ConvaiService_method_names[0], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel)
|
||||
, rpcmethod_HelloStream_(ConvaiService_method_names[1], options.suffix_for_stats(),::grpc::internal::RpcMethod::BIDI_STREAMING, channel)
|
||||
, rpcmethod_SpeechToText_(ConvaiService_method_names[2], options.suffix_for_stats(),::grpc::internal::RpcMethod::BIDI_STREAMING, channel)
|
||||
, rpcmethod_GetResponse_(ConvaiService_method_names[3], options.suffix_for_stats(),::grpc::internal::RpcMethod::BIDI_STREAMING, channel)
|
||||
, rpcmethod_GetResponseSingle_(ConvaiService_method_names[4], options.suffix_for_stats(),::grpc::internal::RpcMethod::SERVER_STREAMING, channel)
|
||||
, rpcmethod_SubmitFeedback_(ConvaiService_method_names[5], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel)
|
||||
{}
|
||||
|
||||
::grpc::Status ConvaiService::Stub::Hello(::grpc::ClientContext* context, const ::service::HelloRequest& request, ::service::HelloResponse* response) {
|
||||
return ::grpc::internal::BlockingUnaryCall< ::service::HelloRequest, ::service::HelloResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Hello_, context, request, response);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::async::Hello(::grpc::ClientContext* context, const ::service::HelloRequest* request, ::service::HelloResponse* response, std::function<void(::grpc::Status)> f) {
|
||||
::grpc::internal::CallbackUnaryCall< ::service::HelloRequest, ::service::HelloResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Hello_, context, request, response, std::move(f));
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::async::Hello(::grpc::ClientContext* context, const ::service::HelloRequest* request, ::service::HelloResponse* response, ::grpc::ClientUnaryReactor* reactor) {
|
||||
::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Hello_, context, request, response, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncResponseReader< ::service::HelloResponse>* ConvaiService::Stub::PrepareAsyncHelloRaw(::grpc::ClientContext* context, const ::service::HelloRequest& request, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::service::HelloResponse, ::service::HelloRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Hello_, context, request);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncResponseReader< ::service::HelloResponse>* ConvaiService::Stub::AsyncHelloRaw(::grpc::ClientContext* context, const ::service::HelloRequest& request, ::grpc::CompletionQueue* cq) {
|
||||
auto* result =
|
||||
this->PrepareAsyncHelloRaw(context, request, cq);
|
||||
result->StartCall();
|
||||
return result;
|
||||
}
|
||||
|
||||
::grpc::ClientReaderWriter< ::service::HelloRequest, ::service::HelloResponse>* ConvaiService::Stub::HelloStreamRaw(::grpc::ClientContext* context) {
|
||||
return ::grpc::internal::ClientReaderWriterFactory< ::service::HelloRequest, ::service::HelloResponse>::Create(channel_.get(), rpcmethod_HelloStream_, context);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::async::HelloStream(::grpc::ClientContext* context, ::grpc::ClientBidiReactor< ::service::HelloRequest,::service::HelloResponse>* reactor) {
|
||||
::grpc::internal::ClientCallbackReaderWriterFactory< ::service::HelloRequest,::service::HelloResponse>::Create(stub_->channel_.get(), stub_->rpcmethod_HelloStream_, context, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::HelloRequest, ::service::HelloResponse>* ConvaiService::Stub::AsyncHelloStreamRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::HelloRequest, ::service::HelloResponse>::Create(channel_.get(), cq, rpcmethod_HelloStream_, context, true, tag);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::HelloRequest, ::service::HelloResponse>* ConvaiService::Stub::PrepareAsyncHelloStreamRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::HelloRequest, ::service::HelloResponse>::Create(channel_.get(), cq, rpcmethod_HelloStream_, context, false, nullptr);
|
||||
}
|
||||
|
||||
::grpc::ClientReaderWriter< ::service::STTRequest, ::service::STTResponse>* ConvaiService::Stub::SpeechToTextRaw(::grpc::ClientContext* context) {
|
||||
return ::grpc::internal::ClientReaderWriterFactory< ::service::STTRequest, ::service::STTResponse>::Create(channel_.get(), rpcmethod_SpeechToText_, context);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::async::SpeechToText(::grpc::ClientContext* context, ::grpc::ClientBidiReactor< ::service::STTRequest,::service::STTResponse>* reactor) {
|
||||
::grpc::internal::ClientCallbackReaderWriterFactory< ::service::STTRequest,::service::STTResponse>::Create(stub_->channel_.get(), stub_->rpcmethod_SpeechToText_, context, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::STTRequest, ::service::STTResponse>* ConvaiService::Stub::AsyncSpeechToTextRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::STTRequest, ::service::STTResponse>::Create(channel_.get(), cq, rpcmethod_SpeechToText_, context, true, tag);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::STTRequest, ::service::STTResponse>* ConvaiService::Stub::PrepareAsyncSpeechToTextRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::STTRequest, ::service::STTResponse>::Create(channel_.get(), cq, rpcmethod_SpeechToText_, context, false, nullptr);
|
||||
}
|
||||
|
||||
::grpc::ClientReaderWriter< ::service::GetResponseRequest, ::service::GetResponseResponse>* ConvaiService::Stub::GetResponseRaw(::grpc::ClientContext* context) {
|
||||
return ::grpc::internal::ClientReaderWriterFactory< ::service::GetResponseRequest, ::service::GetResponseResponse>::Create(channel_.get(), rpcmethod_GetResponse_, context);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::async::GetResponse(::grpc::ClientContext* context, ::grpc::ClientBidiReactor< ::service::GetResponseRequest,::service::GetResponseResponse>* reactor) {
|
||||
::grpc::internal::ClientCallbackReaderWriterFactory< ::service::GetResponseRequest,::service::GetResponseResponse>::Create(stub_->channel_.get(), stub_->rpcmethod_GetResponse_, context, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::GetResponseRequest, ::service::GetResponseResponse>* ConvaiService::Stub::AsyncGetResponseRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::GetResponseRequest, ::service::GetResponseResponse>::Create(channel_.get(), cq, rpcmethod_GetResponse_, context, true, tag);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReaderWriter< ::service::GetResponseRequest, ::service::GetResponseResponse>* ConvaiService::Stub::PrepareAsyncGetResponseRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncReaderWriterFactory< ::service::GetResponseRequest, ::service::GetResponseResponse>::Create(channel_.get(), cq, rpcmethod_GetResponse_, context, false, nullptr);
|
||||
}
|
||||
|
||||
::grpc::ClientReader< ::service::GetResponseResponse>* ConvaiService::Stub::GetResponseSingleRaw(::grpc::ClientContext* context, const ::service::GetResponseRequestSingle& request) {
|
||||
return ::grpc::internal::ClientReaderFactory< ::service::GetResponseResponse>::Create(channel_.get(), rpcmethod_GetResponseSingle_, context, request);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::async::GetResponseSingle(::grpc::ClientContext* context, const ::service::GetResponseRequestSingle* request, ::grpc::ClientReadReactor< ::service::GetResponseResponse>* reactor) {
|
||||
::grpc::internal::ClientCallbackReaderFactory< ::service::GetResponseResponse>::Create(stub_->channel_.get(), stub_->rpcmethod_GetResponseSingle_, context, request, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReader< ::service::GetResponseResponse>* ConvaiService::Stub::AsyncGetResponseSingleRaw(::grpc::ClientContext* context, const ::service::GetResponseRequestSingle& request, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return ::grpc::internal::ClientAsyncReaderFactory< ::service::GetResponseResponse>::Create(channel_.get(), cq, rpcmethod_GetResponseSingle_, context, request, true, tag);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReader< ::service::GetResponseResponse>* ConvaiService::Stub::PrepareAsyncGetResponseSingleRaw(::grpc::ClientContext* context, const ::service::GetResponseRequestSingle& request, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncReaderFactory< ::service::GetResponseResponse>::Create(channel_.get(), cq, rpcmethod_GetResponseSingle_, context, request, false, nullptr);
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Stub::SubmitFeedback(::grpc::ClientContext* context, const ::service::FeedbackRequest& request, ::service::FeedbackResponse* response) {
|
||||
return ::grpc::internal::BlockingUnaryCall< ::service::FeedbackRequest, ::service::FeedbackResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_SubmitFeedback_, context, request, response);
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::async::SubmitFeedback(::grpc::ClientContext* context, const ::service::FeedbackRequest* request, ::service::FeedbackResponse* response, std::function<void(::grpc::Status)> f) {
|
||||
::grpc::internal::CallbackUnaryCall< ::service::FeedbackRequest, ::service::FeedbackResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_SubmitFeedback_, context, request, response, std::move(f));
|
||||
}
|
||||
|
||||
void ConvaiService::Stub::async::SubmitFeedback(::grpc::ClientContext* context, const ::service::FeedbackRequest* request, ::service::FeedbackResponse* response, ::grpc::ClientUnaryReactor* reactor) {
|
||||
::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_SubmitFeedback_, context, request, response, reactor);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncResponseReader< ::service::FeedbackResponse>* ConvaiService::Stub::PrepareAsyncSubmitFeedbackRaw(::grpc::ClientContext* context, const ::service::FeedbackRequest& request, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::service::FeedbackResponse, ::service::FeedbackRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_SubmitFeedback_, context, request);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncResponseReader< ::service::FeedbackResponse>* ConvaiService::Stub::AsyncSubmitFeedbackRaw(::grpc::ClientContext* context, const ::service::FeedbackRequest& request, ::grpc::CompletionQueue* cq) {
|
||||
auto* result =
|
||||
this->PrepareAsyncSubmitFeedbackRaw(context, request, cq);
|
||||
result->StartCall();
|
||||
return result;
|
||||
}
|
||||
|
||||
ConvaiService::Service::Service() {
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[0],
|
||||
::grpc::internal::RpcMethod::NORMAL_RPC,
|
||||
new ::grpc::internal::RpcMethodHandler< ConvaiService::Service, ::service::HelloRequest, ::service::HelloResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
const ::service::HelloRequest* req,
|
||||
::service::HelloResponse* resp) {
|
||||
return service->Hello(ctx, req, resp);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[1],
|
||||
::grpc::internal::RpcMethod::BIDI_STREAMING,
|
||||
new ::grpc::internal::BidiStreamingHandler< ConvaiService::Service, ::service::HelloRequest, ::service::HelloResponse>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
::grpc::ServerReaderWriter<::service::HelloResponse,
|
||||
::service::HelloRequest>* stream) {
|
||||
return service->HelloStream(ctx, stream);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[2],
|
||||
::grpc::internal::RpcMethod::BIDI_STREAMING,
|
||||
new ::grpc::internal::BidiStreamingHandler< ConvaiService::Service, ::service::STTRequest, ::service::STTResponse>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
::grpc::ServerReaderWriter<::service::STTResponse,
|
||||
::service::STTRequest>* stream) {
|
||||
return service->SpeechToText(ctx, stream);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[3],
|
||||
::grpc::internal::RpcMethod::BIDI_STREAMING,
|
||||
new ::grpc::internal::BidiStreamingHandler< ConvaiService::Service, ::service::GetResponseRequest, ::service::GetResponseResponse>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
::grpc::ServerReaderWriter<::service::GetResponseResponse,
|
||||
::service::GetResponseRequest>* stream) {
|
||||
return service->GetResponse(ctx, stream);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[4],
|
||||
::grpc::internal::RpcMethod::SERVER_STREAMING,
|
||||
new ::grpc::internal::ServerStreamingHandler< ConvaiService::Service, ::service::GetResponseRequestSingle, ::service::GetResponseResponse>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
const ::service::GetResponseRequestSingle* req,
|
||||
::grpc::ServerWriter<::service::GetResponseResponse>* writer) {
|
||||
return service->GetResponseSingle(ctx, req, writer);
|
||||
}, this)));
|
||||
AddMethod(new ::grpc::internal::RpcServiceMethod(
|
||||
ConvaiService_method_names[5],
|
||||
::grpc::internal::RpcMethod::NORMAL_RPC,
|
||||
new ::grpc::internal::RpcMethodHandler< ConvaiService::Service, ::service::FeedbackRequest, ::service::FeedbackResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
|
||||
[](ConvaiService::Service* service,
|
||||
::grpc::ServerContext* ctx,
|
||||
const ::service::FeedbackRequest* req,
|
||||
::service::FeedbackResponse* resp) {
|
||||
return service->SubmitFeedback(ctx, req, resp);
|
||||
}, this)));
|
||||
}
|
||||
|
||||
ConvaiService::Service::~Service() {
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::Hello(::grpc::ServerContext* context, const ::service::HelloRequest* request, ::service::HelloResponse* response) {
|
||||
(void) context;
|
||||
(void) request;
|
||||
(void) response;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::HelloStream(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::service::HelloResponse, ::service::HelloRequest>* stream) {
|
||||
(void) context;
|
||||
(void) stream;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::SpeechToText(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::service::STTResponse, ::service::STTRequest>* stream) {
|
||||
(void) context;
|
||||
(void) stream;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::GetResponse(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::service::GetResponseResponse, ::service::GetResponseRequest>* stream) {
|
||||
(void) context;
|
||||
(void) stream;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::GetResponseSingle(::grpc::ServerContext* context, const ::service::GetResponseRequestSingle* request, ::grpc::ServerWriter< ::service::GetResponseResponse>* writer) {
|
||||
(void) context;
|
||||
(void) request;
|
||||
(void) writer;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status ConvaiService::Service::SubmitFeedback(::grpc::ServerContext* context, const ::service::FeedbackRequest* request, ::service::FeedbackResponse* response) {
|
||||
(void) context;
|
||||
(void) request;
|
||||
(void) response;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
|
||||
} // namespace service
|
||||
|
||||
|
||||
#endif
|
||||
2168
ConvAI/Convai/Source/Convai/Private/Proto/service.grpc.pb.h
Normal file
2168
ConvAI/Convai/Source/Convai/Private/Proto/service.grpc.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
20534
ConvAI/Convai/Source/Convai/Private/Proto/service.pb.cc
Normal file
20534
ConvAI/Convai/Source/Convai/Private/Proto/service.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
23289
ConvAI/Convai/Source/Convai/Private/Proto/service.pb.h
Normal file
23289
ConvAI/Convai/Source/Convai/Private/Proto/service.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
173
ConvAI/Convai/Source/Convai/Private/RestAPI/ConvaiAPIBase.cpp
Normal file
173
ConvAI/Convai/Source/Convai/Private/RestAPI/ConvaiAPIBase.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
|
||||
#include "RestAPI/ConvaiAPIBase.h"
|
||||
#include "ConvaiUtils.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(ConvaiBaseHttpLogs);
|
||||
|
||||
|
||||
void UConvaiAPIBaseProxy::Activate()
|
||||
{
|
||||
TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request = CONVAI_HTTP_MODULE::Get().CreateRequest();
|
||||
|
||||
if (!ConfigureRequest(Request, TEXT("")))
|
||||
{
|
||||
HandleFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
Request->OnProcessRequestComplete().BindUObject(this, &ThisClass::OnHttpRequestComplete);
|
||||
|
||||
if (Request->ProcessRequest())
|
||||
{
|
||||
AddToRoot();
|
||||
}
|
||||
}
|
||||
|
||||
bool UConvaiAPIBaseProxy::ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb)
|
||||
{
|
||||
if (!UConvaiFormValidation::ValidateInputText(URL) || !UConvaiFormValidation::ValidateInputText(Verb))
|
||||
{
|
||||
HandleFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
TPair<FString, FString> AuthHeaderAndKey = UConvaiUtils::GetAuthHeaderAndKey();
|
||||
FString AuthKey = AuthHeaderAndKey.Value;
|
||||
FString AuthHeader = AuthHeaderAndKey.Key;
|
||||
|
||||
if (!UConvaiFormValidation::ValidateAuthKey(AuthKey))
|
||||
{
|
||||
HandleFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
Request->SetURL(URL);
|
||||
Request->SetVerb(Verb);
|
||||
Request->SetHeader(AuthHeader, AuthKey);
|
||||
|
||||
// Child classes can add filed to this object
|
||||
TSharedPtr<FJsonObject> ObjectToSend = MakeShareable(new FJsonObject);
|
||||
if (AddContentToRequestAsString(ObjectToSend))
|
||||
{
|
||||
Request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
|
||||
|
||||
FString Content;
|
||||
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&Content);
|
||||
FJsonSerializer::Serialize(ObjectToSend.ToSharedRef(), Writer);
|
||||
|
||||
Request->SetContentAsString(Content);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CONVAI_HTTP_PAYLOAD_ARRAY_TYPE DataToSend;
|
||||
FString Boundary = TEXT("ConvaiPluginFormBoundary") + FString::FromInt(FDateTime::Now().GetTicks());
|
||||
if (AddContentToRequest(DataToSend, Boundary))
|
||||
{
|
||||
if (FString(Verb).Equals(ConvaiHttpConstants::PUT))
|
||||
{
|
||||
Request->SetHeader(TEXT("Content-Type"), TEXT("application/octet-stream"));
|
||||
Request->SetContent(DataToSend);
|
||||
return true;
|
||||
}
|
||||
|
||||
Request->SetHeader(TEXT("Content-Type"), FString::Printf(TEXT("multipart/form-data; boundary=----%s"), *Boundary));
|
||||
|
||||
// Add closing boundary
|
||||
FString ClosingBoundary = FString::Printf(TEXT("\r\n------%s--\r\n"), *Boundary);
|
||||
DataToSend.Append((uint8*)TCHAR_TO_UTF8(*ClosingBoundary), ClosingBoundary.Len());
|
||||
|
||||
// Set the request content and content length
|
||||
Request->SetHeader(TEXT("Content-Length"), FString::FromInt(DataToSend.Num()));
|
||||
Request->SetContent(DataToSend);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UConvaiAPIBaseProxy::OnHttpRequestComplete(CONVAI_HTTP_REQUEST_PTR Request, CONVAI_HTTP_RESPONSE_PTR Response, bool bWasSuccessful)
|
||||
{
|
||||
if (!Response)
|
||||
{
|
||||
if (bWasSuccessful)
|
||||
{
|
||||
CONVAI_LOG(ConvaiBaseHttpLogs, Warning, TEXT("HTTP request succeded - But response pointer is invalid"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiBaseHttpLogs, Warning, TEXT("HTTP request failed - Response pointer is invalid"));
|
||||
}
|
||||
|
||||
HandleFailure();
|
||||
return;
|
||||
}
|
||||
if (!bWasSuccessful || Response->GetResponseCode() < 200 || Response->GetResponseCode() > 299)
|
||||
{
|
||||
CONVAI_LOG(ConvaiBaseHttpLogs, Warning, TEXT("HTTP request failed with code %d, and with response:%s"), Response->GetResponseCode(), *Response->GetContentAsString());
|
||||
HandleFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
ResponseString = Response->GetContentAsString();
|
||||
ResponseData = Response->GetContent();
|
||||
HandleSuccess();
|
||||
}
|
||||
|
||||
void UConvaiAPIBaseProxy::HandleSuccess()
|
||||
{
|
||||
RemoveFromRoot();
|
||||
}
|
||||
|
||||
void UConvaiAPIBaseProxy::HandleFailure()
|
||||
{
|
||||
RemoveFromRoot();
|
||||
}
|
||||
// END Base api proxy
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool UConvaiAPITokenInBodyProxy::AddContentToRequest(CONVAI_HTTP_PAYLOAD_ARRAY_TYPE& DataToSend, const FString& Boundary)
|
||||
{
|
||||
const TPair<FString, FString> AuthHeaderAndKey = UConvaiUtils::GetAuthHeaderAndKey();
|
||||
const FString AuthKey = AuthHeaderAndKey.Value;
|
||||
const FString AuthHeader = AuthHeaderAndKey.Key;
|
||||
|
||||
if (!UConvaiFormValidation::ValidateAuthKey(AuthKey))
|
||||
{
|
||||
HandleFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AuthHeader == ConvaiConstants::Auth_Token_Header)
|
||||
{
|
||||
const FString ExpIdField = FString::Printf(TEXT("\r\n------%s\r\nContent-Disposition: form-data; name=\"experience_session_id\"\r\n\r\n%s"), *Boundary, *AuthKey);
|
||||
DataToSend.Append((uint8*)TCHAR_TO_UTF8(*ExpIdField), ExpIdField.Len());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UConvaiAPITokenInBodyProxy::AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend)
|
||||
{
|
||||
const TPair<FString, FString> AuthHeaderAndKey = UConvaiUtils::GetAuthHeaderAndKey();
|
||||
const FString AuthKey = AuthHeaderAndKey.Value;
|
||||
const FString AuthHeader = AuthHeaderAndKey.Key;
|
||||
|
||||
if (!UConvaiFormValidation::ValidateAuthKey(AuthKey))
|
||||
{
|
||||
HandleFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AuthHeader == ConvaiConstants::Auth_Token_Header)
|
||||
{
|
||||
ObjectToSend->SetStringField(TEXT("experience_session_id"), AuthKey);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
328
ConvAI/Convai/Source/Convai/Private/RestAPI/ConvaiLTMProxy.cpp
Normal file
328
ConvAI/Convai/Source/Convai/Private/RestAPI/ConvaiLTMProxy.cpp
Normal file
@@ -0,0 +1,328 @@
|
||||
|
||||
#include "RestAPI/ConvaiLTMProxy.h"
|
||||
#include "RestAPI/ConvaiURL.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "Utility/Log/ConvaiLogger.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LTMHttpLogs);
|
||||
|
||||
UConvaiCreateSpeakerID* UConvaiCreateSpeakerID::ConvaiCreateSpeakerIDProxy(FString SpeakerName, FString DeviceId)
|
||||
{
|
||||
UConvaiCreateSpeakerID* Proxy = NewObject<UConvaiCreateSpeakerID>();
|
||||
Proxy->URL = UConvaiURL::GetEndpoint(EConvaiEndpoint::NewSpeaker);
|
||||
Proxy->AssociatedSpeakerName = SpeakerName;
|
||||
Proxy->AssociatedDeviceId = DeviceId;
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
bool UConvaiCreateSpeakerID::ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb)
|
||||
{
|
||||
if (!Super::ConfigureRequest(Request, ConvaiHttpConstants::POST))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UConvaiCreateSpeakerID::AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend)
|
||||
{
|
||||
if (AssociatedSpeakerName.IsEmpty())
|
||||
{
|
||||
CONVAI_LOG(LTMHttpLogs, Error, TEXT("Speaker name is empty"));
|
||||
HandleFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectToSend->SetStringField(TEXT("name"), AssociatedSpeakerName);
|
||||
|
||||
if (!AssociatedDeviceId.IsEmpty())
|
||||
{
|
||||
ObjectToSend->SetStringField(TEXT("deviceId"), AssociatedDeviceId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UConvaiCreateSpeakerID::HandleSuccess()
|
||||
{
|
||||
Super::HandleSuccess();
|
||||
|
||||
TSharedPtr<FJsonObject> JsonObject;
|
||||
const TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(ResponseString);
|
||||
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
|
||||
{
|
||||
JsonObject->TryGetStringField(TEXT("speaker_id"), AssociatedSpeakerInfo.SpeakerID);
|
||||
JsonObject->TryGetStringField(TEXT("name"), AssociatedSpeakerInfo.Name);
|
||||
JsonObject->TryGetStringField(TEXT("device_id"), AssociatedSpeakerInfo.DeviceID);
|
||||
OnSuccess.Broadcast(AssociatedSpeakerInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(LTMHttpLogs, Error, TEXT("Parse Json failed"));
|
||||
HandleFailure();
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiCreateSpeakerID::HandleFailure()
|
||||
{
|
||||
Super::HandleFailure();
|
||||
OnFailure.Broadcast(FConvaiSpeakerInfo());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UConvaiListSpeakerID* UConvaiListSpeakerID::ConvaiListSpeakerIDProxy()
|
||||
{
|
||||
UConvaiListSpeakerID* Proxy = NewObject<UConvaiListSpeakerID>();
|
||||
Proxy->URL = UConvaiURL::GetEndpoint(EConvaiEndpoint::SpeakerIDList);
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
bool UConvaiListSpeakerID::ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb)
|
||||
{
|
||||
if (!Super::ConfigureRequest(Request, ConvaiHttpConstants::POST))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UConvaiListSpeakerID::HandleSuccess()
|
||||
{
|
||||
Super::HandleSuccess();
|
||||
|
||||
TArray<FConvaiSpeakerInfo> SpeakerInfoArray;
|
||||
if (UConvaiLTMUtils::ParseConvaiSpeakerInfoArray(ResponseString, SpeakerInfoArray))
|
||||
{
|
||||
OnSuccess.Broadcast(SpeakerInfoArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(LTMHttpLogs, Error, TEXT("Parse speaker id failed"));
|
||||
HandleFailure();
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiListSpeakerID::HandleFailure()
|
||||
{
|
||||
Super::HandleFailure();
|
||||
OnFailure.Broadcast(TArray<FConvaiSpeakerInfo>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UConvaiDeleteSpeakerID* UConvaiDeleteSpeakerID::ConvaiDeleteSpeakerIDProxy(FString SpeakerID)
|
||||
{
|
||||
UConvaiDeleteSpeakerID* Proxy = NewObject<UConvaiDeleteSpeakerID>();
|
||||
Proxy->URL = UConvaiURL::GetEndpoint(EConvaiEndpoint::DeleteSpeakerID);
|
||||
Proxy->AssociatedSpeakerID = SpeakerID;
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
bool UConvaiDeleteSpeakerID::ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb)
|
||||
{
|
||||
if (!Super::ConfigureRequest(Request, ConvaiHttpConstants::POST))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UConvaiDeleteSpeakerID::AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend)
|
||||
{
|
||||
if (AssociatedSpeakerID.IsEmpty())
|
||||
{
|
||||
HandleFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectToSend->SetStringField(TEXT("speakerId"), AssociatedSpeakerID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UConvaiDeleteSpeakerID::HandleSuccess()
|
||||
{
|
||||
Super::HandleSuccess();
|
||||
OnSuccess.Broadcast(ResponseString);
|
||||
}
|
||||
|
||||
void UConvaiDeleteSpeakerID::HandleFailure()
|
||||
{
|
||||
Super::HandleFailure();
|
||||
OnFailure.Broadcast(TEXT("Http req failed"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UConvaiGetLTMStatus* UConvaiGetLTMStatus::ConvaiGetLTMStatusProxy(FString CharacterID)
|
||||
{
|
||||
UConvaiGetLTMStatus* Proxy = NewObject<UConvaiGetLTMStatus>();
|
||||
Proxy->URL = UConvaiURL::GetEndpoint(EConvaiEndpoint::CharacterGet);
|
||||
Proxy->AssociatedCharacterID = CharacterID;
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
bool UConvaiGetLTMStatus::ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb)
|
||||
{
|
||||
if (!Super::ConfigureRequest(Request, ConvaiHttpConstants::POST))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UConvaiGetLTMStatus::AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend)
|
||||
{
|
||||
if (AssociatedCharacterID.IsEmpty())
|
||||
{
|
||||
HandleFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectToSend->SetStringField(TEXT("charID"), AssociatedCharacterID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UConvaiGetLTMStatus::HandleSuccess()
|
||||
{
|
||||
Super::HandleSuccess();
|
||||
bool bEnabled;
|
||||
if (UConvaiLTMUtils::GetLTMStatus(ResponseString, bEnabled))
|
||||
{
|
||||
OnSuccess.Broadcast(bEnabled);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(LTMHttpLogs, Error, TEXT("GetLTMStatus failed"));
|
||||
HandleFailure();
|
||||
}
|
||||
}
|
||||
|
||||
void UConvaiGetLTMStatus::HandleFailure()
|
||||
{
|
||||
Super::HandleFailure();
|
||||
OnFailure.Broadcast(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UConvaiSetLTMStatus* UConvaiSetLTMStatus::ConvaiSetLTMStatusProxy(FString CharacterID, bool bEnable)
|
||||
{
|
||||
|
||||
UConvaiSetLTMStatus* Proxy = NewObject<UConvaiSetLTMStatus>();
|
||||
Proxy->URL = UConvaiURL::GetEndpoint(EConvaiEndpoint::CharacterUpdate);
|
||||
Proxy->AssociatedCharacterID = CharacterID;
|
||||
Proxy->bAssociatedEnable = bEnable;
|
||||
return Proxy;
|
||||
}
|
||||
|
||||
bool UConvaiSetLTMStatus::ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb)
|
||||
{
|
||||
if (!Super::ConfigureRequest(Request, ConvaiHttpConstants::POST))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UConvaiSetLTMStatus::AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend)
|
||||
{
|
||||
if (AssociatedCharacterID.IsEmpty())
|
||||
{
|
||||
HandleFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectToSend->SetStringField(TEXT("charID"), AssociatedCharacterID);
|
||||
|
||||
TSharedPtr<FJsonObject> MemorySettings = MakeShared<FJsonObject>();
|
||||
MemorySettings->SetBoolField(TEXT("enabled"), bAssociatedEnable);
|
||||
|
||||
ObjectToSend->SetObjectField(TEXT("memorySettings"), MemorySettings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UConvaiSetLTMStatus::HandleSuccess()
|
||||
{
|
||||
Super::HandleSuccess();
|
||||
OnSuccess.Broadcast(ResponseString);
|
||||
}
|
||||
|
||||
void UConvaiSetLTMStatus::HandleFailure()
|
||||
{
|
||||
Super::HandleFailure();
|
||||
OnFailure.Broadcast(ResponseString);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool UConvaiLTMUtils::ParseConvaiSpeakerInfoArray(const FString& JsonString, TArray<FConvaiSpeakerInfo>& OutSpeakerInfoArray)
|
||||
{
|
||||
OutSpeakerInfoArray.Empty();
|
||||
|
||||
const TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
|
||||
TArray<TSharedPtr<FJsonValue>> JsonArray;
|
||||
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonArray))
|
||||
{
|
||||
for (const TSharedPtr<FJsonValue>& JsonValue : JsonArray)
|
||||
{
|
||||
TSharedPtr<FJsonObject> JsonObject = JsonValue->AsObject();
|
||||
if (JsonObject.IsValid())
|
||||
{
|
||||
FConvaiSpeakerInfo SpeakerInfo;
|
||||
JsonObject->TryGetStringField(TEXT("speaker_id"), SpeakerInfo.SpeakerID);
|
||||
JsonObject->TryGetStringField(TEXT("name"), SpeakerInfo.Name);
|
||||
JsonObject->TryGetStringField(TEXT("device_id"), SpeakerInfo.DeviceID);
|
||||
|
||||
OutSpeakerInfoArray.Add(SpeakerInfo);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UConvaiLTMUtils::GetLTMStatus(const FString& JsonString, bool& bEnabled)
|
||||
{
|
||||
bEnabled = false;
|
||||
|
||||
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
|
||||
TSharedPtr<FJsonObject> JsonObject;
|
||||
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
|
||||
{
|
||||
if (JsonObject->HasField(TEXT("memory_settings")))
|
||||
{
|
||||
TSharedPtr<FJsonObject> MemorySettingsObject = JsonObject->GetObjectField(TEXT("memory_settings"));
|
||||
if (MemorySettingsObject.IsValid() && MemorySettingsObject->HasField(TEXT("enabled")))
|
||||
{
|
||||
bEnabled = MemorySettingsObject->GetBoolField(TEXT("enabled"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
157
ConvAI/Convai/Source/Convai/Private/RestAPI/ConvaiURL.cpp
Normal file
157
ConvAI/Convai/Source/Convai/Private/RestAPI/ConvaiURL.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
#include "RestAPI/ConvaiURL.h"
|
||||
#include "Misc/CommandLine.h"
|
||||
#include "../Convai.h"
|
||||
#include "Utility/Log/ConvaiLogger.h"
|
||||
|
||||
// Define static members
|
||||
const TCHAR UConvaiURL::BETA_SUBDOMAIN[] = TEXT("beta");
|
||||
const TCHAR UConvaiURL::PROD_SUBDOMAIN[] = TEXT("api");
|
||||
const TCHAR UConvaiURL::BASE_URL[] = TEXT("https://%s.convai.com/");
|
||||
const TCHAR UConvaiURL::BASE_URL_FORMAT[] = TEXT("https://{0}.convai.com/");
|
||||
|
||||
const TCHAR UConvaiURL::LTM_SUBDOMAIN[] = TEXT("user/speaker/");
|
||||
const TCHAR UConvaiURL::USER_SUBDOMAIN[] = TEXT("user/");
|
||||
const TCHAR UConvaiURL::CHARACTER_SUBDOMAIN[] = TEXT("character/");
|
||||
const TCHAR UConvaiURL::NARRATIVE_DESIGN_SUBDOMAIN[] = TEXT("character/narrative/");
|
||||
|
||||
TArray<EConvaiEndpoint> UConvaiURL::BetaEndpoints;
|
||||
|
||||
FString UConvaiURL::CustomBetaBaseURL = TEXT("");
|
||||
FString UConvaiURL::CustomProdBaseURL = TEXT("");
|
||||
bool UConvaiURL::bURLConfigInitialized = false;
|
||||
|
||||
void UConvaiURL::InitializeURLConfig()
|
||||
{
|
||||
if (bURLConfigInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// First check settings
|
||||
FString SettingsBetaURL = Convai::Get().GetConvaiSettings()->CustomBetaURL;
|
||||
SettingsBetaURL.TrimEndInline();
|
||||
SettingsBetaURL.TrimStartInline();
|
||||
if (!SettingsBetaURL.IsEmpty())
|
||||
{
|
||||
CustomBetaBaseURL = SettingsBetaURL;
|
||||
CONVAI_LOG(LogTemp, Log, TEXT("Using beta URL from settings: %s"), *CustomBetaBaseURL);
|
||||
}
|
||||
|
||||
FString SettingsProdURL = Convai::Get().GetConvaiSettings()->CustomProdURL;
|
||||
SettingsProdURL.TrimEndInline();
|
||||
SettingsProdURL.TrimStartInline();
|
||||
if (!SettingsProdURL.IsEmpty())
|
||||
{
|
||||
CustomProdBaseURL = SettingsProdURL;
|
||||
CONVAI_LOG(LogTemp, Log, TEXT("Using prod URL from settings: %s"), *CustomProdBaseURL);
|
||||
}
|
||||
|
||||
// Then check command line parameters (these will override settings if present)
|
||||
FString BetaURL;
|
||||
if (FParse::Value(FCommandLine::Get(), TEXT("ConvaiBetaURL="), BetaURL))
|
||||
{
|
||||
CustomBetaBaseURL = BetaURL;
|
||||
CONVAI_LOG(LogTemp, Log, TEXT("Using custom beta URL from command line: %s"), *CustomBetaBaseURL);
|
||||
}
|
||||
|
||||
FString ProdURL;
|
||||
if (FParse::Value(FCommandLine::Get(), TEXT("ConvaiProdURL="), ProdURL))
|
||||
{
|
||||
CustomProdBaseURL = ProdURL;
|
||||
CONVAI_LOG(LogTemp, Log, TEXT("Using custom prod URL from command line: %s"), *CustomProdBaseURL);
|
||||
}
|
||||
|
||||
bURLConfigInitialized = true;
|
||||
}
|
||||
|
||||
FString UConvaiURL::GetBaseURL(const bool bUseBeta)
|
||||
{
|
||||
InitializeURLConfig();
|
||||
|
||||
if (bUseBeta)
|
||||
{
|
||||
if (!CustomBetaBaseURL.IsEmpty())
|
||||
{
|
||||
return CustomBetaBaseURL;
|
||||
}
|
||||
return TEXT("https://beta.convai.com");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CustomProdBaseURL.IsEmpty())
|
||||
{
|
||||
return CustomProdBaseURL;
|
||||
}
|
||||
return TEXT("https://api.convai.com");
|
||||
}
|
||||
}
|
||||
|
||||
FString UConvaiURL::GetFullURL(const FString& ApiPath, const bool bUseBeta)
|
||||
{
|
||||
FString BaseURL = GetBaseURL(bUseBeta);
|
||||
|
||||
// Ensure the base URL ends with a slash and the API path doesn't start with one
|
||||
if (!BaseURL.EndsWith(TEXT("/")))
|
||||
{
|
||||
BaseURL += TEXT("/");
|
||||
}
|
||||
|
||||
FString Path = ApiPath;
|
||||
if (Path.StartsWith(TEXT("/")))
|
||||
{
|
||||
Path = Path.RightChop(1);
|
||||
}
|
||||
|
||||
return BaseURL + Path;
|
||||
}
|
||||
|
||||
FString UConvaiURL::GetFormattedBaseURL(const FString& Subdomain)
|
||||
{
|
||||
return FString::Format(BASE_URL_FORMAT, { Subdomain });
|
||||
}
|
||||
|
||||
FString UConvaiURL::GetEndpoint(const EConvaiEndpoint Endpoint)
|
||||
{
|
||||
FString Api;
|
||||
switch (Endpoint)
|
||||
{
|
||||
case EConvaiEndpoint::NewSpeaker:
|
||||
Api = FString(LTM_SUBDOMAIN) + TEXT("new");
|
||||
break;
|
||||
case EConvaiEndpoint::SpeakerIDList:
|
||||
Api = FString(LTM_SUBDOMAIN) + TEXT("list");
|
||||
break;
|
||||
case EConvaiEndpoint::DeleteSpeakerID:
|
||||
Api = FString(LTM_SUBDOMAIN) + TEXT("delete");
|
||||
break;
|
||||
case EConvaiEndpoint::ReferralSourceStatus:
|
||||
Api = FString(USER_SUBDOMAIN) + TEXT("referral-source-status");
|
||||
break;
|
||||
case EConvaiEndpoint::UpdateReferralSource:
|
||||
Api = FString(USER_SUBDOMAIN) + TEXT("update-source");
|
||||
break;
|
||||
case EConvaiEndpoint::UserAPIUsage:
|
||||
Api = FString(USER_SUBDOMAIN) + TEXT("user-api-usage");
|
||||
break;
|
||||
case EConvaiEndpoint::CharacterUpdate:
|
||||
Api = FString(CHARACTER_SUBDOMAIN) + TEXT("update");
|
||||
break;
|
||||
case EConvaiEndpoint::CharacterGet:
|
||||
Api = FString(CHARACTER_SUBDOMAIN) + TEXT("get");
|
||||
break;
|
||||
case EConvaiEndpoint::ListCharacterSections:
|
||||
Api = FString(NARRATIVE_DESIGN_SUBDOMAIN) + TEXT("list-sections");
|
||||
break;
|
||||
case EConvaiEndpoint::ListCharacterTriggers:
|
||||
Api = FString(NARRATIVE_DESIGN_SUBDOMAIN) + TEXT("list-triggers");
|
||||
break;
|
||||
default:
|
||||
CONVAI_LOG(LogTemp, Warning, TEXT("Invalid endpoint!"));
|
||||
return FString();
|
||||
}
|
||||
|
||||
const bool bOnProd = !BetaEndpoints.Contains(Endpoint);
|
||||
const FString Subdomain = bOnProd ? FString(PROD_SUBDOMAIN) : FString(BETA_SUBDOMAIN);
|
||||
|
||||
return GetFormattedBaseURL(Subdomain) + Api;
|
||||
}
|
||||
196
ConvAI/Convai/Source/Convai/Private/Utility/Log/ConvaiLogger.cpp
Normal file
196
ConvAI/Convai/Source/Convai/Private/Utility/Log/ConvaiLogger.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
|
||||
#include "Utility/Log/ConvaiLogger.h"
|
||||
#include "Misc/DateTime.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "HAL/PlatformFileManager.h"
|
||||
#include "HAL/PlatformFile.h"
|
||||
#include "Misc/App.h"
|
||||
#include "HAL/PlatformProcess.h" // for FPlatformProcess
|
||||
#include "HAL/Event.h" // for FEvent methods
|
||||
|
||||
FConvaiLogger &FConvaiLogger::Get()
|
||||
{
|
||||
static FConvaiLogger Instance;
|
||||
return Instance;
|
||||
}
|
||||
|
||||
FConvaiLogger::FConvaiLogger()
|
||||
: Thread(nullptr), WakeEvent(FPlatformProcess::GetSynchEventFromPool(false)), bStopping(false)
|
||||
{
|
||||
StartThread();
|
||||
}
|
||||
|
||||
FConvaiLogger::~FConvaiLogger()
|
||||
{
|
||||
ShutdownThread();
|
||||
if (WakeEvent)
|
||||
{
|
||||
FPlatformProcess::ReturnSynchEventToPool(WakeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void FConvaiLogger::StartThread()
|
||||
{
|
||||
// Logs go in "<ProjectDir>/Saved/ConvaiLogs"
|
||||
const FString LogDir = FPaths::Combine(
|
||||
FPaths::ProjectDir(),
|
||||
TEXT("Saved"),
|
||||
TEXT("ConvaiLogs"));
|
||||
IPlatformFile &Plat = FPlatformFileManager::Get().GetPlatformFile();
|
||||
Plat.CreateDirectoryTree(*LogDir);
|
||||
|
||||
FString PixelStreamingPort=TEXT("Default");
|
||||
FParse::Value(FCommandLine::Get(), TEXT("PixelStreamingPort="), PixelStreamingPort);
|
||||
|
||||
// Build base filename: ProjectName_YYYYMMDD_HHMMSS[_Port]
|
||||
const FString Timestamp = FDateTime::Now().ToString(TEXT("%Y%m%d_%H%M%S"));
|
||||
FString BaseName = FString::Printf(TEXT("%s_%s"),
|
||||
FApp::GetProjectName(),
|
||||
*Timestamp);
|
||||
if (!PixelStreamingPort.IsEmpty())
|
||||
{
|
||||
BaseName += FString::Printf(TEXT("_%s"), *PixelStreamingPort);
|
||||
}
|
||||
|
||||
// 2) Ensure uniqueness by appending _1, _2, ... if file already exists
|
||||
FString FileName = BaseName + TEXT(".log");
|
||||
FString CandidatePath = FPaths::Combine(LogDir, FileName);
|
||||
|
||||
int32 Suffix = 1;
|
||||
while (Plat.FileExists(*CandidatePath))
|
||||
{
|
||||
FileName = FString::Printf(TEXT("%s_%d.log"), *BaseName, Suffix++);
|
||||
CandidatePath = FPaths::Combine(LogDir, FileName);
|
||||
}
|
||||
|
||||
// Finally assign the unique path
|
||||
LogFilePath = CandidatePath;
|
||||
|
||||
// Start the logger thread as before
|
||||
Thread = FRunnableThread::Create(
|
||||
this,
|
||||
TEXT("ConvaiLoggerThread"),
|
||||
0,
|
||||
TPri_BelowNormal);
|
||||
}
|
||||
|
||||
void FConvaiLogger::ShutdownThread()
|
||||
{
|
||||
bStopping = true;
|
||||
if (WakeEvent)
|
||||
WakeEvent->Trigger();
|
||||
|
||||
if (Thread)
|
||||
{
|
||||
Thread->WaitForCompletion();
|
||||
delete Thread;
|
||||
Thread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 FConvaiLogger::Run()
|
||||
{
|
||||
while (!bStopping)
|
||||
{
|
||||
WakeEvent->Wait(500);
|
||||
|
||||
TArray<FString> Batch;
|
||||
FString Msg;
|
||||
while (MessageQueue.Dequeue(Msg))
|
||||
{
|
||||
Batch.Add(Msg);
|
||||
}
|
||||
|
||||
if (Batch.Num())
|
||||
{
|
||||
FString Combined = FString::Join(Batch, TEXT("\n")) + TEXT("\n");
|
||||
IPlatformFile &Plat = FPlatformFileManager::Get().GetPlatformFile();
|
||||
if (IFileHandle *Handle = Plat.OpenWrite(*LogFilePath, /*bAppend=*/true))
|
||||
{
|
||||
FTCHARToUTF8 Converter(*Combined);
|
||||
Handle->Write(reinterpret_cast<const uint8 *>(Converter.Get()), Converter.Length());
|
||||
Handle->Flush();
|
||||
delete Handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
TArray<FString> FinalBatch;
|
||||
FString Rem;
|
||||
while (MessageQueue.Dequeue(Rem))
|
||||
{
|
||||
FinalBatch.Add(Rem);
|
||||
}
|
||||
if (FinalBatch.Num())
|
||||
{
|
||||
const FString Combined = FString::Join(FinalBatch, TEXT("\n")) + TEXT("\n");
|
||||
IPlatformFile &Plat = FPlatformFileManager::Get().GetPlatformFile();
|
||||
if (IFileHandle *Handle = Plat.OpenWrite(*LogFilePath, /*bAppend=*/true))
|
||||
{
|
||||
const FTCHARToUTF8 Converter(*Combined);
|
||||
Handle->Write(reinterpret_cast<const uint8 *>(Converter.Get()), Converter.Length());
|
||||
Handle->Flush();
|
||||
delete Handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FConvaiLogger::Stop()
|
||||
{
|
||||
bStopping = true;
|
||||
}
|
||||
|
||||
void FConvaiLogger::Log(const FString &Message)
|
||||
{
|
||||
const FString Formatted = FString::Printf(
|
||||
TEXT("[%s] %s"),
|
||||
*FDateTime::Now().ToString(TEXT("%H:%M:%S")),
|
||||
*Message);
|
||||
MessageQueue.Enqueue(Formatted);
|
||||
if (WakeEvent)
|
||||
WakeEvent->Trigger();
|
||||
}
|
||||
|
||||
void UConvaiBlueprintLogger::C_ConvaiLog(UObject *WorldContextObject, EC_LogLevel Verbosity, const FString &Message)
|
||||
{
|
||||
const FString ContextName = WorldContextObject
|
||||
? WorldContextObject->GetName()
|
||||
: TEXT("UnknownContext");
|
||||
|
||||
const UEnum *EnumPtr = StaticEnum<EC_LogLevel>();
|
||||
const FString VerbName = EnumPtr
|
||||
? EnumPtr->GetNameStringByValue(static_cast<int64>(Verbosity))
|
||||
: TEXT("UnknownVerbosity");
|
||||
|
||||
const FString FullMessage = FString::Printf(
|
||||
TEXT("%s : %s : %s"),
|
||||
*ContextName, *VerbName, *Message);
|
||||
|
||||
switch (Verbosity)
|
||||
{
|
||||
case EC_LogLevel::Verbose:
|
||||
UE_LOG(LogTemp, Verbose, TEXT("%s"), *FullMessage);
|
||||
break;
|
||||
case EC_LogLevel::Log:
|
||||
UE_LOG(LogTemp, Log, TEXT("%s"), *FullMessage);
|
||||
break;
|
||||
case EC_LogLevel::Warning:
|
||||
UE_LOG(LogTemp, Warning, TEXT("%s"), *FullMessage);
|
||||
break;
|
||||
case EC_LogLevel::Error:
|
||||
UE_LOG(LogTemp, Error, TEXT("%s"), *FullMessage);
|
||||
break;
|
||||
case EC_LogLevel::Fatal:
|
||||
UE_LOG(LogTemp, Fatal, TEXT("%s"), *FullMessage);
|
||||
break;
|
||||
default:
|
||||
UE_LOG(LogTemp, Log, TEXT("%s"), *FullMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
FConvaiLogger::Get().Log(FullMessage);
|
||||
}
|
||||
32
ConvAI/Convai/Source/Convai/Private/getentropy_compact.c
Normal file
32
ConvAI/Convai/Source/Convai/Private/getentropy_compact.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma warning (disable:4668) // 'expression' : signed/unsigned mismatch
|
||||
|
||||
#ifdef PLATFORM_LINUX
|
||||
#if PLATFORM_LINUX
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
int getentropy(void *buffer, size_t length) {
|
||||
if (length > 256) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t result = read(fd, buffer, length);
|
||||
int saved_errno = errno;
|
||||
close(fd);
|
||||
if (result != (ssize_t)length) {
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
40
ConvAI/Convai/Source/Convai/Public/ConvaiActionUtils.h
Normal file
40
ConvAI/Convai/Source/Convai/Public/ConvaiActionUtils.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "ConvaiActionUtils.generated.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiActionUtilsLog, Log, All);
|
||||
|
||||
class UConvaiEnvironment;
|
||||
struct FConvaiResultAction;
|
||||
struct FConvaiObjectEntry;
|
||||
|
||||
|
||||
UCLASS()
|
||||
class UConvaiActions : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
// Function to split a string based on commas, but ignoring commas within quotes
|
||||
static TArray<FString> SmartSplit(const FString& SequenceString);
|
||||
|
||||
// Extract text from an action result (e.g. Says "I love AI" -> I love AI)
|
||||
static FString ExtractText(FString Action, FString ActionResult);
|
||||
|
||||
// Extract number from an action result (e.g. Waits for 5 seconds -> 5)
|
||||
static float ExtractNumber(FString ActionResult);
|
||||
|
||||
static FString FindAction(FString ActionToBeParsed, TArray<FString> Actions);
|
||||
|
||||
// Removes inner descriptions from a string e.g. (Waits for <time in seconds> becomes Waits for)
|
||||
static FString RemoveDesc(FString str);
|
||||
|
||||
static bool ParseAction(UConvaiEnvironment* Environment, FString ActionToBeParsed, FConvaiResultAction& ConvaiResultAction);
|
||||
|
||||
static bool ValidateEnvironment(UConvaiEnvironment* Environment, FString& Error);
|
||||
};
|
||||
25
ConvAI/Convai/Source/Convai/Public/ConvaiAndroid.h
Normal file
25
ConvAI/Convai/Source/Convai/Public/ConvaiAndroid.h
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "ConvaiAndroid.generated.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiAndroidLog, Log, All);
|
||||
|
||||
|
||||
UCLASS()
|
||||
class UConvaiAndroid : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Android|Permissions")
|
||||
static void ConvaiAndroidAskMicrophonePermission();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Android|Permissions")
|
||||
static bool ConvaiAndroidHasMicrophonePermission();
|
||||
};
|
||||
147
ConvAI/Convai/Source/Convai/Public/ConvaiAudioCaptureComponent.h
Normal file
147
ConvAI/Convai/Source/Convai/Public/ConvaiAudioCaptureComponent.h
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AudioCapture.h"
|
||||
#include "Components/SynthComponent.h"
|
||||
#include "AudioCaptureCore.h"
|
||||
#include "AudioCaptureDeviceInterface.h"
|
||||
#include "ConvaiAudioCaptureComponent.generated.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiAudioLog, Log, All);
|
||||
|
||||
namespace Audio
|
||||
{
|
||||
/** Class which contains an FAudioCapture object and performs analysis on the audio stream, only outputing audio if it matches a detection criteria. */
|
||||
class FConvaiAudioCaptureSynth
|
||||
{
|
||||
public:
|
||||
FConvaiAudioCaptureSynth();
|
||||
virtual ~FConvaiAudioCaptureSynth();
|
||||
|
||||
TArray<FCaptureDeviceInfo> GetCaptureDevicesAvailable();
|
||||
|
||||
int32 MapInputDeviceIDToDeviceID(int32 InputDeviceID);
|
||||
|
||||
// Gets the default capture device info
|
||||
bool GetDefaultCaptureDeviceInfo(FCaptureDeviceInfo& OutInfo);
|
||||
|
||||
bool GetCaptureDeviceInfo(FCaptureDeviceInfo& OutInfo, int32 DeviceIndex);
|
||||
|
||||
// Opens up a stream to the default capture device
|
||||
bool OpenDefaultStream();
|
||||
|
||||
bool OpenStream(int32 DeviceIndex);
|
||||
|
||||
void CloseStream();
|
||||
|
||||
// Starts capturing audio
|
||||
bool StartCapturing();
|
||||
|
||||
// Stops capturing audio
|
||||
void StopCapturing();
|
||||
|
||||
// Immediately stop capturing audio
|
||||
void AbortCapturing();
|
||||
|
||||
// Returned if the capture synth is closed
|
||||
bool IsStreamOpen() const;
|
||||
|
||||
// Returns true if the capture synth is capturing audio
|
||||
bool IsCapturing() const;
|
||||
|
||||
// Retrieves audio data from the capture synth.
|
||||
// This returns audio only if there was non-zero audio since this function was last called.
|
||||
bool GetAudioData(TArray<float>& OutAudioData);
|
||||
|
||||
// Returns the number of samples enqueued in the capture synth
|
||||
int32 GetNumSamplesEnqueued();
|
||||
|
||||
FAudioCapture* GetAudioCapture();
|
||||
|
||||
private:
|
||||
|
||||
// Number of samples enqueued
|
||||
int32 NumSamplesEnqueued;
|
||||
|
||||
// Information about the default capture device we're going to use
|
||||
FCaptureDeviceInfo CaptureInfo;
|
||||
|
||||
// Audio capture object dealing with getting audio callbacks
|
||||
FAudioCapture AudioCapture;
|
||||
|
||||
// Critical section to prevent reading and writing from the captured buffer at the same time
|
||||
FCriticalSection CaptureCriticalSection;
|
||||
|
||||
// Buffer of audio capture data, yet to be copied to the output
|
||||
TArray<float> AudioCaptureData;
|
||||
|
||||
// If the object has been initialized
|
||||
bool bInitialized;
|
||||
|
||||
// If we're capturing data
|
||||
bool bIsCapturing;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
UCLASS(ClassGroup = Synth, meta = (BlueprintSpawnableComponent))
|
||||
class UConvaiAudioCaptureComponent : public USynthComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
|
||||
UConvaiAudioCaptureComponent(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
//~ Begin USynthComponent interface
|
||||
virtual bool Init(int32& SampleRate) override;
|
||||
virtual int32 OnGenerateAudio(float* OutAudio, int32 NumSamples) override;
|
||||
virtual void OnBeginGenerate() override;
|
||||
virtual void OnEndGenerate() override;
|
||||
//~ End USynthComponent interface
|
||||
|
||||
//~ Begin UObject interface
|
||||
virtual void BeginDestroy();
|
||||
virtual bool IsReadyForFinishDestroy() override;
|
||||
virtual void FinishDestroy() override;
|
||||
//~ End UObject interface
|
||||
|
||||
public:
|
||||
/**
|
||||
* Induced latency in audio frames to use to account for jitter between mic capture hardware and audio render hardware.
|
||||
* Increasing this number will increase latency but reduce potential for underruns.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Latency", meta = (ClampMin = "0", ClampMax = "1024"))
|
||||
int32 JitterLatencyFrames;
|
||||
|
||||
bool GetDefaultCaptureDeviceInfo(Audio::FCaptureDeviceInfo& OutInfo);
|
||||
|
||||
bool GetCaptureDeviceInfo(Audio::FCaptureDeviceInfo& OutInfo, int32 DeviceIndex);
|
||||
|
||||
TArray<Audio::FCaptureDeviceInfo> GetCaptureDevicesAvailable();
|
||||
|
||||
int32 GetActiveCaptureDevice(Audio::FCaptureDeviceInfo& OutInfo);
|
||||
|
||||
bool SetCaptureDevice(int32 DeviceIndex);
|
||||
|
||||
Audio::FConvaiAudioCaptureSynth* GetCaptureSynth();
|
||||
|
||||
private:
|
||||
int32 SelectedDeviceIndex;
|
||||
|
||||
Audio::FConvaiAudioCaptureSynth CaptureSynth;
|
||||
TArray<float> CaptureAudioData;
|
||||
int32 CapturedAudioDataSamples;
|
||||
|
||||
bool bSuccessfullyInitialized;
|
||||
bool bIsCapturing;
|
||||
bool bIsStreamOpen;
|
||||
int32 CaptureChannels;
|
||||
int32 FramesSinceStarting;
|
||||
int32 ReadSampleIndex;
|
||||
FThreadSafeBool bIsDestroying;
|
||||
FThreadSafeBool bIsNotReadyForForFinishDestroy;
|
||||
};
|
||||
659
ConvAI/Convai/Source/Convai/Public/ConvaiAudioStreamer.h
Normal file
659
ConvAI/Convai/Source/Convai/Public/ConvaiAudioStreamer.h
Normal file
@@ -0,0 +1,659 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
//#include "CoreMinimal.h"
|
||||
// #undef UpdateResource
|
||||
#include "Components/AudioComponent.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "Misc/ScopeLock.h"
|
||||
#include "Interfaces/VoiceCodec.h"
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Templates/UnrealTemplate.h"
|
||||
#include "HAL/PlatformAtomics.h"
|
||||
#include "HAL/PlatformMisc.h"
|
||||
|
||||
#include "ConvaiAudioStreamer.generated.h"
|
||||
|
||||
#define NUM_ENTROPY_VALUES 5
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiAudioStreamerLog, Log, All);
|
||||
|
||||
class USoundWaveProcedural;
|
||||
class IConvaiLipSyncInterface;
|
||||
class IConvaiLipSyncExtendedInterface;
|
||||
class IConvaiVisionInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Template for queues.
|
||||
*
|
||||
* This template implements an unbounded non-intrusive queue using a lock-free linked
|
||||
* list that stores copies of the queued items. The template can operate in two modes:
|
||||
* Multiple-producers single-consumer (MPSC) and Single-producer single-consumer (SPSC).
|
||||
*
|
||||
* The queue is thread-safe in both modes. The Dequeue() method ensures thread-safety by
|
||||
* writing it in a way that does not depend on possible instruction reordering on the CPU.
|
||||
* The Enqueue() method uses an atomic compare-and-swap in multiple-producers scenarios.
|
||||
*
|
||||
* @param T The type of items stored in the queue.
|
||||
* @param Mode The queue mode (single-producer, single-consumer by default).
|
||||
* @todo gmp: Implement node pooling.
|
||||
*/
|
||||
template<typename T, EQueueMode Mode = EQueueMode::Spsc>
|
||||
class TConvaiQueue
|
||||
{
|
||||
public:
|
||||
using FElementType = T;
|
||||
|
||||
/** Default constructor. */
|
||||
TConvaiQueue()
|
||||
{
|
||||
Head = Tail = new TNode();
|
||||
}
|
||||
|
||||
/** Destructor. */
|
||||
~TConvaiQueue()
|
||||
{
|
||||
while (Tail != nullptr)
|
||||
{
|
||||
TNode* Node = Tail;
|
||||
Tail = Tail->NextNode;
|
||||
|
||||
delete Node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and returns the item from the tail of the queue.
|
||||
*
|
||||
* @param OutValue Will hold the returned value.
|
||||
* @return true if a value was returned, false if the queue was empty.
|
||||
* @note To be called only from consumer thread.
|
||||
* @see Empty, Enqueue, IsEmpty, Peek, Pop
|
||||
*/
|
||||
bool Dequeue(FElementType& OutItem)
|
||||
{
|
||||
TNode* Popped = Tail->NextNode;
|
||||
|
||||
if (Popped == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TSAN_AFTER(&Tail->NextNode);
|
||||
OutItem = MoveTemp(Popped->Item);
|
||||
|
||||
TNode* OldTail = Tail;
|
||||
Tail = Popped;
|
||||
Tail->Item = FElementType();
|
||||
delete OldTail;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the queue, discarding all items.
|
||||
*
|
||||
* @note To be called only from consumer thread.
|
||||
* @see Dequeue, IsEmpty, Peek, Pop
|
||||
*/
|
||||
void Empty()
|
||||
{
|
||||
while (Pop());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the head of the queue.
|
||||
*
|
||||
* @param Item The item to add.
|
||||
* @return true if the item was added, false otherwise.
|
||||
* @note To be called only from producer thread(s).
|
||||
* @see Dequeue, Pop
|
||||
*/
|
||||
bool Enqueue(const FElementType& Item)
|
||||
{
|
||||
TNode* NewNode = new TNode(Item);
|
||||
|
||||
if (NewNode == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TNode* OldHead;
|
||||
|
||||
if (Mode == EQueueMode::Mpsc)
|
||||
{
|
||||
OldHead = (TNode*)FPlatformAtomics::InterlockedExchangePtr((void**)&Head, NewNode);
|
||||
TSAN_BEFORE(&OldHead->NextNode);
|
||||
FPlatformAtomics::InterlockedExchangePtr((void**)&OldHead->NextNode, NewNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
OldHead = Head;
|
||||
Head = NewNode;
|
||||
TSAN_BEFORE(&OldHead->NextNode);
|
||||
FPlatformMisc::MemoryBarrier();
|
||||
OldHead->NextNode = NewNode;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the head of the queue.
|
||||
*
|
||||
* @param Item The item to add.
|
||||
* @return true if the item was added, false otherwise.
|
||||
* @note To be called only from producer thread(s).
|
||||
* @see Dequeue, Pop
|
||||
*/
|
||||
bool Enqueue(FElementType&& Item)
|
||||
{
|
||||
TNode* NewNode = new TNode(MoveTemp(Item));
|
||||
|
||||
if (NewNode == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TNode* OldHead;
|
||||
|
||||
if (Mode == EQueueMode::Mpsc)
|
||||
{
|
||||
OldHead = (TNode*)FPlatformAtomics::InterlockedExchangePtr((void**)&Head, NewNode);
|
||||
TSAN_BEFORE(&OldHead->NextNode);
|
||||
FPlatformAtomics::InterlockedExchangePtr((void**)&OldHead->NextNode, NewNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
OldHead = Head;
|
||||
Head = NewNode;
|
||||
TSAN_BEFORE(&OldHead->NextNode);
|
||||
FPlatformMisc::MemoryBarrier();
|
||||
OldHead->NextNode = NewNode;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the queue is empty.
|
||||
*
|
||||
* @return true if the queue is empty, false otherwise.
|
||||
* @note To be called only from consumer thread.
|
||||
* @see Dequeue, Empty, Peek, Pop
|
||||
*/
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return (Tail->NextNode == nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Peeks at the queue's tail item without removing it.
|
||||
*
|
||||
* @param OutItem Will hold the peeked at item.
|
||||
* @return true if an item was returned, false if the queue was empty.
|
||||
* @note To be called only from consumer thread.
|
||||
* @see Dequeue, Empty, IsEmpty, Pop
|
||||
*/
|
||||
bool Peek(FElementType& OutItem) const
|
||||
{
|
||||
if (Tail->NextNode == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
OutItem = Tail->NextNode->Item;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek at the queue's tail item without removing it.
|
||||
*
|
||||
* This version of Peek allows peeking at a queue of items that do not allow
|
||||
* copying, such as TUniquePtr.
|
||||
*
|
||||
* @return Pointer to the item, or nullptr if queue is empty
|
||||
*/
|
||||
FElementType* Peek()
|
||||
{
|
||||
if (Tail->NextNode == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &Tail->NextNode->Item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek at the queue's head item
|
||||
*
|
||||
*
|
||||
* @return Pointer to the item, or nullptr if queue is empty
|
||||
*/
|
||||
FElementType* PeekHead()
|
||||
{
|
||||
if (Tail->NextNode == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &Head->Item;
|
||||
}
|
||||
|
||||
|
||||
FORCEINLINE const FElementType* Peek() const
|
||||
{
|
||||
return const_cast<TConvaiQueue*>(this)->Peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the item from the tail of the queue.
|
||||
*
|
||||
* @return true if a value was removed, false if the queue was empty.
|
||||
* @note To be called only from consumer thread.
|
||||
* @see Dequeue, Empty, Enqueue, IsEmpty, Peek
|
||||
*/
|
||||
bool Pop()
|
||||
{
|
||||
TNode* Popped = Tail->NextNode;
|
||||
|
||||
if (Popped == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TSAN_AFTER(&Tail->NextNode);
|
||||
|
||||
TNode* OldTail = Tail;
|
||||
Tail = Popped;
|
||||
Tail->Item = FElementType();
|
||||
delete OldTail;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** Structure for the internal linked list. */
|
||||
struct TNode
|
||||
{
|
||||
/** Holds a pointer to the next node in the list. */
|
||||
TNode* volatile NextNode;
|
||||
|
||||
/** Holds the node's item. */
|
||||
FElementType Item;
|
||||
|
||||
/** Default constructor. */
|
||||
TNode()
|
||||
: NextNode(nullptr)
|
||||
{ }
|
||||
|
||||
/** Creates and initializes a new node. */
|
||||
explicit TNode(const FElementType& InItem)
|
||||
: NextNode(nullptr)
|
||||
, Item(InItem)
|
||||
{ }
|
||||
|
||||
/** Creates and initializes a new node. */
|
||||
explicit TNode(FElementType&& InItem)
|
||||
: NextNode(nullptr)
|
||||
, Item(MoveTemp(InItem))
|
||||
{ }
|
||||
};
|
||||
|
||||
/** Holds a pointer to the head of the list. */
|
||||
MS_ALIGN(16) TNode* volatile Head GCC_ALIGN(16);
|
||||
|
||||
/** Holds a pointer to the tail of the list. */
|
||||
TNode* Tail;
|
||||
|
||||
private:
|
||||
|
||||
/** Hidden copy constructor. */
|
||||
TConvaiQueue(const TConvaiQueue&) = delete;
|
||||
|
||||
/** Hidden assignment operator. */
|
||||
TConvaiQueue& operator=(const TConvaiQueue&) = delete;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UConvaiAudioStreamer : public UAudioComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE(FOnStartedTalkingSignature, UConvaiAudioStreamer, OnStartedTalking);
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE(FOnFinishedTalkingSignature, UConvaiAudioStreamer, OnFinishedTalking);
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE(FOVRLipSyncVisemesDataReadySignature, UConvaiAudioStreamer, OnVisemesReady);
|
||||
|
||||
public:
|
||||
/** Send the encoded audio from the server to all clients (including the server again) */
|
||||
UFUNCTION(NetMulticast, Reliable, Category = "VoiceNetworking")
|
||||
void BroadcastVoiceDataToClients(TArray<uint8> const& EncodedVoiceData, uint32 SampleRate, uint32 NumChannels, uint32 SizeBeforeEncode);
|
||||
|
||||
/** Send the encoded audio from a client(/server) to the server, it should call at the end BroadcastVoiceDataToClients() */
|
||||
UFUNCTION(Server, Reliable, Category = "VoiceNetworking")
|
||||
virtual void ProcessEncodedVoiceData(TArray<uint8> const& EncodedVoiceData, uint32 SampleRate, uint32 NumChannels, uint32 SizeBeforeEncode);
|
||||
|
||||
/** If we should play audio on same client */
|
||||
virtual bool ShouldMuteLocal();
|
||||
|
||||
/** If we should play audio on other clients */
|
||||
virtual bool ShouldMuteGlobal();
|
||||
|
||||
virtual void OnServerAudioReceived(uint8* VoiceData, uint32 VoiceDataSize, bool ContainsHeaderData = true, uint32 SampleRate = 21000, uint32 NumChannels = 1) {};
|
||||
|
||||
void PlayVoiceSynced(uint8* VoiceData, uint32 VoiceDataSize, bool ContainsHeaderData=true, uint32 SampleRate=21000, uint32 NumChannels=1);
|
||||
|
||||
void PlayVoiceData(uint8* VoiceData, uint32 VoiceDataSize, bool ContainsHeaderData=true, uint32 SampleRate=21000, uint32 NumChannels=1);
|
||||
|
||||
void PlayVoiceData(uint8* VoiceData, uint32 VoiceDataSize, bool ContainsHeaderData, FAnimationSequence FaceSequence, uint32 SampleRate = 21000, uint32 NumChannels = 1);
|
||||
|
||||
//UFUNCTION(BlueprintCallable, Category = "Convai")
|
||||
void ForcePlayVoice(USoundWave* VoiceToPlay);
|
||||
|
||||
void StopVoice();
|
||||
|
||||
void PauseVoice();
|
||||
|
||||
void ResumeVoice();
|
||||
|
||||
void StopVoiceWithFade(float InRemainingVoiceFadeOutTime);
|
||||
|
||||
void ResetVoiceFade();
|
||||
|
||||
void UpdateVoiceFade(float DeltaTime);
|
||||
|
||||
bool IsVoiceCurrentlyFading();
|
||||
|
||||
void ClearAudioFinishedTimer();
|
||||
|
||||
bool IsLocal();
|
||||
|
||||
/** Called when starts to talk */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai")
|
||||
FOnStartedTalkingSignature OnStartedTalking;
|
||||
|
||||
/** Called when stops to talk */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai")
|
||||
FOnFinishedTalkingSignature OnFinishedTalking;
|
||||
|
||||
/** Called when there are LipSync visemes available */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai|LipSync")
|
||||
FOVRLipSyncVisemesDataReadySignature OnVisemesReady;
|
||||
|
||||
IConvaiLipSyncInterface* FindFirstLipSyncComponent();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|LipSync")
|
||||
bool SetLipSyncComponent(UActorComponent* LipSyncComponent);
|
||||
|
||||
/** Returns true, if an LipSync Component was available and attached to the character */
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|LipSync")
|
||||
bool SupportsLipSync();
|
||||
|
||||
IConvaiVisionInterface* FindFirstVisionComponent();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Vision")
|
||||
bool SetVisionComponent(UActorComponent* VisionComponent);
|
||||
|
||||
/** Returns true, if an Vision Component was available and attached to the character */
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Vision")
|
||||
bool SupportsVision();
|
||||
|
||||
bool ReplicateVoiceToNetwork;
|
||||
|
||||
public:
|
||||
// UActorComponent interface
|
||||
virtual void BeginPlay() override;
|
||||
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
// UObject Interface.
|
||||
virtual void BeginDestroy() override;
|
||||
|
||||
public:
|
||||
|
||||
FTimerHandle AudioFinishedTimerHandle;
|
||||
FTimerHandle LypSyncTimeoutTimerHandle;
|
||||
double AudioEndTime = 0.0;
|
||||
bool IsTalking = false;
|
||||
float TotalVoiceFadeOutTime;
|
||||
float RemainingVoiceFadeOutTime;
|
||||
|
||||
UPROPERTY()
|
||||
USoundWaveProcedural* SoundWaveProcedural;
|
||||
|
||||
TArray<uint8> AudioDataBuffer;
|
||||
TArray<uint8> ReceivedEncodedAudioDataBuffer;
|
||||
|
||||
IConvaiLipSyncInterface* ConvaiLipSync;
|
||||
IConvaiVisionInterface* ConvaiVision;
|
||||
|
||||
void PlayLipSyncWithPrecomputedFacialAnimationSynced(FAnimationSequence& FaceSequence);
|
||||
|
||||
void PlayLipSyncWithPrecomputedFacialAnimation(FAnimationSequence FaceSequence);
|
||||
|
||||
void PlayLipSync(uint8* InPCMData, uint32 InPCMDataSize, uint32 InSampleRate, uint32 InNumChannels);
|
||||
|
||||
void StopLipSync();
|
||||
|
||||
void PauseLipSync();
|
||||
|
||||
void ResumeLipSync();
|
||||
|
||||
virtual bool CanUseLipSync();
|
||||
|
||||
virtual void ForceRecalculateLipsyncStartTime();
|
||||
|
||||
virtual bool CanUseVision();
|
||||
|
||||
void OnVisemesReadyCallback();
|
||||
|
||||
void OnLipSyncTimeOut();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|LipSync", Meta = (Tooltip = "Returns last predicted viseme scores"))
|
||||
const TArray<float> GetVisemes() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|LipSync", Meta = (Tooltip = "Returns list of viseme names"))
|
||||
const TArray<FString> GetVisemeNames() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|LipSync", Meta = (Tooltip = "Returns map of blendshapes"))
|
||||
const TMap<FName, float> ConvaiGetFaceBlendshapes() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|LipSync", Meta = (Tooltip = "True if the output visemes is in Blendshape format"))
|
||||
bool GeneratesVisemesAsBlendshapes();
|
||||
|
||||
void AddFaceDataToSend(FAnimationSequence FaceSequence);
|
||||
|
||||
// Should be called in the game thread
|
||||
void AddPCMDataToSend(TArray<uint8> PCMDataToAdd, bool ContainsHeaderData = true, uint32 SampleRate = 21000, uint32 NumChannels = 1);
|
||||
|
||||
virtual void onAudioStarted();
|
||||
virtual void onAudioFinished();
|
||||
|
||||
|
||||
// Add to public section
|
||||
enum class EAudioLipSyncState : uint8
|
||||
{
|
||||
Stopped UMETA(DisplayName = "Stopped"),
|
||||
Playing UMETA(DisplayName = "Playing"),
|
||||
WaitingOnLipSync UMETA(DisplayName = "Waiting On LipSync"),
|
||||
WaitingOnAudio UMETA(DisplayName = "Waiting On Audio")
|
||||
};
|
||||
|
||||
EAudioLipSyncState CurrentState;
|
||||
|
||||
// Simplified buffer structure
|
||||
struct FAudioBuffer
|
||||
{
|
||||
TRingBuffer<uint8> Data;
|
||||
float Duration;
|
||||
uint32 SampleRate;
|
||||
uint32 NumChannels;
|
||||
|
||||
FAudioBuffer() : Duration(0.0f), SampleRate(0), NumChannels(0) {}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Data.Empty();
|
||||
Duration = 0.0f;
|
||||
SampleRate = 0;
|
||||
NumChannels = 0;
|
||||
}
|
||||
|
||||
void Init(uint32 BufferSize)
|
||||
{
|
||||
Data.Init(BufferSize);
|
||||
}
|
||||
|
||||
bool IsEmpty() const { return Data.RingDataUsage() == 0; }
|
||||
|
||||
float GetTotalDuration() const { return Duration; }
|
||||
|
||||
// Add data to the buffer
|
||||
void AppendData(const uint8* NewData, uint32 DataSize)
|
||||
{
|
||||
// Validate input parameters to prevent crashes
|
||||
if (!NewData || DataSize == 0)
|
||||
{
|
||||
return; // Ignore invalid data
|
||||
}
|
||||
Data.Enqueue(NewData, DataSize);
|
||||
}
|
||||
|
||||
// Get data from the buffer (copies to the provided buffer)
|
||||
uint32 GetData(uint8* OutBuffer, uint32 BufferSize) const
|
||||
{
|
||||
return Data.Peek(OutBuffer, BufferSize);
|
||||
}
|
||||
|
||||
// Remove data from the buffer
|
||||
void RemoveData(uint32 BytesToRemove)
|
||||
{
|
||||
// Ensure we don't try to remove more than what's available
|
||||
uint32 BytesToActuallyRemove = FMath::Min(BytesToRemove, Data.RingDataUsage());
|
||||
|
||||
if (BytesToActuallyRemove > 0)
|
||||
{
|
||||
// The TRingBuffer::Dequeue method with nullptr is designed to discard data
|
||||
// without copying it, which is exactly what we want for efficient removal
|
||||
Data.Dequeue(nullptr, BytesToActuallyRemove);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FLipSyncBuffer
|
||||
{
|
||||
TArray<FAnimationSequence> Sequences;
|
||||
float TotalDuration;
|
||||
|
||||
FLipSyncBuffer() : TotalDuration(0.0f) {}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Sequences.Empty();
|
||||
TotalDuration = 0.0f;
|
||||
}
|
||||
|
||||
bool IsEmpty() const { return Sequences.Num() == 0; }
|
||||
|
||||
float GetTotalDuration() const { return TotalDuration; }
|
||||
|
||||
void AddSequence(const FAnimationSequence& Sequence)
|
||||
{
|
||||
Sequences.Add(Sequence);
|
||||
TotalDuration += Sequence.Duration;
|
||||
}
|
||||
};
|
||||
|
||||
FAudioBuffer AudioBuffer;
|
||||
FLipSyncBuffer LipSyncBuffer;
|
||||
|
||||
// Configuration parameters
|
||||
float MinBufferDuration;
|
||||
float AudioLipSyncRatio;
|
||||
float EnableSync;
|
||||
|
||||
// State management functions
|
||||
void TransitionToState(EAudioLipSyncState NewState);
|
||||
void HandleAudioReceived(uint8* AudioData, uint32 AudioDataSize, bool ContainsHeaderData, uint32 SampleRate, uint32 NumChannels);
|
||||
void HandleLipSyncReceived(FAnimationSequence& FaceSequence);
|
||||
bool TryPlayBufferedContent(bool force = false);
|
||||
bool HasSufficientLipSync();
|
||||
bool HasSufficientAudio() const;
|
||||
void PlayBufferedContent(float Duration);
|
||||
|
||||
/**
|
||||
* Returns the duration of content (audio and lipsync if applicable) that is
|
||||
* currently playing or buffered and ready to play.
|
||||
* @return Duration in seconds of content remaining
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|Audio")
|
||||
float GetRemainingContentDuration();
|
||||
|
||||
// Add to protected section
|
||||
// Tracking variables for content
|
||||
float TotalPlayingDuration; // Total duration of content currently being played
|
||||
float TotalBufferedDuration; // Total duration of content buffered but not yet played
|
||||
bool bIsSyncingAudioAndLipSync; // Whether we're syncing audio and lipsync
|
||||
|
||||
private:
|
||||
|
||||
// Critical section for protecting SoundWaveProcedural operations
|
||||
FCriticalSection AudioConfigLock;
|
||||
FThreadSafeBool IsAudioConfiguring;
|
||||
|
||||
// Buffer for pending audio data when lock is held
|
||||
TArray<uint8> PendingAudioBuffer;
|
||||
|
||||
// Process any pending audio data
|
||||
void ProcessPendingAudio();
|
||||
|
||||
bool InitEncoder(int32 InSampleRate, int32 InNumChannels, EAudioEncodeHint EncodeHint);
|
||||
int32 Encode(const uint8* RawPCMData, uint32 RawDataSize, uint8* OutCompressedData, uint32& OutCompressedDataSize);
|
||||
void DestroyOpusEncoder();
|
||||
|
||||
bool InitDecoder(int32 InSampleRate, int32 InNumChannels);
|
||||
void Decode(const uint8* CompressedData, uint32 CompressedDataSize, uint8* OutRawPCMData, uint32& OutRawDataSize);
|
||||
void DestroyOpusDecoder();
|
||||
|
||||
void DestroyOpus();
|
||||
|
||||
/** Sample rate encoding (supports 8000, 12000, 16000, 24000, 480000) */
|
||||
int32 EncoderSampleRate;
|
||||
/** Encoded channel count (supports 1,2) */
|
||||
int32 EncoderNumChannels;
|
||||
/**
|
||||
* Number of samples encoded in a time slice "frame" (must match decoder)
|
||||
* One frame defined as (2.5, 5, 10, 20, 40 or 60 ms) of audio data
|
||||
* Voice encoding lower bound is 10ms (audio goes to 2.5ms).
|
||||
* Voice encoding upper bound is 60ms (audio goes to 20ms).
|
||||
* at 48 kHz the permitted values are 120 (2.5ms), 240 (5ms), 480 (10ms), 960 (20ms), 1920 (40ms), and 2880 (60ms)
|
||||
*/
|
||||
int32 EncoderFrameSize;
|
||||
/** Opus encoder stateful data */
|
||||
struct OpusEncoder* Encoder;
|
||||
/** Last value set in the call to Encode() */
|
||||
uint8 EncoderGeneration;
|
||||
|
||||
|
||||
/** Sample rate to decode into, regardless of encoding (supports 8000, 12000, 16000, 24000, 480000) */
|
||||
int32 DecoderSampleRate;
|
||||
/** Decoded channel count (supports 1,2) */
|
||||
int32 DecoderNumChannels;
|
||||
/**
|
||||
* Number of samples encoded in a time slice (must match encoder)
|
||||
* at 48 kHz the permitted values are 120, 240, 480, 960, 1920, and 2880
|
||||
*/
|
||||
int32 DecoderFrameSize;
|
||||
/** Opus decoder stateful data */
|
||||
struct OpusDecoder* Decoder;
|
||||
/** Generation value received from the last incoming packet */
|
||||
uint8 DecoderLastGeneration;
|
||||
|
||||
// Pre-allocated temporary buffer for audio playback
|
||||
TArray<uint8> TempAudioBuffer;
|
||||
static constexpr uint32 TempBufferSize = 1024 * 1024 * 3; // 3 MB buffer
|
||||
};
|
||||
512
ConvAI/Convai/Source/Convai/Public/ConvaiChatBotProxy.h
Normal file
512
ConvAI/Convai/Source/Convai/Public/ConvaiChatBotProxy.h
Normal file
@@ -0,0 +1,512 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Net/OnlineBlueprintCallProxyBase.h"
|
||||
#include "Http.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "ConvaiChatBotProxy.generated.h"
|
||||
|
||||
|
||||
|
||||
//http log
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiBotHttpLog, Log, All);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FBotQueryHttpResponseCallbackSignature, USoundWave*, AudioContent, FString, BotText, FString, NewSessionID, FString, ClassifiedAction);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams(FBotQueryHttpResponseWithUserTextCallbackSignature, USoundWave*, AudioContent, FString, BotText, FString, UserQuery, FString, NewSessionID, FString, ClassifiedAction);
|
||||
|
||||
class USoundWave;
|
||||
class UTexture2D;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UConvaiChatBotQueryProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotQueryHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotQueryHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
|
||||
/**
|
||||
* @param UserQuery The text input to the character
|
||||
* @param VoiceResponse Whether or not we want a voice response
|
||||
* @param CharID The character ID that we want to get response from
|
||||
* @param SessionID The session ID used to track memory of a previous conversation
|
||||
* @param Classification Whether or not use classification
|
||||
* @param ClassLabels Array of classes to output a class from
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (/*DeprecatedFunction, DeprecationMessage = "Use Send Text in 'Convai Player' component for better latency",*/ BlueprintInternalUseOnly = "true", DisplayName = "DEPRECEATED Convai Chatbot Get Response", WorldContext = "WorldContextObject"), Category = "Convai|DEPRECATED")
|
||||
static UConvaiChatBotQueryProxy* CreateChatBotQueryProxy(UObject* WorldContextObject,
|
||||
FString UserQuery,
|
||||
bool VoiceResponse,
|
||||
FString CharID,
|
||||
FString SessionID,
|
||||
bool Classification,
|
||||
TArray<FString> ClassLabels);
|
||||
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
FString URL;
|
||||
FString UserQuery;
|
||||
bool VoiceResponse;
|
||||
FString CharID;
|
||||
FString SessionID;
|
||||
bool Classification;
|
||||
TArray<FString> ClassLabels;
|
||||
|
||||
// Outputs
|
||||
USoundWave* AudioContent;
|
||||
FString BotText;
|
||||
FString NewSessionID;
|
||||
FString ClassifiedAction;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UConvaiChatBotQueryFromAudioProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotQueryHttpResponseWithUserTextCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotQueryHttpResponseWithUserTextCallbackSignature OnFailure;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a response from a character using a path to an audio file
|
||||
* @param Filename The path to the audio file, it can be relative to the game or an absolute path
|
||||
* @param VoiceResponse Whether or not we want a voice response
|
||||
* @param CharID The character ID that we want to get response from
|
||||
* @param SessionID The session ID used to track memory of a previous conversation
|
||||
* @param Classification Whether or not use classification
|
||||
* @param ClassLabels Array of classes to output a class from
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (/*DeprecatedFunction, DeprecationMessage = "Use Start Talking in 'Convai Player' component for better latency",*/ BlueprintInternalUseOnly = "true", DisplayName = "DEPRECEATED Convai Chatbot Get Response From Audio file", WorldContext = "WorldContextObject"), Category = "Convai|DEPRECATED")
|
||||
static UConvaiChatBotQueryFromAudioProxy* CreateChatBotQueryFromAudioProxy(
|
||||
UObject* WorldContextObject,
|
||||
FString Filename,
|
||||
bool VoiceResponse,
|
||||
FString CharID,
|
||||
FString SessionID,
|
||||
bool Classification,
|
||||
TArray<FString> ClassLabels);
|
||||
|
||||
/**
|
||||
* Get a response from a character using a sound wave
|
||||
* @param SoundWave The audio sound wave
|
||||
* @param VoiceResponse Whether or not we want a voice response
|
||||
* @param CharID The character ID that we want to get response from
|
||||
* @param SessionID The session ID used to track memory of a previous conversation
|
||||
* @param Classification Whether or not use classification
|
||||
* @param ClassLabels Array of classes to output a class from
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (/*DeprecatedFunction, DeprecationMessage = "Use Start Talking in 'Convai Player' component for better latency",*/ BlueprintInternalUseOnly = "true", DisplayName = "DEPRECEATED Convai Chatbot Get Response From SoundWav", WorldContext = "WorldContextObject"), Category = "Convai|DEPRECATED")
|
||||
static UConvaiChatBotQueryFromAudioProxy* CreateChatBotQueryFromSoundWavProxy(
|
||||
UObject* WorldContextObject,
|
||||
USoundWave* SoundWave,
|
||||
bool VoiceResponse,
|
||||
FString CharID,
|
||||
FString SessionID,
|
||||
bool Classification,
|
||||
TArray<FString> ClassLabels);
|
||||
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
FString URL;
|
||||
TArray<uint8> Payload;
|
||||
bool VoiceResponse;
|
||||
FString CharID;
|
||||
FString SessionID;
|
||||
bool Classification;
|
||||
TArray<FString> ClassLabels;
|
||||
|
||||
// Outputs
|
||||
USoundWave* AudioContent;
|
||||
FString BotText;
|
||||
FString UserQuery;
|
||||
FString NewSessionID;
|
||||
FString ClassifiedAction;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBotCreateHttpResponseCallbackSignature, FString, CharID);
|
||||
|
||||
UCLASS()
|
||||
class UConvaiChatBotCreateProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotCreateHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotCreateHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new character and outputs its character ID
|
||||
* @param CharName The character name
|
||||
* @param Voice The voice type to be used
|
||||
* @param Backstory The backstory for the character
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Create Character", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiChatBotCreateProxy* CreateCharacterCreateProxy(UObject* WorldContextObject, FString CharName, FString Voice, FString Backstory);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DeprecatedFunction, DeprecationMessage = "Use \"Convai Create Character\" instead", BlueprintInternalUseOnly = "true", DisplayName = "Convai Get All Chatbots IDs", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiChatBotCreateProxy* CreateChatBotCreateProxy(UObject* WorldContextObject, FString CharName, FString Voice, FString Backstory)
|
||||
{
|
||||
return CreateCharacterCreateProxy(WorldContextObject, CharName, Voice, Backstory);
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
FString URL;
|
||||
FString CharName;
|
||||
FString Voice;
|
||||
FString Backstory;
|
||||
|
||||
|
||||
// Outputs
|
||||
FString CharID;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBotUpdateHttpResponseCallbackSignature);
|
||||
|
||||
UCLASS()
|
||||
class UConvaiChatBotUpdateProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotUpdateHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotUpdateHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Updates an already created character, IMPORTANT: if you do not want to update some property (e.g. Name) then leave it as empty string and it will not update
|
||||
* @param CharID The character's ID that is going to be updated
|
||||
* @param NewVoice The new voice type to be used, leave empty if you do not want to update
|
||||
* @param NewBackstory The new backstory, leave empty if you do not want to update
|
||||
* @param NewCharName The new character name, leave empty if you do not want to update
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Update Character", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiChatBotUpdateProxy* CreateCharacterUpdateProxy(UObject* WorldContextObject, FString CharID, FString NewVoice, FString NewBackstory, FString NewCharName, FString NewLanguage);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DeprecatedFunction, DeprecationMessage = "Use \"Convai Update Character\" instead", BlueprintInternalUseOnly = "true", DisplayName = "Convai Update Chatbot", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiChatBotUpdateProxy* CreateChatBotUpdateProxy(UObject* WorldContextObject, FString CharID, FString NewVoice, FString NewBackstory, FString NewCharName, FString NewLanguage)
|
||||
{
|
||||
return CreateCharacterUpdateProxy(WorldContextObject, CharID, NewVoice, NewBackstory, NewCharName, NewLanguage);
|
||||
}
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
FString URL;
|
||||
FString CharID;
|
||||
FString NewCharName;
|
||||
FString NewVoice;
|
||||
FString NewBackstory;
|
||||
FString NewLanguage;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_SevenParams(FBotGetDetailsHttpResponseCallbackSignature
|
||||
, FString, character_name
|
||||
, FString, voice_type
|
||||
, FString, backstory
|
||||
, FString, LanguageCode
|
||||
, bool, HasReadyPlayerMeLink
|
||||
, FString, ReadyPlayerMeLink
|
||||
, FString, AvatarImageLink);
|
||||
|
||||
UCLASS()
|
||||
class UConvaiChatBotGetDetailsProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotGetDetailsHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotGetDetailsHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initiates a post request to the Character API.
|
||||
* @param CharID The character's ID, you can find it from the Dashboard on the Convai.com website
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Get Character Details", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiChatBotGetDetailsProxy* CreateCharacterGetDetailsProxy(UObject* WorldContextObject, FString CharID);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DeprecatedFunction, DeprecationMessage = "Use \"Convai Get Character Details\" instead", BlueprintInternalUseOnly = "true", DisplayName = "Convai Get All Chatbots IDs", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiChatBotGetDetailsProxy* CreateChatBotGetDetailsProxy(UObject* WorldContextObject, FString CharID)
|
||||
{
|
||||
return CreateCharacterGetDetailsProxy(WorldContextObject, CharID);
|
||||
}
|
||||
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
// inputs
|
||||
FString URL;
|
||||
FString CharID;
|
||||
|
||||
// outputs
|
||||
FString character_name;
|
||||
//FString user_id;
|
||||
FString voice_type;
|
||||
//FString timestamp;
|
||||
FString backstory;
|
||||
FString LanguageCode;
|
||||
bool HasReadyPlayerMeLink;
|
||||
FString ReadyPlayerMeLink;
|
||||
FString AvatarImageLink;
|
||||
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBotGetCharsHttpResponseCallbackSignature, const TArray<FString>&, CharIDs);
|
||||
|
||||
UCLASS()
|
||||
class UConvaiChatBotGetCharsProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotGetCharsHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FBotGetCharsHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
/**
|
||||
* Gets all character IDs created by the user.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Get All Characters IDs", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiChatBotGetCharsProxy* CreateCharacterGetCharsProxy(UObject* WorldContextObject);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DeprecatedFunction, DeprecationMessage = "Use \"Convai Get All Characters IDs\" instead", BlueprintInternalUseOnly = "true", DisplayName = "Convai Get All Chatbots IDs", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiChatBotGetCharsProxy* CreateChatBotGetCharsProxy(UObject* WorldContextObject)
|
||||
{
|
||||
return CreateCharacterGetCharsProxy(WorldContextObject);
|
||||
}
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
FString URL;
|
||||
|
||||
// Outputs
|
||||
TArray<FString> CharIDs;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDownloadImageHttpResponseCallbackSignature, UTexture2D*, Image);
|
||||
|
||||
UCLASS()
|
||||
class UConvaiDownloadImageProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FDownloadImageHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FDownloadImageHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Download Image", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiDownloadImageProxy* CreateDownloadImageProxy(UObject* WorldContextObject, FString URL);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Download Image using RPM Link", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UConvaiDownloadImageProxy* CreateDownloadImageForRPMProxy(UObject* WorldContextObject, FString URL);
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
FString URL;
|
||||
|
||||
// Outputs
|
||||
UTexture2D* Image;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FAvailableVoices
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, category = "Convai|Language")
|
||||
TMap<FString, FVoiceLanguageStruct> AvailableVoices;
|
||||
|
||||
FAvailableVoices()
|
||||
{}
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGetAvailableVoicesCallbackSignature, const FAvailableVoices&, AvailableVoices);
|
||||
|
||||
UCLASS()
|
||||
class UConvaiGetAvailableVoicesProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FGetAvailableVoicesCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FGetAvailableVoicesCallbackSignature OnFailure;
|
||||
|
||||
/**
|
||||
* Gets all available voices.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Get Available Voices"), Category = "Convai|REST API")
|
||||
static UConvaiGetAvailableVoicesProxy* CreateGetAvailableVoicesProxy(EVoiceType VoiceType, ELanguageType LanguageType, EGenderType Gender);
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
|
||||
FString URL;
|
||||
EVoiceType FilterVoiceType;
|
||||
ELanguageType FilterLanguageType;
|
||||
EGenderType FilterGender;
|
||||
|
||||
// Output
|
||||
FAvailableVoices AvailableVoices;
|
||||
|
||||
private:
|
||||
// Helper functions
|
||||
bool ParseAllVoiceData(const FString& JsonString, TMap<FString, FVoiceLanguageStruct>& FilteredVoices);
|
||||
bool ParseVoiceData(TSharedPtr<FJsonObject> JsonObject, FVoiceLanguageStruct& OutVoice);
|
||||
FString GetLanguageCodeFromEnum(ELanguageType LanguageType);
|
||||
FString GetGenderFromEnum(EGenderType GenderType);
|
||||
FString GetVoiceTypeFromEnum(EVoiceType VoiceType);
|
||||
};
|
||||
466
ConvAI/Convai/Source/Convai/Public/ConvaiChatbotComponent.h
Normal file
466
ConvAI/Convai/Source/Convai/Public/ConvaiChatbotComponent.h
Normal file
@@ -0,0 +1,466 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
//#include "CoreMinimal.h"
|
||||
#include "Components/AudioComponent.h"
|
||||
#include "ConvaiAudioStreamer.h"
|
||||
#include "Containers/Map.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
|
||||
#include "ConvaiChatbotComponent.generated.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiChatbotComponentLog, Log, All);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_ThreeParams(FOnTranscriptionReceivedSignature_Deprecated, UConvaiChatbotComponent, OnTranscriptionReceivedEvent, FString, Transcription, bool, IsTranscriptionReady, bool, IsFinal);
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SixParams(FOnTranscriptionReceivedSignature_V2, UConvaiChatbotComponent, OnTranscriptionReceivedEvent_V2, UConvaiChatbotComponent*, ChatbotComponent, UConvaiPlayerComponent*, InteractingPlayerComponent, FString, PlayerName, FString, Transcription, bool, IsTranscriptionReady, bool, IsFinal);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FourParams(FOnTextReceivedSignature_Deprecated, UConvaiChatbotComponent, OnTextReceivedEvent, FString, CharacterName, FString, BotText, float, AudioDuration, bool, IsFinal);
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SixParams(FOnTextReceivedSignature_V2, UConvaiChatbotComponent, OnTextReceivedEvent_V2, UConvaiChatbotComponent*, ChatbotComponent, UConvaiPlayerComponent*, InteractingPlayerComponent, FString, CharacterName, FString, BotText, float, AudioDuration, bool, IsFinal);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_OneParam(FOnActionReceivedSignature_Deprecated, UConvaiChatbotComponent, OnActionReceivedEvent, const TArray<FConvaiResultAction>&, SequenceOfActions);
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_ThreeParams(FOnActionReceivedSignature_V2, UConvaiChatbotComponent, OnActionReceivedEvent_V2, UConvaiChatbotComponent*, ChatbotComponent, UConvaiPlayerComponent*, InteractingPlayerComponent, const TArray<FConvaiResultAction>&, SequenceOfActions);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_TwoParams(FOnEmotionReceivedSignature, UConvaiChatbotComponent, OnEmotionStateChangedEvent, UConvaiChatbotComponent*, ChatbotComponent, UConvaiPlayerComponent*, InteractingPlayerComponent);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_OneParam(FOnCharacterDataLoadSignature_Deprecated, UConvaiChatbotComponent, OnCharacterDataLoadEvent, bool, Success);
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_TwoParams(FOnCharacterDataLoadSignature_V2, UConvaiChatbotComponent, OnCharacterDataLoadEvent_V2, UConvaiChatbotComponent*, ChatbotComponent, bool, Success);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_TwoParams(FOnNarrativeSectionReceivedSignature, UConvaiChatbotComponent, OnNarrativeSectionReceivedEvent, UConvaiChatbotComponent*, ChatbotComponent, FString, NarrativeSectionID);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_ThreeParams(FOnInteractionIDReceivedSignature, UConvaiChatbotComponent, OnInteractionIDReceivedEvent, UConvaiChatbotComponent*, ChatbotComponent, UConvaiPlayerComponent*, InteractingPlayerComponent, FString, InteractionID);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE(FOnFailureSignature, UConvaiChatbotComponent, OnFailureEvent);
|
||||
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_TwoParams(FOnInterruptedSignature, UConvaiChatbotComponent, OnInterruptedEvent, UConvaiChatbotComponent*, ChatbotComponent, UConvaiPlayerComponent*, InteractingPlayerComponent);
|
||||
|
||||
// TODO (Mohamed): Manage onDestroy/onEndPlay - should end any on-going streams
|
||||
|
||||
class UConvaiPlayerComponent;
|
||||
class USoundWaveProcedural;
|
||||
class UConvaiGRPCGetResponseProxy;
|
||||
class UConvaiChatBotGetDetailsProxy;
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType, meta = (BlueprintSpawnableComponent), DisplayName = "Convai Chatbot")
|
||||
class CONVAI_API UConvaiChatbotComponent : public UConvaiAudioStreamer
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UConvaiChatbotComponent();
|
||||
|
||||
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
|
||||
/**
|
||||
* Returns true, if the character is being talked to, is talking, or is processing the response.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai")
|
||||
bool IsInConversation();
|
||||
|
||||
/**
|
||||
* Returns true, if the character is still processing and has not received the full response yet.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai", meta = (DisplayName = "Is Thinking"))
|
||||
bool IsProcessing();
|
||||
|
||||
/**
|
||||
* Returns true, if the character is currently listening to a player.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai")
|
||||
bool IsListening();
|
||||
|
||||
/**
|
||||
* Returns true, if the character is currently talking.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai", meta = (DisplayName = "Is Talking"))
|
||||
bool GetIsTalking();
|
||||
|
||||
/** Returns time elapsed since the character started talking */
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Voice")
|
||||
float GetTalkingTimeElapsed();
|
||||
|
||||
/** Returns time remaining audio time for the character to speak */
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Voice")
|
||||
float GetTalkingTimeRemaining();
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Convai", Replicated, BlueprintSetter = LoadCharacter)
|
||||
FString CharacterID;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Convai", Replicated)
|
||||
FString CharacterName;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Convai", Replicated)
|
||||
FString VoiceType;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Convai", Replicated)
|
||||
FString Backstory;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Convai", Replicated)
|
||||
FString LanguageCode;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Convai", Replicated)
|
||||
FString ReadyPlayerMeLink;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Convai", Replicated)
|
||||
FString AvatarImageLink;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Convai", Replicated, meta = (DisplayName = "Interacting Player"))
|
||||
UConvaiPlayerComponent* CurrentConvaiPlayerComponent;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Convai|Actions", Replicated)
|
||||
TArray<FConvaiResultAction> ActionsQueue;
|
||||
|
||||
UPROPERTY(Replicated)
|
||||
FConvaiEmotionState EmotionState;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Convai|Emotion", Replicated)
|
||||
bool LockEmotionState = false;
|
||||
|
||||
/**
|
||||
* Used to track memory of a previous conversation, set to -1 means no previous conversation,
|
||||
* this property will change as you talk to the character, you can save the session ID for a
|
||||
* conversation and then set it back later on to resume a conversation
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Convai", Replicated)
|
||||
FString SessionID = "-1";
|
||||
|
||||
/**
|
||||
* Contains all relevant objects and characters in the scene including the (Player), and also all the actions doable by the character
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, Category = "Convai", BlueprintSetter = LoadEnvironment)
|
||||
UConvaiEnvironment* Environment;
|
||||
|
||||
/**
|
||||
* Time in seconds, for the character's voice audio to gradually degrade until it is completely turned off when interrupted.
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Convai")
|
||||
float InterruptVoiceFadeOutDuration;
|
||||
|
||||
/**
|
||||
* Value between -1 and 1, a value greater than zero over extends the emotions strength and a value less than zero dimishes it.
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Convai")
|
||||
float EmotionOffset = 0;
|
||||
|
||||
/**
|
||||
* Contains key value pairs used for Narrative Design.
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Convai|NarrativeDesign")
|
||||
TMap<FString, FString> NarrativeTemplateKeys;
|
||||
|
||||
/**
|
||||
* Extra information that can be passed to the character, can contain any important data that the chracter needs to know about without the
|
||||
* need of player interaction or narrative triggers, e.g. Inventory items, Player health, key information to solve a puzzle, time of day, etc...
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Convai")
|
||||
FString DynamicEnvironmentInfo;
|
||||
|
||||
/**
|
||||
* Speaker ID used for long term memory (LTM)
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Convai")
|
||||
FString SpeakerID;
|
||||
|
||||
/**
|
||||
* Reset the conversation with the character and remove previous memory, this is the same as setting the session ID property to -1.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai")
|
||||
void ResetConversation();
|
||||
|
||||
/**
|
||||
* Loads a new character using its ID
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintInternalUseOnly, Category = "Convai")
|
||||
void LoadCharacter(FString NewCharacterID);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintInternalUseOnly, Category = "Convai")
|
||||
void LoadEnvironment(UConvaiEnvironment* NewConvaiEnvironment);
|
||||
|
||||
/**
|
||||
* Appends a TArray of FConvaiResultAction items to the existing ActionsQueue.
|
||||
* If ActionsQueue is not empty, it takes the first element, appends the new array to it,
|
||||
* and then reassigns it back to ActionsQueue. If ActionsQueue is empty, it simply sets ActionsQueue to the new array.
|
||||
*
|
||||
* @param NewActions Array of FConvaiResultAction items to be appended.
|
||||
*
|
||||
* @category Convai
|
||||
*/
|
||||
void AppendActionsToQueue(TArray<FConvaiResultAction> NewActions);
|
||||
|
||||
/**
|
||||
* Marks the current action as completed and handles post-execution logic.
|
||||
*
|
||||
* @param IsSuccessful A boolean flag indicating whether the executed action was successful or not. If true, the next action in the queue will be processed. If false, the current action will be retried.
|
||||
* @param Delay A float value representing the time in seconds to wait before attempting either the next action or retrying the current action, depending on the value of IsSuccessful.
|
||||
*
|
||||
* @note This function should be invoked after each action execution to manage the action queue.
|
||||
*
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Actions")
|
||||
void HandleActionCompletion(bool IsSuccessful, float Delay);
|
||||
|
||||
/**
|
||||
* Checks if the ActionsQueue managed by the Convai chatbot component is empty.
|
||||
*
|
||||
* @return Returns true if the ActionsQueue is empty; otherwise, returns false.
|
||||
*
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Convai|Actions")
|
||||
bool IsActionsQueueEmpty();
|
||||
|
||||
/**
|
||||
* Clears the ActionsQueue managed by the Convai chatbot component.
|
||||
*
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Actions")
|
||||
void ClearActionQueue();
|
||||
|
||||
/**
|
||||
* Fetches the first action from the ActionsQueue managed by the Convai chatbot component.
|
||||
*
|
||||
* @param ConvaiResultAction Reference to a struct that will be populated with the details of the first action in the queue.
|
||||
*
|
||||
* @return Returns true if there is at least one action in the ActionsQueue and the struct has been successfully populated; otherwise, returns false.
|
||||
*
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Convai|Actions")
|
||||
bool FetchFirstAction(FConvaiResultAction& ConvaiResultAction);
|
||||
|
||||
/**
|
||||
* Removes the first action from the ActionsQueue managed by the Convai chatbot component.
|
||||
*
|
||||
* @return Returns true if an action was successfully removed; otherwise, returns false.
|
||||
*
|
||||
*/
|
||||
bool DequeueAction();
|
||||
|
||||
/**
|
||||
* Starts executing the first action in the ActionsQueue by calling TriggerNamedBlueprintAction.
|
||||
*
|
||||
* @return Returns true if the first action was successfully started; otherwise, returns false.
|
||||
*
|
||||
*/
|
||||
UFUNCTION()
|
||||
bool StartFirstAction();
|
||||
|
||||
/**
|
||||
* Triggers a specified Blueprint event or function on the owning actor based on the given action name and parameters.
|
||||
*
|
||||
* @param ActionName The name of the Blueprint event or function to trigger. This event or function should exist in the Blueprint that owns this component.
|
||||
* @param ConvaiActionStruct A struct containing additional data or parameters to pass to the Blueprint event or function.
|
||||
*
|
||||
* @note The function attempts to dynamically find and call a Blueprint event or function in the owning actor's class. If the Blueprint event or function does not exist or if the signature doesn't match, the function will log a warning.
|
||||
*
|
||||
*/
|
||||
bool TriggerNamedBlueprintAction(const FString& ActionName, FConvaiResultAction ConvaiActionStruct);
|
||||
bool TryCallFunction(UObject* Object, const FString& FunctionName, FConvaiResultAction& ConvaiResultAction) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Emotion")
|
||||
void ForceSetEmotion(EBasicEmotions BasicEmotion, EEmotionIntensity Intensity, bool ResetOtherEmotions = false);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Convai|Emotion")
|
||||
float GetEmotionScore(EBasicEmotions Emotion);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Convai|Emotion")
|
||||
TMap<FName, float> GetEmotionBlendshapes();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Emotion")
|
||||
void ResetEmotionState();
|
||||
|
||||
public:
|
||||
// UFUNCTION(BlueprintCallable, Category = "Convai|Voice")
|
||||
void StartRecordingVoice();
|
||||
|
||||
// UFUNCTION(BlueprintCallable, Category = "Convai|Voice")
|
||||
USoundWave* FinishRecordingVoice();
|
||||
|
||||
// UFUNCTION(BlueprintCallable, Category = "Convai|Voice")
|
||||
bool PlayRecordedVoice(USoundWave* RecordedVoice);
|
||||
|
||||
public:
|
||||
/** Called when a new action is received from the API */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "_DEPRECATED On Actions Received"))
|
||||
FOnActionReceivedSignature_Deprecated OnActionReceivedEvent;
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "On Actions Received"))
|
||||
FOnActionReceivedSignature_V2 OnActionReceivedEvent_V2;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "On Emotion State Changed"))
|
||||
FOnEmotionReceivedSignature OnEmotionStateChangedEvent;
|
||||
|
||||
/** Called when new text is received from the API, AudioDuration = 0 if no audio was received */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "_DEPRECATED On Text Received"))
|
||||
FOnTextReceivedSignature_Deprecated OnTextReceivedEvent;
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "On Text Received"))
|
||||
FOnTextReceivedSignature_V2 OnTextReceivedEvent_V2;
|
||||
|
||||
/** Called when new transcription is available */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "_DEPRECATED On Transcription Received"))
|
||||
FOnTranscriptionReceivedSignature_Deprecated OnTranscriptionReceivedEvent;
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "On Transcription Received"))
|
||||
FOnTranscriptionReceivedSignature_V2 OnTranscriptionReceivedEvent_V2;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "_DEPRECATED On Character Data Loaded"))
|
||||
FOnCharacterDataLoadSignature_Deprecated OnCharacterDataLoadEvent;
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "On Character Data Loaded"))
|
||||
FOnCharacterDataLoadSignature_V2 OnCharacterDataLoadEvent_V2;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "On Narrative Section Received"))
|
||||
FOnNarrativeSectionReceivedSignature OnNarrativeSectionReceivedEvent;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "On Interaction ID Received"))
|
||||
FOnInteractionIDReceivedSignature OnInteractionIDReceivedEvent;
|
||||
|
||||
/** Called when the character is interrupted */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "On Interrupted"))
|
||||
FOnInterruptedSignature OnInterruptedEvent;
|
||||
|
||||
/** Called when there is an error */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Convai", meta = (DisplayName = "On Failure"))
|
||||
FOnFailureSignature OnFailureEvent;
|
||||
|
||||
public:
|
||||
//UFUNCTION(BlueprintCallable, DisplayName = "Begin Transmission")
|
||||
void StartGetResponseStream(UConvaiPlayerComponent* InConvaiPlayerComponent, FString InputText, UConvaiEnvironment* InEnvironment, bool InGenerateActions, bool InVoiceResponse, bool ReplicateVoiceToNetwork, bool UseOverrideAuthKey, FString OverrideAuthKey, FString OverrideAuthHeader, uint32 InToken, FString InSpeakerID);
|
||||
|
||||
void FinishGetResponseStream(UConvaiPlayerComponent* InConvaiPlayerComponent);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai", meta = (DisplayName = "Invoke Speech"))
|
||||
void ExecuteNarrativeTrigger(FString TriggerMessage, UConvaiEnvironment* InEnvironment, bool InGenerateActions, bool InVoiceResponse, bool InReplicateOnNetwork);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai", meta = (DisplayName = "Invoke Narrative Design Trigger"))
|
||||
void InvokeNarrativeDesignTrigger(FString TriggerName, UConvaiEnvironment* InEnvironment, bool InGenerateActions, bool InVoiceResponse, bool InReplicateOnNetwork);
|
||||
|
||||
void InvokeTrigger_Internal(FString TriggerName, FString TriggerMessage, UConvaiEnvironment* InEnvironment, bool InGenerateActions, bool InVoiceResponse, bool InReplicateOnNetwork);
|
||||
|
||||
// Interrupts the current speech with a provided fade-out duration.
|
||||
// The fade-out duration is controlled by the parameter 'InVoiceFadeOutDuration'.
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai")
|
||||
void InterruptSpeech(float InVoiceFadeOutDuration);
|
||||
|
||||
// Trys to clear the Interacting player variable if there were no conversation going
|
||||
// If Force clear was true, it will interrupt the conversation and clear the interacting player
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai")
|
||||
void TryClearInteractingPlayer(bool& Success, bool Interrupt);
|
||||
|
||||
// Broadcasts an interruption of the current speech across a network, with a provided fade-out duration.
|
||||
// This function ensures that the interruption is communicated reliably to all connected clients.
|
||||
// The fade-out duration is controlled by the parameter 'InVoiceFadeOutDuration'.
|
||||
UFUNCTION(NetMulticast, Reliable, Category = "VoiceNetworking")
|
||||
void Broadcast_InterruptSpeech(float InVoiceFadeOutDuration);
|
||||
|
||||
public:
|
||||
// AActorComponent interface
|
||||
virtual void BeginPlay() override;
|
||||
//virtual void OnRegister() override;
|
||||
//virtual void OnUnregister() override;
|
||||
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
// End AActorComponent interface
|
||||
|
||||
//~ Begin UObject Interface.
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
virtual void BeginDestroy() override;
|
||||
//~ End UObject Interface.
|
||||
|
||||
//~ Begin UConvaiAudioStreamer Interface.
|
||||
virtual bool CanUseLipSync() override;
|
||||
virtual bool CanUseVision() override;
|
||||
//~ End UConvaiAudioStreamer Interface.
|
||||
|
||||
private:
|
||||
UConvaiChatBotGetDetailsProxy* ConvaiGetDetails();
|
||||
|
||||
TScriptDelegate<FWeakObjectPtr> ConvaiChatBotGetDetailsDelegate;
|
||||
|
||||
UFUNCTION()
|
||||
void OnConvaiGetDetailsCompleted(FString ReceivedCharacterName, FString ReceivedVoiceType, FString ReceivedBackstory, FString ReceivedLanguageCode, bool HasReadyPlayerMeLink, FString ReceivedReadyPlayerMeLink, FString ReceivedAvatarImageLink);
|
||||
|
||||
private:
|
||||
// Used when both the voice component ring buffer is empty and we have already sent all the current audio data over the stream
|
||||
void onMicrophoneDataReceived();
|
||||
|
||||
// Returns false if the player has decided to stop sending audio
|
||||
bool CheckTokenValidity();
|
||||
|
||||
// Called when a player time outs while sending audio data (for example 2 secs have passed without us getting any audio from him)
|
||||
void OnPlayerTimeOut();
|
||||
|
||||
void ClearTimeOutTimer();
|
||||
|
||||
bool HasOnGoingGetResponseStream();
|
||||
|
||||
bool CanWriteToGetResponseStream();
|
||||
|
||||
bool ConsumeMicStreamIntoBuffer();
|
||||
|
||||
private:
|
||||
void Start_GRPC_Request(bool UseOverrideAuthKey, FString OverrideAuthKey, FString OverrideAuthHeader, FString TriggerName = "", FString TriggerMessage = "");
|
||||
|
||||
void Bind_GRPC_Request_Delegates();
|
||||
|
||||
void Unbind_GRPC_Request_Delegates();
|
||||
|
||||
void Cleanup(bool StreamConnectionFinished = false);
|
||||
|
||||
private:
|
||||
UFUNCTION(NetMulticast, Reliable, Category = "Convai")
|
||||
void Broadcast_OnTranscriptionReceived(const FString& Transcription, bool IsTranscriptionReady, bool IsFinal);
|
||||
UFUNCTION(NetMulticast, Reliable, Category = "Convai")
|
||||
void Broadcast_onResponseDataReceived(const FString& ReceivedText, bool IsFinal);
|
||||
UFUNCTION(NetMulticast, Reliable, Category = "Convai")
|
||||
void Broadcast_onSessionIDReceived(const FString& ReceivedSessionID);
|
||||
UFUNCTION(NetMulticast, Reliable, Category = "Convai")
|
||||
void Broadcast_onActionSequenceReceived(const TArray<FConvaiResultAction>& ReceivedSequenceOfActions);
|
||||
UFUNCTION(NetMulticast, Reliable, Category = "Convai")
|
||||
void Broadcast_OnNarrativeSectionReceived(const FString& BT_Code, const FString& BT_Constants, const FString& ReceivedNarrativeSectionID);
|
||||
UFUNCTION(NetMulticast, Reliable, Category = "Convai")
|
||||
void Broadcast_onInteractionIDReceived(const FString& ReceivedInteractionID);
|
||||
UFUNCTION(NetMulticast, Reliable, Category = "Convai")
|
||||
void Broadcast_onEmotionReceived(const FString& ReceivedEmotionResponse, bool MultipleEmotions);
|
||||
|
||||
void OnTranscriptionReceived(FString Transcription, bool IsTranscriptionReady, bool IsFinal);
|
||||
void onResponseDataReceived(const FString ReceivedText, const TArray<uint8>& ReceivedAudio, uint32 SampleRate, bool IsFinal);
|
||||
void OnFaceDataReceived(FAnimationSequence FaceDataAnimation);
|
||||
void onSessionIDReceived(FString ReceivedSessionID);
|
||||
void onInteractionIDReceived(FString ReceivedInteractionID);
|
||||
void onActionSequenceReceived(const TArray<FConvaiResultAction>& ReceivedSequenceOfActions);
|
||||
void onEmotionReceived(FString ReceivedEmotionResponse, FAnimationFrame EmotionBlendshapesFrame, bool MultipleEmotions);
|
||||
void onFinishedReceivingData();
|
||||
void OnNarrativeSectionReceived(FString BT_Code, FString BT_Constants, FString ReceivedNarrativeSectionID);
|
||||
void onFailure();
|
||||
|
||||
private:
|
||||
UPROPERTY(Replicated, ReplicatedUsing = OnRep_EnvironmentData)
|
||||
FConvaiEnvironmentDetails ConvaiEnvironmentDetails;
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_EnvironmentData();
|
||||
|
||||
void UpdateEnvironmentData();
|
||||
|
||||
private:
|
||||
UPROPERTY()
|
||||
UConvaiChatBotGetDetailsProxy* ConvaiChatBotGetDetailsProxy;
|
||||
|
||||
UPROPERTY()
|
||||
UConvaiGRPCGetResponseProxy* ConvaiGRPCGetResponseProxy;
|
||||
|
||||
bool GenerateActions; // Should we generate actions
|
||||
bool TextInput; // Whether to use text or audio as input to the API
|
||||
bool VoiceResponse; // Require audio response from the API
|
||||
FString UserText; // Input text to send to the API in case of TextInput is set to true
|
||||
uint32 Token; // Used to check if the Convai player component is still streaming to us
|
||||
|
||||
bool StreamInProgress = false; // Are we receiving mic audio from player?
|
||||
FTimerHandle TimeOutTimerHandle; // Timeout handler for player not sending audio data through mic
|
||||
|
||||
FString LastTranscription;
|
||||
bool ReceivedFinalTranscription;
|
||||
bool ReceivedFinalData; // Did the character end his response
|
||||
FString LastPlayerName;
|
||||
TArray<uint8> PlayerInpuAudioBuffer;
|
||||
|
||||
TMap<FName, float> EmotionBlendshapes;
|
||||
float TotalReceivedAudioDuration = 0;
|
||||
|
||||
TArray<uint8> RecordedAudio;
|
||||
uint32 RecordedAudioSampleRate;
|
||||
bool IsRecordingAudio;
|
||||
};
|
||||
1094
ConvAI/Convai/Source/Convai/Public/ConvaiDefinitions.h
Normal file
1094
ConvAI/Convai/Source/Convai/Public/ConvaiDefinitions.h
Normal file
File diff suppressed because it is too large
Load Diff
108
ConvAI/Convai/Source/Convai/Public/ConvaiFaceSync.h
Normal file
108
ConvAI/Convai/Source/Convai/Public/ConvaiFaceSync.h
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LipSyncInterface.h"
|
||||
|
||||
#include "Components/SceneComponent.h"
|
||||
#include "Containers/Map.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "ConvaiFaceSync.generated.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiFaceSyncLog, Log, All);
|
||||
|
||||
UCLASS(meta = (BlueprintSpawnableComponent), DisplayName = "Convai Face Sync")
|
||||
class CONVAI_API UConvaiFaceSyncComponent : public USceneComponent, public IConvaiLipSyncInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UConvaiFaceSyncComponent();
|
||||
|
||||
virtual ~UConvaiFaceSyncComponent();
|
||||
|
||||
// UActorComponent interface
|
||||
virtual void BeginPlay() override;
|
||||
// virtual void OnRegister() override;
|
||||
// virtual void OnUnregister() override;
|
||||
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction) override;
|
||||
// End UActorComponent interface
|
||||
|
||||
// IConvaiLipSyncInterface
|
||||
virtual void ConvaiInferFacialDataFromAudio(uint8* InPCMData, uint32 InPCMDataSize, uint32 InSampleRate, uint32 InNumChannels) override { return; }
|
||||
virtual void ConvaiStopLipSync() override;
|
||||
virtual TArray<float> ConvaiGetVisemes() override
|
||||
{
|
||||
TArray<float> VisemeValues;
|
||||
CurrentBlendShapesMap.GenerateValueArray(VisemeValues);
|
||||
return VisemeValues;
|
||||
}
|
||||
virtual TArray<FString> ConvaiGetVisemeNames() override { return ConvaiConstants::VisemeNames; }
|
||||
// End IConvaiLipSyncInterface interface
|
||||
|
||||
// IConvaiLipSyncExtendedInterface
|
||||
virtual void ConvaiApplyPrecomputedFacialAnimation(uint8* InPCMData, uint32 InPCMDataSize, uint32 InSampleRate, uint32 InNumChannels, FAnimationSequence FaceSequence) override;
|
||||
virtual void ConvaiApplyFacialFrame(FAnimationFrame FaceFrame, float Duration) override;
|
||||
virtual bool RequiresPrecomputedFaceData() override { return true; }
|
||||
virtual bool GeneratesVisemesAsBlendshapes() override { return ToggleBlendshapeOrViseme; }
|
||||
virtual TMap<FName, float> ConvaiGetFaceBlendshapes() override { return CurrentBlendShapesMap; }
|
||||
// End IConvaiLipSyncExtendedInterface interface
|
||||
|
||||
virtual void Apply_StartEndFrames_PostProcessing(const int& CurrentFrameIndex, const int& NextFrameIndex, float& Alpha, TMap<FName, float>& StartFrame, TMap<FName, float>& EndFrame){}
|
||||
virtual void ApplyPostProcessing() {}
|
||||
|
||||
// UFUNCTION(BlueprintCallable, Category = "Convai|LipSync")
|
||||
void StartRecordingLipSync();
|
||||
|
||||
// UFUNCTION(BlueprintCallable, Category = "Convai|LipSync")
|
||||
FAnimationSequenceBP FinishRecordingLipSync();
|
||||
|
||||
// UFUNCTION(BlueprintCallable, Category = "Convai|LipSync")
|
||||
bool PlayRecordedLipSync(FAnimationSequenceBP RecordedLipSync, int StartFrame, int EndFrame, float OverwriteDuration);
|
||||
|
||||
bool IsValidSequence(const FAnimationSequence &Sequence);
|
||||
|
||||
bool IsPlaying();
|
||||
|
||||
// Record the current time if this is the first LipSync sequence to be received after silence
|
||||
virtual void CalculateStartingTime();
|
||||
|
||||
virtual void ForceRecalculateStartTime() override;
|
||||
|
||||
void ClearMainSequence();
|
||||
|
||||
TMap<FName, float> InterpolateFrames(const TMap<FName, float>& StartFrame, const TMap<FName, float>& EndFrame, float Alpha);
|
||||
|
||||
TMap<FName, float> GenerateZeroFrame() { return GeneratesVisemesAsBlendshapes() ? ZeroBlendshapeFrame : ZeroVisemeFrame; }
|
||||
|
||||
void SetCurrentFrametoZero()
|
||||
{
|
||||
if (GeneratesVisemesAsBlendshapes())
|
||||
CurrentBlendShapesMap = ZeroBlendshapeFrame;
|
||||
else
|
||||
CurrentBlendShapesMap = ZeroVisemeFrame;
|
||||
}
|
||||
|
||||
TMap<FName, float> GetCurrentFrame() { return CurrentBlendShapesMap; }
|
||||
|
||||
const static TMap<FName, float> ZeroBlendshapeFrame;
|
||||
const static TMap<FName, float> ZeroVisemeFrame;
|
||||
|
||||
//UPROPERTY(EditAnywhere, Category = "Convai|LipSync")
|
||||
float AnchorValue = 0.5;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Convai|LipSync")
|
||||
bool ToggleBlendshapeOrViseme = false;
|
||||
|
||||
protected:
|
||||
float CurrentSequenceTimePassed;
|
||||
TMap<FName, float> CurrentBlendShapesMap;
|
||||
FAnimationSequence MainSequenceBuffer;
|
||||
FAnimationSequence RecordedSequenceBuffer;
|
||||
FCriticalSection SequenceCriticalSection;
|
||||
FCriticalSection RecordingCriticalSection;
|
||||
bool Stopping;
|
||||
bool IsRecordingLipSync;
|
||||
double StartTime;
|
||||
bool bIsPlaying;
|
||||
};
|
||||
332
ConvAI/Convai/Source/Convai/Public/ConvaiGRPC.h
Normal file
332
ConvAI/Convai/Source/Convai/Public/ConvaiGRPC.h
Normal file
@@ -0,0 +1,332 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ConvaiSubsystem.h"
|
||||
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Sound/SoundWave.h"
|
||||
#include "Net/OnlineBlueprintCallProxyBase.h"
|
||||
#include "HAL/ThreadSafeBool.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "Containers/Map.h"
|
||||
#include "ConvaiGRPC.generated.h"
|
||||
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiGRPCLog, Log, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiGRPCFeedBackLog, Log, All);
|
||||
|
||||
class USoundWave;
|
||||
class UConvaiEnvironment;
|
||||
struct FAnimationFrame;
|
||||
struct FAnimationSequence;
|
||||
struct FConvaiResultAction;
|
||||
|
||||
DECLARE_DELEGATE_ThreeParams(FConvaiGRPCOnNarrativeDataSignature, const FString /*BT_Code*/, const FString /*BT_Constants*/, const FString /*NarrativeSectionID*/);
|
||||
DECLARE_DELEGATE_ThreeParams(FConvaiGRPCOnTranscriptionSignature, const FString /*Transcription*/, bool /*IsTranscriptionReady*/, bool /*IsFinal*/);
|
||||
DECLARE_DELEGATE_FourParams(FConvaiGRPCOnDataSignature, const FString /*ReceivedText*/, const TArray<uint8>& /*ReceivedAudio*/, uint32 /*SampleRate*/, bool /*IsFinal*/);
|
||||
DECLARE_DELEGATE_OneParam(FConvaiGRPCOnFaceDataSignature, FAnimationSequence /*FaceData*/);
|
||||
DECLARE_DELEGATE_OneParam(FConvaiGRPCOnActionsSignature, const TArray<FConvaiResultAction>& /*ActionSequence*/);
|
||||
DECLARE_DELEGATE_ThreeParams(FConvaiGRPCOnEmotionSignature, FString /*EmotionResponse*/, FAnimationFrame /*EmotionBlendshapes*/, bool /*MultipleEmotions*/);
|
||||
DECLARE_DELEGATE_OneParam(FConvaiGRPCOnSessiondIDSignature, FString /*SessionID*/);
|
||||
DECLARE_DELEGATE_OneParam(FConvaiGRPCOnInteractionIDSignature, FString /*InteractionID*/);
|
||||
DECLARE_DELEGATE(FConvaiGRPCOnEventSignature);
|
||||
|
||||
USTRUCT()
|
||||
struct FConvaiGRPCVisionParams
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
int width;
|
||||
int height;
|
||||
TArray<uint8> data;
|
||||
|
||||
FConvaiGRPCVisionParams()
|
||||
: width(0)
|
||||
, height(0)
|
||||
, data(TArray<uint8>())
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FConvaiGRPCGetResponseParams
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FString UserQuery;
|
||||
|
||||
FString TriggerName;
|
||||
|
||||
FString TriggerMessage;
|
||||
|
||||
FString CharID;
|
||||
|
||||
bool VoiceResponse;
|
||||
|
||||
bool RequireFaceData;
|
||||
|
||||
bool GeneratesVisemesAsBlendshapes;
|
||||
|
||||
FString SessionID;
|
||||
|
||||
UConvaiEnvironment* Environment;
|
||||
|
||||
bool GenerateActions;
|
||||
|
||||
FConvaiGRPCVisionParams ConvaiGRPCVisionParams;
|
||||
|
||||
FString AuthKey;
|
||||
|
||||
FString AuthHeader;
|
||||
|
||||
TMap<FString, FString> Narrative_Template_Keys;
|
||||
|
||||
FString DynamicEnvironmentInfo;
|
||||
|
||||
FString SpeakerID;
|
||||
|
||||
FConvaiGRPCGetResponseParams()
|
||||
: UserQuery(TEXT(""))
|
||||
, TriggerName(TEXT(""))
|
||||
, TriggerMessage(TEXT(""))
|
||||
, CharID(TEXT(""))
|
||||
, VoiceResponse(false)
|
||||
, RequireFaceData(false)
|
||||
, GeneratesVisemesAsBlendshapes(false)
|
||||
, SessionID(TEXT(""))
|
||||
, Environment(nullptr)
|
||||
, GenerateActions(false)
|
||||
, AuthKey(TEXT(""))
|
||||
, AuthHeader(TEXT(""))
|
||||
, DynamicEnvironmentInfo(TEXT(""))
|
||||
, SpeakerID(TEXT(""))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UConvaiGRPCGetResponseProxy : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
// Called when user transcription is received
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnTranscriptionSignature> OnTranscriptionReceived;
|
||||
|
||||
// Called when new text and/or Audio data is received
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnDataSignature> OnDataReceived;
|
||||
|
||||
// Called when new face data is received
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnFaceDataSignature> OnFaceDataReceived;
|
||||
|
||||
// Called when actions are received
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnActionsSignature> OnActionsReceived;
|
||||
|
||||
// Called when new SessionID is received
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnSessiondIDSignature> OnSessionIDReceived;
|
||||
|
||||
// Called when the InteractionID is received
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnInteractionIDSignature> OnInteractionIDReceived;
|
||||
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnNarrativeDataSignature> OnNarrativeDataReceived;
|
||||
|
||||
// Called when new Emotion is received
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnEmotionSignature> OnEmotionReceived;
|
||||
|
||||
// Called when the response stream is done
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnEventSignature> OnFinish;
|
||||
|
||||
// Called when there is an unsuccessful response
|
||||
FThreadSafeDelegateWrapper<FConvaiGRPCOnEventSignature> OnFailure;
|
||||
|
||||
//UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai GRPC Test", WorldContext = "WorldContextObject"), Category = "Convai|gRPC")
|
||||
static UConvaiGRPCGetResponseProxy* CreateConvaiGRPCGetResponseProxy(UObject* WorldContextObject, FConvaiGRPCGetResponseParams ConvaiGRPCGetResponseParams);
|
||||
|
||||
void Activate();
|
||||
|
||||
void WriteAudioDataToSend(uint8* Buffer, uint32 Length);
|
||||
|
||||
void FinishWriting();
|
||||
|
||||
//~ Begin UObject Interface.
|
||||
virtual void BeginDestroy() override;
|
||||
//~ End UObject Interface.
|
||||
|
||||
bool IsStreamFinished()
|
||||
{
|
||||
return ReceivedFinish;
|
||||
}
|
||||
|
||||
bool CanWriteToStream()
|
||||
{
|
||||
return !IsStreamFinished() && !LastWriteReceived && !FinishedWritingToStream;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void CallFinish();
|
||||
|
||||
TArray<uint8> ConsumeFromAudioBuffer(bool& IsThisTheFinalWrite);
|
||||
|
||||
void LogAndEcecuteFailure(FString FuncName);
|
||||
|
||||
void ExtendDeadline();
|
||||
|
||||
void OnStreamInit(bool ok);
|
||||
void OnStreamRead(bool ok);
|
||||
void OnStreamWrite(bool ok);
|
||||
void OnStreamWriteDone(bool ok);
|
||||
void OnStreamFinish(bool ok);
|
||||
|
||||
FgRPC_Delegate OnInitStreamDelegate;
|
||||
FgRPC_Delegate OnStreamReadDelegate;
|
||||
FgRPC_Delegate OnStreamWriteDelegate;
|
||||
FgRPC_Delegate OnStreamWriteDoneDelegate; // called when a stream->writesdone is successful
|
||||
|
||||
// called when a stream->finish is successful it means that the server decided
|
||||
// to end the stream, we should check the status variable in that call
|
||||
// https://groups.google.com/g/grpc-io/c/R0NTqKaHLdE
|
||||
FgRPC_Delegate OnStreamFinishDelegate;
|
||||
|
||||
service::GetResponseRequest request;
|
||||
std::unique_ptr<service::GetResponseResponse> reply;
|
||||
|
||||
// Context for the client. It could be used to convey extra information to
|
||||
// the server and/or tweak certain RPC behaviors.
|
||||
//std::unique_ptr<ClientContext> context;
|
||||
|
||||
// Storage for the status of the RPC upon completion.
|
||||
grpc::Status status;
|
||||
|
||||
std::unique_ptr<::grpc::ClientAsyncReaderWriter< service::GetResponseRequest, service::GetResponseResponse>> stream_handler;
|
||||
|
||||
grpc::ClientContext client_context;
|
||||
|
||||
// True if we are writing audio to the server, false if we are in the receiving stage
|
||||
bool StreamInProgress = false;
|
||||
|
||||
bool FailAlreadyExecuted = false;
|
||||
|
||||
bool FinishedWritingToStream = false;
|
||||
|
||||
std::unique_ptr<service::ConvaiService::Stub> stub_;
|
||||
|
||||
grpc::CompletionQueue* cq_;
|
||||
|
||||
uint32 NumberOfAudioBytesSent = 0;
|
||||
|
||||
private:
|
||||
// Inputs
|
||||
FConvaiGRPCGetResponseParams ConvaiGRPCGetResponseParams;
|
||||
|
||||
|
||||
private:
|
||||
// becomes true if we receive a non-ok header
|
||||
FThreadSafeBool InformOnDataReceived;
|
||||
|
||||
// Stores the audio data to be streamed to the API
|
||||
TArray<uint8> AudioBuffer;
|
||||
|
||||
// True when we are informed that the "AudioBuffer" is complete and no more audio will be received
|
||||
FThreadSafeBool LastWriteReceived;
|
||||
|
||||
// Used to regulate access to the AudioBuffer to prevent racing condition
|
||||
FCriticalSection m_mutex;
|
||||
|
||||
// Used to prevent early execution of the Init delegate
|
||||
FCriticalSection GPRCInitSection;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
|
||||
FThreadSafeBool ReceivedFinish;
|
||||
FThreadSafeBool CalledFinish;
|
||||
FThreadSafeBool ReceivedFinalResponse;
|
||||
|
||||
// Retry reading counters
|
||||
int RetryCount = 0;
|
||||
int MaxRetries = 3;
|
||||
|
||||
int TotalLipSyncResponsesReceived = 0;
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSubmitFeedbackCallbackSignature, FString, FeedbackResponse);
|
||||
|
||||
UCLASS()
|
||||
class UConvaiGRPCSubmitFeedbackProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
// Called when there is a successful response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FSubmitFeedbackCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FSubmitFeedbackCallbackSignature OnFailure;
|
||||
|
||||
/**
|
||||
* Initiates a feedback request to the gRPC API.
|
||||
* @param InteractionID Identifies the message the feedback is being submitted for - Check "On Interaction ID Received" on the Convai Chatbot Component
|
||||
* @param Thumbs Up False if the message is incorrect or inaccurate, True otherwise.
|
||||
* @param FeedbackText Additionaly feedback that can further help the model learn why the user have given a thumbs up or thumbs down.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Submit Feedback", WorldContext = "WorldContextObject"), Category = "Convai")
|
||||
static UConvaiGRPCSubmitFeedbackProxy* CreateConvaiGRPCSubmitFeedbackProxy(UObject* WorldContextObject, FString InteractionID, bool ThumbsUp, FString FeedbackText);
|
||||
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
private:
|
||||
|
||||
FString InteractionID;
|
||||
bool ThumbsUp;
|
||||
FString FeedbackText;
|
||||
|
||||
FString Response;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
|
||||
//~ Begin UObject Interface.
|
||||
virtual void BeginDestroy() override;
|
||||
//~ End UObject Interface.
|
||||
|
||||
private:
|
||||
|
||||
void LogAndEcecuteFailure(FString FuncName);
|
||||
|
||||
void OnStreamFinish(bool ok);
|
||||
|
||||
// called when a stream->finish is successful it means that the server decided
|
||||
// to end the stream, we should check the status variable in that call
|
||||
// https://groups.google.com/g/grpc-io/c/R0NTqKaHLdE
|
||||
FgRPC_Delegate OnStreamFinishDelegate;
|
||||
|
||||
service::FeedbackRequest request;
|
||||
std::unique_ptr<service::FeedbackResponse> reply;
|
||||
|
||||
// Storage for the status of the RPC upon completion.
|
||||
grpc::Status status;
|
||||
|
||||
std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::service::FeedbackResponse>> stream_handler;
|
||||
|
||||
// Context for the client. It could be used to convey extra information to
|
||||
// the server and/or tweak certain RPC behaviors.
|
||||
grpc::ClientContext client_context;
|
||||
|
||||
std::unique_ptr<service::ConvaiService::Stub> stub_;
|
||||
|
||||
grpc::CompletionQueue* cq_;
|
||||
};
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Net/OnlineBlueprintCallProxyBase.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "HttpModule.h"
|
||||
#include "Interfaces/IHttpRequest.h"
|
||||
#include "Interfaces/IHttpResponse.h"
|
||||
#include "JsonUtilities.h"
|
||||
#include "ConvaiNarrativeDesignProxy.generated.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiNarrativeHTTP, Log, All);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FFetchNarrativeSectionsResponseMulticastCallbackSignature, const TArray<FNarrativeSection>&, NarrativeSections);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FFetchNarrativeTriggersResponseMulticastCallbackSignature, const TArray<FNarrativeTrigger>&, NarrativeTriggers);
|
||||
|
||||
UCLASS()
|
||||
class CONVAI_API UFetchNarrativeSectionsProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FFetchNarrativeSectionsResponseMulticastCallbackSignature OnSuccess;
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FFetchNarrativeSectionsResponseMulticastCallbackSignature OnFailure;
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Fetch Narrative Sections", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UFetchNarrativeSectionsProxy* FetchNarrativeSections(UObject* WorldContextObject, FString CharacterId);
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
TArray<FNarrativeSection> NarrativeSections;
|
||||
|
||||
private:
|
||||
void OnHttpRequestCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
|
||||
|
||||
FString CharacterId;
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class CONVAI_API UFetchNarrativeTriggersProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FFetchNarrativeTriggersResponseMulticastCallbackSignature OnSuccess;
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FFetchNarrativeTriggersResponseMulticastCallbackSignature OnFailure;
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Fetch Narrative Triggers", WorldContext = "WorldContextObject"), Category = "Convai|REST API")
|
||||
static UFetchNarrativeTriggersProxy* FetchNarrativeTriggers(UObject* WorldContextObject, FString CharacterId);
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
TArray<FNarrativeTrigger> NarrativeTriggers;
|
||||
|
||||
private:
|
||||
void OnHttpRequestCompleted(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
|
||||
|
||||
FString CharacterId;
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
};
|
||||
323
ConvAI/Convai/Source/Convai/Public/ConvaiPlayerComponent.h
Normal file
323
ConvAI/Convai/Source/Convai/Public/ConvaiPlayerComponent.h
Normal file
@@ -0,0 +1,323 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/AudioComponent.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "ConvaiAudioStreamer.h"
|
||||
#include "Net/OnlineBlueprintCallProxyBase.h"
|
||||
#include "DSP/BufferVectorOperations.h"
|
||||
#include "ConvaiPlayerComponent.generated.h"
|
||||
|
||||
#define TIME_BETWEEN_VOICE_UPDATES_SECS 0.01
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiPlayerLog, Log, All);
|
||||
|
||||
DECLARE_DELEGATE(FonDataReceived_Delegate);
|
||||
|
||||
// class IVoiceCapture;
|
||||
class UConvaiAudioCaptureComponent;
|
||||
|
||||
// UENUM(BlueprintType)
|
||||
// enum class EHardwareInputFeatureBP : uint8
|
||||
// {
|
||||
// EchoCancellation,
|
||||
// NoiseSuppression,
|
||||
// AutomaticGainControl
|
||||
// };
|
||||
|
||||
// TODO (Mohamed): Ensure both Chatbot and Player components have the same ReplicateVoiceToNetwork value
|
||||
// TODO (Mohamed): Send Text should also be handled in this class (UConvaiPlayerComponent) like we did with voice
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FCaptureDeviceInfoBP
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Convai|Microphone")
|
||||
FString DeviceName = "";
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Convai|Microphone")
|
||||
int DeviceIndex = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Convai|Microphone")
|
||||
FString LongDeviceId = "";
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Convai|Microphone")
|
||||
int InputChannels = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Convai|Microphone")
|
||||
int PreferredSampleRate = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Convai|Microphone")
|
||||
bool bSupportsHardwareAEC = 0;
|
||||
};
|
||||
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType, meta = (BlueprintSpawnableComponent), DisplayName = "Convai Player")
|
||||
class CONVAI_API UConvaiPlayerComponent : public UConvaiAudioStreamer
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UConvaiPlayerComponent();
|
||||
|
||||
virtual void OnComponentCreated() override;
|
||||
|
||||
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
|
||||
bool Init();
|
||||
|
||||
//~ Begin ActorComponent Interface.
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
virtual void BeginDestroy() override;
|
||||
//~ End ActorComponent Interface.
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Convai", Replicated, BlueprintSetter = SetPlayerName)
|
||||
FString PlayerName;
|
||||
|
||||
/**
|
||||
* Sets a new player name
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintInternalUseOnly, Category = "Convai")
|
||||
void SetPlayerName(FString NewPlayerName);
|
||||
|
||||
UFUNCTION(Server, Reliable, Category = "Convai|Network")
|
||||
void SetPlayerNameServer(const FString& NewPlayerName);
|
||||
|
||||
/**
|
||||
* Speaker ID used for long term memory (LTM)
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, Category = "Convai", Replicated, BlueprintSetter = SetSpeakerID)
|
||||
FString SpeakerID;
|
||||
|
||||
/**
|
||||
* Sets a new Speaker ID
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintInternalUseOnly, Category = "Convai")
|
||||
void SetSpeakerID(FString NewSpeakerID);
|
||||
|
||||
UFUNCTION(Server, Reliable, Category = "Convai|Network")
|
||||
void SetSpeakerIDServer(const FString& NewSpeakerID);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
bool GetDefaultCaptureDeviceInfo(FCaptureDeviceInfoBP& OutInfo);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
bool GetCaptureDeviceInfo(FCaptureDeviceInfoBP& OutInfo, int DeviceIndex);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
TArray<FCaptureDeviceInfoBP> GetAvailableCaptureDeviceDetails();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
TArray<FString> GetAvailableCaptureDeviceNames();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
void GetActiveCaptureDevice(FCaptureDeviceInfoBP& OutInfo);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
bool SetCaptureDeviceByIndex(int DeviceIndex);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
bool SetCaptureDeviceByName(FString DeviceName);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
void SetMicrophoneVolumeMultiplier(float InVolumeMultiplier, bool& Success);
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Microphone")
|
||||
void GetMicrophoneVolumeMultiplier(float& OutVolumeMultiplier, bool& Success);
|
||||
|
||||
// UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
// void GetIfHardwareFeatureIsSupported(EHardwareInputFeatureBP FeatureType, bool& Success);
|
||||
|
||||
// UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
// void SetHardwareFeatureEnabled(EHardwareInputFeatureBP FeatureType, bool bIsEnabled, bool& Success);
|
||||
|
||||
/**
|
||||
* Start recording audio from the microphone, use "Finish Recording" function afterwards
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
void StartRecording();
|
||||
|
||||
/**
|
||||
* Stops recording from the microphone and outputs the recorded audio as a Sound Wave
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
USoundWave* FinishRecording();
|
||||
|
||||
/**
|
||||
* Starts streaming microphone audio to the character. Use "Finish Talking" afterward to let the character know that you are done talking
|
||||
* @param ConvaiChatbotComponent The character to talk to
|
||||
* @param Environment Holds all relevant objects and characters in the scene including the (Player), and also all the actions doable by the character. Use "CreateConvaiEnvironment" function to create and then use functions like (AddAction, AddCharacter, AddMainCharacter) to fill it up
|
||||
* @param GenerateActions Whether or not to generate actions (Environment has to be given and valid)
|
||||
* @param VoiceResponse If true it will generate a voice response, otherwise, it will only generate a text response.
|
||||
* @param RunOnServer If true it will run this function on the server, this can be used in multiplayer sessions to allow other players to hear the character's voice response.
|
||||
* @param StreamPlayerMic If true it will stream the player's voice to other players in the multiplayer session, this is the same effect as voice chat.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
void StartTalking(
|
||||
UConvaiChatbotComponent* ConvaiChatbotComponent,
|
||||
UConvaiEnvironment* Environment,
|
||||
bool GenerateActions,
|
||||
bool VoiceResponse,
|
||||
bool RunOnServer,
|
||||
bool StreamPlayerMic,
|
||||
bool UseServerAPI_Key);
|
||||
|
||||
/**
|
||||
* Stops streaming microphone audio to the character.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
void FinishTalking();
|
||||
|
||||
UFUNCTION(Server, Reliable, Category = "Convai|Network")
|
||||
void StartTalkingServer(
|
||||
class UConvaiChatbotComponent* ConvaiChatbotComponent,
|
||||
bool EnvironemntSent,
|
||||
const TArray<FString>& Actions,
|
||||
const TArray<FConvaiObjectEntry>& Objects,
|
||||
const TArray<FConvaiObjectEntry>& Characters,
|
||||
FConvaiObjectEntry MainCharacter,
|
||||
bool GenerateActions,
|
||||
bool VoiceResponse,
|
||||
bool StreamPlayerMic,
|
||||
bool UseServerAPI_Key,
|
||||
const FString& ClientAuthKey,
|
||||
const FString& AuthHeader);
|
||||
|
||||
UFUNCTION(Server, Reliable, Category = "Convai|Network")
|
||||
void FinishTalkingServer();
|
||||
|
||||
/**
|
||||
* Sends text to the character.
|
||||
* @param ConvaiChatbotComponent The character to talk to
|
||||
* @param Text Text to be sent to the character.
|
||||
* @param Environment Holds all relevant objects and characters in the scene including the (Player), and also all the actions doable by the character. Use "CreateConvaiEnvironment" function to create and then use functions like (AddAction, AddCharacter, AddMainCharacter) to fill it up
|
||||
* @param GenerateActions Whether or not to generate actions (Environment has to be given and valid)
|
||||
* @param VoiceResponse If true it will generate a voice response, otherwise, it will only generate a text response.
|
||||
* @param RunOnServer If true it will run this function on the server, this can be used in multiplayer sessions to allow other players to hear the character's voice response.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Microphone")
|
||||
void SendText(
|
||||
UConvaiChatbotComponent* ConvaiChatbotComponent,
|
||||
FString Text,
|
||||
UConvaiEnvironment* Environment,
|
||||
bool GenerateActions,
|
||||
bool VoiceResponse,
|
||||
bool RunOnServer,
|
||||
bool UseServerAPI_Key);
|
||||
|
||||
UFUNCTION(Server, Reliable, Category = "Convai|Network")
|
||||
void SendTextServer(
|
||||
UConvaiChatbotComponent* ConvaiChatbotComponent,
|
||||
const FString& Text,
|
||||
bool EnvironemntSent,
|
||||
const TArray<FString>& Actions,
|
||||
const TArray<FConvaiObjectEntry>& Objects,
|
||||
const TArray<FConvaiObjectEntry>& Characters,
|
||||
FConvaiObjectEntry MainCharacter,
|
||||
bool GenerateActions,
|
||||
bool VoiceResponse,
|
||||
bool UseServerAPI_Key,
|
||||
const FString& ClientAuthKey,
|
||||
const FString& AuthHeader);
|
||||
|
||||
virtual bool ShouldMuteLocal() override;
|
||||
|
||||
virtual bool ShouldMuteGlobal() override;
|
||||
|
||||
virtual void OnServerAudioReceived(uint8* VoiceData, uint32 VoiceDataSize, bool ContainsHeaderData = true, uint32 SampleRate = 21000, uint32 NumChannels = 1) override;
|
||||
|
||||
// UActorComponent interface
|
||||
virtual void BeginPlay() override;
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
bool ConsumeStreamingBuffer(TArray<uint8>& Buffer);
|
||||
|
||||
UFUNCTION(Server, Reliable, Category = "Convai|Network")
|
||||
void SetIsStreamingServer(bool value);
|
||||
|
||||
// Returns true if microphone audio is being streamed, false otherwise.
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Microphone", meta = (DisplayName = "Is Talking"))
|
||||
bool GetIsStreaming()
|
||||
{
|
||||
return(IsStreaming);
|
||||
}
|
||||
|
||||
// Returns true if microphone audio is being recorded, false otherwise.
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Microphone", meta = (DisplayName = "Is Recording"))
|
||||
bool GetIsRecording()
|
||||
{
|
||||
return(IsRecording);
|
||||
}
|
||||
|
||||
FonDataReceived_Delegate& getOnDataReceivedDelegate()
|
||||
{
|
||||
return onDataReceived_Delegate;
|
||||
}
|
||||
|
||||
bool CheckTokenValidty(uint32 TokenToCheck)
|
||||
{
|
||||
return Token == TokenToCheck;
|
||||
}
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Convai|PixelStreaming")
|
||||
TWeakObjectPtr<USynthComponent> PixelStreamingAudioComponent;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Convai|PixelStreaming")
|
||||
bool UsePixelStreamingMicInput;
|
||||
|
||||
bool IsPixelStreamingEnabledAndAllowed();
|
||||
|
||||
private:
|
||||
|
||||
uint32 GenerateNewToken()
|
||||
{
|
||||
Token += 1;
|
||||
return Token;
|
||||
}
|
||||
|
||||
UPROPERTY()
|
||||
USoundWaveProcedural* VoiceCaptureSoundWaveProcedural;
|
||||
|
||||
//TSharedPtr<IVoiceCapture> VoiceCapture;
|
||||
|
||||
// Buffer used with recording
|
||||
TArray<uint8> VoiceCaptureBuffer;
|
||||
|
||||
// Buffer used with streaming
|
||||
// TODO (Mohamed): use TCircularAudioBuffer instead
|
||||
TRingBuffer<uint8> VoiceCaptureRingBuffer;
|
||||
|
||||
UPROPERTY()
|
||||
UConvaiAudioCaptureComponent* AudioCaptureComponent = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
UConvaiChatbotComponent* CurrentConvaiChatbotComponent = nullptr;
|
||||
|
||||
void UpdateVoiceCapture(float DeltaTime);
|
||||
void StartVoiceChunkCapture(float ExpectedRecordingTime = 0.01);
|
||||
void StopVoiceChunkCapture();
|
||||
void ReadRecordedBuffer(Audio::AlignedFloatBuffer& RecordedBuffer, float& OutNumChannels, float& OutSampleRate);
|
||||
|
||||
void StartAudioCaptureComponent();
|
||||
void StopAudioCaptureComponent();
|
||||
|
||||
|
||||
FonDataReceived_Delegate onDataReceived_Delegate;
|
||||
|
||||
bool IsRecording = false;
|
||||
bool IsStreaming = false;
|
||||
bool IsInit = false;
|
||||
bool bShouldMuteGlobal;
|
||||
|
||||
float RemainingTimeUntilNextUpdate = 0;
|
||||
|
||||
// Used by a consumer (e.g. chatbot component) to validate if this player component is still streaming audio data to it
|
||||
uint32 Token;
|
||||
|
||||
USoundSubmixBase* _FoundSubmix;
|
||||
};
|
||||
88
ConvAI/Convai/Source/Convai/Public/ConvaiSpeechToTextProxy.h
Normal file
88
ConvAI/Convai/Source/Convai/Public/ConvaiSpeechToTextProxy.h
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Net/OnlineBlueprintCallProxyBase.h"
|
||||
#include "Http.h"
|
||||
#include "ConvaiSpeechToTextProxy.generated.h"
|
||||
|
||||
//http log
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiS2THttpLog, Log, All);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FS2THttpResponseCallbackSignature, FString, Response);
|
||||
|
||||
|
||||
class USoundWave;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UConvaiSpeechToTextProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FS2THttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FS2THttpResponseCallbackSignature OnFailure;
|
||||
|
||||
|
||||
/**
|
||||
* Initiates a post request to the Speech To Text API.
|
||||
* @param URL The url of the API endpoint.
|
||||
* @param API_key The API key issued from the website
|
||||
* @param SoundWave SoundWave that is to be transfered to text
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Speech To Text From SoundWave", WorldContext = "WorldContextObject"), Category = "Convai|Http")
|
||||
static UConvaiSpeechToTextProxy* CreateSpeech2TextFromSoundWaveQueryProxy(UObject* WorldContextObject, USoundWave* SoundWave);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initiates a post request to the Speech To Text API.
|
||||
* @param URL The url of the API endpoint.
|
||||
* @param API_key The API key issued from the website
|
||||
* @param Payload Byte array containing the wav file
|
||||
* @param bStereo Set to true if the wav file has 2 channels
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Speech To Text From byte array", WorldContext = "WorldContextObject"), Category = "Convai|Http")
|
||||
static UConvaiSpeechToTextProxy* CreateSpeech2TextFromArrayQueryProxy(UObject* WorldContextObject, TArray<uint8> Payload);
|
||||
|
||||
/**
|
||||
* Initiates a post request to the Speech To Text API.
|
||||
* @param URL The url of the API endpoint.
|
||||
* @param API_key The API key issued from the website
|
||||
* @param filename The name of the wav file to be sent
|
||||
* @param bStereo Set to true if the wav file has 2 channels
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Speech To Text From file", WorldContext = "WorldContextObject"), Category = "Convai|Http")
|
||||
static UConvaiSpeechToTextProxy* CreateSpeech2TextFromFileNameQueryProxy(UObject* WorldContextObject, FString filename);
|
||||
|
||||
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
|
||||
FString URL;
|
||||
FString filename;
|
||||
TArray<uint8> Payload;
|
||||
bool bStereo;
|
||||
FString Response;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
};
|
||||
163
ConvAI/Convai/Source/Convai/Public/ConvaiSubsystem.h
Normal file
163
ConvAI/Convai/Source/Convai/Public/ConvaiSubsystem.h
Normal file
@@ -0,0 +1,163 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Subsystems/SubsystemCollection.h"
|
||||
#include "Net/OnlineBlueprintCallProxyBase.h"
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "HAL/Runnable.h"
|
||||
#include "HAL/ThreadSafeBool.h"
|
||||
|
||||
THIRD_PARTY_INCLUDES_START
|
||||
#include "Proto/service.grpc.pb.h"
|
||||
#undef min
|
||||
#undef max
|
||||
#undef UpdateResource
|
||||
#undef GetObject
|
||||
#undef GetUObject
|
||||
#undef GetClassName
|
||||
#undef InterlockedExchange
|
||||
#undef InterlockedAnd
|
||||
#undef InterlockedIncrement
|
||||
#undef InterlockedDecrement
|
||||
#undef InterlockedCompareExchange
|
||||
#undef FastFence
|
||||
#undef MemoryBarrier
|
||||
#undef Yield
|
||||
#undef CaptureStackBackTrace
|
||||
#undef GetCurrentTime
|
||||
THIRD_PARTY_INCLUDES_END
|
||||
|
||||
#include "ConvaiSubsystem.generated.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
extern bool GetAppleMicPermission();
|
||||
#endif
|
||||
|
||||
namespace grpc
|
||||
{
|
||||
class Channel;
|
||||
|
||||
template <class R>
|
||||
class ClientAsyncResponseReader;
|
||||
|
||||
class ClientContext;
|
||||
class CompletionQueue;
|
||||
class Status;
|
||||
|
||||
template <class W, class R>
|
||||
class ClientAsyncReaderWriter;
|
||||
class ChannelCredentials;
|
||||
}
|
||||
|
||||
|
||||
//namespace service
|
||||
//{
|
||||
// //class ConvaiService;
|
||||
//
|
||||
// class ConvaiService::Stub;
|
||||
// class GetResponseResponse;
|
||||
// class GetResponseRequest;
|
||||
//};
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiSubsystemLog, Log, All);
|
||||
|
||||
DECLARE_DELEGATE_OneParam(FgRPC_Delegate, bool);
|
||||
|
||||
class FgRPCClient : public FRunnable {
|
||||
public:
|
||||
FgRPCClient(std::string target, const std::shared_ptr<grpc::ChannelCredentials>& creds);
|
||||
|
||||
std::unique_ptr<service::ConvaiService::Stub> GetNewStub();
|
||||
|
||||
grpc::CompletionQueue* GetCompletionQueue();
|
||||
|
||||
public:
|
||||
/**
|
||||
* FRunnable Interface
|
||||
* Loop while listening for completed responses.
|
||||
*/
|
||||
virtual uint32 Run() override;
|
||||
|
||||
void StartStub();
|
||||
|
||||
void CreateChannel();
|
||||
|
||||
void OnStateChange(bool ok);
|
||||
|
||||
virtual void Exit() override;
|
||||
|
||||
private:
|
||||
mutable FCriticalSection CriticalSection;
|
||||
FThreadSafeBool bIsRunning;
|
||||
|
||||
TUniquePtr<FRunnableThread> Thread;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Out of the passed in Channel comes the stub, stored here, our view of the
|
||||
// server's exposed services.
|
||||
std::unique_ptr<service::ConvaiService::Stub> stub_;
|
||||
|
||||
std::shared_ptr<grpc::Channel> Channel;
|
||||
std::shared_ptr<grpc::ChannelCredentials> Creds;
|
||||
std::string Target;
|
||||
|
||||
FgRPC_Delegate OnStateChangeDelegate;
|
||||
|
||||
// The producer-consumer queue we use to communicate asynchronously with the
|
||||
// gRPC runtime.
|
||||
grpc::CompletionQueue cq_;
|
||||
};
|
||||
|
||||
|
||||
UCLASS(meta = (DisplayName = "Convai Subsystem"))
|
||||
class UConvaiSubsystem : public UGameInstanceSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
public:
|
||||
UConvaiSubsystem();
|
||||
|
||||
// Begin USubsystem
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
virtual void Deinitialize() override;
|
||||
// End USubsystem
|
||||
|
||||
void GetAndroidMicPermission();
|
||||
|
||||
public:
|
||||
TSharedPtr<FgRPCClient> gRPC_Runnable;
|
||||
|
||||
public:
|
||||
// Register a chatbot component with the subsystem
|
||||
void RegisterChatbotComponent(class UConvaiChatbotComponent* ChatbotComponent);
|
||||
|
||||
// Unregister a chatbot component from the subsystem
|
||||
void UnregisterChatbotComponent(class UConvaiChatbotComponent* ChatbotComponent);
|
||||
|
||||
// Get all registered chatbot components
|
||||
TArray<class UConvaiChatbotComponent*> GetAllChatbotComponents() const;
|
||||
|
||||
public:
|
||||
// Register a player component with the subsystem
|
||||
void RegisterPlayerComponent(class UConvaiPlayerComponent* PlayerComponent);
|
||||
|
||||
// Unregister a player component from the subsystem
|
||||
void UnregisterPlayerComponent(class UConvaiPlayerComponent* PlayerComponent);
|
||||
|
||||
// Get all registered player components
|
||||
TArray<class UConvaiPlayerComponent*> GetAllPlayerComponents() const;
|
||||
|
||||
private:
|
||||
// Array to store all active chatbot components
|
||||
UPROPERTY()
|
||||
TArray<class UConvaiChatbotComponent*> RegisteredChatbotComponents;
|
||||
|
||||
private:
|
||||
// Array to store all active player components
|
||||
UPROPERTY()
|
||||
TArray<class UConvaiPlayerComponent*> RegisteredPlayerComponents;
|
||||
};
|
||||
83
ConvAI/Convai/Source/Convai/Public/ConvaiTextToSpeechProxy.h
Normal file
83
ConvAI/Convai/Source/Convai/Public/ConvaiTextToSpeechProxy.h
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Net/OnlineBlueprintCallProxyBase.h"
|
||||
#include "Http.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "ConvaiTextToSpeechProxy.generated.h"
|
||||
|
||||
class USoundWave;
|
||||
|
||||
|
||||
|
||||
//http log
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiT2SHttpLog, Log, All);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FT2SHttpResponseCallbackSignature, USoundWave*, Wave);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UConvaiTextToSpeechProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
|
||||
// Called when there is a successful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FT2SHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
// Called when there is an unsuccessful http response
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FT2SHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initiates a post request to the Speech To Text API.
|
||||
* @param API_key The API key issued from the website
|
||||
* @param Transcript The text to be transformed to voice
|
||||
* @param Voice The voice type to be used
|
||||
*/
|
||||
//UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Text To Speech", WorldContext = "WorldContextObject"), Category = "Convai|Http")
|
||||
//static UConvaiTextToSpeechProxy* CreateTextToSpeechQueryProxy(UObject* WorldContextObject, FString Transcript, ETTS_Voice_Type Voice);
|
||||
|
||||
|
||||
/**
|
||||
* Initiates a post request to the Speech To Text API.
|
||||
* @param API_key The API key issued from the website
|
||||
* @param Transcript The text to be transformed to voice
|
||||
* @param Voice The voice type to be used
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Text To Speech", WorldContext = "WorldContextObject"), Category = "Convai|Http")
|
||||
static UConvaiTextToSpeechProxy* CreateTextToSpeechQueryProxy(UObject* WorldContextObject, FString Transcript, FString Voice);
|
||||
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
void onHttpRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bWasSuccessful);
|
||||
|
||||
void failed();
|
||||
void success();
|
||||
void finish();
|
||||
|
||||
|
||||
FString URL;
|
||||
FString Transcript;
|
||||
ETTS_Voice_Type Voice;
|
||||
FString VoiceStr;
|
||||
|
||||
USoundWave* SoundWave;
|
||||
|
||||
// Pointer to the world
|
||||
TWeakObjectPtr<UWorld> WorldPtr;
|
||||
};
|
||||
274
ConvAI/Convai/Source/Convai/Public/ConvaiUtils.h
Normal file
274
ConvAI/Convai/Source/Convai/Public/ConvaiUtils.h
Normal file
@@ -0,0 +1,274 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "Utility/Log/ConvaiLogger.h"
|
||||
#include "ConvaiUtils.generated.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiUtilsLog, Log, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiFormValidationLog, Log, All);
|
||||
|
||||
class USoundWave;
|
||||
class APlayerController;
|
||||
class UObject;
|
||||
class UConvaiSubsystem;
|
||||
struct FAnimationFrame;
|
||||
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiUtils : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
static UConvaiSubsystem* GetConvaiSubsystem(const UObject* WorldContextObject);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Utilities")
|
||||
static void StereoToMono(TArray<uint8> stereoWavBytes, TArray<uint8>& monoWavBytes);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Utilities")
|
||||
static bool ReadFileAsByteArray(const FString FilePath, TArray<uint8>& Bytes);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Utilities")
|
||||
static bool SaveByteArrayAsFile(FString FilePath, TArray<uint8> Bytes);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Utilities")
|
||||
static FString ByteArrayToString(TArray<uint8> Bytes);
|
||||
|
||||
// Writes a string to a file
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Utilities")
|
||||
static bool WriteStringToFile(const FString& StringToWrite, const FString& FilePath);
|
||||
|
||||
// Reads a string from a file
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Utilities")
|
||||
static bool ReadStringFromFile(FString& OutString, const FString& FilePath);
|
||||
|
||||
static float CalculateAudioDuration(uint32 AudioSize, uint8 Channels, uint32 SampleRate, uint8 SampleSize = 2);
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Utilities", meta = (WorldContext = "WorldContextObject", AutoCreateRefTerm = "IncludedCharacters, ExcludedCharacters"))
|
||||
static void ConvaiGetLookedAtCharacter(UObject* WorldContextObject, APlayerController* PlayerController, float Radius, bool PlaneView, TArray<UObject*> IncludedCharacters, TArray<UObject*> ExcludedCharacters, UConvaiChatbotComponent*& ConvaiCharacter, bool& Found);
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Utilities", meta = (WorldContext = "WorldContextObject"))
|
||||
static void ConvaiGetLookedAtObjectOrCharacter(UObject* WorldContextObject, APlayerController* PlayerController, float Radius, bool PlaneView, TArray<FConvaiObjectEntry> ListToSearchIn, FConvaiObjectEntry& FoundObjectOrCharacter, bool& Found);
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Utilities", meta = (WorldContext = "WorldContextObject"))
|
||||
static void ConvaiGetAllPlayerComponents(UObject* WorldContextObject, TArray<class UConvaiPlayerComponent*>& ConvaiPlayerComponents);
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Convai|Utilities", meta = (WorldContext = "WorldContextObject"))
|
||||
static void ConvaiGetAllChatbotComponents(UObject* WorldContextObject, TArray<class UConvaiChatbotComponent*>& ConvaiChatbotComponents);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Settings")
|
||||
static void SetAPI_Key(FString API_Key);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|Settings")
|
||||
static FString GetAPI_Key();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Settings")
|
||||
static void SetAuthToken(FString AuthToken);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|Settings")
|
||||
static FString GetAuthToken();
|
||||
|
||||
static TPair<FString, FString> GetAuthHeaderAndKey();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|Settings")
|
||||
static FString GetTestCharacterID();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|Settings")
|
||||
static bool IsNewActionSystemEnabled();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|Utilities")
|
||||
static void GetPluginInfo(FString PluginName, bool& Found, FString& VersionName, FString& EngineVersion, FString& FriendlyName);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|Utilities")
|
||||
static void GetPlatformInfo(FString& EngineVersion, FString& PlatformName);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|Utilities")
|
||||
static TMap<FName, float> MapBlendshapes(const TMap<FName,float>& InputBlendshapes, const TMap<FName, FConvaiBlendshapeParameters>& BlendshapeMap, float GlobalMultiplier, float GlobalOffset);
|
||||
|
||||
static TArray<uint8> ExtractPCMDataFromSoundWave(USoundWave* SoundWave, int32& OutSampleRate, int32& OutNumChannels);
|
||||
|
||||
static void PCMDataToWav(TArray<uint8> InPCMBytes, TArray<uint8>& OutWaveFileData, int NumChannels, int SampleRate);
|
||||
|
||||
static USoundWave* PCMDataToSoundWav(TArray<uint8> InPCMBytes, int NumChannels, int SampleRate);
|
||||
|
||||
static USoundWave* WavDataToSoundWave(TArray<uint8> InWavData);
|
||||
|
||||
// Writes a USoundWave to a .wav file on disk
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Utilities")
|
||||
static bool WriteSoundWaveToWavFile(USoundWave* SoundWave, const FString& FilePath);
|
||||
|
||||
// Reads a .wav file from disk and creates a USoundWave
|
||||
UFUNCTION(BlueprintPure, Category = "Convai|Utilities")
|
||||
static USoundWave* ReadWavFileAsSoundWave(const FString& FilePath);
|
||||
|
||||
static void ResampleAudio(float currentSampleRate, float targetSampleRate, int numChannels, bool reduceToMono, int16* currentPcmData, int numSamplesToConvert, TArray<int16>& outResampledPcmData);
|
||||
|
||||
static void ResampleAudio(float currentSampleRate, float targetSampleRate, int numChannels, bool reduceToMono, const TArray<int16>& currentPcmData, int numSamplesToConvert, TArray<int16>& outResampledPcmData);
|
||||
|
||||
static FString FUTF8ToFString(const char* StringToConvert);
|
||||
|
||||
static int LevenshteinDistance(const FString& s, const FString& t);
|
||||
|
||||
static TArray<FAnimationFrame> ParseJsonToBlendShapeData(const FString& JsonString);
|
||||
|
||||
static bool ParseVisemeValuesToAnimationFrame(const FString& VisemeValuesString, FAnimationFrame& AnimationFrame);
|
||||
|
||||
// UFUNCTION(BlueprintCallable, Category = "ActorFuncions", meta = (WorldContext = WorldContextObject))
|
||||
static AActor* ConvaiCloneActor(AActor* InputActor);
|
||||
|
||||
// UFUNCTION(BlueprintPure, Category = "Convai|Utilities|AnimationSequence")
|
||||
static FString ConvaiAnimationSequenceToJson(const FAnimationSequenceBP& AnimationSequenceBP);
|
||||
|
||||
// UFUNCTION(BlueprintPure, Category = "Convai|Utilities|AnimationSequence")
|
||||
static void ConvaiAnimationSequenceFromJson(const FString& JsonString, FAnimationSequenceBP& AnimationSequenceBP);
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiSettingsUtils : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
static bool GetParamValueAsString(const FString& paramName, FString& outValue);
|
||||
|
||||
static bool GetParamValueAsFloat(const FString& paramName, float& outValue);
|
||||
|
||||
static bool GetParamValueAsInt(const FString & paramName, int32 & outValue);
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiFormValidation : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
static bool ValidateAuthKey(FString API_Key)
|
||||
{
|
||||
if ((API_Key.Len()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(LogTemp, Warning, TEXT("Empty API Key, please add it in Edit->Project Settings->Convai"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ValidateSessionID(FString SessionID)
|
||||
{
|
||||
if ((SessionID.Len()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiFormValidationLog, Warning, TEXT("Empty Session ID"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ValidateCharacterID(FString CharacterID)
|
||||
{
|
||||
if ((CharacterID.Len()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiFormValidationLog, Warning, TEXT("Empty Character ID"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ValidateInputText(FString InputText)
|
||||
{
|
||||
if ((InputText.Len()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(LogTemp, Warning, TEXT("Empty Input Text"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ValidateVoiceType(FString VoiceType)
|
||||
{
|
||||
if ((VoiceType.Len()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiFormValidationLog, Warning, TEXT("Invalid Voice Type"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ValidateBackstory(FString Backstory)
|
||||
{
|
||||
if ((Backstory.Len()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiFormValidationLog, Warning, TEXT("Empty Backstory"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ValidateCharacterName(FString CharacterName)
|
||||
{
|
||||
if ((CharacterName.Len()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiFormValidationLog, Warning, TEXT("Empty Character Name"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ValidateInputVoice(TArray<uint8> InputVoiceData)
|
||||
{
|
||||
if ((InputVoiceData.Num() > 44))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(ConvaiFormValidationLog, Warning, TEXT("Input Voice is too short (less than 44 bytes)"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UCommandLineUtils : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
// Function to check if a flag is present in the command line - Has issue it always returns false
|
||||
//UFUNCTION(BlueprintCallable, Category = "CommandLine")
|
||||
static bool IsCommandLineFlagPresent(const FString& Flag);
|
||||
|
||||
// Function to get the value of a command line flag as an integer
|
||||
UFUNCTION(BlueprintCallable, Category = "CommandLine")
|
||||
static int32 GetCommandLineFlagValueAsInt(const FString& Flag, int32 DefaultValue = 0);
|
||||
|
||||
// Function to get the value of a command line flag as a string
|
||||
UFUNCTION(BlueprintCallable, Category = "CommandLine")
|
||||
static FString GetCommandLineFlagValueAsString(const FString& Flag, const FString& DefaultValue = TEXT(""));
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "CommandLine")
|
||||
static FString GetCommandLineFlagValueAsStringNoDefault(const FString& Flag);
|
||||
};
|
||||
35
ConvAI/Convai/Source/Convai/Public/LipSyncInterface.h
Normal file
35
ConvAI/Convai/Source/Convai/Public/LipSyncInterface.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "LipSyncInterface.generated.h"
|
||||
|
||||
DECLARE_DELEGATE(FOnVisemesDataReadySignature);
|
||||
|
||||
UINTERFACE()
|
||||
class CONVAI_API UConvaiLipSyncInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class IConvaiLipSyncInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
FOnVisemesDataReadySignature OnVisemesDataReady;
|
||||
|
||||
virtual void ConvaiInferFacialDataFromAudio(uint8* InPCMData, uint32 InPCMDataSize, uint32 InSampleRate, uint32 InNumChannels) = 0;
|
||||
virtual void ConvaiStopLipSync() = 0;
|
||||
virtual TArray<float> ConvaiGetVisemes() = 0;
|
||||
virtual TArray<FString> ConvaiGetVisemeNames() = 0;
|
||||
virtual void ConvaiApplyPrecomputedFacialAnimation(uint8* InPCMData, uint32 InPCMDataSize, uint32 InSampleRate, uint32 InNumChannels, FAnimationSequence FaceSequence) = 0;
|
||||
virtual void ConvaiApplyFacialFrame(FAnimationFrame FaceFrame, float Duration) = 0;
|
||||
virtual bool RequiresPrecomputedFaceData() = 0;
|
||||
virtual bool GeneratesVisemesAsBlendshapes() = 0;
|
||||
virtual TMap<FName, float> ConvaiGetFaceBlendshapes() = 0;
|
||||
virtual void ForceRecalculateStartTime() = 0;
|
||||
};
|
||||
100
ConvAI/Convai/Source/Convai/Public/RestAPI/ConvaiAPIBase.h
Normal file
100
ConvAI/Convai/Source/Convai/Public/RestAPI/ConvaiAPIBase.h
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
#include "CoreMinimal.h"
|
||||
#include "Net/OnlineBlueprintCallProxyBase.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
|
||||
#ifdef USE_CONVAI_HTTP
|
||||
#else
|
||||
#define USE_CONVAI_HTTP 0
|
||||
#endif
|
||||
|
||||
#if USE_CONVAI_HTTP
|
||||
// Use ConvaiHttp module
|
||||
#include "ConvaihttpModule.h"
|
||||
#include "Interfaces/IConvaihttpRequest.h"
|
||||
#include "Interfaces/IConvaihttpResponse.h"
|
||||
#define CONVAI_HTTP_MODULE FConvaihttpModule
|
||||
#define CONVAI_HTTP_REQUEST_INTERFACE IConvaihttpRequest
|
||||
#define CONVAI_HTTP_RESPONSE_INTERFACE IConvaihttpResponse
|
||||
#define CONVAI_HTTP_REQUEST_PTR FConvaihttpRequestPtr
|
||||
#define CONVAI_HTTP_RESPONSE_PTR FConvaihttpResponsePtr
|
||||
#define CONVAI_HTTP_PAYLOAD_ARRAY_TYPE TArray64<uint8>
|
||||
#define CONVAI_HTTP_DOWN_PROGRESS_TYPE uint64
|
||||
#else
|
||||
// Use HTTP module
|
||||
#include "HttpModule.h"
|
||||
#include "Interfaces/IHttpRequest.h"
|
||||
#include "Interfaces/IHttpResponse.h"
|
||||
#define CONVAI_HTTP_MODULE FHttpModule
|
||||
#define CONVAI_HTTP_REQUEST_INTERFACE IHttpRequest
|
||||
#define CONVAI_HTTP_RESPONSE_INTERFACE IHttpResponse
|
||||
#define CONVAI_HTTP_REQUEST_PTR FHttpRequestPtr
|
||||
#define CONVAI_HTTP_RESPONSE_PTR FHttpResponsePtr
|
||||
#define CONVAI_HTTP_PAYLOAD_ARRAY_TYPE TArray<uint8>
|
||||
#if ENGINE_MAJOR_VERSION > 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 4)
|
||||
#define CONVAI_HTTP_DOWN_PROGRESS_TYPE uint64
|
||||
#else
|
||||
#define CONVAI_HTTP_DOWN_PROGRESS_TYPE int32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "ConvaiAPIBase.generated.h"
|
||||
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(ConvaiBaseHttpLogs, Log, All);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FStringHttpResponseCallbackSignature, FString, ResponseString);
|
||||
|
||||
namespace ConvaiHttpConstants
|
||||
{
|
||||
static const TCHAR* GET = TEXT("GET");
|
||||
static const TCHAR* POST = TEXT("POST");
|
||||
static const TCHAR* PUT = TEXT("PUT");
|
||||
}
|
||||
|
||||
//-------------------------------------------Base API class-----------------------------------------
|
||||
|
||||
/** Base class for all the Convai API calls */
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiAPIBaseProxy : public UOnlineBlueprintCallProxyBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void Activate() override;
|
||||
|
||||
protected:
|
||||
|
||||
/*IHttp interface*/
|
||||
virtual void OnHttpRequestComplete(CONVAI_HTTP_REQUEST_PTR Request, CONVAI_HTTP_RESPONSE_PTR Response, bool bWasSuccessful);
|
||||
/*END IHttp interface*/
|
||||
|
||||
virtual bool ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb);
|
||||
virtual bool AddContentToRequest(CONVAI_HTTP_PAYLOAD_ARRAY_TYPE& DataToSend, const FString& Boundary) { return false; }
|
||||
virtual bool AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend) { return false; }
|
||||
virtual void HandleSuccess();
|
||||
virtual void HandleFailure();
|
||||
|
||||
public:
|
||||
FString URL;
|
||||
FString ResponseString;
|
||||
CONVAI_HTTP_PAYLOAD_ARRAY_TYPE ResponseData;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** Base class for all the Convai Asset manager API calls */
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiAPITokenInBodyProxy : public UConvaiAPIBaseProxy
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
virtual bool AddContentToRequest(CONVAI_HTTP_PAYLOAD_ARRAY_TYPE& DataToSend, const FString& Boundary) override;
|
||||
virtual bool AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend) override;
|
||||
};
|
||||
|
||||
188
ConvAI/Convai/Source/Convai/Public/RestAPI/ConvaiLTMProxy.h
Normal file
188
ConvAI/Convai/Source/Convai/Public/RestAPI/ConvaiLTMProxy.h
Normal file
@@ -0,0 +1,188 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "RestAPI/ConvaiAPIBase.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "ConvaiLTMProxy.generated.h"
|
||||
|
||||
struct FConvaiSpeakerInfo;
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LTMHttpLogs, Log, All);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSpeakerIDListHttpResponseCallbackSignature, const TArray<FConvaiSpeakerInfo>&, SpeakerIDs);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSpeakerIDHttpResponseCallbackSignature, const FConvaiSpeakerInfo&, SpeakerID);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLTMStatusHttpResponseCallbackSignature, bool, Status);
|
||||
|
||||
|
||||
|
||||
// Create speaker id
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiCreateSpeakerID : public UConvaiAPIBaseProxy
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FSpeakerIDHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FSpeakerIDHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Create Speaker ID"), Category = "Convai|LTM")
|
||||
static UConvaiCreateSpeakerID* ConvaiCreateSpeakerIDProxy(FString SpeakerName, FString DeviceId);
|
||||
|
||||
protected:
|
||||
virtual bool ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb) override;
|
||||
virtual bool AddContentToRequest(CONVAI_HTTP_PAYLOAD_ARRAY_TYPE& DataToSend, const FString& Boundary) override { return false; }
|
||||
virtual bool AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend) override;
|
||||
virtual void HandleSuccess() override;
|
||||
virtual void HandleFailure() override;
|
||||
|
||||
FString AssociatedSpeakerName;
|
||||
FString AssociatedDeviceId;
|
||||
FConvaiSpeakerInfo AssociatedSpeakerInfo;
|
||||
};
|
||||
// END create speaker id
|
||||
|
||||
|
||||
|
||||
|
||||
// List speaker ids
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiListSpeakerID : public UConvaiAPIBaseProxy
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FSpeakerIDListHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FSpeakerIDListHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai List Speaker IDs"), Category = "Convai|LTM")
|
||||
static UConvaiListSpeakerID* ConvaiListSpeakerIDProxy();
|
||||
|
||||
protected:
|
||||
virtual bool ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb) override;
|
||||
virtual bool AddContentToRequest(CONVAI_HTTP_PAYLOAD_ARRAY_TYPE& DataToSend, const FString& Boundary) override { return false; }
|
||||
virtual bool AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend) override { return false; }
|
||||
virtual void HandleSuccess() override;
|
||||
virtual void HandleFailure() override;
|
||||
};
|
||||
// END list speaker ids
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Delete speaker id
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiDeleteSpeakerID : public UConvaiAPIBaseProxy
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FStringHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FStringHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Delete Speaker ID"), Category = "Convai|LTM")
|
||||
static UConvaiDeleteSpeakerID* ConvaiDeleteSpeakerIDProxy(FString SpeakerID);
|
||||
|
||||
protected:
|
||||
virtual bool ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb) override;
|
||||
virtual bool AddContentToRequest(CONVAI_HTTP_PAYLOAD_ARRAY_TYPE& DataToSend, const FString& Boundary) override { return false; }
|
||||
virtual bool AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend) override;
|
||||
virtual void HandleSuccess() override;
|
||||
virtual void HandleFailure() override;
|
||||
|
||||
FString AssociatedSpeakerID;
|
||||
};
|
||||
// END Delete speaker id
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Get LTM status
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiGetLTMStatus : public UConvaiAPIBaseProxy
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FLTMStatusHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FLTMStatusHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Get LTM Status"), Category = "Convai|LTM")
|
||||
static UConvaiGetLTMStatus* ConvaiGetLTMStatusProxy(FString CharacterID);
|
||||
|
||||
protected:
|
||||
virtual bool ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb) override;
|
||||
virtual bool AddContentToRequest(CONVAI_HTTP_PAYLOAD_ARRAY_TYPE& DataToSend, const FString& Boundary) override { return false; }
|
||||
virtual bool AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend) override;
|
||||
virtual void HandleSuccess() override;
|
||||
virtual void HandleFailure() override;
|
||||
|
||||
FString AssociatedCharacterID;
|
||||
};
|
||||
// END Get LTM status
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Set LTM status
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiSetLTMStatus : public UConvaiAPIBaseProxy
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FStringHttpResponseCallbackSignature OnSuccess;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FStringHttpResponseCallbackSignature OnFailure;
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", DisplayName = "Convai Set LTM Status"), Category = "Convai|LTM")
|
||||
static UConvaiSetLTMStatus* ConvaiSetLTMStatusProxy(FString CharacterID, bool bEnable);
|
||||
|
||||
protected:
|
||||
virtual bool ConfigureRequest(TSharedRef<CONVAI_HTTP_REQUEST_INTERFACE> Request, const TCHAR* Verb) override;
|
||||
virtual bool AddContentToRequest(CONVAI_HTTP_PAYLOAD_ARRAY_TYPE& DataToSend, const FString& Boundary) override { return false; }
|
||||
virtual bool AddContentToRequestAsString(TSharedPtr<FJsonObject>& ObjectToSend) override;
|
||||
virtual void HandleSuccess() override;
|
||||
virtual void HandleFailure() override;
|
||||
|
||||
FString AssociatedCharacterID;
|
||||
bool bAssociatedEnable;
|
||||
};
|
||||
// END Set LTM status
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiLTMUtils : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
static bool ParseConvaiSpeakerInfoArray(const FString& JsonString, TArray<FConvaiSpeakerInfo>& OutSpeakerInfoArray);
|
||||
static bool GetLTMStatus(const FString& JsonString, bool& bEnabled);
|
||||
};
|
||||
56
ConvAI/Convai/Source/Convai/Public/RestAPI/ConvaiURL.h
Normal file
56
ConvAI/Convai/Source/Convai/Public/RestAPI/ConvaiURL.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ConvaiURL.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EConvaiEndpoint : uint8
|
||||
{
|
||||
NewSpeaker UMETA(DisplayName = "New Speaker"),
|
||||
SpeakerIDList UMETA(DisplayName = "Speaker ID List"),
|
||||
DeleteSpeakerID UMETA(DisplayName = "Delete Speaker ID"),
|
||||
ReferralSourceStatus UMETA(DisplayName = "Referral Source Status"),
|
||||
UpdateReferralSource UMETA(DisplayName = "Update Referral Source"),
|
||||
UserAPIUsage UMETA(DisplayName = "User API Usage"),
|
||||
CharacterUpdate UMETA(DisplayName = "Character Update"),
|
||||
CharacterGet UMETA(DisplayName = "Character Get"),
|
||||
ListCharacterSections UMETA(DisplayName = "List Character Sections"),
|
||||
ListCharacterTriggers UMETA(DisplayName = "List Character Triggers")
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiURL : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
static FString GetEndpoint(EConvaiEndpoint Endpoint);
|
||||
|
||||
/** Get the base URL for a specific environment (beta or prod) */
|
||||
static FString GetBaseURL(bool bUseBeta = false);
|
||||
|
||||
/** Get the full URL for a specific API endpoint */
|
||||
static FString GetFullURL(const FString& ApiPath, bool bUseBeta = false);
|
||||
|
||||
static FString GetFormattedBaseURL(const FString& Subdomain);
|
||||
|
||||
/** Initialize URL configuration from command line or settings */
|
||||
static void InitializeURLConfig();
|
||||
|
||||
private:
|
||||
static const TCHAR BETA_SUBDOMAIN[];
|
||||
static const TCHAR PROD_SUBDOMAIN[];
|
||||
static const TCHAR BASE_URL[];
|
||||
static const TCHAR BASE_URL_FORMAT[];
|
||||
|
||||
static const TCHAR LTM_SUBDOMAIN[];
|
||||
static const TCHAR USER_SUBDOMAIN[];
|
||||
static const TCHAR CHARACTER_SUBDOMAIN[];
|
||||
static const TCHAR NARRATIVE_DESIGN_SUBDOMAIN[];
|
||||
|
||||
static TArray<EConvaiEndpoint> BetaEndpoints;
|
||||
|
||||
static FString CustomBetaBaseURL;
|
||||
static FString CustomProdBaseURL;
|
||||
static bool bURLConfigInitialized;
|
||||
};
|
||||
505
ConvAI/Convai/Source/Convai/Public/RingBuffer.h
Normal file
505
ConvAI/Convai/Source/Convai/Public/RingBuffer.h
Normal file
@@ -0,0 +1,505 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Misc/SecureHash.h"
|
||||
|
||||
template< typename DataType >
|
||||
class TRingBuffer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
TRingBuffer(uint32 BufferDataSize);
|
||||
|
||||
TRingBuffer();
|
||||
|
||||
/**
|
||||
* Default Destructor
|
||||
*/
|
||||
~TRingBuffer();
|
||||
|
||||
void Init(uint32 InBufferDataSize);
|
||||
|
||||
/**
|
||||
* Clears memory and indexes
|
||||
*/
|
||||
void Empty();
|
||||
|
||||
/**
|
||||
* Pushes a data word to the end of the FIFO. WILL OVERWRITE OLDEST if full.
|
||||
* @param Val The data word to push
|
||||
*/
|
||||
void Enqueue(const DataType& Val);
|
||||
|
||||
/**
|
||||
* Pushes a buffer of data words to the end of the FIFO. WILL OVERWRITE OLDEST if full.
|
||||
* @param ValBuf The buffer pointer
|
||||
* @param BufLen The length to copy
|
||||
*/
|
||||
void Enqueue(const DataType* ValBuf, const uint32& BufLen);
|
||||
|
||||
/**
|
||||
* Take the next data word from the FIFO buffer.
|
||||
* @param OUT ValOut The variable to receive the data word
|
||||
* @return true if the buffer was not empty, false otherwise.
|
||||
*/
|
||||
bool Dequeue(DataType& ValOut);
|
||||
|
||||
/**
|
||||
* Take the next set of data words from the FIFO buffer.
|
||||
* @param ValBuf The buffer to receive the data
|
||||
* @param BufLen The number of words requested
|
||||
* @return the number of words actually copied
|
||||
*/
|
||||
uint32 Dequeue(DataType* ValBuf, const uint32& BufLen);
|
||||
|
||||
/**
|
||||
* Get the next data word from the FIFO buffer without removing it.
|
||||
* @param OUT ValOut The variable to receive the data word
|
||||
* @return true if the buffer was not empty, false otherwise.
|
||||
*/
|
||||
bool Peek(DataType& ValOut) const;
|
||||
|
||||
/**
|
||||
* Get the next set of data words from the FIFO buffer without removing them.
|
||||
* @param ValBuf The buffer to receive the data
|
||||
* @param BufLen The number of words requested
|
||||
* @return the number of words actually copied
|
||||
*/
|
||||
uint32 Peek(DataType* ValBuf, const uint32& BufLen) const;
|
||||
|
||||
/**
|
||||
* Compare the memory in the FIFO to the memory in the given buffer
|
||||
* @param SerialBuffer The buffer containing data to compare
|
||||
* @param CompareLen The number of words to compare
|
||||
* @return < 0 if data < SerialBuffer.. 0 if data == SerialBuffer... > 0 if data > SerialBuffer
|
||||
*/
|
||||
int32 SerialCompare(const DataType* SerialBuffer, uint32 CompareLen) const;
|
||||
|
||||
/**
|
||||
* Get the SHA1 hash for the data currently in the FIFO
|
||||
* @param OutHash Receives the SHA hash
|
||||
*/
|
||||
void GetShaHash(FSHAHash& OutHash) const;
|
||||
|
||||
/**
|
||||
* Serializes the internal buffer into the given buffer
|
||||
* @param SerialBuffer A preallocated buffer to copy data into
|
||||
*/
|
||||
void Serialize(DataType* SerialBuffer) const;
|
||||
|
||||
/**
|
||||
* Square bracket operators for accessing data in the buffer by FIFO index. [0] returns the next entry in the FIFO that would get provided by Dequeue or Peek.
|
||||
* @param Index The index into the FIFO buffer
|
||||
* @return The data word
|
||||
*/
|
||||
FORCEINLINE const DataType& operator[](const int32& Index) const;
|
||||
FORCEINLINE DataType& operator[](const int32& Index);
|
||||
|
||||
/**
|
||||
* Gets the last data word in the FIFO (i.e. most recently pushed).
|
||||
* @return The last data word
|
||||
*/
|
||||
FORCEINLINE const DataType& Top() const;
|
||||
FORCEINLINE DataType& Top();
|
||||
|
||||
/**
|
||||
* Gets the first data word in the FIFO (i.e. oldest).
|
||||
* @return The first data word
|
||||
*/
|
||||
FORCEINLINE const DataType& Bottom() const;
|
||||
FORCEINLINE DataType& Bottom();
|
||||
|
||||
/**
|
||||
* Gets the buffer index that the last data word is stored in.
|
||||
* @return The index of Top()
|
||||
*/
|
||||
FORCEINLINE uint32 TopIndex() const;
|
||||
|
||||
/**
|
||||
* Gets the buffer index that the first data word is stored in.
|
||||
* @return The index of Bottom()
|
||||
*/
|
||||
FORCEINLINE uint32 BottomIndex() const;
|
||||
|
||||
/**
|
||||
* Gets the buffer index that the next enqueued word will get stored in.
|
||||
* @return The index that the next enqueued word will have
|
||||
*/
|
||||
FORCEINLINE uint32 NextIndex() const;
|
||||
|
||||
/**
|
||||
* Gets the size of the data buffer.
|
||||
* @return Template arg BufferDataSize
|
||||
*/
|
||||
FORCEINLINE uint32 RingDataSize() const;
|
||||
|
||||
/**
|
||||
* Gets the number of words currently in the FIFO.
|
||||
* @return data size
|
||||
*/
|
||||
FORCEINLINE uint32 RingDataUsage() const;
|
||||
|
||||
/**
|
||||
* Gets the total number of words that have been pushed through this buffer since clearing
|
||||
* @return total length of data passed through
|
||||
*/
|
||||
FORCEINLINE uint64 TotalDataPushed() const;
|
||||
|
||||
/**
|
||||
* Maximum size the buffer can grow to (50 MB by default)
|
||||
*/
|
||||
static constexpr uint32 MaxBufferSize = 1024 * 1024 * 50;
|
||||
|
||||
/**
|
||||
* Resizes the buffer to a new size, preserving existing data
|
||||
* @param NewBufferSize The new size of the buffer
|
||||
* @return true if resize was successful, false otherwise
|
||||
*/
|
||||
bool Resize(uint32 NewBufferSize);
|
||||
|
||||
private:
|
||||
//TRingBuffer();
|
||||
|
||||
// Buffer size
|
||||
uint32 BufferDataSize;
|
||||
|
||||
// The data memory
|
||||
DataType* Data;
|
||||
|
||||
// Value keeping track of free space
|
||||
uint32 NumDataAvailable;
|
||||
|
||||
// Value keeping track of the next data index
|
||||
uint32 DataIndex;
|
||||
|
||||
// Value to keep track of total amount of data Enqueued
|
||||
uint64 TotalNumDataPushed;
|
||||
};
|
||||
|
||||
/* TRingBuffer implementation
|
||||
*****************************************************************************/
|
||||
template< typename DataType >
|
||||
TRingBuffer< DataType >::TRingBuffer(uint32 InBufferDataSize)
|
||||
: BufferDataSize(InBufferDataSize)
|
||||
{
|
||||
Data = new DataType[BufferDataSize];
|
||||
Empty();
|
||||
}
|
||||
|
||||
|
||||
template< typename DataType >
|
||||
void TRingBuffer< DataType >::Init(uint32 InBufferDataSize)
|
||||
{
|
||||
BufferDataSize = InBufferDataSize;
|
||||
Data = new DataType[BufferDataSize];
|
||||
Empty();
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
TRingBuffer< DataType >::TRingBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template< typename DataType >
|
||||
TRingBuffer< DataType >::~TRingBuffer()
|
||||
{
|
||||
delete[] Data;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
void TRingBuffer< DataType >::Empty()
|
||||
{
|
||||
FMemory::Memzero(Data, sizeof(DataType)* BufferDataSize);
|
||||
NumDataAvailable = 0;
|
||||
DataIndex = 0;
|
||||
TotalNumDataPushed = 0;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
void TRingBuffer< DataType >::Enqueue(const DataType& Val)
|
||||
{
|
||||
Data[DataIndex++] = Val;
|
||||
DataIndex %= BufferDataSize;
|
||||
++TotalNumDataPushed;
|
||||
NumDataAvailable = FMath::Clamp< uint32 >(NumDataAvailable + 1, 0, BufferDataSize);
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
void TRingBuffer< DataType >::Enqueue(const DataType* ValBuf, const uint32& BufLen)
|
||||
{
|
||||
// Check if we need to resize
|
||||
if (BufLen > BufferDataSize || NumDataAvailable + BufLen > BufferDataSize)
|
||||
{
|
||||
// Calculate new size (double the current size or enough to fit the new data, whichever is larger)
|
||||
uint32 NewSize = FMath::Max(BufferDataSize * 2, NumDataAvailable + BufLen);
|
||||
|
||||
// Cap the maximum size
|
||||
NewSize = FMath::Min(NewSize, MaxBufferSize);
|
||||
|
||||
// Try to resize
|
||||
bool ResizeSuccess = Resize(NewSize);
|
||||
|
||||
// If resize failed and the buffer is too small for the new data
|
||||
if (!ResizeSuccess && BufLen > BufferDataSize)
|
||||
{
|
||||
// We can't fit the entire new buffer, so we'll copy as much as we can
|
||||
uint32 AmountToCopy = BufferDataSize;
|
||||
|
||||
// Copy from the end of the input buffer to get the most recent data
|
||||
const DataType* SourcePtr = ValBuf + (BufLen - AmountToCopy);
|
||||
|
||||
// Clear the buffer and copy what we can
|
||||
Empty();
|
||||
FMemory::Memcpy(Data, SourcePtr, sizeof(DataType) * AmountToCopy);
|
||||
NumDataAvailable = AmountToCopy;
|
||||
DataIndex = 0;
|
||||
TotalNumDataPushed += AmountToCopy;
|
||||
|
||||
return;
|
||||
}
|
||||
// If resize failed but we can fit some data by overwriting old data
|
||||
else if (!ResizeSuccess)
|
||||
{
|
||||
// Calculate how much old data we need to discard
|
||||
uint32 SpaceNeeded = NumDataAvailable + BufLen - BufferDataSize;
|
||||
|
||||
// Discard oldest data
|
||||
NumDataAvailable -= SpaceNeeded;
|
||||
|
||||
// Continue with normal enqueue below
|
||||
}
|
||||
}
|
||||
|
||||
// Original enqueue logic
|
||||
check(BufLen <= BufferDataSize);
|
||||
const uint32 FirstPartLen = BufferDataSize - DataIndex;
|
||||
FMemory::Memcpy(Data + DataIndex, ValBuf, sizeof(DataType) * FMath::Min(FirstPartLen, BufLen));
|
||||
if (FirstPartLen < BufLen)
|
||||
{
|
||||
FMemory::Memcpy(Data, ValBuf + FirstPartLen, sizeof(DataType) * (BufLen - FirstPartLen));
|
||||
}
|
||||
DataIndex += BufLen;
|
||||
DataIndex %= BufferDataSize;
|
||||
TotalNumDataPushed += BufLen;
|
||||
NumDataAvailable = FMath::Clamp<uint32>(NumDataAvailable + BufLen, 0, BufferDataSize);
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
bool TRingBuffer< DataType >::Dequeue(DataType& ValOut)
|
||||
{
|
||||
if (Peek(ValOut))
|
||||
{
|
||||
NumDataAvailable = FMath::Clamp< uint32 >(NumDataAvailable - 1, 0, BufferDataSize);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
uint32 TRingBuffer< DataType >::Dequeue(DataType* ValBuf, const uint32& BufLen)
|
||||
{
|
||||
uint32 DataProvided = 0;
|
||||
|
||||
if (ValBuf != nullptr)
|
||||
{
|
||||
// Normal case: copy data to the provided buffer
|
||||
DataProvided = Peek(ValBuf, BufLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Special case: just discard data without copying
|
||||
DataProvided = FMath::Min(BufLen, NumDataAvailable);
|
||||
}
|
||||
|
||||
// Update the available data count
|
||||
NumDataAvailable -= DataProvided;
|
||||
|
||||
return DataProvided;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
bool TRingBuffer< DataType >::Peek(DataType& ValOut) const
|
||||
{
|
||||
if (NumDataAvailable > 0)
|
||||
{
|
||||
ValOut = Bottom();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
uint32 TRingBuffer< DataType >::Peek(DataType* ValBuf, const uint32& BufLen) const
|
||||
{
|
||||
const uint32 DataProvided = FMath::Min(BufLen, NumDataAvailable);
|
||||
const uint32 BottomIdx = BottomIndex();
|
||||
const uint32 BottomPartLen = BufferDataSize - BottomIdx;
|
||||
FMemory::Memcpy(ValBuf, Data + BottomIdx, sizeof(DataType)* FMath::Min(BottomPartLen, DataProvided));
|
||||
if (BottomPartLen < DataProvided)
|
||||
{
|
||||
FMemory::Memcpy(ValBuf + BottomPartLen, Data, sizeof(DataType)* (DataProvided - BottomPartLen));
|
||||
}
|
||||
return DataProvided;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
int32 TRingBuffer< DataType >::SerialCompare(const DataType* SerialBuffer, uint32 CompareLen) const
|
||||
{
|
||||
check(CompareLen <= BufferDataSize);
|
||||
const uint32 FirstPartLen = BufferDataSize - DataIndex;
|
||||
int32 FirstCmp = FMemory::Memcmp(Data + BottomIndex(), SerialBuffer, sizeof(DataType)* FMath::Min(FirstPartLen, CompareLen));
|
||||
if (FirstCmp != 0 || FirstPartLen >= CompareLen)
|
||||
{
|
||||
return FirstCmp;
|
||||
}
|
||||
return FMemory::Memcmp(Data, &SerialBuffer[FirstPartLen], sizeof(DataType)* (CompareLen - FirstPartLen));
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
void TRingBuffer< DataType >::GetShaHash(FSHAHash& OutHash) const
|
||||
{
|
||||
const uint32 FirstPartLen = FMath::Min(BufferDataSize - DataIndex, NumDataAvailable);
|
||||
FSHA1 Sha;
|
||||
Sha.Update(Data + BottomIndex(), sizeof(DataType) * FirstPartLen);
|
||||
if (FirstPartLen < NumDataAvailable)
|
||||
{
|
||||
Sha.Update(Data, sizeof(DataType) * (NumDataAvailable - FirstPartLen));
|
||||
}
|
||||
Sha.Final();
|
||||
Sha.GetHash(OutHash.Hash);
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
void TRingBuffer< DataType >::Serialize(DataType* SerialBuffer) const
|
||||
{
|
||||
const uint32 BottomIdx = BottomIndex();
|
||||
const uint32 BottomPartLen = BufferDataSize - BottomIdx;
|
||||
FMemory::Memcpy(SerialBuffer, Data + BottomIdx, sizeof(DataType)* BottomPartLen);
|
||||
FMemory::Memcpy(SerialBuffer + BottomPartLen, Data, sizeof(DataType)* (BufferDataSize - BottomPartLen));
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE const DataType& TRingBuffer< DataType >::operator[](const int32& Index) const
|
||||
{
|
||||
return Data[(BottomIndex() + Index) % BufferDataSize];
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE DataType& TRingBuffer< DataType >::operator[](const int32& Index)
|
||||
{
|
||||
return Data[(BottomIndex() + Index) % BufferDataSize];
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE const DataType& TRingBuffer< DataType >::Top() const
|
||||
{
|
||||
return Data[TopIndex()];
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE DataType& TRingBuffer< DataType >::Top()
|
||||
{
|
||||
return Data[TopIndex()];
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE const DataType& TRingBuffer< DataType >::Bottom() const
|
||||
{
|
||||
return Data[BottomIndex()];
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE DataType& TRingBuffer< DataType >::Bottom()
|
||||
{
|
||||
return Data[BottomIndex()];
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE uint32 TRingBuffer< DataType >::TopIndex() const
|
||||
{
|
||||
return (DataIndex + BufferDataSize - 1) % BufferDataSize;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE uint32 TRingBuffer< DataType >::BottomIndex() const
|
||||
{
|
||||
return (DataIndex + BufferDataSize - NumDataAvailable) % BufferDataSize;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE uint32 TRingBuffer< DataType >::NextIndex() const
|
||||
{
|
||||
return DataIndex;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE uint32 TRingBuffer< DataType >::RingDataSize() const
|
||||
{
|
||||
return BufferDataSize;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE uint32 TRingBuffer< DataType >::RingDataUsage() const
|
||||
{
|
||||
return NumDataAvailable;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
FORCEINLINE uint64 TRingBuffer< DataType >::TotalDataPushed() const
|
||||
{
|
||||
return TotalNumDataPushed;
|
||||
}
|
||||
|
||||
template< typename DataType >
|
||||
bool TRingBuffer< DataType >::Resize(uint32 NewBufferSize)
|
||||
{
|
||||
// Don't resize if new size is smaller than current usage
|
||||
if (NewBufferSize < NumDataAvailable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a new buffer
|
||||
DataType* NewData = new DataType[NewBufferSize];
|
||||
if (!NewData)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy existing data to the new buffer
|
||||
if (NumDataAvailable > 0)
|
||||
{
|
||||
// Get the current data in sequential order
|
||||
const uint32 BottomIdx = BottomIndex();
|
||||
const uint32 BottomPartLen = FMath::Min(BufferDataSize - BottomIdx, NumDataAvailable);
|
||||
|
||||
// Copy first part (from bottom index to end of buffer)
|
||||
FMemory::Memcpy(NewData, Data + BottomIdx, sizeof(DataType) * BottomPartLen);
|
||||
|
||||
// Copy second part (from start of buffer if wrapped)
|
||||
if (BottomPartLen < NumDataAvailable)
|
||||
{
|
||||
FMemory::Memcpy(NewData + BottomPartLen, Data, sizeof(DataType) * (NumDataAvailable - BottomPartLen));
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up old buffer and update state
|
||||
delete[] Data;
|
||||
Data = NewData;
|
||||
BufferDataSize = NewBufferSize;
|
||||
|
||||
// Reset the data index to start at 0
|
||||
DataIndex = NumDataAvailable % BufferDataSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// ConvaiLogger.h
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "HAL/Runnable.h"
|
||||
#include "HAL/RunnableThread.h"
|
||||
#include "Containers/Queue.h"
|
||||
#include "Misc/DateTime.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "HAL/PlatformFileManager.h"
|
||||
#include "HAL/PlatformFile.h"
|
||||
#include "HAL/ThreadSafeBool.h"
|
||||
#include "HAL/Event.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "ConvaiLogger.generated.h"
|
||||
|
||||
// In editor: log to both UE4’s log window AND your file logger
|
||||
#define CONVAI_LOG(Category, Verbosity, Format, ...) \
|
||||
UE_LOG(Category, Verbosity, Format, ##__VA_ARGS__); \
|
||||
FConvaiLogger::Get().Log( \
|
||||
FString::Printf( \
|
||||
TEXT(#Category) TEXT(" : ") TEXT(#Verbosity) TEXT(" : ") Format, \
|
||||
##__VA_ARGS__ \
|
||||
) \
|
||||
);
|
||||
|
||||
/**
|
||||
* Asynchronous, file-based logger singleton using IFileHandle in append mode.
|
||||
*/
|
||||
class CONVAI_API FConvaiLogger final : public FRunnable
|
||||
{
|
||||
public:
|
||||
static FConvaiLogger& Get();
|
||||
void Log(const FString& Message);
|
||||
|
||||
// FRunnable interface
|
||||
virtual uint32 Run() override;
|
||||
virtual void Stop() override;
|
||||
|
||||
private:
|
||||
FConvaiLogger();
|
||||
virtual ~FConvaiLogger() override;
|
||||
|
||||
// start/stop thread
|
||||
void StartThread();
|
||||
void ShutdownThread();
|
||||
|
||||
FRunnableThread* Thread;
|
||||
TQueue<FString, EQueueMode::Mpsc> MessageQueue;
|
||||
FEvent* WakeEvent;
|
||||
FString LogFilePath;
|
||||
FThreadSafeBool bStopping;
|
||||
};
|
||||
|
||||
|
||||
// BP function lib for logging
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EC_LogLevel : uint8
|
||||
{
|
||||
Verbose UMETA(DisplayName="Verbose"),
|
||||
Log UMETA(DisplayName="Log"),
|
||||
Warning UMETA(DisplayName="Warning"),
|
||||
Error UMETA(DisplayName="Error"),
|
||||
Fatal UMETA(DisplayName="Fatal")
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class CONVAI_API UConvaiBlueprintLogger : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/**
|
||||
* Logs a message with context of which Blueprint object called this.
|
||||
* @param WorldContextObject – automatically filled by Blueprint
|
||||
* @param Verbosity – choose your verbosity level
|
||||
* @param Message – the text you want to log
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, meta=(WorldContext="WorldContextObject", DisplayName="ConvaiLog"), Category="Convai|Logging")
|
||||
static void C_ConvaiLog(UObject* WorldContextObject, EC_LogLevel Verbosity, const FString& Message);
|
||||
};
|
||||
140
ConvAI/Convai/Source/Convai/Public/VisionInterface.h
Normal file
140
ConvAI/Convai/Source/Convai/Public/VisionInterface.h
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
#include "Engine/Texture.h"
|
||||
#include "VisionInterface.generated.h"
|
||||
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class ETextureSourceType : uint8
|
||||
{
|
||||
Texture2D UMETA(DisplayName = "Texture2D"),
|
||||
RenderTarget2D UMETA(DisplayName = "RenderTarget2D")
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EVisionState : uint8
|
||||
{
|
||||
Stopped UMETA(DisplayName = "Stopped"), // Vision system is inactive and stopped
|
||||
Starting UMETA(DisplayName = "Starting"), // Vision system is initializing
|
||||
Capturing UMETA(DisplayName = "Capturing"), // Vision system is capturing data
|
||||
Stopping UMETA(DisplayName = "Stopping"), // Vision system is in the process of stopping
|
||||
Paused UMETA(DisplayName = "Paused"), // Vision system is paused and not capturing
|
||||
};
|
||||
|
||||
// Delegate to handle state change notifications
|
||||
DECLARE_DELEGATE_OneParam(FOnVisionStateChanged, EVisionState);
|
||||
|
||||
// Delegate to handle when the first frame has been captured
|
||||
DECLARE_DELEGATE(FOnFirstFrameCaptured);
|
||||
|
||||
// Delegate to handle when frames have stopped capturing
|
||||
DECLARE_DELEGATE(FOnFramesStopped);
|
||||
|
||||
UINTERFACE()
|
||||
class CONVAI_API UConvaiVisionInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class IConvaiVisionInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Delegate called when the vision state changes
|
||||
FOnVisionStateChanged OnVisionStateChanged;
|
||||
|
||||
// Delegate called when the first frame is captured
|
||||
FOnFirstFrameCaptured OnFirstFrameCaptured;
|
||||
|
||||
// Delegate called when frame capturing stops
|
||||
FOnFramesStopped OnFramesStopped;
|
||||
|
||||
/**
|
||||
* Starts the vision component.
|
||||
* This will transition the state from Stopped or Paused to Capturing.
|
||||
*/
|
||||
virtual void Start() = 0;
|
||||
|
||||
/**
|
||||
* Stops the vision component.
|
||||
* This will transition the state from Capturing or Paused to Stopped.
|
||||
*/
|
||||
virtual void Stop() = 0;
|
||||
|
||||
/**
|
||||
* Retrieves the current vision state.
|
||||
* @return The current EVisionState of the component.
|
||||
*/
|
||||
virtual EVisionState GetState() const = 0;
|
||||
|
||||
/**
|
||||
* Sets the maximum frames per second (FPS) that the vision component will capture.
|
||||
* @param MaxFPS The maximum FPS value to set.
|
||||
*/
|
||||
virtual void SetMaxFPS(int MaxFPS) = 0;
|
||||
|
||||
/**
|
||||
* Gets the current maximum FPS setting.
|
||||
* @return The maximum FPS setting.
|
||||
*/
|
||||
virtual int GetMaxFPS() const = 0;
|
||||
|
||||
/**
|
||||
* Checks if compressed image data is already available (e.g., received from an external source).
|
||||
* @return True if compressed data is available, false otherwise.
|
||||
*/
|
||||
virtual bool IsCompressedDataAvailable() const = 0;
|
||||
|
||||
/**
|
||||
* Retrieves the pre-existing compressed image data (if available).
|
||||
* @param width The width of the compressed image.
|
||||
* @param height The height of the compressed image.
|
||||
* @param data The array to store the compressed image data.
|
||||
* @return True if compressed data was successfully retrieved, false otherwise.
|
||||
*/
|
||||
virtual bool GetCompressedData(int& width, int& height, TArray<uint8>& data) = 0;
|
||||
|
||||
/**
|
||||
* Captures the current frame in a compressed format with a specific compression ratio.
|
||||
* @param width The width of the captured image, populated by the function.
|
||||
* @param height The height of the captured image, populated by the function.
|
||||
* @param data An array to store the compressed image data, populated by the function.
|
||||
* @param ForceCompressionRatio A specific compression ratio to apply during capture.
|
||||
* @return True if capture succeeded, false otherwise.
|
||||
*/
|
||||
virtual bool CaptureCompressed(int& width, int& height, TArray<uint8>& data, float ForceCompressionRatio) = 0;
|
||||
|
||||
/**
|
||||
* Captures the current frame in raw format (uncompressed).
|
||||
* @param width The width of the captured image, populated by the function.
|
||||
* @param height The height of the captured image, populated by the function.
|
||||
* @param data An array to store the raw image data, populated by the function.
|
||||
* @return True if capture succeeded, false otherwise.
|
||||
*/
|
||||
virtual bool CaptureRaw(int& width, int& height, TArray<uint8>& data) = 0;
|
||||
|
||||
/**
|
||||
* Retrieves the texture of the captured image based on the source type.
|
||||
* @param TextureSourceType The type of texture source (Texture2D or RenderTarget2D).
|
||||
* @return A pointer to the UTexture containing the captured image.
|
||||
*/
|
||||
virtual UTexture* GetImageTexture(ETextureSourceType& TextureSourceType) = 0;
|
||||
|
||||
/**
|
||||
* Retrieves the last error message encountered by the vision component.
|
||||
* @return The last error message as a string.
|
||||
*/
|
||||
virtual FString GetLastErrorMessage() const = 0;
|
||||
|
||||
/**
|
||||
* Retrieves the last error code encountered by the vision component.
|
||||
* @return The last error code.
|
||||
*/
|
||||
virtual int GetLastErrorCode() const = 0;
|
||||
};
|
||||
64
ConvAI/Convai/Source/ConvaiEditor/ConvaiEditor.Build.cs
Normal file
64
ConvAI/Convai/Source/ConvaiEditor/ConvaiEditor.Build.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class ConvaiEditor : ModuleRules
|
||||
{
|
||||
public ConvaiEditor(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"InputCore",
|
||||
"UMG",
|
||||
"Convai",
|
||||
"UMGEditor",
|
||||
"Blutility",
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"UnrealEd",
|
||||
"LevelEditor",
|
||||
"EditorScriptingUtilities",
|
||||
"PropertyEditor",
|
||||
"DeveloperSettings",
|
||||
"Convai",
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "ConvaiEUWBase.h"
|
||||
|
||||
103
ConvAI/Convai/Source/ConvaiEditor/Private/ConvaiEditor.cpp
Normal file
103
ConvAI/Convai/Source/ConvaiEditor/Private/ConvaiEditor.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#include "ConvaiEditor.h"
|
||||
#include "EditorUtilitySubsystem.h"
|
||||
#include "Widgets/Input/SButton.h"
|
||||
#include "DetailLayoutBuilder.h"
|
||||
#include "DetailCategoryBuilder.h"
|
||||
#include "DetailWidgetRow.h"
|
||||
#include "../Convai.h"
|
||||
#include "EditorUtilityWidgetBlueprint.h"
|
||||
#include "Utility/Log/ConvaiLogger.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FConvaiEditorModule"
|
||||
|
||||
void FConvaiEditorModule::StartupModule()
|
||||
{
|
||||
// Register settings customization
|
||||
FPropertyEditorModule& PropertyEditor = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
|
||||
PropertyEditor.RegisterCustomClassLayout(
|
||||
UConvaiSettings::StaticClass()->GetFName(),
|
||||
FOnGetDetailCustomizationInstance::CreateStatic(&FConvaiEditorSettingsCustomization::MakeInstance)
|
||||
);
|
||||
|
||||
// Notify customization module
|
||||
PropertyEditor.NotifyCustomizationModuleChanged();
|
||||
}
|
||||
|
||||
void FConvaiEditorModule::ShutdownModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FConvaiEditorModule, ConvaiEditor)
|
||||
|
||||
|
||||
|
||||
|
||||
TSharedRef<IDetailCustomization> FConvaiEditorSettingsCustomization::MakeInstance()
|
||||
{
|
||||
return MakeShareable(new FConvaiEditorSettingsCustomization);
|
||||
}
|
||||
|
||||
void FConvaiEditorSettingsCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
|
||||
{
|
||||
IDetailCategoryBuilder& ParentCategory = DetailBuilder.EditCategory(TEXT("Convai API"), FText::FromString("Convai API"));
|
||||
|
||||
ParentCategory.AddCustomRow(FText::FromString(""))
|
||||
.WholeRowWidget
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
];
|
||||
|
||||
IDetailCategoryBuilder& SubCategory = DetailBuilder.EditCategory(TEXT("Long Term Memory"), FText::FromString("Long Term Memory"));
|
||||
|
||||
// Add a compact button to the category
|
||||
SubCategory.AddCustomRow(FText::FromString("Spawn Tab"))
|
||||
.WholeRowWidget
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
.HAlign(HAlign_Left)
|
||||
.VAlign(VAlign_Center)
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SButton)
|
||||
.Text(FText::FromString("Manage Speaker ID"))
|
||||
.HAlign(HAlign_Center)
|
||||
.VAlign(VAlign_Center)
|
||||
.ContentPadding(FMargin(8.0f, 2.0f))
|
||||
.OnClicked(this, &FConvaiEditorSettingsCustomization::OnSpawnTabClicked)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
FReply FConvaiEditorSettingsCustomization::OnSpawnTabClicked()
|
||||
{
|
||||
const FString WidgetPath = TEXT("/ConvAI/Editor/EUW_LTM.EUW_LTM");
|
||||
|
||||
UEditorUtilityWidgetBlueprint* WidgetBlueprint = LoadObject<UEditorUtilityWidgetBlueprint>(nullptr, *WidgetPath);
|
||||
|
||||
if (WidgetBlueprint)
|
||||
{
|
||||
if (UEditorUtilitySubsystem* Subsystem = GEditor->GetEditorSubsystem<UEditorUtilitySubsystem>())
|
||||
{
|
||||
Subsystem->SpawnAndRegisterTab(WidgetBlueprint);
|
||||
CONVAI_LOG(LogTemp, Log, TEXT("Successfully spawned the Editor Utility Widget: %s"), *WidgetPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(LogTemp, Warning, TEXT("Failed to get Editor Utility Subsystem."));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(LogTemp, Error, TEXT("Failed to load Editor Utility Widget Blueprint at path: %s"), *WidgetPath);
|
||||
}
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "ConvaiEditorUtils.h"
|
||||
|
||||
#include "EditorUtilityLibrary.h"
|
||||
#include "../Convai.h"
|
||||
#include "ISettingsModule.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "EditorAssetLibrary.h"
|
||||
#include "Utility/Log/ConvaiLogger.h"
|
||||
|
||||
void UConvaiEditorUtils::ConvaiAddSpeakerID(const FConvaiSpeakerInfo& Speaker)
|
||||
{
|
||||
UConvaiSettings* Settings = GetMutableDefault<UConvaiSettings>();
|
||||
if (!Settings)
|
||||
{
|
||||
CONVAI_LOG(LogTemp, Warning, TEXT("ConvaiSettings not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
int32 Index = Settings->SpeakerIDs.IndexOfByPredicate([&](const FConvaiSpeakerInfo& Info)
|
||||
{
|
||||
return Info.SpeakerID == Speaker.SpeakerID;
|
||||
});
|
||||
|
||||
if (Index == INDEX_NONE)
|
||||
{
|
||||
Settings->SpeakerIDs.Add(Speaker);
|
||||
//CONVAI_LOG(LogTemp, Log, TEXT("Added Speaker: ID=%s, Name=%s"), *Speaker.SpeakerID, *Speaker.Name);
|
||||
}
|
||||
|
||||
Settings->SaveConfig(CPF_Config, *Settings->GetDefaultConfigFilename());
|
||||
|
||||
RefreshConvaiSettings();
|
||||
}
|
||||
|
||||
void UConvaiEditorUtils::ConvaiRemoveSpeakerID(const FString& SpeakerID)
|
||||
{
|
||||
UConvaiSettings* Settings = GetMutableDefault<UConvaiSettings>();
|
||||
if (!Settings)
|
||||
{
|
||||
CONVAI_LOG(LogTemp, Warning, TEXT("ConvaiSettings not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
int32 Index = Settings->SpeakerIDs.IndexOfByPredicate([&](const FConvaiSpeakerInfo& Info)
|
||||
{
|
||||
return Info.SpeakerID == SpeakerID;
|
||||
});
|
||||
|
||||
if (Index != INDEX_NONE)
|
||||
{
|
||||
Settings->SpeakerIDs.RemoveAt(Index);
|
||||
//CONVAI_LOG(LogTemp, Log, TEXT("Removed Speaker: ID=%s"), *SpeakerID);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONVAI_LOG(LogTemp, Warning, TEXT("Speaker ID not found: %s"), *SpeakerID);
|
||||
}
|
||||
|
||||
Settings->SaveConfig(CPF_Config, *Settings->GetDefaultConfigFilename());
|
||||
|
||||
RefreshConvaiSettings();
|
||||
}
|
||||
|
||||
#define LOCTEXT_NAMESPACE "Convai"
|
||||
void UConvaiEditorUtils::RefreshConvaiSettings()
|
||||
{
|
||||
if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
|
||||
{
|
||||
// Unregister the settings
|
||||
SettingsModule->UnregisterSettings("Project", "Plugins", "Convai");
|
||||
|
||||
// Re-register the settings
|
||||
UConvaiSettings* Settings = GetMutableDefault<UConvaiSettings>();
|
||||
SettingsModule->RegisterSettings("Project", "Plugins", "Convai",
|
||||
LOCTEXT("RuntimeSettingsName", "Convai"),
|
||||
LOCTEXT("RuntimeSettingsDescription", "Configure Convai settings"),
|
||||
Settings);
|
||||
}
|
||||
}
|
||||
|
||||
TArray<UObject*> UConvaiEditorUtils::BeginTransactionAndGetSelectedAssets(const FString& Context, const FText& Description)
|
||||
{
|
||||
UKismetSystemLibrary::BeginTransaction(Context, Description, nullptr);
|
||||
return UEditorUtilityLibrary::GetSelectedAssets();
|
||||
}
|
||||
|
||||
void UConvaiEditorUtils::SaveLoadedAssetAndEndTransaction(const TArray<UObject*>& LoadedAssets)
|
||||
{
|
||||
UEditorAssetLibrary::CheckoutLoadedAssets(LoadedAssets);
|
||||
UEditorAssetLibrary::SaveLoadedAssets(LoadedAssets);
|
||||
UKismetSystemLibrary::EndTransaction();
|
||||
}
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
17
ConvAI/Convai/Source/ConvaiEditor/Public/ConvaiEUWBase.h
Normal file
17
ConvAI/Convai/Source/ConvaiEditor/Public/ConvaiEUWBase.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "EditorUtilityWidget.h"
|
||||
#include "ConvaiEUWBase.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Abstract)
|
||||
class CONVAIEDITOR_API UConvaiEUWBase : public UEditorUtilityWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
};
|
||||
39
ConvAI/Convai/Source/ConvaiEditor/Public/ConvaiEditor.h
Normal file
39
ConvAI/Convai/Source/ConvaiEditor/Public/ConvaiEditor.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2022 Convai Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DeveloperSettings.h"
|
||||
#include "IDetailCustomization.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
|
||||
class FToolBarBuilder;
|
||||
class FMenuBuilder;
|
||||
|
||||
class FConvaiEditorModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class FConvaiEditorSettingsCustomization : public IDetailCustomization
|
||||
{
|
||||
public:
|
||||
static TSharedRef<IDetailCustomization> MakeInstance();
|
||||
|
||||
virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;
|
||||
|
||||
private:
|
||||
FReply OnSpawnTabClicked();
|
||||
};
|
||||
52
ConvAI/Convai/Source/ConvaiEditor/Public/ConvaiEditorUtils.h
Normal file
52
ConvAI/Convai/Source/ConvaiEditor/Public/ConvaiEditorUtils.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "ConvaiDefinitions.h"
|
||||
|
||||
#include "ConvaiEditorUtils.generated.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class CONVAIEDITOR_API UConvaiEditorUtils : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|LTM")
|
||||
static void ConvaiAddSpeakerID(const FConvaiSpeakerInfo& Speaker);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|LTM")
|
||||
static void ConvaiRemoveSpeakerID(const FString& SpeakerID);
|
||||
|
||||
//UFUNCTION(BlueprintCallable, Category = "Convai|LTM")
|
||||
static void RefreshConvaiSettings();
|
||||
|
||||
// ---------------------------------CCPack---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Begins a transaction in the editor and retrieves the currently selected assets.
|
||||
*
|
||||
* @param Context A string describing the context of the transaction.
|
||||
* @param Description A text description of the transaction.
|
||||
* @return An array of selected assets as UObject references.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Editor")
|
||||
static TArray<UObject*> BeginTransactionAndGetSelectedAssets(const FString& Context, const FText& Description);
|
||||
|
||||
/**
|
||||
* Saves the loaded assets and ends the current transaction.
|
||||
* @param LoadedAssets An array of assets to save.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Convai|Editor")
|
||||
static void SaveLoadedAssetAndEndTransaction(const TArray<UObject*>& LoadedAssets);
|
||||
|
||||
// ---------------------------------END CCPack---------------------------------------------------------------------
|
||||
};
|
||||
|
||||
82
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.cc
vendored
Normal file
82
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.cc
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/any.h>
|
||||
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/message.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
void AnyMetadata::PackFrom(const Message& message) {
|
||||
PackFrom(message, kTypeGoogleApisComPrefix);
|
||||
}
|
||||
|
||||
void AnyMetadata::PackFrom(const Message& message,
|
||||
StringPiece type_url_prefix) {
|
||||
type_url_->Set(
|
||||
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString(),
|
||||
GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix),
|
||||
nullptr);
|
||||
message.SerializeToString(
|
||||
value_->Mutable(ArenaStringPtr::EmptyDefault{}, nullptr));
|
||||
}
|
||||
|
||||
bool AnyMetadata::UnpackTo(Message* message) const {
|
||||
if (!InternalIs(message->GetDescriptor()->full_name())) {
|
||||
return false;
|
||||
}
|
||||
return message->ParseFromString(value_->Get());
|
||||
}
|
||||
|
||||
bool GetAnyFieldDescriptors(const Message& message,
|
||||
const FieldDescriptor** type_url_field,
|
||||
const FieldDescriptor** value_field) {
|
||||
const Descriptor* descriptor = message.GetDescriptor();
|
||||
if (descriptor->full_name() != kAnyFullTypeName) {
|
||||
return false;
|
||||
}
|
||||
*type_url_field = descriptor->FindFieldByNumber(1);
|
||||
*value_field = descriptor->FindFieldByNumber(2);
|
||||
return (*type_url_field != NULL &&
|
||||
(*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
|
||||
*value_field != NULL &&
|
||||
(*value_field)->type() == FieldDescriptor::TYPE_BYTES);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
150
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.h
vendored
Normal file
150
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.h
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ANY_H__
|
||||
#define GOOGLE_PROTOBUF_ANY_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class FieldDescriptor;
|
||||
class Message;
|
||||
|
||||
namespace internal {
|
||||
|
||||
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
|
||||
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
|
||||
extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
|
||||
|
||||
std::string GetTypeUrl(StringPiece message_name,
|
||||
StringPiece type_url_prefix);
|
||||
|
||||
// Helper class used to implement google::protobuf::Any.
|
||||
class PROTOBUF_EXPORT AnyMetadata {
|
||||
typedef ArenaStringPtr UrlType;
|
||||
typedef ArenaStringPtr ValueType;
|
||||
public:
|
||||
// AnyMetadata does not take ownership of "type_url" and "value".
|
||||
constexpr AnyMetadata(UrlType* type_url, ValueType* value)
|
||||
: type_url_(type_url), value_(value) {}
|
||||
|
||||
// Packs a message using the default type URL prefix: "type.googleapis.com".
|
||||
// The resulted type URL will be "type.googleapis.com/<message_full_name>".
|
||||
template <typename T>
|
||||
void PackFrom(const T& message) {
|
||||
InternalPackFrom(message, kTypeGoogleApisComPrefix, T::FullMessageName());
|
||||
}
|
||||
|
||||
void PackFrom(const Message& message);
|
||||
|
||||
// Packs a message using the given type URL prefix. The type URL will be
|
||||
// constructed by concatenating the message type's full name to the prefix
|
||||
// with an optional "/" separator if the prefix doesn't already end with "/".
|
||||
// For example, both PackFrom(message, "type.googleapis.com") and
|
||||
// PackFrom(message, "type.googleapis.com/") yield the same result type
|
||||
// URL: "type.googleapis.com/<message_full_name>".
|
||||
template <typename T>
|
||||
void PackFrom(const T& message, StringPiece type_url_prefix) {
|
||||
InternalPackFrom(message, type_url_prefix, T::FullMessageName());
|
||||
}
|
||||
|
||||
void PackFrom(const Message& message, StringPiece type_url_prefix);
|
||||
|
||||
// Unpacks the payload into the given message. Returns false if the message's
|
||||
// type doesn't match the type specified in the type URL (i.e., the full
|
||||
// name after the last "/" of the type URL doesn't match the message's actual
|
||||
// full name) or parsing the payload has failed.
|
||||
template <typename T>
|
||||
bool UnpackTo(T* message) const {
|
||||
return InternalUnpackTo(T::FullMessageName(), message);
|
||||
}
|
||||
|
||||
bool UnpackTo(Message* message) const;
|
||||
|
||||
// Checks whether the type specified in the type URL matches the given type.
|
||||
// A type is considered matching if its full name matches the full name after
|
||||
// the last "/" in the type URL.
|
||||
template <typename T>
|
||||
bool Is() const {
|
||||
return InternalIs(T::FullMessageName());
|
||||
}
|
||||
|
||||
private:
|
||||
void InternalPackFrom(const MessageLite& message,
|
||||
StringPiece type_url_prefix,
|
||||
StringPiece type_name);
|
||||
bool InternalUnpackTo(StringPiece type_name,
|
||||
MessageLite* message) const;
|
||||
bool InternalIs(StringPiece type_name) const;
|
||||
|
||||
UrlType* type_url_;
|
||||
ValueType* value_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
|
||||
};
|
||||
|
||||
// Get the proto type name from Any::type_url value. For example, passing
|
||||
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/"
|
||||
// in the type url separating the full type name.
|
||||
//
|
||||
// NOTE: this function is available publicly as:
|
||||
// google::protobuf::Any() // static method on the generated message type.
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name);
|
||||
|
||||
// Get the proto type name and prefix from Any::type_url value. For example,
|
||||
// passing "type.googleapis.com/rpc.QueryOrigin" will return
|
||||
// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if the type_url does not have a "/" in the
|
||||
// type url separating the full type name.
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
|
||||
std::string* full_type_name);
|
||||
|
||||
// See if message is of type google.protobuf.Any, if so, return the descriptors
|
||||
// for "type_url" and "value" fields.
|
||||
bool GetAnyFieldDescriptors(const Message& message,
|
||||
const FieldDescriptor** type_url_field,
|
||||
const FieldDescriptor** value_field);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ANY_H__
|
||||
346
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.pb.cc
vendored
Normal file
346
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.pb.cc
vendored
Normal file
@@ -0,0 +1,346 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#include <google/protobuf/any.pb.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class AnyDefaultTypeInternal {
|
||||
public:
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Any> _instance;
|
||||
} _Any_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
static void InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
{
|
||||
void* ptr = &PROTOBUF_NAMESPACE_ID::_Any_default_instance_;
|
||||
new (ptr) PROTOBUF_NAMESPACE_ID::Any();
|
||||
::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Any_google_2fprotobuf_2fany_2eproto =
|
||||
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto}, {}};
|
||||
|
||||
static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1];
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
|
||||
static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
|
||||
|
||||
const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fany_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
~0u, // no _has_bits_
|
||||
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Any, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
~0u, // no _weak_field_map_
|
||||
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Any, type_url_),
|
||||
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Any, value_),
|
||||
};
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
|
||||
{ 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::Any)},
|
||||
};
|
||||
|
||||
static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_Any_default_instance_),
|
||||
};
|
||||
|
||||
const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
|
||||
"\n\031google/protobuf/any.proto\022\017google.prot"
|
||||
"obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
|
||||
" \001(\014Bv\n\023com.google.protobufB\010AnyProtoP\001Z"
|
||||
",google.golang.org/protobuf/types/known/"
|
||||
"anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownT"
|
||||
"ypesb\006proto3"
|
||||
;
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fany_2eproto_deps[1] = {
|
||||
};
|
||||
static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fany_2eproto_sccs[1] = {
|
||||
&scc_info_Any_google_2fprotobuf_2fany_2eproto.base,
|
||||
};
|
||||
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once;
|
||||
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = {
|
||||
false, false, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto", 212,
|
||||
&descriptor_table_google_2fprotobuf_2fany_2eproto_once, descriptor_table_google_2fprotobuf_2fany_2eproto_sccs, descriptor_table_google_2fprotobuf_2fany_2eproto_deps, 1, 0,
|
||||
schemas, file_default_instances, TableStruct_google_2fprotobuf_2fany_2eproto::offsets,
|
||||
file_level_metadata_google_2fprotobuf_2fany_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
|
||||
};
|
||||
|
||||
// Force running AddDescriptors() at dynamic initialization time.
|
||||
static bool dynamic_init_dummy_google_2fprotobuf_2fany_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fany_2eproto)), true);
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
bool Any::GetAnyFieldDescriptors(
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& message,
|
||||
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
|
||||
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field) {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::GetAnyFieldDescriptors(
|
||||
message, type_url_field, value_field);
|
||||
}
|
||||
bool Any::ParseAnyTypeUrl(
|
||||
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
|
||||
std::string* full_type_name) {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::ParseAnyTypeUrl(type_url,
|
||||
full_type_name);
|
||||
}
|
||||
|
||||
class Any::_Internal {
|
||||
public:
|
||||
};
|
||||
|
||||
Any::Any(::PROTOBUF_NAMESPACE_ID::Arena* arena)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(arena),
|
||||
_any_metadata_(&type_url_, &value_) {
|
||||
SharedCtor();
|
||||
RegisterArenaDtor(arena);
|
||||
// @@protoc_insertion_point(arena_constructor:google.protobuf.Any)
|
||||
}
|
||||
Any::Any(const Any& from)
|
||||
: ::PROTOBUF_NAMESPACE_ID::Message(),
|
||||
_any_metadata_(&type_url_, &value_) {
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
if (!from._internal_type_url().empty()) {
|
||||
type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_url(),
|
||||
GetArena());
|
||||
}
|
||||
value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
if (!from._internal_value().empty()) {
|
||||
value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(),
|
||||
GetArena());
|
||||
}
|
||||
// @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
|
||||
}
|
||||
|
||||
void Any::SharedCtor() {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Any_google_2fprotobuf_2fany_2eproto.base);
|
||||
type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
Any::~Any() {
|
||||
// @@protoc_insertion_point(destructor:google.protobuf.Any)
|
||||
SharedDtor();
|
||||
_internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
void Any::SharedDtor() {
|
||||
GOOGLE_DCHECK(GetArena() == nullptr);
|
||||
type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
void Any::ArenaDtor(void* object) {
|
||||
Any* _this = reinterpret_cast< Any* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void Any::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
|
||||
}
|
||||
void Any::SetCachedSize(int size) const {
|
||||
_cached_size_.Set(size);
|
||||
}
|
||||
const Any& Any::default_instance() {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Any_google_2fprotobuf_2fany_2eproto.base);
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
|
||||
void Any::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
|
||||
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
type_url_.ClearToEmpty();
|
||||
value_.ClearToEmpty();
|
||||
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
const char* Any::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
|
||||
#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
|
||||
while (!ctx->Done(&ptr)) {
|
||||
::PROTOBUF_NAMESPACE_ID::uint32 tag;
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
|
||||
CHK_(ptr);
|
||||
switch (tag >> 3) {
|
||||
// string type_url = 1;
|
||||
case 1:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) {
|
||||
auto str = _internal_mutable_type_url();
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
|
||||
CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Any.type_url"));
|
||||
CHK_(ptr);
|
||||
} else goto handle_unusual;
|
||||
continue;
|
||||
// bytes value = 2;
|
||||
case 2:
|
||||
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) {
|
||||
auto str = _internal_mutable_value();
|
||||
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
|
||||
CHK_(ptr);
|
||||
} else goto handle_unusual;
|
||||
continue;
|
||||
default: {
|
||||
handle_unusual:
|
||||
if ((tag & 7) == 4 || tag == 0) {
|
||||
ctx->SetLastTag(tag);
|
||||
goto success;
|
||||
}
|
||||
ptr = UnknownFieldParse(tag,
|
||||
_internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
|
||||
ptr, ctx);
|
||||
CHK_(ptr != nullptr);
|
||||
continue;
|
||||
}
|
||||
} // switch
|
||||
} // while
|
||||
success:
|
||||
return ptr;
|
||||
failure:
|
||||
ptr = nullptr;
|
||||
goto success;
|
||||
#undef CHK_
|
||||
}
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::uint8* Any::_InternalSerialize(
|
||||
::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
|
||||
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
|
||||
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->_internal_type_url().data(), static_cast<int>(this->_internal_type_url().length()),
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
|
||||
"google.protobuf.Any.type_url");
|
||||
target = stream->WriteStringMaybeAliased(
|
||||
1, this->_internal_type_url(), target);
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
target = stream->WriteBytesMaybeAliased(
|
||||
2, this->_internal_value(), target);
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
|
||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
|
||||
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
|
||||
}
|
||||
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t Any::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
|
||||
size_t total_size = 0;
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
|
||||
// Prevent compiler warnings about cached_has_bits being unused
|
||||
(void) cached_has_bits;
|
||||
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
|
||||
this->_internal_type_url());
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
total_size += 1 +
|
||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
|
||||
this->_internal_value());
|
||||
}
|
||||
|
||||
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
|
||||
return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize(
|
||||
_internal_metadata_, total_size, &_cached_size_);
|
||||
}
|
||||
int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
|
||||
SetCachedSize(cached_size);
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void Any::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
const Any* source =
|
||||
::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Any>(
|
||||
&from);
|
||||
if (source == nullptr) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Any)
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any)
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void Any::MergeFrom(const Any& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
|
||||
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
|
||||
(void) cached_has_bits;
|
||||
|
||||
if (from.type_url().size() > 0) {
|
||||
_internal_set_type_url(from._internal_type_url());
|
||||
}
|
||||
if (from.value().size() > 0) {
|
||||
_internal_set_value(from._internal_value());
|
||||
}
|
||||
}
|
||||
|
||||
void Any::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Any)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void Any::CopyFrom(const Any& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool Any::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Any::InternalSwap(Any* other) {
|
||||
using std::swap;
|
||||
_internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
|
||||
type_url_.Swap(&other->type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
|
||||
value_.Swap(&other->value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
|
||||
}
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata Any::GetMetadata() const {
|
||||
return GetMetadataStatic();
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Any >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Any >(arena);
|
||||
}
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
405
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.pb.h
vendored
Normal file
405
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.pb.h
vendored
Normal file
@@ -0,0 +1,405 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#if PROTOBUF_VERSION < 3014000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3014000 < PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_table_driven.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata_lite.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
#include <google/protobuf/port_def.inc>
|
||||
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto PROTOBUF_EXPORT
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
namespace internal {
|
||||
class AnyMetadata;
|
||||
} // namespace internal
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// Internal implementation detail -- do not use these members.
|
||||
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto {
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
|
||||
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
|
||||
static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
|
||||
static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
|
||||
};
|
||||
extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
class Any;
|
||||
class AnyDefaultTypeInternal;
|
||||
PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::Any>(Arena*);
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
PROTOBUF_NAMESPACE_OPEN
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class PROTOBUF_EXPORT Any PROTOBUF_FINAL :
|
||||
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
|
||||
public:
|
||||
inline Any() : Any(nullptr) {}
|
||||
virtual ~Any();
|
||||
|
||||
Any(const Any& from);
|
||||
Any(Any&& from) noexcept
|
||||
: Any() {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
|
||||
inline Any& operator=(const Any& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline Any& operator=(Any&& from) noexcept {
|
||||
if (GetArena() == from.GetArena()) {
|
||||
if (this != &from) InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
|
||||
return GetMetadataStatic().descriptor;
|
||||
}
|
||||
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
|
||||
return GetMetadataStatic().reflection;
|
||||
}
|
||||
static const Any& default_instance();
|
||||
|
||||
static inline const Any* internal_default_instance() {
|
||||
return reinterpret_cast<const Any*>(
|
||||
&_Any_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages =
|
||||
0;
|
||||
|
||||
// implements Any -----------------------------------------------
|
||||
|
||||
void PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) {
|
||||
_any_metadata_.PackFrom(message);
|
||||
}
|
||||
void PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message,
|
||||
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
|
||||
_any_metadata_.PackFrom(message, type_url_prefix);
|
||||
}
|
||||
bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const {
|
||||
return _any_metadata_.UnpackTo(message);
|
||||
}
|
||||
static bool GetAnyFieldDescriptors(
|
||||
const ::PROTOBUF_NAMESPACE_ID::Message& message,
|
||||
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
|
||||
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field);
|
||||
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
|
||||
void PackFrom(const T& message) {
|
||||
_any_metadata_.PackFrom<T>(message);
|
||||
}
|
||||
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
|
||||
void PackFrom(const T& message,
|
||||
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
|
||||
_any_metadata_.PackFrom<T>(message, type_url_prefix);}
|
||||
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
|
||||
bool UnpackTo(T* message) const {
|
||||
return _any_metadata_.UnpackTo<T>(message);
|
||||
}
|
||||
template<typename T> bool Is() const {
|
||||
return _any_metadata_.Is<T>();
|
||||
}
|
||||
static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
|
||||
std::string* full_type_name);
|
||||
friend void swap(Any& a, Any& b) {
|
||||
a.Swap(&b);
|
||||
}
|
||||
inline void Swap(Any* other) {
|
||||
if (other == this) return;
|
||||
if (GetArena() == other->GetArena()) {
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(Any* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetArena() == other->GetArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Any* New() const final {
|
||||
return CreateMaybeMessage<Any>(nullptr);
|
||||
}
|
||||
|
||||
Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
|
||||
return CreateMaybeMessage<Any>(arena);
|
||||
}
|
||||
void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
|
||||
void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
|
||||
void CopyFrom(const Any& from);
|
||||
void MergeFrom(const Any& from);
|
||||
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
|
||||
::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize(
|
||||
::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const final { return _cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
inline void SharedCtor();
|
||||
inline void SharedDtor();
|
||||
void SetCachedSize(int size) const final;
|
||||
void InternalSwap(Any* other);
|
||||
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
|
||||
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
|
||||
return "google.protobuf.Any";
|
||||
}
|
||||
protected:
|
||||
explicit Any(::PROTOBUF_NAMESPACE_ID::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
|
||||
public:
|
||||
|
||||
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
|
||||
private:
|
||||
static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
|
||||
::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fany_2eproto);
|
||||
return ::descriptor_table_google_2fprotobuf_2fany_2eproto.file_level_metadata[kIndexInFileMessages];
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
enum : int {
|
||||
kTypeUrlFieldNumber = 1,
|
||||
kValueFieldNumber = 2,
|
||||
};
|
||||
// string type_url = 1;
|
||||
void clear_type_url();
|
||||
const std::string& type_url() const;
|
||||
void set_type_url(const std::string& value);
|
||||
void set_type_url(std::string&& value);
|
||||
void set_type_url(const char* value);
|
||||
void set_type_url(const char* value, size_t size);
|
||||
std::string* mutable_type_url();
|
||||
std::string* release_type_url();
|
||||
void set_allocated_type_url(std::string* type_url);
|
||||
private:
|
||||
const std::string& _internal_type_url() const;
|
||||
void _internal_set_type_url(const std::string& value);
|
||||
std::string* _internal_mutable_type_url();
|
||||
public:
|
||||
|
||||
// bytes value = 2;
|
||||
void clear_value();
|
||||
const std::string& value() const;
|
||||
void set_value(const std::string& value);
|
||||
void set_value(std::string&& value);
|
||||
void set_value(const char* value);
|
||||
void set_value(const void* value, size_t size);
|
||||
std::string* mutable_value();
|
||||
std::string* release_value();
|
||||
void set_allocated_value(std::string* value);
|
||||
private:
|
||||
const std::string& _internal_value() const;
|
||||
void _internal_set_value(const std::string& value);
|
||||
std::string* _internal_mutable_value();
|
||||
public:
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Any)
|
||||
private:
|
||||
class _Internal;
|
||||
|
||||
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_url_;
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr value_;
|
||||
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
|
||||
::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata _any_metadata_;
|
||||
friend struct ::TableStruct_google_2fprotobuf_2fany_2eproto;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif // __GNUC__
|
||||
// Any
|
||||
|
||||
// string type_url = 1;
|
||||
inline void Any::clear_type_url() {
|
||||
type_url_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& Any::type_url() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
|
||||
return _internal_type_url();
|
||||
}
|
||||
inline void Any::set_type_url(const std::string& value) {
|
||||
_internal_set_type_url(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline std::string* Any::mutable_type_url() {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
|
||||
return _internal_mutable_type_url();
|
||||
}
|
||||
inline const std::string& Any::_internal_type_url() const {
|
||||
return type_url_.Get();
|
||||
}
|
||||
inline void Any::_internal_set_type_url(const std::string& value) {
|
||||
|
||||
type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
|
||||
}
|
||||
inline void Any::set_type_url(std::string&& value) {
|
||||
|
||||
type_url_.Set(
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline void Any::set_type_url(const char* value) {
|
||||
GOOGLE_DCHECK(value != nullptr);
|
||||
|
||||
type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline void Any::set_type_url(const char* value,
|
||||
size_t size) {
|
||||
|
||||
type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArena());
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline std::string* Any::_internal_mutable_type_url() {
|
||||
|
||||
return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
|
||||
}
|
||||
inline std::string* Any::release_type_url() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
|
||||
return type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
|
||||
}
|
||||
inline void Any::set_allocated_type_url(std::string* type_url) {
|
||||
if (type_url != nullptr) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), type_url,
|
||||
GetArena());
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
inline void Any::clear_value() {
|
||||
value_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& Any::value() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
|
||||
return _internal_value();
|
||||
}
|
||||
inline void Any::set_value(const std::string& value) {
|
||||
_internal_set_value(value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
|
||||
}
|
||||
inline std::string* Any::mutable_value() {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
|
||||
return _internal_mutable_value();
|
||||
}
|
||||
inline const std::string& Any::_internal_value() const {
|
||||
return value_.Get();
|
||||
}
|
||||
inline void Any::_internal_set_value(const std::string& value) {
|
||||
|
||||
value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
|
||||
}
|
||||
inline void Any::set_value(std::string&& value) {
|
||||
|
||||
value_.Set(
|
||||
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value)
|
||||
}
|
||||
inline void Any::set_value(const char* value) {
|
||||
GOOGLE_DCHECK(value != nullptr);
|
||||
|
||||
value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
|
||||
}
|
||||
inline void Any::set_value(const void* value,
|
||||
size_t size) {
|
||||
|
||||
value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArena());
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
|
||||
}
|
||||
inline std::string* Any::_internal_mutable_value() {
|
||||
|
||||
return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
|
||||
}
|
||||
inline std::string* Any::release_value() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.value)
|
||||
return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
|
||||
}
|
||||
inline void Any::set_allocated_value(std::string* value) {
|
||||
if (value != nullptr) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value,
|
||||
GetArena());
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
PROTOBUF_NAMESPACE_CLOSE
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
|
||||
158
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.proto
vendored
Normal file
158
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any.proto
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "google.golang.org/protobuf/types/known/anypb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "AnyProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
|
||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||
// URL that describes the type of the serialized message.
|
||||
//
|
||||
// Protobuf library provides support to pack/unpack Any values in the form
|
||||
// of utility functions or additional generated methods of the Any type.
|
||||
//
|
||||
// Example 1: Pack and unpack a message in C++.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any;
|
||||
// any.PackFrom(foo);
|
||||
// ...
|
||||
// if (any.UnpackTo(&foo)) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Example 2: Pack and unpack a message in Java.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any = Any.pack(foo);
|
||||
// ...
|
||||
// if (any.is(Foo.class)) {
|
||||
// foo = any.unpack(Foo.class);
|
||||
// }
|
||||
//
|
||||
// Example 3: Pack and unpack a message in Python.
|
||||
//
|
||||
// foo = Foo(...)
|
||||
// any = Any()
|
||||
// any.Pack(foo)
|
||||
// ...
|
||||
// if any.Is(Foo.DESCRIPTOR):
|
||||
// any.Unpack(foo)
|
||||
// ...
|
||||
//
|
||||
// Example 4: Pack and unpack a message in Go
|
||||
//
|
||||
// foo := &pb.Foo{...}
|
||||
// any, err := anypb.New(foo)
|
||||
// if err != nil {
|
||||
// ...
|
||||
// }
|
||||
// ...
|
||||
// foo := &pb.Foo{}
|
||||
// if err := any.UnmarshalTo(foo); err != nil {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// The pack methods provided by protobuf library will by default use
|
||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||
// methods only use the fully qualified type name after the last '/'
|
||||
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
|
||||
// name "y.z".
|
||||
//
|
||||
//
|
||||
// JSON
|
||||
// ====
|
||||
// The JSON representation of an `Any` value uses the regular
|
||||
// representation of the deserialized, embedded message, with an
|
||||
// additional field `@type` which contains the type URL. Example:
|
||||
//
|
||||
// package google.profile;
|
||||
// message Person {
|
||||
// string first_name = 1;
|
||||
// string last_name = 2;
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.profile.Person",
|
||||
// "firstName": <string>,
|
||||
// "lastName": <string>
|
||||
// }
|
||||
//
|
||||
// If the embedded message type is well-known and has a custom JSON
|
||||
// representation, that representation will be embedded adding a field
|
||||
// `value` which holds the custom JSON in addition to the `@type`
|
||||
// field. Example (for message [google.protobuf.Duration][]):
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
// "value": "1.212s"
|
||||
// }
|
||||
//
|
||||
message Any {
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. This string must contain at least
|
||||
// one "/" character. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
// URL, or have them precompiled into a binary to avoid any
|
||||
// lookup. Therefore, binary compatibility needs to be preserved
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
string type_url = 1;
|
||||
|
||||
// Must be a valid serialized protocol buffer of the above specified type.
|
||||
bytes value = 2;
|
||||
}
|
||||
99
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any_lite.cc
vendored
Normal file
99
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any_lite.cc
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/any.h>
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
std::string GetTypeUrl(StringPiece message_name,
|
||||
StringPiece type_url_prefix) {
|
||||
if (!type_url_prefix.empty() &&
|
||||
type_url_prefix[type_url_prefix.size() - 1] == '/') {
|
||||
return StrCat(type_url_prefix, message_name);
|
||||
} else {
|
||||
return StrCat(type_url_prefix, "/", message_name);
|
||||
}
|
||||
}
|
||||
|
||||
const char kAnyFullTypeName[] = "google.protobuf.Any";
|
||||
const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
|
||||
const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
|
||||
|
||||
void AnyMetadata::InternalPackFrom(const MessageLite& message,
|
||||
StringPiece type_url_prefix,
|
||||
StringPiece type_name) {
|
||||
type_url_->Set(&::google::protobuf::internal::GetEmptyString(),
|
||||
GetTypeUrl(type_name, type_url_prefix), nullptr);
|
||||
message.SerializeToString(
|
||||
value_->Mutable(ArenaStringPtr::EmptyDefault{}, nullptr));
|
||||
}
|
||||
|
||||
bool AnyMetadata::InternalUnpackTo(StringPiece type_name,
|
||||
MessageLite* message) const {
|
||||
if (!InternalIs(type_name)) {
|
||||
return false;
|
||||
}
|
||||
return message->ParseFromString(value_->Get());
|
||||
}
|
||||
|
||||
bool AnyMetadata::InternalIs(StringPiece type_name) const {
|
||||
StringPiece type_url = type_url_->Get();
|
||||
return type_url.size() >= type_name.size() + 1 &&
|
||||
type_url[type_url.size() - type_name.size() - 1] == '/' &&
|
||||
HasSuffixString(type_url, type_name);
|
||||
}
|
||||
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
|
||||
std::string* full_type_name) {
|
||||
size_t pos = type_url.find_last_of("/");
|
||||
if (pos == std::string::npos || pos + 1 == type_url.size()) {
|
||||
return false;
|
||||
}
|
||||
if (url_prefix) {
|
||||
*url_prefix = std::string(type_url.substr(0, pos + 1));
|
||||
}
|
||||
*full_type_name = std::string(type_url.substr(pos + 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name) {
|
||||
return ParseAnyTypeUrl(type_url, nullptr, full_type_name);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
175
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any_test.cc
vendored
Normal file
175
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any_test.cc
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/any_test.pb.h>
|
||||
#include <google/protobuf/unittest.pb.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace {
|
||||
|
||||
TEST(AnyMetadataTest, ConstInit) {
|
||||
PROTOBUF_CONSTINIT static internal::AnyMetadata metadata(nullptr, nullptr);
|
||||
(void)metadata;
|
||||
}
|
||||
|
||||
TEST(AnyTest, TestPackAndUnpack) {
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
protobuf_unittest::TestAny message;
|
||||
message.mutable_any_value()->PackFrom(submessage);
|
||||
|
||||
std::string data = message.SerializeAsString();
|
||||
|
||||
ASSERT_TRUE(message.ParseFromString(data));
|
||||
EXPECT_TRUE(message.has_any_value());
|
||||
submessage.Clear();
|
||||
ASSERT_TRUE(message.any_value().UnpackTo(&submessage));
|
||||
EXPECT_EQ(12345, submessage.int32_value());
|
||||
}
|
||||
|
||||
TEST(AnyTest, TestUnpackWithTypeMismatch) {
|
||||
protobuf_unittest::TestAny payload;
|
||||
payload.set_int32_value(13);
|
||||
google::protobuf::Any any;
|
||||
any.PackFrom(payload);
|
||||
|
||||
// Attempt to unpack into the wrong type.
|
||||
protobuf_unittest::TestAllTypes dest;
|
||||
EXPECT_FALSE(any.UnpackTo(&dest));
|
||||
}
|
||||
|
||||
TEST(AnyTest, TestPackAndUnpackAny) {
|
||||
// We can pack a Any message inside another Any message.
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
google::protobuf::Any any;
|
||||
any.PackFrom(submessage);
|
||||
protobuf_unittest::TestAny message;
|
||||
message.mutable_any_value()->PackFrom(any);
|
||||
|
||||
std::string data = message.SerializeAsString();
|
||||
|
||||
ASSERT_TRUE(message.ParseFromString(data));
|
||||
EXPECT_TRUE(message.has_any_value());
|
||||
any.Clear();
|
||||
submessage.Clear();
|
||||
ASSERT_TRUE(message.any_value().UnpackTo(&any));
|
||||
ASSERT_TRUE(any.UnpackTo(&submessage));
|
||||
EXPECT_EQ(12345, submessage.int32_value());
|
||||
}
|
||||
|
||||
TEST(AnyTest, TestPackWithCustomTypeUrl) {
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
google::protobuf::Any any;
|
||||
// Pack with a custom type URL prefix.
|
||||
any.PackFrom(submessage, "type.myservice.com");
|
||||
EXPECT_EQ("type.myservice.com/protobuf_unittest.TestAny", any.type_url());
|
||||
// Pack with a custom type URL prefix ending with '/'.
|
||||
any.PackFrom(submessage, "type.myservice.com/");
|
||||
EXPECT_EQ("type.myservice.com/protobuf_unittest.TestAny", any.type_url());
|
||||
// Pack with an empty type URL prefix.
|
||||
any.PackFrom(submessage, "");
|
||||
EXPECT_EQ("/protobuf_unittest.TestAny", any.type_url());
|
||||
|
||||
// Test unpacking the type.
|
||||
submessage.Clear();
|
||||
EXPECT_TRUE(any.UnpackTo(&submessage));
|
||||
EXPECT_EQ(12345, submessage.int32_value());
|
||||
}
|
||||
|
||||
TEST(AnyTest, TestIs) {
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
google::protobuf::Any any;
|
||||
any.PackFrom(submessage);
|
||||
ASSERT_TRUE(any.ParseFromString(any.SerializeAsString()));
|
||||
EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>());
|
||||
EXPECT_FALSE(any.Is<google::protobuf::Any>());
|
||||
|
||||
protobuf_unittest::TestAny message;
|
||||
message.mutable_any_value()->PackFrom(any);
|
||||
ASSERT_TRUE(message.ParseFromString(message.SerializeAsString()));
|
||||
EXPECT_FALSE(message.any_value().Is<protobuf_unittest::TestAny>());
|
||||
EXPECT_TRUE(message.any_value().Is<google::protobuf::Any>());
|
||||
|
||||
any.set_type_url("/protobuf_unittest.TestAny");
|
||||
EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>());
|
||||
// The type URL must contain at least one "/".
|
||||
any.set_type_url("protobuf_unittest.TestAny");
|
||||
EXPECT_FALSE(any.Is<protobuf_unittest::TestAny>());
|
||||
// The type name after the slash must be fully qualified.
|
||||
any.set_type_url("/TestAny");
|
||||
EXPECT_FALSE(any.Is<protobuf_unittest::TestAny>());
|
||||
}
|
||||
|
||||
TEST(AnyTest, MoveConstructor) {
|
||||
protobuf_unittest::TestAny payload;
|
||||
payload.set_int32_value(12345);
|
||||
|
||||
google::protobuf::Any src;
|
||||
src.PackFrom(payload);
|
||||
|
||||
const char* type_url = src.type_url().data();
|
||||
|
||||
google::protobuf::Any dst(std::move(src));
|
||||
EXPECT_EQ(type_url, dst.type_url().data());
|
||||
payload.Clear();
|
||||
ASSERT_TRUE(dst.UnpackTo(&payload));
|
||||
EXPECT_EQ(12345, payload.int32_value());
|
||||
}
|
||||
|
||||
TEST(AnyTest, MoveAssignment) {
|
||||
protobuf_unittest::TestAny payload;
|
||||
payload.set_int32_value(12345);
|
||||
|
||||
google::protobuf::Any src;
|
||||
src.PackFrom(payload);
|
||||
|
||||
const char* type_url = src.type_url().data();
|
||||
|
||||
google::protobuf::Any dst;
|
||||
dst = std::move(src);
|
||||
EXPECT_EQ(type_url, dst.type_url().data());
|
||||
payload.Clear();
|
||||
ASSERT_TRUE(dst.UnpackTo(&payload));
|
||||
EXPECT_EQ(12345, payload.int32_value());
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
41
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any_test.proto
vendored
Normal file
41
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/any_test.proto
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package protobuf_unittest;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
message TestAny {
|
||||
int32 int32_value = 1;
|
||||
google.protobuf.Any any_value = 2;
|
||||
repeated google.protobuf.Any repeated_any_value = 3;
|
||||
}
|
||||
1253
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/api.pb.cc
vendored
Normal file
1253
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/api.pb.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1489
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/api.pb.h
vendored
Normal file
1489
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/api.pb.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
208
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/api.proto
vendored
Normal file
208
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/api.proto
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
import "google/protobuf/source_context.proto";
|
||||
import "google/protobuf/type.proto";
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "ApiProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option go_package = "google.golang.org/protobuf/types/known/apipb";
|
||||
|
||||
// Api is a light-weight descriptor for an API Interface.
|
||||
//
|
||||
// Interfaces are also described as "protocol buffer services" in some contexts,
|
||||
// such as by the "service" keyword in a .proto file, but they are different
|
||||
// from API Services, which represent a concrete implementation of an interface
|
||||
// as opposed to simply a description of methods and bindings. They are also
|
||||
// sometimes simply referred to as "APIs" in other contexts, such as the name of
|
||||
// this message itself. See https://cloud.google.com/apis/design/glossary for
|
||||
// detailed terminology.
|
||||
message Api {
|
||||
// The fully qualified name of this interface, including package name
|
||||
// followed by the interface's simple name.
|
||||
string name = 1;
|
||||
|
||||
// The methods of this interface, in unspecified order.
|
||||
repeated Method methods = 2;
|
||||
|
||||
// Any metadata attached to the interface.
|
||||
repeated Option options = 3;
|
||||
|
||||
// A version string for this interface. If specified, must have the form
|
||||
// `major-version.minor-version`, as in `1.10`. If the minor version is
|
||||
// omitted, it defaults to zero. If the entire version field is empty, the
|
||||
// major version is derived from the package name, as outlined below. If the
|
||||
// field is not empty, the version in the package name will be verified to be
|
||||
// consistent with what is provided here.
|
||||
//
|
||||
// The versioning schema uses [semantic
|
||||
// versioning](http://semver.org) where the major version number
|
||||
// indicates a breaking change and the minor version an additive,
|
||||
// non-breaking change. Both version numbers are signals to users
|
||||
// what to expect from different versions, and should be carefully
|
||||
// chosen based on the product plan.
|
||||
//
|
||||
// The major version is also reflected in the package name of the
|
||||
// interface, which must end in `v<major-version>`, as in
|
||||
// `google.feature.v1`. For major versions 0 and 1, the suffix can
|
||||
// be omitted. Zero major versions must only be used for
|
||||
// experimental, non-GA interfaces.
|
||||
//
|
||||
//
|
||||
string version = 4;
|
||||
|
||||
// Source context for the protocol buffer service represented by this
|
||||
// message.
|
||||
SourceContext source_context = 5;
|
||||
|
||||
// Included interfaces. See [Mixin][].
|
||||
repeated Mixin mixins = 6;
|
||||
|
||||
// The source syntax of the service.
|
||||
Syntax syntax = 7;
|
||||
}
|
||||
|
||||
// Method represents a method of an API interface.
|
||||
message Method {
|
||||
// The simple name of this method.
|
||||
string name = 1;
|
||||
|
||||
// A URL of the input message type.
|
||||
string request_type_url = 2;
|
||||
|
||||
// If true, the request is streamed.
|
||||
bool request_streaming = 3;
|
||||
|
||||
// The URL of the output message type.
|
||||
string response_type_url = 4;
|
||||
|
||||
// If true, the response is streamed.
|
||||
bool response_streaming = 5;
|
||||
|
||||
// Any metadata attached to the method.
|
||||
repeated Option options = 6;
|
||||
|
||||
// The source syntax of this method.
|
||||
Syntax syntax = 7;
|
||||
}
|
||||
|
||||
// Declares an API Interface to be included in this interface. The including
|
||||
// interface must redeclare all the methods from the included interface, but
|
||||
// documentation and options are inherited as follows:
|
||||
//
|
||||
// - If after comment and whitespace stripping, the documentation
|
||||
// string of the redeclared method is empty, it will be inherited
|
||||
// from the original method.
|
||||
//
|
||||
// - Each annotation belonging to the service config (http,
|
||||
// visibility) which is not set in the redeclared method will be
|
||||
// inherited.
|
||||
//
|
||||
// - If an http annotation is inherited, the path pattern will be
|
||||
// modified as follows. Any version prefix will be replaced by the
|
||||
// version of the including interface plus the [root][] path if
|
||||
// specified.
|
||||
//
|
||||
// Example of a simple mixin:
|
||||
//
|
||||
// package google.acl.v1;
|
||||
// service AccessControl {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v1/{resource=**}:getAcl";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// package google.storage.v2;
|
||||
// service Storage {
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl);
|
||||
//
|
||||
// // Get a data record.
|
||||
// rpc GetData(GetDataRequest) returns (Data) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Example of a mixin configuration:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
//
|
||||
// The mixin construct implies that all methods in `AccessControl` are
|
||||
// also declared with same name and request/response types in
|
||||
// `Storage`. A documentation generator or annotation processor will
|
||||
// see the effective `Storage.GetAcl` method after inheriting
|
||||
// documentation and annotations as follows:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Note how the version in the path pattern changed from `v1` to `v2`.
|
||||
//
|
||||
// If the `root` field in the mixin is specified, it should be a
|
||||
// relative path under which inherited HTTP paths are placed. Example:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
// root: acls
|
||||
//
|
||||
// This implies the following inherited HTTP annotation:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
message Mixin {
|
||||
// The fully qualified name of the interface which is included.
|
||||
string name = 1;
|
||||
|
||||
// If non-empty specifies a path under which inherited HTTP paths
|
||||
// are rooted.
|
||||
string root = 2;
|
||||
}
|
||||
449
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena.cc
vendored
Normal file
449
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena.cc
vendored
Normal file
@@ -0,0 +1,449 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
static const size_t kMinCleanupListElements = 8;
|
||||
static const size_t kMaxCleanupListElements = 64; // 1kB on 64-bit.
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
PROTOBUF_EXPORT /*static*/ void* (*const ArenaOptions::kDefaultBlockAlloc)(
|
||||
size_t) = &::operator new;
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
||||
ArenaImpl::CacheAlignedLifecycleIdGenerator ArenaImpl::lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
|
||||
static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
|
||||
new internal::ThreadLocalStorage<ThreadCache>();
|
||||
return *thread_cache_->Get();
|
||||
}
|
||||
#elif defined(PROTOBUF_USE_DLLS)
|
||||
ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
|
||||
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = {
|
||||
0, static_cast<LifecycleIdAtomic>(-1), nullptr};
|
||||
return thread_cache_;
|
||||
}
|
||||
#else
|
||||
PROTOBUF_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {
|
||||
0, static_cast<LifecycleIdAtomic>(-1), nullptr};
|
||||
#endif
|
||||
|
||||
void ArenaFree(void* object, size_t size) {
|
||||
#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
|
||||
::operator delete(object, size);
|
||||
#else
|
||||
(void)size;
|
||||
::operator delete(object);
|
||||
#endif
|
||||
}
|
||||
|
||||
ArenaImpl::ArenaImpl(const ArenaOptions& options) {
|
||||
ArenaMetricsCollector* collector = nullptr;
|
||||
bool record_allocs = false;
|
||||
if (options.make_metrics_collector != nullptr) {
|
||||
collector = (*options.make_metrics_collector)();
|
||||
record_allocs = (collector && collector->RecordAllocs());
|
||||
}
|
||||
|
||||
// Get memory where we can store non-default options if needed.
|
||||
// Use supplied initial_block if it is large enough.
|
||||
size_t min_block_size = kOptionsSize + kBlockHeaderSize + kSerialArenaSize;
|
||||
char* mem = options.initial_block;
|
||||
size_t mem_size = options.initial_block_size;
|
||||
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0);
|
||||
if (mem == nullptr || mem_size < min_block_size) {
|
||||
// Supplied initial block is not big enough.
|
||||
mem_size = std::max(min_block_size, options.start_block_size);
|
||||
mem = reinterpret_cast<char*>((*options.block_alloc)(mem_size));
|
||||
}
|
||||
|
||||
// Create the special block.
|
||||
const bool special = true;
|
||||
const bool user_owned = (mem == options.initial_block);
|
||||
auto block =
|
||||
new (mem) SerialArena::Block(mem_size, nullptr, special, user_owned);
|
||||
|
||||
// Options occupy the beginning of the initial block.
|
||||
options_ = new (block->Pointer(block->pos())) Options;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(options_, kOptionsSize);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
options_->start_block_size = options.start_block_size;
|
||||
options_->max_block_size = options.max_block_size;
|
||||
options_->block_alloc = options.block_alloc;
|
||||
options_->block_dealloc = options.block_dealloc;
|
||||
options_->metrics_collector = collector;
|
||||
block->set_pos(block->pos() + kOptionsSize);
|
||||
|
||||
Init(record_allocs);
|
||||
SetInitialBlock(block);
|
||||
}
|
||||
|
||||
void ArenaImpl::Init(bool record_allocs) {
|
||||
ThreadCache& tc = thread_cache();
|
||||
auto id = tc.next_lifecycle_id;
|
||||
constexpr uint64 kInc = ThreadCache::kPerThreadIds * 2;
|
||||
if (PROTOBUF_PREDICT_FALSE((id & (kInc - 1)) == 0)) {
|
||||
if (sizeof(lifecycle_id_generator_.id) == 4) {
|
||||
// 2^32 is dangerous low to guarantee uniqueness. If we start dolling out
|
||||
// unique id's in ranges of kInc it's unacceptably low. In this case
|
||||
// we increment by 1. The additional range of kPerThreadIds that are used
|
||||
// per thread effectively pushes the overflow time from weeks to years
|
||||
// of continuous running.
|
||||
id = lifecycle_id_generator_.id.fetch_add(1, std::memory_order_relaxed) *
|
||||
kInc;
|
||||
} else {
|
||||
id =
|
||||
lifecycle_id_generator_.id.fetch_add(kInc, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
tc.next_lifecycle_id = id + 2;
|
||||
// We store "record_allocs" in the low bit of lifecycle_id_.
|
||||
lifecycle_id_ = id | (record_allocs ? 1 : 0);
|
||||
hint_.store(nullptr, std::memory_order_relaxed);
|
||||
threads_.store(nullptr, std::memory_order_relaxed);
|
||||
space_allocated_.store(0, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void ArenaImpl::SetInitialBlock(SerialArena::Block* block) {
|
||||
// Calling thread owns the first block. This allows the single-threaded case
|
||||
// to allocate on the first block without having to perform atomic operations.
|
||||
SerialArena* serial = SerialArena::New(block, &thread_cache(), this);
|
||||
serial->set_next(NULL);
|
||||
threads_.store(serial, std::memory_order_relaxed);
|
||||
space_allocated_.store(block->size(), std::memory_order_relaxed);
|
||||
CacheSerialArena(serial);
|
||||
}
|
||||
|
||||
ArenaImpl::~ArenaImpl() {
|
||||
// Have to do this in a first pass, because some of the destructors might
|
||||
// refer to memory in other blocks.
|
||||
CleanupList();
|
||||
|
||||
ArenaMetricsCollector* collector = nullptr;
|
||||
auto deallocator = &ArenaFree;
|
||||
if (options_) {
|
||||
collector = options_->metrics_collector;
|
||||
deallocator = options_->block_dealloc;
|
||||
}
|
||||
|
||||
PerBlock([deallocator](SerialArena::Block* b) {
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// This memory was provided by the underlying allocator as unpoisoned, so
|
||||
// return it in an unpoisoned state.
|
||||
ASAN_UNPOISON_MEMORY_REGION(b->Pointer(0), b->size());
|
||||
#endif // ADDRESS_SANITIZER
|
||||
if (!b->user_owned()) {
|
||||
(*deallocator)(b, b->size());
|
||||
}
|
||||
});
|
||||
|
||||
if (collector) {
|
||||
collector->OnDestroy(SpaceAllocated());
|
||||
}
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::Reset() {
|
||||
if (options_ && options_->metrics_collector) {
|
||||
options_->metrics_collector->OnReset(SpaceAllocated());
|
||||
}
|
||||
|
||||
// Have to do this in a first pass, because some of the destructors might
|
||||
// refer to memory in other blocks.
|
||||
CleanupList();
|
||||
|
||||
// Discard all blocks except the special block (if present).
|
||||
uint64 space_allocated = 0;
|
||||
SerialArena::Block* special_block = nullptr;
|
||||
auto deallocator = (options_ ? options_->block_dealloc : &ArenaFree);
|
||||
PerBlock(
|
||||
[&space_allocated, &special_block, deallocator](SerialArena::Block* b) {
|
||||
space_allocated += b->size();
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// This memory was provided by the underlying allocator as unpoisoned,
|
||||
// so return it in an unpoisoned state.
|
||||
ASAN_UNPOISON_MEMORY_REGION(b->Pointer(0), b->size());
|
||||
#endif // ADDRESS_SANITIZER
|
||||
if (!b->special()) {
|
||||
(*deallocator)(b, b->size());
|
||||
} else {
|
||||
// Prepare special block for reuse.
|
||||
// Note: if options_ is present, it occupies the beginning of the
|
||||
// block and therefore pos is advanced past it.
|
||||
GOOGLE_DCHECK(special_block == nullptr);
|
||||
special_block = b;
|
||||
}
|
||||
});
|
||||
|
||||
Init(record_allocs());
|
||||
if (special_block != nullptr) {
|
||||
// next() should still be nullptr since we are using a stack discipline, but
|
||||
// clear it anyway to reduce fragility.
|
||||
GOOGLE_DCHECK_EQ(special_block->next(), nullptr);
|
||||
special_block->clear_next();
|
||||
special_block->set_pos(kBlockHeaderSize + (options_ ? kOptionsSize : 0));
|
||||
SetInitialBlock(special_block);
|
||||
}
|
||||
return space_allocated;
|
||||
}
|
||||
|
||||
std::pair<void*, size_t> ArenaImpl::NewBuffer(size_t last_size,
|
||||
size_t min_bytes) {
|
||||
size_t size;
|
||||
if (last_size != -1) {
|
||||
// Double the current block size, up to a limit.
|
||||
auto max_size = options_ ? options_->max_block_size : kDefaultMaxBlockSize;
|
||||
size = std::min(2 * last_size, max_size);
|
||||
} else {
|
||||
size = options_ ? options_->start_block_size : kDefaultStartBlockSize;
|
||||
}
|
||||
// Verify that min_bytes + kBlockHeaderSize won't overflow.
|
||||
GOOGLE_CHECK_LE(min_bytes, std::numeric_limits<size_t>::max() - kBlockHeaderSize);
|
||||
size = std::max(size, kBlockHeaderSize + min_bytes);
|
||||
|
||||
void* mem = options_ ? (*options_->block_alloc)(size) : ::operator new(size);
|
||||
space_allocated_.fetch_add(size, std::memory_order_relaxed);
|
||||
return {mem, size};
|
||||
}
|
||||
|
||||
SerialArena::Block* SerialArena::NewBlock(SerialArena::Block* last_block,
|
||||
size_t min_bytes, ArenaImpl* arena) {
|
||||
void* mem;
|
||||
size_t size;
|
||||
std::tie(mem, size) =
|
||||
arena->NewBuffer(last_block ? last_block->size() : -1, min_bytes);
|
||||
Block* b = new (mem) Block(size, last_block, false, false);
|
||||
return b;
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
void SerialArena::AddCleanupFallback(void* elem, void (*cleanup)(void*)) {
|
||||
size_t size = cleanup_ ? cleanup_->size * 2 : kMinCleanupListElements;
|
||||
size = std::min(size, kMaxCleanupListElements);
|
||||
size_t bytes = internal::AlignUpTo8(CleanupChunk::SizeOf(size));
|
||||
CleanupChunk* list = reinterpret_cast<CleanupChunk*>(AllocateAligned(bytes));
|
||||
list->next = cleanup_;
|
||||
list->size = size;
|
||||
|
||||
cleanup_ = list;
|
||||
cleanup_ptr_ = &list->nodes[0];
|
||||
cleanup_limit_ = &list->nodes[size];
|
||||
|
||||
AddCleanup(elem, cleanup);
|
||||
}
|
||||
|
||||
void* ArenaImpl::AllocateAlignedAndAddCleanup(size_t n,
|
||||
void (*cleanup)(void*)) {
|
||||
SerialArena* arena;
|
||||
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAlignedAndAddCleanup(n, cleanup);
|
||||
} else {
|
||||
return AllocateAlignedAndAddCleanupFallback(n, cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaImpl::AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
SerialArena* arena;
|
||||
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
arena->AddCleanup(elem, cleanup);
|
||||
} else {
|
||||
return AddCleanupFallback(elem, cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
void* ArenaImpl::AllocateAlignedFallback(size_t n) {
|
||||
return GetSerialArenaFallback(&thread_cache())->AllocateAligned(n);
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
void* ArenaImpl::AllocateAlignedAndAddCleanupFallback(size_t n,
|
||||
void (*cleanup)(void*)) {
|
||||
return GetSerialArenaFallback(
|
||||
&thread_cache())->AllocateAlignedAndAddCleanup(n, cleanup);
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
void ArenaImpl::AddCleanupFallback(void* elem, void (*cleanup)(void*)) {
|
||||
GetSerialArenaFallback(&thread_cache())->AddCleanup(elem, cleanup);
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
void* SerialArena::AllocateAlignedFallback(size_t n) {
|
||||
// Sync back to current's pos.
|
||||
head_->set_pos(head_->size() - (limit_ - ptr_));
|
||||
|
||||
head_ = NewBlock(head_, n, arena_);
|
||||
ptr_ = head_->Pointer(head_->pos());
|
||||
limit_ = head_->Pointer(head_->size());
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
return AllocateAligned(n);
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SpaceAllocated() const {
|
||||
return space_allocated_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SpaceUsed() const {
|
||||
SerialArena* serial = threads_.load(std::memory_order_acquire);
|
||||
uint64 space_used = 0;
|
||||
for (; serial; serial = serial->next()) {
|
||||
space_used += serial->SpaceUsed();
|
||||
}
|
||||
// Remove the overhead of Options structure, if any.
|
||||
if (options_) {
|
||||
space_used -= kOptionsSize;
|
||||
}
|
||||
return space_used;
|
||||
}
|
||||
|
||||
uint64 SerialArena::SpaceUsed() const {
|
||||
// Get current block's size from ptr_ (since we can't trust head_->pos().
|
||||
uint64 space_used = ptr_ - head_->Pointer(kBlockHeaderSize);
|
||||
// Get subsequent block size from b->pos().
|
||||
for (Block* b = head_->next(); b; b = b->next()) {
|
||||
space_used += (b->pos() - kBlockHeaderSize);
|
||||
}
|
||||
// Remove the overhead of the SerialArena itself.
|
||||
space_used -= ArenaImpl::kSerialArenaSize;
|
||||
return space_used;
|
||||
}
|
||||
|
||||
void ArenaImpl::CleanupList() {
|
||||
// By omitting an Acquire barrier we ensure that any user code that doesn't
|
||||
// properly synchronize Reset() or the destructor will throw a TSAN warning.
|
||||
SerialArena* serial = threads_.load(std::memory_order_relaxed);
|
||||
|
||||
for (; serial; serial = serial->next()) {
|
||||
serial->CleanupList();
|
||||
}
|
||||
}
|
||||
|
||||
void SerialArena::CleanupList() {
|
||||
if (cleanup_ != NULL) {
|
||||
CleanupListFallback();
|
||||
}
|
||||
}
|
||||
|
||||
void SerialArena::CleanupListFallback() {
|
||||
// The first chunk might be only partially full, so calculate its size
|
||||
// from cleanup_ptr_. Subsequent chunks are always full, so use list->size.
|
||||
size_t n = cleanup_ptr_ - &cleanup_->nodes[0];
|
||||
CleanupChunk* list = cleanup_;
|
||||
while (true) {
|
||||
CleanupNode* node = &list->nodes[0];
|
||||
// Cleanup newest elements first (allocated last).
|
||||
for (size_t i = n; i > 0; i--) {
|
||||
node[i - 1].cleanup(node[i - 1].elem);
|
||||
}
|
||||
list = list->next;
|
||||
if (list == nullptr) {
|
||||
break;
|
||||
}
|
||||
// All but the first chunk are always full.
|
||||
n = list->size;
|
||||
}
|
||||
}
|
||||
|
||||
SerialArena* SerialArena::New(Block* b, void* owner, ArenaImpl* arena) {
|
||||
auto pos = b->pos();
|
||||
GOOGLE_DCHECK_LE(pos + ArenaImpl::kSerialArenaSize, b->size());
|
||||
SerialArena* serial = reinterpret_cast<SerialArena*>(b->Pointer(pos));
|
||||
b->set_pos(pos + ArenaImpl::kSerialArenaSize);
|
||||
serial->arena_ = arena;
|
||||
serial->owner_ = owner;
|
||||
serial->head_ = b;
|
||||
serial->ptr_ = b->Pointer(b->pos());
|
||||
serial->limit_ = b->Pointer(b->size());
|
||||
serial->cleanup_ = NULL;
|
||||
serial->cleanup_ptr_ = NULL;
|
||||
serial->cleanup_limit_ = NULL;
|
||||
return serial;
|
||||
}
|
||||
|
||||
PROTOBUF_NOINLINE
|
||||
SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) {
|
||||
// Look for this SerialArena in our linked list.
|
||||
SerialArena* serial = threads_.load(std::memory_order_acquire);
|
||||
for (; serial; serial = serial->next()) {
|
||||
if (serial->owner() == me) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!serial) {
|
||||
// This thread doesn't have any SerialArena, which also means it doesn't
|
||||
// have any blocks yet. So we'll allocate its first block now.
|
||||
SerialArena::Block* b = SerialArena::NewBlock(NULL, kSerialArenaSize, this);
|
||||
serial = SerialArena::New(b, me, this);
|
||||
|
||||
SerialArena* head = threads_.load(std::memory_order_relaxed);
|
||||
do {
|
||||
serial->set_next(head);
|
||||
} while (!threads_.compare_exchange_weak(
|
||||
head, serial, std::memory_order_release, std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
CacheSerialArena(serial);
|
||||
return serial;
|
||||
}
|
||||
|
||||
ArenaMetricsCollector::~ArenaMetricsCollector() {}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
PROTOBUF_FUNC_ALIGN(32)
|
||||
void* Arena::AllocateAlignedNoHook(size_t n) {
|
||||
return impl_.AllocateAligned(n);
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
694
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena.h
vendored
Normal file
694
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena.h
vendored
Normal file
@@ -0,0 +1,694 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file defines an Arena allocator for better allocation performance.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_H__
|
||||
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#ifdef max
|
||||
#undef max // Visual Studio defines this macro
|
||||
#endif
|
||||
#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS
|
||||
// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
namespace std {
|
||||
using type_info = ::type_info;
|
||||
}
|
||||
#else
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
#include <type_traits>
|
||||
#include <google/protobuf/arena_impl.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
struct ArenaOptions; // defined below
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Arena; // defined below
|
||||
class Message; // defined in message.h
|
||||
class MessageLite;
|
||||
template <typename Key, typename T>
|
||||
class Map;
|
||||
|
||||
namespace arena_metrics {
|
||||
|
||||
void EnableArenaMetrics(ArenaOptions* options);
|
||||
|
||||
} // namespace arena_metrics
|
||||
|
||||
namespace internal {
|
||||
|
||||
struct ArenaStringPtr; // defined in arenastring.h
|
||||
class LazyField; // defined in lazy_field.h
|
||||
class EpsCopyInputStream; // defined in parse_context.h
|
||||
|
||||
template <typename Type>
|
||||
class GenericTypeHandler; // defined in repeated_field.h
|
||||
|
||||
// Templated cleanup methods.
|
||||
template <typename T>
|
||||
void arena_destruct_object(void* object) {
|
||||
reinterpret_cast<T*>(object)->~T();
|
||||
}
|
||||
template <typename T>
|
||||
void arena_delete_object(void* object) {
|
||||
delete reinterpret_cast<T*>(object);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
// ArenaOptions provides optional additional parameters to arena construction
|
||||
// that control its block-allocation behavior.
|
||||
struct ArenaOptions {
|
||||
// This defines the size of the first block requested from the system malloc.
|
||||
// Subsequent block sizes will increase in a geometric series up to a maximum.
|
||||
size_t start_block_size;
|
||||
|
||||
// This defines the maximum block size requested from system malloc (unless an
|
||||
// individual arena allocation request occurs with a size larger than this
|
||||
// maximum). Requested block sizes increase up to this value, then remain
|
||||
// here.
|
||||
size_t max_block_size;
|
||||
|
||||
// An initial block of memory for the arena to use, or NULL for none. If
|
||||
// provided, the block must live at least as long as the arena itself. The
|
||||
// creator of the Arena retains ownership of the block after the Arena is
|
||||
// destroyed.
|
||||
char* initial_block;
|
||||
|
||||
// The size of the initial block, if provided.
|
||||
size_t initial_block_size;
|
||||
|
||||
// A function pointer to an alloc method that returns memory blocks of size
|
||||
// requested. By default, it contains a ptr to the malloc function.
|
||||
//
|
||||
// NOTE: block_alloc and dealloc functions are expected to behave like
|
||||
// malloc and free, including Asan poisoning.
|
||||
void* (*block_alloc)(size_t);
|
||||
// A function pointer to a dealloc method that takes ownership of the blocks
|
||||
// from the arena. By default, it contains a ptr to a wrapper function that
|
||||
// calls free.
|
||||
void (*block_dealloc)(void*, size_t);
|
||||
|
||||
ArenaOptions()
|
||||
: start_block_size(kDefaultStartBlockSize),
|
||||
max_block_size(kDefaultMaxBlockSize),
|
||||
initial_block(NULL),
|
||||
initial_block_size(0),
|
||||
block_alloc(kDefaultBlockAlloc),
|
||||
block_dealloc(&internal::ArenaFree),
|
||||
make_metrics_collector(nullptr) {}
|
||||
|
||||
PROTOBUF_EXPORT static void* (*const kDefaultBlockAlloc)(size_t);
|
||||
|
||||
private:
|
||||
// If make_metrics_collector is not nullptr, it will be called at Arena init
|
||||
// time. It may return a pointer to a collector instance that will be notified
|
||||
// of interesting events related to the arena.
|
||||
internal::ArenaMetricsCollector* (*make_metrics_collector)();
|
||||
|
||||
// Constants define default starting block size and max block size for
|
||||
// arena allocator behavior -- see descriptions above.
|
||||
static const size_t kDefaultStartBlockSize =
|
||||
internal::ArenaImpl::kDefaultStartBlockSize;
|
||||
static const size_t kDefaultMaxBlockSize =
|
||||
internal::ArenaImpl::kDefaultMaxBlockSize;
|
||||
|
||||
friend void arena_metrics::EnableArenaMetrics(ArenaOptions*);
|
||||
|
||||
friend class Arena;
|
||||
friend class ArenaOptionsTestFriend;
|
||||
friend class internal::ArenaImpl;
|
||||
};
|
||||
|
||||
// Support for non-RTTI environments. (The metrics hooks API uses type
|
||||
// information.)
|
||||
#if PROTOBUF_RTTI
|
||||
#define RTTI_TYPE_ID(type) (&typeid(type))
|
||||
#else
|
||||
#define RTTI_TYPE_ID(type) (NULL)
|
||||
#endif
|
||||
|
||||
// Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
|
||||
// with new/delete, and improves performance by aggregating allocations into
|
||||
// larger blocks and freeing allocations all at once. Protocol messages are
|
||||
// allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
|
||||
// are automatically freed when the arena is destroyed.
|
||||
//
|
||||
// This is a thread-safe implementation: multiple threads may allocate from the
|
||||
// arena concurrently. Destruction is not thread-safe and the destructing
|
||||
// thread must synchronize with users of the arena first.
|
||||
//
|
||||
// An arena provides two allocation interfaces: CreateMessage<T>, which works
|
||||
// for arena-enabled proto2 message types as well as other types that satisfy
|
||||
// the appropriate protocol (described below), and Create<T>, which works for
|
||||
// any arbitrary type T. CreateMessage<T> is better when the type T supports it,
|
||||
// because this interface (i) passes the arena pointer to the created object so
|
||||
// that its sub-objects and internal allocations can use the arena too, and (ii)
|
||||
// elides the object's destructor call when possible. Create<T> does not place
|
||||
// any special requirements on the type T, and will invoke the object's
|
||||
// destructor when the arena is destroyed.
|
||||
//
|
||||
// The arena message allocation protocol, required by
|
||||
// CreateMessage<T>(Arena* arena, Args&&... args), is as follows:
|
||||
//
|
||||
// - The type T must have (at least) two constructors: a constructor callable
|
||||
// with `args` (without `arena`), called when a T is allocated on the heap;
|
||||
// and a constructor callable with `Arena* arena, Args&&... args`, called when
|
||||
// a T is allocated on an arena. If the second constructor is called with a
|
||||
// NULL arena pointer, it must be equivalent to invoking the first
|
||||
// (`args`-only) constructor.
|
||||
//
|
||||
// - The type T must have a particular type trait: a nested type
|
||||
// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
|
||||
// such type trait exists, then the instantiation CreateMessage<T> will fail
|
||||
// to compile.
|
||||
//
|
||||
// - The type T *may* have the type trait |DestructorSkippable_|. If this type
|
||||
// trait is present in the type, then its destructor will not be called if and
|
||||
// only if it was passed a non-NULL arena pointer. If this type trait is not
|
||||
// present on the type, then its destructor is always called when the
|
||||
// containing arena is destroyed.
|
||||
//
|
||||
// This protocol is implemented by all arena-enabled proto2 message classes as
|
||||
// well as protobuf container types like RepeatedPtrField and Map. The protocol
|
||||
// is internal to protobuf and is not guaranteed to be stable. Non-proto types
|
||||
// should not rely on this protocol.
|
||||
class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
|
||||
public:
|
||||
// Default constructor with sensible default options, tuned for average
|
||||
// use-cases.
|
||||
inline Arena() : impl_() {}
|
||||
|
||||
// Construct an arena with default options, except for the supplied
|
||||
// initial block. It is more efficient to use this constructor
|
||||
// instead of passing ArenaOptions if the only configuration needed
|
||||
// by the caller is supplying an initial block.
|
||||
inline Arena(char* initial_block, size_t initial_block_size)
|
||||
: impl_(initial_block, initial_block_size) {}
|
||||
|
||||
// Arena constructor taking custom options. See ArenaOptions above for
|
||||
// descriptions of the options available.
|
||||
explicit Arena(const ArenaOptions& options) : impl_(options) {}
|
||||
|
||||
// Block overhead. Use this as a guide for how much to over-allocate the
|
||||
// initial block if you want an allocation of size N to fit inside it.
|
||||
//
|
||||
// WARNING: if you allocate multiple objects, it is difficult to guarantee
|
||||
// that a series of allocations will fit in the initial block, especially if
|
||||
// Arena changes its alignment guarantees in the future!
|
||||
static const size_t kBlockOverhead = internal::ArenaImpl::kBlockHeaderSize +
|
||||
internal::ArenaImpl::kSerialArenaSize;
|
||||
|
||||
inline ~Arena() {}
|
||||
|
||||
// TODO(protobuf-team): Fix callers to use constructor and delete this method.
|
||||
void Init(const ArenaOptions&) {}
|
||||
|
||||
// API to create proto2 message objects on the arena. If the arena passed in
|
||||
// is NULL, then a heap allocated object is returned. Type T must be a message
|
||||
// defined in a .proto file with cc_enable_arenas set to true, otherwise a
|
||||
// compilation error will occur.
|
||||
//
|
||||
// RepeatedField and RepeatedPtrField may also be instantiated directly on an
|
||||
// arena with this method.
|
||||
//
|
||||
// This function also accepts any type T that satisfies the arena message
|
||||
// allocation protocol, documented above.
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateMessage(Arena* arena, Args&&... args) {
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
// We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
|
||||
// because protobuf generated classes specialize CreateMaybeMessage() and we
|
||||
// need to use that specialization for code size reasons.
|
||||
return Arena::CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// API to create any objects on the arena. Note that only the object will
|
||||
// be created on the arena; the underlying ptrs (in case of a proto2 message)
|
||||
// will be still heap allocated. Proto messages should usually be allocated
|
||||
// with CreateMessage<T>() instead.
|
||||
//
|
||||
// Note that even if T satisfies the arena message construction protocol
|
||||
// (InternalArenaConstructable_ trait and optional DestructorSkippable_
|
||||
// trait), as described above, this function does not follow the protocol;
|
||||
// instead, it treats T as a black-box type, just as if it did not have these
|
||||
// traits. Specifically, T's constructor arguments will always be only those
|
||||
// passed to Create<T>() -- no additional arena pointer is implicitly added.
|
||||
// Furthermore, the destructor will always be called at arena destruction time
|
||||
// (unless the destructor is trivial). Hence, from T's point of view, it is as
|
||||
// if the object were allocated on the heap (except that the underlying memory
|
||||
// is obtained from the arena).
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* Create(Arena* arena, Args&&... args) {
|
||||
return CreateNoMessage<T>(arena, is_arena_constructable<T>(),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Create an array of object type T on the arena *without* invoking the
|
||||
// constructor of T. If `arena` is null, then the return value should be freed
|
||||
// with `delete[] x;` (or `::operator delete[](x);`).
|
||||
// To ensure safe uses, this function checks at compile time
|
||||
// (when compiled as C++11) that T is trivially default-constructible and
|
||||
// trivially destructible.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateArray(Arena* arena,
|
||||
size_t num_elements) {
|
||||
static_assert(std::is_pod<T>::value,
|
||||
"CreateArray requires a trivially constructible type");
|
||||
static_assert(std::is_trivially_destructible<T>::value,
|
||||
"CreateArray requires a trivially destructible type");
|
||||
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
|
||||
<< "Requested size is too large to fit into size_t.";
|
||||
if (arena == NULL) {
|
||||
return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
|
||||
} else {
|
||||
return arena->CreateInternalRawArray<T>(num_elements);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the total space allocated by the arena, which is the sum of the
|
||||
// sizes of the underlying blocks. This method is relatively fast; a counter
|
||||
// is kept as blocks are allocated.
|
||||
uint64 SpaceAllocated() const { return impl_.SpaceAllocated(); }
|
||||
// Returns the total space used by the arena. Similar to SpaceAllocated but
|
||||
// does not include free space and block overhead. The total space returned
|
||||
// may not include space used by other threads executing concurrently with
|
||||
// the call to this method.
|
||||
uint64 SpaceUsed() const { return impl_.SpaceUsed(); }
|
||||
|
||||
// Frees all storage allocated by this arena after calling destructors
|
||||
// registered with OwnDestructor() and freeing objects registered with Own().
|
||||
// Any objects allocated on this arena are unusable after this call. It also
|
||||
// returns the total space used by the arena which is the sums of the sizes
|
||||
// of the allocated blocks. This method is not thread-safe.
|
||||
uint64 Reset() { return impl_.Reset(); }
|
||||
|
||||
// Adds |object| to a list of heap-allocated objects to be freed with |delete|
|
||||
// when the arena is destroyed or reset.
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE void Own(T* object) {
|
||||
OwnInternal(object, std::is_convertible<T*, Message*>());
|
||||
}
|
||||
|
||||
// Adds |object| to a list of objects whose destructors will be manually
|
||||
// called when the arena is destroyed or reset. This differs from Own() in
|
||||
// that it does not free the underlying memory with |delete|; hence, it is
|
||||
// normally only used for objects that are placement-newed into
|
||||
// arena-allocated memory.
|
||||
template <typename T>
|
||||
PROTOBUF_NOINLINE void OwnDestructor(T* object) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a custom member function on an object to the list of destructors that
|
||||
// will be manually called when the arena is destroyed or reset. This differs
|
||||
// from OwnDestructor() in that any member function may be specified, not only
|
||||
// the class destructor.
|
||||
PROTOBUF_NOINLINE void OwnCustomDestructor(void* object,
|
||||
void (*destruct)(void*)) {
|
||||
impl_.AddCleanup(object, destruct);
|
||||
}
|
||||
|
||||
// Retrieves the arena associated with |value| if |value| is an arena-capable
|
||||
// message, or NULL otherwise. If possible, the call resolves at compile time.
|
||||
// Note that we can often devirtualize calls to `value->GetArena()` so usually
|
||||
// calling this method is unnecessary.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArena(const T* value) {
|
||||
return GetArenaInternal(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class InternalHelper {
|
||||
template <typename U>
|
||||
static char DestructorSkippable(const typename U::DestructorSkippable_*);
|
||||
template <typename U>
|
||||
static double DestructorSkippable(...);
|
||||
|
||||
typedef std::integral_constant<
|
||||
bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
|
||||
sizeof(char) ||
|
||||
std::is_trivially_destructible<T>::value>
|
||||
is_destructor_skippable;
|
||||
|
||||
template <typename U>
|
||||
static char ArenaConstructable(
|
||||
const typename U::InternalArenaConstructable_*);
|
||||
template <typename U>
|
||||
static double ArenaConstructable(...);
|
||||
|
||||
typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
|
||||
static_cast<const T*>(0))) ==
|
||||
sizeof(char)>
|
||||
is_arena_constructable;
|
||||
|
||||
template <typename U,
|
||||
typename std::enable_if<
|
||||
std::is_same<Arena*, decltype(std::declval<const U>()
|
||||
.GetArena())>::value,
|
||||
int>::type = 0>
|
||||
static char HasGetArena(decltype(&U::GetArena));
|
||||
template <typename U>
|
||||
static double HasGetArena(...);
|
||||
|
||||
typedef std::integral_constant<bool, sizeof(HasGetArena<T>(nullptr)) ==
|
||||
sizeof(char)>
|
||||
has_get_arena;
|
||||
|
||||
template <typename... Args>
|
||||
static T* Construct(void* ptr, Args&&... args) {
|
||||
return new (ptr) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
static Arena* GetArena(const T* p) { return p->GetArena(); }
|
||||
|
||||
friend class Arena;
|
||||
};
|
||||
|
||||
// Helper typetraits that indicates support for arenas in a type T at compile
|
||||
// time. This is public only to allow construction of higher-level templated
|
||||
// utilities.
|
||||
//
|
||||
// is_arena_constructable<T>::value is true if the message type T has arena
|
||||
// support enabled, and false otherwise.
|
||||
//
|
||||
// is_destructor_skippable<T>::value is true if the message type T has told
|
||||
// the arena that it is safe to skip the destructor, and false otherwise.
|
||||
//
|
||||
// This is inside Arena because only Arena has the friend relationships
|
||||
// necessary to see the underlying generated code traits.
|
||||
template <typename T>
|
||||
struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
|
||||
template <typename T>
|
||||
struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable {
|
||||
};
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
struct has_get_arena : InternalHelper<T>::has_get_arena {};
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena,
|
||||
Args&&... args) {
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
if (arena == NULL) {
|
||||
return new T(nullptr, std::forward<Args>(args)...);
|
||||
} else {
|
||||
return arena->DoCreateMessage<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
// This specialization for no arguments is necessary, because its behavior is
|
||||
// slightly different. When the arena pointer is nullptr, it calls T()
|
||||
// instead of T(nullptr).
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena) {
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
if (arena == NULL) {
|
||||
return new T();
|
||||
} else {
|
||||
return arena->DoCreateMessage<T>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena,
|
||||
Args&&... args) {
|
||||
if (arena == NULL) {
|
||||
return new T(std::forward<Args>(args)...);
|
||||
} else {
|
||||
return arena->DoCreate<T>(std::is_trivially_destructible<T>::value,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
inline void AllocHook(const std::type_info* allocated_type, size_t n) const {
|
||||
impl_.RecordAlloc(allocated_type, n);
|
||||
}
|
||||
|
||||
// Allocate and also optionally call collector with the allocated type info
|
||||
// when allocation recording is enabled.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void* AllocateInternal(bool skip_explicit_ownership) {
|
||||
const size_t n = internal::AlignUpTo8(sizeof(T));
|
||||
// Monitor allocation if needed.
|
||||
impl_.RecordAlloc(RTTI_TYPE_ID(T), n);
|
||||
if (skip_explicit_ownership) {
|
||||
return AllocateAlignedTo<alignof(T)>(sizeof(T));
|
||||
} else {
|
||||
if (alignof(T) <= 8) {
|
||||
return impl_.AllocateAlignedAndAddCleanup(
|
||||
n, &internal::arena_destruct_object<T>);
|
||||
} else {
|
||||
auto ptr =
|
||||
reinterpret_cast<uintptr_t>(impl_.AllocateAlignedAndAddCleanup(
|
||||
sizeof(T) + alignof(T) - 8,
|
||||
&internal::arena_destruct_object<T>));
|
||||
return reinterpret_cast<void*>((ptr + alignof(T) - 8) &
|
||||
(~alignof(T) + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CreateMessage<T> requires that T supports arenas, but this private method
|
||||
// works whether or not T supports arenas. These are not exposed to user code
|
||||
// as it can cause confusing API usages, and end up having double free in
|
||||
// user code. These are used only internally from LazyField and Repeated
|
||||
// fields, since they are designed to work in all mode combinations.
|
||||
template <typename Msg, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(Arena* arena,
|
||||
std::true_type,
|
||||
Args&&... args) {
|
||||
return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena,
|
||||
std::false_type,
|
||||
Args&&... args) {
|
||||
return CreateInternal<T>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena,
|
||||
Args&&... args) {
|
||||
return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateNoMessage(Arena* arena, std::true_type,
|
||||
Args&&... args) {
|
||||
// User is constructing with Create() despite the fact that T supports arena
|
||||
// construction. In this case we have to delegate to CreateInternal(), and
|
||||
// we can't use any CreateMaybeMessage() specialization that may be defined.
|
||||
return CreateInternal<T>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE static T* CreateNoMessage(Arena* arena,
|
||||
std::false_type,
|
||||
Args&&... args) {
|
||||
// User is constructing with Create() and the type does not support arena
|
||||
// construction. In this case we can delegate to CreateMaybeMessage() and
|
||||
// use any specialization that may be available for that.
|
||||
return CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Just allocate the required size for the given type assuming the
|
||||
// type has a trivial constructor.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE T* CreateInternalRawArray(size_t num_elements) {
|
||||
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
|
||||
<< "Requested size is too large to fit into size_t.";
|
||||
// We count on compiler to realize that if sizeof(T) is a multiple of
|
||||
// 8 AlignUpTo can be elided.
|
||||
const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements);
|
||||
// Monitor allocation if needed.
|
||||
impl_.RecordAlloc(RTTI_TYPE_ID(T), n);
|
||||
return static_cast<T*>(AllocateAlignedTo<alignof(T)>(n));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE T* DoCreate(bool skip_explicit_ownership,
|
||||
Args&&... args) {
|
||||
return new (AllocateInternal<T>(skip_explicit_ownership))
|
||||
T(std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T, typename... Args>
|
||||
PROTOBUF_ALWAYS_INLINE T* DoCreateMessage(Args&&... args) {
|
||||
return InternalHelper<T>::Construct(
|
||||
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
|
||||
this, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// CreateInArenaStorage is used to implement map field. Without it,
|
||||
// Map need to call generated message's protected arena constructor,
|
||||
// which needs to declare Map as friend of generated message.
|
||||
template <typename T, typename... Args>
|
||||
static void CreateInArenaStorage(T* ptr, Arena* arena, Args&&... args) {
|
||||
CreateInArenaStorageInternal(ptr, arena,
|
||||
typename is_arena_constructable<T>::type(),
|
||||
std::forward<Args>(args)...);
|
||||
RegisterDestructorInternal(
|
||||
ptr, arena,
|
||||
typename InternalHelper<T>::is_destructor_skippable::type());
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
|
||||
std::true_type, Args&&... args) {
|
||||
InternalHelper<T>::Construct(ptr, arena, std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T, typename... Args>
|
||||
static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */,
|
||||
std::false_type, Args&&... args) {
|
||||
new (ptr) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */,
|
||||
std::true_type) {}
|
||||
template <typename T>
|
||||
static void RegisterDestructorInternal(T* ptr, Arena* arena,
|
||||
std::false_type) {
|
||||
arena->OwnDestructor(ptr);
|
||||
}
|
||||
|
||||
// These implement Own(), which registers an object for deletion (destructor
|
||||
// call and operator delete()). The second parameter has type 'true_type' if T
|
||||
// is a subtype of Message and 'false_type' otherwise. Collapsing
|
||||
// all template instantiations to one for generic Message reduces code size,
|
||||
// using the virtual destructor instead.
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_delete_object<Message>);
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) {
|
||||
if (object != NULL) {
|
||||
impl_.AddCleanup(object, &internal::arena_delete_object<T>);
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for GetArena(). Only message objects with
|
||||
// InternalArenaConstructable_ tags can be associated with an arena, and such
|
||||
// objects must implement a GetArena() method.
|
||||
template <typename T, typename std::enable_if<
|
||||
is_arena_constructable<T>::value, int>::type = 0>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
|
||||
return InternalHelper<T>::GetArena(value);
|
||||
}
|
||||
template <typename T,
|
||||
typename std::enable_if<!is_arena_constructable<T>::value &&
|
||||
has_get_arena<T>::value,
|
||||
int>::type = 0>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
|
||||
return value->GetArena();
|
||||
}
|
||||
template <typename T,
|
||||
typename std::enable_if<!is_arena_constructable<T>::value &&
|
||||
!has_get_arena<T>::value,
|
||||
int>::type = 0>
|
||||
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
|
||||
(void)value;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// For friends of arena.
|
||||
void* AllocateAligned(size_t n) {
|
||||
return AllocateAlignedNoHook(internal::AlignUpTo8(n));
|
||||
}
|
||||
template<size_t Align>
|
||||
void* AllocateAlignedTo(size_t n) {
|
||||
static_assert(Align > 0, "Alignment must be greater than 0");
|
||||
static_assert((Align & (Align - 1)) == 0, "Alignment must be power of two");
|
||||
if (Align <= 8) return AllocateAligned(n);
|
||||
// TODO(b/151247138): if the pointer would have been aligned already,
|
||||
// this is wasting space. We should pass the alignment down.
|
||||
uintptr_t ptr = reinterpret_cast<uintptr_t>(AllocateAligned(n + Align - 8));
|
||||
ptr = (ptr + Align - 1) & (~Align + 1);
|
||||
return reinterpret_cast<void*>(ptr);
|
||||
}
|
||||
|
||||
void* AllocateAlignedNoHook(size_t n);
|
||||
|
||||
internal::ArenaImpl impl_;
|
||||
|
||||
template <typename Type>
|
||||
friend class internal::GenericTypeHandler;
|
||||
friend struct internal::ArenaStringPtr; // For AllocateAligned.
|
||||
friend class internal::LazyField; // For CreateMaybeMessage.
|
||||
friend class internal::EpsCopyInputStream; // For parser performance
|
||||
friend class MessageLite;
|
||||
template <typename Key, typename T>
|
||||
friend class Map;
|
||||
};
|
||||
|
||||
// Defined above for supporting environments without RTTI.
|
||||
#undef RTTI_TYPE_ID
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_H__
|
||||
491
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena_impl.h
vendored
Normal file
491
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena_impl.h
vendored
Normal file
@@ -0,0 +1,491 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file defines an Arena allocator for better allocation performance.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
struct ArenaOptions;
|
||||
|
||||
namespace internal {
|
||||
|
||||
inline size_t AlignUpTo8(size_t n) {
|
||||
// Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
|
||||
return (n + 7) & static_cast<size_t>(-8);
|
||||
}
|
||||
|
||||
using LifecycleIdAtomic = uint64_t;
|
||||
|
||||
void PROTOBUF_EXPORT ArenaFree(void* object, size_t size);
|
||||
|
||||
// MetricsCollector collects stats for a particular arena.
|
||||
class PROTOBUF_EXPORT ArenaMetricsCollector {
|
||||
public:
|
||||
virtual ~ArenaMetricsCollector();
|
||||
|
||||
// Invoked when the arena is about to be destroyed. This method will
|
||||
// typically finalize any metric collection and delete the collector.
|
||||
// space_allocated is the space used by the arena.
|
||||
virtual void OnDestroy(uint64 space_allocated) = 0;
|
||||
|
||||
// OnReset() is called when the associated arena is reset.
|
||||
// space_allocated is the space used by the arena just before the reset.
|
||||
virtual void OnReset(uint64 space_allocated) = 0;
|
||||
|
||||
// Does OnAlloc() need to be called? If false, metric collection overhead
|
||||
// will be reduced since we will not do extra work per allocation.
|
||||
virtual bool RecordAllocs() = 0;
|
||||
|
||||
// OnAlloc is called when an allocation happens.
|
||||
// type_info is promised to be static - its lifetime extends to
|
||||
// match program's lifetime (It is given by typeid operator).
|
||||
// Note: typeid(void) will be passed as allocated_type every time we
|
||||
// intentionally want to avoid monitoring an allocation. (i.e. internal
|
||||
// allocations for managing the arena)
|
||||
virtual void OnAlloc(const std::type_info* allocated_type,
|
||||
uint64 alloc_size) = 0;
|
||||
};
|
||||
|
||||
class ArenaImpl;
|
||||
|
||||
// A thread-unsafe Arena that can only be used within its owning thread.
|
||||
class PROTOBUF_EXPORT SerialArena {
|
||||
public:
|
||||
// Blocks are variable length malloc-ed objects. The following structure
|
||||
// describes the common header for all blocks.
|
||||
class PROTOBUF_EXPORT Block {
|
||||
public:
|
||||
Block(size_t size, Block* next, bool special, bool user_owned)
|
||||
: next_and_bits_(reinterpret_cast<uintptr_t>(next) | (special ? 1 : 0) |
|
||||
(user_owned ? 2 : 0)),
|
||||
pos_(kBlockHeaderSize),
|
||||
size_(size) {
|
||||
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(next) & 3, 0u);
|
||||
}
|
||||
|
||||
char* Pointer(size_t n) {
|
||||
GOOGLE_DCHECK(n <= size_);
|
||||
return reinterpret_cast<char*>(this) + n;
|
||||
}
|
||||
|
||||
// One of the blocks may be special. This is either a user-supplied
|
||||
// initial block, or a block we created at startup to hold Options info.
|
||||
// A special block is not deleted by Reset.
|
||||
bool special() const { return (next_and_bits_ & 1) != 0; }
|
||||
|
||||
// Whether or not this current block is owned by the user.
|
||||
// Only special blocks can be user_owned.
|
||||
bool user_owned() const { return (next_and_bits_ & 2) != 0; }
|
||||
|
||||
Block* next() const {
|
||||
const uintptr_t bottom_bits = 3;
|
||||
return reinterpret_cast<Block*>(next_and_bits_ & ~bottom_bits);
|
||||
}
|
||||
|
||||
void clear_next() {
|
||||
next_and_bits_ &= 3; // Set next to nullptr, preserve bottom bits.
|
||||
}
|
||||
|
||||
size_t pos() const { return pos_; }
|
||||
size_t size() const { return size_; }
|
||||
void set_pos(size_t pos) { pos_ = pos; }
|
||||
|
||||
private:
|
||||
// Holds pointer to next block for this thread + special/user_owned bits.
|
||||
uintptr_t next_and_bits_;
|
||||
|
||||
size_t pos_;
|
||||
size_t size_;
|
||||
// data follows
|
||||
};
|
||||
|
||||
// The allocate/free methods here are a little strange, since SerialArena is
|
||||
// allocated inside a Block which it also manages. This is to avoid doing
|
||||
// an extra allocation for the SerialArena itself.
|
||||
|
||||
// Creates a new SerialArena inside Block* and returns it.
|
||||
static SerialArena* New(Block* b, void* owner, ArenaImpl* arena);
|
||||
|
||||
void CleanupList();
|
||||
uint64 SpaceUsed() const;
|
||||
|
||||
bool HasSpace(size_t n) { return n <= static_cast<size_t>(limit_ - ptr_); }
|
||||
|
||||
void* AllocateAligned(size_t n) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) {
|
||||
return AllocateAlignedFallback(n);
|
||||
}
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Allocate space if the current region provides enough space.
|
||||
bool MaybeAllocateAligned(size_t n, void** out) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false;
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
*out = ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
if (PROTOBUF_PREDICT_FALSE(cleanup_ptr_ == cleanup_limit_)) {
|
||||
AddCleanupFallback(elem, cleanup);
|
||||
return;
|
||||
}
|
||||
cleanup_ptr_->elem = elem;
|
||||
cleanup_ptr_->cleanup = cleanup;
|
||||
cleanup_ptr_++;
|
||||
}
|
||||
|
||||
void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*)) {
|
||||
void* ret = AllocateAligned(n);
|
||||
AddCleanup(ret, cleanup);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Block* head() const { return head_; }
|
||||
void* owner() const { return owner_; }
|
||||
SerialArena* next() const { return next_; }
|
||||
void set_next(SerialArena* next) { next_ = next; }
|
||||
static Block* NewBlock(Block* last_block, size_t min_bytes, ArenaImpl* arena);
|
||||
|
||||
private:
|
||||
// Node contains the ptr of the object to be cleaned up and the associated
|
||||
// cleanup function ptr.
|
||||
struct CleanupNode {
|
||||
void* elem; // Pointer to the object to be cleaned up.
|
||||
void (*cleanup)(void*); // Function pointer to the destructor or deleter.
|
||||
};
|
||||
|
||||
// Cleanup uses a chunked linked list, to reduce pointer chasing.
|
||||
struct CleanupChunk {
|
||||
static size_t SizeOf(size_t i) {
|
||||
return sizeof(CleanupChunk) + (sizeof(CleanupNode) * (i - 1));
|
||||
}
|
||||
size_t size; // Total elements in the list.
|
||||
CleanupChunk* next; // Next node in the list.
|
||||
CleanupNode nodes[1]; // True length is |size|.
|
||||
};
|
||||
|
||||
ArenaImpl* arena_; // Containing arena.
|
||||
void* owner_; // &ThreadCache of this thread;
|
||||
Block* head_; // Head of linked list of blocks.
|
||||
CleanupChunk* cleanup_; // Head of cleanup list.
|
||||
SerialArena* next_; // Next SerialArena in this linked list.
|
||||
|
||||
// Next pointer to allocate from. Always 8-byte aligned. Points inside
|
||||
// head_ (and head_->pos will always be non-canonical). We keep these
|
||||
// here to reduce indirection.
|
||||
char* ptr_;
|
||||
char* limit_;
|
||||
|
||||
// Next CleanupList members to append to. These point inside cleanup_.
|
||||
CleanupNode* cleanup_ptr_;
|
||||
CleanupNode* cleanup_limit_;
|
||||
|
||||
void* AllocateAlignedFallback(size_t n);
|
||||
void AddCleanupFallback(void* elem, void (*cleanup)(void*));
|
||||
void CleanupListFallback();
|
||||
|
||||
public:
|
||||
static constexpr size_t kBlockHeaderSize =
|
||||
(sizeof(Block) + 7) & static_cast<size_t>(-8);
|
||||
};
|
||||
|
||||
// This class provides the core Arena memory allocation library. Different
|
||||
// implementations only need to implement the public interface below.
|
||||
// Arena is not a template type as that would only be useful if all protos
|
||||
// in turn would be templates, which will/cannot happen. However separating
|
||||
// the memory allocation part from the cruft of the API users expect we can
|
||||
// use #ifdef the select the best implementation based on hardware / OS.
|
||||
class PROTOBUF_EXPORT ArenaImpl {
|
||||
public:
|
||||
static const size_t kDefaultStartBlockSize = 256;
|
||||
static const size_t kDefaultMaxBlockSize = 8192;
|
||||
|
||||
ArenaImpl() { Init(false); }
|
||||
|
||||
ArenaImpl(char* mem, size_t size) {
|
||||
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
|
||||
Init(false);
|
||||
|
||||
// Ignore initial block if it is too small.
|
||||
if (mem != nullptr && size >= kBlockHeaderSize + kSerialArenaSize) {
|
||||
SetInitialBlock(new (mem) SerialArena::Block(size, nullptr, true, true));
|
||||
}
|
||||
}
|
||||
|
||||
explicit ArenaImpl(const ArenaOptions& options);
|
||||
|
||||
// Destructor deletes all owned heap allocated objects, and destructs objects
|
||||
// that have non-trivial destructors, except for proto2 message objects whose
|
||||
// destructors can be skipped. Also, frees all blocks except the initial block
|
||||
// if it was passed in.
|
||||
~ArenaImpl();
|
||||
|
||||
uint64 Reset();
|
||||
|
||||
uint64 SpaceAllocated() const;
|
||||
uint64 SpaceUsed() const;
|
||||
|
||||
void* AllocateAligned(size_t n) {
|
||||
SerialArena* arena;
|
||||
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAligned(n);
|
||||
} else {
|
||||
return AllocateAlignedFallback(n);
|
||||
}
|
||||
}
|
||||
|
||||
// This function allocates n bytes if the common happy case is true and
|
||||
// returns true. Otherwise does nothing and returns false. This strange
|
||||
// semantics is necessary to allow callers to program functions that only
|
||||
// have fallback function calls in tail position. This substantially improves
|
||||
// code for the happy path.
|
||||
PROTOBUF_ALWAYS_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
|
||||
SerialArena* a;
|
||||
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFromThreadCache(&a))) {
|
||||
return a->MaybeAllocateAligned(n, out);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*));
|
||||
|
||||
// Add object pointer and cleanup function pointer to the list.
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*));
|
||||
|
||||
inline void RecordAlloc(const std::type_info* allocated_type,
|
||||
size_t n) const {
|
||||
if (PROTOBUF_PREDICT_FALSE(record_allocs())) {
|
||||
options_->metrics_collector->OnAlloc(allocated_type, n);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<void*, size_t> NewBuffer(size_t last_size, size_t min_bytes);
|
||||
|
||||
private:
|
||||
// Pointer to a linked list of SerialArena.
|
||||
std::atomic<SerialArena*> threads_;
|
||||
std::atomic<SerialArena*> hint_; // Fast thread-local block access
|
||||
std::atomic<size_t> space_allocated_; // Total size of all allocated blocks.
|
||||
|
||||
// Unique for each arena. Changes on Reset().
|
||||
// Least-significant-bit is 1 iff allocations should be recorded.
|
||||
uint64 lifecycle_id_;
|
||||
|
||||
struct Options {
|
||||
size_t start_block_size;
|
||||
size_t max_block_size;
|
||||
void* (*block_alloc)(size_t);
|
||||
void (*block_dealloc)(void*, size_t);
|
||||
ArenaMetricsCollector* metrics_collector;
|
||||
};
|
||||
|
||||
Options* options_ = nullptr;
|
||||
|
||||
void* AllocateAlignedFallback(size_t n);
|
||||
void* AllocateAlignedAndAddCleanupFallback(size_t n, void (*cleanup)(void*));
|
||||
void AddCleanupFallback(void* elem, void (*cleanup)(void*));
|
||||
|
||||
void Init(bool record_allocs);
|
||||
void SetInitialBlock(
|
||||
SerialArena::Block* block); // Can be called right after Init()
|
||||
|
||||
// Return true iff allocations should be recorded in a metrics collector.
|
||||
inline bool record_allocs() const { return lifecycle_id_ & 1; }
|
||||
|
||||
// Invoke fn(b) for every Block* b.
|
||||
template <typename Functor>
|
||||
void PerBlock(Functor fn) {
|
||||
// By omitting an Acquire barrier we ensure that any user code that doesn't
|
||||
// properly synchronize Reset() or the destructor will throw a TSAN warning.
|
||||
SerialArena* serial = threads_.load(std::memory_order_relaxed);
|
||||
while (serial) {
|
||||
// fn() may delete blocks and arenas, so fetch next pointers before fn();
|
||||
SerialArena* cur = serial;
|
||||
serial = serial->next();
|
||||
for (auto* block = cur->head(); block != nullptr;) {
|
||||
auto* b = block;
|
||||
block = b->next();
|
||||
fn(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete or Destruct all objects owned by the arena.
|
||||
void CleanupList();
|
||||
|
||||
inline void CacheSerialArena(SerialArena* serial) {
|
||||
thread_cache().last_serial_arena = serial;
|
||||
thread_cache().last_lifecycle_id_seen = lifecycle_id_;
|
||||
// TODO(haberman): evaluate whether we would gain efficiency by getting rid
|
||||
// of hint_. It's the only write we do to ArenaImpl in the allocation path,
|
||||
// which will dirty the cache line.
|
||||
|
||||
hint_.store(serial, std::memory_order_release);
|
||||
}
|
||||
|
||||
PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFast(SerialArena** arena) {
|
||||
if (GetSerialArenaFromThreadCache(arena)) return true;
|
||||
|
||||
// Check whether we own the last accessed SerialArena on this arena. This
|
||||
// fast path optimizes the case where a single thread uses multiple arenas.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
SerialArena* serial = hint_.load(std::memory_order_acquire);
|
||||
if (PROTOBUF_PREDICT_TRUE(serial != NULL && serial->owner() == tc)) {
|
||||
*arena = serial;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFromThreadCache(
|
||||
SerialArena** arena) {
|
||||
// If this thread already owns a block in this arena then try to use that.
|
||||
// This fast path optimizes the case where multiple threads allocate from
|
||||
// the same arena.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == lifecycle_id_)) {
|
||||
*arena = tc->last_serial_arena;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
SerialArena* GetSerialArenaFallback(void* me);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
struct alignas(64) ThreadCache {
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// If we are using the ThreadLocalStorage class to store the ThreadCache,
|
||||
// then the ThreadCache's default constructor has to be responsible for
|
||||
// initializing it.
|
||||
ThreadCache()
|
||||
: next_lifecycle_id(0),
|
||||
last_lifecycle_id_seen(-1),
|
||||
last_serial_arena(NULL) {}
|
||||
#endif
|
||||
|
||||
// Number of per-thread lifecycle IDs to reserve. Must be power of two.
|
||||
// To reduce contention on a global atomic, each thread reserves a batch of
|
||||
// IDs. The following number is calculated based on a stress test with
|
||||
// ~6500 threads all frequently allocating a new arena.
|
||||
static constexpr size_t kPerThreadIds = 256;
|
||||
// Next lifecycle ID available to this thread. We need to reserve a new
|
||||
// batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`.
|
||||
uint64 next_lifecycle_id;
|
||||
// The ThreadCache is considered valid as long as this matches the
|
||||
// lifecycle_id of the arena being used.
|
||||
uint64 last_lifecycle_id_seen;
|
||||
SerialArena* last_serial_arena;
|
||||
};
|
||||
|
||||
// Lifecycle_id can be highly contended variable in a situation of lots of
|
||||
// arena creation. Make sure that other global variables are not sharing the
|
||||
// cacheline.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
struct alignas(64) CacheAlignedLifecycleIdGenerator {
|
||||
std::atomic<LifecycleIdAtomic> id;
|
||||
};
|
||||
static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// Android ndk does not support __thread keyword so we use a custom thread
|
||||
// local storage class we implemented.
|
||||
// iOS also does not support the __thread keyword.
|
||||
static ThreadCache& thread_cache();
|
||||
#elif defined(PROTOBUF_USE_DLLS)
|
||||
// Thread local variables cannot be exposed through DLL interface but we can
|
||||
// wrap them in static functions.
|
||||
static ThreadCache& thread_cache();
|
||||
#else
|
||||
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
|
||||
static ThreadCache& thread_cache() { return thread_cache_; }
|
||||
#endif
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArenaImpl);
|
||||
// All protos have pointers back to the arena hence Arena must have
|
||||
// pointer stability.
|
||||
ArenaImpl(ArenaImpl&&) = delete;
|
||||
ArenaImpl& operator=(ArenaImpl&&) = delete;
|
||||
|
||||
public:
|
||||
// kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8
|
||||
// to protect the invariant that pos is always at a multiple of 8.
|
||||
static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize;
|
||||
static constexpr size_t kSerialArenaSize =
|
||||
(sizeof(SerialArena) + 7) & static_cast<size_t>(-8);
|
||||
static constexpr size_t kOptionsSize =
|
||||
(sizeof(Options) + 7) & static_cast<size_t>(-8);
|
||||
static_assert(kBlockHeaderSize % 8 == 0,
|
||||
"kBlockHeaderSize must be a multiple of 8.");
|
||||
static_assert(kSerialArenaSize % 8 == 0,
|
||||
"kSerialArenaSize must be a multiple of 8.");
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_IMPL_H__
|
||||
50
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena_test_util.cc
vendored
Normal file
50
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena_test_util.cc
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/arena_test_util.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
|
||||
#define EXPECT_EQ GOOGLE_CHECK_EQ
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
NoHeapChecker::~NoHeapChecker() {
|
||||
capture_alloc.Unhook();
|
||||
EXPECT_EQ(0, capture_alloc.alloc_count());
|
||||
EXPECT_EQ(0, capture_alloc.free_count());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
99
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena_test_util.h
vendored
Normal file
99
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena_test_util.h
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
template <typename T, bool use_arena>
|
||||
void TestParseCorruptedString(const T& message) {
|
||||
int success_count = 0;
|
||||
std::string s;
|
||||
{
|
||||
// Map order is not deterministic. To make the test deterministic we want
|
||||
// to serialize the proto deterministically.
|
||||
io::StringOutputStream output(&s);
|
||||
io::CodedOutputStream out(&output);
|
||||
out.SetSerializationDeterministic(true);
|
||||
message.SerializePartialToCodedStream(&out);
|
||||
}
|
||||
const int kMaxIters = 900;
|
||||
const int stride = s.size() <= kMaxIters ? 1 : s.size() / kMaxIters;
|
||||
const int start = stride == 1 || use_arena ? 0 : (stride + 1) / 2;
|
||||
for (int i = start; i < s.size(); i += stride) {
|
||||
for (int c = 1 + (i % 17); c < 256; c += 2 * c + (i & 3)) {
|
||||
s[i] ^= c;
|
||||
Arena arena;
|
||||
T* message = Arena::CreateMessage<T>(use_arena ? &arena : nullptr);
|
||||
if (message->ParseFromString(s)) {
|
||||
++success_count;
|
||||
}
|
||||
if (!use_arena) {
|
||||
delete message;
|
||||
}
|
||||
s[i] ^= c; // Restore s to its original state.
|
||||
}
|
||||
}
|
||||
// This next line is a low bar. But getting through the test without crashing
|
||||
// due to use-after-free or other bugs is a big part of what we're checking.
|
||||
GOOGLE_CHECK_GT(success_count, 0);
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
class NoHeapChecker {
|
||||
public:
|
||||
NoHeapChecker() { capture_alloc.Hook(); }
|
||||
~NoHeapChecker();
|
||||
|
||||
private:
|
||||
class NewDeleteCapture {
|
||||
public:
|
||||
// TODO(xiaofeng): Implement this for opensource protobuf.
|
||||
void Hook() {}
|
||||
void Unhook() {}
|
||||
int alloc_count() { return 0; }
|
||||
int free_count() { return 0; }
|
||||
} capture_alloc;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
|
||||
1410
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena_unittest.cc
vendored
Normal file
1410
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arena_unittest.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
254
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arenastring.cc
vendored
Normal file
254
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arenastring.cc
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/parse_context.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
// clang-format off
|
||||
#include <google/protobuf/port_def.inc>
|
||||
// clang-format on
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
const std::string& LazyString::Init() const {
|
||||
static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
|
||||
mu.Lock();
|
||||
const std::string* res = inited_.load(std::memory_order_acquire);
|
||||
if (res == nullptr) {
|
||||
auto init_value = init_value_;
|
||||
res = ::new (static_cast<void*>(string_buf_))
|
||||
std::string(init_value.ptr, init_value.size);
|
||||
inited_.store(res, std::memory_order_release);
|
||||
}
|
||||
mu.Unlock();
|
||||
return *res;
|
||||
}
|
||||
|
||||
|
||||
void ArenaStringPtr::Set(const std::string* default_value,
|
||||
ConstStringParam value, ::google::protobuf::Arena* arena) {
|
||||
if (IsDefault(default_value)) {
|
||||
tagged_ptr_.Set(Arena::Create<std::string>(arena, value));
|
||||
} else {
|
||||
UnsafeMutablePointer()->assign(value.data(), value.length());
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(const std::string* default_value, std::string&& value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (IsDefault(default_value)) {
|
||||
if (arena == nullptr) {
|
||||
tagged_ptr_.Set(new std::string(std::move(value)));
|
||||
} else {
|
||||
tagged_ptr_.Set(Arena::Create<std::string>(arena, std::move(value)));
|
||||
}
|
||||
} else if (IsDonatedString()) {
|
||||
std::string* current = tagged_ptr_.Get();
|
||||
auto* s = new (current) std::string(std::move(value));
|
||||
arena->OwnDestructor(s);
|
||||
tagged_ptr_.Set(s);
|
||||
} else /* !IsDonatedString() */ {
|
||||
*UnsafeMutablePointer() = std::move(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(EmptyDefault, ConstStringParam value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(&GetEmptyStringAlreadyInited(), value, arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(EmptyDefault, std::string&& value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(&GetEmptyStringAlreadyInited(), std::move(value), arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(NonEmptyDefault, ConstStringParam value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(nullptr, value, arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Set(NonEmptyDefault, std::string&& value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
Set(nullptr, std::move(value), arena);
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::Mutable(EmptyDefault, ::google::protobuf::Arena* arena) {
|
||||
if (!IsDonatedString() && !IsDefault(&GetEmptyStringAlreadyInited())) {
|
||||
return UnsafeMutablePointer();
|
||||
} else {
|
||||
return MutableSlow(arena);
|
||||
}
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::Mutable(const LazyString& default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (!IsDonatedString() && !IsDefault(nullptr)) {
|
||||
return UnsafeMutablePointer();
|
||||
} else {
|
||||
return MutableSlow(arena, default_value);
|
||||
}
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::MutableNoCopy(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (!IsDonatedString() && !IsDefault(default_value)) {
|
||||
return UnsafeMutablePointer();
|
||||
} else {
|
||||
GOOGLE_DCHECK(IsDefault(default_value));
|
||||
// Allocate empty. The contents are not relevant.
|
||||
std::string* new_string = Arena::Create<std::string>(arena);
|
||||
tagged_ptr_.Set(new_string);
|
||||
return new_string;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Lazy>
|
||||
std::string* ArenaStringPtr::MutableSlow(::google::protobuf::Arena* arena,
|
||||
const Lazy&... lazy_default) {
|
||||
const std::string* const default_value =
|
||||
sizeof...(Lazy) == 0 ? &GetEmptyStringAlreadyInited() : nullptr;
|
||||
GOOGLE_DCHECK(IsDefault(default_value));
|
||||
std::string* new_string =
|
||||
Arena::Create<std::string>(arena, lazy_default.get()...);
|
||||
tagged_ptr_.Set(new_string);
|
||||
return new_string;
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::Release(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (IsDefault(default_value)) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return ReleaseNonDefault(default_value, arena);
|
||||
}
|
||||
}
|
||||
|
||||
std::string* ArenaStringPtr::ReleaseNonDefault(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
GOOGLE_DCHECK(!IsDefault(default_value));
|
||||
|
||||
if (!IsDonatedString()) {
|
||||
std::string* released;
|
||||
if (arena != nullptr) {
|
||||
released = new std::string;
|
||||
released->swap(*UnsafeMutablePointer());
|
||||
} else {
|
||||
released = UnsafeMutablePointer();
|
||||
}
|
||||
tagged_ptr_.Set(const_cast<std::string*>(default_value));
|
||||
return released;
|
||||
} else /* IsDonatedString() */ {
|
||||
GOOGLE_DCHECK(arena != nullptr);
|
||||
std::string* released = new std::string(Get());
|
||||
tagged_ptr_.Set(const_cast<std::string*>(default_value));
|
||||
return released;
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::SetAllocated(const std::string* default_value,
|
||||
std::string* value, ::google::protobuf::Arena* arena) {
|
||||
// Release what we have first.
|
||||
if (arena == nullptr && !IsDefault(default_value)) {
|
||||
delete UnsafeMutablePointer();
|
||||
}
|
||||
if (value == nullptr) {
|
||||
tagged_ptr_.Set(const_cast<std::string*>(default_value));
|
||||
} else {
|
||||
#ifdef NDEBUG
|
||||
tagged_ptr_.Set(value);
|
||||
if (arena != nullptr) {
|
||||
arena->Own(value);
|
||||
}
|
||||
#else
|
||||
// On debug builds, copy the string so the address differs. delete will
|
||||
// fail if value was a stack-allocated temporary/etc., which would have
|
||||
// failed when arena ran its cleanup list.
|
||||
std::string* new_value = Arena::Create<std::string>(arena, *value);
|
||||
delete value;
|
||||
tagged_ptr_.Set(new_value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Destroy(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (arena == nullptr) {
|
||||
GOOGLE_DCHECK(!IsDonatedString());
|
||||
if (!IsDefault(default_value)) {
|
||||
delete UnsafeMutablePointer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Destroy(EmptyDefault, ::google::protobuf::Arena* arena) {
|
||||
Destroy(&GetEmptyStringAlreadyInited(), arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena) {
|
||||
Destroy(nullptr, arena);
|
||||
}
|
||||
|
||||
void ArenaStringPtr::ClearToEmpty() {
|
||||
if (IsDefault(&GetEmptyStringAlreadyInited())) {
|
||||
// Already set to default -- do nothing.
|
||||
} else {
|
||||
// Unconditionally mask away the tag.
|
||||
//
|
||||
// UpdateDonatedString uses assign when capacity is larger than the new
|
||||
// value, which is trivially true in the donated string case.
|
||||
// const_cast<std::string*>(PtrValue<std::string>())->clear();
|
||||
tagged_ptr_.Get()->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaStringPtr::ClearToDefault(const LazyString& default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
(void)arena;
|
||||
if (IsDefault(nullptr)) {
|
||||
// Already set to default -- do nothing.
|
||||
} else if (!IsDonatedString()) {
|
||||
UnsafeMutablePointer()->assign(default_value.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
375
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arenastring.h
vendored
Normal file
375
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arenastring.h
vendored
Normal file
@@ -0,0 +1,375 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
#define GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/port.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
#ifdef SWIG
|
||||
#error "You cannot SWIG proto headers"
|
||||
#endif
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Lazy string instance to support string fields with non-empty default.
|
||||
// These are initialized on the first call to .get().
|
||||
class PROTOBUF_EXPORT LazyString {
|
||||
public:
|
||||
// We explicitly make LazyString an aggregate so that MSVC can do constant
|
||||
// initialization on it without marking it `constexpr`.
|
||||
// We do not want to use `constexpr` because it makes it harder to have extern
|
||||
// storage for it and causes library bloat.
|
||||
struct InitValue {
|
||||
const char* ptr;
|
||||
size_t size;
|
||||
};
|
||||
// We keep a union of the initialization value and the std::string to save on
|
||||
// space. We don't need the string array after Init() is done.
|
||||
union {
|
||||
mutable InitValue init_value_;
|
||||
alignas(std::string) mutable char string_buf_[sizeof(std::string)];
|
||||
};
|
||||
mutable std::atomic<const std::string*> inited_;
|
||||
|
||||
const std::string& get() const {
|
||||
// This check generates less code than a call-once invocation.
|
||||
auto* res = inited_.load(std::memory_order_acquire);
|
||||
if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init();
|
||||
return *res;
|
||||
}
|
||||
|
||||
private:
|
||||
// Initialize the string in `string_buf_`, update `inited_` and return it.
|
||||
// We return it here to avoid having to read it again in the inlined code.
|
||||
const std::string& Init() const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TaggedPtr {
|
||||
public:
|
||||
TaggedPtr() = default;
|
||||
explicit constexpr TaggedPtr(const std::string* ptr)
|
||||
: ptr_(const_cast<std::string*>(ptr)) {}
|
||||
|
||||
void SetTagged(T* p) {
|
||||
Set(p);
|
||||
ptr_ = reinterpret_cast<void*>(as_int() | 1);
|
||||
}
|
||||
void Set(T* p) { ptr_ = p; }
|
||||
T* Get() const { return reinterpret_cast<T*>(as_int() & -2); }
|
||||
bool IsTagged() const { return as_int() & 1; }
|
||||
|
||||
// Returned value is only safe to dereference if IsTagged() == false.
|
||||
// It is safe to compare.
|
||||
T* UnsafeGet() const { return static_cast<T*>(ptr_); }
|
||||
|
||||
bool IsNull() { return ptr_ == nullptr; }
|
||||
|
||||
private:
|
||||
uintptr_t as_int() const { return reinterpret_cast<uintptr_t>(ptr_); }
|
||||
void* ptr_;
|
||||
};
|
||||
|
||||
static_assert(std::is_trivial<TaggedPtr<std::string>>::value,
|
||||
"TaggedPtr must be trivial");
|
||||
|
||||
// This class encapsulates a pointer to a std::string with or without a donated
|
||||
// buffer, tagged by bottom bit. It is a high-level wrapper that almost directly
|
||||
// corresponds to the interface required by string fields in generated
|
||||
// code. It replaces the old std::string* pointer in such cases.
|
||||
//
|
||||
// The object has different but similar code paths for when the default value is
|
||||
// the empty string and when it is a non-empty string.
|
||||
// The empty string is handled different throughout the library and there is a
|
||||
// single global instance of it we can share.
|
||||
//
|
||||
// For fields with an empty string default value, there are three distinct
|
||||
// states:
|
||||
//
|
||||
// - Pointer set to 'String' tag (LSB is 0), equal to
|
||||
// &GetEmptyStringAlreadyInited(): field is set to its default value. Points
|
||||
// to a true std::string*, but we do not own that std::string* (it's a
|
||||
// globally shared instance).
|
||||
//
|
||||
// - Pointer set to 'String' tag (LSB is 0), but not equal to the global empty
|
||||
// string: field points to a true std::string* instance that we own. This
|
||||
// instance is either on the heap or on the arena (i.e. registered on
|
||||
// free()/destructor-call list) as appropriate.
|
||||
//
|
||||
// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
|
||||
// instance with a buffer on the arena (arena != NULL, always, in this case).
|
||||
//
|
||||
// For fields with a non-empty string default value, there are three distinct
|
||||
// states:
|
||||
//
|
||||
// - Pointer set to 'String' tag (LSB is 0), equal to `nullptr`:
|
||||
// Field is in "default" mode and does not point to any actual instance.
|
||||
// Methods that might need to create an instance of the object will pass a
|
||||
// `const LazyString&` for it.
|
||||
//
|
||||
// - Pointer set to 'String' tag (LSB is 0), but not equal to `nullptr`:
|
||||
// field points to a true std::string* instance that we own. This instance is
|
||||
// either on the heap or on the arena (i.e. registered on
|
||||
// free()/destructor-call list) as appropriate.
|
||||
//
|
||||
// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
|
||||
// instance with a buffer on the arena (arena != NULL, always, in this case).
|
||||
//
|
||||
// Generated code and reflection code both ensure that ptr_ is never null for
|
||||
// fields with an empty default.
|
||||
// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and
|
||||
// so the field is always manually initialized via method calls.
|
||||
//
|
||||
// Side-note: why pass information about the default on every API call? Because
|
||||
// we don't want to hold it in a member variable, or else this would go into
|
||||
// every proto message instance. This would be a huge waste of space, since the
|
||||
// default instance pointer is typically a global (static class field). We want
|
||||
// the generated code to be as efficient as possible, and if we take
|
||||
// the default value information as a parameter that's in practice taken from a
|
||||
// static class field, and compare ptr_ to the default value, we end up with a
|
||||
// single "cmp %reg, GLOBAL" in the resulting machine code. (Note that this also
|
||||
// requires the String tag to be 0 so we can avoid the mask before comparing.)
|
||||
struct PROTOBUF_EXPORT ArenaStringPtr {
|
||||
ArenaStringPtr() = default;
|
||||
explicit constexpr ArenaStringPtr(const std::string* default_value)
|
||||
: tagged_ptr_(default_value) {}
|
||||
|
||||
// Some methods below are overloaded on a `default_value` and on tags.
|
||||
// The tagged overloads help reduce code size in the callers in generated
|
||||
// code, while the `default_value` overloads are useful from reflection.
|
||||
// By-value empty struct arguments are elided in the ABI.
|
||||
struct EmptyDefault {};
|
||||
struct NonEmptyDefault {};
|
||||
|
||||
void Set(const std::string* default_value, ConstStringParam value,
|
||||
::google::protobuf::Arena* arena);
|
||||
void Set(const std::string* default_value, std::string&& value,
|
||||
::google::protobuf::Arena* arena);
|
||||
void Set(EmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
|
||||
void Set(EmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
|
||||
void Set(NonEmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
|
||||
void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
|
||||
|
||||
// Basic accessors.
|
||||
const std::string& Get() const PROTOBUF_ALWAYS_INLINE {
|
||||
// Unconditionally mask away the tag.
|
||||
return *tagged_ptr_.Get();
|
||||
}
|
||||
const std::string* GetPointer() const PROTOBUF_ALWAYS_INLINE {
|
||||
// Unconditionally mask away the tag.
|
||||
return tagged_ptr_.Get();
|
||||
}
|
||||
|
||||
// For fields with an empty default value.
|
||||
std::string* Mutable(EmptyDefault, ::google::protobuf::Arena* arena);
|
||||
// For fields with a non-empty default value.
|
||||
std::string* Mutable(const LazyString& default_value, ::google::protobuf::Arena* arena);
|
||||
|
||||
// Release returns a std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field is not set, this returns NULL. The
|
||||
// caller retains ownership. Clears this field back to NULL state. Used to
|
||||
// implement release_<field>() methods on generated classes.
|
||||
std::string* Release(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena);
|
||||
std::string* ReleaseNonDefault(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena);
|
||||
|
||||
// Takes a std::string that is heap-allocated, and takes ownership. The
|
||||
// std::string's destructor is registered with the arena. Used to implement
|
||||
// set_allocated_<field> in generated classes.
|
||||
void SetAllocated(const std::string* default_value, std::string* value,
|
||||
::google::protobuf::Arena* arena);
|
||||
|
||||
// Swaps internal pointers. Arena-safety semantics: this is guarded by the
|
||||
// logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
|
||||
// 'unsafe' if called directly.
|
||||
inline void Swap(ArenaStringPtr* other, const std::string* default_value,
|
||||
Arena* arena) PROTOBUF_ALWAYS_INLINE;
|
||||
|
||||
// Frees storage (if not on an arena).
|
||||
void Destroy(const std::string* default_value, ::google::protobuf::Arena* arena);
|
||||
void Destroy(EmptyDefault, ::google::protobuf::Arena* arena);
|
||||
void Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena);
|
||||
|
||||
// Clears content, but keeps allocated std::string, to avoid the overhead of
|
||||
// heap operations. After this returns, the content (as seen by the user) will
|
||||
// always be the empty std::string. Assumes that |default_value| is an empty
|
||||
// std::string.
|
||||
void ClearToEmpty();
|
||||
|
||||
// Clears content, assuming that the current value is not the empty
|
||||
// string default.
|
||||
void ClearNonDefaultToEmpty();
|
||||
|
||||
// Clears content, but keeps allocated std::string if arena != NULL, to avoid
|
||||
// the overhead of heap operations. After this returns, the content (as seen
|
||||
// by the user) will always be equal to |default_value|.
|
||||
void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena);
|
||||
|
||||
// Called from generated code / reflection runtime only. Resets value to point
|
||||
// to a default string pointer, with the semantics that this
|
||||
// ArenaStringPtr does not own the pointed-to memory. Disregards initial value
|
||||
// of ptr_ (so this is the *ONLY* safe method to call after construction or
|
||||
// when reinitializing after becoming the active field in a oneof union).
|
||||
inline void UnsafeSetDefault(const std::string* default_value);
|
||||
|
||||
// Returns a mutable pointer, but doesn't initialize the string to the
|
||||
// default value.
|
||||
std::string* MutableNoArenaNoDefault(const std::string* default_value);
|
||||
|
||||
// Get a mutable pointer with unspecified contents.
|
||||
// Similar to `MutableNoArenaNoDefault`, but also handles the arena case.
|
||||
// If the value was donated, the contents are discarded.
|
||||
std::string* MutableNoCopy(const std::string* default_value,
|
||||
::google::protobuf::Arena* arena);
|
||||
|
||||
// Destroy the string. Assumes `arena == nullptr`.
|
||||
void DestroyNoArena(const std::string* default_value);
|
||||
|
||||
// Internal setter used only at parse time to directly set a donated string
|
||||
// value.
|
||||
void UnsafeSetTaggedPointer(TaggedPtr<std::string> value) {
|
||||
tagged_ptr_ = value;
|
||||
}
|
||||
// Generated code only! An optimization, in certain cases the generated
|
||||
// code is certain we can obtain a std::string with no default checks and
|
||||
// tag tests.
|
||||
std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL;
|
||||
|
||||
inline bool IsDefault(const std::string* default_value) const {
|
||||
// Relies on the fact that kPtrTagString == 0, so if IsString(), ptr_ is the
|
||||
// actual std::string pointer (and if !IsString(), ptr_ will never be equal
|
||||
// to any aligned |default_value| pointer). The key is that we want to avoid
|
||||
// masking in the fastpath const-pointer Get() case for non-arena code.
|
||||
return tagged_ptr_.UnsafeGet() == default_value;
|
||||
}
|
||||
|
||||
private:
|
||||
TaggedPtr<std::string> tagged_ptr_;
|
||||
|
||||
bool IsDonatedString() const { return false; }
|
||||
|
||||
// Slow paths.
|
||||
|
||||
// MutableSlow requires that !IsString() || IsDefault
|
||||
// Variadic to support 0 args for EmptyDefault and 1 arg for LazyString.
|
||||
template <typename... Lazy>
|
||||
std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default);
|
||||
|
||||
};
|
||||
|
||||
inline void ArenaStringPtr::UnsafeSetDefault(const std::string* value) {
|
||||
tagged_ptr_.Set(const_cast<std::string*>(value));
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::Swap(ArenaStringPtr* other,
|
||||
const std::string* default_value,
|
||||
Arena* arena) {
|
||||
#ifndef NDEBUG
|
||||
// For debug builds, we swap the contents of the string, rather than the
|
||||
// std::string instances themselves. This invalidates previously taken const
|
||||
// references that are (per our documentation) invalidated by calling Swap()
|
||||
// on the message.
|
||||
//
|
||||
// If both strings are the default_value, swapping is uninteresting.
|
||||
// Otherwise, we use ArenaStringPtr::Mutable() to access the std::string, to
|
||||
// ensure that we do not try to mutate default_value itself.
|
||||
if (IsDefault(default_value) && other->IsDefault(default_value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (default_value == nullptr) {
|
||||
// If we have non-empty default, then `default_value` is null and we can't
|
||||
// call Mutable the same way. Just do the regular swap.
|
||||
std::swap(tagged_ptr_, other->tagged_ptr_);
|
||||
} else {
|
||||
std::string* this_ptr = Mutable(EmptyDefault{}, arena);
|
||||
std::string* other_ptr = other->Mutable(EmptyDefault{}, arena);
|
||||
|
||||
this_ptr->swap(*other_ptr);
|
||||
}
|
||||
#else
|
||||
std::swap(tagged_ptr_, other->tagged_ptr_);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::ClearNonDefaultToEmpty() {
|
||||
// Unconditionally mask away the tag.
|
||||
tagged_ptr_.Get()->clear();
|
||||
}
|
||||
|
||||
inline std::string* ArenaStringPtr::MutableNoArenaNoDefault(
|
||||
const std::string* default_value) {
|
||||
// VERY IMPORTANT for performance and code size: this will reduce to a member
|
||||
// variable load, a pointer check (against |default_value|, in practice a
|
||||
// static global) and a branch to the slowpath (which calls operator new and
|
||||
// the ctor). DO NOT add any tagged-pointer operations here.
|
||||
if (IsDefault(default_value)) {
|
||||
std::string* new_string = new std::string();
|
||||
tagged_ptr_.Set(new_string);
|
||||
return new_string;
|
||||
} else {
|
||||
return UnsafeMutablePointer();
|
||||
}
|
||||
}
|
||||
|
||||
inline void ArenaStringPtr::DestroyNoArena(const std::string* default_value) {
|
||||
if (!IsDefault(default_value)) {
|
||||
delete UnsafeMutablePointer();
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string* ArenaStringPtr::UnsafeMutablePointer() {
|
||||
GOOGLE_DCHECK(!tagged_ptr_.IsTagged());
|
||||
GOOGLE_DCHECK(tagged_ptr_.UnsafeGet() != nullptr);
|
||||
return tagged_ptr_.UnsafeGet();
|
||||
}
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
175
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arenastring_unittest.cc
vendored
Normal file
175
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/arenastring_unittest.cc
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
|
||||
// Must be included last.
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
using internal::ArenaStringPtr;
|
||||
|
||||
static std::string WrapString(const char* value) { return value; }
|
||||
|
||||
using EmptyDefault = ArenaStringPtr::EmptyDefault;
|
||||
|
||||
const internal::LazyString nonempty_default{{{"default", 7}}, {nullptr}};
|
||||
|
||||
// Test ArenaStringPtr with arena == NULL.
|
||||
TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) {
|
||||
ArenaStringPtr field;
|
||||
const std::string* empty_default = &internal::GetEmptyString();
|
||||
field.UnsafeSetDefault(empty_default);
|
||||
EXPECT_EQ(std::string(""), field.Get());
|
||||
field.Set(empty_default, WrapString("Test short"), NULL);
|
||||
EXPECT_EQ(std::string("Test short"), field.Get());
|
||||
field.Set(empty_default, WrapString("Test long long long long value"), NULL);
|
||||
EXPECT_EQ(std::string("Test long long long long value"), field.Get());
|
||||
field.Set(empty_default, std::string(""), NULL);
|
||||
field.Destroy(empty_default, NULL);
|
||||
|
||||
ArenaStringPtr field2;
|
||||
field2.UnsafeSetDefault(empty_default);
|
||||
std::string* mut = field2.Mutable(EmptyDefault{}, NULL);
|
||||
EXPECT_EQ(mut, field2.Mutable(EmptyDefault{}, NULL));
|
||||
EXPECT_EQ(mut, &field2.Get());
|
||||
EXPECT_NE(empty_default, mut);
|
||||
EXPECT_EQ(std::string(""), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(std::string("Test long long long long value"), field2.Get());
|
||||
field2.Destroy(empty_default, NULL);
|
||||
|
||||
ArenaStringPtr field3;
|
||||
field3.UnsafeSetDefault(nullptr);
|
||||
mut = field3.Mutable(nonempty_default, NULL);
|
||||
EXPECT_EQ(mut, field3.Mutable(nonempty_default, NULL));
|
||||
EXPECT_EQ(mut, &field3.Get());
|
||||
EXPECT_NE(nullptr, mut);
|
||||
EXPECT_EQ(std::string("default"), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(std::string("Test long long long long value"), field3.Get());
|
||||
field3.Destroy(nullptr, NULL);
|
||||
}
|
||||
|
||||
TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) {
|
||||
Arena arena;
|
||||
ArenaStringPtr field;
|
||||
const std::string* empty_default = &internal::GetEmptyString();
|
||||
field.UnsafeSetDefault(empty_default);
|
||||
EXPECT_EQ(std::string(""), field.Get());
|
||||
field.Set(empty_default, WrapString("Test short"), &arena);
|
||||
EXPECT_EQ(std::string("Test short"), field.Get());
|
||||
field.Set(empty_default, WrapString("Test long long long long value"),
|
||||
&arena);
|
||||
EXPECT_EQ(std::string("Test long long long long value"), field.Get());
|
||||
field.Set(empty_default, std::string(""), &arena);
|
||||
field.Destroy(empty_default, &arena);
|
||||
|
||||
ArenaStringPtr field2;
|
||||
field2.UnsafeSetDefault(empty_default);
|
||||
std::string* mut = field2.Mutable(EmptyDefault{}, &arena);
|
||||
EXPECT_EQ(mut, field2.Mutable(EmptyDefault{}, &arena));
|
||||
EXPECT_EQ(mut, &field2.Get());
|
||||
EXPECT_NE(empty_default, mut);
|
||||
EXPECT_EQ(std::string(""), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(std::string("Test long long long long value"), field2.Get());
|
||||
field2.Destroy(empty_default, &arena);
|
||||
|
||||
ArenaStringPtr field3;
|
||||
field3.UnsafeSetDefault(nullptr);
|
||||
mut = field3.Mutable(nonempty_default, &arena);
|
||||
EXPECT_EQ(mut, field3.Mutable(nonempty_default, &arena));
|
||||
EXPECT_EQ(mut, &field3.Get());
|
||||
EXPECT_NE(nullptr, mut);
|
||||
EXPECT_EQ(std::string("default"), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(std::string("Test long long long long value"), field3.Get());
|
||||
field3.Destroy(nullptr, &arena);
|
||||
}
|
||||
|
||||
TEST(ArenaStringPtrTest, ArenaStringPtrOnArenaNoSSO) {
|
||||
Arena arena;
|
||||
ArenaStringPtr field;
|
||||
const std::string* empty_default = &internal::GetEmptyString();
|
||||
field.UnsafeSetDefault(empty_default);
|
||||
EXPECT_EQ(std::string(""), field.Get());
|
||||
|
||||
// Avoid triggering the SSO optimization by setting the string to something
|
||||
// larger than the internal buffer.
|
||||
field.Set(empty_default, WrapString("Test long long long long value"),
|
||||
&arena);
|
||||
EXPECT_EQ(std::string("Test long long long long value"), field.Get());
|
||||
field.Set(empty_default, std::string(""), &arena);
|
||||
field.Destroy(empty_default, &arena);
|
||||
|
||||
ArenaStringPtr field2;
|
||||
field2.UnsafeSetDefault(empty_default);
|
||||
std::string* mut = field2.Mutable(EmptyDefault{}, &arena);
|
||||
EXPECT_EQ(mut, field2.Mutable(EmptyDefault{}, &arena));
|
||||
EXPECT_EQ(mut, &field2.Get());
|
||||
EXPECT_NE(empty_default, mut);
|
||||
EXPECT_EQ(std::string(""), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(std::string("Test long long long long value"), field2.Get());
|
||||
field2.Destroy(empty_default, &arena);
|
||||
|
||||
ArenaStringPtr field3;
|
||||
field3.UnsafeSetDefault(nullptr);
|
||||
mut = field3.Mutable(nonempty_default, &arena);
|
||||
EXPECT_EQ(mut, field3.Mutable(nonempty_default, &arena));
|
||||
EXPECT_EQ(mut, &field3.Get());
|
||||
EXPECT_NE(nullptr, mut);
|
||||
EXPECT_EQ(std::string("default"), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(std::string("Test long long long long value"), field3.Get());
|
||||
field3.Destroy(nullptr, &arena);
|
||||
}
|
||||
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
167
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/annotation_test_util.cc
vendored
Normal file
167
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/annotation_test_util.cc
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/compiler/annotation_test_util.h>
|
||||
|
||||
#include <memory>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/command_line_interface.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace annotation_test_util {
|
||||
namespace {
|
||||
|
||||
// A CodeGenerator that captures the FileDescriptor it's passed as a
|
||||
// FileDescriptorProto.
|
||||
class DescriptorCapturingGenerator : public CodeGenerator {
|
||||
public:
|
||||
// Does not own file; file must outlive the Generator.
|
||||
explicit DescriptorCapturingGenerator(FileDescriptorProto* file)
|
||||
: file_(file) {}
|
||||
|
||||
virtual bool Generate(const FileDescriptor* file,
|
||||
const std::string& parameter, GeneratorContext* context,
|
||||
std::string* error) const {
|
||||
file->CopyTo(file_);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
FileDescriptorProto* file_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
void AddFile(const std::string& filename, const std::string& data) {
|
||||
GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data,
|
||||
true));
|
||||
}
|
||||
|
||||
bool RunProtoCompiler(const std::string& filename,
|
||||
const std::string& plugin_specific_args,
|
||||
CommandLineInterface* cli, FileDescriptorProto* file) {
|
||||
cli->SetInputsAreProtoPathRelative(true);
|
||||
|
||||
DescriptorCapturingGenerator capturing_generator(file);
|
||||
cli->RegisterGenerator("--capture_out", &capturing_generator, "");
|
||||
|
||||
std::string proto_path = "-I" + TestTempDir();
|
||||
std::string capture_out = "--capture_out=" + TestTempDir();
|
||||
|
||||
const char* argv[] = {"protoc", proto_path.c_str(),
|
||||
plugin_specific_args.c_str(), capture_out.c_str(),
|
||||
filename.c_str()};
|
||||
|
||||
return cli->Run(5, argv) == 0;
|
||||
}
|
||||
|
||||
bool DecodeMetadata(const std::string& path, GeneratedCodeInfo* info) {
|
||||
std::string data;
|
||||
GOOGLE_CHECK_OK(File::GetContents(path, &data, true));
|
||||
io::ArrayInputStream input(data.data(), data.size());
|
||||
return info->ParseFromZeroCopyStream(&input);
|
||||
}
|
||||
|
||||
void FindAnnotationsOnPath(
|
||||
const GeneratedCodeInfo& info, const std::string& source_file,
|
||||
const std::vector<int>& path,
|
||||
std::vector<const GeneratedCodeInfo::Annotation*>* annotations) {
|
||||
for (int i = 0; i < info.annotation_size(); ++i) {
|
||||
const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i);
|
||||
if (annotation->source_file() != source_file ||
|
||||
annotation->path_size() != path.size()) {
|
||||
continue;
|
||||
}
|
||||
int node = 0;
|
||||
for (; node < path.size(); ++node) {
|
||||
if (annotation->path(node) != path[node]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (node == path.size()) {
|
||||
annotations->push_back(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
|
||||
const GeneratedCodeInfo& info, const std::string& source_file,
|
||||
const std::vector<int>& path) {
|
||||
std::vector<const GeneratedCodeInfo::Annotation*> annotations;
|
||||
FindAnnotationsOnPath(info, source_file, path, &annotations);
|
||||
if (annotations.empty()) {
|
||||
return NULL;
|
||||
}
|
||||
return annotations[0];
|
||||
}
|
||||
|
||||
bool AtLeastOneAnnotationMatchesSubstring(
|
||||
const std::string& file_content,
|
||||
const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
|
||||
const std::string& expected_text) {
|
||||
for (std::vector<const GeneratedCodeInfo::Annotation*>::const_iterator
|
||||
i = annotations.begin(),
|
||||
e = annotations.end();
|
||||
i != e; ++i) {
|
||||
const GeneratedCodeInfo::Annotation* annotation = *i;
|
||||
uint32 begin = annotation->begin();
|
||||
uint32 end = annotation->end();
|
||||
if (end < begin || end > file_content.size()) {
|
||||
return false;
|
||||
}
|
||||
if (file_content.substr(begin, end - begin) == expected_text) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AnnotationMatchesSubstring(const std::string& file_content,
|
||||
const GeneratedCodeInfo::Annotation* annotation,
|
||||
const std::string& expected_text) {
|
||||
std::vector<const GeneratedCodeInfo::Annotation*> annotations;
|
||||
annotations.push_back(annotation);
|
||||
return AtLeastOneAnnotationMatchesSubstring(file_content, annotations,
|
||||
expected_text);
|
||||
}
|
||||
} // namespace annotation_test_util
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
115
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/annotation_test_util.h
vendored
Normal file
115
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/annotation_test_util.h
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
|
||||
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Utilities that assist in writing tests for generator annotations.
|
||||
// See java/internal/annotation_unittest.cc for an example.
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace annotation_test_util {
|
||||
|
||||
// Struct that contains the file generated from a .proto file and its
|
||||
// GeneratedCodeInfo. For example, the Java generator will fill this struct
|
||||
// (for some 'foo.proto') with:
|
||||
// file_path = "Foo.java"
|
||||
// file_content = content of Foo.java
|
||||
// file_info = parsed content of Foo.java.pb.meta
|
||||
struct ExpectedOutput {
|
||||
std::string file_path;
|
||||
std::string file_content;
|
||||
GeneratedCodeInfo file_info;
|
||||
explicit ExpectedOutput(const std::string& file_path)
|
||||
: file_path(file_path) {}
|
||||
};
|
||||
|
||||
// Creates a file with name `filename` and content `data` in temp test
|
||||
// directory.
|
||||
void AddFile(const std::string& filename, const std::string& data);
|
||||
|
||||
// Runs proto compiler. Captures proto file structure in FileDescriptorProto.
|
||||
// Files will be generated in TestTempDir() folder. Callers of this
|
||||
// function must read generated files themselves.
|
||||
//
|
||||
// filename: source .proto file used to generate code.
|
||||
// plugin_specific_args: command line arguments specific to current generator.
|
||||
// For Java, this value might be "--java_out=annotate_code:test_temp_dir"
|
||||
// cli: instance of command line interface to run generator. See Java's
|
||||
// annotation_unittest.cc for an example of how to initialize it.
|
||||
// file: output parameter, will be set to the descriptor of the proto file
|
||||
// specified in filename.
|
||||
bool RunProtoCompiler(const std::string& filename,
|
||||
const std::string& plugin_specific_args,
|
||||
CommandLineInterface* cli, FileDescriptorProto* file);
|
||||
|
||||
bool DecodeMetadata(const std::string& path, GeneratedCodeInfo* info);
|
||||
|
||||
// Finds all of the Annotations for a given source file and path.
|
||||
// See Location.path in http://google3/net/proto2/proto/descriptor.proto for
|
||||
// explanation of what path vector is.
|
||||
void FindAnnotationsOnPath(
|
||||
const GeneratedCodeInfo& info, const std::string& source_file,
|
||||
const std::vector<int>& path,
|
||||
std::vector<const GeneratedCodeInfo::Annotation*>* annotations);
|
||||
|
||||
// Finds the Annotation for a given source file and path (or returns null if it
|
||||
// couldn't). If there are several annotations for given path, returns the first
|
||||
// one. See Location.path in
|
||||
// http://google3/net/proto2/proto/descriptor.proto for explanation of what path
|
||||
// vector is.
|
||||
const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
|
||||
const GeneratedCodeInfo& info, const std::string& source_file,
|
||||
const std::vector<int>& path);
|
||||
|
||||
// Returns true if at least one of the provided annotations covers a given
|
||||
// substring in file_content.
|
||||
bool AtLeastOneAnnotationMatchesSubstring(
|
||||
const std::string& file_content,
|
||||
const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
|
||||
const std::string& expected_text);
|
||||
|
||||
// Returns true if the provided annotation covers a given substring in
|
||||
// file_content.
|
||||
bool AnnotationMatchesSubstring(const std::string& file_content,
|
||||
const GeneratedCodeInfo::Annotation* annotation,
|
||||
const std::string& expected_text);
|
||||
|
||||
} // namespace annotation_test_util
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
|
||||
128
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/code_generator.cc
vendored
Normal file
128
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/code_generator.cc
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/plugin.pb.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
|
||||
CodeGenerator::~CodeGenerator() {}
|
||||
|
||||
bool CodeGenerator::GenerateAll(const std::vector<const FileDescriptor*>& files,
|
||||
const std::string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
std::string* error) const {
|
||||
// Default implementation is just to call the per file method, and prefix any
|
||||
// error string with the file to provide context.
|
||||
bool succeeded = true;
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
const FileDescriptor* file = files[i];
|
||||
succeeded = Generate(file, parameter, generator_context, error);
|
||||
if (!succeeded && error && error->empty()) {
|
||||
*error =
|
||||
"Code generator returned false but provided no error "
|
||||
"description.";
|
||||
}
|
||||
if (error && !error->empty()) {
|
||||
*error = file->name() + ": " + *error;
|
||||
break;
|
||||
}
|
||||
if (!succeeded) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
GeneratorContext::~GeneratorContext() {}
|
||||
|
||||
io::ZeroCopyOutputStream* GeneratorContext::OpenForAppend(
|
||||
const std::string& filename) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
|
||||
const std::string& filename, const std::string& insertion_point) {
|
||||
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
|
||||
return NULL; // make compiler happy
|
||||
}
|
||||
|
||||
io::ZeroCopyOutputStream* GeneratorContext::OpenForInsertWithGeneratedCodeInfo(
|
||||
const std::string& filename, const std::string& insertion_point,
|
||||
const google::protobuf::GeneratedCodeInfo& /*info*/) {
|
||||
return OpenForInsert(filename, insertion_point);
|
||||
}
|
||||
|
||||
void GeneratorContext::ListParsedFiles(
|
||||
std::vector<const FileDescriptor*>* output) {
|
||||
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
|
||||
}
|
||||
|
||||
void GeneratorContext::GetCompilerVersion(Version* version) const {
|
||||
version->set_major(GOOGLE_PROTOBUF_VERSION / 1000000);
|
||||
version->set_minor(GOOGLE_PROTOBUF_VERSION / 1000 % 1000);
|
||||
version->set_patch(GOOGLE_PROTOBUF_VERSION % 1000);
|
||||
version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX);
|
||||
}
|
||||
|
||||
// Parses a set of comma-delimited name/value pairs.
|
||||
void ParseGeneratorParameter(
|
||||
const std::string& text,
|
||||
std::vector<std::pair<std::string, std::string> >* output) {
|
||||
std::vector<std::string> parts = Split(text, ",", true);
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
std::string::size_type equals_pos = parts[i].find_first_of('=');
|
||||
std::pair<std::string, std::string> value;
|
||||
if (equals_pos == std::string::npos) {
|
||||
value.first = parts[i];
|
||||
value.second = "";
|
||||
} else {
|
||||
value.first = parts[i].substr(0, equals_pos);
|
||||
value.second = parts[i].substr(equals_pos + 1);
|
||||
}
|
||||
output->push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
202
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/code_generator.h
vendored
Normal file
202
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/code_generator.h
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Defines the abstract interface implemented by each of the language-specific
|
||||
// code generators.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io {
|
||||
class ZeroCopyOutputStream;
|
||||
}
|
||||
class FileDescriptor;
|
||||
class GeneratedCodeInfo;
|
||||
|
||||
namespace compiler {
|
||||
class AccessInfoMap;
|
||||
|
||||
class Version;
|
||||
|
||||
// Defined in this file.
|
||||
class CodeGenerator;
|
||||
class GeneratorContext;
|
||||
|
||||
// The abstract interface to a class which generates code implementing a
|
||||
// particular proto file in a particular language. A number of these may
|
||||
// be registered with CommandLineInterface to support various languages.
|
||||
class PROTOC_EXPORT CodeGenerator {
|
||||
public:
|
||||
inline CodeGenerator() {}
|
||||
virtual ~CodeGenerator();
|
||||
|
||||
// Generates code for the given proto file, generating one or more files in
|
||||
// the given output directory.
|
||||
//
|
||||
// A parameter to be passed to the generator can be specified on the command
|
||||
// line. This is intended to be used to pass generator specific parameters.
|
||||
// It is empty if no parameter was given. ParseGeneratorParameter (below),
|
||||
// can be used to accept multiple parameters within the single parameter
|
||||
// command line flag.
|
||||
//
|
||||
// Returns true if successful. Otherwise, sets *error to a description of
|
||||
// the problem (e.g. "invalid parameter") and returns false.
|
||||
virtual bool Generate(const FileDescriptor* file,
|
||||
const std::string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
std::string* error) const = 0;
|
||||
|
||||
// Generates code for all given proto files.
|
||||
//
|
||||
// WARNING: The canonical code generator design produces one or two output
|
||||
// files per input .proto file, and we do not wish to encourage alternate
|
||||
// designs.
|
||||
//
|
||||
// A parameter is given as passed on the command line, as in |Generate()|
|
||||
// above.
|
||||
//
|
||||
// Returns true if successful. Otherwise, sets *error to a description of
|
||||
// the problem (e.g. "invalid parameter") and returns false.
|
||||
virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files,
|
||||
const std::string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
std::string* error) const;
|
||||
|
||||
// Sync with plugin.proto.
|
||||
enum Feature {
|
||||
FEATURE_PROTO3_OPTIONAL = 1,
|
||||
};
|
||||
|
||||
// Implement this to indicate what features this code generator supports.
|
||||
// This should be a bitwise OR of features from the Features enum in
|
||||
// plugin.proto.
|
||||
virtual uint64_t GetSupportedFeatures() const { return 0; }
|
||||
|
||||
// This is no longer used, but this class is part of the opensource protobuf
|
||||
// library, so it has to remain to keep vtables the same for the current
|
||||
// version of the library. When protobufs does a api breaking change, the
|
||||
// method can be removed.
|
||||
virtual bool HasGenerateAll() const { return true; }
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
|
||||
};
|
||||
|
||||
// CodeGenerators generate one or more files in a given directory. This
|
||||
// abstract interface represents the directory to which the CodeGenerator is
|
||||
// to write and other information about the context in which the Generator
|
||||
// runs.
|
||||
class PROTOC_EXPORT GeneratorContext {
|
||||
public:
|
||||
inline GeneratorContext() {
|
||||
}
|
||||
virtual ~GeneratorContext();
|
||||
|
||||
// Opens the given file, truncating it if it exists, and returns a
|
||||
// ZeroCopyOutputStream that writes to the file. The caller takes ownership
|
||||
// of the returned object. This method never fails (a dummy stream will be
|
||||
// returned instead).
|
||||
//
|
||||
// The filename given should be relative to the root of the source tree.
|
||||
// E.g. the C++ generator, when generating code for "foo/bar.proto", will
|
||||
// generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that
|
||||
// "foo/" is included in these filenames. The filename is not allowed to
|
||||
// contain "." or ".." components.
|
||||
virtual io::ZeroCopyOutputStream* Open(const std::string& filename) = 0;
|
||||
|
||||
// Similar to Open() but the output will be appended to the file if exists
|
||||
virtual io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename);
|
||||
|
||||
// Creates a ZeroCopyOutputStream which will insert code into the given file
|
||||
// at the given insertion point. See plugin.proto (plugin.pb.h) for more
|
||||
// information on insertion points. The default implementation
|
||||
// assert-fails -- it exists only for backwards-compatibility.
|
||||
//
|
||||
// WARNING: This feature is currently EXPERIMENTAL and is subject to change.
|
||||
virtual io::ZeroCopyOutputStream* OpenForInsert(
|
||||
const std::string& filename, const std::string& insertion_point);
|
||||
|
||||
// Similar to OpenForInsert, but if `info` is non-empty, will open (or create)
|
||||
// filename.pb.meta and insert info at the appropriate place with the
|
||||
// necessary shifts. The default implementation ignores `info`.
|
||||
//
|
||||
// WARNING: This feature will be REMOVED in the near future.
|
||||
virtual io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo(
|
||||
const std::string& filename, const std::string& insertion_point,
|
||||
const google::protobuf::GeneratedCodeInfo& info);
|
||||
|
||||
// Returns a vector of FileDescriptors for all the files being compiled
|
||||
// in this run. Useful for languages, such as Go, that treat files
|
||||
// differently when compiled as a set rather than individually.
|
||||
virtual void ListParsedFiles(std::vector<const FileDescriptor*>* output);
|
||||
|
||||
// Retrieves the version number of the protocol compiler associated with
|
||||
// this GeneratorContext.
|
||||
virtual void GetCompilerVersion(Version* version) const;
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
|
||||
};
|
||||
|
||||
// The type GeneratorContext was once called OutputDirectory. This typedef
|
||||
// provides backward compatibility.
|
||||
typedef GeneratorContext OutputDirectory;
|
||||
|
||||
// Several code generators treat the parameter argument as holding a
|
||||
// list of options separated by commas. This helper function parses
|
||||
// a set of comma-delimited name/value pairs: e.g.,
|
||||
// "foo=bar,baz,qux=corge"
|
||||
// parses to the pairs:
|
||||
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
|
||||
PROTOC_EXPORT void ParseGeneratorParameter(
|
||||
const std::string&, std::vector<std::pair<std::string, std::string> >*);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
|
||||
2688
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/command_line_interface.cc
vendored
Normal file
2688
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/command_line_interface.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
466
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/command_line_interface.h
vendored
Normal file
466
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/command_line_interface.h
vendored
Normal file
@@ -0,0 +1,466 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Implements the Protocol Compiler front-end such that it may be reused by
|
||||
// custom compilers written to support other languages.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Descriptor; // descriptor.h
|
||||
class DescriptorDatabase; // descriptor_database.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
class FileDescriptor; // descriptor.h
|
||||
class FileDescriptorSet; // descriptor.h
|
||||
class FileDescriptorProto; // descriptor.pb.h
|
||||
template <typename T>
|
||||
class RepeatedPtrField; // repeated_field.h
|
||||
class SimpleDescriptorDatabase; // descriptor_database.h
|
||||
|
||||
namespace compiler {
|
||||
|
||||
class CodeGenerator; // code_generator.h
|
||||
class GeneratorContext; // code_generator.h
|
||||
class DiskSourceTree; // importer.h
|
||||
|
||||
// This class implements the command-line interface to the protocol compiler.
|
||||
// It is designed to make it very easy to create a custom protocol compiler
|
||||
// supporting the languages of your choice. For example, if you wanted to
|
||||
// create a custom protocol compiler binary which includes both the regular
|
||||
// C++ support plus support for your own custom output "Foo", you would
|
||||
// write a class "FooGenerator" which implements the CodeGenerator interface,
|
||||
// then write a main() procedure like this:
|
||||
//
|
||||
// int main(int argc, char* argv[]) {
|
||||
// google::protobuf::compiler::CommandLineInterface cli;
|
||||
//
|
||||
// // Support generation of C++ source and headers.
|
||||
// google::protobuf::compiler::cpp::CppGenerator cpp_generator;
|
||||
// cli.RegisterGenerator("--cpp_out", &cpp_generator,
|
||||
// "Generate C++ source and header.");
|
||||
//
|
||||
// // Support generation of Foo code.
|
||||
// FooGenerator foo_generator;
|
||||
// cli.RegisterGenerator("--foo_out", &foo_generator,
|
||||
// "Generate Foo file.");
|
||||
//
|
||||
// return cli.Run(argc, argv);
|
||||
// }
|
||||
//
|
||||
// The compiler is invoked with syntax like:
|
||||
// protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto
|
||||
//
|
||||
// The .proto file to compile can be specified on the command line using either
|
||||
// its physical file path, or a virtual path relative to a directory specified
|
||||
// in --proto_path. For example, for src/foo.proto, the following two protoc
|
||||
// invocations work the same way:
|
||||
// 1. protoc --proto_path=src src/foo.proto (physical file path)
|
||||
// 2. protoc --proto_path=src foo.proto (virtual path relative to src)
|
||||
//
|
||||
// If a file path can be interpreted both as a physical file path and as a
|
||||
// relative virtual path, the physical file path takes precedence.
|
||||
//
|
||||
// For a full description of the command-line syntax, invoke it with --help.
|
||||
class PROTOC_EXPORT CommandLineInterface {
|
||||
public:
|
||||
static const char* const kPathSeparator;
|
||||
|
||||
CommandLineInterface();
|
||||
~CommandLineInterface();
|
||||
|
||||
// Register a code generator for a language.
|
||||
//
|
||||
// Parameters:
|
||||
// * flag_name: The command-line flag used to specify an output file of
|
||||
// this type. The name must start with a '-'. If the name is longer
|
||||
// than one letter, it must start with two '-'s.
|
||||
// * generator: The CodeGenerator which will be called to generate files
|
||||
// of this type.
|
||||
// * help_text: Text describing this flag in the --help output.
|
||||
//
|
||||
// Some generators accept extra parameters. You can specify this parameter
|
||||
// on the command-line by placing it before the output directory, separated
|
||||
// by a colon:
|
||||
// protoc --foo_out=enable_bar:outdir
|
||||
// The text before the colon is passed to CodeGenerator::Generate() as the
|
||||
// "parameter".
|
||||
void RegisterGenerator(const std::string& flag_name, CodeGenerator* generator,
|
||||
const std::string& help_text);
|
||||
|
||||
// Register a code generator for a language.
|
||||
// Besides flag_name you can specify another option_flag_name that could be
|
||||
// used to pass extra parameters to the registered code generator.
|
||||
// Suppose you have registered a generator by calling:
|
||||
// command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
|
||||
// Then you could invoke the compiler with a command like:
|
||||
// protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
|
||||
// This will pass "enable_bar,enable_baz" as the parameter to the generator.
|
||||
void RegisterGenerator(const std::string& flag_name,
|
||||
const std::string& option_flag_name,
|
||||
CodeGenerator* generator,
|
||||
const std::string& help_text);
|
||||
|
||||
// Enables "plugins". In this mode, if a command-line flag ends with "_out"
|
||||
// but does not match any registered generator, the compiler will attempt to
|
||||
// find a "plugin" to implement the generator. Plugins are just executables.
|
||||
// They should live somewhere in the PATH.
|
||||
//
|
||||
// The compiler determines the executable name to search for by concatenating
|
||||
// exe_name_prefix with the unrecognized flag name, removing "_out". So, for
|
||||
// example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out,
|
||||
// the compiler will try to run the program "protoc-gen-foo".
|
||||
//
|
||||
// The plugin program should implement the following usage:
|
||||
// plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
|
||||
// --out indicates the output directory (as passed to the --foo_out
|
||||
// parameter); if omitted, the current directory should be used. --parameter
|
||||
// gives the generator parameter, if any was provided (see below). The
|
||||
// PROTO_FILES list the .proto files which were given on the compiler
|
||||
// command-line; these are the files for which the plugin is expected to
|
||||
// generate output code. Finally, DESCRIPTORS is an encoded FileDescriptorSet
|
||||
// (as defined in descriptor.proto). This is piped to the plugin's stdin.
|
||||
// The set will include descriptors for all the files listed in PROTO_FILES as
|
||||
// well as all files that they import. The plugin MUST NOT attempt to read
|
||||
// the PROTO_FILES directly -- it must use the FileDescriptorSet.
|
||||
//
|
||||
// The plugin should generate whatever files are necessary, as code generators
|
||||
// normally do. It should write the names of all files it generates to
|
||||
// stdout. The names should be relative to the output directory, NOT absolute
|
||||
// names or relative to the current directory. If any errors occur, error
|
||||
// messages should be written to stderr. If an error is fatal, the plugin
|
||||
// should exit with a non-zero exit code.
|
||||
//
|
||||
// Plugins can have generator parameters similar to normal built-in
|
||||
// generators. Extra generator parameters can be passed in via a matching
|
||||
// "_opt" parameter. For example:
|
||||
// protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz
|
||||
// This will pass "enable_bar,enable_baz" as the parameter to the plugin.
|
||||
//
|
||||
void AllowPlugins(const std::string& exe_name_prefix);
|
||||
|
||||
// Run the Protocol Compiler with the given command-line parameters.
|
||||
// Returns the error code which should be returned by main().
|
||||
//
|
||||
// It may not be safe to call Run() in a multi-threaded environment because
|
||||
// it calls strerror(). I'm not sure why you'd want to do this anyway.
|
||||
int Run(int argc, const char* const argv[]);
|
||||
|
||||
// DEPRECATED. Calling this method has no effect. Protocol compiler now
|
||||
// always try to find the .proto file relative to the current directory
|
||||
// first and if the file is not found, it will then treat the input path
|
||||
// as a virtual path.
|
||||
void SetInputsAreProtoPathRelative(bool /* enable */) {}
|
||||
|
||||
// Provides some text which will be printed when the --version flag is
|
||||
// used. The version of libprotoc will also be printed on the next line
|
||||
// after this text.
|
||||
void SetVersionInfo(const std::string& text) { version_info_ = text; }
|
||||
|
||||
|
||||
private:
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
class ErrorPrinter;
|
||||
class GeneratorContextImpl;
|
||||
class MemoryOutputStream;
|
||||
typedef std::unordered_map<std::string, std::unique_ptr<GeneratorContextImpl>>
|
||||
GeneratorContextMap;
|
||||
|
||||
// Clear state from previous Run().
|
||||
void Clear();
|
||||
|
||||
// Remaps the proto file so that it is relative to one of the directories
|
||||
// in proto_path_. Returns false if an error occurred.
|
||||
bool MakeProtoProtoPathRelative(DiskSourceTree* source_tree,
|
||||
std::string* proto,
|
||||
DescriptorDatabase* fallback_database);
|
||||
|
||||
// Remaps each file in input_files_ so that it is relative to one of the
|
||||
// directories in proto_path_. Returns false if an error occurred.
|
||||
bool MakeInputsBeProtoPathRelative(DiskSourceTree* source_tree,
|
||||
DescriptorDatabase* fallback_database);
|
||||
|
||||
// Is this .proto file whitelisted, or do we have a command-line flag allowing
|
||||
// us to use proto3 optional? This is a temporary control to avoid people from
|
||||
// using proto3 optional until code generators have implemented it.
|
||||
bool AllowProto3Optional(const FileDescriptor& file) const;
|
||||
|
||||
// Fails if these files use proto3 optional and the code generator doesn't
|
||||
// support it. This is a permanent check.
|
||||
bool EnforceProto3OptionalSupport(
|
||||
const std::string& codegen_name, uint64 supported_features,
|
||||
const std::vector<const FileDescriptor*>& parsed_files) const;
|
||||
|
||||
|
||||
// Return status for ParseArguments() and InterpretArgument().
|
||||
enum ParseArgumentStatus {
|
||||
PARSE_ARGUMENT_DONE_AND_CONTINUE,
|
||||
PARSE_ARGUMENT_DONE_AND_EXIT,
|
||||
PARSE_ARGUMENT_FAIL
|
||||
};
|
||||
|
||||
// Parse all command-line arguments.
|
||||
ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
|
||||
|
||||
// Read an argument file and append the file's content to the list of
|
||||
// arguments. Return false if the file cannot be read.
|
||||
bool ExpandArgumentFile(const std::string& file,
|
||||
std::vector<std::string>* arguments);
|
||||
|
||||
// Parses a command-line argument into a name/value pair. Returns
|
||||
// true if the next argument in the argv should be used as the value,
|
||||
// false otherwise.
|
||||
//
|
||||
// Examples:
|
||||
// "-Isrc/protos" ->
|
||||
// name = "-I", value = "src/protos"
|
||||
// "--cpp_out=src/foo.pb2.cc" ->
|
||||
// name = "--cpp_out", value = "src/foo.pb2.cc"
|
||||
// "foo.proto" ->
|
||||
// name = "", value = "foo.proto"
|
||||
bool ParseArgument(const char* arg, std::string* name, std::string* value);
|
||||
|
||||
// Interprets arguments parsed with ParseArgument.
|
||||
ParseArgumentStatus InterpretArgument(const std::string& name,
|
||||
const std::string& value);
|
||||
|
||||
// Print the --help text to stderr.
|
||||
void PrintHelpText();
|
||||
|
||||
// Loads proto_path_ into the provided source_tree.
|
||||
bool InitializeDiskSourceTree(DiskSourceTree* source_tree,
|
||||
DescriptorDatabase* fallback_database);
|
||||
|
||||
// Verify that all the input files exist in the given database.
|
||||
bool VerifyInputFilesInDescriptors(DescriptorDatabase* fallback_database);
|
||||
|
||||
// Parses input_files_ into parsed_files
|
||||
bool ParseInputFiles(DescriptorPool* descriptor_pool,
|
||||
DiskSourceTree* source_tree,
|
||||
std::vector<const FileDescriptor*>* parsed_files);
|
||||
|
||||
// Generate the given output file from the given input.
|
||||
struct OutputDirective; // see below
|
||||
bool GenerateOutput(const std::vector<const FileDescriptor*>& parsed_files,
|
||||
const OutputDirective& output_directive,
|
||||
GeneratorContext* generator_context);
|
||||
bool GeneratePluginOutput(
|
||||
const std::vector<const FileDescriptor*>& parsed_files,
|
||||
const std::string& plugin_name, const std::string& parameter,
|
||||
GeneratorContext* generator_context, std::string* error);
|
||||
|
||||
// Implements --encode and --decode.
|
||||
bool EncodeOrDecode(const DescriptorPool* pool);
|
||||
|
||||
// Implements the --descriptor_set_out option.
|
||||
bool WriteDescriptorSet(
|
||||
const std::vector<const FileDescriptor*>& parsed_files);
|
||||
|
||||
// Implements the --dependency_out option
|
||||
bool GenerateDependencyManifestFile(
|
||||
const std::vector<const FileDescriptor*>& parsed_files,
|
||||
const GeneratorContextMap& output_directories,
|
||||
DiskSourceTree* source_tree);
|
||||
|
||||
// Get all transitive dependencies of the given file (including the file
|
||||
// itself), adding them to the given list of FileDescriptorProtos. The
|
||||
// protos will be ordered such that every file is listed before any file that
|
||||
// depends on it, so that you can call DescriptorPool::BuildFile() on them
|
||||
// in order. Any files in *already_seen will not be added, and each file
|
||||
// added will be inserted into *already_seen. If include_source_code_info is
|
||||
// true then include the source code information in the FileDescriptorProtos.
|
||||
// If include_json_name is true, populate the json_name field of
|
||||
// FieldDescriptorProto for all fields.
|
||||
static void GetTransitiveDependencies(
|
||||
const FileDescriptor* file, bool include_json_name,
|
||||
bool include_source_code_info,
|
||||
std::set<const FileDescriptor*>* already_seen,
|
||||
RepeatedPtrField<FileDescriptorProto>* output);
|
||||
|
||||
// Implements the --print_free_field_numbers. This function prints free field
|
||||
// numbers into stdout for the message and it's nested message types in
|
||||
// post-order, i.e. nested types first. Printed range are left-right
|
||||
// inclusive, i.e. [a, b].
|
||||
//
|
||||
// Groups:
|
||||
// For historical reasons, groups are considered to share the same
|
||||
// field number space with the parent message, thus it will not print free
|
||||
// field numbers for groups. The field numbers used in the groups are
|
||||
// excluded in the free field numbers of the parent message.
|
||||
//
|
||||
// Extension Ranges:
|
||||
// Extension ranges are considered ocuppied field numbers and they will not be
|
||||
// listed as free numbers in the output.
|
||||
void PrintFreeFieldNumbers(const Descriptor* descriptor);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// The name of the executable as invoked (i.e. argv[0]).
|
||||
std::string executable_name_;
|
||||
|
||||
// Version info set with SetVersionInfo().
|
||||
std::string version_info_;
|
||||
|
||||
// Registered generators.
|
||||
struct GeneratorInfo {
|
||||
std::string flag_name;
|
||||
std::string option_flag_name;
|
||||
CodeGenerator* generator;
|
||||
std::string help_text;
|
||||
};
|
||||
typedef std::map<std::string, GeneratorInfo> GeneratorMap;
|
||||
GeneratorMap generators_by_flag_name_;
|
||||
GeneratorMap generators_by_option_name_;
|
||||
// A map from generator names to the parameters specified using the option
|
||||
// flag. For example, if the user invokes the compiler with:
|
||||
// protoc --foo_out=outputdir --foo_opt=enable_bar ...
|
||||
// Then there will be an entry ("--foo_out", "enable_bar") in this map.
|
||||
std::map<std::string, std::string> generator_parameters_;
|
||||
// Similar to generator_parameters_, but stores the parameters for plugins.
|
||||
std::map<std::string, std::string> plugin_parameters_;
|
||||
|
||||
// See AllowPlugins(). If this is empty, plugins aren't allowed.
|
||||
std::string plugin_prefix_;
|
||||
|
||||
// Maps specific plugin names to files. When executing a plugin, this map
|
||||
// is searched first to find the plugin executable. If not found here, the
|
||||
// PATH (or other OS-specific search strategy) is searched.
|
||||
std::map<std::string, std::string> plugins_;
|
||||
|
||||
// Stuff parsed from command line.
|
||||
enum Mode {
|
||||
MODE_COMPILE, // Normal mode: parse .proto files and compile them.
|
||||
MODE_ENCODE, // --encode: read text from stdin, write binary to stdout.
|
||||
MODE_DECODE, // --decode: read binary from stdin, write text to stdout.
|
||||
MODE_PRINT, // Print mode: print info of the given .proto files and exit.
|
||||
};
|
||||
|
||||
Mode mode_ = MODE_COMPILE;
|
||||
|
||||
enum PrintMode {
|
||||
PRINT_NONE, // Not in MODE_PRINT
|
||||
PRINT_FREE_FIELDS, // --print_free_fields
|
||||
};
|
||||
|
||||
PrintMode print_mode_ = PRINT_NONE;
|
||||
|
||||
enum ErrorFormat {
|
||||
ERROR_FORMAT_GCC, // GCC error output format (default).
|
||||
ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs).
|
||||
};
|
||||
|
||||
ErrorFormat error_format_ = ERROR_FORMAT_GCC;
|
||||
|
||||
std::vector<std::pair<std::string, std::string> >
|
||||
proto_path_; // Search path for proto files.
|
||||
std::vector<std::string> input_files_; // Names of the input proto files.
|
||||
|
||||
// Names of proto files which are allowed to be imported. Used by build
|
||||
// systems to enforce depend-on-what-you-import.
|
||||
std::set<std::string> direct_dependencies_;
|
||||
bool direct_dependencies_explicitly_set_ = false;
|
||||
|
||||
// If there's a violation of depend-on-what-you-import, this string will be
|
||||
// presented to the user. "%s" will be replaced with the violating import.
|
||||
std::string direct_dependencies_violation_msg_;
|
||||
|
||||
// output_directives_ lists all the files we are supposed to output and what
|
||||
// generator to use for each.
|
||||
struct OutputDirective {
|
||||
std::string name; // E.g. "--foo_out"
|
||||
CodeGenerator* generator; // NULL for plugins
|
||||
std::string parameter;
|
||||
std::string output_location;
|
||||
};
|
||||
std::vector<OutputDirective> output_directives_;
|
||||
|
||||
// When using --encode or --decode, this names the type we are encoding or
|
||||
// decoding. (Empty string indicates --decode_raw.)
|
||||
std::string codec_type_;
|
||||
|
||||
// If --descriptor_set_in was given, these are filenames containing
|
||||
// parsed FileDescriptorSets to be used for loading protos. Otherwise, empty.
|
||||
std::vector<std::string> descriptor_set_in_names_;
|
||||
|
||||
// If --descriptor_set_out was given, this is the filename to which the
|
||||
// FileDescriptorSet should be written. Otherwise, empty.
|
||||
std::string descriptor_set_out_name_;
|
||||
|
||||
// If --dependency_out was given, this is the path to the file where the
|
||||
// dependency file will be written. Otherwise, empty.
|
||||
std::string dependency_out_name_;
|
||||
|
||||
// True if --include_imports was given, meaning that we should
|
||||
// write all transitive dependencies to the DescriptorSet. Otherwise, only
|
||||
// the .proto files listed on the command-line are added.
|
||||
bool imports_in_descriptor_set_;
|
||||
|
||||
// True if --include_source_info was given, meaning that we should not strip
|
||||
// SourceCodeInfo from the DescriptorSet.
|
||||
bool source_info_in_descriptor_set_ = false;
|
||||
|
||||
// Was the --disallow_services flag used?
|
||||
bool disallow_services_ = false;
|
||||
|
||||
// Was the --experimental_allow_proto3_optional flag used?
|
||||
bool allow_proto3_optional_ = false;
|
||||
|
||||
// When using --encode, this will be passed to SetSerializationDeterministic.
|
||||
bool deterministic_output_ = false;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include <google/protobuf/port_undef.inc>
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
|
||||
2772
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/command_line_interface_unittest.cc
vendored
Normal file
2772
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/command_line_interface_unittest.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
199
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
vendored
Normal file
199
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This test insures that net/proto2/proto/descriptor.pb.{h,cc} match exactly
|
||||
// what would be generated by the protocol compiler. These files are not
|
||||
// generated automatically at build time because they are compiled into the
|
||||
// protocol compiler itself. So, if they were auto-generated, you'd have a
|
||||
// chicken-and-egg problem.
|
||||
//
|
||||
// If this test fails, run the script
|
||||
// "generate_descriptor_proto.sh" and add
|
||||
// descriptor.pb.{h,cc} to your changelist.
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_generator.h>
|
||||
#include <google/protobuf/compiler/importer.h>
|
||||
#include <google/protobuf/test_util2.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
#include <google/protobuf/stubs/map_util.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
class MockErrorCollector : public MultiFileErrorCollector {
|
||||
public:
|
||||
MockErrorCollector() {}
|
||||
~MockErrorCollector() {}
|
||||
|
||||
std::string text_;
|
||||
|
||||
// implements ErrorCollector ---------------------------------------
|
||||
void AddError(const std::string& filename, int line, int column,
|
||||
const std::string& message) {
|
||||
strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
|
||||
message);
|
||||
}
|
||||
};
|
||||
|
||||
class MockGeneratorContext : public GeneratorContext {
|
||||
public:
|
||||
void ExpectFileMatches(const std::string& virtual_filename,
|
||||
const std::string& physical_filename) {
|
||||
auto it = files_.find(virtual_filename);
|
||||
ASSERT_TRUE(it != files_.end())
|
||||
<< "Generator failed to generate file: " << virtual_filename;
|
||||
|
||||
std::string expected_contents = *it->second;
|
||||
std::string actual_contents;
|
||||
GOOGLE_CHECK_OK(
|
||||
File::GetContents(TestUtil::TestSourceDir() + "/" + physical_filename,
|
||||
&actual_contents, true))
|
||||
<< physical_filename;
|
||||
CleanStringLineEndings(&actual_contents, false);
|
||||
|
||||
#ifdef WRITE_FILES // Define to debug mismatched files.
|
||||
GOOGLE_CHECK_OK(File::SetContents("/tmp/expected.cc", expected_contents,
|
||||
true));
|
||||
GOOGLE_CHECK_OK(
|
||||
File::SetContents("/tmp/actual.cc", actual_contents, true));
|
||||
#endif
|
||||
|
||||
ASSERT_EQ(expected_contents, actual_contents)
|
||||
<< physical_filename
|
||||
<< " needs to be regenerated. Please run "
|
||||
"generate_descriptor_proto.sh. "
|
||||
"Then add this file to your CL.";
|
||||
}
|
||||
|
||||
// implements GeneratorContext --------------------------------------
|
||||
|
||||
virtual io::ZeroCopyOutputStream* Open(const std::string& filename) {
|
||||
auto& map_slot = files_[filename];
|
||||
map_slot.reset(new std::string);
|
||||
return new io::StringOutputStream(map_slot.get());
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, std::unique_ptr<std::string>> files_;
|
||||
};
|
||||
|
||||
const char kDescriptorParameter[] = "dllexport_decl=PROTOBUF_EXPORT";
|
||||
const char kPluginParameter[] = "dllexport_decl=PROTOC_EXPORT";
|
||||
|
||||
|
||||
const char* test_protos[][2] = {
|
||||
{"google/protobuf/descriptor", kDescriptorParameter},
|
||||
{"google/protobuf/compiler/plugin", kPluginParameter},
|
||||
};
|
||||
|
||||
TEST(BootstrapTest, GeneratedFilesMatch) {
|
||||
// We need a mapping from the actual file to virtual and actual path
|
||||
// of the data to compare to.
|
||||
std::map<std::string, std::string> vpath_map;
|
||||
std::map<std::string, std::string> rpath_map;
|
||||
rpath_map
|
||||
["third_party/protobuf_legacy_opensource/src/google/protobuf/"
|
||||
"test_messages_proto2"] =
|
||||
"net/proto2/z_generated_example/test_messages_proto2";
|
||||
rpath_map
|
||||
["third_party/protobuf_legacy_opensource/src/google/protobuf/"
|
||||
"test_messages_proto3"] =
|
||||
"net/proto2/z_generated_example/test_messages_proto3";
|
||||
rpath_map["net/proto2/internal/proto2_weak"] =
|
||||
"net/proto2/z_generated_example/proto2_weak";
|
||||
|
||||
DiskSourceTree source_tree;
|
||||
source_tree.MapPath("", TestUtil::TestSourceDir());
|
||||
|
||||
for (auto file_parameter : test_protos) {
|
||||
MockErrorCollector error_collector;
|
||||
Importer importer(&source_tree, &error_collector);
|
||||
const FileDescriptor* file =
|
||||
importer.Import(file_parameter[0] + std::string(".proto"));
|
||||
ASSERT_TRUE(file != nullptr)
|
||||
<< "Can't import file " << file_parameter[0] + std::string(".proto")
|
||||
<< "\n";
|
||||
EXPECT_EQ("", error_collector.text_);
|
||||
CppGenerator generator;
|
||||
MockGeneratorContext context;
|
||||
#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE
|
||||
generator.set_opensource_runtime(true);
|
||||
generator.set_runtime_include_base(GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE);
|
||||
#endif
|
||||
std::string error;
|
||||
ASSERT_TRUE(generator.Generate(file, file_parameter[1], &context, &error));
|
||||
|
||||
std::string vpath =
|
||||
FindWithDefault(vpath_map, file_parameter[0], file_parameter[0]);
|
||||
std::string rpath =
|
||||
FindWithDefault(rpath_map, file_parameter[0], file_parameter[0]);
|
||||
context.ExpectFileMatches(vpath + ".pb.cc", rpath + ".pb.cc");
|
||||
context.ExpectFileMatches(vpath + ".pb.h", rpath + ".pb.h");
|
||||
}
|
||||
}
|
||||
|
||||
// test Generate in cpp_generator.cc
|
||||
TEST(BootstrapTest, OptionNotExist) {
|
||||
cpp::CppGenerator generator;
|
||||
DescriptorPool pool;
|
||||
GeneratorContext* generator_context = nullptr;
|
||||
std::string parameter = "aaa";
|
||||
std::string error;
|
||||
ASSERT_FALSE(generator.Generate(
|
||||
pool.FindFileByName("google/protobuf/descriptor.proto"), parameter,
|
||||
generator_context, &error));
|
||||
EXPECT_EQ(error, "Unknown generator option: " + parameter);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
434
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_enum.cc
vendored
Normal file
434
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_enum.cc
vendored
Normal file
@@ -0,0 +1,434 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
|
||||
// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
|
||||
// generation of the GOOGLE_ARRAYSIZE constant.
|
||||
bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
|
||||
int32 max_value = descriptor->value(0)->number();
|
||||
for (int i = 0; i < descriptor->value_count(); i++) {
|
||||
if (descriptor->value(i)->number() > max_value) {
|
||||
max_value = descriptor->value(i)->number();
|
||||
}
|
||||
}
|
||||
return max_value != kint32max;
|
||||
}
|
||||
|
||||
// Returns the number of unique numeric enum values. This is less than
|
||||
// descriptor->value_count() when there are aliased values.
|
||||
int CountUniqueValues(const EnumDescriptor* descriptor) {
|
||||
std::set<int> values;
|
||||
for (int i = 0; i < descriptor->value_count(); ++i) {
|
||||
values.insert(descriptor->value(i)->number());
|
||||
}
|
||||
return values.size();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
|
||||
const std::map<std::string, std::string>& vars,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor),
|
||||
classname_(ClassName(descriptor, false)),
|
||||
options_(options),
|
||||
generate_array_size_(ShouldGenerateArraySize(descriptor)),
|
||||
variables_(vars) {
|
||||
variables_["classname"] = classname_;
|
||||
variables_["classtype"] = QualifiedClassName(descriptor_, options);
|
||||
variables_["short_name"] = descriptor_->name();
|
||||
variables_["nested_name"] = descriptor_->name();
|
||||
variables_["resolved_name"] = ResolveKeyword(descriptor_->name());
|
||||
variables_["prefix"] =
|
||||
(descriptor_->containing_type() == NULL) ? "" : classname_ + "_";
|
||||
}
|
||||
|
||||
EnumGenerator::~EnumGenerator() {}
|
||||
|
||||
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
Formatter format(printer, variables_);
|
||||
format("enum ${1$$classname$$}$ : int {\n", descriptor_);
|
||||
format.Indent();
|
||||
|
||||
const EnumValueDescriptor* min_value = descriptor_->value(0);
|
||||
const EnumValueDescriptor* max_value = descriptor_->value(0);
|
||||
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
auto format_value = format;
|
||||
format_value.Set("name", EnumValueName(descriptor_->value(i)));
|
||||
// In C++, an value of -2147483648 gets interpreted as the negative of
|
||||
// 2147483648, and since 2147483648 can't fit in an integer, this produces a
|
||||
// compiler warning. This works around that issue.
|
||||
format_value.Set("number", Int32ToString(descriptor_->value(i)->number()));
|
||||
format_value.Set("deprecation",
|
||||
DeprecatedAttribute(options_, descriptor_->value(i)));
|
||||
|
||||
if (i > 0) format_value(",\n");
|
||||
format_value("${1$$prefix$$name$$}$ $deprecation$= $number$",
|
||||
descriptor_->value(i));
|
||||
|
||||
if (descriptor_->value(i)->number() < min_value->number()) {
|
||||
min_value = descriptor_->value(i);
|
||||
}
|
||||
if (descriptor_->value(i)->number() > max_value->number()) {
|
||||
max_value = descriptor_->value(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
|
||||
// For new enum semantics: generate min and max sentinel values equal to
|
||||
// INT32_MIN and INT32_MAX
|
||||
if (descriptor_->value_count() > 0) format(",\n");
|
||||
format(
|
||||
"$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = "
|
||||
"std::numeric_limits<$int32$>::min(),\n"
|
||||
"$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = "
|
||||
"std::numeric_limits<$int32$>::max()");
|
||||
}
|
||||
|
||||
format.Outdent();
|
||||
format("\n};\n");
|
||||
|
||||
format(
|
||||
"$dllexport_decl $bool $classname$_IsValid(int value);\n"
|
||||
"constexpr $classname$ ${1$$prefix$$short_name$_MIN$}$ = "
|
||||
"$prefix$$2$;\n"
|
||||
"constexpr $classname$ ${1$$prefix$$short_name$_MAX$}$ = "
|
||||
"$prefix$$3$;\n",
|
||||
descriptor_, EnumValueName(min_value), EnumValueName(max_value));
|
||||
|
||||
if (generate_array_size_) {
|
||||
format(
|
||||
"constexpr int ${1$$prefix$$short_name$_ARRAYSIZE$}$ = "
|
||||
"$prefix$$short_name$_MAX + 1;\n\n",
|
||||
descriptor_);
|
||||
}
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
format(
|
||||
"$dllexport_decl $const ::$proto_ns$::EnumDescriptor* "
|
||||
"$classname$_descriptor();\n");
|
||||
}
|
||||
|
||||
// The _Name and _Parse functions. The lite implementation is table-based, so
|
||||
// we make sure to keep the tables hidden in the .cc file.
|
||||
if (!HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
format("const std::string& $classname$_Name($classname$ value);\n");
|
||||
}
|
||||
// The _Name() function accepts the enum type itself but also any integral
|
||||
// type.
|
||||
format(
|
||||
"template<typename T>\n"
|
||||
"inline const std::string& $classname$_Name(T enum_t_value) {\n"
|
||||
" static_assert(::std::is_same<T, $classname$>::value ||\n"
|
||||
" ::std::is_integral<T>::value,\n"
|
||||
" \"Incorrect type passed to function $classname$_Name.\");\n");
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
format(
|
||||
" return ::$proto_ns$::internal::NameOfEnum(\n"
|
||||
" $classname$_descriptor(), enum_t_value);\n");
|
||||
} else {
|
||||
format(
|
||||
" return $classname$_Name(static_cast<$classname$>(enum_t_value));\n");
|
||||
}
|
||||
format("}\n");
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
format(
|
||||
"inline bool $classname$_Parse(\n"
|
||||
" ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
|
||||
"value) "
|
||||
"{\n"
|
||||
" return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n"
|
||||
" $classname$_descriptor(), name, value);\n"
|
||||
"}\n");
|
||||
} else {
|
||||
format(
|
||||
"bool $classname$_Parse(\n"
|
||||
" ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
|
||||
"value);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateGetEnumDescriptorSpecializations(
|
||||
io::Printer* printer) {
|
||||
Formatter format(printer, variables_);
|
||||
format(
|
||||
"template <> struct is_proto_enum< $classtype$> : ::std::true_type "
|
||||
"{};\n");
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
format(
|
||||
"template <>\n"
|
||||
"inline const EnumDescriptor* GetEnumDescriptor< $classtype$>() {\n"
|
||||
" return $classtype$_descriptor();\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateSymbolImports(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("typedef $classname$ $resolved_name$;\n");
|
||||
|
||||
for (int j = 0; j < descriptor_->value_count(); j++) {
|
||||
std::string deprecated_attr =
|
||||
DeprecatedAttribute(options_, descriptor_->value(j));
|
||||
format(
|
||||
"$1$static constexpr $resolved_name$ ${2$$3$$}$ =\n"
|
||||
" $classname$_$3$;\n",
|
||||
deprecated_attr, descriptor_->value(j),
|
||||
EnumValueName(descriptor_->value(j)));
|
||||
}
|
||||
|
||||
format(
|
||||
"static inline bool $nested_name$_IsValid(int value) {\n"
|
||||
" return $classname$_IsValid(value);\n"
|
||||
"}\n"
|
||||
"static constexpr $resolved_name$ ${1$$nested_name$_MIN$}$ =\n"
|
||||
" $classname$_$nested_name$_MIN;\n"
|
||||
"static constexpr $resolved_name$ ${1$$nested_name$_MAX$}$ =\n"
|
||||
" $classname$_$nested_name$_MAX;\n",
|
||||
descriptor_);
|
||||
if (generate_array_size_) {
|
||||
format(
|
||||
"static constexpr int ${1$$nested_name$_ARRAYSIZE$}$ =\n"
|
||||
" $classname$_$nested_name$_ARRAYSIZE;\n",
|
||||
descriptor_);
|
||||
}
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
format(
|
||||
"static inline const ::$proto_ns$::EnumDescriptor*\n"
|
||||
"$nested_name$_descriptor() {\n"
|
||||
" return $classname$_descriptor();\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
format(
|
||||
"template<typename T>\n"
|
||||
"static inline const std::string& $nested_name$_Name(T enum_t_value) {\n"
|
||||
" static_assert(::std::is_same<T, $resolved_name$>::value ||\n"
|
||||
" ::std::is_integral<T>::value,\n"
|
||||
" \"Incorrect type passed to function $nested_name$_Name.\");\n"
|
||||
" return $classname$_Name(enum_t_value);\n"
|
||||
"}\n");
|
||||
format(
|
||||
"static inline bool "
|
||||
"$nested_name$_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,\n"
|
||||
" $resolved_name$* value) {\n"
|
||||
" return $classname$_Parse(name, value);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
|
||||
Formatter format(printer, variables_);
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
format(
|
||||
"const ::$proto_ns$::EnumDescriptor* $classname$_descriptor() {\n"
|
||||
" ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
|
||||
" return $file_level_enum_descriptors$[$1$];\n"
|
||||
"}\n",
|
||||
idx);
|
||||
}
|
||||
|
||||
format(
|
||||
"bool $classname$_IsValid(int value) {\n"
|
||||
" switch (value) {\n");
|
||||
|
||||
// Multiple values may have the same number. Make sure we only cover
|
||||
// each number once by first constructing a set containing all valid
|
||||
// numbers, then printing a case statement for each element.
|
||||
|
||||
std::set<int> numbers;
|
||||
for (int j = 0; j < descriptor_->value_count(); j++) {
|
||||
const EnumValueDescriptor* value = descriptor_->value(j);
|
||||
numbers.insert(value->number());
|
||||
}
|
||||
|
||||
for (std::set<int>::iterator iter = numbers.begin(); iter != numbers.end();
|
||||
++iter) {
|
||||
format(" case $1$:\n", Int32ToString(*iter));
|
||||
}
|
||||
|
||||
format(
|
||||
" return true;\n"
|
||||
" default:\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
if (!HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
// In lite mode (where descriptors are unavailable), we generate separate
|
||||
// tables for mapping between enum names and numbers. The _entries table
|
||||
// contains the bulk of the data and is sorted by name, while
|
||||
// _entries_by_number is sorted by number and just contains pointers into
|
||||
// _entries. The two tables allow mapping from name to number and number to
|
||||
// name, both in time logarithmic in the number of enum entries. This could
|
||||
// probably be made faster, but for now the tables are intended to be simple
|
||||
// and compact.
|
||||
//
|
||||
// Enums with allow_alias = true support multiple entries with the same
|
||||
// numerical value. In cases where there are multiple names for the same
|
||||
// number, we treat the first name appearing in the .proto file as the
|
||||
// canonical one.
|
||||
std::map<std::string, int> name_to_number;
|
||||
std::map<int, std::string> number_to_canonical_name;
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
const EnumValueDescriptor* value = descriptor_->value(i);
|
||||
name_to_number.emplace(value->name(), value->number());
|
||||
// The same number may appear with multiple names, so we use emplace() to
|
||||
// let the first name win.
|
||||
number_to_canonical_name.emplace(value->number(), value->name());
|
||||
}
|
||||
|
||||
format(
|
||||
"static ::$proto_ns$::internal::ExplicitlyConstructed<std::string> "
|
||||
"$classname$_strings[$1$] = {};\n\n",
|
||||
CountUniqueValues(descriptor_));
|
||||
|
||||
// We concatenate all the names for a given enum into one big string
|
||||
// literal. If instead we store an array of string literals, the linker
|
||||
// seems to put all enum strings for a given .proto file in the same
|
||||
// section, which hinders its ability to strip out unused strings.
|
||||
format("static const char $classname$_names[] =");
|
||||
for (const auto& p : name_to_number) {
|
||||
format("\n \"$1$\"", p.first);
|
||||
}
|
||||
format(";\n\n");
|
||||
|
||||
format(
|
||||
"static const ::$proto_ns$::internal::EnumEntry $classname$_entries[] "
|
||||
"= {\n");
|
||||
int i = 0;
|
||||
std::map<int, int> number_to_index;
|
||||
int data_index = 0;
|
||||
for (const auto& p : name_to_number) {
|
||||
format(" { {$classname$_names + $1$, $2$}, $3$ },\n", data_index,
|
||||
p.first.size(), p.second);
|
||||
if (number_to_canonical_name[p.second] == p.first) {
|
||||
number_to_index.emplace(p.second, i);
|
||||
}
|
||||
++i;
|
||||
data_index += p.first.size();
|
||||
}
|
||||
|
||||
format(
|
||||
"};\n"
|
||||
"\n"
|
||||
"static const int $classname$_entries_by_number[] = {\n");
|
||||
for (const auto& p : number_to_index) {
|
||||
format(" $1$, // $2$ -> $3$\n", p.second, p.first,
|
||||
number_to_canonical_name[p.first]);
|
||||
}
|
||||
format(
|
||||
"};\n"
|
||||
"\n");
|
||||
|
||||
format(
|
||||
"const std::string& $classname$_Name(\n"
|
||||
" $classname$ value) {\n"
|
||||
" static const bool dummy =\n"
|
||||
" ::$proto_ns$::internal::InitializeEnumStrings(\n"
|
||||
" $classname$_entries,\n"
|
||||
" $classname$_entries_by_number,\n"
|
||||
" $1$, $classname$_strings);\n"
|
||||
" (void) dummy;\n"
|
||||
" int idx = ::$proto_ns$::internal::LookUpEnumName(\n"
|
||||
" $classname$_entries,\n"
|
||||
" $classname$_entries_by_number,\n"
|
||||
" $1$, value);\n"
|
||||
" return idx == -1 ? ::$proto_ns$::internal::GetEmptyString() :\n"
|
||||
" $classname$_strings[idx].get();\n"
|
||||
"}\n",
|
||||
CountUniqueValues(descriptor_));
|
||||
format(
|
||||
"bool $classname$_Parse(\n"
|
||||
" ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
|
||||
"value) "
|
||||
"{\n"
|
||||
" int int_value;\n"
|
||||
" bool success = ::$proto_ns$::internal::LookUpEnumValue(\n"
|
||||
" $classname$_entries, $1$, name, &int_value);\n"
|
||||
" if (success) {\n"
|
||||
" *value = static_cast<$classname$>(int_value);\n"
|
||||
" }\n"
|
||||
" return success;\n"
|
||||
"}\n",
|
||||
descriptor_->value_count());
|
||||
}
|
||||
|
||||
if (descriptor_->containing_type() != NULL) {
|
||||
std::string parent = ClassName(descriptor_->containing_type(), false);
|
||||
// Before C++17, we must define the static constants which were
|
||||
// declared in the header, to give the linker a place to put them.
|
||||
// But pre-2015 MSVC++ insists that we not.
|
||||
format(
|
||||
"#if (__cplusplus < 201703) && "
|
||||
"(!defined(_MSC_VER) || _MSC_VER >= 1900)\n");
|
||||
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
format("constexpr $classname$ $1$::$2$;\n", parent,
|
||||
EnumValueName(descriptor_->value(i)));
|
||||
}
|
||||
format(
|
||||
"constexpr $classname$ $1$::$nested_name$_MIN;\n"
|
||||
"constexpr $classname$ $1$::$nested_name$_MAX;\n",
|
||||
parent);
|
||||
if (generate_array_size_) {
|
||||
format("constexpr int $1$::$nested_name$_ARRAYSIZE;\n", parent);
|
||||
}
|
||||
|
||||
format(
|
||||
"#endif // (__cplusplus < 201703) && "
|
||||
"(!defined(_MSC_VER) || _MSC_VER >= 1900)\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
105
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_enum.h
vendored
Normal file
105
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_enum.h
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class EnumGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
EnumGenerator(const EnumDescriptor* descriptor,
|
||||
const std::map<std::string, std::string>& vars,
|
||||
const Options& options);
|
||||
~EnumGenerator();
|
||||
|
||||
// Generate header code defining the enum. This code should be placed
|
||||
// within the enum's package namespace, but NOT within any class, even for
|
||||
// nested enums.
|
||||
void GenerateDefinition(io::Printer* printer);
|
||||
|
||||
// Generate specialization of GetEnumDescriptor<MyEnum>().
|
||||
// Precondition: in ::google::protobuf namespace.
|
||||
void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
|
||||
|
||||
// For enums nested within a message, generate code to import all the enum's
|
||||
// symbols (e.g. the enum type name, all its values, etc.) into the class's
|
||||
// namespace. This should be placed inside the class definition in the
|
||||
// header.
|
||||
void GenerateSymbolImports(io::Printer* printer) const;
|
||||
|
||||
// Source file stuff.
|
||||
|
||||
// Generate non-inline methods related to the enum, such as IsValidValue().
|
||||
// Goes in the .cc file. EnumDescriptors are stored in an array, idx is
|
||||
// the index in this array that corresponds with this enum.
|
||||
void GenerateMethods(int idx, io::Printer* printer);
|
||||
|
||||
private:
|
||||
const EnumDescriptor* descriptor_;
|
||||
const std::string classname_;
|
||||
const Options& options_;
|
||||
// whether to generate the *_ARRAYSIZE constant.
|
||||
const bool generate_array_size_;
|
||||
|
||||
std::map<std::string, std::string> variables_;
|
||||
|
||||
friend class FileGenerator;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
||||
490
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_enum_field.cc
vendored
Normal file
490
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_enum_field.cc
vendored
Normal file
@@ -0,0 +1,490 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||
std::map<std::string, std::string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
|
||||
(*variables)["type"] = QualifiedClassName(descriptor->enum_type(), options);
|
||||
(*variables)["default"] = Int32ToString(default_value->number());
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: FieldGenerator(descriptor, options) {
|
||||
SetEnumVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
EnumFieldGenerator::~EnumFieldGenerator() {}
|
||||
|
||||
void EnumFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("int $name$_;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateAccessorDeclarations(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format(
|
||||
"$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
|
||||
"$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
|
||||
"private:\n"
|
||||
"$type$ ${1$_internal_$name$$}$() const;\n"
|
||||
"void ${1$_internal_set_$name$$}$($type$ value);\n"
|
||||
"public:\n",
|
||||
descriptor_);
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateInlineAccessorDefinitions(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format(
|
||||
"inline $type$ $classname$::_internal_$name$() const {\n"
|
||||
" return static_cast< $type$ >($name$_);\n"
|
||||
"}\n"
|
||||
"inline $type$ $classname$::$name$() const {\n"
|
||||
"$annotate_accessor$"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return _internal_$name$();\n"
|
||||
"}\n"
|
||||
"inline void $classname$::_internal_set_$name$($type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
|
||||
format(" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
format(
|
||||
" $set_hasbit$\n"
|
||||
" $name$_ = value;\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$($type$ value) {\n"
|
||||
"$annotate_accessor$"
|
||||
" _internal_set_$name$(value);\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("_internal_set_$name$(from._internal_$name$());\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("swap($name$_, other->$name$_);\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateCopyConstructorCode(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("$name$_ = from.$name$_;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format(
|
||||
"target = stream->EnsureSpace(target);\n"
|
||||
"target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
|
||||
" $number$, this->_internal_$name$(), target);\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format(
|
||||
"total_size += $tag_size$ +\n"
|
||||
" "
|
||||
"::$proto_ns$::internal::WireFormatLite::EnumSize(this->_internal_$name$("
|
||||
"));\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
EnumOneofFieldGenerator::EnumOneofFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options)
|
||||
: EnumFieldGenerator(descriptor, options) {
|
||||
SetCommonOneofFieldVariables(descriptor, &variables_);
|
||||
}
|
||||
|
||||
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format(
|
||||
"inline $type$ $classname$::_internal_$name$() const {\n"
|
||||
" if (_internal_has_$name$()) {\n"
|
||||
" return static_cast< $type$ >($field_member$);\n"
|
||||
" }\n"
|
||||
" return static_cast< $type$ >($default$);\n"
|
||||
"}\n"
|
||||
"inline $type$ $classname$::$name$() const {\n"
|
||||
"$annotate_accessor$"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return _internal_$name$();\n"
|
||||
"}\n"
|
||||
"inline void $classname$::_internal_set_$name$($type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
|
||||
format(" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
format(
|
||||
" if (!_internal_has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" }\n"
|
||||
" $field_member$ = value;\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$($type$ value) {\n"
|
||||
"$annotate_accessor$"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
" _internal_set_$name$(value);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("$field_member$ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
|
||||
// Don't print any swapping code. Swapping the union will swap this field.
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateConstructorCode(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options)
|
||||
: FieldGenerator(descriptor, options) {
|
||||
SetEnumVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GeneratePrivateMembers(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("::$proto_ns$::RepeatedField<int> $name$_;\n");
|
||||
if (descriptor_->is_packed() &&
|
||||
HasGeneratedMethods(descriptor_->file(), options_)) {
|
||||
format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format(
|
||||
"private:\n"
|
||||
"$type$ ${1$_internal_$name$$}$(int index) const;\n"
|
||||
"void ${1$_internal_add_$name$$}$($type$ value);\n"
|
||||
"::$proto_ns$::RepeatedField<int>* "
|
||||
"${1$_internal_mutable_$name$$}$();\n"
|
||||
"public:\n"
|
||||
"$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
|
||||
"$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
|
||||
"$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
|
||||
"$deprecated_attr$const ::$proto_ns$::RepeatedField<int>& "
|
||||
"${1$$name$$}$() const;\n"
|
||||
"$deprecated_attr$::$proto_ns$::RepeatedField<int>* "
|
||||
"${1$mutable_$name$$}$();\n",
|
||||
descriptor_);
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format(
|
||||
"inline $type$ $classname$::_internal_$name$(int index) const {\n"
|
||||
" return static_cast< $type$ >($name$_.Get(index));\n"
|
||||
"}\n"
|
||||
"inline $type$ $classname$::$name$(int index) const {\n"
|
||||
"$annotate_accessor$"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return _internal_$name$(index);\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
|
||||
"$annotate_accessor$");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
|
||||
format(" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
format(
|
||||
" $name$_.Set(index, value);\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n"
|
||||
"inline void $classname$::_internal_add_$name$($type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
|
||||
format(" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
format(
|
||||
" $name$_.Add(value);\n"
|
||||
"}\n"
|
||||
"inline void $classname$::add_$name$($type$ value) {\n"
|
||||
"$annotate_accessor$"
|
||||
" // @@protoc_insertion_point(field_add:$full_name$)\n"
|
||||
" _internal_add_$name$(value);\n"
|
||||
"}\n"
|
||||
"inline const ::$proto_ns$::RepeatedField<int>&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
"$annotate_accessor$"
|
||||
" // @@protoc_insertion_point(field_list:$full_name$)\n"
|
||||
" return $name$_;\n"
|
||||
"}\n"
|
||||
"inline ::$proto_ns$::RepeatedField<int>*\n"
|
||||
"$classname$::_internal_mutable_$name$() {\n"
|
||||
" return &$name$_;\n"
|
||||
"}\n"
|
||||
"inline ::$proto_ns$::RepeatedField<int>*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
"$annotate_accessor$"
|
||||
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
|
||||
" return _internal_mutable_$name$();\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateClearingCode(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("$name$_.Clear();\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateMergingCode(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateSwappingCode(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format("$name$_.InternalSwap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateConstructorCode(
|
||||
io::Printer* printer) const {
|
||||
// Not needed for repeated fields.
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStream(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
// Don't use ReadRepeatedPrimitive here so that the enum can be validated.
|
||||
format(
|
||||
"int value = 0;\n"
|
||||
"DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||
" input, &value)));\n");
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_)) {
|
||||
format("add_$name$(static_cast< $type$ >(value));\n");
|
||||
} else {
|
||||
format(
|
||||
"if ($type$_IsValid(value)) {\n"
|
||||
" add_$name$(static_cast< $type$ >(value));\n");
|
||||
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
format(
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint(\n"
|
||||
" $number$, static_cast<$uint64$>(value));\n");
|
||||
} else {
|
||||
format(
|
||||
"} else {\n"
|
||||
" unknown_fields_stream.WriteVarint32(tag);\n"
|
||||
" unknown_fields_stream.WriteVarint32(\n"
|
||||
" static_cast<$uint32$>(value));\n");
|
||||
}
|
||||
format("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStreamWithPacking(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
if (!descriptor_->is_packed()) {
|
||||
// This path is rarely executed, so we use a non-inlined implementation.
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_)) {
|
||||
format(
|
||||
"DO_((::$proto_ns$::internal::"
|
||||
"WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
|
||||
" input,\n"
|
||||
" $number$,\n"
|
||||
" nullptr,\n"
|
||||
" nullptr,\n"
|
||||
" this->_internal_mutable_$name$())));\n");
|
||||
} else if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
format(
|
||||
"DO_((::$proto_ns$::internal::WireFormat::"
|
||||
"ReadPackedEnumPreserveUnknowns(\n"
|
||||
" input,\n"
|
||||
" $number$,\n"
|
||||
" $type$_IsValid,\n"
|
||||
" mutable_unknown_fields(),\n"
|
||||
" this->_internal_mutable_$name$())));\n");
|
||||
} else {
|
||||
format(
|
||||
"DO_((::$proto_ns$::internal::"
|
||||
"WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
|
||||
" input,\n"
|
||||
" $number$,\n"
|
||||
" $type$_IsValid,\n"
|
||||
" &unknown_fields_stream,\n"
|
||||
" this->_internal_mutable_$name$())));\n");
|
||||
}
|
||||
} else {
|
||||
format(
|
||||
"$uint32$ length;\n"
|
||||
"DO_(input->ReadVarint32(&length));\n"
|
||||
"::$proto_ns$::io::CodedInputStream::Limit limit = "
|
||||
"input->PushLimit(static_cast<int>(length));\n"
|
||||
"while (input->BytesUntilLimit() > 0) {\n"
|
||||
" int value = 0;\n"
|
||||
" DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||
" input, &value)));\n");
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_)) {
|
||||
format(" add_$name$(static_cast< $type$ >(value));\n");
|
||||
} else {
|
||||
format(
|
||||
" if ($type$_IsValid(value)) {\n"
|
||||
" _internal_add_$name$(static_cast< $type$ >(value));\n"
|
||||
" } else {\n");
|
||||
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
format(
|
||||
" mutable_unknown_fields()->AddVarint(\n"
|
||||
" $number$, static_cast<$uint64$>(value));\n");
|
||||
} else {
|
||||
format(
|
||||
" unknown_fields_stream.WriteVarint32(tag);\n"
|
||||
" unknown_fields_stream.WriteVarint32(\n"
|
||||
" static_cast<$uint32$>(value));\n");
|
||||
}
|
||||
format(" }\n");
|
||||
}
|
||||
format(
|
||||
"}\n"
|
||||
"input->PopLimit(limit);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
|
||||
io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
if (descriptor_->is_packed()) {
|
||||
// Write the tag and the size.
|
||||
format(
|
||||
"{\n"
|
||||
" int byte_size = "
|
||||
"_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n"
|
||||
" if (byte_size > 0) {\n"
|
||||
" target = stream->WriteEnumPacked(\n"
|
||||
" $number$, $name$_, byte_size, target);\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
} else {
|
||||
format(
|
||||
"for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
|
||||
" target = stream->EnsureSpace(target);\n"
|
||||
" target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
|
||||
" $number$, this->_internal_$name$(i), target);\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
format(
|
||||
"{\n"
|
||||
" size_t data_size = 0;\n"
|
||||
" unsigned int count = static_cast<unsigned "
|
||||
"int>(this->_internal_$name$_size());");
|
||||
format.Indent();
|
||||
format(
|
||||
"for (unsigned int i = 0; i < count; i++) {\n"
|
||||
" data_size += ::$proto_ns$::internal::WireFormatLite::EnumSize(\n"
|
||||
" this->_internal_$name$(static_cast<int>(i)));\n"
|
||||
"}\n");
|
||||
|
||||
if (descriptor_->is_packed()) {
|
||||
format(
|
||||
"if (data_size > 0) {\n"
|
||||
" total_size += $tag_size$ +\n"
|
||||
" ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
|
||||
" static_cast<$int32$>(data_size));\n"
|
||||
"}\n"
|
||||
"int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
|
||||
"_$name$_cached_byte_size_.store(cached_size,\n"
|
||||
" std::memory_order_relaxed);\n"
|
||||
"total_size += data_size;\n");
|
||||
} else {
|
||||
format("total_size += ($tag_size$UL * count) + data_size;\n");
|
||||
}
|
||||
format.Outdent();
|
||||
format("}\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
113
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_enum_field.h
vendored
Normal file
113
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_enum_field.h
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class EnumFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
|
||||
~EnumFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
|
||||
};
|
||||
|
||||
class EnumOneofFieldGenerator : public EnumFieldGenerator {
|
||||
public:
|
||||
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~EnumOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedEnumFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~RepeatedEnumFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const {}
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
|
||||
187
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_extension.cc
vendored
Normal file
187
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_extension.cc
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_extension.h>
|
||||
#include <map>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
// Returns the fully-qualified class name of the message that this field
|
||||
// extends. This function is used in the Google-internal code to handle some
|
||||
// legacy cases.
|
||||
std::string ExtendeeClassName(const FieldDescriptor* descriptor) {
|
||||
const Descriptor* extendee = descriptor->containing_type();
|
||||
return ClassName(extendee, true);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor), options_(options) {
|
||||
// Construct type_traits_.
|
||||
if (descriptor_->is_repeated()) {
|
||||
type_traits_ = "Repeated";
|
||||
}
|
||||
|
||||
switch (descriptor_->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
type_traits_.append("EnumTypeTraits< ");
|
||||
type_traits_.append(ClassName(descriptor_->enum_type(), true));
|
||||
type_traits_.append(", ");
|
||||
type_traits_.append(ClassName(descriptor_->enum_type(), true));
|
||||
type_traits_.append("_IsValid>");
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
type_traits_.append("StringTypeTraits");
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
type_traits_.append("MessageTypeTraits< ");
|
||||
type_traits_.append(ClassName(descriptor_->message_type(), true));
|
||||
type_traits_.append(" >");
|
||||
break;
|
||||
default:
|
||||
type_traits_.append("PrimitiveTypeTraits< ");
|
||||
type_traits_.append(PrimitiveTypeName(options_, descriptor_->cpp_type()));
|
||||
type_traits_.append(" >");
|
||||
break;
|
||||
}
|
||||
SetCommonVars(options, &variables_);
|
||||
variables_["extendee"] = ExtendeeClassName(descriptor_);
|
||||
variables_["type_traits"] = type_traits_;
|
||||
std::string name = descriptor_->name();
|
||||
variables_["name"] = ResolveKeyword(name);
|
||||
variables_["constant_name"] = FieldConstantName(descriptor_);
|
||||
variables_["field_type"] =
|
||||
StrCat(static_cast<int>(descriptor_->type()));
|
||||
variables_["packed"] = descriptor_->is_packed() ? "true" : "false";
|
||||
|
||||
std::string scope =
|
||||
IsScoped() ? ClassName(descriptor_->extension_scope(), false) + "::" : "";
|
||||
variables_["scope"] = scope;
|
||||
std::string scoped_name = scope + ResolveKeyword(name);
|
||||
variables_["scoped_name"] = scoped_name;
|
||||
variables_["number"] = StrCat(descriptor_->number());
|
||||
}
|
||||
|
||||
ExtensionGenerator::~ExtensionGenerator() {}
|
||||
|
||||
bool ExtensionGenerator::IsScoped() const {
|
||||
return descriptor_->extension_scope() != nullptr;
|
||||
}
|
||||
|
||||
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) const {
|
||||
Formatter format(printer, variables_);
|
||||
|
||||
// If this is a class member, it needs to be declared "static". Otherwise,
|
||||
// it needs to be "extern". In the latter case, it also needs the DLL
|
||||
// export/import specifier.
|
||||
std::string qualifier;
|
||||
if (!IsScoped()) {
|
||||
qualifier = "extern";
|
||||
if (!options_.dllexport_decl.empty()) {
|
||||
qualifier = options_.dllexport_decl + " " + qualifier;
|
||||
}
|
||||
} else {
|
||||
qualifier = "static";
|
||||
}
|
||||
|
||||
format(
|
||||
"static const int $constant_name$ = $number$;\n"
|
||||
"$1$ ::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n"
|
||||
" ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n"
|
||||
" ${2$$name$$}$;\n",
|
||||
qualifier, descriptor_);
|
||||
}
|
||||
|
||||
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
// If we are building for lite with implicit weak fields, we want to skip over
|
||||
// any custom options (i.e. extensions of messages from descriptor.proto).
|
||||
// This prevents the creation of any unnecessary linker references to the
|
||||
// descriptor messages.
|
||||
if (options_.lite_implicit_weak_fields &&
|
||||
descriptor_->containing_type()->file()->name() ==
|
||||
"net/proto2/proto/descriptor.proto") {
|
||||
return;
|
||||
}
|
||||
|
||||
Formatter format(printer, variables_);
|
||||
std::string default_str;
|
||||
// If this is a class member, it needs to be declared in its class scope.
|
||||
if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
||||
// We need to declare a global string which will contain the default value.
|
||||
// We cannot declare it at class scope because that would require exposing
|
||||
// it in the header which would be annoying for other reasons. So we
|
||||
// replace :: with _ in the name and declare it as a global.
|
||||
default_str =
|
||||
StringReplace(variables_["scoped_name"], "::", "_", true) + "_default";
|
||||
format("const std::string $1$($2$);\n", default_str,
|
||||
DefaultValue(options_, descriptor_));
|
||||
} else if (descriptor_->message_type()) {
|
||||
// We have to initialize the default instance for extensions at registration
|
||||
// time.
|
||||
default_str =
|
||||
FieldMessageTypeName(descriptor_, options_) + "::default_instance()";
|
||||
} else {
|
||||
default_str = DefaultValue(options_, descriptor_);
|
||||
}
|
||||
|
||||
// Likewise, class members need to declare the field constant variable.
|
||||
if (IsScoped()) {
|
||||
format(
|
||||
"#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"
|
||||
"const int $scope$$constant_name$;\n"
|
||||
"#endif\n");
|
||||
}
|
||||
|
||||
format(
|
||||
"::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n"
|
||||
" ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n"
|
||||
" $scoped_name$($constant_name$, $1$);\n",
|
||||
default_str);
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
91
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_extension.h
vendored
Normal file
91
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_extension.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class FieldDescriptor; // descriptor.h
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Generates code for an extension, which may be within the scope of some
|
||||
// message or may be at file scope. This is much simpler than FieldGenerator
|
||||
// since extensions are just simple identifiers with interesting types.
|
||||
class ExtensionGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
explicit ExtensionGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~ExtensionGenerator();
|
||||
|
||||
// Header stuff.
|
||||
void GenerateDeclaration(io::Printer* printer) const;
|
||||
|
||||
// Source file stuff.
|
||||
void GenerateDefinition(io::Printer* printer);
|
||||
|
||||
bool IsScoped() const;
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
std::string type_traits_;
|
||||
Options options_;
|
||||
|
||||
std::map<std::string, std::string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
||||
195
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_field.cc
vendored
Normal file
195
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_field.cc
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <memory>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_map_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
using internal::WireFormat;
|
||||
|
||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
std::map<std::string, std::string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonVars(options, variables);
|
||||
(*variables)["ns"] = Namespace(descriptor, options);
|
||||
(*variables)["name"] = FieldName(descriptor);
|
||||
(*variables)["index"] = StrCat(descriptor->index());
|
||||
(*variables)["number"] = StrCat(descriptor->number());
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||
(*variables)["field_member"] = FieldName(descriptor) + "_";
|
||||
|
||||
(*variables)["tag_size"] = StrCat(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
(*variables)["deprecated_attr"] = DeprecatedAttribute(options, descriptor);
|
||||
|
||||
(*variables)["set_hasbit"] = "";
|
||||
(*variables)["clear_hasbit"] = "";
|
||||
if (HasHasbit(descriptor)) {
|
||||
(*variables)["set_hasbit_io"] =
|
||||
"_Internal::set_has_" + FieldName(descriptor) + "(&_has_bits_);";
|
||||
} else {
|
||||
(*variables)["set_hasbit_io"] = "";
|
||||
}
|
||||
(*variables)["annotate_accessor"] = "";
|
||||
|
||||
// These variables are placeholders to pick out the beginning and ends of
|
||||
// identifiers for annotations (when doing so with existing variables would
|
||||
// be ambiguous or impossible). They should never be set to anything but the
|
||||
// empty string.
|
||||
(*variables)["{"] = "";
|
||||
(*variables)["}"] = "";
|
||||
}
|
||||
|
||||
void FieldGenerator::SetHasBitIndex(int32 has_bit_index) {
|
||||
if (!HasHasbit(descriptor_)) {
|
||||
GOOGLE_CHECK_EQ(has_bit_index, -1);
|
||||
return;
|
||||
}
|
||||
variables_["set_hasbit"] = StrCat(
|
||||
"_has_bits_[", has_bit_index / 32, "] |= 0x",
|
||||
strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
|
||||
variables_["clear_hasbit"] = StrCat(
|
||||
"_has_bits_[", has_bit_index / 32, "] &= ~0x",
|
||||
strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
|
||||
}
|
||||
|
||||
void SetCommonOneofFieldVariables(
|
||||
const FieldDescriptor* descriptor,
|
||||
std::map<std::string, std::string>* variables) {
|
||||
const std::string prefix = descriptor->containing_oneof()->name() + "_.";
|
||||
(*variables)["oneof_name"] = descriptor->containing_oneof()->name();
|
||||
(*variables)["field_member"] =
|
||||
StrCat(prefix, (*variables)["name"], "_");
|
||||
}
|
||||
|
||||
FieldGenerator::~FieldGenerator() {}
|
||||
|
||||
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
|
||||
const Options& options,
|
||||
MessageSCCAnalyzer* scc_analyzer)
|
||||
: descriptor_(descriptor), field_generators_(descriptor->field_count()) {
|
||||
// Construct all the FieldGenerators.
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
field_generators_[i].reset(
|
||||
MakeGenerator(descriptor->field(i), options, scc_analyzer));
|
||||
}
|
||||
}
|
||||
|
||||
FieldGenerator* FieldGeneratorMap::MakeGoogleInternalGenerator(
|
||||
const FieldDescriptor* field, const Options& options,
|
||||
MessageSCCAnalyzer* scc_analyzer) {
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FieldGenerator* FieldGeneratorMap::MakeGenerator(
|
||||
const FieldDescriptor* field, const Options& options,
|
||||
MessageSCCAnalyzer* scc_analyzer) {
|
||||
FieldGenerator* generator =
|
||||
MakeGoogleInternalGenerator(field, options, scc_analyzer);
|
||||
if (generator) {
|
||||
return generator;
|
||||
}
|
||||
|
||||
if (field->is_repeated()) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
if (field->is_map()) {
|
||||
return new MapFieldGenerator(field, options);
|
||||
} else {
|
||||
return new RepeatedMessageFieldGenerator(field, options,
|
||||
scc_analyzer);
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
return new RepeatedStringFieldGenerator(field, options);
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return new RepeatedEnumFieldGenerator(field, options);
|
||||
default:
|
||||
return new RepeatedPrimitiveFieldGenerator(field, options);
|
||||
}
|
||||
} else if (field->real_containing_oneof()) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return new MessageOneofFieldGenerator(field, options, scc_analyzer);
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
return new StringOneofFieldGenerator(field, options);
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return new EnumOneofFieldGenerator(field, options);
|
||||
default:
|
||||
return new PrimitiveOneofFieldGenerator(field, options);
|
||||
}
|
||||
} else {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return new MessageFieldGenerator(field, options, scc_analyzer);
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
return new StringFieldGenerator(field, options);
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return new EnumFieldGenerator(field, options);
|
||||
default:
|
||||
return new PrimitiveFieldGenerator(field, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FieldGeneratorMap::~FieldGeneratorMap() {}
|
||||
|
||||
const FieldGenerator& FieldGeneratorMap::get(
|
||||
const FieldDescriptor* field) const {
|
||||
GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
|
||||
return *field_generators_[field->index()];
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
222
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_field.h
vendored
Normal file
222
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_field.h
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Helper function: set variables in the map that are the same for all
|
||||
// field code generators.
|
||||
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
|
||||
// 'deprecation'].
|
||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
std::map<std::string, std::string>* variables,
|
||||
const Options& options);
|
||||
|
||||
void SetCommonOneofFieldVariables(
|
||||
const FieldDescriptor* descriptor,
|
||||
std::map<std::string, std::string>* variables);
|
||||
|
||||
class FieldGenerator {
|
||||
public:
|
||||
explicit FieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor), options_(options) {}
|
||||
virtual ~FieldGenerator();
|
||||
virtual void GenerateSerializeWithCachedSizes(
|
||||
io::Printer* printer) const final{};
|
||||
// Generate lines of code declaring members fields of the message class
|
||||
// needed to represent this field. These are placed inside the message
|
||||
// class.
|
||||
virtual void GeneratePrivateMembers(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate static default variable for this field. These are placed inside
|
||||
// the message class. Most field types don't need this, so the default
|
||||
// implementation is empty.
|
||||
virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate prototypes for all of the accessor functions related to this
|
||||
// field. These are placed inside the class definition.
|
||||
virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate inline definitions of accessor functions for this field.
|
||||
// These are placed inside the header after all class definitions.
|
||||
virtual void GenerateInlineAccessorDefinitions(
|
||||
io::Printer* printer) const = 0;
|
||||
|
||||
// Generate definitions of accessors that aren't inlined. These are
|
||||
// placed somewhere in the .cc file.
|
||||
// Most field types don't need this, so the default implementation is empty.
|
||||
virtual void GenerateNonInlineAccessorDefinitions(
|
||||
io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate declarations of accessors that are for internal purposes only.
|
||||
// Most field types don't need this, so the default implementation is empty.
|
||||
virtual void GenerateInternalAccessorDefinitions(
|
||||
io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate definitions of accessors that are for internal purposes only.
|
||||
// Most field types don't need this, so the default implementation is empty.
|
||||
virtual void GenerateInternalAccessorDeclarations(
|
||||
io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate lines of code (statements, not declarations) which clear the
|
||||
// field. This is used to define the clear_$name$() method
|
||||
virtual void GenerateClearingCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate lines of code (statements, not declarations) which clear the
|
||||
// field as part of the Clear() method for the whole message. For message
|
||||
// types which have field presence bits, MessageGenerator::GenerateClear
|
||||
// will have already checked the presence bits.
|
||||
//
|
||||
// Since most field types can re-use GenerateClearingCode, this method is
|
||||
// not pure virtual.
|
||||
virtual void GenerateMessageClearingCode(io::Printer* printer) const {
|
||||
GenerateClearingCode(printer);
|
||||
}
|
||||
|
||||
// Generate lines of code (statements, not declarations) which merges the
|
||||
// contents of the field from the current message to the target message,
|
||||
// which is stored in the generated code variable "from".
|
||||
// This is used to fill in the MergeFrom method for the whole message.
|
||||
// Details of this usage can be found in message.cc under the
|
||||
// GenerateMergeFrom method.
|
||||
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generates a copy constructor
|
||||
virtual void GenerateCopyConstructorCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate lines of code (statements, not declarations) which swaps
|
||||
// this field and the corresponding field of another message, which
|
||||
// is stored in the generated code variable "other". This is used to
|
||||
// define the Swap method. Details of usage can be found in
|
||||
// message.cc under the GenerateSwap method.
|
||||
virtual void GenerateSwappingCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate initialization code for private members declared by
|
||||
// GeneratePrivateMembers(). These go into the message class's SharedCtor()
|
||||
// method, invoked by each of the generated constructors.
|
||||
virtual void GenerateConstructorCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate any code that needs to go in the class's SharedDtor() method,
|
||||
// invoked by the destructor.
|
||||
// Most field types don't need this, so the default implementation is empty.
|
||||
virtual void GenerateDestructorCode(io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate a manual destructor invocation for use when the message is on an
|
||||
// arena. The code that this method generates will be executed inside a
|
||||
// shared-for-the-whole-message-class method registered with
|
||||
// OwnDestructor(). The method should return |true| if it generated any code
|
||||
// that requires a call; this allows the message generator to eliminate the
|
||||
// OwnDestructor() registration if no fields require it.
|
||||
virtual bool GenerateArenaDestructorCode(io::Printer* printer) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate lines to serialize this field directly to the array "target",
|
||||
// which are placed within the message's SerializeWithCachedSizesToArray()
|
||||
// method. This must also advance "target" past the written bytes.
|
||||
virtual void GenerateSerializeWithCachedSizesToArray(
|
||||
io::Printer* printer) const = 0;
|
||||
|
||||
// Generate lines to compute the serialized size of this field, which
|
||||
// are placed in the message's ByteSize() method.
|
||||
virtual void GenerateByteSize(io::Printer* printer) const = 0;
|
||||
|
||||
void SetHasBitIndex(int32 has_bit_index);
|
||||
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
const Options& options_;
|
||||
std::map<std::string, std::string> variables_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
|
||||
};
|
||||
|
||||
// Convenience class which constructs FieldGenerators for a Descriptor.
|
||||
class FieldGeneratorMap {
|
||||
public:
|
||||
FieldGeneratorMap(const Descriptor* descriptor, const Options& options,
|
||||
MessageSCCAnalyzer* scc_analyzer);
|
||||
~FieldGeneratorMap();
|
||||
|
||||
const FieldGenerator& get(const FieldDescriptor* field) const;
|
||||
|
||||
void SetHasBitIndices(const std::vector<int>& has_bit_indices_) {
|
||||
for (int i = 0; i < descriptor_->field_count(); ++i) {
|
||||
field_generators_[i]->SetHasBitIndex(has_bit_indices_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const Descriptor* descriptor_;
|
||||
std::vector<std::unique_ptr<FieldGenerator>> field_generators_;
|
||||
|
||||
static FieldGenerator* MakeGoogleInternalGenerator(
|
||||
const FieldDescriptor* field, const Options& options,
|
||||
MessageSCCAnalyzer* scc_analyzer);
|
||||
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
|
||||
const Options& options,
|
||||
MessageSCCAnalyzer* scc_analyzer);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||
1507
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_file.cc
vendored
Normal file
1507
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_file.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
206
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_file.h
vendored
Normal file
206
ConvAI/Convai/Source/ThirdParty/gRPC/Include/google/protobuf/compiler/cpp/cpp_file.h
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/compiler/scc.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class FileDescriptor; // descriptor.h
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class EnumGenerator; // enum.h
|
||||
class MessageGenerator; // message.h
|
||||
class ServiceGenerator; // service.h
|
||||
class ExtensionGenerator; // extension.h
|
||||
|
||||
class FileGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
FileGenerator(const FileDescriptor* file, const Options& options);
|
||||
~FileGenerator();
|
||||
|
||||
// Shared code between the two header generators below.
|
||||
void GenerateHeader(io::Printer* printer);
|
||||
|
||||
// info_path, if non-empty, should be the path (relative to printer's
|
||||
// output) to the metadata file describing this proto header.
|
||||
void GenerateProtoHeader(io::Printer* printer, const std::string& info_path);
|
||||
// info_path, if non-empty, should be the path (relative to printer's
|
||||
// output) to the metadata file describing this PB header.
|
||||
void GeneratePBHeader(io::Printer* printer, const std::string& info_path);
|
||||
void GenerateSource(io::Printer* printer);
|
||||
|
||||
int NumMessages() const { return message_generators_.size(); }
|
||||
// Similar to GenerateSource but generates only one message
|
||||
void GenerateSourceForMessage(int idx, io::Printer* printer);
|
||||
void GenerateGlobalSource(io::Printer* printer);
|
||||
|
||||
private:
|
||||
// Internal type used by GenerateForwardDeclarations (defined in file.cc).
|
||||
class ForwardDeclarations;
|
||||
struct CrossFileReferences;
|
||||
|
||||
void IncludeFile(const std::string& google3_name, io::Printer* printer) {
|
||||
DoIncludeFile(google3_name, false, printer);
|
||||
}
|
||||
void IncludeFileAndExport(const std::string& google3_name,
|
||||
io::Printer* printer) {
|
||||
DoIncludeFile(google3_name, true, printer);
|
||||
}
|
||||
void DoIncludeFile(const std::string& google3_name, bool do_export,
|
||||
io::Printer* printer);
|
||||
|
||||
std::string CreateHeaderInclude(const std::string& basename,
|
||||
const FileDescriptor* file);
|
||||
void GetCrossFileReferencesForField(const FieldDescriptor* field,
|
||||
CrossFileReferences* refs);
|
||||
void GetCrossFileReferencesForFile(const FileDescriptor* file,
|
||||
CrossFileReferences* refs);
|
||||
void GenerateInternalForwardDeclarations(const CrossFileReferences& refs,
|
||||
io::Printer* printer);
|
||||
void GenerateSourceIncludes(io::Printer* printer);
|
||||
void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
|
||||
|
||||
void GenerateInitForSCC(const SCC* scc, const CrossFileReferences& refs,
|
||||
io::Printer* printer);
|
||||
void GenerateTables(io::Printer* printer);
|
||||
void GenerateReflectionInitializationCode(io::Printer* printer);
|
||||
|
||||
// For other imports, generates their forward-declarations.
|
||||
void GenerateForwardDeclarations(io::Printer* printer);
|
||||
|
||||
// Generates top or bottom of a header file.
|
||||
void GenerateTopHeaderGuard(io::Printer* printer, bool pb_h);
|
||||
void GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h);
|
||||
|
||||
// Generates #include directives.
|
||||
void GenerateLibraryIncludes(io::Printer* printer);
|
||||
void GenerateDependencyIncludes(io::Printer* printer);
|
||||
|
||||
// Generate a pragma to pull in metadata using the given info_path (if
|
||||
// non-empty). info_path should be relative to printer's output.
|
||||
void GenerateMetadataPragma(io::Printer* printer,
|
||||
const std::string& info_path);
|
||||
|
||||
// Generates a couple of different pieces before definitions:
|
||||
void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
|
||||
|
||||
// Generates types for classes.
|
||||
void GenerateMessageDefinitions(io::Printer* printer);
|
||||
|
||||
void GenerateEnumDefinitions(io::Printer* printer);
|
||||
|
||||
// Generates generic service definitions.
|
||||
void GenerateServiceDefinitions(io::Printer* printer);
|
||||
|
||||
// Generates extension identifiers.
|
||||
void GenerateExtensionIdentifiers(io::Printer* printer);
|
||||
|
||||
// Generates inline function definitions.
|
||||
void GenerateInlineFunctionDefinitions(io::Printer* printer);
|
||||
|
||||
void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
|
||||
|
||||
// Sometimes the names we use in a .proto file happen to be defined as
|
||||
// macros on some platforms (e.g., macro/minor used in plugin.proto are
|
||||
// defined as macros in sys/types.h on FreeBSD and a few other platforms).
|
||||
// To make the generated code compile on these platforms, we either have to
|
||||
// undef the macro for these few platforms, or rename the field name for all
|
||||
// platforms. Since these names are part of protobuf public API, renaming is
|
||||
// generally a breaking change so we prefer the #undef approach.
|
||||
void GenerateMacroUndefs(io::Printer* printer);
|
||||
|
||||
bool IsSCCRepresentative(const Descriptor* d) {
|
||||
return GetSCCRepresentative(d) == d;
|
||||
}
|
||||
const Descriptor* GetSCCRepresentative(const Descriptor* d) {
|
||||
return GetSCC(d)->GetRepresentative();
|
||||
}
|
||||
const SCC* GetSCC(const Descriptor* d) { return scc_analyzer_.GetSCC(d); }
|
||||
|
||||
bool IsDepWeak(const FileDescriptor* dep) const {
|
||||
if (weak_deps_.count(dep) != 0) {
|
||||
GOOGLE_CHECK(!options_.opensource_runtime);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<const FileDescriptor*> weak_deps_;
|
||||
std::vector<const SCC*> sccs_;
|
||||
|
||||
const FileDescriptor* file_;
|
||||
const Options options_;
|
||||
|
||||
MessageSCCAnalyzer scc_analyzer_;
|
||||
|
||||
std::map<std::string, std::string> variables_;
|
||||
|
||||
// Contains the post-order walk of all the messages (and child messages) in
|
||||
// this file. If you need a pre-order walk just reverse iterate.
|
||||
std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
|
||||
std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
|
||||
std::vector<std::unique_ptr<ServiceGenerator>> service_generators_;
|
||||
std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user