1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00

Locale based formatting support.

This commit is contained in:
Sandu Liviu Catalin 2021-04-20 18:19:58 +03:00
parent 0223621b75
commit 1969d1e624
2 changed files with 108 additions and 16 deletions

View File

@ -119,7 +119,7 @@ struct SqWeakReferenceFmt : public SqObjectFmt
};
// ------------------------------------------------------------------------------------------------
SQInteger FormatContext::Proc(HSQUIRRELVM vm, SQInteger text, SQInteger args, SQInteger end)
SQInteger FormatContext::Process(HSQUIRRELVM vm, SQInteger text, SQInteger args, SQInteger end)
{
// Is there any argument limit?
if (end < 0) end = sq_gettop(vm);
@ -137,7 +137,7 @@ SQInteger FormatContext::Proc(HSQUIRRELVM vm, SQInteger text, SQInteger args, SQ
// 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));
mStr = fmt::basic_string_view< SQChar >(s, static_cast< size_t >(i));
// Process the arguments in the specified range
for(SQInteger idx = args; SQ_SUCCEEDED(mRes) && idx <= end; ++idx)
{
@ -219,18 +219,6 @@ SQInteger FormatContext::Proc(HSQUIRRELVM vm, SQInteger text, SQInteger args, SQ
default: mRes = sq_throwerror(vm, "Unknown or unsupported object type");
}
}
// Attempt to generate the format string
if (SQ_SUCCEEDED(mRes))
{
try
{
mOut = fmt::vformat(f_str, mArgs);
}
catch (const std::exception & e)
{
mRes = sq_throwerror(vm, e.what());
}
}
// Return result
return mRes;
}
@ -440,9 +428,44 @@ void ExtendedFormatProcess(StackStrF & ss, SQInteger top)
// ------------------------------------------------------------------------------------------------
static SQInteger SqFormat(HSQUIRRELVM vm)
{
const SQInteger top = sq_gettop(vm);
// Make sure we have enough parameters
if (top < 2)
{
return sq_throwerror(vm, "Insufficient parameters");
}
FormatContext ctx;
// Attempt to generate the formatted string
if (SQ_FAILED(ctx.Proc(vm, 2, 3, sq_gettop(vm))))
if (SQ_FAILED(ctx.Proc(vm, 2, 3, top)) || SQ_FAILED(ctx.Generate(vm)))
{
return ctx.mRes;
}
// Push it on the stack
sq_pushstring(vm, ctx.mOut.data(), static_cast< SQInteger >(ctx.mOut.size()));
// Specify that we returned a value
return 1;
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqLocaleFormat(HSQUIRRELVM vm)
{
const SQInteger top = sq_gettop(vm);
// Make sure we have enough parameters
if (top < 3)
{
return sq_throwerror(vm, "Insufficient parameters");
}
StackStrF loc(vm, 2);
// Attempt to generate the locale string
if (SQ_FAILED(loc.Proc(false)))
{
return loc.mRes;
}
FormatContext ctx;
// Attempt to generate the formatted string
if (SQ_FAILED(ctx.Proc(vm, 3, 4, top)) || SQ_FAILED(ctx.GenerateLoc(vm, loc.mPtr)))
{
return ctx.mRes;
}
@ -456,6 +479,7 @@ static SQInteger SqFormat(HSQUIRRELVM vm)
void Register_Format(HSQUIRRELVM vm)
{
RootTable(vm).SquirrelFunc(_SC("fmt"), SqFormat);
RootTable(vm).SquirrelFunc(_SC("locale_fmt"), SqLocaleFormat);
}
} // Namespace:: SqMod

View File

@ -6,6 +6,7 @@
// ------------------------------------------------------------------------------------------------
#include <fmt/args.h>
#include <fmt/format.h>
#include <fmt/locale.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
@ -30,6 +31,11 @@ struct FormatContext
*/
SQInteger mRes{SQ_OK};
/* --------------------------------------------------------------------------------------------
* Format string.
*/
fmt::basic_string_view< SQChar > mStr{};
/* --------------------------------------------------------------------------------------------
* Output string buffer.
*/
@ -68,7 +74,69 @@ struct FormatContext
/* --------------------------------------------------------------------------------------------
* Process the formatted string.
*/
SQMOD_NODISCARD SQInteger Proc(HSQUIRRELVM vm, SQInteger text, SQInteger args, SQInteger end = -1);
SQMOD_NODISCARD SQInteger Proc(HSQUIRRELVM vm, SQInteger text, SQInteger args, SQInteger end = -1)
{
if (SQ_SUCCEEDED(Process(vm, text, args, end)))
{
try
{
mOut = fmt::vformat(mStr, mArgs);
}
catch (const std::exception & e)
{
mRes = sq_throwerror(vm, e.what());
}
}
// Return result
return mRes;
}
/* --------------------------------------------------------------------------------------------
* Process the formatted string.
*/
SQMOD_NODISCARD SQInteger Process(HSQUIRRELVM vm, SQInteger text, SQInteger args, SQInteger end = -1);
/* --------------------------------------------------------------------------------------------
* Process the formatted string.
*/
SQMOD_NODISCARD SQInteger Generate(HSQUIRRELVM vm)
{
// Attempt to generate the format string
if (SQ_SUCCEEDED(mRes))
{
try
{
mOut = fmt::vformat(mStr, mArgs);
}
catch (const std::exception & e)
{
mRes = sq_throwerror(vm, e.what());
}
}
// Return result
return mRes;
}
/* --------------------------------------------------------------------------------------------
* Process the formatted string.
*/
SQMOD_NODISCARD SQInteger GenerateLoc(HSQUIRRELVM vm, const SQChar * loc)
{
// Attempt to generate the format string
if (SQ_SUCCEEDED(mRes))
{
try
{
mOut = fmt::vformat(std::locale(loc), mStr, mArgs);
}
catch (const std::exception & e)
{
mRes = sq_throwerror(vm, e.what());
}
}
// Return result
return mRes;
}
};
/* ------------------------------------------------------------------------------------------------