bool FJsonObjectConverter::UStructToJsonObject(const UStruct* StructDefinition, const void* Struct, TSharedRef<FJsonObject> OutJsonObject, int64 CheckFlags, int64 SkipFlags) { for(TFieldIterator<UProperty> It(StructDefinition); It; ++It) { UProperty* Property = *It; // Check to see if we should ignore this property if (CheckFlags != 0 && !Property->HasAnyPropertyFlags(CheckFlags)) { continue; } if (Property->HasAnyPropertyFlags(SkipFlags)) { continue; } FString VariableName = StandardizeCase(Property->GetName()); const void* Value = Property->ContainerPtrToValuePtr<uint8>(Struct); // convert the property to a FJsonValue TSharedPtr<FJsonValue> JsonValue = UPropertyToJsonValue(Property, Value, CheckFlags, SkipFlags); if (!JsonValue.IsValid()) { UClass* PropClass = Property->GetClass(); UE_LOG(LogJson, Error, TEXT("UStructToJsonObject - Unhandled property type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); return false; } // set the value on the output object OutJsonObject->SetField(VariableName, JsonValue); } return true; }
bool FJsonObjectConverter::UStructToJsonAttributes(const UStruct* StructDefinition, const void* Struct, TMap< FString, TSharedPtr<FJsonValue> >& OutJsonAttributes, int64 CheckFlags, int64 SkipFlags, const CustomExportCallback* ExportCb) { if (SkipFlags == 0) { // If we have no specified skip flags, skip deprecated by default when writing SkipFlags |= CPF_Deprecated; } if (StructDefinition == FJsonObjectWrapper::StaticStruct()) { // Just copy it into the object const FJsonObjectWrapper* ProxyObject = (const FJsonObjectWrapper *)Struct; if (ProxyObject->JsonObject.IsValid()) { OutJsonAttributes = ProxyObject->JsonObject->Values; } return true; } for (TFieldIterator<UProperty> It(StructDefinition); It; ++It) { UProperty* Property = *It; // Check to see if we should ignore this property if (CheckFlags != 0 && !Property->HasAnyPropertyFlags(CheckFlags)) { continue; } if (Property->HasAnyPropertyFlags(SkipFlags)) { continue; } FString VariableName = StandardizeCase(Property->GetName()); const void* Value = Property->ContainerPtrToValuePtr<uint8>(Struct); // convert the property to a FJsonValue TSharedPtr<FJsonValue> JsonValue = UPropertyToJsonValue(Property, Value, CheckFlags, SkipFlags, ExportCb); if (!JsonValue.IsValid()) { UClass* PropClass = Property->GetClass(); UE_LOG(LogJson, Error, TEXT("UStructToJsonObject - Unhandled property type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); return false; } // set the value on the output object OutJsonAttributes.Add(VariableName, JsonValue); } return true; }
void FLuaScriptCodeGenerator::ExportClass(UClass* Class, const FString& SourceHeaderFilename, const FString& GeneratedHeaderFilename, bool bHasChanged) { if (!CanExportClass(Class)) { return; } UE_LOG(LogScriptGenerator, Log, TEXT("Exporting class %s"), *Class->GetName()); ExportedClasses.Add(Class->GetFName()); LuaExportedClasses.Add(Class); AllSourceClassHeaders.Add(SourceHeaderFilename); const FString ClassGlueFilename = GetScriptHeaderForClass(Class); AllScriptHeaders.Add(ClassGlueFilename); const FString ClassNameCPP = GetClassNameCPP(Class); FString GeneratedGlue(TEXT("#pragma once\r\n\r\n")); // Export all functions for (TFieldIterator<UFunction> FuncIt(Class /*, EFieldIteratorFlags::ExcludeSuper*/); FuncIt; ++FuncIt) { UFunction* Function = *FuncIt; if (CanExportFunction(ClassNameCPP, Class, Function)) { GeneratedGlue += ExportFunction(ClassNameCPP, Class, Function); } } // Export properties that are owned by this class int32 PropertyIndex = 0; for (TFieldIterator<UProperty> PropertyIt(Class /*, EFieldIteratorFlags::ExcludeSuper*/); PropertyIt; ++PropertyIt, ++PropertyIndex) { UProperty* Property = *PropertyIt; if (CanExportProperty(ClassNameCPP, Class, Property)) { UE_LOG(LogScriptGenerator, Log, TEXT(" %s %s"), *Property->GetClass()->GetName(), *Property->GetName()); GeneratedGlue += ExportProperty(ClassNameCPP, Class, Property, PropertyIndex); } } GeneratedGlue += ExportAdditionalClassGlue(ClassNameCPP, Class); SaveHeaderIfChanged(ClassGlueFilename, GeneratedGlue); }
/** * Deserialize the data contained within a message using the parameter fields of a given UStruct * @param Message message containing the data to retrieve * @param Object structure containing reflection information that matches message * @param Parms memory layout to store the message's data * @param PropFlags any flags relevant to the field iteration * * @return TRUE if successful, FALSE otherwise */ bool DeserializeRPCParams(const google::protobuf::Message* Message, UStruct* Object, void* Parms, int64 PropFlags) { bool bSuccess = true; const google::protobuf::Descriptor* Desc = Message->GetDescriptor(); const google::protobuf::Reflection* Refl = Message->GetReflection(); for(TFieldIterator<UProperty> It(Object); It && (It->PropertyFlags & PropFlags); ++It) { UProperty* Property = *It; UClass* PropClass = Property->GetClass(); const google::protobuf::FieldDescriptor* FieldDesc = Desc->FindFieldByName(TCHAR_TO_UTF8(*Property->GetNameCPP())); if (FieldDesc) { if (FieldDesc->is_repeated()) { int32 NumElements = Refl->FieldSize(*Message, FieldDesc); FScriptArrayHelper* ArrayHelper = NULL; if (PropClass == UArrayProperty::StaticClass()) { void* Value = Property->ContainerPtrToValuePtr<uint8>(Parms); UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property); Property = ArrayProperty->Inner; PropClass = Property->GetClass(); ArrayHelper = new FScriptArrayHelper(ArrayProperty, Value); ArrayHelper->EmptyAndAddValues(NumElements); } else { if (Property->ArrayDim < NumElements) { UE_LOG_ONLINE(Error, TEXT("DeserializeRPCParams - Static array mismatch (%d != %d) property type '%s': %s"), NumElements, Property->ArrayDim, *PropClass->GetName(), *Property->GetPathName()); NumElements = Property->ArrayDim; } } for (int32 i = 0; i < NumElements; i++) { void* Value = ArrayHelper ? ArrayHelper->GetRawPtr(i) : Property->ContainerPtrToValuePtr<uint8>(Parms, i); if (PropClass == UIntProperty::StaticClass()) { *(int32*)Value = Refl->GetRepeatedInt32(*Message, FieldDesc, i); } else if (PropClass == UFloatProperty::StaticClass()) { *(float*)Value = Refl->GetRepeatedFloat(*Message, FieldDesc, i); } else if (PropClass == UBoolProperty::StaticClass() && CastChecked<UBoolProperty>(Property)->IsNativeBool()) { *(bool*)Value = Refl->GetRepeatedBool(*Message, FieldDesc, i); } else if (PropClass == UByteProperty::StaticClass() && CastChecked<UByteProperty>(Property)->Enum == NULL) { const google::protobuf::string& String = Refl->GetRepeatedStringReference(*Message, FieldDesc, i, NULL); if (ArrayHelper) { // Message only contains one string, but we need an array of bytes ArrayHelper->AddValues(String.size() - 1); Value = ArrayHelper->GetRawPtr(i); } FMemory::Memcpy(Value, String.c_str(), String.size()); break; } else if (PropClass == UStrProperty::StaticClass()) { const google::protobuf::string& String = Refl->GetRepeatedStringReference(*Message, FieldDesc, i, NULL); *(FString*)Value = UTF8_TO_TCHAR(String.c_str()); } else if (PropClass == UStructProperty::StaticClass()) { UStructProperty* StructProperty = Cast<UStructProperty>(Property); const google::protobuf::Message& SubMessage = Refl->GetRepeatedMessage(*Message, FieldDesc, i); DeserializeRPCParams(&SubMessage, StructProperty->Struct, Value, CPF_AllFlags); } else { bSuccess = false; UE_LOG_ONLINE(Error, TEXT("DeserializeRPCParams - Unhandled property type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); } } if (ArrayHelper) { delete ArrayHelper; } } else { if (Property->ArrayDim == 1) { void* Value = Property->ContainerPtrToValuePtr<uint8>(Parms); if (PropClass == UIntProperty::StaticClass()) { *(int32*)Value = Refl->GetInt32(*Message, FieldDesc); } else if (PropClass == UFloatProperty::StaticClass()) { *(float*)Value = Refl->GetFloat(*Message, FieldDesc); } else if (PropClass == UBoolProperty::StaticClass() && CastChecked<UBoolProperty>(Property)->IsNativeBool()) { *(bool*)Value = Refl->GetBool(*Message, FieldDesc); } else if (PropClass == UByteProperty::StaticClass() && CastChecked<UByteProperty>(Property)->Enum == NULL) { int32 NumBytes = Refl->FieldSize(*Message, FieldDesc); google::protobuf::string Bytes = Refl->GetString(*Message, FieldDesc); FMemory::Memcpy(Value, Bytes.c_str(), NumBytes); } else if (PropClass == UStrProperty::StaticClass()) { google::protobuf::string String = Refl->GetString(*Message, FieldDesc); *(FString*)Value = UTF8_TO_TCHAR(String.c_str()); } else if (PropClass == UStructProperty::StaticClass()) { UStructProperty* StructProperty = Cast<UStructProperty>(Property); const google::protobuf::Message& SubMessage = Refl->GetMessage(*Message, FieldDesc); DeserializeRPCParams(&SubMessage, StructProperty->Struct, Value, CPF_AllFlags); } else { bSuccess = false; UE_LOG_ONLINE(Error, TEXT("DeserializeRPCParams - Unhandled property type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); } } else { bSuccess = false; UE_LOG_ONLINE(Error, TEXT("DeserializeRPCParams - Property reflection mismatch type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); } } } else { bSuccess = false; UE_LOG_ONLINE(Error, TEXT("DeserializeRPCParams - Property reflection missing type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); } } return bSuccess; }
/** * Serialize the parameter fields of a given UStruct into a message object * @param NewMessage message to fill * @param Object structure containing reflection information that matches message * @param Parms data to serialize into the new message * @param PropFlags any flags relevant to the field iteration * * @return TRUE if successful, FALSE otherwise */ bool SerializeRPCParams(google::protobuf::Message* NewMessage, UStruct* Object, void* Parms, int64 PropFlags) { bool bSuccess = true; const google::protobuf::Descriptor* Desc = NewMessage->GetDescriptor(); const google::protobuf::Reflection* Refl = NewMessage->GetReflection(); for(TFieldIterator<UProperty> It(Object); It && (It->PropertyFlags & PropFlags); ++It) { UProperty* Property = *It; UClass* PropClass = Property->GetClass(); const google::protobuf::FieldDescriptor* FieldDesc = Desc->FindFieldByName(TCHAR_TO_UTF8(*Property->GetNameCPP())); if (FieldDesc) { if (FieldDesc->is_repeated()) { int32 NumElements = Property->ArrayDim; FScriptArrayHelper* ArrayHelper = NULL; if (PropClass == UArrayProperty::StaticClass()) { void* Value = Property->ContainerPtrToValuePtr<uint8>(Parms); UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property); Property = ArrayProperty->Inner; PropClass = Property->GetClass(); ArrayHelper = new FScriptArrayHelper(ArrayProperty, Value); NumElements = ArrayHelper->Num(); } for (int32 i = 0; i < NumElements; i++) { void* Value = ArrayHelper ? ArrayHelper->GetRawPtr(i) : Property->ContainerPtrToValuePtr<void>(Parms, i); if (PropClass == UIntProperty::StaticClass()) { Refl->AddInt32(NewMessage, FieldDesc, *(int32*)Value); } else if (PropClass == UFloatProperty::StaticClass()) { Refl->AddFloat(NewMessage, FieldDesc, *(float*)Value); } else if (PropClass == UBoolProperty::StaticClass() && CastChecked<UBoolProperty>(Property)->IsNativeBool()) { Refl->AddBool(NewMessage, FieldDesc, *(bool*)Value); } else if (PropClass == UByteProperty::StaticClass() && CastChecked<UByteProperty>(Property)->Enum == NULL) { // All bytes are stored in a single string google::protobuf::string Bytes((ANSICHAR*)Value, NumElements); Refl->AddString(NewMessage, FieldDesc, Bytes); break; } else if (PropClass == UStrProperty::StaticClass()) { Refl->AddString(NewMessage, FieldDesc, TCHAR_TO_UTF8(**(FString*)Value)); } else if (PropClass == UStructProperty::StaticClass()) { UStructProperty* StructProperty = Cast<UStructProperty>(Property); google::protobuf::Message* SubMessage = Refl->AddMessage(NewMessage, FieldDesc, NULL); SerializeRPCParams(SubMessage, StructProperty->Struct, Value, CPF_AllFlags); } else { bSuccess = false; UE_LOG_ONLINE(Error, TEXT("SerializeRPCParams - Unhandled property type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); } } if (ArrayHelper) { delete ArrayHelper; } } else { if (Property->ArrayDim == 1) { void* Value = Property->ContainerPtrToValuePtr<uint8>(Parms); if (PropClass == UIntProperty::StaticClass()) { Refl->SetInt32(NewMessage, FieldDesc, *(int32*)Value); } else if (PropClass == UFloatProperty::StaticClass()) { Refl->SetFloat(NewMessage, FieldDesc, *(float*)Value); } else if (PropClass == UBoolProperty::StaticClass() && CastChecked<UBoolProperty>(Property)->IsNativeBool()) { Refl->SetBool(NewMessage, FieldDesc, *(bool*)Value); } else if (PropClass == UByteProperty::StaticClass() && CastChecked<UByteProperty>(Property)->Enum == NULL) { google::protobuf::string Bytes((ANSICHAR*)Value, 1); Refl->SetString(NewMessage, FieldDesc, Bytes); } else if (PropClass == UStrProperty::StaticClass()) { Refl->SetString(NewMessage, FieldDesc, TCHAR_TO_UTF8(**(FString*)Value)); } else if (PropClass == UStructProperty::StaticClass()) { UStructProperty* StructProperty = Cast<UStructProperty>(Property); google::protobuf::Message* SubMessage = Refl->MutableMessage(NewMessage, FieldDesc, NULL); SerializeRPCParams(SubMessage, StructProperty->Struct, Value, CPF_AllFlags); } else { bSuccess = false; UE_LOG_ONLINE(Error, TEXT("SerializeRPCParams - Unhandled property type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); } } else { bSuccess = false; UE_LOG_ONLINE(Error, TEXT("SerializeRPCParams - Property reflection mismatch type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); } } } else { bSuccess = false; UE_LOG_ONLINE(Error, TEXT("SerializeRPCParams - Property reflection missing type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); } } return bSuccess; }
/** * Creates a message definition for a group of properties * @param MsgProtoDesc descriptor to fill with the definition * @param FieldIt grouping of properties to define * @param PropertyFlags flags properties must have to be considered for the message * * @return TRUE on successful creation, FALSE otherwise */ bool CreateProtoDeclaration(google::protobuf::DescriptorProto* MsgProtoDesc, UStruct* Object, uint64 PropertyFlags) { bool bSuccess = true; int32 FieldIdx = 1; TFieldIterator<UProperty> FieldIt(Object); for(; FieldIt && (FieldIt->PropertyFlags & PropertyFlags); ++FieldIt) { UProperty* Property = *FieldIt; UClass* PropClass = Property->GetClass(); if (PropClass != UInterfaceProperty::StaticClass() && PropClass != UObjectProperty::StaticClass()) { bool bIsRepeated = false; UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property); if (ArrayProperty != NULL) { UClass* InnerPropClass = ArrayProperty->Inner->GetClass(); if (InnerPropClass != UInterfaceProperty::StaticClass() && InnerPropClass != UObjectProperty::StaticClass()) { Property = ArrayProperty->Inner; bIsRepeated = true; } else { UE_LOG_ONLINE(Error, TEXT("CreateProtoDeclaration - Unhandled property type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); bSuccess = false; break; } } else if(Property->ArrayDim != 1) { bIsRepeated = true; } FString SubMsgName; UStructProperty* StructProperty = Cast<UStructProperty>(Property); if (StructProperty != NULL) { FString TypeText, ExtendedTypeText; TypeText = Property->GetCPPType(&ExtendedTypeText, CPPF_None); google::protobuf::DescriptorProto* StructProtDesc = MsgProtoDesc->add_nested_type(); SubMsgName = FString::Printf(TEXT("%s%sMessage"), *TypeText, *ExtendedTypeText); StructProtDesc->set_name(TCHAR_TO_UTF8(*SubMsgName)); if (!CreateProtoDeclaration(StructProtDesc, StructProperty->Struct, CPF_AllFlags)) { StructProtDesc->Clear(); bSuccess = false; break; } } int32 Type = GetTypeFromProperty(Property); if (google::protobuf::FieldDescriptorProto_Type_IsValid(Type)) { google::protobuf::FieldDescriptorProto* MsgFieldProto = MsgProtoDesc->add_field(); MsgFieldProto->set_name(TCHAR_TO_UTF8(*Property->GetNameCPP())); MsgFieldProto->set_number(FieldIdx); MsgFieldProto->set_type((google::protobuf::FieldDescriptorProto_Type)Type); if (SubMsgName.Len() > 0) { MsgFieldProto->set_type_name(TCHAR_TO_UTF8(*SubMsgName)); } if (bIsRepeated) { MsgFieldProto->set_label(google::protobuf::FieldDescriptorProto_Label_LABEL_REPEATED); } else { MsgFieldProto->set_label(google::protobuf::FieldDescriptorProto_Label_LABEL_OPTIONAL); } FieldIdx++; } else { UE_LOG_ONLINE(Error, TEXT("CreateProtoDeclaration - Unhandled property mapping '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); bSuccess = false; break; } } else { UE_LOG_ONLINE(Error, TEXT("CreateProtoDeclaration - Unhandled property type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); bSuccess = false; break; } } return bSuccess; }