From db53935db95cc0beb4cd6ff79f2b74ce4bb837f7 Mon Sep 17 00:00:00 2001 From: jyelon Date: Wed, 4 Mar 2026 20:32:05 -0500 Subject: [PATCH] Refactors in UlxLuaValues, and add cursor-rewind to ReadLuaValues node. --- Source/Integration/Common.h | 7 ++ Source/Integration/LuaCall.cpp | 153 ++++++++++++------------------ Source/Integration/LuaCall.h | 30 ++---- Source/Integration/StreamBuffer.h | 3 +- 4 files changed, 79 insertions(+), 114 deletions(-) diff --git a/Source/Integration/Common.h b/Source/Integration/Common.h index 3cf0c0b4..5e54da52 100644 --- a/Source/Integration/Common.h +++ b/Source/Integration/Common.h @@ -11,6 +11,7 @@ #pragma once #include +#include "lpx-basebuffer.hpp" #include "Blueprint/UserWidget.h" #include "Common.generated.h" @@ -56,6 +57,12 @@ enum class ElxLuaValueType : uint8 { Vector }; +struct LuaValue : BaseLuaValue +{ + ElxLuaValueType GetElxType() const { return static_cast(type); } + void SetElxType(ElxLuaValueType t) { type = static_cast(t); } +}; + //////////////////////////////////////////////////////////// // // Branching Enums diff --git a/Source/Integration/LuaCall.cpp b/Source/Integration/LuaCall.cpp index 6f09e0ef..58eecde9 100644 --- a/Source/Integration/LuaCall.cpp +++ b/Source/Integration/LuaCall.cpp @@ -365,42 +365,23 @@ void UlxLuaCallLibrary::LuaCallArgument_boolean(UObject *context, bool pbool) { ///////////////////////////////////////////////////////////////// -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); + Values.Empty(); + Cursor = 0; + SavedCursor = 0; + FlxStreamBuffer Decoder(data); while (!Decoder.empty()) { - LuaValueType Tag = Decoder.read_lua_value_type(); - int64 Pos = Decoder.total_reads(); - ElxLuaValueType Type; - switch (Tag) + LuaValue Value; + Decoder.read_lua_value(&Value); + if (Decoder.any_error()) { - case LuaValueType::BOOLEAN: Type=ElxLuaValueType::Boolean; Decoder.read_bool(); break; - case LuaValueType::NUMBER: Type=ElxLuaValueType::Float; Decoder.read_double(); break; - case LuaValueType::STRING: Type=ElxLuaValueType::String; Decoder.read_string_view(); break; - case LuaValueType::TOKEN: Type=ElxLuaValueType::Name; Decoder.read_string_view(); break; - case LuaValueType::VECTOR: Type=ElxLuaValueType::Vector; Decoder.read_fvector(); break; - default: { - Empty(); - return false; - } + Values.Empty(); + return false; } - int64 Pos2 = Decoder.total_reads(); - Types.Add(Type); - Data.Add(std::string_view(SerializedChar + Pos, Pos2 - Pos)); + Values.Add(MoveTemp(Value)); } return true; } @@ -409,61 +390,49 @@ FString UlxLuaValues::DebugString() const { TStringBuilder<2048> Output; Output << TEXT("{ "); - for (int i = 0; i < Types.Num(); i++) + for (int i = 0; i < Values.Num(); i++) { if (i > 0) Output << TEXT(" "); - if (i == Cursor) Output << TEXT("^ "); - ElxLuaValueType Type = Types[i]; - FlxStreamBuffer Decoder(Data[i]); - switch (Type) + const auto &V = Values[i]; + switch (V.type) { - case ElxLuaValueType::Boolean: - Output << Decoder.read_bool(); + case LuaValueType::BOOLEAN: + Output << (V.x == 1.0); break; - case ElxLuaValueType::Float: - Output << FString::Printf(TEXT("%lf"), Decoder.read_double()); + case LuaValueType::NUMBER: + Output << FString::Printf(TEXT("%lf"), V.x); break; - case ElxLuaValueType::String: - Output << TEXT("\"") << Decoder.read_fstring() << TEXT("\""); + case LuaValueType::STRING: + Output << TEXT("\"") << FString(V.s.size(), (const UTF8CHAR *)V.s.data()) << TEXT("\""); break; - case ElxLuaValueType::Name: - Output << Decoder.read_fname(); + case LuaValueType::TOKEN: + Output << FString(V.s.size(), (const UTF8CHAR *)V.s.data()); break; - case ElxLuaValueType::Vector: { - FVector Vec = Decoder.read_fvector(); - Output << FString::Printf(TEXT("(%lf, %lf, %lf)"), Vec.X, Vec.Y, Vec.Z); + case LuaValueType::VECTOR: + Output << FString::Printf(TEXT("(%lf, %lf, %lf)"), V.x, V.y, V.z); + break; + default: + Output << TEXT("?"); break; - } } } Output << TEXT(" }"); return Output.ToString(); } -ElxSuccessOrWrongType UlxLuaValues::CheckType(ElxLuaValueType Type, ElxLuaValueType Desired) -{ - if (Type != Desired) - { - return ElxSuccessOrWrongType::WrongType; - } - return ElxSuccessOrWrongType::Success; -} - ElxLuaValueType UlxLuaValues::NextType() const { - if (Cursor < 0) return ElxLuaValueType::End; - if (Cursor >= Types.Num()) return ElxLuaValueType::End; - return Types[Cursor]; + if ((Cursor < 0) || (Cursor >= Values.Num())) return ElxLuaValueType::End; + return Values[Cursor].GetElxType(); } void UlxLuaValues::DiscardBeforeCursor() { if (Cursor > 0) { - Types.RemoveAt(0, Cursor); - Data.RemoveAt(0, Cursor); + Values.RemoveAt(0, Cursor); SavedCursor = FMath::Max(0, SavedCursor - Cursor); Cursor = 0; } @@ -471,79 +440,81 @@ void UlxLuaValues::DiscardBeforeCursor() void UlxLuaValues::ReadString(ElxSuccessOrWrongType &Status, FString &Result) { - Status = CheckType(NextType(), ElxLuaValueType::String); - if (Status == ElxSuccessOrWrongType::WrongType) + if (NextType() != ElxLuaValueType::String) { - Cursor = SavedCursor; Result.Empty(); return; + Status = WrongType; Cursor = SavedCursor; Result.Empty(); return; } - Result = FlxStreamBuffer(Data[Cursor++]).read_fstring(); + const auto &V = Values[Cursor++]; + Result = FString(V.s.size(), (const UTF8CHAR *)V.s.data()); + Status = Success; } void UlxLuaValues::ReadName(ElxSuccessOrWrongType &Status, FName &Result) { - Status = CheckType(NextType(), ElxLuaValueType::Name); - if (Status == ElxSuccessOrWrongType::WrongType) + if (NextType() != ElxLuaValueType::Name) { - Cursor = SavedCursor; Result = FName(); return; + Status = WrongType; Cursor = SavedCursor; Result = FName(); return; } - Result = FlxStreamBuffer(Data[Cursor++]).read_fname(); + const auto &V = Values[Cursor++]; + Result = FName(V.s.size(), (const UTF8CHAR *)V.s.data(), FNAME_Add); + Status = Success; } void UlxLuaValues::ReadFloat(ElxSuccessOrWrongType &Status, double &Result) { - Status = CheckType(NextType(), ElxLuaValueType::Float); - if (Status == ElxSuccessOrWrongType::WrongType) + if (NextType() != ElxLuaValueType::Float) { - Cursor = SavedCursor; Result = 0.0; return; + Status = WrongType; Cursor = SavedCursor; Result = 0.0; return; } - Result = FlxStreamBuffer(Data[Cursor++]).read_double(); + Result = Values[Cursor++].x; + Status = Success; } void UlxLuaValues::ReadInt(ElxSuccessOrWrongType &Status, int &Result) { - Status = CheckType(NextType(), ElxLuaValueType::Float); - if (Status == ElxSuccessOrWrongType::WrongType) + if (NextType() != ElxLuaValueType::Float) { - Cursor = SavedCursor; Result = 0; return; + Status = WrongType; Cursor = SavedCursor; Result = 0; return; } - double dvalue = FlxStreamBuffer(Data[Cursor++]).read_double(); + double dvalue = Values[Cursor++].x; Result = int(dvalue); if (double(Result) != dvalue) { - Status = ElxSuccessOrWrongType::WrongType; - Cursor = SavedCursor; Result = 0; return; + Status = WrongType; Cursor = SavedCursor; Result = 0; return; } + Status = Success; } void UlxLuaValues::ReadVector(ElxSuccessOrWrongType &Status, FVector &Result) { - Status = CheckType(NextType(), ElxLuaValueType::Vector); - if (Status == ElxSuccessOrWrongType::WrongType) + if (NextType() != ElxLuaValueType::Vector) { - Cursor = SavedCursor; Result = FVector(); return; + Status = WrongType; Cursor = SavedCursor; Result = FVector(); return; } - Result = FlxStreamBuffer(Data[Cursor++]).read_fvector(); + const auto &V = Values[Cursor++]; + Result = FVector(V.x, V.y, V.z); + Status = Success; } void UlxLuaValues::ReadVector2D(ElxSuccessOrWrongType &Status, FVector2D &Result) { - Status = CheckType(NextType(), ElxLuaValueType::Vector); - if (Status == ElxSuccessOrWrongType::WrongType) + if (NextType() != ElxLuaValueType::Vector) { - Cursor = SavedCursor; Result = FVector2D(); return; + Status = WrongType; Cursor = SavedCursor; Result = FVector2D(); return; } - FVector VValue = FlxStreamBuffer(Data[Cursor++]).read_fvector(); - Result = FVector2D(VValue.X, VValue.Y); + const auto &V = Values[Cursor++]; + Result = FVector2D(V.x, V.y); + Status = Success; } void UlxLuaValues::ReadBoolean(ElxSuccessOrWrongType &Status, bool &Result) { - Status = CheckType(NextType(), ElxLuaValueType::Boolean); - if (Status == ElxSuccessOrWrongType::WrongType) + if (NextType() != ElxLuaValueType::Boolean) { - Cursor = SavedCursor; Result = false; return; + Status = WrongType; Cursor = SavedCursor; Result = false; return; } - Result = FlxStreamBuffer(Data[Cursor++]).read_bool(); + Result = (Values[Cursor++].x == 1.0); + Status = Success; } FFormatArgumentData UlxLuaValues::FormatArgumentDataLuaValues(const UlxLuaValues *AutoConvertedValue, const FString &Name) diff --git a/Source/Integration/LuaCall.h b/Source/Integration/LuaCall.h index db6a4e5e..bc22fc23 100644 --- a/Source/Integration/LuaCall.h +++ b/Source/Integration/LuaCall.h @@ -19,6 +19,7 @@ #include #include #include "Kismet/BlueprintFunctionLibrary.h" +#include "Common.h" #include "LuaCall.generated.h" class UlxLuaValues; @@ -212,18 +213,9 @@ class INTEGRATION_API UlxLuaValues : public UObject GENERATED_BODY() private: - // The raw serialized data returned by Lua. + // The deserialized values. // - std::string Serialized; - - // For each chunk, the type of the chunk. - // - TArray Types; - - // For each chunk, a pointer to the serialized - // data. - // - TArray Data; + TArray Values; // The current cursor. // @@ -233,14 +225,8 @@ private: // int SavedCursor = 0; -private: - // Clear everything. - // - void Empty(); - - // Compare two types for equality. - // - static ElxSuccessOrWrongType CheckType(ElxLuaValueType Type, ElxLuaValueType Desired); + static const ElxSuccessOrWrongType WrongType = ElxSuccessOrWrongType::WrongType; + static const ElxSuccessOrWrongType Success = ElxSuccessOrWrongType::Success; public: UlxLuaValues() {} @@ -264,13 +250,13 @@ public: // Return the number of elements remaining after the cursor. // UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array") - int Length() const { return Types.Num() - Cursor; } + int Length() const { return Values.Num() - Cursor; } // Return the total number of elements, including both those // before and after the cursor. // UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array") - int TotalLength() const { return Types.Num(); } + int TotalLength() const { return Values.Num(); } // Get the current position of the cursor. // @@ -281,7 +267,7 @@ public: // be within the array. // UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array") - void SetCursor(int n) { Cursor = FMath::Clamp(n, 0, Types.Num()); } + void SetCursor(int n) { Cursor = FMath::Clamp(n, 0, Values.Num()); } // Get the type of the next element. // diff --git a/Source/Integration/StreamBuffer.h b/Source/Integration/StreamBuffer.h index c7398b67..e4da4bc5 100644 --- a/Source/Integration/StreamBuffer.h +++ b/Source/Integration/StreamBuffer.h @@ -1,5 +1,6 @@ #pragma once +#include "Common.h" #include "CoreMinimal.h" #include "lpx-basebuffer.hpp" @@ -12,7 +13,7 @@ public: using string_type = std::string; using fvector_type = FVector; using dvector_type = FVector; - using luavalue_type = BaseLuaValue; + using luavalue_type = LuaValue; void *basebuffer_malloc(size_t size) { return malloc(size); } void basebuffer_free(void *p) { free(p); } void clear_error_flags() { err_eof_on_read_ = err_string_too_long_ = err_integer_truncated_ = false; }