1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 16:57:16 +01:00
SqMod/shared/Base/Utility.hpp
Sandu Liviu Catalin 0137dfc66f Move the plugin Squirrel utilities to the Sqrat binding utility.
Implement registration of functions and methods with string formatting support in the Sqrat binding utility.
Few minor other fixes.
2016-11-16 11:54:07 +02:00

1625 lines
50 KiB
C++

#ifndef _BASE_UTILITY_HPP_
#define _BASE_UTILITY_HPP_
// ------------------------------------------------------------------------------------------------
#ifdef SQMOD_PLUGIN_API
#include <ModBase.hpp>
#include <SqMod.h>
#else
#include <SqBase.hpp>
#include <vcmp.h>
#endif // SQMOD_PLUGIN_API
// ------------------------------------------------------------------------------------------------
#include <cmath>
#include <limits>
#include <cassert>
// ------------------------------------------------------------------------------------------------
#include <sqrat.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Forward declarations.
*/
class Buffer;
/* ------------------------------------------------------------------------------------------------
* Proxies to communicate with the server.
*/
extern PluginFuncs* _Func;
extern PluginCallbacks* _Clbk;
extern PluginInfo* _Info;
/* ------------------------------------------------------------------------------------------------
* Helper to register pure typename functions for better performance.
*/
#define SQMODE_DECL_TYPENAME(t, s) /*
*/ namespace { /*
*/ struct t { /*
*/ static const SQChar Str[]; /*
*/ static SQInteger Fn(HSQUIRRELVM vm); /*
*/ }; /*
*/ const SQChar t::Str[] = s; /*
*/ SQInteger t::Fn(HSQUIRRELVM vm) { /*
*/ sq_pushstring(vm, Str, sizeof(Str) / sizeof(SQChar)); /*
*/ return 1; /*
*/ } /*
*/ } /*
*/
/* ------------------------------------------------------------------------------------------------
* Retrieve the temporary buffer.
*/
SStr GetTempBuff();
/* ------------------------------------------------------------------------------------------------
* Retrieve the size of the temporary buffer.
*/
Uint32 GetTempBuffSize();
/* ------------------------------------------------------------------------------------------------
* Output a message only if the _DEBUG was defined.
*/
void OutputDebug(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Output a formatted user message to the console.
*/
void OutputMessage(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Output a formatted error message to the console.
*/
void OutputError(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Generate a formatted string and throw it as a sqrat exception.
*/
void SqThrowF(CCStr str, ...);
/* ------------------------------------------------------------------------------------------------
* Quickly generate a formatted string on a small static buffer without any memory allocations.
* NOTE: This does throw an exception in case of failure.
*/
CSStr FmtStr(CSStr str, ...);
/* ------------------------------------------------------------------------------------------------
* Quickly generate a formatted string on a small static buffer without any memory allocations.
* NOTE: This does not throw an exception in case of failure.
*/
CSStr ToStrF(CCStr str, ...);
/* ------------------------------------------------------------------------------------------------
* Generate a formatted string on a temporary buffer and return the string but not the buffer.
* NOTE: This does not throw an exception in case of failure.
*/
CSStr ToStringF(CCStr str, ...);
/* ------------------------------------------------------------------------------------------------
* Simple function to check whether the specified string can be considered as a boolean value
*/
bool SToB(CSStr str);
/* ------------------------------------------------------------------------------------------------
* Retrieve a reference to a null script object.
*/
Object & NullObject();
/* ------------------------------------------------------------------------------------------------
* Retrieve a reference to a null/empty script table.
*/
Table & NullTable();
/* ------------------------------------------------------------------------------------------------
* Retrieve a reference to a null/empty script array.
*/
Array & NullArray();
/* ------------------------------------------------------------------------------------------------
* Retrieve a reference to a null script function.
*/
Function & NullFunction();
/* ------------------------------------------------------------------------------------------------
* Retrieve a reference to a null string.
*/
String & NullString();
/* ------------------------------------------------------------------------------------------------
* Compute the next power of two for the specified number.
*/
inline Uint32 NextPow2(Uint32 num)
{
--num;
num |= num >> 1;
num |= num >> 2;
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;
return ++num;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the maximum value of a fundamental type.
*/
template < typename T > constexpr T MaxOf() noexcept
{
return std::numeric_limits< T >::max();
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the minimum value of a fundamental type.
*/
template < typename T > constexpr T MinOf() noexcept
{
return std::numeric_limits< T >::min();
}
/* ------------------------------------------------------------------------------------------------
* Perform an equality comparison between two values taking into account floating point issues.
*/
template< typename T > inline bool EpsEq(const T a, const T b)
{
return abs(a - b) <= 0;
}
template <> inline bool EpsEq(const Float32 a, const Float32 b)
{
return fabs(a - b) <= 0.000001f;
}
template <> inline bool EpsEq(const Float64 a, const Float64 b)
{
return fabs(a - b) <= 0.000000001d;
}
/* ------------------------------------------------------------------------------------------------
* Perform a less than comparison between two values taking into account floating point issues.
*/
template< typename T > inline bool EpsLt(const T a, const T b)
{
return !EpsEq(a, b) && (a < b);
}
template <> inline bool EpsLt(const Float32 a, const Float32 b)
{
return !EpsEq(a, b) && (a - b) < 0.000001f;
}
template <> inline bool EpsLt(const Float64 a, const Float64 b)
{
return !EpsEq(a, b) && (a - b) < 0.000000001d;
}
/* ------------------------------------------------------------------------------------------------
* Perform a greater than comparison between two values taking into account floating point issues.
*/
template< typename T > inline bool EpsGt(const T a, const T b)
{
return !EpsEq(a, b) && (a > b);
}
template <> inline bool EpsGt(const Float32 a, const Float32 b)
{
return !EpsEq(a, b) && (a - b) > 0.000001f;
}
template <> inline bool EpsGt(const Float64 a, const Float64 b)
{
return !EpsEq(a, b) && (a - b) > 0.000000001d;
}
/* ------------------------------------------------------------------------------------------------
* Perform a less than or equal comparison between two values taking into account
* floating point issues.
*/
template< typename T > inline bool EpsLtEq(const T a, const T b)
{
return !EpsEq(a, b) || (a < b);
}
template <> inline bool EpsLtEq(const Float32 a, const Float32 b)
{
return !EpsEq(a, b) || (a - b) < 0.000001f;
}
template <> inline bool EpsLtEq(const Float64 a, const Float64 b)
{
return !EpsEq(a, b) || (a - b) < 0.000000001d;
}
/* ------------------------------------------------------------------------------------------------
* Perform a greater than or equal comparison between two values taking into account
* floating point issues.
*/
template< typename T > inline bool EpsGtEq(const T a, const T b)
{
return !EpsEq(a, b) || (a > b);
}
template <> inline bool EpsGtEq(const Float32 a, const Float32 b)
{
return !EpsEq(a, b) || (a - b) > 0.000001f;
}
template <> inline bool EpsGtEq(const Float64 a, const Float64 b)
{
return !EpsEq(a, b) || (a - b) > 0.000000001d;
}
/* ------------------------------------------------------------------------------------------------
* Utility used to convert strings to numeric values and/or backwards.
*/
template < typename T > struct ConvNum;
/* ------------------------------------------------------------------------------------------------
* Specializations for each numeric type conversion to string and/or backwards.
*/
template <> struct ConvNum< Int8 >
{
static CCStr ToStr(Int8 v);
static Int8 FromStr(CCStr s);
static Int8 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Uint8 >
{
static CCStr ToStr(Uint8 v);
static Uint8 FromStr(CCStr s);
static Uint8 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Int16 >
{
static CCStr ToStr(Int16 v);
static Int16 FromStr(CCStr s);
static Int16 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Uint16 >
{
static CCStr ToStr(Uint16 v);
static Uint16 FromStr(CCStr s);
static Uint16 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Int32 >
{
static CCStr ToStr(Int32 v);
static Int32 FromStr(CCStr s);
static Int32 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Uint32 >
{
static CCStr ToStr(Uint32 v);
static Uint32 FromStr(CCStr s);
static Uint32 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Int64 >
{
static CCStr ToStr(Int64 v);
static Int64 FromStr(CCStr s);
static Int64 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Uint64 >
{
static CCStr ToStr(Uint64 v);
static Uint64 FromStr(CCStr s);
static Uint64 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< LongI >
{
static CCStr ToStr(LongI v);
static LongI FromStr(CCStr s);
static LongI FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Ulong >
{
static CCStr ToStr(Ulong v);
static Ulong FromStr(CCStr s);
static Ulong FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Float32 >
{
static CCStr ToStr(Float32 v);
static Float32 FromStr(CCStr s);
static Float32 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< Float64 >
{
static CCStr ToStr(Float64 v);
static Float64 FromStr(CCStr s);
static Float64 FromStr(CCStr s, Int32 base);
};
template <> struct ConvNum< bool >
{
static CCStr ToStr(bool v);
static bool FromStr(CCStr s);
static bool FromStr(CCStr s, Int32 base);
};
/* ------------------------------------------------------------------------------------------------
* Utility used to cast between specialized types and perform proper conversion.
*/
template < typename T > struct ConvTo
{
// --------------------------------------------------------------------------------------------
static constexpr T Min = std::numeric_limits< T >::min();
static constexpr T Max = std::numeric_limits< T >::max();
// --------------------------------------------------------------------------------------------
template < typename U > static inline T From(U v)
{
if (v > Max)
{
return Max;
}
else if (v < Min)
{
return Min;
}
return static_cast< T >(v);
}
};
/* ------------------------------------------------------------------------------------------------
* Convert a string to 8/16/32 bit signed integers.
*/
template <> template <> inline Int8 ConvTo< Int8 >::From< CCStr >(CCStr v)
{
return ConvNum< Int8 >::FromStr(v);
}
template <> template <> inline Int16 ConvTo< Int16 >::From< CCStr >(CCStr v)
{
return ConvNum< Int16 >::FromStr(v);
}
template <> template <> inline Int32 ConvTo< Int32 >::From< CCStr >(CCStr v)
{
return ConvNum< Int32 >::FromStr(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert a string to 8/16/32 bit unsigned integers.
*/
template <> template <> inline Uint8 ConvTo< Uint8 >::From< CCStr >(CCStr v)
{
return ConvNum< Uint8 >::FromStr(v);
}
template <> template <> inline Uint16 ConvTo< Uint16 >::From< CCStr >(CCStr v)
{
return ConvNum< Uint16 >::FromStr(v);
}
template <> template <> inline Uint32 ConvTo< Uint32 >::From< CCStr >(CCStr v)
{
return ConvNum< Uint32 >::FromStr(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert to 8 bit signed integer from any unsigned integer.
*/
template <> template <> inline Int8 ConvTo< Int8 >::From< Uint8 >(Uint8 v)
{
return (v >= static_cast< Uint8 >(Max)) ? Max : static_cast< Int8 >(v);
}
template <> template <> inline Int8 ConvTo< Int8 >::From< Uint16 >(Uint16 v)
{
return (v >= static_cast< Uint8 >(Max)) ? Max : static_cast< Int8 >(v);
}
template <> template <> inline Int8 ConvTo< Int8 >::From< Uint32 >(Uint32 v)
{
return (v >= static_cast< Uint8 >(Max)) ? Max : static_cast< Int8 >(v);
}
template <> template <> inline Int8 ConvTo< Int8 >::From< Uint64 >(Uint64 v)
{
return (v >= static_cast< Uint8 >(Max)) ? Max : static_cast< Int8 >(v);
}
template <> template <> inline Int8 ConvTo< Int8 >::From< Ulong >(Ulong v)
{
return (v >= static_cast< Uint8 >(Max)) ? Max : static_cast< Int8 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert to 16 bit signed integer from any unsigned integer.
*/
template <> template <> inline Int16 ConvTo< Int16 >::From< Uint8 >(Uint8 v)
{
return static_cast< Int16 >(v);
}
template <> template <> inline Int16 ConvTo< Int16 >::From< Uint16 >(Uint16 v)
{
return (v >= static_cast< Uint16 >(Max)) ? Max : static_cast< Int16 >(v);
}
template <> template <> inline Int16 ConvTo< Int16 >::From< Uint32 >(Uint32 v)
{
return (v >= static_cast< Uint16 >(Max)) ? Max : static_cast< Int16 >(v);
}
template <> template <> inline Int16 ConvTo< Int16 >::From< Uint64 >(Uint64 v)
{
return (v >= static_cast< Uint16 >(Max)) ? Max : static_cast< Int16 >(v);
}
template <> template <> inline Int16 ConvTo< Int16 >::From< Ulong >(Ulong v)
{
return (v >= static_cast< Uint16 >(Max)) ? Max : static_cast< Int16 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert to 32 bit signed integer from any unsigned integer.
*/
template <> template <> inline Int32 ConvTo< Int32 >::From< Uint8 >(Uint8 v)
{
return static_cast< Int32 >(v);
}
template <> template <> inline Int32 ConvTo< Int32 >::From< Uint16 >(Uint16 v)
{
return static_cast< Int32 >(v);
}
template <> template <> inline Int32 ConvTo< Int32 >::From< Uint32 >(Uint32 v)
{
return (v >= static_cast< Uint32 >(Max)) ? Max : static_cast< Int32 >(v);
}
template <> template <> inline Int32 ConvTo< Int32 >::From< Uint64 >(Uint64 v)
{
return (v >= static_cast< Uint32 >(Max)) ? Max : static_cast< Int32 >(v);
}
template <> template <> inline Int32 ConvTo< Int32 >::From< Ulong >(Ulong v)
{
return (v >= static_cast< Uint32 >(Max)) ? Max : static_cast< Int32 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert to 8 bit unsigned integer from any signed integer.
*/
template <> template <> inline Uint8 ConvTo< Uint8 >::From< Int8 >(Int8 v)
{
return (v <= 0) ? 0 : static_cast< Uint8 >(v);
}
template <> template <> inline Uint8 ConvTo< Uint8 >::From< Int16 >(Int16 v)
{
if (v <= 0)
{
return 0;
}
else if (v >= static_cast< Int16 >(Max))
{
return Max;
}
return static_cast< Uint8 >(v);
}
template <> template <> inline Uint8 ConvTo< Uint8 >::From< Int32 >(Int32 v)
{
if (v <= 0)
{
return 0;
}
else if (v >= static_cast< Int16 >(Max))
{
return Max;
}
return static_cast< Uint8 >(v);
}
template <> template <> inline Uint8 ConvTo< Uint8 >::From< Int64 >(Int64 v)
{
if (v <= 0)
{
return 0;
}
else if (v >= static_cast< Int16 >(Max))
{
return Max;
}
return static_cast< Uint8 >(v);
}
template <> template <> inline Uint8 ConvTo< Uint8 >::From< LongI >(LongI v)
{
if (v <= 0)
{
return 0;
}
else if (v >= static_cast< Int16 >(Max))
{
return Max;
}
return static_cast< Uint8 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert to 16 bit unsigned integer from any signed integer.
*/
template <> template <> inline Uint16 ConvTo< Uint16 >::From< Int8 >(Int8 v)
{
return (v <= 0) ? 0 : static_cast< Uint16 >(v);
}
template <> template <> inline Uint16 ConvTo< Uint16 >::From< Int16 >(Int16 v)
{
return (v <= 0) ? 0 : static_cast< Uint16 >(v);
}
template <> template <> inline Uint16 ConvTo< Uint16 >::From< Int32 >(Int32 v)
{
if (v <= 0)
{
return 0;
}
else if (v >= static_cast< Int32 >(Max))
{
return Max;
}
return static_cast< Uint16 >(v);
}
template <> template <> inline Uint16 ConvTo< Uint16 >::From< Int64 >(Int64 v)
{
if (v <= 0)
{
return 0;
}
else if (v >= static_cast< Int32 >(Max))
{
return Max;
}
return static_cast< Uint16 >(v);
}
template <> template <> inline Uint16 ConvTo< Uint16 >::From< LongI >(LongI v)
{
if (v <= 0)
{
return 0;
}
else if (v >= static_cast< Int32 >(Max))
{
return Max;
}
return static_cast< Uint16 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert to 32 bit unsigned integer from any signed integer.
*/
template <> template <> inline Uint32 ConvTo< Uint32 >::From< Int8 >(Int8 v)
{
return (v <= 0) ? 0 : static_cast< Uint32 >(v);
}
template <> template <> inline Uint32 ConvTo< Uint32 >::From< Int16 >(Int16 v)
{
return (v <= 0) ? 0 : static_cast< Uint32 >(v);
}
template <> template <> inline Uint32 ConvTo< Uint32 >::From< Int32 >(Int32 v)
{
return (v <= 0) ? 0 : static_cast< Uint32 >(v);
}
template <> template <> inline Uint32 ConvTo< Uint32 >::From< Int64 >(Int64 v)
{
if (v <= 0)
{
return 0;
}
else if (v >= static_cast< Int64 >(Max))
{
return Max;
}
return static_cast< Uint32 >(v);
}
template <> template <> inline Uint32 ConvTo< Uint32 >::From< LongI >(LongI v)
{
#if (ULONG_MAX > UINT_MAX)
if (v <= 0)
{
return 0;
}
else if (v >= static_cast< Int64 >(Max))
{
return Max;
}
return static_cast< Uint32 >(v);
#else
return (v <= 0) ? 0 : static_cast< Uint32 >(v);
#endif
}
/* ------------------------------------------------------------------------------------------------
* Convert to signed integer from 32 bit floating point number.
*/
template <> template <> inline Int8 ConvTo< Int8 >::From< Float32 >(Float32 v)
{
if (EpsLt(v, static_cast< Float32 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float32 >(Max)))
{
return Max;
}
return static_cast< Int8 >(v);
}
template <> template <> inline Int16 ConvTo< Int16 >::From< Float32 >(Float32 v)
{
if (EpsLt(v, static_cast< Float32 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float32 >(Max)))
{
return Max;
}
return static_cast< Int16 >(v);
}
template <> template <> inline Int32 ConvTo< Int32 >::From< Float32 >(Float32 v)
{
if (EpsLt(v, static_cast< Float32 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float32 >(Max)))
{
return Max;
}
return static_cast< Int32 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert to signed integer from 64 bit floating point number.
*/
template <> template <> inline Int8 ConvTo< Int8 >::From< Float64 >(Float64 v)
{
if (EpsLt(v, static_cast< Float64 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float64 >(Max)))
{
return Max;
}
return static_cast< Int8 >(v);
}
template <> template <> inline Int16 ConvTo< Int16 >::From< Float64 >(Float64 v)
{
if (EpsLt(v, static_cast< Float64 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float64 >(Max)))
{
return Max;
}
return static_cast< Int16 >(v);
}
template <> template <> inline Int32 ConvTo< Int32 >::From< Float64 >(Float64 v)
{
if (EpsLt(v, static_cast< Float64 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float64 >(Max)))
{
return Max;
}
return static_cast< Int32 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert to unsigned integer from 32 bit floating point number.
*/
template <> template <> inline Uint8 ConvTo< Uint8 >::From< Float32 >(Float32 v)
{
if (EpsLt(v, static_cast< Float32 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float32 >(Max)))
{
return Max;
}
return static_cast< Uint8 >(v);
}
template <> template <> inline Uint16 ConvTo< Uint16 >::From< Float32 >(Float32 v)
{
if (EpsLt(v, static_cast< Float32 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float32 >(Max)))
{
return Max;
}
return static_cast< Uint16 >(v);
}
template <> template <> inline Uint32 ConvTo< Uint32 >::From< Float32 >(Float32 v)
{
if (EpsLt(v, static_cast< Float32 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float32 >(Max)))
{
return Max;
}
return static_cast< Uint32 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert to unsigned integer from 64 bit floating point number.
*/
template <> template <> inline Uint8 ConvTo< Uint8 >::From< Float64 >(Float64 v)
{
if (EpsLt(v, static_cast< Float64 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float64 >(Max)))
{
return Max;
}
return static_cast< Uint8 >(v);
}
template <> template <> inline Uint16 ConvTo< Uint16 >::From< Float64 >(Float64 v)
{
if (EpsLt(v, static_cast< Float64 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float64 >(Max)))
{
return Max;
}
return static_cast< Uint16 >(v);
}
template <> template <> inline Uint32 ConvTo< Uint32 >::From< Float64 >(Float64 v)
{
if (EpsLt(v, static_cast< Float64 >(Min)))
{
return Min;
}
else if (EpsGt(v, static_cast< Float64 >(Max)))
{
return Max;
}
return static_cast< Uint32 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert other numeric values to 64 bit signed integer.
*/
template <> struct ConvTo< Int64 >
{
// --------------------------------------------------------------------------------------------
static constexpr Int64 Min = std::numeric_limits< Int64 >::min();
static constexpr Int64 Max = std::numeric_limits< Int64 >::max();
// --------------------------------------------------------------------------------------------
template < typename T > static inline Int64 From(T v)
{
return static_cast< Int64 >(v);
}
};
// ------------------------------------------------------------------------------------------------
template <> inline Int64 ConvTo< Int64 >::From< CCStr >(CCStr v)
{
return ConvNum< Int64 >::FromStr(v);
}
// ------------------------------------------------------------------------------------------------
template <> inline Int64 ConvTo< Int64 >::From< Uint64 >(Uint64 v)
{
return (v >= static_cast< Uint64 >(Max)) ? Max : static_cast< Int64 >(v);
}
#if (ULONG_MAX > UINT_MAX)
// ------------------------------------------------------------------------------------------------
template <> inline Int64 ConvTo< Int64 >::From< Ulong >(Ulong v)
{
return (v >= static_cast< Ulong >(Max)) ? Max : static_cast< Int64 >(v);
}
#endif
/* ------------------------------------------------------------------------------------------------
* Convert other numeric values to 64 bit unsigned integer.
*/
template <> struct ConvTo< Uint64 >
{
// --------------------------------------------------------------------------------------------
static constexpr Uint64 Min = std::numeric_limits< Uint64 >::min();
static constexpr Uint64 Max = std::numeric_limits< Uint64 >::max();
// --------------------------------------------------------------------------------------------
template < typename T > static inline Uint64 From(T v)
{
return (v <= static_cast< T >(0)) ? 0 : static_cast< Uint64 >(v);
}
};
// ------------------------------------------------------------------------------------------------
template <> inline Uint64 ConvTo< Uint64 >::From< CCStr >(CCStr v)
{
return ConvNum< Uint64 >::FromStr(v);
}
// ------------------------------------------------------------------------------------------------
template <> inline Uint64 ConvTo< Uint64 >::From< Float32 >(Float32 v)
{
return From(ConvTo< Int64 >::From(v));
}
// ------------------------------------------------------------------------------------------------
template <> inline Uint64 ConvTo< Uint64 >::From< Float64 >(Float64 v)
{
return From(ConvTo< Int64 >::From(v));
}
/* ------------------------------------------------------------------------------------------------
* Convert other numeric values to signed long integer.
*/
template <> struct ConvTo< LongI >
{
// --------------------------------------------------------------------------------------------
static constexpr LongI Min = std::numeric_limits< LongI >::min();
static constexpr LongI Max = std::numeric_limits< LongI >::max();
// --------------------------------------------------------------------------------------------
template < typename T > static inline LongI From(T v)
{
return static_cast< LongI >(v);
}
};
// ------------------------------------------------------------------------------------------------
template <> inline LongI ConvTo< LongI >::From< CCStr >(CCStr v)
{
return ConvNum< LongI >::FromStr(v);
}
// ------------------------------------------------------------------------------------------------
#if (ULONG_MAX <= UINT_MAX)
template <> inline LongI ConvTo< LongI >::From< Uint32 >(Uint32 v)
{
return (v >= static_cast< Uint32 >(Max)) ? Max : static_cast< LongI >(v);
}
#endif
// ------------------------------------------------------------------------------------------------
template <> inline LongI ConvTo< LongI >::From< Uint64 >(Uint64 v)
{
return (v >= static_cast< Uint64 >(Max)) ? Max : static_cast< LongI >(v);
}
// ------------------------------------------------------------------------------------------------
template <> inline LongI ConvTo< LongI >::From< Ulong >(Ulong v)
{
return (v >= static_cast< Ulong >(Max)) ? Max : static_cast< LongI >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert other numeric values to unsigned long integer.
*/
template <> struct ConvTo< Ulong >
{
// --------------------------------------------------------------------------------------------
static constexpr Ulong Min = std::numeric_limits< Ulong >::min();
static constexpr Ulong Max = std::numeric_limits< Ulong >::max();
// --------------------------------------------------------------------------------------------
template < typename T > static inline Ulong From(T v)
{
return (v <= static_cast< T >(0)) ? 0 : static_cast< Ulong >(v);
}
};
// ------------------------------------------------------------------------------------------------
template <> inline Ulong ConvTo< Ulong >::From< CCStr >(CCStr v)
{
return ConvNum< Ulong >::FromStr(v);
}
// ------------------------------------------------------------------------------------------------
#if (ULONG_MAX <= UINT_MAX)
template <> inline Ulong ConvTo< Ulong >::From< Int64 >(Int64 v)
{
if (v <= 0)
{
return Min;
}
else if (v >= static_cast< Int64 >(Max))
{
return Max;
}
return static_cast< Ulong >(v);
}
template <> inline Ulong ConvTo< Ulong >::From< Uint64 >(Uint64 v)
{
return (v >= Max) ? Max : static_cast< Ulong >(v);
}
#endif
// ------------------------------------------------------------------------------------------------
template <> inline Ulong ConvTo< Ulong >::From< Float32 >(Float32 v)
{
return From(ConvTo< LongI >::From(v));
}
// ------------------------------------------------------------------------------------------------
template <> inline Ulong ConvTo< Ulong >::From< Float64 >(Float64 v)
{
return From(ConvTo< LongI >::From(v));
}
/* ------------------------------------------------------------------------------------------------
* Convert other numeric values to 32 bit floating point value.
*/
template <> struct ConvTo< Float32 >
{
// --------------------------------------------------------------------------------------------
static constexpr Float32 Min = std::numeric_limits< Float32 >::min();
static constexpr Float32 Max = std::numeric_limits< Float32 >::max();
// --------------------------------------------------------------------------------------------
template < typename T > static inline Float32 From(T v)
{
return static_cast< Float32 >(v);
}
};
// ------------------------------------------------------------------------------------------------
template <> inline Float32 ConvTo< Float32 >::From< CCStr >(CCStr v)
{
return ConvNum< Float32 >::FromStr(v);
}
// ------------------------------------------------------------------------------------------------
template <> inline Float32 ConvTo< Float32 >::From< Float64 >(Float64 v)
{
if (EpsGt(v, static_cast< Float64 >(Max)))
{
return Max;
}
else if (EpsLt(v, static_cast< Float64 >(Min)))
{
return Min;
}
return static_cast< Float32 >(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert other numeric values to 64 bit floating point value.
*/
template <> struct ConvTo< Float64 >
{
// --------------------------------------------------------------------------------------------
static constexpr Float64 Min = std::numeric_limits< Float64 >::min();
static constexpr Float64 Max = std::numeric_limits< Float64 >::max();
// --------------------------------------------------------------------------------------------
template < typename T > static inline Float64 From(T v)
{
return static_cast< Float64 >(v);
}
};
// ------------------------------------------------------------------------------------------------
template <> inline Float64 ConvTo< Float64 >::From< CCStr >(CCStr v)
{
return ConvNum< Float64 >::FromStr(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert other numeric values to boolean value.
*/
template <> struct ConvTo< bool >
{
// --------------------------------------------------------------------------------------------
template < typename T > static inline bool From(T v)
{
return static_cast< bool >(v);
}
};
// ------------------------------------------------------------------------------------------------
template <> inline bool ConvTo< bool >::From< CCStr >(CCStr v)
{
return ConvNum< bool >::FromStr(v);
}
/* ------------------------------------------------------------------------------------------------
* Convert other numeric values to string value.
*/
template <> struct ConvTo< CStr >
{
// --------------------------------------------------------------------------------------------
template < typename T > static inline CStr From(T v)
{
return const_cast< CStr >(ConvNum< T >::ToStr(v));
}
};
/* ------------------------------------------------------------------------------------------------
* Convert other numeric values to string value.
*/
template <> struct ConvTo< CCStr >
{
// --------------------------------------------------------------------------------------------
template < typename T > static inline CCStr From(T v)
{
return ConvNum< T >::ToStr(v);
}
};
/* ------------------------------------------------------------------------------------------------
* Force a value to be within a certain range.
*/
template< typename T, typename U, typename V > inline T Clamp(T val, U min, V max)
{
// Is the specified value bellow the minimum?
if (val < min)
{
return min;
}
// Is the specified value above the maximum?
else if (val > max)
{
return max;
}
// Return the value as is
return val;
}
/* ------------------------------------------------------------------------------------------------
* Force a value to be higher then than the imposed limit.
*/
template< typename T, typename U > inline T ClampMin(T val, U min)
{
// Is the specified value bellow the minimum?
if (val < min)
{
return min;
}
// Return the value as is
return val;
}
/* ------------------------------------------------------------------------------------------------
* Force a value to be smaller then than the imposed limit.
*/
template< typename T, typename U > inline T ClampMax(T val, U max)
{
// Is the specified value above the maximum?
if (val > max)
{
return max;
}
// Return the value as is
return val;
}
/* ------------------------------------------------------------------------------------------------
* Force a value to be within a certain range.
*/
template<> inline Float32 Clamp(Float32 val, Float32 min, Float32 max)
{
// Is the specified value bellow the minimum?
if (EpsLt(val, min))
{
return min;
}
// Is the specified value above the maximum?
else if (EpsGt(val, max))
{
return max;
}
// Return the value as is
return val;
}
/* ------------------------------------------------------------------------------------------------
* Force a value to be within a certain range.
*/
template<> inline Float64 Clamp(Float64 val, Float64 min, Float64 max)
{
// Is the specified value bellow the minimum?
if (EpsLt(val, min))
{
return min;
}
// Is the specified value above the maximum?
else if (EpsGt(val, max))
{
return max;
}
// Return the value as is
return val;
}
/* ------------------------------------------------------------------------------------------------
* Force a value to be the boundaries of the specified type.
*/
template < typename T, typename U > inline U ClampL(T v)
{
return ConvTo< U >::From(v);
}
/* ------------------------------------------------------------------------------------------------
* Helper class allows the use of functions with ctype style as predicate for algorithms.
*/
struct IsCType
{
// ------------------------------------------------------------------------------------------------
typedef int (*CTypeFn)(int); // The signature of a ctype function.
private:
// ------------------------------------------------------------------------------------------------
CTypeFn m_Fn; // Pointer to the actual function that does the comparison.
public:
/* ------------------------------------------------------------------------------------------------
* Base constructor.
*/
IsCType(CTypeFn fn)
: m_Fn(fn)
{
/* ... */
}
/* ------------------------------------------------------------------------------------------------
* Function call operator.
*/
template < typename T > bool operator () (T c)
{
return (m_Fn(static_cast< int >(c)) != 0);
}
};
/* ------------------------------------------------------------------------------------------------
* Helper class allows the use of functions with ctype style as predicate for algorithms.
*/
struct IsNotCType
{
// ------------------------------------------------------------------------------------------------
typedef int (*CTypeFn)(int); // The signature of a ctype function.
private:
// ------------------------------------------------------------------------------------------------
CTypeFn m_Fn; // Pointer to the actual function that does the comparison.
public:
/* ------------------------------------------------------------------------------------------------
* Base constructor.
*/
IsNotCType(CTypeFn fn)
: m_Fn(fn)
{
/* ... */
}
/* ------------------------------------------------------------------------------------------------
* Function call operator.
*/
template < typename T > bool operator () (T c)
{
return (m_Fn(static_cast< int >(c)) == 0);
}
};
/* ------------------------------------------------------------------------------------------------
* Utility implementing RAII to toggle a bit mask on and off at all costs.
*/
template < typename T > struct BitGuard
{
private:
/* ------------------------------------------------------------------------------------------------
* The lock to be toggled.
*/
T & m_Lock;
/* ------------------------------------------------------------------------------------------------
* The mask to be applied.
*/
T m_Mask;
public:
/* ------------------------------------------------------------------------------------------------
* Base constructor.
*/
BitGuard(T & lock, T mask)
: m_Lock(lock), m_Mask(mask)
{
// Apply the specified mask
m_Lock |= m_Mask;
}
/* ------------------------------------------------------------------------------------------------
* Destructor.
*/
~BitGuard()
{
// In case one of the bits was turned off in the meantime
m_Lock |= m_Mask;
// Now turn off all the bits in the mask
m_Lock ^= m_Mask;
}
};
// ------------------------------------------------------------------------------------------------
typedef BitGuard< Uint8 > BitGuardU8;
typedef BitGuard< Uint16 > BitGuardU16;
typedef BitGuard< Uint32 > BitGuardU32;
/* ------------------------------------------------------------------------------------------------
* RAII approach to make sure an instance is deleted regardless of what exceptions are thrown.
*/
template < typename T > struct DeleteGuard
{
private:
// --------------------------------------------------------------------------------------------
T * m_Ptr; // Pointer to the instance to manage.
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
DeleteGuard(T * ptr)
: m_Ptr(ptr)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
DeleteGuard(const DeleteGuard & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
DeleteGuard(DeleteGuard && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~DeleteGuard()
{
if (m_Ptr)
{
delete m_Ptr;
}
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
DeleteGuard & operator = (const DeleteGuard & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
DeleteGuard & operator = (DeleteGuard && o) = delete;
/* --------------------------------------------------------------------------------------------
* Implicit conversion the managed instance type.
*/
operator T * () const
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the managed instance.
*/
T * Get() const
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Release the managed instance.
*/
void Release()
{
m_Ptr = nullptr;
}
};
/* ------------------------------------------------------------------------------------------------
* RAII approach to make sure a value is assigned regardless of what exceptions are thrown.
*/
template < typename T > class AutoAssign
{
private:
// --------------------------------------------------------------------------------------------
T & m_Var; // Variable to receive the value.
T m_Val; // Value to be assigned.
public:
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
AutoAssign(T & variable, T value)
: m_Var(variable), m_Val(value)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
AutoAssign(T & variable, T value, T start)
: m_Var(variable), m_Val(value)
{
m_Var = start;
}
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
AutoAssign(const AutoAssign & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
AutoAssign(AutoAssign && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~AutoAssign()
{
m_Var = m_Val;
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
AutoAssign & operator = (const AutoAssign & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
AutoAssign & operator = (AutoAssign && o) = delete;
/* --------------------------------------------------------------------------------------------
* Direct value assignment.
*/
template < typename U > AutoAssign & operator = (U value)
{
m_Var = value;
}
/* --------------------------------------------------------------------------------------------
* Direct value assignment.
*/
template < typename U > void Set(U value)
{
m_Val = value;
}
};
/* ------------------------------------------------------------------------------------------------
* Retrieve the string representation of a certain type.
*/
CSStr SqTypeName(SQObjectType type);
/* ------------------------------------------------------------------------------------------------
* Retrieve the string representation of a certain type from a value on the stack.
*/
String SqTypeName(HSQUIRRELVM vm, SQInteger idx);
/* ------------------------------------------------------------------------------------------------
* Create a script object from the specified value on the default VM.
*/
template < typename T > Object MakeObject(const T & v)
{
// Remember the current stack size
const StackGuard sg;
// Transform the specified value into a script object
PushVar< T >(DefaultVM::Get(), v);
// Get the object from the stack and return it
return Var< Object >(DefaultVM::Get(), -1).value;
}
/* ------------------------------------------------------------------------------------------------
* Create a script object from the specified value on the specified VM.
*/
template < typename T > Object MakeObject(HSQUIRRELVM vm, const T & v)
{
// Remember the current stack size
const StackGuard sg;
// Transform the specified value into a script object
PushVar< T >(vm, v);
// Get the object from the stack and return it
return Var< Object >(vm, -1).value;
}
/* ------------------------------------------------------------------------------------------------
* Create a script string instance from a buffer.
*/
Object BufferToStrObj(const Buffer & b);
/* ------------------------------------------------------------------------------------------------
* Create a script string instance from a portion of a buffer.
*/
Object BufferToStrObj(const Buffer & b, Uint32 size);
/* ------------------------------------------------------------------------------------------------
* Create a signed long integer instance from an integer.
*/
Object MakeSLongObj(Int64 value);
/* ------------------------------------------------------------------------------------------------
* Create a unsigned long integer instance from an integer.
*/
Object MakeULongObj(Uint64 value);
/* ------------------------------------------------------------------------------------------------
* Create a signed long integer instance from an integer.
*/
Object MakeSLongObj(HSQUIRRELVM vm, Int64 value);
/* ------------------------------------------------------------------------------------------------
* Create a unsigned long integer instance from an integer.
*/
Object MakeULongObj(HSQUIRRELVM vm, Uint64 value);
/* ------------------------------------------------------------------------------------------------
* Retrieve a signed 64 bit integer from an signed long integer instance.
*/
Int64 FetchSLongObjVal(const Object & value);
/* ------------------------------------------------------------------------------------------------
* Retrieve a unsigned 64 bit integer from an unsigned long integer instance.
*/
Uint64 FetchULongObjVal(const Object & value);
/* ------------------------------------------------------------------------------------------------
* Retrieve the date components from a date instance.
*/
SQRESULT FetchDateObjVal(const Object & value, Uint16 & year, Uint8 & month, Uint8 & day);
/* ------------------------------------------------------------------------------------------------
* Retrieve the date components from a date instance as a string.
*/
CSStr FetchDateObjStr(const Object & value);
/* ------------------------------------------------------------------------------------------------
* Retrieve the time components from a date instance.
*/
SQRESULT FetchTimeObjVal(const Object & value, Uint8 & hour, Uint8 & minute, Uint8 & second);
/* ------------------------------------------------------------------------------------------------
* Retrieve the time components from a date instance.
*/
SQRESULT FetchTimeObjVal(const Object & value, Uint8 & hour, Uint8 & minute, Uint8 & second, Uint16 & millisecond);
/* ------------------------------------------------------------------------------------------------
* Retrieve the time components from a date instance as a string.
*/
CSStr FetchTimeObjStr(const Object & value);
/* ------------------------------------------------------------------------------------------------
* Retrieve the time components from a date instance as the number of seconds.
*/
Int32 FetchTimeObjSeconds(const Object & value);
/* ------------------------------------------------------------------------------------------------
* Retrieve the date-time components from a date-time instance.
*/
SQRESULT FetchDatetimeObjVal(const Object & value, Uint16 & year, Uint8 & month, Uint8 & day, Uint8 & hour,
Uint8 & minute, Uint8 & second);
/* ------------------------------------------------------------------------------------------------
* Retrieve the date-time components from a date-time instance.
*/
SQRESULT FetchDatetimeObjVal(const Object & value, Uint16 & year, Uint8 & month, Uint8 & day, Uint8 & hour,
Uint8 & minute, Uint8 & second, Uint16 & millisecond);
/* ------------------------------------------------------------------------------------------------
* Retrieve the date-time components from a date-time instance as a string.
*/
CSStr FetchDatetimeObjStr(const Object & value);
/* ------------------------------------------------------------------------------------------------
* Attempt to pop the value at the specified index on the stack as a native integer.
*/
SQInteger PopStackInteger(HSQUIRRELVM vm, SQInteger idx);
/* ------------------------------------------------------------------------------------------------
* Attempt to pop the value at the specified index on the stack as a native float.
*/
SQFloat PopStackFloat(HSQUIRRELVM vm, SQInteger idx);
/* ------------------------------------------------------------------------------------------------
* Attempt to pop the value at the specified index on the stack as a signed long integer.
*/
Int64 PopStackSLong(HSQUIRRELVM vm, SQInteger idx);
/* ------------------------------------------------------------------------------------------------
* Attempt to pop the value at the specified index on the stack as an unsigned long integer.
*/
Uint64 PopStackULong(HSQUIRRELVM vm, SQInteger idx);
// ------------------------------------------------------------------------------------------------
#ifdef SQMOD_PLUGIN_API
/* ------------------------------------------------------------------------------------------------
* Validate the module API to make sure we don't run into issues.
*/
bool CheckModuleAPIVer(CCStr ver, CCStr mod);
/* ------------------------------------------------------------------------------------------------
* Make sure that the module was loaded after the host plug-in.
*/
bool CheckModuleOrder(PluginFuncs * vcapi, Uint32 mod_id, CCStr mod);
/* ------------------------------------------------------------------------------------------------
* Used by the modules to import the API from the host plug-in.
*/
void ImportModuleAPI(PluginFuncs * vcapi, CCStr mod);
#endif // SQMOD_PLUGIN_API
} // Namespace:: SqMod
#endif // _BASE_UTILITY_HPP_