#include "StringDecoder.h" void UlxLuaValues::Empty() { Serialized.clear(); Types.Empty(); Data.Empty(); Cursor = 0; } bool UlxLuaValues::Initialize(std::string_view data) { Empty(); Serialized = data; const char *SerializedChar = &Serialized[0]; FlxStreamBuffer Decoder(Serialized); while (!Decoder.empty()) { SimpleDynamicTag Tag = Decoder.read_simple_dynamic_tag(); int64 Pos = Decoder.total_reads(); ElxLuaValueType Type; switch (Tag) { case SimpleDynamicTag::BOOLEAN: Type=ElxLuaValueType::Boolean; Decoder.read_bool(); break; case SimpleDynamicTag::NUMBER: Type=ElxLuaValueType::Float; Decoder.read_double(); break; case SimpleDynamicTag::STRING: Type=ElxLuaValueType::String; Decoder.read_string_view(); break; case SimpleDynamicTag::TOKEN: Type=ElxLuaValueType::Name; Decoder.read_string_view(); break; case SimpleDynamicTag::VECTOR: Type=ElxLuaValueType::Vector; Decoder.read_fvector(); break; default: { Empty(); return false; } } int64 Pos2 = Decoder.total_reads(); Types.Add(Type); Data.Add(std::string_view(SerializedChar + Pos, Pos2 - Pos)); } return true; } FString UlxLuaValues::DebugString() const { TStringBuilder<2048> Output; Output << TEXT("{ "); for (int i = 0; i < Types.Num(); i++) { if (i > 0) Output << TEXT(", "); ElxLuaValueType Type = Types[i]; FlxStreamBuffer Decoder(Data[i]); switch (Type) { case ElxLuaValueType::Boolean: Output << Decoder.read_bool(); break; case ElxLuaValueType::Float: Output << FString::Printf(TEXT("%lf"), Decoder.read_double()); break; case ElxLuaValueType::String: Output << TEXT("\"") << Decoder.read_fstring() << TEXT("\""); break; case ElxLuaValueType::Name: Output << Decoder.read_fname(); break; case ElxLuaValueType::Vector: { FVector Vec = Decoder.read_fvector(); Output << FString::Printf(TEXT("(%lf, %lf, %lf)"), Vec.X, Vec.Y, Vec.Z); break; } } } Output << TEXT(" }"); return Output.ToString(); } bool UlxLuaValues::CheckType(ElxLuaValueType Type, ElxLuaValueType Desired) { if (Type != Desired) { FString TypeName = StaticEnum()->GetDisplayNameTextByValue(int64(Type)).ToString(); FString DesiredName = StaticEnum()->GetDisplayNameTextByValue(int64(Desired)).ToString(); UE_LOG(LogBlueprint, Error, TEXT("Expected a value of type %s, but found %s instead."), *DesiredName, *TypeName); return false; } return true; } ElxLuaValueType UlxLuaValues::GetType(int n) const { if (n < 0) return ElxLuaValueType::None; if (n >= Types.Num()) return ElxLuaValueType::None; return Types[Cursor]; } // // Get the Nth value in the array. Array bounds-checking // is handled by 'GetType', which returns 'None' for out-of-bounds // accesses. // FString UlxLuaValues::GetString(int n) const { if (!CheckType(GetType(n), ElxLuaValueType::String)) return FString(); FlxStreamBuffer Decoder(Data[n]); return Decoder.read_fstring(); } FName UlxLuaValues::GetName(int n) const { if (!CheckType(GetType(n), ElxLuaValueType::Name)) return FName(); FlxStreamBuffer Decoder(Data[n]); return Decoder.read_fname(); } double UlxLuaValues::GetFloat(int n) const { if (!CheckType(GetType(n), ElxLuaValueType::Float)) return 0.0; FlxStreamBuffer Decoder(Data[n]); return Decoder.read_double(); } int UlxLuaValues::GetInt(int n) const { if (!CheckType(GetType(n), ElxLuaValueType::Float)) return 0; FlxStreamBuffer Decoder(Data[n]); return int(Decoder.read_double()); } FVector UlxLuaValues::GetVector(int n) const { if (!CheckType(GetType(n), ElxLuaValueType::Vector)) return FVector(); FlxStreamBuffer Decoder(Data[n]); return Decoder.read_fvector(); } FVector2D UlxLuaValues::GetVector2D(int n) const { if (!CheckType(GetType(n), ElxLuaValueType::Vector)) return FVector2D(); FlxStreamBuffer Decoder(Data[n]); FVector v = Decoder.read_fvector(); return FVector2D(v.X, v.Y); } bool UlxLuaValues::GetBoolean(int n) const { if (!CheckType(GetType(n), ElxLuaValueType::Boolean)) return false; FlxStreamBuffer Decoder(Data[n]); return Decoder.read_bool(); }