// ------------------------------------------------------------------------------------------------ #include "Base/Utility.hpp" #include "Base/Buffer.hpp" // ------------------------------------------------------------------------------------------------ #include #include #include #include #include #include // ------------------------------------------------------------------------------------------------ #ifdef SQMOD_OS_WINDOWS #include #endif // SQMOD_OS_WINDOWS // ------------------------------------------------------------------------------------------------ #ifndef SQMOD_PLUGIN_API #include "Library/Numeric/LongInt.hpp" #include #endif // SQMOD_PLUGIN_API // ------------------------------------------------------------------------------------------------ namespace SqMod { // ------------------------------------------------------------------------------------------------ PluginFuncs* _Func = nullptr; PluginCallbacks* _Clbk = nullptr; PluginInfo* _Info = nullptr; // ------------------------------------------------------------------------------------------------ #ifdef SQMOD_PLUGIN_API HSQAPI _SqAPI = nullptr; HSQEXPORTS _SqMod = nullptr; HSQUIRRELVM _SqVM = nullptr; #endif // SQMOD_PLUGIN_API /* ------------------------------------------------------------------------------------------------ * Common buffers to reduce memory allocations. To be immediately copied upon return! */ static SQChar g_Buffer[4096]; static SQChar g_NumBuf[1024]; // ------------------------------------------------------------------------------------------------ SStr GetTempBuff() { return g_Buffer; } // ------------------------------------------------------------------------------------------------ Uint32 GetTempBuffSize() { return sizeof(g_Buffer); } /* -------------------------------------------------------------------------------------------- * Raw console message output. */ static inline void OutputMessageImpl(CCStr msg, va_list args) { #ifdef SQMOD_OS_WINDOWS HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csb_before; GetConsoleScreenBufferInfo( hstdout, &csb_before); SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN); std::printf("[SQMOD] "); SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY); std::vprintf(msg, args); std::puts(""); SetConsoleTextAttribute(hstdout, csb_before.wAttributes); #else std::printf("\033[21;32m[SQMOD]\033[0m"); std::vprintf(msg, args); std::puts(""); #endif // SQMOD_OS_WINDOWS } /* -------------------------------------------------------------------------------------------- * Raw console error output. */ static inline void OutputErrorImpl(CCStr msg, va_list args) { #ifdef SQMOD_OS_WINDOWS HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csb_before; GetConsoleScreenBufferInfo( hstdout, &csb_before); SetConsoleTextAttribute(hstdout, FOREGROUND_RED | FOREGROUND_INTENSITY); std::printf("[SQMOD] "); SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY); std::vprintf(msg, args); std::puts(""); SetConsoleTextAttribute(hstdout, csb_before.wAttributes); #else std::printf("\033[21;91m[SQMOD]\033[0m"); std::vprintf(msg, args); std::puts(""); #endif // SQMOD_OS_WINDOWS } // -------------------------------------------------------------------------------------------- void OutputDebug(CCStr msg, ...) { #ifdef _DEBUG // Initialize the arguments list va_list args; va_start(args, msg); // Call the output function OutputMessageImpl(msg, args); // Finalize the arguments list va_end(args); #else SQMOD_UNUSED_VAR(msg); #endif } // -------------------------------------------------------------------------------------------- void OutputMessage(CCStr msg, ...) { // Initialize the arguments list va_list args; va_start(args, msg); // Call the output function OutputMessageImpl(msg, args); // Finalize the arguments list va_end(args); } // -------------------------------------------------------------------------------------------- void OutputError(CCStr msg, ...) { // Initialize the arguments list va_list args; va_start(args, msg); // Call the output function OutputErrorImpl(msg, args); // Finalize the arguments list va_end(args); } // ------------------------------------------------------------------------------------------------ void SqThrowF(CSStr str, ...) { // Initialize the argument list va_list args; va_start (args, str); // Write the requested contents if (std::vsnprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0) { // Write a generic message at least std::strcpy(g_Buffer, "Unknown error has occurred"); } // Finalize the argument list va_end(args); // Throw the exception with the resulted message throw Sqrat::Exception(g_Buffer); } // ------------------------------------------------------------------------------------------------ CSStr FmtStr(CSStr str, ...) { // Initialize the argument list va_list args; va_start (args, str); // Write the requested contents if (std::vsnprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0) { STHROWF("Failed to run the specified string format"); } // Finalize the argument list va_end(args); // Return the data from the buffer return g_Buffer; } // ------------------------------------------------------------------------------------------------ CSStr ToStrF(CSStr str, ...) { // Prepare the arguments list va_list args; va_start(args, str); // Write the requested contents if (std::vsnprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0) { g_Buffer[0] = '\0'; // Make sure the string is null terminated } // Finalize the argument list va_end(args); // Return the resulted string return g_Buffer; } // ------------------------------------------------------------------------------------------------ CSStr ToStringF(CSStr str, ...) { // Acquire a moderately sized buffer Buffer b(128); // Prepare the arguments list va_list args; va_start (args, str); // Attempt to run the specified format if (b.WriteF(0, str, args) == 0) { b.At(0) = '\0'; // Make sure the string is null terminated } // Finalize the argument list va_end(args); // Return the resulted string return b.Get< SQChar >(); } // ------------------------------------------------------------------------------------------------ bool SToB(CSStr str) { // Temporary buffer to store the lowercase string SQChar buffer[8]; // The currently processed character unsigned i = 0; // Convert only the necessary characters to lowercase while (i < 7 && *str != '\0') { buffer[i++] = static_cast< SQChar >(std::tolower(*(str++))); } // Add the null terminator buffer[i] = '\0'; // Compare the lowercase string and return the result return (std::strcmp(buffer, "true") == 0 || std::strcmp(buffer, "yes") == 0 || std::strcmp(buffer, "on") == 0 || std::strcmp(buffer, "1") == 0) ? true : false; } // ------------------------------------------------------------------------------------------------ Object & NullObject() { static Object o; o.Release(); return o; } // ------------------------------------------------------------------------------------------------ Table & NullTable() { static Table t; t.Release(); return t; } // ------------------------------------------------------------------------------------------------ Array & NullArray() { static Array a; a.Release(); return a; } // ------------------------------------------------------------------------------------------------ Function & NullFunction() { static Function f; f.Release(); return f; } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Int8 >::ToStr(Int8 v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%d", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } Int8 ConvNum< Int8 >::FromStr(CSStr s) { return ConvTo< Int8 >::From(std::strtol(s, nullptr, 10)); } Int8 ConvNum< Int8 >::FromStr(CSStr s, Int32 base) { return ConvTo< Int8 >::From(std::strtol(s, nullptr, base)); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Uint8 >::ToStr(Uint8 v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%u", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } Uint8 ConvNum< Uint8 >::FromStr(CSStr s) { return ConvTo< Uint8 >::From(std::strtoul(s, nullptr, 10)); } Uint8 ConvNum< Uint8 >::FromStr(CSStr s, Int32 base) { return ConvTo< Uint8 >::From(std::strtoul(s, nullptr, base)); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Int16 >::ToStr(Int16 v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%d", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } Int16 ConvNum< Int16 >::FromStr(CSStr s) { return ConvTo< Int16 >::From(std::strtol(s, nullptr, 10)); } Int16 ConvNum< Int16 >::FromStr(CSStr s, Int32 base) { return ConvTo< Int16 >::From(std::strtol(s, nullptr, base)); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Uint16 >::ToStr(Uint16 v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%u", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } Uint16 ConvNum< Uint16 >::FromStr(CSStr s) { return ConvTo< Uint16 >::From(std::strtoul(s, nullptr, 10)); } Uint16 ConvNum< Uint16 >::FromStr(CSStr s, Int32 base) { return ConvTo< Uint16 >::From(std::strtoul(s, nullptr, base)); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Int32 >::ToStr(Int32 v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%d", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } Int32 ConvNum< Int32 >::FromStr(CSStr s) { return ConvTo< Int32 >::From(std::strtol(s, nullptr, 10)); } Int32 ConvNum< Int32 >::FromStr(CSStr s, Int32 base) { return ConvTo< Int32 >::From(std::strtol(s, nullptr, base)); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Uint32 >::ToStr(Uint32 v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%u", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } Uint32 ConvNum< Uint32 >::FromStr(CSStr s) { return ConvTo< Uint32 >::From(std::strtoul(s, nullptr, 10)); } Uint32 ConvNum< Uint32 >::FromStr(CSStr s, Int32 base) { return ConvTo< Uint32 >::From(std::strtoul(s, nullptr, base)); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Int64 >::ToStr(Int64 v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%lld", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } Int64 ConvNum< Int64 >::FromStr(CSStr s) { return std::strtoll(s, nullptr, 10); } Int64 ConvNum< Int64 >::FromStr(CSStr s, Int32 base) { return std::strtoll(s, nullptr, base); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Uint64 >::ToStr(Uint64 v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%llu", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } Uint64 ConvNum< Uint64 >::FromStr(CSStr s) { return std::strtoull(s, nullptr, 10); } Uint64 ConvNum< Uint64 >::FromStr(CSStr s, Int32 base) { return std::strtoull(s, nullptr, base); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< LongI >::ToStr(LongI v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%ld", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } LongI ConvNum< LongI >::FromStr(CSStr s) { return std::strtol(s, nullptr, 10); } LongI ConvNum< LongI >::FromStr(CSStr s, Int32 base) { return std::strtol(s, nullptr, base); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Ulong >::ToStr(Ulong v) { // Write the numeric value to the buffer if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%lu", v) < 0) { g_NumBuf[0] = '\0'; } // Return the beginning of the buffer return g_NumBuf; } Ulong ConvNum< Ulong >::FromStr(CSStr s) { return std::strtoul(s, nullptr, 10); } Ulong ConvNum< Ulong >::FromStr(CSStr s, Int32 base) { return std::strtoul(s, nullptr, base); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Float32 >::ToStr(Float32 v) { // Attempt to convert the value to a string if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%f", v) < 0) { g_NumBuf[0] = '\0'; } // Return the data from the buffer return g_NumBuf; } Float32 ConvNum< Float32 >::FromStr(CSStr s) { return std::strtof(s, nullptr); } Float32 ConvNum< Float32 >::FromStr(CSStr s, Int32 /*base*/) { return std::strtof(s, nullptr); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< Float64 >::ToStr(Float64 v) { // Attempt to convert the value to a string if (std::snprintf(g_NumBuf, sizeof(g_NumBuf), "%f", v) < 0) { g_NumBuf[0] = '\0'; } // Return the data from the buffer return g_NumBuf; } Float64 ConvNum< Float64 >::FromStr(CSStr s) { return std::strtod(s, nullptr); } Float64 ConvNum< Float64 >::FromStr(CSStr s, Int32 /*base*/) { return std::strtod(s, nullptr); } // ------------------------------------------------------------------------------------------------ CSStr ConvNum< bool >::ToStr(bool v) { if (v) { g_NumBuf[0] = 't'; g_NumBuf[1] = 'r'; g_NumBuf[2] = 'u'; g_NumBuf[3] = 'e'; g_NumBuf[4] = '\0'; } else { g_NumBuf[0] = 'f'; g_NumBuf[1] = 'a'; g_NumBuf[2] = 'l'; g_NumBuf[3] = 's'; g_NumBuf[4] = 'e'; g_NumBuf[5] = '\0'; } return g_NumBuf; } bool ConvNum< bool >::FromStr(CSStr s) { return (std::strcmp(s, "true") == 0) ? true : false; } bool ConvNum< bool >::FromStr(CSStr s, Int32 /*base*/) { return (std::strcmp(s, "true") == 0) ? true : false; } // -------------------------------------------------------------------------------------------- StackStrF::StackStrF(HSQUIRRELVM vm, SQInteger idx, bool fmt) : mPtr(nullptr) , mLen(-1) , mRes(SQ_OK) , mObj() , mVM(vm) { const Int32 top = sq_gettop(vm); // Reset the converted value object sq_resetobject(&mObj); // Was the string or value specified? if (top <= (idx - 1)) { mRes = sq_throwerror(vm, "Missing string or value"); } // Do we have enough values to call the format function and are we allowed to? else if (top > idx && fmt) { // Pointer to the generated string SStr str = nullptr; // Attempt to generate the specified string format mRes = sqstd_format(vm, idx, &mLen, &str); // Did the format succeeded but ended up with a null string pointer? if (SQ_SUCCEEDED(mRes) && !str) { mRes = sq_throwerror(vm, "Unable to generate the string"); } else { mPtr = const_cast< CSStr >(str); } } // Is the value on the stack an actual string? else if (sq_gettype(vm, idx) == OT_STRING) { // Obtain a reference to the string object mRes = sq_getstackobj(vm, idx, &mObj); // Could we retrieve the object from the stack? if (SQ_SUCCEEDED(mRes)) { // Keep a strong reference to the object sq_addref(vm, &mObj); // Attempt to retrieve the string value from the stack mRes = sq_getstring(vm, idx, &mPtr); } // Did the retrieval succeeded but ended up with a null string pointer? if (SQ_SUCCEEDED(mRes) && !mPtr) { mRes = sq_throwerror(vm, "Unable to retrieve the string"); } } // We have to try and convert it to string else { // Attempt to convert the value from the stack to a string mRes = sq_tostring(vm, idx); // Could we convert the specified value to string? if (SQ_SUCCEEDED(mRes)) { // Obtain a reference to the resulted object mRes = sq_getstackobj(vm, -1, &mObj); // Could we retrieve the object from the stack? if (SQ_SUCCEEDED(mRes)) { // Keep a strong reference to the object sq_addref(vm, &mObj); // Attempt to obtain the string pointer mRes = sq_getstring(vm, -1, &mPtr); } } // Pop a value from the stack regardless of the result sq_pop(vm, 1); // Did the retrieval succeeded but ended up with a null string pointer? if (SQ_SUCCEEDED(mRes) && !mPtr) { mRes = sq_throwerror(vm, "Unable to retrieve the value"); } } } // ------------------------------------------------------------------------------------------------ StackStrF::~StackStrF() { if (mVM && !sq_isnull(mObj)) { sq_release(mVM, &mObj); } } // ------------------------------------------------------------------------------------------------ Object BufferToStrObj(const Buffer & b) { // Obtain the initial stack size const StackGuard sg(DefaultVM::Get()); // Push the string onto the stack sq_pushstring(DefaultVM::Get(), b.Data(), b.Position()); // Obtain the object from the stack and return it return Var< Object >(DefaultVM::Get(), -1).value; } // -------------------------------------------------------------------------------------------- Object BufferToStrObj(const Buffer & b, Uint32 size) { // Perform a range check on the specified buffer if (size > b.Capacity()) { STHROWF("The specified buffer size is out of range: %u >= %u", size, b.Capacity()); } // Obtain the initial stack size const StackGuard sg(DefaultVM::Get()); // Push the string onto the stack sq_pushstring(DefaultVM::Get(), b.Data(), size); // Obtain the object from the stack and return it return Var< Object >(DefaultVM::Get(), -1).value; } // ------------------------------------------------------------------------------------------------ Object MakeSLongObj(Int64 val) { // Obtain the default virtual machine HSQUIRRELVM vm = DefaultVM::Get(); // Obtain the initial stack size const StackGuard sg(vm); #ifdef SQMOD_PLUGIN_API // Push a long integer instance with the requested value on the stack _SqMod->PushSLongObject(vm, val); #else // Transform the specified value into a script object PushVar< SLongInt >(vm, SLongInt(val)); #endif // SQMOD_PLUGIN_API // Obtain the object from the stack and return it return Var< Object >(vm, -1).value; } // ------------------------------------------------------------------------------------------------ Object MakeULongObj(Uint64 val) { // Obtain the default virtual machine HSQUIRRELVM vm = DefaultVM::Get(); // Obtain the initial stack size const StackGuard sg(vm); #ifdef SQMOD_PLUGIN_API // Push a long integer instance with the requested value on the stack _SqMod->PushULongObject(vm, val); #else // Transform the specified value into a script object PushVar< ULongInt >(vm, ULongInt(val)); #endif // SQMOD_PLUGIN_API // Obtain the object from the stack and return it return Var< Object >(vm, -1).value; } // ------------------------------------------------------------------------------------------------ Object MakeSLongObj(HSQUIRRELVM vm, Int64 val) { // Obtain the initial stack size const StackGuard sg(vm); #ifdef SQMOD_PLUGIN_API // Push a long integer instance with the requested value on the stack _SqMod->PushSLongObject(vm, val); #else // Transform the specified value into a script object PushVar< SLongInt >(vm, SLongInt(val)); #endif // SQMOD_PLUGIN_API // Obtain the object from the stack and return it return Var< Object >(vm, -1).value; } // ------------------------------------------------------------------------------------------------ Object MakeULongObj(HSQUIRRELVM vm, Uint64 val) { // Obtain the initial stack size const StackGuard sg(vm); #ifdef SQMOD_PLUGIN_API // Push a long integer instance with the requested value on the stack _SqMod->PushULongObject(vm, val); #else // Transform the specified value into a script object PushVar< ULongInt >(vm, ULongInt(val)); #endif // SQMOD_PLUGIN_API // Obtain the object from the stack and return it return Var< Object >(vm, -1).value; } // ------------------------------------------------------------------------------------------------ Int64 FetchSLongObjVal(Object & val) { // Obtain the initial stack size const StackGuard sg(DefaultVM::Get()); // Push the specified object onto the stack Var< Object & >::push(DefaultVM::Get(), val); // Retrieve and return the object value from the stack return PopStackSLong(DefaultVM::Get(), -1); } // ------------------------------------------------------------------------------------------------ Uint64 FetchULongObjVal(Object & val) { // Obtain the initial stack size const StackGuard sg(DefaultVM::Get()); // Push the specified object onto the stack Var< Object & >::push(DefaultVM::Get(), val); // Retrieve and return the object value from the stack return PopStackSLong(DefaultVM::Get(), -1); } // ------------------------------------------------------------------------------------------------ Int64 FetchSLongObjVal(HSQUIRRELVM vm, Object & val) { // Obtain the initial stack size const StackGuard sg(vm); // Push the specified object onto the stack Var< Object & >::push(vm, val); // Retrieve and return the object value from the stack return PopStackSLong(vm, -1); } // ------------------------------------------------------------------------------------------------ Uint64 FetchULongObjVal(HSQUIRRELVM vm, Object & val) { // Obtain the initial stack size const StackGuard sg(vm); // Push the specified object onto the stack Var< Object & >::push(vm, val); // Retrieve and return the object value from the stack return PopStackSLong(vm, -1); } // ------------------------------------------------------------------------------------------------ SQInteger PopStackInteger(HSQUIRRELVM vm, SQInteger idx) { #ifdef SQMOD_PLUGIN_API return _SqMod->PopStackInteger(vm, idx); #else // Identify which type must be extracted switch (sq_gettype(vm, idx)) { case OT_INTEGER: { SQInteger val; sq_getinteger(vm, idx, &val); return val; } break; case OT_FLOAT: { SQFloat val; sq_getfloat(vm, idx, &val); return ConvTo< SQInteger >::From(val); } break; case OT_BOOL: { SQBool val; sq_getbool(vm, idx, &val); return static_cast< SQInteger >(val); } break; case OT_STRING: { CSStr val = nullptr; // Attempt to retrieve and convert the string if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0') { return ConvTo< SQInteger >::From(std::strtoll(val, nullptr, 10)); } } break; case OT_ARRAY: case OT_TABLE: case OT_CLASS: case OT_USERDATA: { return sq_getsize(vm, idx); } break; case OT_INSTANCE: { // Attempt to treat the value as a signed long instance try { return ConvTo< SQInteger >::From(Var< const SLongInt & >(vm, idx).value.GetNum()); } catch (...) { // Just ignore it... } // Attempt to treat the value as a unsigned long instance try { return ConvTo< SQInteger >::From(Var< const ULongInt & >(vm, idx).value.GetNum()); } catch (...) { // Just ignore it... } // Attempt to get the size of the instance as a fallback return sq_getsize(vm, idx); } break; default: break; } // Default to 0 return 0; #endif // SQMOD_PLUGIN_API } // ------------------------------------------------------------------------------------------------ SQFloat PopStackFloat(HSQUIRRELVM vm, SQInteger idx) { #ifdef SQMOD_PLUGIN_API return _SqMod->PopStackFloat(vm, idx); #else // Identify which type must be extracted switch (sq_gettype(vm, idx)) { case OT_FLOAT: { SQFloat val; sq_getfloat(vm, idx, &val); return val; } break; case OT_INTEGER: { SQInteger val; sq_getinteger(vm, idx, &val); return ConvTo< SQFloat >::From(val); } break; case OT_BOOL: { SQBool val; sq_getbool(vm, idx, &val); return ConvTo< SQFloat >::From(val); } break; case OT_STRING: { CSStr val = nullptr; // Attempt to retrieve and convert the string if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0') { #ifdef SQUSEDOUBLE return std::strtod(val, nullptr); #else return std::strtof(val, nullptr); #endif // SQUSEDOUBLE } } break; case OT_ARRAY: case OT_TABLE: case OT_CLASS: case OT_USERDATA: { return ConvTo< SQFloat >::From(sq_getsize(vm, idx)); } break; case OT_INSTANCE: { // Attempt to treat the value as a signed long instance try { return ConvTo< SQFloat >::From(Var< const SLongInt & >(vm, idx).value.GetNum()); } catch (...) { // Just ignore it... } // Attempt to treat the value as a unsigned long instance try { return ConvTo< SQFloat >::From(Var< const ULongInt & >(vm, idx).value.GetNum()); } catch (...) { // Just ignore it... } // Attempt to get the size of the instance as a fallback return ConvTo< SQFloat >::From(sq_getsize(vm, idx)); } break; default: break; } // Default to 0 return 0.0; #endif // SQMOD_PLUGIN_API } // ------------------------------------------------------------------------------------------------ Int64 PopStackSLong(HSQUIRRELVM vm, SQInteger idx) { #ifdef SQMOD_PLUGIN_API return _SqMod->PopStackSLong(vm, idx); #else // Identify which type must be extracted switch (sq_gettype(vm, idx)) { case OT_INTEGER: { SQInteger val; sq_getinteger(vm, idx, &val); return static_cast< Int64 >(val); } break; case OT_FLOAT: { SQFloat val; sq_getfloat(vm, idx, &val); return ConvTo< Int64 >::From(val); } break; case OT_BOOL: { SQBool val; sq_getbool(vm, idx, &val); return static_cast< Int64 >(val); } break; case OT_STRING: { CSStr val = nullptr; // Attempt to retrieve and convert the string if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0') { return std::strtoll(val, nullptr, 10); } } break; case OT_ARRAY: case OT_TABLE: case OT_CLASS: case OT_USERDATA: { return static_cast< Int64 >(sq_getsize(vm, idx)); } break; case OT_INSTANCE: { // Attempt to treat the value as a signed long instance try { return Var< const SLongInt & >(vm, idx).value.GetNum(); } catch (...) { // Just ignore it... } // Attempt to treat the value as a unsigned long instance try { return ConvTo< Int64 >::From(Var< const ULongInt & >(vm, idx).value.GetNum()); } catch (...) { // Just ignore it... } // Attempt to get the size of the instance as a fallback return static_cast< Int64 >(sq_getsize(vm, idx)); } break; default: break; } // Default to 0 return 0; #endif // SQMOD_PLUGIN_API } // ------------------------------------------------------------------------------------------------ Uint64 PopStackULong(HSQUIRRELVM vm, SQInteger idx) { #ifdef SQMOD_PLUGIN_API return _SqMod->PopStackULong(vm, idx); #else // Identify which type must be extracted switch (sq_gettype(vm, idx)) { case OT_INTEGER: { SQInteger val; sq_getinteger(vm, idx, &val); return ConvTo< Uint64 >::From(val); } break; case OT_FLOAT: { SQFloat val; sq_getfloat(vm, idx, &val); return ConvTo< Uint64 >::From(val); } break; case OT_BOOL: { SQBool val; sq_getbool(vm, idx, &val); return ConvTo< Uint64 >::From(val); } break; case OT_STRING: { CSStr val = nullptr; // Attempt to retrieve and convert the string if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0') { return std::strtoull(val, nullptr, 10); } } break; case OT_ARRAY: case OT_TABLE: case OT_CLASS: case OT_USERDATA: { return ConvTo< Uint64 >::From(sq_getsize(vm, idx)); } break; case OT_INSTANCE: { // Attempt to treat the value as a signed long instance try { return ConvTo< Uint64 >::From(Var< const SLongInt & >(vm, idx).value.GetNum()); } catch (...) { // Just ignore it... } // Attempt to treat the value as a unsigned long instance try { return Var< const ULongInt & >(vm, idx).value.GetNum(); } catch (...) { // Just ignore it... } // Attempt to get the size of the instance as a fallback return ConvTo< Uint64 >::From(sq_getsize(vm, idx)); } break; default: break; } // Default to 0 return 0; #endif // SQMOD_PLUGIN_API } } // Namespace:: SqMod