1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 16:57:16 +01:00
SqMod/shared/Base/Utility.cpp
Sandu Liviu Catalin 85e881effa Fix const correctness in utility functions.
By not taking the object reference as const we are forced to make copies of objects that are const or use const_cast. Eitherway, this is the correct way because objects are not modified.
2016-06-13 00:27:06 +03:00

1150 lines
34 KiB
C++

// ------------------------------------------------------------------------------------------------
#include "Base/Utility.hpp"
#include "Base/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
#include <ctime>
#include <cfloat>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
// ------------------------------------------------------------------------------------------------
#ifdef SQMOD_OS_WINDOWS
#include <windows.h>
#endif // SQMOD_OS_WINDOWS
// ------------------------------------------------------------------------------------------------
#ifndef SQMOD_PLUGIN_API
#include "Library/Numeric/LongInt.hpp"
#include <sqstdstring.h>
#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;
}
// ------------------------------------------------------------------------------------------------
String & NullString()
{
static String s;
s.resize(0);
return s;
}
// ------------------------------------------------------------------------------------------------
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_getstringandsize(vm, idx, &mPtr, &mLen);
}
// 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_getstringandsize(vm, -1, &mPtr, &mLen);
}
}
// 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);
}
}
// ------------------------------------------------------------------------------------------------
CSStr SqTypeName(SQObjectType type)
{
switch (type)
{
case OT_NULL: return _SC("null");
case OT_INTEGER: return _SC("integer");
case OT_FLOAT: return _SC("float");
case OT_BOOL: return _SC("bool");
case OT_STRING: return _SC("string");
case OT_TABLE: return _SC("table");
case OT_ARRAY: return _SC("array");
case OT_USERDATA: return _SC("userdata");
case OT_CLOSURE: return _SC("closure");
case OT_NATIVECLOSURE: return _SC("nativeclosure");
case OT_GENERATOR: return _SC("generator");
case OT_USERPOINTER: return _SC("userpointer");
case OT_THREAD: return _SC("thread");
case OT_FUNCPROTO: return _SC("funcproto");
case OT_CLASS: return _SC("class");
case OT_INSTANCE: return _SC("instance");
case OT_WEAKREF: return _SC("weakref");
case OT_OUTER: return _SC("outer");
default: return _SC("unknown");
}
}
// ------------------------------------------------------------------------------------------------
String SqTypeName(HSQUIRRELVM vm, SQInteger idx)
{
// Remember the current stack size
const StackGuard sg(vm);
// Attempt to retrieve the type name of the specified value
if (SQ_FAILED(sq_typeof(vm, idx)))
{
return _SC("unknown");
}
// Attempt to convert the obtained value to a string
StackStrF val(vm, -1, false);
// Did the conversion failed?
if (SQ_FAILED(val.mRes))
{
return _SC("unknown");
}
// Return the obtained string value
return String(val.mPtr, val.mLen);
}
// ------------------------------------------------------------------------------------------------
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(const Object & val)
{
// Obtain the initial stack size
const StackGuard sg(DefaultVM::Get());
// Push the specified object onto the stack
Var< const Object & >::push(DefaultVM::Get(), val);
// Retrieve and return the object value from the stack
return PopStackSLong(DefaultVM::Get(), -1);
}
// ------------------------------------------------------------------------------------------------
Uint64 FetchULongObjVal(const Object & val)
{
// Obtain the initial stack size
const StackGuard sg(DefaultVM::Get());
// Push the specified object onto the stack
Var< const Object & >::push(DefaultVM::Get(), val);
// Retrieve and return the object value from the stack
return PopStackSLong(DefaultVM::Get(), -1);
}
// ------------------------------------------------------------------------------------------------
Int64 FetchSLongObjVal(HSQUIRRELVM vm, const Object & val)
{
// Obtain the initial stack size
const StackGuard sg(vm);
// Push the specified object onto the stack
Var< const Object & >::push(vm, val);
// Retrieve and return the object value from the stack
return PopStackSLong(vm, -1);
}
// ------------------------------------------------------------------------------------------------
Uint64 FetchULongObjVal(HSQUIRRELVM vm, const Object & val)
{
// Obtain the initial stack size
const StackGuard sg(vm);
// Push the specified object onto the stack
Var< const 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