inline Object Object::GetOpt<Object>(const std::string &key, const Object &defaultObject) const { auto value = FindOpt(key); if(!value) return defaultObject; try { return value->AsObject(); } catch(std::exception &) { return defaultObject; } }
inline Object Object::Get<Object>(const std::string &key) const { auto value = Find(key); return value->AsObject(); }
inline Object::Object(const std::string &jsonPayload) { auto value = JSON::Parse(jsonPayload.c_str()); m_fields = std::move(value->AsObject().m_fields); }
bool USocketIOClientComponent::CallBPFunctionWithResponse(UObject* Target, const FString& FunctionName, TArray<TSharedPtr<FJsonValue>> Response) { if (!Target->IsValidLowLevel()) { UE_LOG(SocketIOLog, Warning, TEXT("CallFunctionByNameWithArguments: Target not found for '%s'"), *FunctionName); return false; } UFunction* Function = Target->FindFunction(FName(*FunctionName)); if (nullptr == Function) { UE_LOG(SocketIOLog, Warning, TEXT("CallFunctionByNameWithArguments: Function not found '%s'"), *FunctionName); return false; } //Check function signature TFieldIterator<UProperty> Iterator(Function); TArray<UProperty*> Properties; while (Iterator && (Iterator->PropertyFlags & CPF_Parm)) { UProperty* Prop = *Iterator; Properties.Add(Prop); ++Iterator; } auto ResponseJsonValue = USIOJConvert::ToSIOJsonValue(Response); bool bResponseNumNotZero = Response.Num() > 0; bool bNoFunctionParams = Properties.Num() == 0; bool bNullResponse = ResponseJsonValue->IsNull(); if (bNullResponse && bNoFunctionParams) { Target->ProcessEvent(Function, nullptr); return true; } else if (bResponseNumNotZero) { //function has too few params if (bNoFunctionParams) { UE_LOG(SocketIOLog, Warning, TEXT("CallFunctionByNameWithArguments: Function '%s' has too few parameters, callback parameters ignored : <%s>"), *FunctionName, *ResponseJsonValue->EncodeJson()); Target->ProcessEvent(Function, nullptr); return true; } struct FDynamicArgs { void* Arg01 = nullptr; USIOJsonValue* Arg02 = nullptr; }; //create the container FDynamicArgs Args = FDynamicArgs(); //add the full response array as second param Args.Arg02 = ResponseJsonValue; const FString& FirstParam = Properties[0]->GetCPPType(); auto FirstFJsonValue = Response[0]; //Is first param... //SIOJsonValue? if (FirstParam.Equals("USIOJsonValue*")) { //convenience wrapper, response is a single object USIOJsonValue* Value = NewObject<USIOJsonValue>(); Value->SetRootValue(FirstFJsonValue); Args.Arg01 = Value; Target->ProcessEvent(Function, &Args); return true; } //SIOJsonObject? else if (FirstParam.Equals("USIOJsonObject*")) { //convenience wrapper, response is a single object USIOJsonObject* ObjectValue = NewObject<USIOJsonObject>(); ObjectValue->SetRootObject(FirstFJsonValue->AsObject()); Args.Arg01 = ObjectValue; Target->ProcessEvent(Function, &Args); return true; } //String? else if (FirstParam.Equals("FString")) { FString StringValue = USIOJConvert::ToJsonString(FirstFJsonValue); Target->ProcessEvent(Function, &StringValue); return true; } //Float? else if (FirstParam.Equals("float")) { float NumberValue = (float)FirstFJsonValue->AsNumber(); Target->ProcessEvent(Function, &NumberValue); return true; } //Int? else if (FirstParam.Equals("int32")) { int NumberValue = (int)FirstFJsonValue->AsNumber(); Target->ProcessEvent(Function, &NumberValue); return true; } //bool? else if (FirstParam.Equals("bool")) { bool BoolValue = FirstFJsonValue->AsBool(); Target->ProcessEvent(Function, &BoolValue); return true; } //array? else if (FirstParam.Equals("TArray")) { UArrayProperty* ArrayProp = Cast<UArrayProperty>(Properties[0]); FString Inner; ArrayProp->GetCPPMacroType(Inner); //byte array is the only supported version if (Inner.Equals("uint8")) { TArray<uint8> Bytes = ResponseJsonValue->AsArray()[0]->AsBinary(); Target->ProcessEvent(Function, &Bytes); return true; } } } UE_LOG(SocketIOLog, Warning, TEXT("CallFunctionByNameWithArguments: Function '%s' signature not supported expected <%s>"), *FunctionName, *ResponseJsonValue->EncodeJson()); return false; }
bool ff::Value::Convert(Type type, Value **ppValue) const { assertRetVal(ppValue, false); *ppValue = nullptr; if (type == GetType()) { *ppValue = GetAddRef(const_cast<Value *>(this)); return true; } wchar_t buf[256]; switch (GetType()) { case Type::Null: switch (type) { case Type::String: CreateString(String(L"null"), ppValue); break; } break; case Type::Bool: switch (type) { case Type::Double: CreateDouble(AsBool() ? 1.0 : 0.0, ppValue); break; case Type::Float: CreateFloat(AsBool() ? 1.0f : 0.0f, ppValue); break; case Type::Int: CreateInt(AsBool() ? 1 : 0, ppValue); break; case Type::String: CreateString(AsBool() ? String(L"true") : String(L"false"), ppValue); break; } break; case Type::Double: switch (type) { case Type::Bool: CreateBool(AsDouble() != 0, ppValue); break; case Type::Float: CreateFloat((float)AsDouble(), ppValue); break; case Type::Int: CreateInt((int)AsDouble(), ppValue); break; case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"%g", AsDouble()); CreateString(String(buf), ppValue); break; } break; case Type::Float: switch (type) { case Type::Bool: CreateBool(AsFloat() != 0, ppValue); break; case Type::Double: CreateDouble((double)AsFloat(), ppValue); break; case Type::Int: CreateInt((int)AsFloat(), ppValue); break; case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"%g", AsFloat()); CreateString(String(buf), ppValue); break; } break; case Type::Int: switch (type) { case Type::Bool: CreateBool(AsInt() != 0, ppValue); break; case Type::Double: CreateDouble((double)AsInt(), ppValue); break; case Type::Float: CreateFloat((float)AsInt(), ppValue); break; case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"%d", AsInt()); CreateString(String(buf), ppValue); break; } break; case Type::Point: switch (type) { case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"(%d,%d)", AsPoint().x, AsPoint().y); CreateString(String(buf), ppValue); break; } break; case Type::PointF: switch (type) { case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"(%g,%g)", AsPointF().x, AsPointF().y); CreateString(String(buf), ppValue); break; } break; case Type::Rect: switch (type) { case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"(%d,%d,%d,%d)", AsRect().left, AsRect().top, AsRect().right, AsRect().bottom); CreateString(String(buf), ppValue); break; } break; case Type::RectF: switch (type) { case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"(%g,%g,%g,%g)", AsRectF().left, AsRectF().top, AsRectF().right, AsRectF().bottom); CreateString(String(buf), ppValue); break; } break; case Type::String: switch (type) { case Type::Bool: if (AsString().empty() || AsString() == L"false" || AsString() == L"no" || AsString() == L"0") { CreateBool(false, ppValue); } else if (AsString() == L"true" || AsString() == L"yes" || AsString() == L"1") { CreateBool(true, ppValue); } break; case Type::Double: { const wchar_t *start = AsString().c_str(); wchar_t *end = nullptr; double val = wcstod(start, &end); if (end > start && !*end) { CreateDouble(val, ppValue); } } break; case Type::Float: { const wchar_t *start = AsString().c_str(); wchar_t *end = nullptr; double val = wcstod(start, &end); if (end > start && !*end) { CreateFloat((float)val, ppValue); } } break; case Type::Int: { const wchar_t *start = AsString().c_str(); wchar_t *end = nullptr; long val = wcstol(start, &end, 10); if (end > start && !*end) { CreateInt((int)val, ppValue); } } break; case Type::Guid: { GUID guid; if (StringToGuid(AsString(), guid)) { CreateGuid(guid, ppValue); } } break; } break; case Type::Object: switch (type) { case Type::Bool: CreateBool(AsObject() != nullptr, ppValue); break; } break; case Type::Guid: switch (type) { case Type::String: CreateString(StringFromGuid(AsGuid()), ppValue); break; } break; case Type::Data: switch (type) { case Type::SavedData: { ff::ComPtr<ff::ISavedData> savedData; if (ff::CreateLoadedDataFromMemory(AsData(), false, &savedData)) { CreateSavedData(savedData, ppValue); } } break; } break; case Type::SavedData: switch (type) { case Type::Data: { ff::ComPtr<ff::ISavedData> savedData; if (AsSavedData()->Clone(&savedData)) { ff::ComPtr<ff::IData> data = savedData->Load(); if (data) { CreateData(data, ppValue); } } } break; } break; case Type::Dict: switch (type) { case Type::Data: case Type::SavedData: case Type::SavedDict: { ff::ComPtr<ff::IData> data; ff::ComPtr<ff::ISavedData> savedData; if (ff::SaveDict(AsDict(), true, false, &data)) { if (type == Type::Data) { CreateData(data, ppValue); } else if (ff::CreateLoadedDataFromMemory(data, true, &savedData)) { if (type == Type::SavedData) { CreateSavedData(savedData, ppValue); } else { CreateSavedDict(savedData, ppValue); } } } } break; } break; case Type::SavedDict: switch (type) { case Type::Data: { ff::ComPtr<ff::ISavedData> savedData; if (AsSavedData()->Clone(&savedData)) { ff::ComPtr<ff::IData> data = savedData->Load(); if (data) { CreateData(data, ppValue); } } } break; case Type::SavedData: CreateSavedData(AsSavedData(), ppValue); break; case Type::Dict: { ff::ComPtr<ff::ISavedData> savedData; if (AsSavedData()->Clone(&savedData)) { ff::ComPtr<ff::IData> data = savedData->Load(); ff::ComPtr<ff::IDataReader> dataReader; Dict dict; if (data && ff::CreateDataReader(data, 0, &dataReader) && ff::LoadDict(dataReader, dict)) { CreateDict(std::move(dict), ppValue); } } } break; } break; case Type::Resource: AsResource()->GetValue()->Convert(type, ppValue); break; case Type::IntVector: switch (type) { case Type::Point: if (AsIntVector().Size() == 2) { PointInt point( AsIntVector().GetAt(0), AsIntVector().GetAt(1)); CreatePoint(point, ppValue); } break; case Type::Rect: if (AsIntVector().Size() == 4) { RectInt rect( AsIntVector().GetAt(0), AsIntVector().GetAt(1), AsIntVector().GetAt(2), AsIntVector().GetAt(3)); CreateRect(rect, ppValue); } break; } break; case Type::FloatVector: switch (type) { case Type::PointF: if (AsFloatVector().Size() == 2) { PointFloat point( AsFloatVector().GetAt(0), AsFloatVector().GetAt(1)); CreatePointF(point, ppValue); } break; case Type::RectF: if (AsFloatVector().Size() == 4) { RectFloat rect( AsFloatVector().GetAt(0), AsFloatVector().GetAt(1), AsFloatVector().GetAt(2), AsFloatVector().GetAt(3)); CreateRectF(rect, ppValue); } break; } break; case Type::ValueVector: switch (type) { case Type::Point: if (AsValueVector().Size() == 2) { ValuePtr newValues[2]; const Vector<ValuePtr> &values = AsValueVector(); if (values[0]->Convert(Type::Int, &newValues[0]) && values[1]->Convert(Type::Int, &newValues[1])) { CreatePoint(PointInt(newValues[0]->AsInt(), newValues[1]->AsInt()), ppValue); } } break; case Type::PointF: if (AsValueVector().Size() == 2) { ValuePtr newValues[2]; const Vector<ValuePtr> &values = AsValueVector(); if (values[0]->Convert(Type::Float, &newValues[0]) && values[1]->Convert(Type::Float, &newValues[1])) { CreatePointF(PointFloat(newValues[0]->AsFloat(), newValues[1]->AsFloat()), ppValue); } } break; case Type::Rect: if (AsValueVector().Size() == 4) { ValuePtr newValues[4]; const Vector<ValuePtr> &values = AsValueVector(); if (values[0]->Convert(Type::Int, &newValues[0]) && values[1]->Convert(Type::Int, &newValues[1]) && values[2]->Convert(Type::Int, &newValues[2]) && values[3]->Convert(Type::Int, &newValues[3])) { CreateRect(RectInt( newValues[0]->AsInt(), newValues[1]->AsInt(), newValues[2]->AsInt(), newValues[3]->AsInt()), ppValue); } } break; case Type::RectF: if (AsValueVector().Size() == 4) { ValuePtr newValues[4]; const Vector<ValuePtr> &values = AsValueVector(); if (values[0]->Convert(Type::Float, &newValues[0]) && values[1]->Convert(Type::Float, &newValues[1]) && values[2]->Convert(Type::Float, &newValues[2]) && values[3]->Convert(Type::Float, &newValues[3])) { CreateRectF(RectFloat( newValues[0]->AsFloat(), newValues[1]->AsFloat(), newValues[2]->AsFloat(), newValues[3]->AsFloat()), ppValue); } } break; case Type::StringVector: { bool valid = true; Vector<String> newValues; const Vector<ValuePtr> &values = AsValueVector(); for (ValuePtr oldValue : values) { ValuePtr newValue; valid = oldValue->Convert(Type::String, &newValue); if (valid) { newValues.Push(newValue->AsString()); } else { break; } } if (valid) { CreateStringVector(std::move(newValues), ppValue); } } break; case Type::IntVector: { bool valid = true; Vector<int> newValues; const Vector<ValuePtr> &values = AsValueVector(); for (ValuePtr oldValue : values) { ValuePtr newValue; valid = oldValue->Convert(Type::Int, &newValue); if (valid) { newValues.Push(newValue->AsInt()); } else { break; } } if (valid) { CreateIntVector(std::move(newValues), ppValue); } } break; case Type::DoubleVector: { bool valid = true; Vector<double> newValues; const Vector<ValuePtr> &values = AsValueVector(); for (ValuePtr oldValue : values) { ValuePtr newValue; valid = oldValue->Convert(Type::Double, &newValue); if (valid) { newValues.Push(newValue->AsDouble()); } else { break; } } if (valid) { CreateDoubleVector(std::move(newValues), ppValue); } } break; case Type::FloatVector: { bool valid = true; Vector<float> newValues; const Vector<ValuePtr> &values = AsValueVector(); for (ValuePtr oldValue : values) { ValuePtr newValue; valid = oldValue->Convert(Type::Float, &newValue); if (valid) { newValues.Push(newValue->AsFloat()); } else { break; } } if (valid) { CreateFloatVector(std::move(newValues), ppValue); } } break; } break; } if (*ppValue) { return true; } return false; }
bool ff::Value::operator==(const Value &r) const { if (this == &r) { return true; } if (GetType() != r.GetType()) { return false; } switch (GetType()) { case Type::Null: return true; case Type::Bool: return AsBool() == r.AsBool(); case Type::Double: return AsDouble() == r.AsDouble(); case Type::Float: return AsFloat() == r.AsFloat(); case Type::Int: return AsInt() == r.AsInt(); case Type::Object: return AsObject() == r.AsObject(); case Type::Point: return AsPoint() == r.AsPoint(); case Type::PointF: return AsPointF() == r.AsPointF(); case Type::Rect: return AsRect() == r.AsRect(); case Type::RectF: return AsRectF() == r.AsRectF(); case Type::String: return AsString() == r.AsString(); case Type::StringVector: return AsStringVector() == r.AsStringVector(); case Type::ValueVector: return AsValueVector() == r.AsValueVector(); case Type::Guid: return AsGuid() == r.AsGuid() ? true : false; case Type::IntVector: return AsIntVector() == r.AsIntVector(); case Type::DoubleVector: return AsDoubleVector() == r.AsDoubleVector(); case Type::FloatVector: return AsFloatVector() == r.AsFloatVector(); case Type::DataVector: return AsDataVector() == r.AsDataVector(); case Type::Data: return AsData() == r.AsData(); case Type::SavedData: case Type::SavedDict: return AsSavedData() == r.AsSavedData(); default: assert(false); return false; } }