From 950d684f9a321e818aefce3f160fa280f6d91826 Mon Sep 17 00:00:00 2001 From: Sandu Liviu Catalin Date: Fri, 2 Apr 2021 19:12:06 +0300 Subject: [PATCH] Global wide switch to extended format support. --- module/Library/Format.cpp | 38 ++++++++++++++++++++++++++++++--- module/Library/Format.hpp | 5 +++++ module/Library/Utils/String.cpp | 25 ++++++++++++++++++++++ module/Library/Utils/String.hpp | 33 ++++++++++++++++++++++++++++ module/Sqrat/sqratUtil.h | 19 ++++++----------- 5 files changed, 104 insertions(+), 16 deletions(-) diff --git a/module/Library/Format.cpp b/module/Library/Format.cpp index 9791f2c8..4ca3f9d7 100644 --- a/module/Library/Format.cpp +++ b/module/Library/Format.cpp @@ -134,10 +134,11 @@ SQInteger FormatContext::Proc(HSQUIRRELVM vm, SQInteger text, SQInteger args, SQ if (SQ_FAILED(mRes)) { return mRes; - } + // Drop previous arguments, if any + } else mArgs.clear(); // Remember the format string and assume it lives on the stack fmt::basic_string_view< SQChar > f_str(s, static_cast< size_t >(i)); - // + // Process the arguments in the specified range for(SQInteger idx = args; SQ_SUCCEEDED(mRes) && idx <= end; ++idx) { switch(sq_gettype(vm, idx)) @@ -406,7 +407,38 @@ inline auto FormatObjectInContext(HSQUIRRELVM vm, SQInteger idx, SQInteger src, } // ------------------------------------------------------------------------------------------------ -SQInteger SqFormat(HSQUIRRELVM vm) +void ExtendedFormatProcess(StackStrF & ss, SQInteger top) +{ + FormatContext ctx; + // Attempt to perform the format + ss.mRes = ctx.Proc(ss.mVM, ss.mIdx, ss.mIdx + 1, top); + // Did format succeed? + if (SQ_SUCCEEDED(ss.mRes)) + { + // Transform the string into a script object + sq_pushstring(ss.mVM, ctx.mOut.data(), static_cast(ctx.mOut.size())); + // At this point we have a new object on the stack that must be removed + SqPopTopGuard spg(ss.mVM); + // Obtain a reference to the string object + ss.mRes = sq_getstackobj(ss.mVM, -1, &ss.mObj); + // Could we retrieve the object from the stack? + if (SQ_SUCCEEDED(ss.mRes)) + { + // Keep a strong reference to the object + sq_addref(ss.mVM, &ss.mObj); + // Attempt to retrieve the string value from the stack + ss.mRes = sq_getstringandsize(ss.mVM, -1, &ss.mPtr, &ss.mLen); + } + // Did the retrieval succeeded but ended up with a null string pointer? + if (SQ_SUCCEEDED(ss.mRes) && !ss.mPtr) + { + ss.mRes = sq_throwerror(ss.mVM, "Unable to retrieve the string"); + } + } +} + +// ------------------------------------------------------------------------------------------------ +static SQInteger SqFormat(HSQUIRRELVM vm) { FormatContext ctx; // Attempt to generate the formatted string diff --git a/module/Library/Format.hpp b/module/Library/Format.hpp index 81907b7a..77d85514 100644 --- a/module/Library/Format.hpp +++ b/module/Library/Format.hpp @@ -71,4 +71,9 @@ struct FormatContext SQMOD_NODISCARD SQInteger Proc(HSQUIRRELVM vm, SQInteger text, SQInteger args, SQInteger end = -1); }; +/* ------------------------------------------------------------------------------------------------ + * Helper function used to process a formatted string into the specified StackStrF instance. +*/ +void ExtendedFormatProcess(StackStrF & ss, SQInteger top); + } // Namespace:: SqMod diff --git a/module/Library/Utils/String.cpp b/module/Library/Utils/String.cpp index 418ea9ff..6734d5dd 100644 --- a/module/Library/Utils/String.cpp +++ b/module/Library/Utils/String.cpp @@ -1,5 +1,6 @@ // ------------------------------------------------------------------------------------------------ #include "Library/Utils/String.hpp" +#include "Library/Format.hpp" // ------------------------------------------------------------------------------------------------ namespace SqMod { @@ -7,6 +8,25 @@ namespace SqMod { // ------------------------------------------------------------------------------------------------ SQMOD_DECL_TYPENAME(Typename, _SC("SqString")) +// ------------------------------------------------------------------------------------------------ +static SQInteger SqStringFormat(HSQUIRRELVM vm) +{ + FormatContext ctx; + // Attempt to generate the formatted string + if (SQ_FAILED(ctx.Proc(vm, 2, 3, sq_gettop(vm)))) + { + return ctx.mRes; + } + // Create the instance and guard it to make sure it gets deleted in case of exceptions + DeleteGuard< SqString > instance(new SqString(std::move(ctx.mOut))); + // Push the instance on the stack + ClassType< SqString >::PushInstance(vm, instance); + // Stop guarding the instance + instance.Release(); + // Specify that we returned a value + return 1; +} + // ================================================================================================ void Register_Native_String(HSQUIRRELVM vm, Table & ns) { @@ -17,7 +37,9 @@ void Register_Native_String(HSQUIRRELVM vm, Table & ns) .Ctor< StackStrF & >() // Meta-methods .SquirrelFunc(_SC("_typename"), &Typename::Fn) + .Func(_SC("_tostring"), &SqString::GetString) // Properties + .Prop(_SC("Str"), &SqString::GetString, &SqString::SetString) .Prop(_SC("Front"), &SqString::Front) .Prop(_SC("Back"), &SqString::Back) .Prop(_SC("Empty"), &SqString::Empty) @@ -58,7 +80,10 @@ void Register_Native_String(HSQUIRRELVM vm, Table & ns) .Func(_SC("GenerateBetween"), &SqString::GenerateBetween) .Func(_SC("Sort"), &SqString::Sort) .Func(_SC("Shuffle"), &SqString::Shuffle) + .Func(_SC("Assign"), &SqString::SetString) ); + // -------------------------------------------------------------------------------------------- + RootTable(vm).SquirrelFunc(_SC("SqStringF"), SqStringFormat); } } // Namespace:: SqMod diff --git a/module/Library/Utils/String.hpp b/module/Library/Utils/String.hpp index 543c15d2..99f4c6f5 100644 --- a/module/Library/Utils/String.hpp +++ b/module/Library/Utils/String.hpp @@ -158,6 +158,39 @@ struct SqString return mS; } + /* -------------------------------------------------------------------------------------------- + * Retrieve the internal string container. + */ + SQMOD_NODISCARD String & ToString() + { + return mS; + } + + /* -------------------------------------------------------------------------------------------- + * Retrieve the internal string container. + */ + SQMOD_NODISCARD const String & ToString() const + { + return mS; + } + + /* -------------------------------------------------------------------------------------------- + * Retrieve the internal string container. + */ + SQMOD_NODISCARD const String & GetString() const + { + return mS; + } + + /* -------------------------------------------------------------------------------------------- + * Modify the internal string container. + */ + SQMOD_NODISCARD SqString & SetString(StackStrF & str) + { + mS.assign(str.mPtr, static_cast< size_t >(str.mLen)); + return *this; // Allow chaining + } + /* -------------------------------------------------------------------------------------------- * Retrieve a value from the container. */ diff --git a/module/Sqrat/sqratUtil.h b/module/Sqrat/sqratUtil.h index 4eff1c9b..25b51f37 100644 --- a/module/Sqrat/sqratUtil.h +++ b/module/Sqrat/sqratUtil.h @@ -39,6 +39,10 @@ #include +namespace SqMod { +extern void ExtendedFormatProcess(StackStrF & ss, SQInteger top); +} // Namespace:: SqMod + namespace Sqrat { #if defined(__GNUC__) @@ -1980,19 +1984,7 @@ struct StackStrF // Do we have enough values to call the format function and are we allowed to? else if (fmt && (top - 1) >= mIdx) { - // Pointer to the generated string - SQChar * str = nullptr; - // Attempt to generate the specified string format - mRes = sqstd_format(mVM, mIdx, &mLen, &str); - // Did the format succeeded but ended up with a null string pointer? - if (SQ_SUCCEEDED(mRes) && !str) - { - mRes = sq_throwerror(mVM, "Unable to generate the string"); - } - else - { - mPtr = const_cast< const SQChar * >(str); - } + ::SqMod::ExtendedFormatProcess(*this, top); } // Is the value on the stack an actual string? else if (sq_gettype(mVM, mIdx) == OT_STRING) @@ -2040,6 +2032,7 @@ struct StackStrF mRes = sq_throwerror(mVM, "Unable to retrieve the value"); } } + // Return last known result return mRes; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////