mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2026-04-23 04:27:22 +02:00
Compare commits
199 Commits
4090b558ad
...
8d15f4b6
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d15f4b6e9 | |||
| c0d142ab34 | |||
| f77ec9482f | |||
| 4fc1e892f7 | |||
| 015047a935 | |||
| bc1fc1d245 | |||
| 2a069f3040 | |||
| d295828545 | |||
| 483ac37bdb | |||
| 78dc76e6b4 | |||
| e29070af49 | |||
| 1f25b3ea60 | |||
| 52cfa235be | |||
| ec7f1183d8 | |||
| a788e059a5 | |||
| 5f20ffc4de | |||
| 08106156c4 | |||
| 60119ff8fa | |||
| f4720ae77a | |||
| c9fb257f48 | |||
| 475a428366 | |||
| 42ac0e32b7 | |||
| 3e75e36cdf | |||
| ac7d18f297 | |||
| 39473a68f4 | |||
| 5a57bf2fbf | |||
| 15e85f1394 | |||
| e8fa9e0259 | |||
| c551390999 | |||
| 804a5abb29 | |||
| 68551e4466 | |||
| 4618577ae4 | |||
| 2f428962c8 | |||
| 34a78dc166 | |||
| 49df7b75ee | |||
| 0d927f5d72 | |||
| 44243aadd2 | |||
| aa3952fd45 | |||
| ebe60ebf4b | |||
| fa9c3a5821 | |||
| f238588abe | |||
| 39524098f1 | |||
| ea63899c9a | |||
| 8f11e08150 | |||
| b8b5e89216 | |||
| 87387999f3 | |||
| d6a56feb87 | |||
| 9c94fb7afc | |||
| 2f3684e251 | |||
| 7afc05e52b | |||
| eca11b73ba | |||
| 5c54dc6a95 | |||
| 9330cd4eb3 | |||
| 7576409ceb | |||
| f278d151d6 | |||
| b3b57d5b2b | |||
| c4130c589f | |||
| 2d24860905 | |||
| eb90d9bc99 | |||
| b87e68b9fc | |||
| a1a71ee031 | |||
| c4b9b4c0a5 | |||
| b3f9f9e47a | |||
| a2421afca1 | |||
| e2cbd7d5cf | |||
| 2725387112 | |||
| 7248351469 | |||
| e253dc2038 | |||
| 38f0a53cd8 | |||
| 1c7fee69ea | |||
| 2b85b3a035 | |||
| 11fb1fa25c | |||
| 8dc0ca18f5 | |||
| 7e39fab21a | |||
| da139c6a81 | |||
| 27521f209d | |||
| e6cbdfaf30 | |||
| fd62cafe33 | |||
| d749250e1b | |||
| c205261ee9 | |||
| 4af93aff14 | |||
| d246ee8430 | |||
| 6419fc0f4d | |||
| 0213ffe632 | |||
| 5f364605ab | |||
| 3e9f25502b | |||
| 1d85603dfb | |||
| 259af04d0e | |||
| 4d1971d66b | |||
| b4bf96ce4b | |||
| f192767853 | |||
| a58b9fe267 | |||
| 4a8a7172d4 | |||
| cae745378d | |||
| 62b9504d43 | |||
| 26ccfa62b9 | |||
| 83f2ab79e0 | |||
| 57321af0c7 | |||
| 8d908208f0 | |||
| 87cb6a2cba | |||
| 0487f26865 | |||
| e3c32e4788 | |||
| b978bc5046 | |||
| 0f235ff6af | |||
| 7057939854 | |||
| eb3100de36 | |||
| f72c0f896e | |||
| 0d323f4a26 | |||
| 0c4c78da6e | |||
| 2011631e78 | |||
| 801ccbd6cd | |||
| 9062121cc8 | |||
| 596da38403 | |||
| aa2a8f32d1 | |||
| 13fc02e9ca | |||
| 17875509c0 | |||
| 5df55164ee | |||
| 45570af13b | |||
| 949e5e61d0 | |||
| e4aa96a8c3 | |||
| e60e2958f0 | |||
| dfee411de5 | |||
| 37383b9383 | |||
| ba4b8524e5 | |||
| f1ef37bdf3 | |||
| 9235cb5069 | |||
| 4e27ba4a4f | |||
| 19102a9334 | |||
| 1d8d31518c | |||
| a19a171e0d | |||
| 4c3921d88a | |||
| e9f5111a33 | |||
| 08a5ba3154 | |||
| 13a7a98abe | |||
| f8ebb0e2b1 | |||
| f49452c165 | |||
| 60467782e3 | |||
| 4f70f89b78 | |||
| f6cb8ff8a1 | |||
| 4876b37f7f | |||
| b46535dedf | |||
| ba82f742e1 | |||
| 66c731bf65 | |||
| 5dcc57a130 | |||
| 1bd1b5545b | |||
| 8288c32d41 | |||
| e577a96f7e | |||
| d947bf75f5 | |||
| 9cbac142c2 | |||
| db9586bc3d | |||
| 4cefc96faf | |||
| 608c444694 | |||
| cacc6c7c62 | |||
| 11c17189b3 | |||
| 1a11dd777e | |||
| 05e644b040 | |||
| f3d4dab454 | |||
| d787803fd8 | |||
| 81893bf236 | |||
| 9f808376b9 | |||
| cbfed04bc9 | |||
| 44ed4c849c | |||
| bc2260a0f0 | |||
| d879999aeb | |||
| d1bf8f5033 | |||
| f4c2665e86 | |||
| 31029cbaf0 | |||
| 5ea7364a6d | |||
| b67a637c61 | |||
| c0fc1aea75 | |||
| 2a06a00e3e | |||
| f23a2fe389 | |||
| 69a4d305a5 | |||
| 0008869ddd | |||
| fa4644d00f | |||
| b78b3e8ede | |||
| 21c9797d1a | |||
| 94f4459d5b | |||
| 88b084422d | |||
| 954f28c2dc | |||
| 9ca62af730 | |||
| 3c6c9bc47b | |||
| acadc852c4 | |||
| 7a3d92d1d1 | |||
| 151077c799 | |||
| a99e926088 | |||
| 490f80d1e9 | |||
| 1d2a78c91e | |||
| f23a8bc8f5 | |||
| 11f3c52319 | |||
| 2b1c76a05d | |||
| a36e85d9b7 | |||
| 2fb0f851c0 | |||
| 7655c1cb98 | |||
| 9d62233cfc | |||
| 503b61c3df | |||
| 181b0f4377 | |||
| cb359ed61e | |||
| ec01a80486 |
@@ -31,6 +31,12 @@ jobs:
|
||||
- name: Install Postgre SQL
|
||||
run: sudo apt-get -y install libpq-dev
|
||||
|
||||
- name: Install Sodium
|
||||
run: sudo apt-get -y install libsodium-dev
|
||||
|
||||
- name: Install GNUTLS
|
||||
run: sudo apt-get -y install libgnutls28-dev
|
||||
|
||||
- name: Install ZLib
|
||||
run: sudo apt-get -y install zlib1g-dev
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
/bin/*
|
||||
|
||||
# Exclude
|
||||
!/bin/demo
|
||||
!/vendor
|
||||
|
||||
# Hidden files and folders
|
||||
.*
|
||||
|
||||
+12
-6
@@ -1,6 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.7)
|
||||
project(SqMod)
|
||||
|
||||
# This plug-in only works on 64-bit
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
message(FATAL_ERROR "SqMod does not support 32-bit platforms anymore.")
|
||||
endif()
|
||||
|
||||
# Tell CMake where to find our scripts
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/vendor/POCO/cmake)
|
||||
@@ -8,10 +13,12 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/vendor/POCO/cmake)
|
||||
# Several plugin options
|
||||
option(ENABLE_API21 "Build for 2.1 API." OFF)
|
||||
option(ENABLE_OFFICIAL "Enable compatibility with official legacy plug-in" ON)
|
||||
option(FORCE_32BIT_BIN "Create a 32-bit executable binary if the compiler defaults to 64-bit." OFF)
|
||||
# As a fall-back for certain situations (mainly some docker ubuntu containers)
|
||||
option(ENABLE_BUILTIN_MYSQL_C "Enable built-in MySQL connector library" OFF)
|
||||
#option(FORCE_32BIT_BIN "Create a 32-bit executable binary if the compiler defaults to 64-bit." OFF)
|
||||
# This option should only be available in certain conditions
|
||||
if(WIN32 AND MINGW)
|
||||
option(COPY_DEPENDENCIES "Copy deppendent DLLs into the deps folder." OFF)
|
||||
option(COPY_DEPENDENCIES "Copy dependent DLLs into the deps folder." OFF)
|
||||
endif()
|
||||
|
||||
# C++14 is mandatory
|
||||
@@ -93,10 +100,9 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Determine if build mode
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "(Debug)+")
|
||||
add_compile_options(-g)
|
||||
endif()
|
||||
# Strip binary
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s -g")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s -g")
|
||||
|
||||
# Enable position independent code
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
@@ -300,6 +301,21 @@ String AABB::ToString() const
|
||||
return fmt::format("{},{},{},{},{},{}", min.x, min.y, min.z, max.x, max.y, max.z);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void AABB::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{min:{{x:{},y:{},z:{}}},max:{{x:{},y:{},z:{}}},",
|
||||
min.x, min.y, min.z, max.x, max.y, max.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{min:[{},{},{}],max:[{},{},{}]}},",
|
||||
min.x, min.y, min.z, max.x, max.y, max.z);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void AABB::SetStr(SQChar delim, StackStrF & values)
|
||||
{
|
||||
@@ -793,6 +809,7 @@ void Register_AABB(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< AABB >, SQFloat, SQInteger, bool, std::nullptr_t, AABB >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &AABB::ToString)
|
||||
.Func(_SC("_tojson"), &AABB::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< AABB >, SQFloat, SQInteger, bool, std::nullptr_t, AABB >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< AABB >, SQFloat, SQInteger, bool, std::nullptr_t, AABB >)
|
||||
|
||||
@@ -264,7 +264,12 @@ struct AABB
|
||||
*/
|
||||
SQMOD_NODISCARD int32_t Cmp(SQFloat s) const
|
||||
{
|
||||
#ifdef SQUSEDOUBLE
|
||||
auto f = static_cast< Value >(s);
|
||||
return Cmp(AABB(f, f, f, f, f, f));
|
||||
#else
|
||||
return Cmp(AABB(s, s, s, s, s, s));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -299,6 +304,11 @@ struct AABB
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set the values extracted from the specified string using the specified delimiter.
|
||||
*/
|
||||
|
||||
+19
-4
@@ -3,6 +3,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -360,6 +361,19 @@ String Circle::ToString() const
|
||||
return fmt::format("{},{},{}", pos.x, pos.y, rad);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Circle::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},r:{}}},", pos.x, pos.y, rad);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{}],", pos.x, pos.y, rad);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Circle::SetRadius(Value nr)
|
||||
{
|
||||
@@ -476,16 +490,16 @@ Array Circle::ToPointsArray(SQInteger num_segments) const
|
||||
if (i >= num_segments) return false;
|
||||
// Get the current angle
|
||||
#ifdef SQUSEDOUBLE
|
||||
SQFloat theta = 2.0d * SQMOD_PI64 * static_cast< SQFloat >(i) / static_cast< SQFloat >(num_segments);
|
||||
SQFloat theta = 2.0 * SQMOD_PI64 * static_cast< SQFloat >(i) / static_cast< SQFloat >(num_segments);
|
||||
#else
|
||||
SQFloat theta = 2.0f * SQMOD_PI * static_cast< SQFloat >(i) / static_cast< SQFloat >(num_segments);
|
||||
#endif // SQUSEDOUBLE
|
||||
// Calculate the x component
|
||||
SQFloat x = (rad * cosf(theta)) + pos.x;
|
||||
SQFloat x = (rad * std::cos(theta)) + pos.x;
|
||||
// Calculate the y component
|
||||
SQFloat y = (rad * sinf(theta)) + pos.y;
|
||||
SQFloat y = (rad * std::sin(theta)) + pos.y;
|
||||
// Push the Vector2 instance on the stack
|
||||
Var< Vector2 >::push(vm, Vector2{x, y});
|
||||
Var< Vector2 >::push(vm, Vector2{static_cast< Vector2::Value >(x), static_cast< Vector2::Value >(y)});
|
||||
// Insert the element on the stack into the array
|
||||
return true;
|
||||
}, num_segments);
|
||||
@@ -552,6 +566,7 @@ void Register_Circle(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Circle >, SQFloat, SQInteger, bool, std::nullptr_t, Circle >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &Circle::ToString)
|
||||
.Func(_SC("_toJSON"), &Circle::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Circle >, SQFloat, SQInteger, bool, std::nullptr_t, Circle >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Circle >, SQFloat, SQInteger, bool, std::nullptr_t, Circle >)
|
||||
|
||||
@@ -341,6 +341,11 @@ struct Circle
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set the specified radius.
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -481,6 +482,19 @@ String Color3::ToString() const
|
||||
return fmt::format("{},{},{}", r, g, b);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Color3::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{r:{},g:{},b:{}}},", r, g, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{}],", r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Color3::SetScalar(Value ns)
|
||||
{
|
||||
@@ -741,6 +755,7 @@ void Register_Color3(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Color3 >, SQFloat, SQInteger, bool, std::nullptr_t, Color3 >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &Color3::ToString)
|
||||
.Func(_SC("_tojson"), &Color3::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Color3 >, SQFloat, SQInteger, bool, std::nullptr_t, Color3 >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Color3 >, SQFloat, SQInteger, bool, std::nullptr_t, Color3 >)
|
||||
|
||||
@@ -405,6 +405,11 @@ struct Color3
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set all components to the specified scalar value.
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -506,6 +507,19 @@ String Color4::ToString() const
|
||||
return fmt::format("{},{},{},{}", r, g, b, a);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Color4::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{r:{},g:{},b:{},a:{}}},", r, g, b, a);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{},{}],", r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Color4::SetScalar(Value ns)
|
||||
{
|
||||
@@ -781,6 +795,7 @@ void Register_Color4(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Color4 >, SQFloat, SQInteger, bool, std::nullptr_t, Color4 >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &Color4::ToString)
|
||||
.Func(_SC("_tojson"), &Color4::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Color4 >, SQFloat, SQInteger, bool, std::nullptr_t, Color4 >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Color4 >, SQFloat, SQInteger, bool, std::nullptr_t, Color4 >)
|
||||
|
||||
@@ -405,6 +405,11 @@ struct Color4
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set all components to the specified scalar value.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -349,6 +350,19 @@ String Quaternion::ToString() const
|
||||
return fmt::format("{},{},{},{}", x, y, z, w);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Quaternion::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},z:{},w:{}}},", x, y, z, w);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{},{}],", x, y, z, w);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Quaternion::SetScalar(Value ns)
|
||||
{
|
||||
@@ -775,6 +789,7 @@ void Register_Quaternion(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Quaternion >, SQFloat, SQInteger, bool, std::nullptr_t, Quaternion >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &Quaternion::ToString)
|
||||
.Func(_SC("_tojson"), &Quaternion::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Quaternion >, SQFloat, SQInteger, bool, std::nullptr_t, Quaternion >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Quaternion >, SQFloat, SQInteger, bool, std::nullptr_t, Quaternion >)
|
||||
|
||||
@@ -296,6 +296,11 @@ struct Quaternion
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set all components to the specified scalar value.
|
||||
*/
|
||||
|
||||
@@ -807,7 +807,7 @@ static SQInteger SqPackARGB(SQInteger r, SQInteger g, SQInteger b, SQInteger a)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqNameFilterCheck(HSQUIRRELVM vm)
|
||||
{
|
||||
const int32_t top = sq_gettop(vm);
|
||||
SQInteger top = sq_gettop(vm);
|
||||
// Was the filter string specified?
|
||||
if (top <= 1)
|
||||
{
|
||||
@@ -1031,7 +1031,7 @@ const String CmpGE::FSTRV("Assertion failed. Value mismatch: {0} >= {1}"); // NO
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqNameFilterCheckInsensitive(HSQUIRRELVM vm)
|
||||
{
|
||||
const int32_t top = sq_gettop(vm);
|
||||
SQInteger top = sq_gettop(vm);
|
||||
// Was the filter string specified?
|
||||
if (top <= 1)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
struct CtxJSON;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Helper constants used by the bas types.
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -360,6 +361,19 @@ String Sphere::ToString() const
|
||||
return fmt::format("{},{},{},{}", pos.x, pos.y, pos.z, rad);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Sphere::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},z:{},r:{}}},", pos.x, pos.y, pos.z, rad);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{},{}],", pos.x, pos.y, pos.z, rad);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Sphere::SetRadius(Value nr)
|
||||
{
|
||||
@@ -527,6 +541,7 @@ void Register_Sphere(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Sphere >, SQFloat, SQInteger, bool, std::nullptr_t, Sphere >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &Sphere::ToString)
|
||||
.Func(_SC("_tojson"), &Sphere::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Sphere >, SQFloat, SQInteger, bool, std::nullptr_t, Sphere >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Sphere >, SQFloat, SQInteger, bool, std::nullptr_t, Sphere >)
|
||||
|
||||
@@ -341,6 +341,11 @@ struct Sphere
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set the specified radius.
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -295,6 +296,19 @@ String Vector2::ToString() const
|
||||
return fmt::format("{},{}", x, y);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Vector2::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{}}},", x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{}],", x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Vector2::SetScalar(Value ns)
|
||||
{
|
||||
@@ -428,6 +442,7 @@ void Register_Vector2(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector2 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2 >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &Vector2::ToString)
|
||||
.Func(_SC("_tojson"), &Vector2::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector2 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2 >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector2 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2 >)
|
||||
|
||||
@@ -285,6 +285,11 @@ struct Vector2
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set all components to the specified scalar value.
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -441,6 +442,19 @@ String Vector2i::ToString() const
|
||||
return fmt::format("{},{}", x, y);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Vector2i::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{}}},", x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{}],", x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Vector2i::SetScalar(Value ns)
|
||||
{
|
||||
@@ -574,6 +588,7 @@ void Register_Vector2i(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector2i >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2i >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &Vector2i::ToString)
|
||||
.Func(_SC("_tojson"), &Vector2i::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector2i >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2i >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector2i >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2i >)
|
||||
|
||||
@@ -390,6 +390,11 @@ struct Vector2i
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set all components to the specified scalar value.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -331,6 +332,19 @@ String Vector3::ToString() const
|
||||
return fmt::format("{},{},{}", x, y, z);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Vector3::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},z:{}}},", x, y, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{}],", x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Vector3::SetScalar(Value ns)
|
||||
{
|
||||
@@ -696,6 +710,7 @@ void Register_Vector3(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector3 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector3 >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &Vector3::ToString)
|
||||
.Func(_SC("_tojson"), &Vector3::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector3 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector3 >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector3 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector3 >)
|
||||
|
||||
@@ -297,6 +297,11 @@ struct Vector3
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set all components to the specified scalar value.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Base/DynArg.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/JSON.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -344,6 +345,19 @@ String Vector4::ToString() const
|
||||
return fmt::format("{},{},{},{}", x, y, z, w);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Vector4::ToJSON(CtxJSON & ctx) const
|
||||
{
|
||||
if (ctx.mObjectOverArray)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},z:{},w:{}}},", x, y, z, w);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{},{}],", x, y, z, w);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Vector4::SetScalar(Value ns)
|
||||
{
|
||||
@@ -526,6 +540,7 @@ void Register_Vector4(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector4 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector4 >)
|
||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||
.Func(_SC("_tostring"), &Vector4::ToString)
|
||||
.Func(_SC("_tojson"), &Vector4::ToJSON)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector4 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector4 >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector4 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector4 >)
|
||||
|
||||
@@ -295,6 +295,11 @@ struct Vector4
|
||||
*/
|
||||
SQMOD_NODISCARD String ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||
*/
|
||||
void ToJSON(CtxJSON & ctx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set all components to the specified scalar value.
|
||||
*/
|
||||
|
||||
+32
-15
@@ -1,5 +1,7 @@
|
||||
# Create the Squirrel module
|
||||
add_library(SqModule MODULE SqBase.hpp Main.cpp
|
||||
# SDK
|
||||
SDK/sqmod.h
|
||||
# VCMP
|
||||
VCMP/vcmp.h
|
||||
VCMP/vcmp20.h
|
||||
@@ -76,15 +78,17 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
|
||||
Library/IO/Stream.cpp Library/IO/Stream.hpp
|
||||
Library/JSON.cpp Library/JSON.hpp
|
||||
Library/MMDB.cpp Library/MMDB.hpp
|
||||
Library/Net.cpp Library/Net.hpp
|
||||
Library/Numeric.cpp Library/Numeric.hpp
|
||||
Library/Numeric/Long.cpp Library/Numeric/Long.hpp
|
||||
Library/Numeric/Math.cpp Library/Numeric/Math.hpp
|
||||
Library/Numeric/Random.cpp Library/Numeric/Random.hpp
|
||||
Library/RegEx.cpp Library/RegEx.hpp
|
||||
Library/String.cpp Library/String.hpp
|
||||
Library/System.cpp Library/System.hpp
|
||||
Library/System/Dir.cpp Library/System/Dir.hpp
|
||||
Library/System/Env.cpp Library/System/Env.hpp
|
||||
Library/System/Path.cpp Library/System/Path.hpp
|
||||
Library/UTF8.cpp Library/UTF8.hpp
|
||||
Library/Utils.cpp Library/Utils.hpp
|
||||
Library/Utils/Announce.cpp Library/Utils/Announce.hpp
|
||||
Library/Utils/String.cpp Library/Utils/String.hpp
|
||||
@@ -104,17 +108,15 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
|
||||
# POCO
|
||||
PocoLib/Crypto.cpp PocoLib/Crypto.hpp
|
||||
PocoLib/Data.cpp PocoLib/Data.hpp
|
||||
PocoLib/JSON.cpp PocoLib/JSON.hpp
|
||||
PocoLib/Net.cpp PocoLib/Net.hpp
|
||||
PocoLib/RegEx.cpp PocoLib/RegEx.hpp
|
||||
PocoLib/Register.cpp PocoLib/Register.hpp
|
||||
PocoLib/Time.cpp PocoLib/Time.hpp
|
||||
PocoLib/Util.cpp PocoLib/Util.hpp
|
||||
PocoLib/XML.cpp PocoLib/XML.hpp
|
||||
#
|
||||
Core.cpp Core.hpp
|
||||
Logger.cpp Logger.hpp
|
||||
Register.cpp
|
||||
Exports.cpp
|
||||
)
|
||||
# Various definitions required by the plug-in
|
||||
target_compile_definitions(SqModule PRIVATE SCRAT_USE_EXCEPTIONS=1)
|
||||
@@ -133,9 +135,9 @@ if(WIN32 OR MINGW)
|
||||
target_link_libraries(SqModule wsock32 ws2_32 shlwapi)
|
||||
endif()
|
||||
# Link to base libraries
|
||||
target_link_libraries(SqModule Squirrel fmt::fmt SimpleINI TinyDir ConcurrentQueue SAJSON CPR PUGIXML maxminddb libzmq-static)
|
||||
target_link_libraries(SqModule RPMalloc Squirrel fmt::fmt SimpleINI TinyDir xxHash ConcurrentQueue SAJSON CPR UTF8Lib PUGIXML CivetWeb maxminddb libzmq-static)
|
||||
# Link to POCO libraries
|
||||
target_link_libraries(SqModule Poco::Foundation Poco::Crypto Poco::Data Poco::Net Poco::JSON Poco::XML)
|
||||
target_link_libraries(SqModule Poco::Foundation Poco::Crypto Poco::Data Poco::Net)
|
||||
# Does POCO have SQLite support?
|
||||
if(ENABLE_DATA_SQLITE)
|
||||
if(NOT POCO_UNBUNDLED)
|
||||
@@ -150,9 +152,12 @@ if(ENABLE_DATA_SQLITE)
|
||||
# Include legacy implementation sources
|
||||
target_sources(SqModule PRIVATE Library/SQLite.hpp Library/SQLite.cpp)
|
||||
endif()
|
||||
# Do we have built-in MYSQL enabled?
|
||||
if (NOT ENABLE_BUILTIN_MYSQL_C)
|
||||
find_package(MySQL)
|
||||
endif()
|
||||
# Does POCO have MySLQ support?
|
||||
find_package(MySQL)
|
||||
if(MYSQL_FOUND)
|
||||
if(ENABLE_BUILTIN_MYSQL_C OR MYSQL_FOUND)
|
||||
message(STATUS "MySQL was enabled")
|
||||
# Link the libraries
|
||||
target_link_libraries(SqModule Poco::DataMySQL)
|
||||
@@ -175,6 +180,8 @@ if(${CMAKE_BUILD_TYPE} MATCHES "(Release)+")
|
||||
else()
|
||||
target_compile_definitions(SqModule PRIVATE _DEBUG=1 SQMOD_EXCEPTLOC=1)
|
||||
endif()
|
||||
# Strip binary
|
||||
set_target_properties(SqModule PROPERTIES LINK_FLAGS_RELEASE -s)
|
||||
# Force 32-bit binaries when necessary
|
||||
if(FORCE_32BIT_BIN)
|
||||
set_target_properties(SqModule PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
|
||||
@@ -197,8 +204,18 @@ else(WIN32)
|
||||
endif(WIN32)
|
||||
# Include current directory in the search path
|
||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/SDK)
|
||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/VCMP)
|
||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/Sqrat)
|
||||
# Include PCRE directory in the header search path
|
||||
if (POCO_UNBUNDLED)
|
||||
find_package(PCRE REQUIRED)
|
||||
target_link_libraries(SqModule PRIVATE Pcre::Pcre)
|
||||
else()
|
||||
# Get the foundation source folder path
|
||||
get_target_property(POCO_FOUNDATION_SOURCE_DIR Foundation SOURCE_DIR)
|
||||
target_include_directories(SqModule PRIVATE "${POCO_FOUNDATION_SOURCE_DIR}/src")
|
||||
endif()
|
||||
# Copy module into the plug-ins folder
|
||||
add_custom_command(TARGET SqModule POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:SqModule> "${PROJECT_SOURCE_DIR}/bin/plugins")
|
||||
# Copy several dependent DLLs on windows to make distribution easier (used mainly by people that distribute builds)
|
||||
@@ -209,12 +226,12 @@ if(WIN32 AND MINGW AND COPY_DEPENDENCIES)
|
||||
endif()
|
||||
# Make sure the deps folder exists
|
||||
file(MAKE_DIRECTORY "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
# Copy dependencies into the plug-ins folder (only so it can be distributed with the DLL)
|
||||
# Copy dependencies into the deps folder (only so it can be distributed with the DLL)
|
||||
file(COPY "${MINGW_BIN_PATH}/zlib1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libpq.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libzstd.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libpsl-5.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libffi-7.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libffi-8.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libcurl-4.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libssh2-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libidn2-0.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
@@ -232,17 +249,17 @@ if(WIN32 AND MINGW AND COPY_DEPENDENCIES)
|
||||
file(COPY "${MINGW_BIN_PATH}/libp11-kit-0.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libbrotlidec.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libbrotlicommon.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libunistring-2.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libunistring-5.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libnghttp2-14.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libwinpthread-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libstdc++-6.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT FORCE_32BIT_BIN)
|
||||
file(COPY "${MINGW_BIN_PATH}/libgcc_s_seh-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libssl-1_1-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libcrypto-1_1-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libssl-3-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libcrypto-3-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
else()
|
||||
file(COPY "${MINGW_BIN_PATH}/libssl-1_1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libcrypto-1_1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libssl-3.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
file(COPY "${MINGW_BIN_PATH}/libcrypto-3.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
endif()
|
||||
if(POCO_UNBUNDLED)
|
||||
file(COPY "${MINGW_BIN_PATH}/libexpat-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||
|
||||
+121
-8
@@ -48,6 +48,8 @@ extern void TerminatePrivileges();
|
||||
extern void TerminateRoutines();
|
||||
extern void TerminateCommands();
|
||||
extern void TerminateSignals();
|
||||
extern void TerminateNet();
|
||||
extern void TerminatePocoNet();
|
||||
extern void TerminatePocoData();
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -159,6 +161,7 @@ Core::Core() noexcept
|
||||
, m_Scripts()
|
||||
, m_PendingScripts()
|
||||
, m_Options()
|
||||
, m_ExtCommands{nullptr, nullptr, nullptr, nullptr}
|
||||
, m_Blips()
|
||||
, m_Checkpoints()
|
||||
, m_KeyBinds()
|
||||
@@ -439,9 +442,9 @@ bool Core::Execute()
|
||||
m_LockPostLoadSignal = false;
|
||||
m_LockUnloadSignal = false;
|
||||
|
||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to register their API");
|
||||
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins that the API is being registered");
|
||||
// Tell modules to do their monkey business
|
||||
//_Func->SendPluginCommand(0xDEADBABE, "");
|
||||
_Func->SendPluginCommand(SQMOD_LOAD_CMD, SQMOD_HOST_NAME);
|
||||
|
||||
// Load pending scripts while we're in the bounds of the allowed recursiveness
|
||||
for (unsigned levels = 0; !m_PendingScripts.empty() && (levels < 8); ++levels)
|
||||
@@ -509,9 +512,9 @@ void Core::Terminate(bool shutdown)
|
||||
// Clear the callbacks
|
||||
ResetSignalPair(mOnUnload);
|
||||
|
||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release their resources");
|
||||
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release their resources");
|
||||
// Tell modules to do their monkey business
|
||||
//_Func->SendPluginCommand(0xDEADC0DE, "");
|
||||
_Func->SendPluginCommand(SQMOD_TERMINATE_CMD, SQMOD_HOST_NAME);
|
||||
}
|
||||
|
||||
cLogDbg(m_Verbosity >= 1, "Clearing the entity containers");
|
||||
@@ -547,7 +550,11 @@ void Core::Terminate(bool shutdown)
|
||||
// Release announcers
|
||||
AnnounceTerminate();
|
||||
cLogDbg(m_Verbosity >= 1, "Announcer terminated");
|
||||
// Release network
|
||||
TerminateNet();
|
||||
cLogDbg(m_Verbosity >= 1, "Network terminated");
|
||||
// Release Poco statement results
|
||||
TerminatePocoNet();
|
||||
TerminatePocoData();
|
||||
cLogDbg(m_Verbosity >= 1, "Poco terminated");
|
||||
// Release ZMQ sockets
|
||||
@@ -590,9 +597,9 @@ void Core::Terminate(bool shutdown)
|
||||
HSQUIRRELVM sq_vm = m_VM;
|
||||
m_VM = nullptr;
|
||||
|
||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins the virtual machine is closing");
|
||||
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins the virtual machine is closing");
|
||||
// Tell modules to do their monkey business
|
||||
//_Func->SendPluginCommand(0xBAAAAAAD, "");
|
||||
_Func->SendPluginCommand(SQMOD_CLOSING_CMD, SQMOD_HOST_NAME);
|
||||
// Release any callbacks from the logger
|
||||
Logger::Get().Release();
|
||||
cLogDbg(m_Verbosity >= 2, "Closing Virtual Machine");
|
||||
@@ -623,9 +630,9 @@ void Core::Terminate(bool shutdown)
|
||||
// Destroy the VM context, if any
|
||||
delete ctx;
|
||||
|
||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release the virtual machine");
|
||||
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins the virtual machine was closed");
|
||||
// Tell modules to do their monkey business
|
||||
//_Func->SendPluginCommand(0xDEADBEAF, "");
|
||||
_Func->SendPluginCommand(SQMOD_RELEASED_CMD, SQMOD_HOST_NAME);
|
||||
}
|
||||
|
||||
OutputMessage("Squirrel plug-in was successfully terminated");
|
||||
@@ -898,6 +905,81 @@ String Core::FetchCodeLine(const SQChar * src, SQInteger line, bool trim)
|
||||
return script->FetchLine(line, trim);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int32_t Core::RegisterExtCommand(ExtPluginCommand_t fn)
|
||||
{
|
||||
ExtPluginCommand_t * slot = nullptr;
|
||||
// Find a free slot or matching function pointer in the pool
|
||||
for (size_t i = 0; i < m_ExtCommands.max_size(); ++i)
|
||||
{
|
||||
// Is this slot available and are we still looking for a slot?
|
||||
if (m_ExtCommands[i] == nullptr && slot == nullptr)
|
||||
{
|
||||
slot = &m_ExtCommands[i]; // Found a slot
|
||||
}
|
||||
// We keep looking for duplicates even if we found the slot
|
||||
else if (m_ExtCommands[i] == fn)
|
||||
{
|
||||
return 0; // Already registered
|
||||
}
|
||||
}
|
||||
// Do we have a free slot?
|
||||
if (slot != nullptr)
|
||||
{
|
||||
*slot = fn; // Use this slot
|
||||
return 1; // Successfully registered
|
||||
}
|
||||
// No space in the pool
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int32_t Core::UnregisterExtCommand(ExtPluginCommand_t fn)
|
||||
{
|
||||
// Find the matching function pointer
|
||||
for (size_t i = 0; i < m_ExtCommands.max_size(); ++i)
|
||||
{
|
||||
// Is this the same pointer?
|
||||
if (m_ExtCommands[i] != nullptr && m_ExtCommands[i] == fn)
|
||||
{
|
||||
// Forget about it
|
||||
m_ExtCommands[i] = nullptr;
|
||||
return 1; // Successfully unregistered
|
||||
}
|
||||
}
|
||||
// No space
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int32_t Core::SendExtCommand(int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size)
|
||||
{
|
||||
int32_t count = 0;
|
||||
// Send the command to all registered function pointers
|
||||
for (size_t i = 0; i < m_ExtCommands.max_size(); ++i)
|
||||
{
|
||||
if (m_ExtCommands[i] != nullptr)
|
||||
{
|
||||
const int32_t r = m_ExtCommands[i](target, req, tag, data, size);
|
||||
// Command processed
|
||||
++count;
|
||||
// Command failed?
|
||||
if (r < 0)
|
||||
{
|
||||
LogErr("External command failed (%i): target(%i), req(%i), tag(%i), data(%p), size (%zu)",
|
||||
r, target, req, tag, data, size);
|
||||
}
|
||||
// Command consumed?
|
||||
else if (r > 0)
|
||||
{
|
||||
break; // This function pointer requested exclusive access over this command
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return how many function pointers received this command
|
||||
return count;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool Core::DoScripts(Scripts::iterator itr, Scripts::iterator end)
|
||||
{
|
||||
@@ -2365,6 +2447,8 @@ void Core::InitEvents()
|
||||
InitSignalPair(mOnServerOption, m_Events, "ServerOption");
|
||||
InitSignalPair(mOnScriptReload, m_Events, "ScriptReload");
|
||||
InitSignalPair(mOnScriptLoaded, m_Events, "ScriptLoaded");
|
||||
InitSignalPair(mOnExtCommandReply, m_Events, "ExtCommandReply");
|
||||
InitSignalPair(mOnExtCommandEvent, m_Events, "ExtCommandEvent");
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Core::DropEvents()
|
||||
@@ -2510,6 +2594,8 @@ void Core::DropEvents()
|
||||
ResetSignalPair(mOnServerOption);
|
||||
ResetSignalPair(mOnScriptReload);
|
||||
ResetSignalPair(mOnScriptLoaded);
|
||||
ResetSignalPair(mOnExtCommandReply);
|
||||
ResetSignalPair(mOnExtCommandEvent);
|
||||
m_Events.Release();
|
||||
}
|
||||
|
||||
@@ -2855,6 +2941,31 @@ static LightObj & SqGetClientDataBuffer()
|
||||
return Core::Get().GetClientDataBuffer();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqSendExtCommand(int32_t target, int32_t req, int32_t tag, SqBuffer & buffer)
|
||||
{
|
||||
// Default to an empty/null buffer
|
||||
const uint8_t * data = nullptr;
|
||||
size_t size = 0;
|
||||
// Does the buffer actually point to anything?
|
||||
if (buffer.GetRef())
|
||||
{
|
||||
data = buffer.GetRef()->Begin< uint8_t >();
|
||||
size = buffer.GetRef()->PositionAs< size_t >();
|
||||
}
|
||||
// Forward the request
|
||||
return Core::Get().SendExtCommand(target, req, tag, data, size);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqSendExtCommandStr(int32_t target, int32_t req, int32_t tag, StackStrF & str)
|
||||
{
|
||||
// Forward the request
|
||||
return Core::Get().SendExtCommand(target, req, tag,
|
||||
reinterpret_cast< const uint8_t * >(str.mPtr),
|
||||
str.mLen <= 0 ? 0 : static_cast< size_t >(str.mLen));
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_Core(HSQUIRRELVM vm)
|
||||
{
|
||||
@@ -2904,6 +3015,8 @@ void Register_Core(HSQUIRRELVM vm)
|
||||
.Func(_SC("DestroyPickup"), &SqDelPickup)
|
||||
.Func(_SC("DestroyVehicle"), &SqDelVehicle)
|
||||
.Func(_SC("ClientDataBuffer"), &SqGetClientDataBuffer)
|
||||
.Func(_SC("SendExtCommand"), &SqSendExtCommand)
|
||||
.FmtFunc(_SC("SendExtCommandStr"), &SqSendExtCommandStr)
|
||||
.Func(_SC("OnPreLoad"), &SqGetPreLoadEvent)
|
||||
.Func(_SC("OnPostLoad"), &SqGetPostLoadEvent)
|
||||
.Func(_SC("OnUnload"), &SqGetUnloadEvent)
|
||||
|
||||
+105
-5
@@ -9,6 +9,9 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <unordered_map>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "SDK/sqmod.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
@@ -56,6 +59,8 @@ public:
|
||||
typedef std::vector< ScriptSrc > Scripts; // List of loaded scripts.
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef std::unordered_map< String, String > Options; // List of custom options.
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef std::array< ExtPluginCommand_t, 4 > ExtCommands; // 4 external command parsers should be enough.
|
||||
|
||||
private:
|
||||
|
||||
@@ -68,6 +73,7 @@ private:
|
||||
Scripts m_Scripts; // Loaded scripts objects.
|
||||
Scripts m_PendingScripts; // Pending scripts objects.
|
||||
Options m_Options; // Custom configuration options.
|
||||
ExtCommands m_ExtCommands; // External command parsers pointers.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Blips m_Blips; // Blips pool.
|
||||
@@ -399,6 +405,23 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD String FetchCodeLine(const SQChar * src, SQInteger line, bool trim = true);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Register a pointer to a function used to processes commands from script.
|
||||
* Returns -1 it failed (no free slot), 0 if it was already registered and 1 if it succeeded.
|
||||
*/
|
||||
int32_t RegisterExtCommand(ExtPluginCommand_t fn);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Remove a pointer to a function used to processes commands from script.
|
||||
* Returns -1 it failed (no free slot) and 1 if it succeeded.
|
||||
*/
|
||||
int32_t UnregisterExtCommand(ExtPluginCommand_t fn);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Send a command to all functions currently registered to receive them.
|
||||
*/
|
||||
int32_t SendExtCommand(int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size);
|
||||
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -710,6 +733,16 @@ public:
|
||||
*/
|
||||
void EmitClientScriptData(int32_t player_id, const uint8_t * data, size_t size);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Send a response to the script that may have resulted from a previous command.
|
||||
*/
|
||||
void EmitExtCommandReply(int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Forward an event to the script from an external plug-in.
|
||||
*/
|
||||
void EmitExtCommandEvent(int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -864,6 +897,8 @@ public:
|
||||
SignalPair mOnServerOption{};
|
||||
SignalPair mOnScriptReload{};
|
||||
SignalPair mOnScriptLoaded{};
|
||||
SignalPair mOnExtCommandReply{};
|
||||
SignalPair mOnExtCommandEvent{};
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -993,28 +1028,93 @@ template < class F > inline void ForeachActivePickup(F f) { ForeachActiveEntity(
|
||||
template < class F > inline void ForeachActivePlayer(F f) { ForeachActiveEntity(Core::Get().GetPlayers(), std::forward< F >(f)); }
|
||||
template < class F > inline void ForeachActiveVehicle(F f) { ForeachActiveEntity(Core::Get().GetVehicles(), std::forward< F >(f)); }
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Process the identifier of each player slot.
|
||||
*/
|
||||
template < class F > inline void ForeachPlayerSlot(F f) {
|
||||
for (int32_t i = 0, n = static_cast< int32_t >(_Func->GetMaxPlayers()); i < n; ++i) {
|
||||
f(i);
|
||||
}
|
||||
}
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Process the identifier of each player slot and count processed players.
|
||||
*/
|
||||
template < class F > SQMOD_NODISCARD inline int32_t ForeachPlayerSlotCount(F f) {
|
||||
int32_t c = 0;
|
||||
for (int32_t i = 0, n = static_cast< int32_t >(_Func->GetMaxPlayers()); i < n; ++i) {
|
||||
if (f(i)) ++c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Process the identifier of each player slot until a certain criteria is met.
|
||||
*/
|
||||
template < class F > SQMOD_NODISCARD inline int32_t ForeachPlayerSlotUntil(F f) {
|
||||
for (int32_t i = 0, n = static_cast< int32_t >(_Func->GetMaxPlayers()); i < n; ++i) {
|
||||
if (f(i)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Process the identifier of each connected player.
|
||||
*/
|
||||
template < class F > inline void ForeachConnectedPlayer(F f) {
|
||||
for (int32_t i = 0, n = _Func->GetMaxPlayers(); i < n; ++i) f(i);
|
||||
for (int32_t i = 0, n = static_cast< int32_t >(_Func->GetMaxPlayers()); i < n; ++i) {
|
||||
if (_Func->IsPlayerConnected(i) != 0) f(i);
|
||||
}
|
||||
}
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Process the identifier of each connected player and count processed players.
|
||||
*/
|
||||
template < class F > SQMOD_NODISCARD inline int32_t ForeachConnectedPlayerCount(F f) {
|
||||
int32_t c = 0;
|
||||
for (int32_t i = 0, n = _Func->GetMaxPlayers(); i < n; ++i)
|
||||
if (f(i)) ++c;
|
||||
for (int32_t i = 0, n = static_cast< int32_t >(_Func->GetMaxPlayers()); i < n; ++i) {
|
||||
if (_Func->IsPlayerConnected(i) != 0 && f(i)) ++c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Process the identifier of each connected player until a certain criteria is met.
|
||||
*/
|
||||
template < class F > SQMOD_NODISCARD inline int32_t ForeachConnectedPlayerUntil(F f) {
|
||||
for (int32_t i = 0, n = _Func->GetMaxPlayers(); i < n; ++i)
|
||||
if (f(i)) return i;
|
||||
for (int32_t i = 0, n = static_cast< int32_t >(_Func->GetMaxPlayers()); i < n; ++i) {
|
||||
if (_Func->IsPlayerConnected(i) != 0 && f(i)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Used to select entity instances based on type.
|
||||
*/
|
||||
template < class > struct EntityInstSelect;
|
||||
// Specialization for blips.
|
||||
template < > struct EntityInstSelect< CBlip > {
|
||||
static BlipInst & Get(int32_t id) { return Core::Get().GetBlip(id); }
|
||||
};
|
||||
// Specialization for checkpoints.
|
||||
template < > struct EntityInstSelect< CCheckpoint > {
|
||||
static CheckpointInst & Get(int32_t id) { return Core::Get().GetCheckpoint(id); }
|
||||
};
|
||||
// Specialization for keybinds.
|
||||
template < > struct EntityInstSelect< CKeyBind > {
|
||||
static KeyBindInst & Get(int32_t id) { return Core::Get().GetKeyBind(id); }
|
||||
};
|
||||
// Specialization for objects.
|
||||
template < > struct EntityInstSelect< CObject > {
|
||||
static ObjectInst & Get(int32_t id) { return Core::Get().GetObj(id); }
|
||||
};
|
||||
// Specialization for pickups.
|
||||
template < > struct EntityInstSelect< CPickup > {
|
||||
static PickupInst & Get(int32_t id) { return Core::Get().GetPickup(id); }
|
||||
};
|
||||
// Specialization for players.
|
||||
template < > struct EntityInstSelect< CPlayer > {
|
||||
static PlayerInst & Get(int32_t id) { return Core::Get().GetPlayer(id); }
|
||||
};
|
||||
// Specialization for vehicles.
|
||||
template < > struct EntityInstSelect< CVehicle > {
|
||||
static VehicleInst & Get(int32_t id) { return Core::Get().GetVehicle(id); }
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
+36
-8
@@ -53,7 +53,7 @@ void Area::AddCircleEx(SQFloat cx, SQFloat cy, SQFloat cr, SQInteger num_segment
|
||||
CheckLock();
|
||||
// Get the current angle
|
||||
#ifdef SQUSEDOUBLE
|
||||
SQFloat theta = 2.0d * SQMOD_PI64 * static_cast< SQFloat >(i) / static_cast< SQFloat >(num_segments);
|
||||
SQFloat theta = 2.0 * SQMOD_PI64 * static_cast< SQFloat >(i) / static_cast< SQFloat >(num_segments);
|
||||
#else
|
||||
SQFloat theta = 2.0f * SQMOD_PI * static_cast< SQFloat >(i) / static_cast< SQFloat >(num_segments);
|
||||
#endif // SQUSEDOUBLE
|
||||
@@ -62,9 +62,9 @@ void Area::AddCircleEx(SQFloat cx, SQFloat cy, SQFloat cr, SQInteger num_segment
|
||||
// Calculate the y component
|
||||
SQFloat y = (cr * std::sin(theta)) + cy;
|
||||
// Insert the point into the list
|
||||
mPoints.emplace_back(x, y);
|
||||
mPoints.emplace_back(static_cast< Vector2::Value >(x), static_cast< Vector2::Value >(y));
|
||||
// Update the bounding box
|
||||
Expand(x, y);
|
||||
Expand(static_cast< Vector2::Value >(x), static_cast< Vector2::Value >(y));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ bool Area::IsInside(float x, float y) const
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AreaManager::AreaManager(size_t sz) noexcept
|
||||
: m_Queue(), m_ProcList(), m_Grid{}
|
||||
: m_Queue(), m_ProcList(), m_Grid{}, m_Cells{}
|
||||
{
|
||||
// Negative half grid size (left)
|
||||
int l = (-GRIDH * CELLD);
|
||||
@@ -171,21 +171,30 @@ AreaManager::AreaManager(size_t sz) noexcept
|
||||
int r = (l + CELLD);
|
||||
// Positive half grid size (top)
|
||||
int t = abs(l);
|
||||
// Row/Column of the grid
|
||||
int row = 0, col = 0;
|
||||
// Initialize the grid cells
|
||||
for (auto & a : m_Grid)
|
||||
{
|
||||
// Reset the column
|
||||
col = 0;
|
||||
// Process row
|
||||
for (auto & c : a)
|
||||
{
|
||||
auto & cx = m_Cells[row][col];
|
||||
// Grab a reference to the cell
|
||||
// Configure the range of the cell
|
||||
c.mL = static_cast< float >(l);
|
||||
c.mB = static_cast< float >(b);
|
||||
c.mR = static_cast< float >(r);
|
||||
c.mT = static_cast< float >(t);
|
||||
c.mL = cx.mL = static_cast< float >(l);
|
||||
c.mB = cx.mB = static_cast< float >(b);
|
||||
c.mR = cx.mR = static_cast< float >(r);
|
||||
c.mT = cx.mT = static_cast< float >(t);
|
||||
// Reserve area memory if requested
|
||||
c.mAreas.reserve(sz);
|
||||
// Reset the locks on this area
|
||||
c.mLocks = 0;
|
||||
// Set the row and column
|
||||
c.mRow = row;
|
||||
c.mCol = col++;
|
||||
// Advance the left side
|
||||
l = r;
|
||||
// Advance the right side
|
||||
@@ -203,6 +212,8 @@ AreaManager::AreaManager(size_t sz) noexcept
|
||||
t -= CELLD;
|
||||
}
|
||||
}
|
||||
// Advance row
|
||||
++row;
|
||||
}
|
||||
// Reserve some space in the queue
|
||||
m_Queue.reserve(128);
|
||||
@@ -340,6 +351,21 @@ void AreaManager::RemoveArea(Area & a)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Vector2i AreaManager::LocateCell(float x, float y)
|
||||
{
|
||||
for (int r = 0; r < GRIDN; ++r)
|
||||
{
|
||||
for (int c = 0; c < GRIDN; ++c)
|
||||
{
|
||||
auto & bb = m_Cells[r][c];
|
||||
// Check whether point is inside cell
|
||||
if (bb.mL <= x && bb.mR >= x && bb.mB <= y && bb.mT >= y)
|
||||
{
|
||||
return {r, c}; // Is inside
|
||||
}
|
||||
}
|
||||
}
|
||||
// Point is out of bounds
|
||||
return {NOCELL, NOCELL};
|
||||
/*
|
||||
// Transform the world coordinates into a cell coordinates
|
||||
// and cast to integral after rounding the value
|
||||
int xc = static_cast< int >(std::round(x / CELLD));
|
||||
@@ -364,6 +390,7 @@ Vector2i AreaManager::LocateCell(float x, float y)
|
||||
}
|
||||
// Return the identified cell row and column
|
||||
return {GRIDH+xc, GRIDH-yc};
|
||||
*/
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -469,6 +496,7 @@ void Register_Areas(HSQUIRRELVM vm)
|
||||
.Func(_SC("TestEx"), &Area::TestEx)
|
||||
.Func(_SC("Manage"), &Area::Manage)
|
||||
.Func(_SC("Unmanage"), &Area::Unmanage)
|
||||
.CbFunc(_SC("EachCell"), &Area::EachCell)
|
||||
// Static Functions
|
||||
.StaticFunc(_SC("GlobalTest"), &Areas_TestPoint)
|
||||
.StaticFunc(_SC("GlobalTestEx"), &Areas_TestPointEx)
|
||||
|
||||
+28
-4
@@ -29,15 +29,25 @@ struct AreaCell
|
||||
Areas mAreas; // Areas that intersect with the cell.
|
||||
// --------------------------------------------------------------------------------------------
|
||||
int mLocks; // The amount of locks on the cell.
|
||||
int mRow; // Row location in the grid.
|
||||
int mCol; // Column location in the grid.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
AreaCell()
|
||||
: mL(0), mB(0), mR(0), mT(0), mAreas(0), mLocks(0)
|
||||
: mL(0), mB(0), mR(0), mT(0), mAreas(0), mLocks(0), mRow(0), mCol(0)
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Show information (mainly for debug purposes).
|
||||
*/
|
||||
String Dump()
|
||||
{
|
||||
return fmt::format("({} : {} | {} : {}) {} : {}", mL, mB, mR, mT, mRow, mCol);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -454,6 +464,17 @@ struct Area
|
||||
*/
|
||||
bool Unmanage();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Iterate all managed cells through a functor.
|
||||
*/
|
||||
void EachCell(Function & fn) const
|
||||
{
|
||||
for (const auto & e : mCells)
|
||||
{
|
||||
fn.Execute(static_cast< SQInteger >(e->mRow), static_cast< SQInteger >(e->mCol));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -610,7 +631,10 @@ private:
|
||||
ProcList m_ProcList; // Actions ready to be completed.
|
||||
// --------------------------------------------------------------------------------------------
|
||||
AreaCell m_Grid[GRIDN][GRIDN]; // A grid of area lists.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
struct {
|
||||
float mL, mB, mR, mT;
|
||||
} m_Cells[GRIDN][GRIDN];
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -664,7 +688,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Clear all cell lists and release any script references.
|
||||
*/
|
||||
static Vector2i LocateCell(float x, float y);
|
||||
Vector2i LocateCell(float x, float y);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Test a point to see whether it intersects with any areas
|
||||
@@ -679,7 +703,7 @@ public:
|
||||
return; // Not our problem
|
||||
}
|
||||
// Retrieve a reference to the identified cell
|
||||
AreaCell & c = m_Grid[cc.y][cc.x];
|
||||
AreaCell & c = m_Grid[cc.x][cc.y];
|
||||
// Is this cell empty?
|
||||
if (c.mAreas.empty())
|
||||
{
|
||||
|
||||
+34
-21
@@ -148,6 +148,7 @@ public:
|
||||
: m_Ptr(o.m_Ptr), m_Cap(o.m_Cap), m_Cur(o.m_Cur)
|
||||
{
|
||||
o.m_Ptr = nullptr;
|
||||
o.m_Cap = o.m_Cur = 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -175,6 +176,7 @@ public:
|
||||
m_Cap = o.m_Cap;
|
||||
m_Cur = o.m_Cur;
|
||||
o.m_Ptr = nullptr;
|
||||
o.m_Cap = o.m_Cur = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -283,13 +285,13 @@ public:
|
||||
// Make sure that the buffer can host at least one element of this type
|
||||
if (m_Cap < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Make sure that the specified element is withing buffer range
|
||||
else if (n > (m_Cap - sizeof(T)))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Element of size (%d) at index (%u) is out of buffer capacity (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Element of size ({}) at index ({}) is out of buffer capacity ({})"),
|
||||
sizeof(T), n, m_Cap);
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -304,13 +306,13 @@ public:
|
||||
// Make sure that the buffer can host at least one element of this type
|
||||
if (m_Cap < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Make sure that the specified element is withing buffer range
|
||||
else if (n > (m_Cap - sizeof(T)))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Element of size (%d) at index (%u) is out of buffer capacity (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Element of size ({}) at index ({}) is out of buffer capacity ({})"),
|
||||
sizeof(T), n, m_Cap);
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -357,7 +359,7 @@ public:
|
||||
// Make sure that the buffer can host at least one element of this type
|
||||
if (m_Cap < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -372,7 +374,7 @@ public:
|
||||
// Make sure that the buffer can host at least one element of this type
|
||||
if (m_Cap < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -387,7 +389,7 @@ public:
|
||||
// Make sure that the buffer can host at least two elements of this type
|
||||
if (m_Cap < (sizeof(T) * 2))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host two elements of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host two elements of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -402,7 +404,7 @@ public:
|
||||
// Make sure that the buffer can host at least two elements of this type
|
||||
if (m_Cap < (sizeof(T) * 2))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host two elements of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host two elements of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -417,7 +419,7 @@ public:
|
||||
// Make sure that the buffer can host at least one element of this type
|
||||
if (m_Cap < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -432,7 +434,7 @@ public:
|
||||
// Make sure that the buffer can host at least one element of this type
|
||||
if (m_Cap < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -447,7 +449,7 @@ public:
|
||||
// Make sure that the buffer can host at least two elements of this type
|
||||
if (m_Cap < (sizeof(T) * 2))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host two elements of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host two elements of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -462,7 +464,7 @@ public:
|
||||
// Make sure that the buffer can host at least two elements of this type
|
||||
if (m_Cap < (sizeof(T) * 2))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host two elements of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host two elements of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -538,7 +540,7 @@ public:
|
||||
// Make sure that at least one element of this type exists after the cursor
|
||||
if ((m_Cur + sizeof(T)) > m_Cap)
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Element of size ({}) starting at ({}) exceeds buffer capacity ({})"),
|
||||
sizeof(T), m_Cur, m_Cap);
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -553,7 +555,7 @@ public:
|
||||
// Make sure that at least one element of this type exists after the cursor
|
||||
if ((m_Cur + sizeof(T)) > m_Cap)
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Element of size ({}) starting at ({}) exceeds buffer capacity ({})"),
|
||||
sizeof(T), m_Cur, m_Cap);
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -568,7 +570,7 @@ public:
|
||||
// The cursor must have at least one element of this type behind
|
||||
if (m_Cur < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Cannot read an element of size (%u) before the cursor at (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Cannot read an element of size ({}) before the cursor at ({})"),
|
||||
sizeof(T), m_Cur);
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -583,7 +585,7 @@ public:
|
||||
// The cursor must have at least one element of this type behind
|
||||
if (m_Cur < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Cannot read an element of size (%u) before the cursor at (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Cannot read an element of size ({}) before the cursor at ({})"),
|
||||
sizeof(T), m_Cur);
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -598,13 +600,13 @@ public:
|
||||
// Make sure that the buffer can host at least one element of this type
|
||||
if (m_Cap < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// There must be buffer left for at least two elements of this type after the cursor
|
||||
else if ((m_Cur + (sizeof(T) * 2)) > m_Cap)
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Element of size ({}) starting at ({}) exceeds buffer capacity ({})"),
|
||||
sizeof(T), m_Cur + sizeof(T), m_Cap);
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -619,13 +621,13 @@ public:
|
||||
// Make sure that the buffer can host at least one element of this type
|
||||
if (m_Cap < sizeof(T))
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||
m_Cap, sizeof(T));
|
||||
}
|
||||
// There must be buffer left for at least two elements of this type after the cursor
|
||||
else if ((m_Cur + (sizeof(T) * 2)) > m_Cap)
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)"),
|
||||
ThrowMemExcept(fmt::runtime("Element of size ({}) starting at ({}) exceeds buffer capacity ({})"),
|
||||
sizeof(T), m_Cur + sizeof(T), m_Cap);
|
||||
}
|
||||
// Return the requested element
|
||||
@@ -706,7 +708,7 @@ public:
|
||||
// See if the requested capacity doesn't exceed the limit
|
||||
if (n > Max< T >())
|
||||
{
|
||||
ThrowMemExcept(fmt::runtime("Requested buffer of (%u) elements exceeds the (%u) limit"), n, Max< T >());
|
||||
ThrowMemExcept(fmt::runtime("Requested buffer of ({}) elements exceeds the ({}) limit"), n, Max< T >());
|
||||
}
|
||||
// Is there an existing buffer?
|
||||
else if (n && !m_Cap)
|
||||
@@ -856,6 +858,17 @@ public:
|
||||
m_Cur += Write(m_Cur, str, size);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Steal ownership of the internal memory buffer. Whoever gets hold of the buffer must invoke delete [] on it.
|
||||
*/
|
||||
SQMOD_NODISCARD Pointer Steal()
|
||||
{
|
||||
Pointer ptr = m_Ptr;
|
||||
m_Ptr = nullptr;
|
||||
m_Cap = m_Cur = 0; // Save this before calling this method
|
||||
return ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
|
||||
+13
-75
@@ -2,7 +2,6 @@
|
||||
#include "Core/Common.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cerrno>
|
||||
@@ -149,7 +148,7 @@ void SqThrowLastF(const SQChar * msg, ...)
|
||||
// Now it's safe to throw the error
|
||||
SqThrowF(fmt::runtime("{} [{}]"), b.Data(), message);
|
||||
#else
|
||||
SqThrowF("{} [{}]", b.Data(), std::strerror(errno));
|
||||
SqThrowF(fmt::runtime("{} [{}]"), b.Data(), std::strerror(errno));
|
||||
#endif // SQMOD_OS_WINDOWS
|
||||
}
|
||||
|
||||
@@ -249,6 +248,14 @@ String SqTypeName(HSQUIRRELVM vm, SQInteger idx)
|
||||
return String(val.mPtr, static_cast< size_t >(val.mLen));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
String SqTypeName(HSQUIRRELVM vm, LightObj & obj)
|
||||
{
|
||||
const StackGuard sg(vm);
|
||||
sq_pushobject(vm, obj);
|
||||
return SqTypeName(vm, -1);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj BufferToStrObj(const Buffer & b)
|
||||
{
|
||||
@@ -313,46 +320,10 @@ SQInteger PopStackInteger(HSQUIRRELVM vm, SQInteger idx)
|
||||
case OT_TABLE:
|
||||
case OT_CLASS:
|
||||
case OT_USERDATA:
|
||||
{
|
||||
return sq_getsize(vm, idx);
|
||||
}
|
||||
case OT_INSTANCE:
|
||||
{
|
||||
SQUserPointer tag;
|
||||
// Attempt to retrieve the type tag
|
||||
if (SQ_FAILED(sq_gettypetag(vm, -1, &tag)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Is the instance SLongInt? (signed long)
|
||||
else if (static_cast< AbstractStaticClassData * >(tag) == StaticClassTypeTag< SLongInt >::Get())
|
||||
{
|
||||
try
|
||||
{
|
||||
return ConvTo< SQInteger >::From(Var< const SLongInt & >(vm, idx).value.GetNum());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Just ignore it...
|
||||
}
|
||||
}
|
||||
// Is the instance ULongInt? (unsigned long)
|
||||
else if (static_cast< AbstractStaticClassData * >(tag) == StaticClassTypeTag< ULongInt >::Get())
|
||||
{
|
||||
try
|
||||
{
|
||||
return ConvTo< SQInteger >::From(Var< const ULongInt & >(vm, idx).value.GetNum());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Just ignore it...
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempt to get the size of the instance as a fall back
|
||||
return sq_getsize(vm, idx);
|
||||
}
|
||||
// Attempt to get the size of the instance as a fall back
|
||||
return sq_getsize(vm, idx);
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
@@ -406,41 +377,8 @@ SQFloat PopStackFloat(HSQUIRRELVM vm, SQInteger idx)
|
||||
}
|
||||
case OT_INSTANCE:
|
||||
{
|
||||
SQUserPointer tag;
|
||||
// Attempt to retrieve the type tag
|
||||
if (SQ_FAILED(sq_gettypetag(vm, -1, &tag)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Is the instance SLongInt? (signed long)
|
||||
else if (static_cast< AbstractStaticClassData * >(tag) == StaticClassTypeTag< SLongInt >::Get())
|
||||
{
|
||||
try
|
||||
{
|
||||
return ConvTo< SQFloat >::From(Var< const SLongInt & >(vm, idx).value.GetNum());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Just ignore it...
|
||||
}
|
||||
}
|
||||
// Is the instance ULongInt? (unsigned long)
|
||||
else if (static_cast< AbstractStaticClassData * >(tag) == StaticClassTypeTag< ULongInt >::Get())
|
||||
{
|
||||
try
|
||||
{
|
||||
return ConvTo< SQFloat >::From(Var< const ULongInt & >(vm, idx).value.GetNum());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Just ignore it...
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempt to get the size of the instance as a fall back
|
||||
return ConvTo< SQFloat >::From(sq_getsize(vm, idx));
|
||||
}
|
||||
// Attempt to get the size of the instance as a fall back
|
||||
return ConvTo< SQFloat >::From(sq_getsize(vm, idx));
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
+98
-3
@@ -40,6 +40,7 @@
|
||||
#include <sqratTable.h>
|
||||
#include <sqratUtil.h>
|
||||
#include <fmt/core.h>
|
||||
#include <rpmalloc.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
@@ -171,9 +172,9 @@ void OutputMessage(const char * msg, ...);
|
||||
void OutputError(const char * msg, ...);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Generate a formatted string and throw it as a sqrat exception.
|
||||
* Generate a formatted string and throw it as a Sqrat exception.
|
||||
*/
|
||||
template < class... Args > void SqThrowF(Args &&... args)
|
||||
template < class... Args > inline void SqThrowF(Args &&... args)
|
||||
{
|
||||
throw Sqrat::Exception(fmt::format(std::forward< Args >(args)...));
|
||||
}
|
||||
@@ -181,7 +182,7 @@ template < class... Args > void SqThrowF(Args &&... args)
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Generate a formatted string and throw it as a squirrel exception.
|
||||
*/
|
||||
template < class... Args > SQRESULT SqThrowErrorF(HSQUIRRELVM vm, Args &&... args)
|
||||
template < class... Args > inline SQRESULT SqThrowErrorF(HSQUIRRELVM vm, Args &&... args)
|
||||
{
|
||||
String msg;
|
||||
try
|
||||
@@ -241,6 +242,11 @@ SQMOD_NODISCARD const SQChar * SqTypeName(SQObjectType type);
|
||||
*/
|
||||
SQMOD_NODISCARD String SqTypeName(HSQUIRRELVM vm, SQInteger idx);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the string representation of a certain type from a script object.
|
||||
*/
|
||||
SQMOD_NODISCARD String SqTypeName(HSQUIRRELVM vm, LightObj & obj);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Create a script string instance from a buffer.
|
||||
*/
|
||||
@@ -266,4 +272,93 @@ SQMOD_NODISCARD SQFloat PopStackFloat(HSQUIRRELVM vm, SQInteger idx);
|
||||
*/
|
||||
SQMOD_NODISCARD bool SToB(const SQChar * str);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* RAII allocator initializer.
|
||||
*/
|
||||
struct RPMallocInit
|
||||
{
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
RPMallocInit()
|
||||
{
|
||||
if (rpmalloc_initialize() != 0)
|
||||
{
|
||||
OutputError("Failed to initialize memory allocator");
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor (disabled).
|
||||
*/
|
||||
RPMallocInit(const RPMallocInit &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor (disabled).
|
||||
*/
|
||||
RPMallocInit(RPMallocInit &&) noexcept = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~RPMallocInit()
|
||||
{
|
||||
if (rpmalloc_is_thread_initialized()) rpmalloc_finalize();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator (disabled).
|
||||
*/
|
||||
RPMallocInit & operator = (const RPMallocInit &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator (disabled).
|
||||
*/
|
||||
RPMallocInit & operator = (RPMallocInit &&) noexcept = delete;
|
||||
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* RAII allocator thread initializer.
|
||||
*/
|
||||
struct RPMallocThreadInit
|
||||
{
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
RPMallocThreadInit()
|
||||
{
|
||||
rpmalloc_thread_initialize();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor (disabled).
|
||||
*/
|
||||
RPMallocThreadInit(const RPMallocThreadInit &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor (disabled).
|
||||
*/
|
||||
RPMallocThreadInit(RPMallocThreadInit &&) noexcept = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~RPMallocThreadInit()
|
||||
{
|
||||
if (rpmalloc_is_thread_initialized()) rpmalloc_thread_finalize(1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator (disabled).
|
||||
*/
|
||||
RPMallocThreadInit & operator = (const RPMallocThreadInit &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator (disabled).
|
||||
*/
|
||||
RPMallocThreadInit & operator = (RPMallocThreadInit &&) noexcept = delete;
|
||||
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
+43
-4
@@ -347,7 +347,7 @@ void Core::EmitIncomingConnection(char * player_name, size_t name_buffer_size, c
|
||||
// Release any stored buffer information
|
||||
m_IncomingNameBuffer = nullptr;
|
||||
m_IncomingNameCapacity = 0;
|
||||
// We catched the exception so we can release the assigned buffer
|
||||
// We caught the exception so we can release the assigned buffer
|
||||
throw; // re-throw it
|
||||
}
|
||||
// Release any stored buffer information
|
||||
@@ -392,7 +392,8 @@ void Core::EmitPlayerRequestSpawn(int32_t player_id)
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
if (IsOfficial())
|
||||
{
|
||||
ExecuteLegacyEvent(m_VM, _SC("onPlayerRequestSpawn"), _player.mLgObj);
|
||||
LightObj r = EvaluateLegacyEvent(m_VM, _SC("onPlayerRequestSpawn"), _player.mLgObj);
|
||||
SetState(r.IsNull() ? 1 : r.Cast< int32_t >());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -444,7 +445,7 @@ void Core::EmitPlayerKilled(int32_t player_id, int32_t killer_id, int32_t reason
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
if (IsOfficial())
|
||||
{
|
||||
if (!team_kill)
|
||||
if (team_kill)
|
||||
{
|
||||
ExecuteLegacyEvent(m_VM, _SC("onPlayerTeamKill"), _killer.mLgObj, _player.mLgObj, reason, static_cast< int32_t >(body_part));
|
||||
}
|
||||
@@ -1743,7 +1744,7 @@ void Core::EmitEntityPool(vcmpEntityPool entity_type, int32_t entity_id, bool is
|
||||
break;
|
||||
case vcmpEntityPoolRadio:
|
||||
// @TODO Implement...
|
||||
//break;
|
||||
break;
|
||||
#if SQMOD_SDK_LEAST(2, 1)
|
||||
case vcmpEntityPoolPlayer:
|
||||
// @TODO Implement...
|
||||
@@ -2245,6 +2246,44 @@ void Core::EmitClientScriptData(int32_t player_id, const uint8_t * data, size_t
|
||||
m_ClientData.Release();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Core::EmitExtCommandReply(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||
{
|
||||
SQMOD_CO_EV_TRACEBACK("[TRACE<] Core::ExtCommandReply(%i, %i, %p, %zu)", sender, tag, data, size)
|
||||
// Don't even bother if there's no one listening
|
||||
if (!(mOnExtCommandReply.first->IsEmpty()))
|
||||
{
|
||||
// Allocate a buffer with the received size
|
||||
Buffer b(static_cast< Buffer::SzType >(size));
|
||||
// Replicate the data to the allocated buffer
|
||||
b.Write(0, reinterpret_cast< Buffer::ConstPtr >(data), static_cast< Buffer::SzType >(size));
|
||||
// Prepare an object for the obtained buffer
|
||||
LightObj obj(SqTypeIdentity< SqBuffer >{}, m_VM, std::move(b));
|
||||
// Forward the event call
|
||||
(*mOnExtCommandReply.first)(sender, tag, obj, size);
|
||||
}
|
||||
SQMOD_CO_EV_TRACEBACK("[TRACE>] Core::ExtCommandReply")
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Core::EmitExtCommandEvent(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||
{
|
||||
SQMOD_CO_EV_TRACEBACK("[TRACE<] Core::ExtCommandEvent(%i, %i, %p, %zu)", sender, tag, data, size)
|
||||
// Don't even bother if there's no one listening
|
||||
if (!(mOnExtCommandEvent.first->IsEmpty()))
|
||||
{
|
||||
// Allocate a buffer with the received size
|
||||
Buffer b(static_cast< Buffer::SzType >(size));
|
||||
// Replicate the data to the allocated buffer
|
||||
b.Write(0, reinterpret_cast< Buffer::ConstPtr >(data), static_cast< Buffer::SzType >(size));
|
||||
// Prepare an object for the obtained buffer
|
||||
LightObj obj(SqTypeIdentity< SqBuffer >{}, m_VM, std::move(b));
|
||||
// Forward the event call
|
||||
(*mOnExtCommandEvent.first)(sender, tag, obj, size);
|
||||
}
|
||||
SQMOD_CO_EV_TRACEBACK("[TRACE>] Core::ExtCommandEvent")
|
||||
}
|
||||
|
||||
#undef NULL_SQOBJ_ // don't need this anymore
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
@@ -549,6 +549,8 @@ void Register_Routine(HSQUIRRELVM vm)
|
||||
.Prop(_SC("Inactive"), &Routine::GetInactive)
|
||||
.Prop(_SC("Persistent"), &Routine::GetPersistent, &Routine::SetPersistent)
|
||||
.Prop(_SC("Yields"), &Routine::GetYields, &Routine::SetYields)
|
||||
.Prop(_SC("Elapsed"), &Routine::GetElapsed)
|
||||
.Prop(_SC("Remaining"), &Routine::GetRemaining)
|
||||
.Prop(_SC("Terminated"), &Routine::GetTerminated)
|
||||
.Prop(_SC("Arguments"), &Routine::GetArguments)
|
||||
// Member Methods
|
||||
|
||||
+27
-1
@@ -408,7 +408,6 @@ public:
|
||||
}
|
||||
// Unable to find such routine
|
||||
STHROWF("Unable to fetch a routine with tag ({}). No such routine", tag.mPtr);
|
||||
SQ_UNREACHABLE
|
||||
// Should not reach this point but if it did, we have to return something
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
@@ -418,6 +417,7 @@ public:
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
SQ_UNREACHABLE
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -804,6 +804,32 @@ public:
|
||||
return (m_Slot == SQMOD_MAX_ROUTINES);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the time elapsed since the routine was created or invoked.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger GetElapsed() const
|
||||
{
|
||||
if (m_Slot >= SQMOD_MAX_ROUTINES)
|
||||
{
|
||||
STHROWF("This instance does not reference a valid routine");
|
||||
}
|
||||
// We know it's valid so let's return it
|
||||
return s_Instances[m_Slot].mInterval - s_Intervals[m_Slot];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the time remaining until the routine is invoked.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger GetRemaining() const
|
||||
{
|
||||
if (m_Slot >= SQMOD_MAX_ROUTINES)
|
||||
{
|
||||
STHROWF("This instance does not reference a valid routine");
|
||||
}
|
||||
// We know it's valid so let's return it
|
||||
return s_Intervals[m_Slot];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the number of arguments to be forwarded.
|
||||
*/
|
||||
|
||||
@@ -1723,6 +1723,7 @@ void Register_Signal(HSQUIRRELVM vm)
|
||||
.SquirrelFunc(_SC("Eliminate"), &Signal::SqEliminate)
|
||||
.SquirrelFunc(_SC("EliminateThis"), &Signal::SqEliminateThis)
|
||||
.SquirrelFunc(_SC("EliminateFunc"), &Signal::SqEliminateFunc)
|
||||
.SquirrelFunc(_SC("Broadcast"), &Signal::SqEmit)
|
||||
.SquirrelFunc(_SC("Emit"), &Signal::SqEmit)
|
||||
.SquirrelFunc(_SC("Query"), &Signal::SqQuery)
|
||||
.SquirrelFunc(_SC("Consume"), &Signal::SqConsume)
|
||||
|
||||
+40
-9
@@ -328,17 +328,40 @@ SQInteger Tasks::Find(int32_t id, int32_t type, SQInteger & pos, HSQUIRRELVM vm)
|
||||
{
|
||||
// Grab the top of the stack
|
||||
const SQInteger top = sq_gettop(vm);
|
||||
// Was there a callback specified?
|
||||
// Was there a callback or tag specified?
|
||||
if (top <= 1)
|
||||
{
|
||||
return sq_throwerror(vm, "Missing task callback");
|
||||
return sq_throwerror(vm, "Missing task callback or tag");
|
||||
}
|
||||
|
||||
SQRESULT res = SQ_OK;
|
||||
// Grab the hash of the callback object
|
||||
const SQHash chash = sq_gethash(vm, 2);
|
||||
// Fetch the task identifier type
|
||||
const SQObjectType ot = sq_gettype(vm, 2);
|
||||
// Are we looking for a task with a specific tag?
|
||||
if (ot == OT_STRING)
|
||||
{
|
||||
// Attempt to retrieve the value from the stack as a string
|
||||
StackStrF tag(vm, 2);
|
||||
// Have we failed to retrieve the string?
|
||||
if (SQ_FAILED(tag.Proc(true)))
|
||||
{
|
||||
return tag.mRes; // Propagate the error!
|
||||
}
|
||||
// Attempt to find the requested task
|
||||
for (const auto & t : s_Tasks)
|
||||
{
|
||||
if (t.mEntity == id && t.mType == type && t.mTag.compare(0, String::npos, tag.mPtr) == 0)
|
||||
{
|
||||
pos = static_cast< SQInteger >(&t - s_Tasks); // Store the index of this element
|
||||
}
|
||||
}
|
||||
}
|
||||
// Validate the callback type
|
||||
else if (ot != OT_CLOSURE && ot != OT_NATIVECLOSURE)
|
||||
{
|
||||
return sq_throwerror(vm, "Invalid callback type");
|
||||
}
|
||||
// Should we include the iterations in the criteria?
|
||||
if (top > 3)
|
||||
else if (top > 3)
|
||||
{
|
||||
SQInteger intrv = 0;
|
||||
// Grab the interval from the stack
|
||||
@@ -348,6 +371,8 @@ SQInteger Tasks::Find(int32_t id, int32_t type, SQInteger & pos, HSQUIRRELVM vm)
|
||||
{
|
||||
return res; // Propagate the error
|
||||
}
|
||||
// Grab the hash of the callback object
|
||||
const SQHash chash = sq_gethash(vm, 2);
|
||||
// Attempt to find the requested task
|
||||
for (const auto & t : s_Tasks)
|
||||
{
|
||||
@@ -375,6 +400,8 @@ SQInteger Tasks::Find(int32_t id, int32_t type, SQInteger & pos, HSQUIRRELVM vm)
|
||||
{
|
||||
return res; // Propagate the error
|
||||
}
|
||||
// Grab the hash of the callback object
|
||||
const SQHash chash = sq_gethash(vm, 2);
|
||||
// Cast iterations to the right type
|
||||
const Iterator itr = ConvTo< Iterator >::From(sqitr);
|
||||
// Attempt to find the requested task
|
||||
@@ -388,6 +415,8 @@ SQInteger Tasks::Find(int32_t id, int32_t type, SQInteger & pos, HSQUIRRELVM vm)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grab the hash of the callback object
|
||||
const SQHash chash = sq_gethash(vm, 2);
|
||||
// Attempt to find the requested task
|
||||
for (const auto & t : s_Tasks)
|
||||
{
|
||||
@@ -416,7 +445,7 @@ SQInteger Tasks::Remove(int32_t id, int32_t type, HSQUIRRELVM vm)
|
||||
// Did we find anything?
|
||||
else if (pos < 0)
|
||||
{
|
||||
return sq_throwerror(vm, "Unable to locate such task");
|
||||
sq_pushbool(vm, SQFalse); // Unable to locate such task
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -424,9 +453,11 @@ SQInteger Tasks::Remove(int32_t id, int32_t type, HSQUIRRELVM vm)
|
||||
s_Tasks[pos].Terminate();
|
||||
// Reset the timer
|
||||
s_Intervals[pos] = 0;
|
||||
// A task was successfully removed
|
||||
sq_pushbool(vm, SQTrue);
|
||||
}
|
||||
// Specify that we don't return anything
|
||||
return 0;
|
||||
// Specify that we return a value
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -37,9 +37,9 @@ private:
|
||||
LightObj mData; // A reference to the arbitrary data associated with this instance.
|
||||
Iterator mIterations; // Number of iterations before self destruct.
|
||||
Interval mInterval; // Interval between task invocations.
|
||||
int16_t mEntity; // The identifier of the entity to which is belongs.
|
||||
uint8_t mType; // The type of the entity to which is belongs.
|
||||
uint8_t mArgc; // The number of arguments that the task must forward.
|
||||
int16_t mEntity; // The identifier of the entity to which is belongs.
|
||||
uint8_t mType; // The type of the entity to which is belongs.
|
||||
uint8_t mArgc; // The number of arguments that the task must forward.
|
||||
Argument mArgv[8]; // The arguments that the task must forward.
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
|
||||
@@ -103,7 +103,7 @@ void ThreadPool::Terminate(bool SQ_UNUSED_ARG(shutdown))
|
||||
// Is the item valid?
|
||||
if (item)
|
||||
{
|
||||
item->OnCompleted(); // Allow the item to finish itself
|
||||
[[maybe_unused]] auto _ = item->OnCompleted(true); // Allow the item to finish itself
|
||||
}
|
||||
// Item processed
|
||||
item.reset();
|
||||
@@ -125,7 +125,15 @@ void ThreadPool::Process()
|
||||
// Is the item valid?
|
||||
if (item)
|
||||
{
|
||||
item->OnCompleted(); // Allow the item to finish itself
|
||||
try {
|
||||
// Allow the item to finish itself
|
||||
if (item->OnCompleted(false))
|
||||
{
|
||||
Enqueue(std::move(item)); // Queue again
|
||||
}
|
||||
} catch (const std::exception & e) {
|
||||
LogErr("Exception occured in %s completion stage [%s] for [%s]", item->TypeName(), e.what(), item->IdentifiableInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,6 +146,8 @@ void ThreadPool::WorkerProc()
|
||||
bool retry = false;
|
||||
// Pointer to the dequeued item
|
||||
Item item;
|
||||
// Initialize third-party allocator for this thread
|
||||
auto rpmallocinit = std::make_unique< RPMallocThreadInit >();
|
||||
// Constantly process items from the queue
|
||||
while (true)
|
||||
{
|
||||
@@ -147,7 +157,11 @@ void ThreadPool::WorkerProc()
|
||||
// Is there an item that requested to try again?
|
||||
if (item)
|
||||
{
|
||||
item->OnAborted(true); // NOLINT(bugprone-use-after-move) There's an `if` condition above idiot!
|
||||
try {
|
||||
item->OnAborted(true); // NOLINT(bugprone-use-after-move) There's an `if` condition above idiot!
|
||||
} catch (const std::exception & e) {
|
||||
LogErr("Exception occured in %s cancelation stage [%s] for [%s]", item->TypeName(), e.what(), item->IdentifiableInfo());
|
||||
}
|
||||
}
|
||||
// Exit the loop
|
||||
break;
|
||||
@@ -173,15 +187,30 @@ void ThreadPool::WorkerProc()
|
||||
// Is there an item to be processed?
|
||||
if (item)
|
||||
{
|
||||
item->OnAborted(false); // It should mark itself as aborted somehow!
|
||||
try {
|
||||
item->OnAborted(false); // It should mark itself as aborted somehow!
|
||||
} catch (const std::exception & e) {
|
||||
LogErr("Exception occured in %s forced cancelation stage [%s] for [%s]", item->TypeName(), e.what(), item->IdentifiableInfo());
|
||||
}
|
||||
}
|
||||
// Exit the loop
|
||||
break;
|
||||
}
|
||||
bool r;
|
||||
// Attempt preparation
|
||||
try {
|
||||
r = item->OnPrepare();
|
||||
} catch (const std::exception & e) {
|
||||
LogErr("Exception occured in %s preparation stage [%s] for [%s]", item->TypeName(), e.what(), item->IdentifiableInfo());
|
||||
}
|
||||
// Perform the task
|
||||
if (item->OnPrepare())
|
||||
if (r)
|
||||
{
|
||||
retry = item->OnProcess();
|
||||
try {
|
||||
retry = item->OnProcess();
|
||||
} catch (const std::exception & e) {
|
||||
LogErr("Exception occured in %s processing stage [%s] for [%s]", item->TypeName(), e.what(), item->IdentifiableInfo());
|
||||
}
|
||||
}
|
||||
// The task was performed
|
||||
if (!retry)
|
||||
|
||||
+55
-12
@@ -55,6 +55,16 @@ struct ThreadPoolItem
|
||||
*/
|
||||
ThreadPoolItem & operator = (ThreadPoolItem && o) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Provide a name to what type of task this is. Mainly for debugging purposes.
|
||||
*/
|
||||
SQMOD_NODISCARD virtual const char * TypeName() noexcept { return "worker item"; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Provide unique information that may help identify the task. Mainly for debugging purposes.
|
||||
*/
|
||||
SQMOD_NODISCARD virtual const char * IdentifiableInfo() noexcept { return ""; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Invoked in worker thread by the thread pool after obtaining the task from the queue.
|
||||
* Must return true to indicate that the task can be performed. False indicates failure.
|
||||
@@ -69,8 +79,10 @@ struct ThreadPoolItem
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Invoked in main thread by the thread pool after the task was completed.
|
||||
* If it returns true then it will be put back into the queue to be processed again.
|
||||
* If the boolean parameter is true then the thread-pool is in the process of shutting down.
|
||||
*/
|
||||
virtual void OnCompleted() { }
|
||||
SQMOD_NODISCARD virtual bool OnCompleted(bool SQ_UNUSED_ARG(stop)) { return false; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Called in worker by the thread pool to let the task know that it will be aborted.
|
||||
@@ -98,13 +110,13 @@ private:
|
||||
* Destructor.
|
||||
*/
|
||||
~ThreadPool();
|
||||
|
||||
public:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
using Item = std::unique_ptr< ThreadPoolItem >; // Owning pointer of an item.
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
using Pool = std::vector< std::thread >; // Worker container.
|
||||
using Item = std::unique_ptr< ThreadPoolItem >; // Owning pointer of an item.
|
||||
// --------------------------------------------------------------------------------------------
|
||||
using Finished = moodycamel::ConcurrentQueue< Item >; // Finished items.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
@@ -171,9 +183,25 @@ public:
|
||||
void Process();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Queue an item to be processed.
|
||||
* Queue an item to be processed. Will take ownership of the given pointer!
|
||||
*/
|
||||
void Enqueue(ThreadPoolItem * item)
|
||||
{
|
||||
Enqueue(Item{item});
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Queue an item to be processed. Will take ownership of the given pointer!
|
||||
*/
|
||||
template < class T > void CastEnqueue(std::unique_ptr< T > && item)
|
||||
{
|
||||
Enqueue(Item{std::forward< std::unique_ptr< T > >(item)});
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Queue an item to be processed. Will take ownership of the given pointer!
|
||||
*/
|
||||
void Enqueue(Item && item)
|
||||
{
|
||||
// Only queue valid items
|
||||
if (!item || !m_Running) return;
|
||||
@@ -183,7 +211,7 @@ public:
|
||||
// Acquire a lock on the mutex
|
||||
std::unique_lock< std::mutex > lock(m_Mutex);
|
||||
// Push the item in the queue
|
||||
m_Queue.push(Item(item));
|
||||
m_Queue.push(std::forward< Item >(item));
|
||||
// Release the mutex before notifying
|
||||
lock.unlock();
|
||||
// Notify one thread that there's work
|
||||
@@ -191,16 +219,32 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
bool r;
|
||||
// Attempt preparation
|
||||
try {
|
||||
r = item->OnPrepare();
|
||||
} catch (const std::exception & e) {
|
||||
LogErr("Exception occured in %s preparation stage [%s] for [%s]", item->TypeName(), e.what(), item->IdentifiableInfo());
|
||||
}
|
||||
// Perform the task in-place
|
||||
if (item->OnPrepare())
|
||||
if (r)
|
||||
{
|
||||
if (item->OnProcess())
|
||||
try {
|
||||
r = item->OnProcess();
|
||||
} catch (const std::exception & e) {
|
||||
LogErr("Exception occured in %s processing stage [%s] for [%s]", item->TypeName(), e.what(), item->IdentifiableInfo());
|
||||
}
|
||||
if (r)
|
||||
{
|
||||
item->OnAborted(true); // Not accepted in single thread
|
||||
try {
|
||||
item->OnAborted(true); // Not accepted in single thread
|
||||
} catch (const std::exception & e) {
|
||||
LogErr("Exception occured in %s cancelation stage [%s] for [%s]", item->TypeName(), e.what(), item->IdentifiableInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Item was finished in main thread
|
||||
item->OnCompleted();
|
||||
// Task is completed in processing stage
|
||||
m_Finished.enqueue(std::forward< Item >(item));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +255,6 @@ public:
|
||||
{
|
||||
return m_Threads.size();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
+20
-4
@@ -31,6 +31,8 @@ template < class Key, class T, class Pred = std::equal_to< Key > > struct VecMap
|
||||
using difference_type = typename storage_type::difference_type;
|
||||
using iterator = typename storage_type::iterator;
|
||||
using const_iterator = typename storage_type::const_iterator;
|
||||
using reverse_iterator = typename storage_type::reverse_iterator;
|
||||
using const_reverse_iterator = typename storage_type::const_reverse_iterator;
|
||||
using insert_return_type = std::pair< iterator, pointer >;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -100,12 +102,12 @@ template < class Key, class T, class Pred = std::equal_to< Key > > struct VecMap
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve a reverse iterator to the beginning (const). See: std::vector::[c]rbegin()
|
||||
*/
|
||||
const_iterator rbegin() const noexcept { return m_Storage.rbegin(); }
|
||||
reverse_iterator rbegin() const noexcept { return m_Storage.rbegin(); }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve a reverse iterator to the beginning (const). See: std::vector::crbegin()
|
||||
*/
|
||||
const_iterator crbegin() const noexcept { return m_Storage.crbegin(); }
|
||||
const_reverse_iterator crbegin() const noexcept { return m_Storage.crbegin(); }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve a reverse iterator to the beginning. See: std::vector::rend()
|
||||
@@ -115,12 +117,12 @@ template < class Key, class T, class Pred = std::equal_to< Key > > struct VecMap
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve a reverse iterator to the beginning (const). See: std::vector::[c]rend()
|
||||
*/
|
||||
const_iterator rend() const noexcept { return m_Storage.rend(); }
|
||||
reverse_iterator rend() const noexcept { return m_Storage.rend(); }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve a reverse iterator to the beginning (const). See: std::vector::crend()
|
||||
*/
|
||||
const_iterator crend() const noexcept { return m_Storage.crend(); }
|
||||
const_reverse_iterator crend() const noexcept { return m_Storage.crend(); }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Check if elements are stored in the container.
|
||||
@@ -249,6 +251,20 @@ template < class Key, class T, class Pred = std::equal_to< Key > > struct VecMap
|
||||
return m_Storage.back().second;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieves a reference to the front of the container.
|
||||
* Available for internal use only.
|
||||
*/
|
||||
reference front() { return m_Storage.front(); }
|
||||
const_reference front() const { return m_Storage.front(); }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieves a reference to the back of the container.
|
||||
* Available for internal use only.
|
||||
*/
|
||||
reference back() { return m_Storage.back(); }
|
||||
const_reference back() const { return m_Storage.back(); }
|
||||
|
||||
private:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -157,16 +157,16 @@ void CCheckpoint::SetWorld(int32_t world)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetCheckPointWorld(m_ID, world);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & CHECKPOINTCL_EMIT_CHECKPOINT_WORLD))
|
||||
else if (!(m_CircularLocks & CHECKPOINTCL_EMIT_CHECKPOINT_WORLD))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, CHECKPOINTCL_EMIT_CHECKPOINT_WORLD);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitCheckpointWorld(m_ID, current, world);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetCheckPointWorld(m_ID, world);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -257,8 +257,6 @@ void CCheckpoint::SetRadius(float radius)
|
||||
Validate();
|
||||
// Grab the current value for this property
|
||||
const float current = _Func->GetCheckPointRadius(m_ID);
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetCheckPointRadius(m_ID, radius);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & CHECKPOINTCL_EMIT_CHECKPOINT_RADIUS))
|
||||
{
|
||||
@@ -267,6 +265,8 @@ void CCheckpoint::SetRadius(float radius)
|
||||
// Now forward the event call
|
||||
Core::Get().EmitCheckpointRadius(m_ID, current, radius);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetCheckPointRadius(m_ID, radius);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -468,6 +468,16 @@ void CCheckpoint::SetColorA(int32_t a) const
|
||||
// Perform the requested operation
|
||||
_Func->SetCheckPointColour(m_ID, r, g, b, a);
|
||||
}
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj & CCheckpoint::GetLegacyObject() const
|
||||
{
|
||||
// Validate the managed identifier
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return Core::Get().GetCheckpoint(m_ID).mLgObj;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static LightObj & Checkpoint_CreateEx1a(int32_t world, bool sphere, float x, float y, float z,
|
||||
@@ -517,6 +527,9 @@ void Register_CCheckpoint(HSQUIRRELVM vm)
|
||||
.Prop(_SC("Tag"), &CCheckpoint::GetTag, &CCheckpoint::SetTag)
|
||||
.Prop(_SC("Data"), &CCheckpoint::GetData, &CCheckpoint::SetData)
|
||||
.Prop(_SC("Active"), &CCheckpoint::IsActive)
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
.Prop(_SC("Legacy"), &CCheckpoint::GetLegacyObject)
|
||||
#endif
|
||||
// Core Methods
|
||||
.FmtFunc(_SC("SetTag"), &CCheckpoint::ApplyTag)
|
||||
.Func(_SC("CustomEvent"), &CCheckpoint::CustomEvent)
|
||||
|
||||
@@ -320,6 +320,12 @@ public:
|
||||
* Modify the alpha transparency of the managed checkpoint entity.
|
||||
*/
|
||||
void SetColorA(int32_t a) const;
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve legacy object instance for this entity.
|
||||
*/
|
||||
LightObj & GetLegacyObject() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
+25
-12
@@ -163,16 +163,16 @@ void CObject::SetWorld(int32_t world)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetObjectWorld(m_ID, world);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & OBJECTCL_EMIT_OBJECT_WORLD))
|
||||
else if (!(m_CircularLocks & OBJECTCL_EMIT_OBJECT_WORLD))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, OBJECTCL_EMIT_OBJECT_WORLD);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitObjectWorld(m_ID, current, world);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetObjectWorld(m_ID, world);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -202,16 +202,16 @@ void CObject::SetAlphaEx(int32_t alpha, uint32_t time)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetObjectAlpha(m_ID, alpha, time);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & OBJECTCL_EMIT_OBJECT_ALPHA))
|
||||
else if (!(m_CircularLocks & OBJECTCL_EMIT_OBJECT_ALPHA))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, OBJECTCL_EMIT_OBJECT_ALPHA);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitObjectAlpha(m_ID, current, alpha, time);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetObjectAlpha(m_ID, alpha, time);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -400,16 +400,16 @@ void CObject::SetShotReport(bool toggle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetObjectShotReportEnabled(m_ID, static_cast< uint8_t >(toggle));
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & OBJECTCL_EMIT_OBJECT_REPORT))
|
||||
else if (!(m_CircularLocks & OBJECTCL_EMIT_OBJECT_REPORT))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, OBJECTCL_EMIT_OBJECT_REPORT);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitObjectReport(m_ID, current, toggle, false);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetObjectShotReportEnabled(m_ID, static_cast< uint8_t >(toggle));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -433,16 +433,16 @@ void CObject::SetTouchedReport(bool toggle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetObjectTouchedReportEnabled(m_ID, static_cast< uint8_t >(toggle));
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & OBJECTCL_EMIT_OBJECT_REPORT))
|
||||
else if (!(m_CircularLocks & OBJECTCL_EMIT_OBJECT_REPORT))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, OBJECTCL_EMIT_OBJECT_REPORT);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitObjectReport(m_ID, current, toggle, true);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetObjectTouchedReportEnabled(m_ID, static_cast< uint8_t >(toggle));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -833,6 +833,16 @@ void CObject::RotateByEulerZ(float z) const
|
||||
// Perform the requested operation
|
||||
_Func->RotateObjectByEuler(m_ID, 0.0f, 0.0f, z, mRotateByEulerDuration);
|
||||
}
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj & CObject::GetLegacyObject() const
|
||||
{
|
||||
// Validate the managed identifier
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return Core::Get().GetObj(m_ID).mLgObj;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static LightObj & Object_CreateEx1a(int32_t model, int32_t world, float x, float y, float z,
|
||||
@@ -883,6 +893,9 @@ void Register_CObject(HSQUIRRELVM vm)
|
||||
.Prop(_SC("Tag"), &CObject::GetTag, &CObject::SetTag)
|
||||
.Prop(_SC("Data"), &CObject::GetData, &CObject::SetData)
|
||||
.Prop(_SC("Active"), &CObject::IsActive)
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
.Prop(_SC("Legacy"), &CObject::GetLegacyObject)
|
||||
#endif
|
||||
// Core Methods
|
||||
.FmtFunc(_SC("SetTag"), &CObject::ApplyTag)
|
||||
.Func(_SC("CustomEvent"), &CObject::CustomEvent)
|
||||
|
||||
@@ -499,6 +499,12 @@ public:
|
||||
* Modify the rotation on the z axis of the managed object entity.
|
||||
*/
|
||||
void RotateByEulerZ(float z) const;
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve legacy object instance for this entity.
|
||||
*/
|
||||
LightObj & GetLegacyObject() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
+41
-26
@@ -145,19 +145,20 @@ void CPickup::SetOption(int32_t option_id, bool toggle)
|
||||
{
|
||||
// Attempt to obtain the current value of the specified option
|
||||
const bool value = _Func->GetPickupOption(m_ID, static_cast< vcmpPickupOption >(option_id));
|
||||
// Attempt to modify the current value of the specified option
|
||||
if (_Func->SetPickupOption(m_ID, static_cast< vcmpPickupOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
else if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_OPTION))
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_OPTION))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PICKUPCL_EMIT_PICKUP_OPTION);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPickupOption(m_ID, option_id, value, 0, NullLightObj());
|
||||
}
|
||||
// Attempt to modify the current value of the specified option
|
||||
if (_Func->SetPickupOption(m_ID, static_cast< vcmpPickupOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -165,19 +166,20 @@ void CPickup::SetOptionEx(int32_t option_id, bool toggle, int32_t header, LightO
|
||||
{
|
||||
// Attempt to obtain the current value of the specified option
|
||||
const bool value = _Func->GetPickupOption(m_ID, static_cast< vcmpPickupOption >(option_id));
|
||||
// Attempt to modify the current value of the specified option
|
||||
if (_Func->SetPickupOption(m_ID, static_cast< vcmpPickupOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
else if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_OPTION))
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_OPTION))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PICKUPCL_EMIT_PICKUP_OPTION);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPickupOption(m_ID, option_id, value, header, payload);
|
||||
}
|
||||
// Attempt to modify the current value of the specified option
|
||||
if (_Func->SetPickupOption(m_ID, static_cast< vcmpPickupOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -201,16 +203,16 @@ void CPickup::SetWorld(int32_t world)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPickupWorld(m_ID, world);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_WORLD))
|
||||
else if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_WORLD))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PICKUPCL_EMIT_PICKUP_WORLD);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPickupWorld(m_ID, current, world);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPickupWorld(m_ID, world);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -234,16 +236,16 @@ void CPickup::SetAlpha(int32_t alpha)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPickupAlpha(m_ID, alpha);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_ALPHA))
|
||||
else if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_ALPHA))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PICKUPCL_EMIT_PICKUP_ALPHA);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPickupAlpha(m_ID, current, alpha);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPickupAlpha(m_ID, alpha);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -267,16 +269,16 @@ void CPickup::SetAutomatic(bool toggle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPickupIsAutomatic(m_ID, static_cast< uint8_t >(toggle));
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_AUTOMATIC))
|
||||
else if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_AUTOMATIC))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PICKUPCL_EMIT_PICKUP_AUTOMATIC);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPickupAutomatic(m_ID, current, toggle);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPickupIsAutomatic(m_ID, static_cast< uint8_t >(toggle));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -300,16 +302,16 @@ void CPickup::SetAutoTimer(int32_t timer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPickupAutoTimer(m_ID, static_cast< uint32_t >(timer));
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_AUTOTIMER))
|
||||
else if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_AUTOTIMER))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PICKUPCL_EMIT_PICKUP_AUTOTIMER);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPickupAutoTimer(m_ID, current, timer);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPickupAutoTimer(m_ID, static_cast< uint32_t >(timer));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -447,6 +449,16 @@ void CPickup::SetPositionZ(float z) const
|
||||
// Perform the requested operation
|
||||
_Func->SetPickupPosition(m_ID, z, y, z);
|
||||
}
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj & CPickup::GetLegacyObject() const
|
||||
{
|
||||
// Validate the managed identifier
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return Core::Get().GetPickup(m_ID).mLgObj;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static LightObj & Pickup_CreateEx1a(int32_t model, int32_t world, int32_t quantity,
|
||||
@@ -494,6 +506,9 @@ void Register_CPickup(HSQUIRRELVM vm)
|
||||
.Prop(_SC("Tag"), &CPickup::GetTag, &CPickup::SetTag)
|
||||
.Prop(_SC("Data"), &CPickup::GetData, &CPickup::SetData)
|
||||
.Prop(_SC("Active"), &CPickup::IsActive)
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
.Prop(_SC("Legacy"), &CPickup::GetLegacyObject)
|
||||
#endif
|
||||
// Core Methods
|
||||
.FmtFunc(_SC("SetTag"), &CPickup::ApplyTag)
|
||||
.Func(_SC("CustomEvent"), &CPickup::CustomEvent)
|
||||
|
||||
@@ -298,6 +298,12 @@ public:
|
||||
* Modify the position on the z axis of the managed pickup entity.
|
||||
*/
|
||||
void SetPositionZ(float z) const;
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve legacy object instance for this entity.
|
||||
*/
|
||||
LightObj & GetLegacyObject() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
+83
-45
@@ -168,16 +168,16 @@ void CPlayer::SetAdmin(bool toggle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerAdmin(m_ID, static_cast< uint8_t >(toggle));
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_ADMIN))
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_ADMIN))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PLAYERCL_EMIT_PLAYER_ADMIN);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerAdmin(m_ID, current, toggle);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerAdmin(m_ID, static_cast< uint8_t >(toggle));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -373,13 +373,6 @@ void CPlayer::SetOptionEx(int32_t option_id, bool toggle, int32_t header, LightO
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
else if (_Func->SetPlayerOption(m_ID,
|
||||
static_cast< vcmpPlayerOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
// Avoid infinite recursive event loops
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_OPTION))
|
||||
{
|
||||
@@ -388,6 +381,13 @@ void CPlayer::SetOptionEx(int32_t option_id, bool toggle, int32_t header, LightO
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerOption(m_ID, option_id, current, header, payload);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
if (_Func->SetPlayerOption(m_ID,
|
||||
static_cast< vcmpPlayerOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
}
|
||||
#if SQMOD_SDK_LEAST(2, 1)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -433,16 +433,16 @@ void CPlayer::SetWorld(int32_t world)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerWorld(m_ID, world);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_WORLD))
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_WORLD))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PLAYERCL_EMIT_PLAYER_WORLD);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerWorld(m_ID, current, world, false);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerWorld(m_ID, world);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -466,16 +466,16 @@ void CPlayer::SetSecondaryWorld(int32_t world)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerSecondaryWorld(m_ID, world);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_WORLD))
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_WORLD))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PLAYERCL_EMIT_PLAYER_WORLD);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerWorld(m_ID, current, world, true);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerSecondaryWorld(m_ID, world);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -526,11 +526,6 @@ void CPlayer::SetTeam(int32_t team)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
else if (_Func->SetPlayerTeam(m_ID, team) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid team identifier: {}", team);
|
||||
}
|
||||
// Avoid infinite recursive event loops
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_TEAM))
|
||||
{
|
||||
@@ -539,6 +534,11 @@ void CPlayer::SetTeam(int32_t team)
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerTeam(m_ID, current, team);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
if (_Func->SetPlayerTeam(m_ID, team) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid team identifier: {}", team);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -562,11 +562,6 @@ void CPlayer::SetSkin(int32_t skin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
else if (_Func->SetPlayerSkin(m_ID, skin) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid skin identifier: {}", skin);
|
||||
}
|
||||
// Avoid infinite recursive event loops
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_SKIN))
|
||||
{
|
||||
@@ -575,6 +570,11 @@ void CPlayer::SetSkin(int32_t skin)
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerSkin(m_ID, current, skin);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
if (_Func->SetPlayerSkin(m_ID, skin) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid skin identifier: {}", skin);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -665,16 +665,16 @@ void CPlayer::SetMoney(int32_t amount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerMoney(m_ID, amount);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_MONEY))
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_MONEY))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PLAYERCL_EMIT_PLAYER_MONEY);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerMoney(m_ID, current, amount);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerMoney(m_ID, amount);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -684,8 +684,6 @@ void CPlayer::GiveMoney(int32_t amount)
|
||||
Validate();
|
||||
// Grab the current value for this property
|
||||
const int32_t current = _Func->GetPlayerMoney(m_ID);
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->GivePlayerMoney(m_ID, amount);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_MONEY))
|
||||
{
|
||||
@@ -694,6 +692,8 @@ void CPlayer::GiveMoney(int32_t amount)
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerMoney(m_ID, current, current + amount);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->GivePlayerMoney(m_ID, amount);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -717,16 +717,16 @@ void CPlayer::SetScore(int32_t score)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerScore(m_ID, score);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_SCORE))
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_SCORE))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PLAYERCL_EMIT_PLAYER_SCORE);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerScore(m_ID, current, score);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerScore(m_ID, score);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -750,16 +750,16 @@ void CPlayer::SetWantedLevel(int32_t level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerWantedLevel(m_ID, level);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_WANTED_LEVEL))
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_WANTED_LEVEL))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PLAYERCL_EMIT_PLAYER_WANTED_LEVEL);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerWantedLevel(m_ID, current, level);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerWantedLevel(m_ID, level);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -832,8 +832,6 @@ void CPlayer::SetImmunity(uint32_t flags)
|
||||
Validate();
|
||||
// Grab the current value for this property
|
||||
const uint32_t current = _Func->GetPlayerImmunityFlags(m_ID);
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerImmunityFlags(m_ID, static_cast< uint32_t >(flags));
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_IMMUNITY))
|
||||
{
|
||||
@@ -842,6 +840,8 @@ void CPlayer::SetImmunity(uint32_t flags)
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerImmunity(m_ID, static_cast< int32_t >(current), static_cast< int32_t >(flags));
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerImmunityFlags(m_ID, static_cast< uint32_t >(flags));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -969,16 +969,16 @@ void CPlayer::SetAlphaEx(int32_t alpha, int32_t fade)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerAlpha(m_ID, alpha, static_cast< uint32_t >(fade));
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_ALPHA))
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_ALPHA))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PLAYERCL_EMIT_PLAYER_ALPHA);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerAlpha(m_ID, current, alpha, fade);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetPlayerAlpha(m_ID, alpha, static_cast< uint32_t >(fade));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -1044,7 +1044,7 @@ uint32_t CPlayer::GetGameKeys() const
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool CPlayer::Embark(CVehicle & vehicle) const
|
||||
bool CPlayer::Embark(CVehicle & vehicle)
|
||||
{
|
||||
// Is the specified vehicle even valid?
|
||||
if (!vehicle.IsActive())
|
||||
@@ -1053,13 +1053,26 @@ bool CPlayer::Embark(CVehicle & vehicle) const
|
||||
}
|
||||
// Validate the managed identifier
|
||||
Validate();
|
||||
// If the player embarks in the same vehicle then ignore
|
||||
if (_Func->GetPlayerVehicleId(m_ID) == vehicle.GetID())
|
||||
{
|
||||
return true; // I guess this is somewhat successful
|
||||
}
|
||||
// Avoid infinite recursive event loops
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_EMBARK))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PLAYERCL_EMIT_PLAYER_EMBARK);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerEmbarking(m_ID, vehicle.GetID(), 0);
|
||||
}
|
||||
// Perform the requested operation
|
||||
return (_Func->PutPlayerInVehicle(m_ID, vehicle.GetID(), 0,
|
||||
static_cast< uint8_t >(true), static_cast< uint8_t >(true)) != vcmpErrorRequestDenied);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool CPlayer::EmbarkEx(CVehicle & vehicle, int32_t slot, bool allocate, bool warp) const
|
||||
bool CPlayer::EmbarkEx(CVehicle & vehicle, int32_t slot, bool allocate, bool warp)
|
||||
{
|
||||
// Is the specified vehicle even valid?
|
||||
if (!vehicle.IsActive())
|
||||
@@ -1068,6 +1081,19 @@ bool CPlayer::EmbarkEx(CVehicle & vehicle, int32_t slot, bool allocate, bool war
|
||||
}
|
||||
// Validate the managed identifier
|
||||
Validate();
|
||||
// If the player embarks in the same vehicle then ignore
|
||||
if (_Func->GetPlayerVehicleId(m_ID) == vehicle.GetID())
|
||||
{
|
||||
return true; // I guess this is somewhat successful
|
||||
}
|
||||
// Avoid infinite recursive event loops
|
||||
else if (!(m_CircularLocks & PLAYERCL_EMIT_PLAYER_EMBARK))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, PLAYERCL_EMIT_PLAYER_EMBARK);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerEmbarking(m_ID, vehicle.GetID(), slot);
|
||||
}
|
||||
// Perform the requested operation
|
||||
return (_Func->PutPlayerInVehicle(m_ID, vehicle.GetID(), slot,
|
||||
static_cast< uint8_t >(allocate), static_cast< uint8_t >(warp)) != vcmpErrorRequestDenied);
|
||||
@@ -2567,7 +2593,16 @@ SQInteger CPlayer::AnnounceEx(HSQUIRRELVM vm)
|
||||
// This function does not return a value
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj & CPlayer::GetLegacyObject() const
|
||||
{
|
||||
// Validate the managed identifier
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return Core::Get().GetPlayer(m_ID).mLgObj;
|
||||
}
|
||||
#endif
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Player_FindAuto(HSQUIRRELVM vm)
|
||||
{
|
||||
@@ -2767,6 +2802,9 @@ void Register_CPlayer(HSQUIRRELVM vm)
|
||||
.Prop(_SC("Tag"), &CPlayer::GetTag, &CPlayer::SetTag)
|
||||
.Prop(_SC("Data"), &CPlayer::GetData, &CPlayer::SetData)
|
||||
.Prop(_SC("Active"), &CPlayer::IsActive)
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
.Prop(_SC("Legacy"), &CPlayer::GetLegacyObject)
|
||||
#endif
|
||||
// Core Methods
|
||||
.FmtFunc(_SC("SetTag"), &CPlayer::ApplyTag)
|
||||
.Func(_SC("CustomEvent"), &CPlayer::CustomEvent)
|
||||
|
||||
@@ -21,7 +21,8 @@ enum PlayerCircularLocks
|
||||
PLAYERCL_EMIT_PLAYER_SCORE = (1u << 6u),
|
||||
PLAYERCL_EMIT_PLAYER_WANTED_LEVEL = (1u << 7u),
|
||||
PLAYERCL_EMIT_PLAYER_IMMUNITY = (1u << 8u),
|
||||
PLAYERCL_EMIT_PLAYER_ALPHA = (1u << 9u)
|
||||
PLAYERCL_EMIT_PLAYER_ALPHA = (1u << 9u),
|
||||
PLAYERCL_EMIT_PLAYER_EMBARK = (1u << 10u)
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -593,12 +594,12 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Embark the managed player entity into the specified vehicle entity.
|
||||
*/
|
||||
bool Embark(CVehicle & vehicle) const;
|
||||
bool Embark(CVehicle & vehicle);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Embark the managed player entity into the specified vehicle entity.
|
||||
*/
|
||||
bool EmbarkEx(CVehicle & vehicle, int32_t slot, bool allocate, bool warp) const;
|
||||
bool EmbarkEx(CVehicle & vehicle, int32_t slot, bool allocate, bool warp);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Disembark the managed player entity from the currently embarked vehicle entity.
|
||||
@@ -1100,6 +1101,12 @@ public:
|
||||
* Send a formatted announcement message to the managed player entity.
|
||||
*/
|
||||
static SQInteger AnnounceEx(HSQUIRRELVM vm);
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve legacy object instance for this entity.
|
||||
*/
|
||||
LightObj & GetLegacyObject() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
+78
-37
@@ -148,19 +148,20 @@ void CVehicle::SetOption(int32_t option_id, bool toggle)
|
||||
{
|
||||
// Attempt to obtain the current value of the specified option
|
||||
const bool value = _Func->GetVehicleOption(m_ID, static_cast< vcmpVehicleOption >(option_id));
|
||||
// Attempt to modify the current value of the specified option
|
||||
if (_Func->SetVehicleOption(m_ID, static_cast< vcmpVehicleOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
else if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_OPTION))
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_OPTION))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, VEHICLECL_EMIT_VEHICLE_OPTION);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehicleOption(m_ID, option_id, value, 0, NullLightObj());
|
||||
}
|
||||
// Attempt to modify the current value of the specified option
|
||||
if (_Func->SetVehicleOption(m_ID, static_cast< vcmpVehicleOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -168,19 +169,20 @@ void CVehicle::SetOptionEx(int32_t option_id, bool toggle, int32_t header, Light
|
||||
{
|
||||
// Attempt to obtain the current value of the specified option
|
||||
const bool value = _Func->GetVehicleOption(m_ID, static_cast< vcmpVehicleOption >(option_id));
|
||||
// Attempt to modify the current value of the specified option
|
||||
if (_Func->SetVehicleOption(m_ID, static_cast< vcmpVehicleOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
else if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_OPTION))
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_OPTION))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, VEHICLECL_EMIT_VEHICLE_OPTION);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehicleOption(m_ID, option_id, value, header, payload);
|
||||
}
|
||||
// Attempt to modify the current value of the specified option
|
||||
if (_Func->SetVehicleOption(m_ID, static_cast< vcmpVehicleOption >(option_id),
|
||||
static_cast< uint8_t >(toggle)) == vcmpErrorArgumentOutOfBounds)
|
||||
{
|
||||
STHROWF("Invalid option identifier: {}", option_id);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -222,16 +224,16 @@ void CVehicle::SetWorld(int32_t world)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleWorld(m_ID, world);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_WORLD))
|
||||
else if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_WORLD))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, VEHICLECL_EMIT_VEHICLE_WORLD);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehicleWorld(m_ID, current, world);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleWorld(m_ID, world);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -321,8 +323,6 @@ void CVehicle::SetImmunity(uint32_t flags)
|
||||
Validate();
|
||||
// Grab the current value for this property
|
||||
const uint32_t current = _Func->GetVehicleImmunityFlags(m_ID);
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleImmunityFlags(m_ID, static_cast< uint32_t >(flags));
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_IMMUNITY))
|
||||
{
|
||||
@@ -331,6 +331,8 @@ void CVehicle::SetImmunity(uint32_t flags)
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehicleImmunity(m_ID, static_cast< int32_t >(current), static_cast< int32_t >(flags));
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleImmunityFlags(m_ID, static_cast< uint32_t >(flags));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -914,16 +916,16 @@ void CVehicle::SetPartStatus(int32_t part, int32_t status)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehiclePartStatus(m_ID, part, status);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_PARTSTATUS))
|
||||
else if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_PARTSTATUS))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, VEHICLECL_EMIT_VEHICLE_PARTSTATUS);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehiclePartStatus(m_ID, part, current, status);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehiclePartStatus(m_ID, part, status);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -947,16 +949,16 @@ void CVehicle::SetTyreStatus(int32_t tyre, int32_t status)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleTyreStatus(m_ID, tyre, status);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_TYRESTATUS))
|
||||
else if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_TYRESTATUS))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, VEHICLECL_EMIT_VEHICLE_TYRESTATUS);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehicleTyreStatus(m_ID, tyre, current, status);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleTyreStatus(m_ID, tyre, status);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -980,16 +982,16 @@ void CVehicle::SetDamageData(uint32_t data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleDamageData(m_ID, data);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_DAMAGEDATA))
|
||||
else if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_DAMAGEDATA))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, VEHICLECL_EMIT_VEHICLE_DAMAGEDATA);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehicleDamageData(m_ID, current, data);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleDamageData(m_ID, data);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -1013,16 +1015,16 @@ void CVehicle::SetRadio(int32_t radio)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleRadio(m_ID, radio);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_RADIO))
|
||||
else if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_RADIO))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, VEHICLECL_EMIT_VEHICLE_RADIO);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehicleRadio(m_ID, current, radio);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetVehicleRadio(m_ID, radio);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -1089,8 +1091,6 @@ void CVehicle::SetHandlingRule(int32_t rule, float data)
|
||||
Validate();
|
||||
// Grab the current value for this property
|
||||
const auto current = static_cast< SQFloat >(_Func->GetInstHandlingRule(m_ID, rule));
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetInstHandlingRule(m_ID, rule, data);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_HANDLINGRULE))
|
||||
{
|
||||
@@ -1099,6 +1099,8 @@ void CVehicle::SetHandlingRule(int32_t rule, float data)
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehicleHandlingRule(m_ID, rule, current, data);
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->SetInstHandlingRule(m_ID, rule, data);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -1108,8 +1110,6 @@ void CVehicle::ResetHandlingRule(int32_t rule)
|
||||
Validate();
|
||||
// Grab the current value for this property
|
||||
const auto current = static_cast< SQFloat >(_Func->GetInstHandlingRule(m_ID, rule));
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->ResetInstHandlingRule(m_ID, rule);
|
||||
// Avoid infinite recursive event loops
|
||||
if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_HANDLINGRULE))
|
||||
{
|
||||
@@ -1118,6 +1118,8 @@ void CVehicle::ResetHandlingRule(int32_t rule)
|
||||
// Now forward the event call
|
||||
Core::Get().EmitVehicleHandlingRule(m_ID, rule, current, static_cast< SQFloat >(_Func->GetInstHandlingRule(m_ID, rule)));
|
||||
}
|
||||
// Avoid property unwind from a recursive call
|
||||
_Func->ResetInstHandlingRule(m_ID, rule);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -1148,7 +1150,7 @@ void CVehicle::SetLightsData(int32_t data) const
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool CVehicle::Embark(CPlayer & player) const
|
||||
bool CVehicle::Embark(CPlayer & player)
|
||||
{
|
||||
// Is the specified player even valid?
|
||||
if (!player.IsActive())
|
||||
@@ -1157,6 +1159,19 @@ bool CVehicle::Embark(CPlayer & player) const
|
||||
}
|
||||
// Validate the managed identifier
|
||||
Validate();
|
||||
// If the player embarks in the same vehicle then ignore
|
||||
if (_Func->GetPlayerVehicleId(player.GetID()) == m_ID)
|
||||
{
|
||||
return true; // I guess this is somewhat successful
|
||||
}
|
||||
// Avoid infinite recursive event loops
|
||||
else if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_EMBARK))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, VEHICLECL_EMIT_VEHICLE_EMBARK);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerEmbarking(player.GetID(), m_ID, 0);
|
||||
}
|
||||
// Perform the requested operation
|
||||
return (_Func->PutPlayerInVehicle(player.GetID(), m_ID, 0,
|
||||
static_cast< uint8_t >(true), static_cast< uint8_t >(true))
|
||||
@@ -1164,7 +1179,7 @@ bool CVehicle::Embark(CPlayer & player) const
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool CVehicle::EmbarkEx(CPlayer & player, int32_t slot, bool allocate, bool warp) const
|
||||
bool CVehicle::EmbarkEx(CPlayer & player, int32_t slot, bool allocate, bool warp)
|
||||
{
|
||||
// Is the specified player even valid?
|
||||
if (!player.IsActive())
|
||||
@@ -1173,6 +1188,19 @@ bool CVehicle::EmbarkEx(CPlayer & player, int32_t slot, bool allocate, bool warp
|
||||
}
|
||||
// Validate the managed identifier
|
||||
Validate();
|
||||
// If the player embarks in the same vehicle then ignore
|
||||
if (_Func->GetPlayerVehicleId(player.GetID()) == m_ID)
|
||||
{
|
||||
return true; // I guess this is somewhat successful
|
||||
}
|
||||
// Avoid infinite recursive event loops
|
||||
else if (!(m_CircularLocks & VEHICLECL_EMIT_VEHICLE_EMBARK))
|
||||
{
|
||||
// Prevent this event from triggering while executed
|
||||
BitGuardU32 bg(m_CircularLocks, VEHICLECL_EMIT_VEHICLE_EMBARK);
|
||||
// Now forward the event call
|
||||
Core::Get().EmitPlayerEmbarking(player.GetID(), m_ID, 0);
|
||||
}
|
||||
// Perform the requested operation
|
||||
return (_Func->PutPlayerInVehicle(player.GetID(), m_ID, slot,
|
||||
static_cast< uint8_t >(allocate), static_cast< uint8_t >(warp)) != vcmpErrorRequestDenied);
|
||||
@@ -1987,6 +2015,16 @@ void CVehicle::SetRelativeTurnSpeedZ(float z) const
|
||||
// Perform the requested operation
|
||||
_Func->SetVehicleTurnSpeed(m_ID, z, y, z, static_cast< uint8_t >(false), static_cast< uint8_t >(true));
|
||||
}
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj & CVehicle::GetLegacyObject() const
|
||||
{
|
||||
// Validate the managed identifier
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return Core::Get().GetVehicle(m_ID).mLgObj;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static LightObj & Vehicle_CreateEx1a(int32_t model, int32_t world, float x, float y, float z, float angle,
|
||||
@@ -2033,6 +2071,9 @@ void Register_CVehicle(HSQUIRRELVM vm)
|
||||
.Prop(_SC("ID"), &CVehicle::GetID)
|
||||
.Prop(_SC("Tag"), &CVehicle::GetTag, &CVehicle::SetTag)
|
||||
.Prop(_SC("Data"), &CVehicle::GetData, &CVehicle::SetData)
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
.Prop(_SC("Legacy"), &CVehicle::GetLegacyObject)
|
||||
#endif
|
||||
.Prop(_SC("Active"), &CVehicle::IsActive)
|
||||
// Core Methods
|
||||
.FmtFunc(_SC("SetTag"), &CVehicle::ApplyTag)
|
||||
|
||||
@@ -18,7 +18,8 @@ enum VehicleCircularLocks
|
||||
VEHICLECL_EMIT_VEHICLE_TYRESTATUS = (1u << 4u),
|
||||
VEHICLECL_EMIT_VEHICLE_DAMAGEDATA = (1u << 5u),
|
||||
VEHICLECL_EMIT_VEHICLE_RADIO = (1u << 6u),
|
||||
VEHICLECL_EMIT_VEHICLE_HANDLINGRULE = (1u << 7u)
|
||||
VEHICLECL_EMIT_VEHICLE_HANDLINGRULE = (1u << 7u),
|
||||
VEHICLECL_EMIT_VEHICLE_EMBARK = (1u << 8u) // This should probably be shared with CPlayer
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -615,12 +616,12 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Embark the specified player entity into the managed vehicle entity.
|
||||
*/
|
||||
bool Embark(CPlayer & player) const;
|
||||
bool Embark(CPlayer & player);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Embark the specified player entity into the managed vehicle entity.
|
||||
*/
|
||||
bool EmbarkEx(CPlayer & player, int32_t slot, bool allocate, bool warp) const;
|
||||
bool EmbarkEx(CPlayer & player, int32_t slot, bool allocate, bool warp);
|
||||
#if SQMOD_SDK_LEAST(2, 1)
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set whether the target player will see an objective arrow over a vehicle.
|
||||
@@ -941,6 +942,12 @@ public:
|
||||
* Modify the relative turn velocity on the z axis of the managed vehicle entity.
|
||||
*/
|
||||
void SetRelativeTurnSpeedZ(float z) const;
|
||||
#ifdef VCMP_ENABLE_OFFICIAL
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve legacy object instance for this entity.
|
||||
*/
|
||||
LightObj & GetLegacyObject() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Core.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cstring>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqmod.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static int32_t RegisterCommandFn(ExtPluginCommand_t fn)
|
||||
{
|
||||
return Core::Get().RegisterExtCommand(fn);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static int32_t UnregisterCommandFn(ExtPluginCommand_t fn)
|
||||
{
|
||||
return Core::Get().UnregisterExtCommand(fn);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static int32_t SendCommandFn(int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size)
|
||||
{
|
||||
return Core::Get().SendExtCommand(target, req, tag, data, size);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static int32_t SendCommandReplyFn(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
const CoreState cs(SQMOD_SUCCESS);
|
||||
// Forward the call to the script callbacks
|
||||
Core::Get().EmitExtCommandReply(sender, tag, data, size);
|
||||
// Return the last known plug-in state
|
||||
return Core::Get().GetState();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static int32_t SendCommandEventFn(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
const CoreState cs(SQMOD_SUCCESS);
|
||||
// Forward the call to the script callbacks
|
||||
Core::Get().EmitExtCommandEvent(sender, tag, data, size);
|
||||
// Return the last known plug-in state
|
||||
return Core::Get().GetState();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static const SQ_MOD_EXPORTS g_SqModExports{
|
||||
sizeof(SQ_MOD_EXPORTS),
|
||||
&RegisterCommandFn,
|
||||
&UnregisterCommandFn,
|
||||
&SendCommandFn,
|
||||
&SendCommandReplyFn,
|
||||
&SendCommandEventFn
|
||||
};
|
||||
|
||||
// The server needs a pointer to a pointer, and a persistent one
|
||||
static const SQ_MOD_EXPORTS * g_SqModExportsPtr = &g_SqModExports;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void InitExports()
|
||||
{
|
||||
// Tell the server about the pointer to the exports structure
|
||||
_Func->ExportFunctions(_Info->pluginId, reinterpret_cast< const void ** >(&g_SqModExportsPtr), sizeof(HSQ_MOD_EXPORTS));
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
+39
-5
@@ -16,6 +16,7 @@ SQMOD_DECL_TYPENAME(SqCpResponse, _SC("SqCprResponse"))
|
||||
SQMOD_DECL_TYPENAME(SqCpParameters, _SC("SqCprParameters"))
|
||||
SQMOD_DECL_TYPENAME(SqCpPayload, _SC("SqCprPayload"))
|
||||
SQMOD_DECL_TYPENAME(SqCpProxies, _SC("SqCprProxies"))
|
||||
SQMOD_DECL_TYPENAME(SqCpRedirect, _SC("SqCprRedirect"))
|
||||
SQMOD_DECL_TYPENAME(SqCpSession, _SC("SqCprSession"))
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -46,9 +47,11 @@ struct CpBaseAction : public ThreadPoolItem
|
||||
~CpBaseAction() override = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Task completed callback.
|
||||
* Invoked in main thread by the thread pool after the task was completed.
|
||||
* If it returns true then it will be put back into the queue to be processed again.
|
||||
* If the boolean parameter is trye then the thread-pool is in the process of shutting down.
|
||||
*/
|
||||
void OnCompleted() override
|
||||
SQMOD_NODISCARD bool OnCompleted(bool SQ_UNUSED_ARG(stop)) override
|
||||
{
|
||||
// Is there a callback?
|
||||
if (!mCallback.IsNull())
|
||||
@@ -57,6 +60,8 @@ struct CpBaseAction : public ThreadPoolItem
|
||||
}
|
||||
// Unlock the session
|
||||
mInstance->mPending = nullptr;
|
||||
// Don't re-queue
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -404,10 +409,20 @@ static const EnumElement g_StatusCodes[] = {
|
||||
{_SC("MISC_CODE_OFFSET"), cpr::status::MISC_CODE_OFFSET}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static const EnumElement g_PostRedirectFlags[] = {
|
||||
{_SC("Post301"), static_cast< SQInteger >(cpr::PostRedirectFlags::POST_301)},
|
||||
{_SC("Post302"), static_cast< SQInteger >(cpr::PostRedirectFlags::POST_302)},
|
||||
{_SC("Post303"), static_cast< SQInteger >(cpr::PostRedirectFlags::POST_303)},
|
||||
{_SC("Postall"), static_cast< SQInteger >(cpr::PostRedirectFlags::POST_ALL)},
|
||||
{_SC("None"), static_cast< SQInteger >(cpr::PostRedirectFlags::NONE)},
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static const EnumElements g_EnumList[] = {
|
||||
{_SC("SqCprErrorCode"), g_ErrorCodes},
|
||||
{_SC("SqCprStatusCode"), g_StatusCodes}
|
||||
{_SC("SqCprErrorCode"), g_ErrorCodes},
|
||||
{_SC("SqCprStatusCode"), g_StatusCodes},
|
||||
{_SC("SqCprPostRedirectFlags"), g_PostRedirectFlags}
|
||||
};
|
||||
|
||||
// ================================================================================================
|
||||
@@ -605,6 +620,26 @@ void Register_CURL(HSQUIRRELVM vm)
|
||||
.CbFunc(_SC("While"), &CpProxies::While)
|
||||
);
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
cpns.Bind(_SC("Redirect"),
|
||||
Class< CpRedirect >(vm, SqCpRedirect::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< SQInteger >()
|
||||
.Ctor< SQInteger, bool >()
|
||||
.Ctor< SQInteger, bool, SQInteger >()
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_typename"), &SqCpRedirect::Fn)
|
||||
// Properties
|
||||
.Prop(_SC("Maximum"), &CpRedirect::GetMaximum, &CpRedirect::SetMaximum)
|
||||
.Prop(_SC("Follow"), &CpRedirect::GetFollow, &CpRedirect::SetFollow)
|
||||
.Prop(_SC("Flags"), &CpRedirect::GetFlags, &CpRedirect::SetFlags)
|
||||
// Member Methods
|
||||
.Func(_SC("SetMaximum"), &CpRedirect::ApplyMaximum)
|
||||
.Func(_SC("SetFollow"), &CpRedirect::ApplyFollow)
|
||||
.Func(_SC("SetFlags"), &CpRedirect::ApplyFlags)
|
||||
);
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
cpns.Bind(_SC("Session"),
|
||||
Class< CpSession, NoCopy< CpSession > >(vm, SqCpSession::Str)
|
||||
@@ -631,7 +666,6 @@ void Register_CURL(HSQUIRRELVM vm)
|
||||
.Func(_SC("YieldProxies"), &CpSession::YieldProxies)
|
||||
.FmtFunc(_SC("SetNTLM"), &CpSession::SetNTLM_)
|
||||
.Func(_SC("SetRedirect"), &CpSession::SetRedirect_)
|
||||
.Func(_SC("SetMaxRedirects"), &CpSession::SetMaxRedirects_)
|
||||
.Func(_SC("SetCookies"), &CpSession::SetCookies_)
|
||||
.FmtFunc(_SC("SetBody"), &CpSession::SetBody_)
|
||||
.Func(_SC("SetLowSpeed"), &CpSession::SetLowSpeed_)
|
||||
|
||||
+150
-14
@@ -888,7 +888,7 @@ struct CpResponse : public cpr::Response
|
||||
*/
|
||||
void SetStatusCode(SQInteger value)
|
||||
{
|
||||
cpr::Response::status_code = value;
|
||||
cpr::Response::status_code = static_cast< long >(value);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1604,6 +1604,152 @@ struct CpProxies : public cpr::Proxies
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Wrapper for cpr::Redirect that can be bound to the script engine.
|
||||
*/
|
||||
struct CpRedirect : public cpr::Redirect
|
||||
{
|
||||
using cpr::Redirect::Redirect;
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
CpRedirect() = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
explicit CpRedirect(SQInteger maximum)
|
||||
: cpr::Redirect(static_cast< long >(maximum), true, cpr::PostRedirectFlags::POST_ALL)
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
CpRedirect(SQInteger maximum, bool follow)
|
||||
: cpr::Redirect(static_cast< long >(maximum), follow, cpr::PostRedirectFlags::POST_ALL)
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
CpRedirect(SQInteger maximum, bool follow, SQInteger post_flags)
|
||||
: cpr::Redirect(static_cast< long >(maximum), follow, static_cast< cpr::PostRedirectFlags >(post_flags))
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
explicit CpRedirect(const cpr::Redirect & e) : cpr::Redirect(e) { }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
explicit CpRedirect(cpr::Redirect && e) : cpr::Redirect(e) { }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
CpRedirect(const CpRedirect &) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
CpRedirect(CpRedirect &&) noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~CpRedirect() = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
CpRedirect & operator = (const CpRedirect &) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
CpRedirect & operator = (CpRedirect &&) noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the maximum number of redirects to follow. 0: Refuse any redirects. -1: Infinite number of redirects.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger GetMaximum() const noexcept
|
||||
{
|
||||
return static_cast< SQInteger >(cpr::Redirect::maximum);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the maximum number of redirects to follow. 0: Refuse any redirects. -1: Infinite number of redirects.
|
||||
*/
|
||||
void SetMaximum(SQInteger value) noexcept
|
||||
{
|
||||
cpr::Redirect::maximum = static_cast< long >(value);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the maximum number of redirects to follow. 0: Refuse any redirects. -1: Infinite number of redirects.
|
||||
*/
|
||||
CpRedirect & ApplyMaximum(SQInteger value) noexcept
|
||||
{
|
||||
SetMaximum(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve whether to follow 3xx redirects.
|
||||
*/
|
||||
SQMOD_NODISCARD bool GetFollow() const noexcept
|
||||
{
|
||||
return cpr::Redirect::follow;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify whether to follow 3xx redirects.
|
||||
*/
|
||||
void SetFollow(bool value) noexcept
|
||||
{
|
||||
cpr::Redirect::follow = value;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify whether to follow 3xx redirects.
|
||||
*/
|
||||
CpRedirect & ApplyFollow(bool value) noexcept
|
||||
{
|
||||
SetMaximum(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the flags to control how to act after a redirect for a post request.
|
||||
*/
|
||||
SQMOD_NODISCARD bool GetFlags() const noexcept
|
||||
{
|
||||
return cpr::Redirect::follow;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the flags to control how to act after a redirect for a post request.
|
||||
*/
|
||||
void SetFlags(bool value) noexcept
|
||||
{
|
||||
cpr::Redirect::follow = value;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the flags to control how to act after a redirect for a post request.
|
||||
*/
|
||||
CpRedirect & ApplyFlags(bool value) noexcept
|
||||
{
|
||||
SetMaximum(value);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Wrapper for cpr::Session that can be bound to the script engine.
|
||||
*/
|
||||
@@ -1620,7 +1766,7 @@ struct CpSession : public cpr::Session
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* URL constructor.
|
||||
*/
|
||||
CpSession(StackStrF & url)
|
||||
explicit CpSession(StackStrF & url)
|
||||
: cpr::Session()
|
||||
{
|
||||
cpr::Session::SetUrl(cpr::Url(url.mPtr, url.GetSize()));
|
||||
@@ -1654,7 +1800,7 @@ struct CpSession : public cpr::Session
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Throw exception if the session is locked.
|
||||
*/
|
||||
void LockCheck()
|
||||
void LockCheck() const
|
||||
{
|
||||
if (mPending)
|
||||
{
|
||||
@@ -1827,23 +1973,13 @@ struct CpSession : public cpr::Session
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify redirect option.
|
||||
*/
|
||||
CpSession & SetRedirect_(bool redirect)
|
||||
CpSession & SetRedirect_(CpRedirect & redirect)
|
||||
{
|
||||
LockCheck();
|
||||
cpr::Session::SetRedirect(redirect);
|
||||
return *this; // Allow chaining
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify max-redirects option.
|
||||
*/
|
||||
CpSession & SetMaxRedirects_(SQInteger max_redirects)
|
||||
{
|
||||
LockCheck();
|
||||
cpr::Session::SetMaxRedirects(cpr::MaxRedirects(static_cast< int32_t >(max_redirects)));
|
||||
return *this; // Allow chaining
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify cookies option.
|
||||
*/
|
||||
|
||||
+20
-16
@@ -3,7 +3,6 @@
|
||||
#include "Library/Chrono/Date.hpp"
|
||||
#include "Library/Chrono/Timer.hpp"
|
||||
#include "Library/Chrono/Timestamp.hpp"
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -243,33 +242,38 @@ int64_t Chrono::DateRangeToSeconds(uint16_t _year, uint8_t _month, uint8_t _day,
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SLongInt SqGetEpochTimeMicro()
|
||||
static SQRESULT SqGetEpochTimeMicro(HSQUIRRELVM vm)
|
||||
{
|
||||
return SLongInt(Chrono::GetEpochTimeMicro());
|
||||
sq_pushinteger(vm, Chrono::GetEpochTimeMicro());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SLongInt SqGetEpochTimeMilli()
|
||||
static SQRESULT SqGetEpochTimeMilli(HSQUIRRELVM vm)
|
||||
{
|
||||
return SLongInt(Chrono::GetEpochTimeMilli());
|
||||
sq_pushinteger(vm, Chrono::GetEpochTimeMilli());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SLongInt SqGetCurrentSysTime()
|
||||
static SQRESULT SqGetCurrentSysTime(HSQUIRRELVM vm)
|
||||
{
|
||||
return SLongInt(Chrono::GetCurrentSysTime());
|
||||
sq_pushinteger(vm, Chrono::GetCurrentSysTime());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqGetTickCount()
|
||||
static SQRESULT SqGetTickCount(HSQUIRRELVM vm)
|
||||
{
|
||||
return ConvTo< SQInteger >::From(GetTickCount());
|
||||
sq_pushinteger(vm, ConvTo< SQInteger >::From(GetTickCount()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SLongInt SqGetTickCount64()
|
||||
static SQRESULT SqGetTickCount64(HSQUIRRELVM vm)
|
||||
{
|
||||
return SLongInt(GetTickCount64());
|
||||
sq_pushinteger(vm, ConvTo< SQInteger >::From(GetTickCount64()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
@@ -284,11 +288,11 @@ void Register_Chrono(HSQUIRRELVM vm)
|
||||
Register_ChronoTimestamp(vm, cns);
|
||||
|
||||
cns
|
||||
.Func(_SC("EpochMicro"), &SqGetEpochTimeMicro)
|
||||
.Func(_SC("EpochMilli"), &SqGetEpochTimeMilli)
|
||||
.Func(_SC("Current"), &SqGetCurrentSysTime)
|
||||
.Func(_SC("TickCount"), &SqGetTickCount)
|
||||
.Func(_SC("TickCount64"), &SqGetTickCount64)
|
||||
.SquirrelFunc(_SC("EpochMicro"), &SqGetEpochTimeMicro)
|
||||
.SquirrelFunc(_SC("EpochMilli"), &SqGetEpochTimeMilli)
|
||||
.SquirrelFunc(_SC("Current"), &SqGetCurrentSysTime)
|
||||
.SquirrelFunc(_SC("TickCount"), &SqGetTickCount)
|
||||
.SquirrelFunc(_SC("TickCount64"), &SqGetTickCount64)
|
||||
.Func(_SC("IsLeapYear"), &Chrono::IsLeapYear)
|
||||
.Func(_SC("IsDateValid"), &Chrono::ValidDate)
|
||||
.Func(_SC("DaysInYear"), &Chrono::DaysInYear)
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Core/Common.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <ctime>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
|
||||
@@ -12,6 +12,19 @@ SQMOD_DECL_TYPENAME(Typename, _SC("SqDate"))
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQChar Date::Delimiter = '-';
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Date::Date(int64_t ts)
|
||||
: Date()
|
||||
{
|
||||
const auto y = static_cast< uint16_t >(std::lround(std::floor(ts / 3.17098e-14)));
|
||||
ts -= int64_t{y} * 3.17098e-14;
|
||||
const auto m = static_cast< uint8_t >(std::lround(std::floor(ts / 2.628e+12)));
|
||||
ts -= int64_t{m} * 2.628e+12;
|
||||
const auto d = static_cast< uint8_t >(std::lround(std::floor(ts / 8.64e+10)));
|
||||
// Set the specified date
|
||||
Set(y, m, d);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int32_t Date::Compare(const Date & o) const
|
||||
{
|
||||
@@ -363,6 +376,12 @@ Timestamp Date::GetTimestamp() const
|
||||
return Timestamp(static_cast< int64_t >(days * 86400000000LL));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::time_t Date::ToTimeT() const
|
||||
{
|
||||
return GetTimestamp().ToTimeT();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_ChronoDate(HSQUIRRELVM vm, Table & /*cns*/)
|
||||
{
|
||||
|
||||
@@ -83,6 +83,11 @@ public:
|
||||
SetStr(str);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Time-stamp constructor.
|
||||
*/
|
||||
explicit Date(int64_t ts);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
@@ -349,6 +354,11 @@ public:
|
||||
* Convert this date instance to a time-stamp.
|
||||
*/
|
||||
SQMOD_NODISCARD Timestamp GetTimestamp() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
std::time_t ToTimeT() const;
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
@@ -16,6 +16,26 @@ SQChar Datetime::Delimiter = ' ';
|
||||
SQChar Datetime::DateDelim = '-';
|
||||
SQChar Datetime::TimeDelim = ':';
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Datetime::Datetime(int64_t ts)
|
||||
: Datetime()
|
||||
{
|
||||
const auto y = static_cast< uint16_t >(std::lround(std::floor(ts / 3.17098e-14)));
|
||||
ts -= int64_t{y} * 3.17098e-14;
|
||||
const auto mo = static_cast< uint8_t >(std::lround(std::floor(ts / 2.628e+12)));
|
||||
ts -= int64_t{mo} * 2.628e+12;
|
||||
const auto d = static_cast< uint8_t >(std::lround(std::floor(ts / 8.64e+10)));
|
||||
ts -= int64_t{d} * 8.64e+10;
|
||||
const auto h = static_cast< uint8_t >(std::lround(std::floor(ts / 3.6e+9)));
|
||||
ts -= int64_t{h} * 3.6e+9;
|
||||
const auto mi = static_cast< uint8_t >(std::lround(std::floor(ts / 6e+7)));
|
||||
ts -= int64_t{mi} * 6e+7;
|
||||
const auto s = static_cast< uint8_t >(std::lround(std::floor(ts / 1e+6)));
|
||||
ts -= int64_t{s} * 1e+6;
|
||||
// Set the specified date-time
|
||||
Set(y, mo, d, h, mi, s, static_cast< uint16_t >(ts / 1000LL));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int32_t Datetime::Compare(const Datetime & o) const
|
||||
{
|
||||
@@ -745,6 +765,12 @@ Timestamp Datetime::GetTimestamp() const
|
||||
return Timestamp(ms);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::time_t Datetime::ToTimeT() const
|
||||
{
|
||||
return GetTimestamp().ToTimeT();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_ChronoDatetime(HSQUIRRELVM vm, Table & /*cns*/)
|
||||
{
|
||||
|
||||
@@ -140,6 +140,11 @@ public:
|
||||
Set(year, month, day, hour, minute, second, millisecond);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Time-stamp constructor.
|
||||
*/
|
||||
explicit Datetime(int64_t ts);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
@@ -572,6 +577,11 @@ public:
|
||||
* Convert this date-time instance to a time-stamp.
|
||||
*/
|
||||
SQMOD_NODISCARD Timestamp GetTimestamp() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
std::time_t ToTimeT() const;
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
@@ -12,6 +12,20 @@ SQMOD_DECL_TYPENAME(Typename, _SC("SqTime"))
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQChar Time::Delimiter = ':';
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Time::Time(int64_t ts)
|
||||
: Time()
|
||||
{
|
||||
const auto h = static_cast< uint8_t >(std::lround(std::floor(ts / 3.6e+9)));
|
||||
ts -= int64_t{h} * 3.6e+9;
|
||||
const auto m = static_cast< uint8_t >(std::lround(std::floor(ts / 6e+7)));
|
||||
ts -= int64_t{m} * 6e+7;
|
||||
const auto s = static_cast< uint8_t >(std::lround(std::floor(ts / 1e+6)));
|
||||
ts -= int64_t{s} * 1e+6;
|
||||
// Set the specified time
|
||||
Set(h, m, s, static_cast< uint16_t >(ts / 1000LL));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int32_t Time::Compare(const Time & o) const
|
||||
{
|
||||
@@ -410,6 +424,12 @@ Timestamp Time::GetTimestamp() const
|
||||
return Timestamp(ms);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::time_t Time::ToTimeT() const
|
||||
{
|
||||
return GetTimestamp().ToTimeT();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_ChronoTime(HSQUIRRELVM vm, Table & /*cns*/)
|
||||
{
|
||||
|
||||
@@ -26,10 +26,10 @@ protected:
|
||||
private:
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
uint8_t m_Hour{}; // Hour
|
||||
uint8_t m_Minute{}; // Minute
|
||||
uint8_t m_Second{}; // Second
|
||||
uint16_t m_Millisecond{}; // Millisecond
|
||||
uint8_t m_Hour{0}; // Hour
|
||||
uint8_t m_Minute{0}; // Minute
|
||||
uint8_t m_Second{0}; // Second
|
||||
uint16_t m_Millisecond{0}; // Millisecond
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQChar m_Delimiter; // Component delimiter when generating strings.
|
||||
@@ -94,6 +94,11 @@ public:
|
||||
SetStr(str);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Time-stamp constructor.
|
||||
*/
|
||||
explicit Time(int64_t ts);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
@@ -354,6 +359,11 @@ public:
|
||||
* Convert this time instance to a time-stamp.
|
||||
*/
|
||||
SQMOD_NODISCARD Timestamp GetTimestamp() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
std::time_t ToTimeT() const;
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/Chrono/Timestamp.hpp"
|
||||
#include "Library/Chrono/Timer.hpp"
|
||||
#include "Library/Chrono/Time.hpp"
|
||||
#include "Library/Chrono/Date.hpp"
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
#include "Library/Chrono/Datetime.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <chrono>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
@@ -10,13 +14,6 @@ namespace SqMod {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_DECL_TYPENAME(Typename, _SC("SqTimestamp"))
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Timestamp::Timestamp(const SLongInt & t)
|
||||
: m_Timestamp(t.GetNum())
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int32_t Timestamp::Cmp(const Timestamp & o) const
|
||||
{
|
||||
@@ -47,27 +44,152 @@ void Timestamp::SetNow()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SLongInt Timestamp::GetMicroseconds() const
|
||||
SQInteger Timestamp::GetMicroseconds() const
|
||||
{
|
||||
return SLongInt(m_Timestamp);
|
||||
return m_Timestamp;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Timestamp::SetMicroseconds(const SLongInt & amount)
|
||||
void Timestamp::SetMicroseconds(SQInteger amount)
|
||||
{
|
||||
m_Timestamp = amount.GetNum();
|
||||
m_Timestamp = amount;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SLongInt Timestamp::GetMilliseconds() const
|
||||
Timestamp & Timestamp::AddMicroseconds(SQInteger amount) { m_Timestamp += amount; return *this; }
|
||||
Timestamp & Timestamp::SubMicroseconds(SQInteger amount) { m_Timestamp -= amount; return *this; }
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Timestamp::GetMilliseconds() const
|
||||
{
|
||||
return SLongInt(m_Timestamp / 1000L);
|
||||
return m_Timestamp / 1000L;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Timestamp::SetMilliseconds(const SLongInt & amount)
|
||||
void Timestamp::SetMilliseconds(SQInteger amount)
|
||||
{
|
||||
m_Timestamp = (amount.GetNum() * 1000L);
|
||||
m_Timestamp = (amount * 1000L);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Timestamp & Timestamp::AddMilliseconds(SQInteger amount) { m_Timestamp += (amount * 1000L); return *this; }
|
||||
Timestamp & Timestamp::SubMilliseconds(SQInteger amount) { m_Timestamp -= (amount * 1000L); return *this; }
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Time Timestamp::GetTime() const
|
||||
{
|
||||
return Time(m_Timestamp);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Timestamp::SetTime(const Time & t)
|
||||
{
|
||||
SetHoursI(t.GetHour());
|
||||
AddMinutesI(t.GetMinute());
|
||||
AddSecondsI(t.GetSecond());
|
||||
AddMillisecondsRaw(t.GetMillisecond());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Timestamp & Timestamp::AddTime(const Time & t)
|
||||
{
|
||||
AddHoursI(t.GetHour());
|
||||
AddMinutesI(t.GetMinute());
|
||||
AddSecondsI(t.GetSecond());
|
||||
AddMillisecondsRaw(t.GetMillisecond());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Timestamp & Timestamp::SubTime(const Time & t)
|
||||
{
|
||||
SubMillisecondsRaw(t.GetMillisecond());
|
||||
SubSecondsI(t.GetSecond());
|
||||
SubMinutesI(t.GetMinute());
|
||||
SubHoursI(t.GetHour());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Date Timestamp::GetDate() const
|
||||
{
|
||||
return Date(m_Timestamp);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Timestamp::SetDate(const Date & d)
|
||||
{
|
||||
SetYearsI(d.GetYear());
|
||||
AddDaysF(d.GetMonth() * 30.4167);
|
||||
AddDaysI(d.GetDay());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Timestamp & Timestamp::AddDate(const Date & d)
|
||||
{
|
||||
AddYearsI(d.GetYear());
|
||||
AddDaysF(d.GetMonth() * 30.4167);
|
||||
AddDaysI(d.GetDay());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Timestamp & Timestamp::SubDate(const Date & d)
|
||||
{
|
||||
SubDaysI(d.GetDay());
|
||||
SubDaysF(d.GetMonth() * 30.4167);
|
||||
SubYearsI(d.GetYear());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Datetime Timestamp::GetDatetime() const
|
||||
{
|
||||
return Datetime(m_Timestamp);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Timestamp::SetDatetime(const Datetime & dt)
|
||||
{
|
||||
SetYearsI(dt.GetYear());
|
||||
AddDaysF(dt.GetMonth() * 30.4167);
|
||||
AddDaysI(dt.GetDay());
|
||||
AddHoursI(dt.GetHour());
|
||||
AddMinutesI(dt.GetMinute());
|
||||
AddSecondsI(dt.GetSecond());
|
||||
AddMillisecondsRaw(dt.GetMillisecond());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Timestamp & Timestamp::AddDatetime(const Datetime & dt)
|
||||
{
|
||||
AddYearsI(dt.GetYear());
|
||||
AddDaysF(dt.GetMonth() * 30.4167);
|
||||
AddDaysI(dt.GetDay());
|
||||
AddHoursI(dt.GetHour());
|
||||
AddMinutesI(dt.GetMinute());
|
||||
AddSecondsI(dt.GetSecond());
|
||||
AddMillisecondsRaw(dt.GetMillisecond());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Timestamp & Timestamp::SubDatetime(const Datetime & dt)
|
||||
{
|
||||
SubMillisecondsRaw(dt.GetMillisecond());
|
||||
SubSecondsI(dt.GetSecond());
|
||||
SubMinutesI(dt.GetMinute());
|
||||
SubHoursI(dt.GetHour());
|
||||
SubDaysI(dt.GetDay());
|
||||
SubDaysF(dt.GetMonth() * 30.4167);
|
||||
SubYearsI(dt.GetYear());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::time_t Timestamp::ToTimeT() const
|
||||
{
|
||||
return std::chrono::system_clock::to_time_t(std::chrono::time_point< std::chrono::system_clock >{std::chrono::microseconds{m_Timestamp}});
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -83,7 +205,7 @@ static Timestamp SqGetMicrosecondsRaw(int64_t amount)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static Timestamp SqGetMicroseconds(const SLongInt & amount)
|
||||
static Timestamp SqGetMicroseconds(SQInteger amount)
|
||||
{
|
||||
return Timestamp(amount);
|
||||
}
|
||||
@@ -156,8 +278,46 @@ void Register_ChronoTimestamp(HSQUIRRELVM vm, Table & /*cns*/)
|
||||
.Prop(_SC("DaysI"), &Timestamp::GetDaysI, &Timestamp::SetDaysI)
|
||||
.Prop(_SC("YearsF"), &Timestamp::GetYearsF, &Timestamp::SetYearsF)
|
||||
.Prop(_SC("YearsI"), &Timestamp::GetYearsI, &Timestamp::SetYearsI)
|
||||
.Prop(_SC("Time"), &Timestamp::GetTime, &Timestamp::SetTime)
|
||||
.Prop(_SC("Date"), &Timestamp::GetDate, &Timestamp::SetDate)
|
||||
.Prop(_SC("Datetime"), &Timestamp::GetDatetime, &Timestamp::SetDatetime)
|
||||
// Member Methods
|
||||
.Func(_SC("SetNow"), &Timestamp::SetNow)
|
||||
// Properties
|
||||
.Func(_SC("AddMicroseconds"), &Timestamp::AddMicroseconds)
|
||||
.Func(_SC("SubMicroseconds"), &Timestamp::SubMicroseconds)
|
||||
.Func(_SC("AddMicrosecondsRaw"), &Timestamp::AddMicrosecondsRaw)
|
||||
.Func(_SC("SubMicrosecondsRaw"), &Timestamp::SubMicrosecondsRaw)
|
||||
.Func(_SC("AddMilliseconds"), &Timestamp::AddMilliseconds)
|
||||
.Func(_SC("SubMilliseconds"), &Timestamp::SubMilliseconds)
|
||||
.Func(_SC("AddMillisecondsRaw"), &Timestamp::AddMillisecondsRaw)
|
||||
.Func(_SC("SubMillisecondsRaw"), &Timestamp::SubMillisecondsRaw)
|
||||
.Func(_SC("AddSecondsF"), &Timestamp::AddSecondsF)
|
||||
.Func(_SC("SubSecondsF"), &Timestamp::SubSecondsF)
|
||||
.Func(_SC("AddSecondsI"), &Timestamp::AddSecondsI)
|
||||
.Func(_SC("SubSecondsI"), &Timestamp::SubSecondsI)
|
||||
.Func(_SC("AddMinutesF"), &Timestamp::AddMinutesF)
|
||||
.Func(_SC("SubMinutesF"), &Timestamp::SubMinutesF)
|
||||
.Func(_SC("AddMinutesI"), &Timestamp::AddMinutesI)
|
||||
.Func(_SC("SubMinutesI"), &Timestamp::SubMinutesI)
|
||||
.Func(_SC("AddHoursF"), &Timestamp::AddHoursF)
|
||||
.Func(_SC("SubHoursF"), &Timestamp::SubHoursF)
|
||||
.Func(_SC("AddHoursI"), &Timestamp::AddHoursI)
|
||||
.Func(_SC("SubHoursI"), &Timestamp::SubHoursI)
|
||||
.Func(_SC("AddDaysF"), &Timestamp::AddDaysF)
|
||||
.Func(_SC("SubDaysF"), &Timestamp::SubDaysF)
|
||||
.Func(_SC("AddDaysI"), &Timestamp::AddDaysI)
|
||||
.Func(_SC("SubDaysI"), &Timestamp::SubDaysI)
|
||||
.Func(_SC("AddYearsF"), &Timestamp::AddYearsF)
|
||||
.Func(_SC("SubYearsF"), &Timestamp::SubYearsF)
|
||||
.Func(_SC("AddYearsI"), &Timestamp::AddYearsI)
|
||||
.Func(_SC("SubYearsI"), &Timestamp::SubYearsI)
|
||||
.Func(_SC("AddTime"), &Timestamp::AddTime)
|
||||
.Func(_SC("SubTime"), &Timestamp::SubTime)
|
||||
.Func(_SC("AddDate"), &Timestamp::AddDate)
|
||||
.Func(_SC("SubDate"), &Timestamp::SubDate)
|
||||
.Func(_SC("AddDatetime"), &Timestamp::AddDatetime)
|
||||
.Func(_SC("SubDatetime"), &Timestamp::SubDatetime)
|
||||
// Static Functions
|
||||
.StaticFunc(_SC("GetNow"), &SqGetEpochTimeNow)
|
||||
.StaticFunc(_SC("GetMicrosRaw"), &SqGetMicrosecondsRaw)
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
class Date;
|
||||
class Time;
|
||||
class Timer;
|
||||
class Datetime;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
@@ -37,11 +40,6 @@ public:
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
explicit Timestamp(const SLongInt & t);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
@@ -119,12 +117,18 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD SLongInt GetMicroseconds() const;
|
||||
SQMOD_NODISCARD SQInteger GetMicroseconds() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
void SetMicroseconds(const SLongInt & amount);
|
||||
void SetMicroseconds(SQInteger amount);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddMicroseconds(SQInteger amount);
|
||||
Timestamp & SubMicroseconds(SQInteger amount);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
@@ -145,12 +149,24 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD SLongInt GetMilliseconds() const;
|
||||
Timestamp & AddMicrosecondsRaw(SQInteger amount) { m_Timestamp += amount; return *this; }
|
||||
Timestamp & SubMicrosecondsRaw(SQInteger amount) { m_Timestamp -= amount; return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
void SetMilliseconds(const SLongInt & amount);
|
||||
SQMOD_NODISCARD SQInteger GetMilliseconds() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
void SetMilliseconds(SQInteger amount);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddMilliseconds(SQInteger amount);
|
||||
Timestamp & SubMilliseconds(SQInteger amount);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
@@ -168,6 +184,12 @@ public:
|
||||
m_Timestamp = int64_t(int64_t(amount) * 1000L);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddMillisecondsRaw(SQInteger amount) { m_Timestamp += int64_t(int64_t(amount) * 1000L); return *this; }
|
||||
Timestamp & SubMillisecondsRaw(SQInteger amount) { m_Timestamp -= int64_t(int64_t(amount) * 1000L); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
@@ -184,6 +206,12 @@ public:
|
||||
m_Timestamp = int64_t(double(amount) * 1000000L);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddSecondsF(SQFloat amount) { m_Timestamp += int64_t(double(amount) * 1000000L); return *this; }
|
||||
Timestamp & SubSecondsF(SQFloat amount) { m_Timestamp -= int64_t(double(amount) * 1000000L); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
@@ -200,12 +228,18 @@ public:
|
||||
m_Timestamp = int64_t(int64_t(amount) * 1000000L);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddSecondsI(SQInteger amount) { m_Timestamp += int64_t(int64_t(amount) * 1000000L); return *this; }
|
||||
Timestamp & SubSecondsI(SQInteger amount) { m_Timestamp -= int64_t(int64_t(amount) * 1000000L); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD SQFloat GetMinutesF() const
|
||||
{
|
||||
return SQFloat(m_Timestamp / 60000000.0);
|
||||
return SQFloat(m_Timestamp) / 60000000.0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -216,6 +250,12 @@ public:
|
||||
m_Timestamp = int64_t(double(amount) * 60000000L);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddMinutesF(SQFloat amount) { m_Timestamp += int64_t(double(amount) * 60000000L); return *this; }
|
||||
Timestamp & SubMinutesF(SQFloat amount) { m_Timestamp -= int64_t(double(amount) * 60000000L); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
@@ -232,12 +272,18 @@ public:
|
||||
m_Timestamp = int64_t(int64_t(amount) * 60000000L);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddMinutesI(SQInteger amount) { m_Timestamp += int64_t(int64_t(amount) * 60000000L); return *this; }
|
||||
Timestamp & SubMinutesI(SQInteger amount) { m_Timestamp -= int64_t(int64_t(amount) * 60000000L); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD SQFloat GetHoursF() const
|
||||
{
|
||||
return SQFloat(m_Timestamp / 3600000000.0);
|
||||
return SQFloat(m_Timestamp) / 3600000000.0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -248,6 +294,12 @@ public:
|
||||
m_Timestamp = int64_t(double(amount) * 3600000000LL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddHoursF(SQFloat amount) { m_Timestamp += int64_t(double(amount) * 3600000000LL); return *this; }
|
||||
Timestamp & SubHoursF(SQFloat amount) { m_Timestamp -= int64_t(double(amount) * 3600000000LL); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
@@ -264,12 +316,18 @@ public:
|
||||
m_Timestamp = int64_t(double(amount) * 3600000000LL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddHoursI(SQInteger amount) { m_Timestamp += int64_t(double(amount) * 3600000000LL); return *this; }
|
||||
Timestamp & SubHoursI(SQInteger amount) { m_Timestamp -= int64_t(double(amount) * 3600000000LL); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD SQFloat GetDaysF() const
|
||||
{
|
||||
return SQFloat(m_Timestamp / 86400000000.0);
|
||||
return SQFloat(m_Timestamp) / 86400000000.0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -280,6 +338,12 @@ public:
|
||||
m_Timestamp = int64_t(double(amount) * 86400000000LL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddDaysF(SQFloat amount) { m_Timestamp += int64_t(double(amount) * 86400000000LL); return *this; }
|
||||
Timestamp & SubDaysF(SQFloat amount) { m_Timestamp -= int64_t(double(amount) * 86400000000LL); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
@@ -296,12 +360,18 @@ public:
|
||||
m_Timestamp = int64_t(double(amount) * 86400000000LL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddDaysI(SQInteger amount) { m_Timestamp += int64_t(double(amount) * 86400000000LL); return *this; }
|
||||
Timestamp & SubDaysI(SQInteger amount) { m_Timestamp -= int64_t(double(amount) * 86400000000LL); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD SQFloat GetYearsF() const
|
||||
{
|
||||
return SQFloat(m_Timestamp / 31557600000000.0);
|
||||
return SQFloat(m_Timestamp) / 31557600000000.0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -312,6 +382,12 @@ public:
|
||||
m_Timestamp = int64_t(double(amount) * 31557600000000LL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddYearsF(SQFloat amount) { m_Timestamp += int64_t(double(amount) * 31557600000000LL); return *this; }
|
||||
Timestamp & SubYearsF(SQFloat amount) { m_Timestamp -= int64_t(double(amount) * 31557600000000LL); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
@@ -328,6 +404,65 @@ public:
|
||||
m_Timestamp = int64_t(double(amount) * 31557600000000LL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddYearsI(SQInteger amount) { m_Timestamp += int64_t(double(amount) * 31557600000000LL); return *this; }
|
||||
Timestamp & SubYearsI(SQInteger amount) { m_Timestamp -= int64_t(double(amount) * 31557600000000LL); return *this; }
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD Time GetTime() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
void SetTime(const Time & t);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddTime(const Time & t);
|
||||
Timestamp & SubTime(const Time & t);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD Date GetDate() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
void SetDate(const Date & d);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddDate(const Date & d);
|
||||
Timestamp & SubDate(const Date & d);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD Datetime GetDatetime() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
void SetDatetime(const Datetime & dt);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Timestamp & AddDatetime(const Datetime & dt);
|
||||
Timestamp & SubDatetime(const Datetime & dt);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQMOD_NODISCARD std::time_t ToTimeT() const;
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
+124
-102
@@ -1,6 +1,5 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/IO/Buffer.hpp"
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
#include "Base/AABB.hpp"
|
||||
#include "Base/Circle.hpp"
|
||||
#include "Base/Color3.hpp"
|
||||
@@ -12,6 +11,13 @@
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <Poco/Checksum.h>
|
||||
#include <Poco/Base32Encoder.h>
|
||||
#include <Poco/Base32Decoder.h>
|
||||
#include <Poco/Base64Encoder.h>
|
||||
#include <Poco/Base64Decoder.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sstream>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
@@ -20,25 +26,7 @@ namespace SqMod {
|
||||
SQMOD_DECL_TYPENAME(Typename, _SC("SqBuffer"))
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteInt64(const SLongInt & val)
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< int64_t >(val.GetNum());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteUint64(const ULongInt & val)
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< uint64_t >(val.GetNum());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger SqBuffer::WriteRawString(StackStrF & val)
|
||||
SQInteger SqBuffer::WriteRawString(StackStrF & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
@@ -49,14 +37,14 @@ SQInteger SqBuffer::WriteRawString(StackStrF & val)
|
||||
}
|
||||
// Calculate the string length
|
||||
Buffer::SzType length = ConvTo< Buffer::SzType >::From(val.mLen);
|
||||
// Write the the string contents
|
||||
// Write the string contents
|
||||
m_Buffer->AppendS(val.mPtr, length);
|
||||
// Return the length of the written string
|
||||
return val.mLen;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger SqBuffer::WriteClientString(StackStrF & val)
|
||||
SQInteger SqBuffer::WriteClientString(StackStrF & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
@@ -81,97 +69,67 @@ SQInteger SqBuffer::WriteClientString(StackStrF & val)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteAABB(const AABB & val)
|
||||
void SqBuffer::WriteAABB(const AABB & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< AABB >(val);
|
||||
Valid().Push< AABB >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteCircle(const Circle & val)
|
||||
void SqBuffer::WriteCircle(const Circle & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< Circle >(val);
|
||||
Valid().Push< Circle >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteColor3(const Color3 & val)
|
||||
void SqBuffer::WriteColor3(const Color3 & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< Color3 >(val);
|
||||
Valid().Push< Color3 >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteColor4(const Color4 & val)
|
||||
void SqBuffer::WriteColor4(const Color4 & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< Color4 >(val);
|
||||
Valid().Push< Color4 >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteQuaternion(const Quaternion & val)
|
||||
void SqBuffer::WriteQuaternion(const Quaternion & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< Quaternion >(val);
|
||||
Valid().Push< Quaternion >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteSphere(const Sphere &val)
|
||||
void SqBuffer::WriteSphere(const Sphere &val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< Sphere >(val);
|
||||
Valid().Push< Sphere >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteVector2(const Vector2 & val)
|
||||
void SqBuffer::WriteVector2(const Vector2 & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< Vector2 >(val);
|
||||
Valid().Push< Vector2 >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteVector2i(const Vector2i & val)
|
||||
void SqBuffer::WriteVector2i(const Vector2i & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< Vector2i >(val);
|
||||
Valid().Push< Vector2i >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteVector3(const Vector3 & val)
|
||||
void SqBuffer::WriteVector3(const Vector3 & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< Vector3 >(val);
|
||||
Valid().Push< Vector3 >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqBuffer::WriteVector4(const Vector4 & val)
|
||||
void SqBuffer::WriteVector4(const Vector4 & val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< Vector4 >(val);
|
||||
Valid().Push< Vector4 >(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SLongInt SqBuffer::ReadInt64()
|
||||
SQInteger SqBuffer::ReadInt64() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -180,11 +138,11 @@ SLongInt SqBuffer::ReadInt64()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< int64_t >(1);
|
||||
// Return the requested information
|
||||
return SLongInt(value);
|
||||
return static_cast< SQInteger >(value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ULongInt SqBuffer::ReadUint64()
|
||||
SQInteger SqBuffer::ReadUint64() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -193,11 +151,11 @@ ULongInt SqBuffer::ReadUint64()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< uint64_t >(1);
|
||||
// Return the requested information
|
||||
return ULongInt(value);
|
||||
return static_cast< SQInteger >(value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj SqBuffer::ReadRawString(SQInteger length)
|
||||
LightObj SqBuffer::ReadRawString(SQInteger length) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -237,7 +195,7 @@ LightObj SqBuffer::ReadRawString(SQInteger length)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj SqBuffer::ReadClientString()
|
||||
LightObj SqBuffer::ReadClientString() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -264,7 +222,7 @@ LightObj SqBuffer::ReadClientString()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AABB SqBuffer::ReadAABB()
|
||||
AABB SqBuffer::ReadAABB() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -273,11 +231,11 @@ AABB SqBuffer::ReadAABB()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< AABB >(1);
|
||||
// Return the requested information
|
||||
return AABB(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Circle SqBuffer::ReadCircle()
|
||||
Circle SqBuffer::ReadCircle() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -286,11 +244,11 @@ Circle SqBuffer::ReadCircle()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< Circle >(1);
|
||||
// Return the requested information
|
||||
return Circle(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Color3 SqBuffer::ReadColor3()
|
||||
Color3 SqBuffer::ReadColor3() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -299,11 +257,11 @@ Color3 SqBuffer::ReadColor3()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< Color3 >(1);
|
||||
// Return the requested information
|
||||
return Color3(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Color4 SqBuffer::ReadColor4()
|
||||
Color4 SqBuffer::ReadColor4() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -312,11 +270,11 @@ Color4 SqBuffer::ReadColor4()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< Color4 >(1);
|
||||
// Return the requested information
|
||||
return Color4(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Quaternion SqBuffer::ReadQuaternion()
|
||||
Quaternion SqBuffer::ReadQuaternion() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -325,11 +283,11 @@ Quaternion SqBuffer::ReadQuaternion()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< Quaternion >(1);
|
||||
// Return the requested information
|
||||
return Quaternion(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Sphere SqBuffer::ReadSphere()
|
||||
Sphere SqBuffer::ReadSphere() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -338,11 +296,11 @@ Sphere SqBuffer::ReadSphere()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< Sphere >(1);
|
||||
// Return the requested information
|
||||
return Sphere(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Vector2 SqBuffer::ReadVector2()
|
||||
Vector2 SqBuffer::ReadVector2() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -351,11 +309,11 @@ Vector2 SqBuffer::ReadVector2()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< Vector2 >(1);
|
||||
// Return the requested information
|
||||
return Vector2(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Vector2i SqBuffer::ReadVector2i()
|
||||
Vector2i SqBuffer::ReadVector2i() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -364,11 +322,11 @@ Vector2i SqBuffer::ReadVector2i()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< Vector2i >(1);
|
||||
// Return the requested information
|
||||
return Vector2i(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Vector3 SqBuffer::ReadVector3()
|
||||
Vector3 SqBuffer::ReadVector3() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -377,11 +335,11 @@ Vector3 SqBuffer::ReadVector3()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< Vector3 >(1);
|
||||
// Return the requested information
|
||||
return Vector3(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Vector4 SqBuffer::ReadVector4()
|
||||
Vector4 SqBuffer::ReadVector4() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -390,36 +348,97 @@ Vector4 SqBuffer::ReadVector4()
|
||||
// Advance the buffer cursor
|
||||
m_Buffer->Advance< Vector4 >(1);
|
||||
// Return the requested information
|
||||
return Vector4(value);
|
||||
return {value};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger SqBuffer::GetCRC32(SQInteger n)
|
||||
extern SQInteger SqFromNativeJSON(HSQUIRRELVM vm, const char * data, size_t size);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger SqBuffer::GetJSON(HSQUIRRELVM vm) const
|
||||
{
|
||||
// Remember the current stack size
|
||||
const SQInteger top = sq_gettop(vm);
|
||||
// Was the JSON string size specified?
|
||||
if (top < 2)
|
||||
{
|
||||
return sq_throwerror(vm, _SC("Please specify the size of the JSON string to parse"));
|
||||
}
|
||||
// Do we even point to a valid buffer?
|
||||
if (!m_Buffer)
|
||||
{
|
||||
return sq_throwerror(vm, _SC("Invalid memory buffer reference"));
|
||||
}
|
||||
// Validate the buffer itself
|
||||
else if (!(*m_Buffer))
|
||||
{
|
||||
return sq_throwerror(vm, _SC("Invalid memory buffer"));
|
||||
}
|
||||
// Attempt to create the JSON object and push it on the stack
|
||||
return SqFromNativeJSON(vm, &m_Buffer->Cursor< char >(), static_cast< size_t >(Var< SQInteger >{vm, 2}.value));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger SqBuffer::GetCRC32(SQInteger n) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
// Create the checksum computer
|
||||
Poco::Checksum c(Poco::Checksum::TYPE_CRC32);
|
||||
// Give it the data to process
|
||||
c.update(&m_Buffer->Cursor< char >(), n >= 0 ? static_cast< uint32_t >(n) : m_Buffer->Remaining());
|
||||
c.update(&m_Buffer->Cursor< char >(), ClampRemaining(n));
|
||||
// return the result
|
||||
return static_cast< SQInteger >(c.checksum());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger SqBuffer::GetADLER32(SQInteger n)
|
||||
SQInteger SqBuffer::GetADLER32(SQInteger n) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
// Create the checksum computer
|
||||
Poco::Checksum c(Poco::Checksum::TYPE_ADLER32);
|
||||
// Give it the data to process
|
||||
c.update(&m_Buffer->Cursor< char >(), n >= 0 ? static_cast< uint32_t >(n) : m_Buffer->Remaining());
|
||||
c.update(&m_Buffer->Cursor< char >(), ClampRemaining(n));
|
||||
// return the result
|
||||
return static_cast< SQInteger >(c.checksum());
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj SqBuffer::GetBase32(SQInteger n) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
// Create a string receiver
|
||||
std::ostringstream out;
|
||||
// Create the encoder
|
||||
Poco::Base32Encoder enc(out);
|
||||
// Encode the string
|
||||
enc.write(&m_Buffer->Cursor< char >(), ClampRemaining(n));
|
||||
// Close the encoder
|
||||
enc.close();
|
||||
// Return the resulted string
|
||||
return LightObj{out.str()};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj SqBuffer::GetBase64(SQInteger n) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
// Create a string receiver
|
||||
std::ostringstream out;
|
||||
// Create the encoder
|
||||
Poco::Base64Encoder enc(out);
|
||||
// Encode the string
|
||||
enc.write(&m_Buffer->Cursor< char >(), ClampRemaining(n));
|
||||
// Close the encoder
|
||||
enc.close();
|
||||
// Return the resulted string
|
||||
return LightObj{out.str()};
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_Buffer(HSQUIRRELVM vm)
|
||||
{
|
||||
@@ -506,6 +525,9 @@ void Register_Buffer(HSQUIRRELVM vm)
|
||||
.Func(_SC("ReadVector4"), &SqBuffer::ReadVector4)
|
||||
.Func(_SC("CRC32"), &SqBuffer::GetCRC32)
|
||||
.Func(_SC("ADLER32"), &SqBuffer::GetADLER32)
|
||||
.Func(_SC("Base32"), &SqBuffer::GetBase32)
|
||||
.Func(_SC("Base64"), &SqBuffer::GetBase64)
|
||||
.SquirrelMethod< SqBuffer, &SqBuffer::GetJSON >(_SC("GetJSON"))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+165
-200
@@ -45,7 +45,6 @@ public:
|
||||
SqBuffer()
|
||||
: m_Buffer(new Buffer())
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -54,7 +53,6 @@ public:
|
||||
explicit SqBuffer(SQInteger n)
|
||||
: m_Buffer(new Buffer(ConvTo< SzType >::From(n)))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -63,7 +61,6 @@ public:
|
||||
SqBuffer(SQInteger n, SQInteger c)
|
||||
: m_Buffer(new Buffer(ConvTo< SzType >::From(n), ConvTo< SzType >::From(c)))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -72,7 +69,6 @@ public:
|
||||
SqBuffer(ConstPtr p, SQInteger n)
|
||||
: m_Buffer(new Buffer(p, ConvTo< SzType >::From(n)))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -81,7 +77,6 @@ public:
|
||||
SqBuffer(ConstPtr p, SQInteger n, SQInteger c)
|
||||
: m_Buffer(new Buffer(p, ConvTo< SzType >::From(n), ConvTo< SzType >::From(c)))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -90,7 +85,6 @@ public:
|
||||
explicit SqBuffer(const SRef & ref) // NOLINT(modernize-pass-by-value)
|
||||
: m_Buffer(ref)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -99,7 +93,6 @@ public:
|
||||
explicit SqBuffer(const Buffer & b)
|
||||
: m_Buffer(new Buffer(b))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -108,7 +101,6 @@ public:
|
||||
explicit SqBuffer(Buffer && b)
|
||||
: m_Buffer(new Buffer(std::move(b)))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -181,26 +173,58 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the managed memory buffer reference.
|
||||
*/
|
||||
SQMOD_NODISCARD Buffer & Valid() const
|
||||
{
|
||||
Validate();
|
||||
// Return the buffer
|
||||
return *m_Buffer;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the managed memory buffer reference and the buffer itself.
|
||||
*/
|
||||
SQMOD_NODISCARD Buffer & ValidDeeper() const
|
||||
{
|
||||
ValidateDeeper();
|
||||
// Return the buffer
|
||||
return *m_Buffer;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Limit the specified amount at to the range of the cursor and the end of the buffer.
|
||||
*/
|
||||
SQMOD_NODISCARD SzType ClampRemaining(SQInteger n) const
|
||||
{
|
||||
// Do we even specify a buffer amount?
|
||||
if (n >= 0)
|
||||
{
|
||||
// Is it within the range we currently have left?
|
||||
if (static_cast< SzType >(n) <= m_Buffer->Remaining())
|
||||
{
|
||||
return static_cast< SzType >(n);
|
||||
}
|
||||
}
|
||||
// Fall back to the actual remaining data
|
||||
return m_Buffer->Remaining();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve a certain element type at the specified position.
|
||||
*/
|
||||
SQMOD_NODISCARD Value Get(SQInteger n) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
return m_Buffer->At(ConvTo< SzType >::From(n));
|
||||
return Valid().At(ConvTo< SzType >::From(n));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify a certain element type at the specified position.
|
||||
*/
|
||||
void Set(SQInteger n, SQInteger v)
|
||||
void Set(SQInteger n, SQInteger v) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
m_Buffer->At(ConvTo< SzType >::From(n)) = ConvTo< Value >::From(v);
|
||||
Valid().At(ConvTo< SzType >::From(n)) = ConvTo< Value >::From(v);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -208,21 +232,15 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD Value GetFront() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
return m_Buffer->Front();
|
||||
return Valid().Front();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the element at the front of the buffer.
|
||||
*/
|
||||
void SetFront(SQInteger v)
|
||||
void SetFront(SQInteger v) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
m_Buffer->Front() = ConvTo< Value >::From(v);
|
||||
Valid().Front() = ConvTo< Value >::From(v);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -230,21 +248,15 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD Value GetNext() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
return m_Buffer->Next();
|
||||
return Valid().Next();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the element after the first element in the buffer.
|
||||
*/
|
||||
void SetNext(SQInteger v)
|
||||
void SetNext(SQInteger v) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
m_Buffer->Next() = ConvTo< Value >::From(v);
|
||||
Valid().Next() = ConvTo< Value >::From(v);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -252,21 +264,15 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD Value GetBack() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
return m_Buffer->Back();
|
||||
return Valid().Back();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the element at the back of the buffer.
|
||||
*/
|
||||
void SetBack(SQInteger v)
|
||||
void SetBack(SQInteger v) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
m_Buffer->Back() = ConvTo< Value >::From(v);
|
||||
Valid().Back() = ConvTo< Value >::From(v);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -274,65 +280,55 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD Value GetPrev() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
return m_Buffer->Prev();
|
||||
return Valid().Prev();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the element before the last element in the buffer.
|
||||
*/
|
||||
void SetPrev(SQInteger v)
|
||||
void SetPrev(SQInteger v) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
m_Buffer->Prev() = ConvTo< Value >::From(v);
|
||||
Valid().Prev() = ConvTo< Value >::From(v);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Reposition the edit cursor to the specified number of elements ahead.
|
||||
*/
|
||||
void Advance(SQInteger n)
|
||||
SqBuffer & Advance(SQInteger n)
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Advance(ConvTo< SzType >::From(n));
|
||||
Valid().Advance(ConvTo< SzType >::From(n));
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Reposition the edit cursor to the specified number of elements behind.
|
||||
*/
|
||||
void Retreat(SQInteger n)
|
||||
SqBuffer & Retreat(SQInteger n)
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Retreat(ConvTo< SzType >::From(n));
|
||||
Valid().Retreat(ConvTo< SzType >::From(n));
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Reposition the edit cursor to a fixed position within the buffer.
|
||||
*/
|
||||
void Move(SQInteger n)
|
||||
SqBuffer & Move(SQInteger n)
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Move(ConvTo< SzType >::From(n));
|
||||
Valid().Move(ConvTo< SzType >::From(n));
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Append a value to the current cursor location and advance the cursor.
|
||||
*/
|
||||
void Push(SQInteger v)
|
||||
SqBuffer & Push(SQInteger v)
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push(ConvTo< Value >::From(v));
|
||||
Valid().Push(ConvTo< Value >::From(v));
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -340,21 +336,15 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD Value GetCursor() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
return m_Buffer->Cursor();
|
||||
return Valid().Cursor();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the element at the cursor position.
|
||||
*/
|
||||
void SetCursor(SQInteger v)
|
||||
void SetCursor(SQInteger v) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
m_Buffer->Cursor() = ConvTo< Value >::From(v);
|
||||
Valid().Cursor() = ConvTo< Value >::From(v);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -362,21 +352,15 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD Value GetBefore() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
return m_Buffer->Before();
|
||||
return Valid().Before();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the element before the cursor position.
|
||||
*/
|
||||
void SetBefore(SQInteger v)
|
||||
void SetBefore(SQInteger v) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
m_Buffer->Before() = ConvTo< Value >::From(v);
|
||||
Valid().Before() = ConvTo< Value >::From(v);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -384,21 +368,15 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD Value GetAfter() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
return m_Buffer->After();
|
||||
return Valid().After();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the element after the cursor position.
|
||||
*/
|
||||
void SetAfter(SQInteger v)
|
||||
void SetAfter(SQInteger v) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested element
|
||||
m_Buffer->After() = ConvTo< Value >::From(v);
|
||||
Valid().After() = ConvTo< Value >::From(v);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -414,10 +392,7 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD SzType GetSize() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return m_Buffer->CapacityAs< Value >();
|
||||
return Valid().CapacityAs< Value >();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -425,10 +400,7 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD SzType GetCapacity() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return m_Buffer->Capacity();
|
||||
return Valid().Capacity();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -436,10 +408,7 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD SzType GetPosition() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return m_Buffer->Position();
|
||||
return Valid().Position();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -447,27 +416,23 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD SzType GetRemaining() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return m_Buffer->Remaining();
|
||||
return Valid().Remaining();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Grow the size of the internal buffer by the specified amount of bytes.
|
||||
*/
|
||||
void Grow(SQInteger n)
|
||||
SqBuffer & Grow(SQInteger n)
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
return m_Buffer->Grow(ConvTo< SzType >::From(n) * sizeof(Value));
|
||||
Valid().Grow(ConvTo< SzType >::From(n) * sizeof(Value));
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Makes sure there is enough capacity to hold the specified element count.
|
||||
*/
|
||||
void Adjust(SQInteger n)
|
||||
SqBuffer & Adjust(SQInteger n)
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
@@ -483,170 +448,154 @@ public:
|
||||
{
|
||||
STHROWF("{}", e.what()); // Re-package
|
||||
}
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a signed 8 bit integer to the buffer.
|
||||
*/
|
||||
void WriteInt8(SQInteger val)
|
||||
void WriteInt8(SQInteger val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< int8_t >(ConvTo< int8_t >::From(val));
|
||||
Valid().Push< int8_t >(static_cast< int8_t >(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write an unsigned 8 bit integer to the buffer.
|
||||
*/
|
||||
void WriteUint8(SQInteger val)
|
||||
void WriteUint8(SQInteger val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< uint8_t >(ConvTo< uint8_t >::From(val));
|
||||
Valid().Push< uint8_t >(static_cast< uint8_t >(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a signed 16 bit integer to the buffer.
|
||||
*/
|
||||
void WriteInt16(SQInteger val)
|
||||
void WriteInt16(SQInteger val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< int16_t >(ConvTo< int16_t >::From(val));
|
||||
Valid().Push< int16_t >(static_cast< int16_t >(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write an unsigned 16 bit integer to the buffer.
|
||||
*/
|
||||
void WriteUint16(SQInteger val)
|
||||
void WriteUint16(SQInteger val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< uint16_t >(ConvTo< uint16_t >::From(val));
|
||||
Valid().Push< uint16_t >(static_cast< uint16_t >(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a signed 32 bit integer to the buffer.
|
||||
*/
|
||||
void WriteInt32(SQInteger val)
|
||||
void WriteInt32(SQInteger val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< int32_t >(ConvTo< int32_t >::From(val));
|
||||
Valid().Push< int32_t >(static_cast< int32_t >(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write an unsigned 32 bit integer to the buffer.
|
||||
*/
|
||||
void WriteUint32(SQInteger val)
|
||||
void WriteUint32(SQInteger val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< uint32_t >(ConvTo< uint32_t >::From(val));
|
||||
Valid().Push< uint32_t >(static_cast< uint32_t >(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a signed 64 bit integer to the buffer.
|
||||
*/
|
||||
void WriteInt64(const SLongInt & val);
|
||||
void WriteInt64(SQInteger val) const
|
||||
{
|
||||
Valid().Push< int64_t >(static_cast< int64_t >(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write an unsigned 64 bit integer to the buffer.
|
||||
*/
|
||||
void WriteUint64(const ULongInt & val);
|
||||
void WriteUint64(SQInteger val) const
|
||||
{
|
||||
Valid().Push< uint64_t >(static_cast< uint64_t >(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a 32 bit float to the buffer.
|
||||
*/
|
||||
void WriteFloat32(SQFloat val)
|
||||
void WriteFloat32(SQFloat val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< float >(ConvTo< float >::From(val));
|
||||
Valid().Push< float >(ConvTo< float >::From(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a 64 bit float to the buffer.
|
||||
*/
|
||||
void WriteFloat64(SQFloat val)
|
||||
void WriteFloat64(SQFloat val) const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Buffer->Push< double >(ConvTo< double >::From(val));
|
||||
Valid().Push< double >(ConvTo< double >::From(val));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a raw string to the buffer.
|
||||
*/
|
||||
SQInteger WriteRawString(StackStrF & val);
|
||||
SQInteger WriteRawString(StackStrF & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a client encoded string to the buffer.
|
||||
*/
|
||||
SQInteger WriteClientString(StackStrF & val);
|
||||
SQInteger WriteClientString(StackStrF & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a AABB to the buffer.
|
||||
*/
|
||||
void WriteAABB(const AABB & val);
|
||||
void WriteAABB(const AABB & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a Circle to the buffer.
|
||||
*/
|
||||
void WriteCircle(const Circle & val);
|
||||
void WriteCircle(const Circle & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a Color3 to the buffer.
|
||||
*/
|
||||
void WriteColor3(const Color3 & val);
|
||||
void WriteColor3(const Color3 & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a Color4 to the buffer.
|
||||
*/
|
||||
void WriteColor4(const Color4 & val);
|
||||
void WriteColor4(const Color4 & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a Quaternion to the buffer.
|
||||
*/
|
||||
void WriteQuaternion(const Quaternion & val);
|
||||
void WriteQuaternion(const Quaternion & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a Sphere to the buffer.
|
||||
*/
|
||||
void WriteSphere(const Sphere &val);
|
||||
void WriteSphere(const Sphere &val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a Vector2 to the buffer.
|
||||
*/
|
||||
void WriteVector2(const Vector2 & val);
|
||||
void WriteVector2(const Vector2 & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a Vector2i to the buffer.
|
||||
*/
|
||||
void WriteVector2i(const Vector2i & val);
|
||||
void WriteVector2i(const Vector2i & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a Vector3 to the buffer.
|
||||
*/
|
||||
void WriteVector3(const Vector3 & val);
|
||||
void WriteVector3(const Vector3 & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a Vector4 to the buffer.
|
||||
*/
|
||||
void WriteVector4(const Vector4 & val);
|
||||
void WriteVector4(const Vector4 & val) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a signed 8 bit integer from the buffer.
|
||||
*/
|
||||
SQInteger ReadInt8()
|
||||
SQMOD_NODISCARD SQInteger ReadInt8() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -661,7 +610,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read an unsigned 8 bit integer from the buffer.
|
||||
*/
|
||||
SQInteger ReadUint8()
|
||||
SQMOD_NODISCARD SQInteger ReadUint8() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -676,7 +625,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a signed 16 bit integer from the buffer.
|
||||
*/
|
||||
SQInteger ReadInt16()
|
||||
SQMOD_NODISCARD SQInteger ReadInt16() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -691,7 +640,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read an unsigned 16 bit integer from the buffer.
|
||||
*/
|
||||
SQInteger ReadUint16()
|
||||
SQMOD_NODISCARD SQInteger ReadUint16() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -706,7 +655,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a signed 32 bit integer from the buffer.
|
||||
*/
|
||||
SQInteger ReadInt32()
|
||||
SQMOD_NODISCARD SQInteger ReadInt32() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -721,7 +670,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read an unsigned 32 bit integer from the buffer.
|
||||
*/
|
||||
SQInteger ReadUint32()
|
||||
SQMOD_NODISCARD SQInteger ReadUint32() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -736,17 +685,17 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a signed 64 bit integer from the buffer.
|
||||
*/
|
||||
SLongInt ReadInt64();
|
||||
SQMOD_NODISCARD SQInteger ReadInt64() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read an unsigned 64 bit integer from the buffer.
|
||||
*/
|
||||
ULongInt ReadUint64();
|
||||
SQMOD_NODISCARD SQInteger ReadUint64() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a 32 bit float from the buffer.
|
||||
*/
|
||||
SQFloat ReadFloat32()
|
||||
SQMOD_NODISCARD SQFloat ReadFloat32() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -761,7 +710,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a 64 bit float from the buffer.
|
||||
*/
|
||||
SQFloat ReadFloat64()
|
||||
SQMOD_NODISCARD SQFloat ReadFloat64() const
|
||||
{
|
||||
// Validate the managed buffer reference
|
||||
ValidateDeeper();
|
||||
@@ -776,72 +725,88 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a raw string from the buffer.
|
||||
*/
|
||||
LightObj ReadRawString(SQInteger length);
|
||||
SQMOD_NODISCARD LightObj ReadRawString(SQInteger length) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a string from the buffer.
|
||||
*/
|
||||
LightObj ReadClientString();
|
||||
SQMOD_NODISCARD LightObj ReadClientString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a AABB from the buffer.
|
||||
*/
|
||||
AABB ReadAABB();
|
||||
SQMOD_NODISCARD AABB ReadAABB() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a Circle from the buffer.
|
||||
*/
|
||||
Circle ReadCircle();
|
||||
SQMOD_NODISCARD Circle ReadCircle() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a Color3 from the buffer.
|
||||
*/
|
||||
Color3 ReadColor3();
|
||||
SQMOD_NODISCARD Color3 ReadColor3() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a Color4 from the buffer.
|
||||
*/
|
||||
Color4 ReadColor4();
|
||||
SQMOD_NODISCARD Color4 ReadColor4() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a Quaternion from the buffer.
|
||||
*/
|
||||
Quaternion ReadQuaternion();
|
||||
SQMOD_NODISCARD Quaternion ReadQuaternion() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a Sphere from the buffer.
|
||||
*/
|
||||
Sphere ReadSphere();
|
||||
SQMOD_NODISCARD Sphere ReadSphere() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a Vector2 from the buffer.
|
||||
*/
|
||||
Vector2 ReadVector2();
|
||||
SQMOD_NODISCARD Vector2 ReadVector2() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a Vector2i from the buffer.
|
||||
*/
|
||||
Vector2i ReadVector2i();
|
||||
SQMOD_NODISCARD Vector2i ReadVector2i() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a Vector3 from the buffer.
|
||||
*/
|
||||
Vector3 ReadVector3();
|
||||
SQMOD_NODISCARD Vector3 ReadVector3() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Read a Vector4 from the buffer.
|
||||
*/
|
||||
Vector4 ReadVector4();
|
||||
SQMOD_NODISCARD Vector4 ReadVector4() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Transform a portion of the data in the buffer to a JSON object.
|
||||
* This has the benefit that a temporary string doesn't have to be created.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger GetJSON(HSQUIRRELVM vm) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Compute the CRC-32 checksums on the data in the buffer.
|
||||
*/
|
||||
SQInteger GetCRC32(SQInteger n);
|
||||
SQMOD_NODISCARD SQInteger GetCRC32(SQInteger n) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Compute the Adler-32 checksums on the data in the buffer.
|
||||
*/
|
||||
SQInteger GetADLER32(SQInteger n);
|
||||
SQMOD_NODISCARD SQInteger GetADLER32(SQInteger n) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Encode the specified range of data as base32 and return it.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj GetBase32(SQInteger n) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Encode the specified range of data as base64 and return it.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj GetBase64(SQInteger n) const;
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
@@ -381,7 +381,7 @@ void Register_INI(HSQUIRRELVM vm)
|
||||
.Func(_SC("Check"), &IniResult::Check)
|
||||
);
|
||||
|
||||
inins.Bind(_SC("IniEntries"),
|
||||
inins.Bind(_SC("Entries"),
|
||||
Class< IniEntries >(vm, EntriesTypename::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
@@ -409,7 +409,7 @@ void Register_INI(HSQUIRRELVM vm)
|
||||
.Func(_SC("SortByLoadOrder"), &IniEntries::SortByLoadOrder)
|
||||
);
|
||||
|
||||
inins.Bind(_SC("IniDocument"),
|
||||
inins.Bind(_SC("Document"),
|
||||
Class< IniDocument, NoCopy< IniDocument > >(vm, DocumentTypename::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
@@ -464,7 +464,7 @@ void Register_INI(HSQUIRRELVM vm)
|
||||
.Overload< bool (IniDocument::*)(const SQChar *, const SQChar *, const SQChar *, bool) >(_SC("DeleteValue"), &IniDocument::DeleteValue)
|
||||
);
|
||||
|
||||
RootTable(vm).Bind(_SC("SqIni"), inins);
|
||||
RootTable(vm).Bind(_SC("SqINI"), inins);
|
||||
|
||||
ConstTable(vm).Enum(_SC("SqIniError"), Enumeration(vm)
|
||||
.Const(_SC("Ok"), int32_t(SI_OK))
|
||||
|
||||
+608
-5
@@ -2,6 +2,7 @@
|
||||
#include "Library/JSON.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sajson.h>
|
||||
#include <sqratConst.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -11,13 +12,10 @@
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqToJSON(HSQUIRRELVM vm) noexcept
|
||||
{
|
||||
return sq_throwerror(vm, _SC("Not implemented yet!"));
|
||||
}
|
||||
SQMOD_DECL_TYPENAME(SqCtxJSON, _SC("SqCtxJSON"))
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqFromJson_Push(HSQUIRRELVM vm, const sajson::value & node) noexcept
|
||||
static SQInteger SqFromJson_Push(HSQUIRRELVM vm, const sajson::value & node) noexcept // NOLINT(misc-no-recursion)
|
||||
{
|
||||
// Operation result
|
||||
SQInteger r = SQ_OK;
|
||||
@@ -151,11 +149,616 @@ static SQInteger SqFromJSON(HSQUIRRELVM vm) noexcept
|
||||
return SQ_SUCCEEDED(r) ? 1 : r;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger SqFromNativeJSON(HSQUIRRELVM vm, const char * data, size_t size)
|
||||
{
|
||||
// Attempt to parse the specified JSON string
|
||||
const sajson::document & document = sajson::parse(sajson::dynamic_allocation(), sajson::string(data, size));
|
||||
// See if there was an error
|
||||
if (!document.is_valid())
|
||||
{
|
||||
return sq_throwerror(vm, document.get_error_message_as_cstring());
|
||||
}
|
||||
// Process the nodes that were parsed from the string
|
||||
SQInteger r = SqFromJson_Push(vm, document.get_root());
|
||||
// We either have a value to return or we propagate some error
|
||||
return SQ_SUCCEEDED(r) ? 1 : r;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CtxJSON & CtxJSON::OpenArray()
|
||||
{
|
||||
// Add the array-begin character
|
||||
mOutput.push_back('[');
|
||||
// Go forward one level
|
||||
Advance();
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CtxJSON & CtxJSON::CloseArray()
|
||||
{
|
||||
// If the last character is a comma then replace it
|
||||
if (mOutput.back() == ',')
|
||||
{
|
||||
mOutput.back() = ']';
|
||||
}
|
||||
// Append the array-end character
|
||||
else
|
||||
{
|
||||
mOutput.push_back(']');
|
||||
}
|
||||
// Move the comma after the closing character
|
||||
mOutput.push_back(',');
|
||||
// Go back one level
|
||||
Retreat();
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CtxJSON & CtxJSON::ReopenArray()
|
||||
{
|
||||
// If the last character is a comma then remove it
|
||||
if (mOutput.back() == ',')
|
||||
{
|
||||
mOutput.pop_back();
|
||||
}
|
||||
// If the last character is the array-end character then replace it with a comma
|
||||
if (mOutput.back() == ']')
|
||||
{
|
||||
mOutput.back() = ',';
|
||||
}
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CtxJSON & CtxJSON::OpenObject()
|
||||
{
|
||||
// Add the object-begin character
|
||||
mOutput.push_back('{');
|
||||
// Go forward one level
|
||||
Advance();
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CtxJSON & CtxJSON::CloseObject()
|
||||
{
|
||||
// If the last character is a comma then replace it
|
||||
if (mOutput.back() == ',')
|
||||
{
|
||||
mOutput.back() = '}';
|
||||
}
|
||||
// Append the object-end character
|
||||
else
|
||||
{
|
||||
mOutput.push_back('}');
|
||||
}
|
||||
// Move the comma after the closing character
|
||||
mOutput.push_back(',');
|
||||
// Go back one level
|
||||
Retreat();
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CtxJSON & CtxJSON::ReopenObject()
|
||||
{
|
||||
// If the last character is a comma then remove it
|
||||
if (mOutput.back() == ',')
|
||||
{
|
||||
mOutput.pop_back();
|
||||
}
|
||||
// If the last character is the object-end character then replace it with a comma
|
||||
if (mOutput.back() == '}')
|
||||
{
|
||||
mOutput.back() = ',';
|
||||
}
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CtxJSON & CtxJSON::MakeKey()
|
||||
{
|
||||
// If the last character is a comma then replace it
|
||||
if (mOutput.back() == ',')
|
||||
{
|
||||
mOutput.back() = ':';
|
||||
}
|
||||
// Append the array-end character
|
||||
else
|
||||
{
|
||||
mOutput.push_back(':');
|
||||
}
|
||||
// Allow the hook to react
|
||||
if (mKeyHook)
|
||||
{
|
||||
mKeyHook(*this);
|
||||
}
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool CtxJSON::CheckWeakRefWrap(HSQUIRRELVM vm, SQInteger idx) noexcept
|
||||
{
|
||||
SQRESULT r = sq_getweakrefval(vm, idx);
|
||||
// Whether the type doesn't have to be wrapped
|
||||
bool w = true;
|
||||
// Attempt to grab the value pointed by the weak reference
|
||||
if (SQ_SUCCEEDED(r))
|
||||
{
|
||||
// Attempt to serialize the actual value
|
||||
w = sq_gettype(vm, -1) != OT_TABLE && sq_gettype(vm, -1) != OT_ARRAY && sq_gettype(vm, -1) == OT_INSTANCE;
|
||||
// Pop the referenced value
|
||||
sq_poptop(vm);
|
||||
}
|
||||
// Wrap the value by default
|
||||
return w;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQRESULT CtxJSON::SerializeParams(HSQUIRRELVM vm)
|
||||
{
|
||||
bool wrap_everything_in_array = false;
|
||||
// Clear the output buffer if necessary
|
||||
mOutput.clear();
|
||||
mDepth = 0;
|
||||
// Fetch the number of objects on the stack
|
||||
const auto top = sq_gettop(vm);
|
||||
// If there's more than one argument then they all get wrapped inside an array
|
||||
// If there is one argument and is not an array, table or instance then do the same
|
||||
if (top > 2 || (sq_gettype(vm, 2) != OT_TABLE &&
|
||||
sq_gettype(vm, 2) != OT_ARRAY &&
|
||||
sq_gettype(vm, 2) != OT_INSTANCE &&
|
||||
CheckWeakRefWrap(vm, 2)))
|
||||
{
|
||||
wrap_everything_in_array = true;
|
||||
// Open an array
|
||||
OpenArray();
|
||||
}
|
||||
// Serialize every specified argument
|
||||
for (SQInteger i = 2; i <= top; ++i)
|
||||
{
|
||||
if (SQRESULT r = SerializeAt(vm, i); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
}
|
||||
// Was everything wrapped inside an array?
|
||||
if (wrap_everything_in_array)
|
||||
{
|
||||
CloseArray();
|
||||
}
|
||||
// Remove trailing separator, if any
|
||||
if (mOutput.back() == ',')
|
||||
{
|
||||
mOutput.pop_back();
|
||||
}
|
||||
// Push the output string on the stack
|
||||
sq_pushstring(vm, mOutput.c_str(), static_cast< SQInteger >(mOutput.size()));
|
||||
// Specify that we have a value on the stack
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQRESULT CtxJSON::SerializeAt(HSQUIRRELVM vm, SQInteger idx) // NOLINT(misc-no-recursion)
|
||||
{
|
||||
// Identify object type
|
||||
switch (sq_gettype(vm, idx))
|
||||
{
|
||||
case OT_NULL: {
|
||||
PushNull();
|
||||
} break;
|
||||
case OT_INTEGER: {
|
||||
SQInteger v;
|
||||
// Attempt to retrieve the value from the stack
|
||||
if (SQRESULT r = sq_getinteger(vm, idx, &v); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
// Write the value in the output
|
||||
PushInteger(v);
|
||||
} break;
|
||||
case OT_FLOAT: {
|
||||
SQFloat v;
|
||||
// Attempt to retrieve the value from the stack
|
||||
if (SQRESULT r = sq_getfloat(vm, idx, &v); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
// Write the value in the output
|
||||
#ifdef SQUSEDOUBLE
|
||||
PushDouble(v);
|
||||
#else
|
||||
PushFloat(v);
|
||||
#endif
|
||||
} break;
|
||||
case OT_BOOL: {
|
||||
SQBool v;
|
||||
// Attempt to retrieve the value from the stack
|
||||
if (SQRESULT r = sq_getbool(vm, idx, &v); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
// Write the value in the output
|
||||
PushBool(v != SQFalse);
|
||||
} break;
|
||||
case OT_STRING: {
|
||||
const SQChar * v = nullptr;
|
||||
SQInteger n = 0;
|
||||
// Attempt to retrieve and convert the string
|
||||
if (SQRESULT r = sq_getstringandsize(vm, idx, &v, &n); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
// Write the value in the output
|
||||
PushString(v, static_cast< size_t >(n));
|
||||
} break;
|
||||
case OT_TABLE: {
|
||||
if (SQRESULT r = SerializeTable(vm, idx); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
} break;
|
||||
case OT_ARRAY: {
|
||||
if (SQRESULT r = SerializeArray(vm, idx); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
} break;
|
||||
case OT_INSTANCE: {
|
||||
if (SQRESULT r = SerializeInstance(vm, idx); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
} break;
|
||||
case OT_WEAKREF: {
|
||||
if (SQRESULT r = SerializeWeakRef(vm, idx); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
} break;
|
||||
case OT_USERDATA:
|
||||
case OT_CLOSURE:
|
||||
case OT_NATIVECLOSURE:
|
||||
case OT_GENERATOR:
|
||||
case OT_USERPOINTER:
|
||||
case OT_THREAD:
|
||||
case OT_FUNCPROTO:
|
||||
case OT_CLASS:
|
||||
case OT_OUTER:
|
||||
return sq_throwerrorf(vm, _SC("Type (%s) is not serializable"), SqTypeName(sq_gettype(vm, 2)));
|
||||
}
|
||||
// Serialization was successful
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQRESULT CtxJSON::SerializeArray(HSQUIRRELVM vm, SQInteger idx) // NOLINT(misc-no-recursion)
|
||||
{
|
||||
// Begin array scope
|
||||
OpenArray();
|
||||
// Push null to initiate iteration
|
||||
sq_pushnull(vm);
|
||||
// So we can use absolute stack indexes to avoid errors
|
||||
const auto top = sq_gettop(vm);
|
||||
// Start iterating the array at the specified position in the stack
|
||||
for(SQRESULT r = SQ_OK; SQ_SUCCEEDED(sq_next(vm, idx));)
|
||||
{
|
||||
// Attempt serialization of the currently iterated value
|
||||
r = SerializeAt(vm, top + 2);
|
||||
// Check for failures
|
||||
if (SQ_FAILED(r))
|
||||
{
|
||||
// Pop the null iterator, key and value from the stack
|
||||
sq_pop(vm, 3);
|
||||
// Propagate the error
|
||||
return r;
|
||||
}
|
||||
// Pop the key and value from the stack (i.e. cleanup after `sq_next`)
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
// Pop the null iterator
|
||||
sq_poptop(vm);
|
||||
// Close array scope
|
||||
CloseArray();
|
||||
// Serialization was successful
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQRESULT CtxJSON::SerializeTable(HSQUIRRELVM vm, SQInteger idx) // NOLINT(misc-no-recursion)
|
||||
{
|
||||
// Begin object scope
|
||||
OpenObject();
|
||||
// Push null to initiate iteration
|
||||
sq_pushnull(vm);
|
||||
// So we can use absolute stack indexes to avoid errors
|
||||
const auto top = sq_gettop(vm);
|
||||
// Start iterating the object at the specified position in the stack
|
||||
for(SQRESULT r = SQ_OK; SQ_SUCCEEDED(sq_next(vm, idx));)
|
||||
{
|
||||
if (sq_gettype(vm, -2) == OT_STRING)
|
||||
{
|
||||
// Attempt serialization of the currently iterated element key
|
||||
r = SerializeAt(vm, top + 1);
|
||||
// Can we proceed with the value?
|
||||
if (SQ_SUCCEEDED(r))
|
||||
{
|
||||
// Mark the value above as the key of this element and
|
||||
// attempt serialization of the currently iterated element value
|
||||
r = MakeKey().SerializeAt(vm, top + 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r = sq_throwerror(vm, _SC("Only string values are accepted as object keys"));
|
||||
}
|
||||
// Check for failures
|
||||
if (SQ_FAILED(r))
|
||||
{
|
||||
// Pop the null iterator, key and value from the stack
|
||||
sq_pop(vm, 3);
|
||||
// Propagate the error
|
||||
return r;
|
||||
}
|
||||
// Pop the key and value from the stack (i.e. cleanup after `sq_next`)
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
// Pop the null iterator
|
||||
sq_poptop(vm);
|
||||
// Close object scope
|
||||
CloseObject();
|
||||
// Serialization was successful
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQRESULT CtxJSON::SerializeInstance(HSQUIRRELVM vm, SQInteger idx)
|
||||
{
|
||||
sq_pushstring(vm, mMetaMethod.c_str(), static_cast< SQInteger >(mMetaMethod.size()));
|
||||
// Attempt to retrieve the meta-method from the instance
|
||||
if(SQRESULT r = sq_get(vm, idx); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
// Make sure this is actually a closure/function that we can invoke
|
||||
else if (const auto t = sq_gettype(vm, -1); t != OT_CLOSURE && t != OT_NATIVECLOSURE)
|
||||
{
|
||||
// Remove whatever is on the stack
|
||||
sq_poptop(vm);
|
||||
// Abort the operation as we can't do anything about it
|
||||
return sq_throwerrorf(vm, _SC("`_tojson` meta-method is not a closure for type (%s)"), SqTypeName(vm, idx).c_str());
|
||||
}
|
||||
// Push the instance itself the stack (the environment)
|
||||
sq_push(vm, idx);
|
||||
// Push this instance on the stack (the json context)
|
||||
ClassType< CtxJSON >::PushInstance(vm, this);
|
||||
// Invoke the function to perform the conversion in this context
|
||||
SQRESULT r = sq_call(vm, 2, SQFalse, SQFalse);
|
||||
// Remove the closure from the stack
|
||||
sq_poptop(vm);
|
||||
// Propagate the result, whatever that is
|
||||
return r;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQRESULT CtxJSON::SerializeWeakRef(HSQUIRRELVM vm, SQInteger idx) // NOLINT(misc-no-recursion)
|
||||
{
|
||||
SQRESULT r = sq_getweakrefval(vm, idx);
|
||||
// Attempt to grab the value pointed by the weak reference
|
||||
if (SQ_SUCCEEDED(r))
|
||||
{
|
||||
// Attempt to serialize the actual value
|
||||
r = SerializeAt(vm, sq_gettop(vm));
|
||||
// Pop the referenced value
|
||||
sq_poptop(vm);
|
||||
}
|
||||
// Propagate the error, if any
|
||||
return r;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQRESULT CtxJSON::PushValues(HSQUIRRELVM vm)
|
||||
{
|
||||
// Fetch the number of objects on the stack
|
||||
const auto top = sq_gettop(vm);
|
||||
// Do we have a value?
|
||||
if (top < 2)
|
||||
{
|
||||
return sq_throwerror(vm, _SC("Must specify at least one value to be pushed"));
|
||||
}
|
||||
// Serialize every specified argument
|
||||
for (SQInteger i = 2; i <= top; ++i)
|
||||
{
|
||||
if (SQRESULT r = SerializeAt(vm, i); SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
}
|
||||
// Allow chaining
|
||||
sq_push(vm, 1);
|
||||
// Specify that a value was returned
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQRESULT CtxJSON::PushElement(HSQUIRRELVM vm)
|
||||
{
|
||||
// Fetch the number of objects on the stack
|
||||
const auto top = sq_gettop(vm);
|
||||
// Do we have a value?
|
||||
if (top < 3)
|
||||
{
|
||||
return sq_throwerrorf(vm, _SC("Not enough parameters. Received %lld but %lld needed"), top-1, 2);
|
||||
}
|
||||
else if (sq_gettype(vm, 2) != OT_STRING)
|
||||
{
|
||||
return sq_throwerrorf(vm, _SC("Element key must be a string"));
|
||||
}
|
||||
// Attempt serialization of the currently iterated element key
|
||||
if (SQRESULT r = SerializeAt(vm, 2); SQ_SUCCEEDED(r))
|
||||
{
|
||||
// Mark the value above as the key of this element and
|
||||
// attempt serialization of the currently iterated element value
|
||||
r = MakeKey().SerializeAt(vm, 3);
|
||||
// Check for failures
|
||||
if (SQ_FAILED(r))
|
||||
{
|
||||
return r; // Propagate the error
|
||||
}
|
||||
}
|
||||
// Allow chaining
|
||||
sq_push(vm, 1);
|
||||
// Specify that a value was returned
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CtxJSON & CtxJSON::PushKey(StackStrF & key)
|
||||
{
|
||||
// Validate the string value
|
||||
if (key.mLen >= 0 && SQ_SUCCEEDED(key.mRes))
|
||||
{
|
||||
PushString(key.mPtr, static_cast< size_t >(key.mLen));
|
||||
MakeKey();
|
||||
}
|
||||
else
|
||||
{
|
||||
STHROWF("Invalid object key");
|
||||
}
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CtxJSON::PushNull()
|
||||
{
|
||||
mOutput.append("null,");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CtxJSON::PushInteger(SQInteger value)
|
||||
{
|
||||
fmt::format_int f(value);
|
||||
// Append the formatted integer to the buffer
|
||||
mOutput.append(f.data(), f.size());
|
||||
mOutput.push_back(',');
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CtxJSON::PushFloat(float value)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(mOutput), "{},", value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CtxJSON::PushDouble(double value)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(mOutput), "{},", value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CtxJSON::PushBool(bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
mOutput.append("true,", 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
mOutput.append("false,", 6);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CtxJSON::PushString(const SQChar * str)
|
||||
{
|
||||
mOutput.push_back('"');
|
||||
mOutput.append(str);
|
||||
mOutput.push_back('"');
|
||||
mOutput.push_back(',');
|
||||
// Allow the hook to know
|
||||
mString.assign(str);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CtxJSON::PushString(const SQChar * str, size_t length)
|
||||
{
|
||||
mOutput.push_back('"');
|
||||
mOutput.append(str, length);
|
||||
mOutput.push_back('"');
|
||||
mOutput.push_back(',');
|
||||
// Allow the hook to know
|
||||
mString.assign(str, length);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqToJSON(HSQUIRRELVM vm) noexcept
|
||||
{
|
||||
// Make sure the instance is cleaned up even in the case of exceptions
|
||||
DeleteGuard< CtxJSON > sq_dg(new CtxJSON());
|
||||
// Remember the instance, so we don't have to cast the script object back
|
||||
auto ctx = sq_dg.Get();
|
||||
// Turn it into a script object because it may be passed as a parameter to `_tojson` meta-methods
|
||||
LightObj obj(sq_dg, vm);
|
||||
// Proceed with the serialization
|
||||
return ctx->SerializeParams(vm);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqToCompactJSON(HSQUIRRELVM vm) noexcept
|
||||
{
|
||||
// Make sure the instance is cleaned up even in the case of exceptions
|
||||
DeleteGuard< CtxJSON > sq_dg(new CtxJSON(false));
|
||||
// Remember the instance, so we don't have to cast the script object back
|
||||
auto ctx = sq_dg.Get();
|
||||
// Turn it into a script object because it may be passed as a parameter to `_tojson` meta-methods
|
||||
LightObj obj(sq_dg, vm);
|
||||
// Proceed with the serialization
|
||||
return ctx->SerializeParams(vm);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_JSON(HSQUIRRELVM vm)
|
||||
{
|
||||
RootTable(vm).SquirrelFunc(_SC("SqToJSON"), SqToJSON);
|
||||
RootTable(vm).SquirrelFunc(_SC("SqToCompactJSON"), SqToCompactJSON);
|
||||
RootTable(vm).SquirrelFunc(_SC("SqFromJSON"), SqFromJSON);
|
||||
// --------------------------------------------------------------------------------------------
|
||||
RootTable(vm).Bind(_SC("SqCtxJSON"),
|
||||
Class< CtxJSON, NoCopy< CtxJSON > >(vm, SqCtxJSON::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< bool >()
|
||||
.Ctor< bool, StackStrF & >()
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_typename"), &SqCtxJSON::Fn)
|
||||
// Properties
|
||||
.Prop(_SC("Output"), &CtxJSON::GetOutput)
|
||||
.Prop(_SC("Depth"), &CtxJSON::GetDepth)
|
||||
.Prop(_SC("OOA"), &CtxJSON::GetObjectOverArray, &CtxJSON::SetObjectOverArray)
|
||||
.Prop(_SC("ObjectOverArray"), &CtxJSON::GetObjectOverArray, &CtxJSON::SetObjectOverArray)
|
||||
// Member Methods
|
||||
.SquirrelMethod< CtxJSON, &CtxJSON::SerializeParams >(_SC("Serialize"))
|
||||
.SquirrelMethod< CtxJSON, &CtxJSON::PushValues >(_SC("PushValues"))
|
||||
.SquirrelMethod< CtxJSON, &CtxJSON::PushElement >(_SC("PushElement"))
|
||||
.Func(_SC("OpenArray"), &CtxJSON::OpenArray)
|
||||
.Func(_SC("CloseArray"), &CtxJSON::CloseArray)
|
||||
.Func(_SC("OpenObject"), &CtxJSON::OpenObject)
|
||||
.Func(_SC("CloseObject"), &CtxJSON::CloseObject)
|
||||
.Func(_SC("MakeKey"), &CtxJSON::MakeKey)
|
||||
.FmtFunc(_SC("PushKey"), &CtxJSON::PushKey)
|
||||
.Func(_SC("SetOOA"), &CtxJSON::SetObjectOverArray)
|
||||
.Func(_SC("SetObjectOverArray"), &CtxJSON::SetObjectOverArray)
|
||||
);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
+271
-2
@@ -5,12 +5,281 @@
|
||||
#include "Library/IO/Buffer.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sajson.h>
|
||||
#include <functional>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <fmt/args.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/xchar.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* JSON serializer. The generated JSON output is always minified for efficiency reasons.
|
||||
*/
|
||||
struct CtxJSON
|
||||
{
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Output string.
|
||||
*/
|
||||
String mOutput{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Prefer a table with named members even when a simple array would do the job.
|
||||
* Take a Vector3 for example. Compact array [x, y, z] or named object {x: #.#, y: #.#, z: #.#}
|
||||
*/
|
||||
bool mObjectOverArray{true};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* How nested are we currently.
|
||||
*/
|
||||
uint32_t mDepth{0};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* The meta-method name to use on objects.
|
||||
*/
|
||||
String mMetaMethod{"_tojson"};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Last pushed string value. Can be used to heck for key name in the hook.
|
||||
*/
|
||||
String mString{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Internal utility used to monitor the existence of certain keys to allow overloading.
|
||||
*/
|
||||
std::function< void(CtxJSON&) > mKeyHook{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
CtxJSON() = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
explicit CtxJSON(bool ooa)
|
||||
: CtxJSON()
|
||||
{
|
||||
mObjectOverArray = ooa;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
CtxJSON(bool ooa, StackStrF & mmname)
|
||||
: CtxJSON()
|
||||
{
|
||||
mObjectOverArray = ooa;
|
||||
// Allow custom metamethod names
|
||||
mMetaMethod.assign(mmname.mPtr, static_cast< size_t >(mmname.mLen));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Internal constructor.
|
||||
*/
|
||||
explicit CtxJSON(std::function< void(CtxJSON&) > && kh)
|
||||
: CtxJSON()
|
||||
{
|
||||
mKeyHook = std::move(kh);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
CtxJSON(const CtxJSON &) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
CtxJSON(CtxJSON &&) noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~CtxJSON() = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
CtxJSON & operator = (const CtxJSON &) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
CtxJSON & operator = (CtxJSON &&) noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the current depth.
|
||||
*/
|
||||
SQMOD_NODISCARD const String & GetOutput() const noexcept
|
||||
{
|
||||
return mOutput;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the current depth.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger GetDepth() const noexcept
|
||||
{
|
||||
return mDepth;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve whether objects are preferred over arrays.
|
||||
*/
|
||||
SQMOD_NODISCARD bool GetObjectOverArray() const noexcept
|
||||
{
|
||||
return mObjectOverArray;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve whether objects are preferred over arrays.
|
||||
*/
|
||||
CtxJSON & SetObjectOverArray(bool toggle) noexcept
|
||||
{
|
||||
mObjectOverArray = toggle;
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Increase indentation by one level.
|
||||
*/
|
||||
void Advance() noexcept
|
||||
{
|
||||
++mDepth;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Decrease indentation by one level.
|
||||
*/
|
||||
void Retreat() noexcept
|
||||
{
|
||||
assert(mDepth > 0);
|
||||
if (mDepth) --mDepth;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Begin writing an array.
|
||||
*/
|
||||
CtxJSON & OpenArray();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Stop writing an array.
|
||||
*/
|
||||
CtxJSON & CloseArray();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Resume writing an array.
|
||||
*/
|
||||
CtxJSON & ReopenArray();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Begin writing an object.
|
||||
*/
|
||||
CtxJSON & OpenObject();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Stop writing an object.
|
||||
*/
|
||||
CtxJSON & CloseObject();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Resume writing an object.
|
||||
*/
|
||||
CtxJSON & ReopenObject();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Begin writing a key value.
|
||||
*/
|
||||
CtxJSON & MakeKey();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Check whether the specified weak-ref points to a type of value that must be wrapped.
|
||||
*/
|
||||
SQMOD_NODISCARD static bool CheckWeakRefWrap(HSQUIRRELVM vm, SQInteger idx) noexcept;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Serialize given arguments.
|
||||
*/
|
||||
SQRESULT SerializeParams(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Serialize the value a specific position in the stack.
|
||||
*/
|
||||
SQRESULT SerializeAt(HSQUIRRELVM vm, SQInteger idx);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Serialize the array a specific position in the stack. Stack index must be absolute!
|
||||
*/
|
||||
SQRESULT SerializeArray(HSQUIRRELVM vm, SQInteger idx);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Serialize the table a specific position in the stack. Stack index must be absolute!
|
||||
*/
|
||||
SQRESULT SerializeTable(HSQUIRRELVM vm, SQInteger idx);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Serialize the instance a specific position in the stack. Stack index must be absolute!
|
||||
*/
|
||||
SQRESULT SerializeInstance(HSQUIRRELVM vm, SQInteger idx);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Serialize the weak-ref a specific position in the stack. Stack index must be absolute!
|
||||
*/
|
||||
SQRESULT SerializeWeakRef(HSQUIRRELVM vm, SQInteger idx);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Serialize a value to the current container. It assumes an array or object is currently open.
|
||||
*/
|
||||
SQRESULT PushValues(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Serialize a key/value pair to the current object. It assumes an object is currently open.
|
||||
*/
|
||||
SQRESULT PushElement(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Push a key in the output. It assumes an object was open and previous element closed properly.
|
||||
*/
|
||||
CtxJSON & PushKey(StackStrF & key);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a null value to the output.
|
||||
*/
|
||||
void PushNull();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write an integer value to the output.
|
||||
*/
|
||||
void PushInteger(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a single precision floating point value to the output.
|
||||
*/
|
||||
void PushFloat(float value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a double precision floating point value to the output.
|
||||
*/
|
||||
void PushDouble(double value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a boolean value to the output.
|
||||
*/
|
||||
void PushBool(bool value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a string value to the output.
|
||||
*/
|
||||
void PushString(const SQChar * str);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a string value to the output.
|
||||
*/
|
||||
void PushString(const SQChar * str, size_t length);
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
+19
-19
@@ -36,7 +36,7 @@ static SQChar * Bin128ToDec(const uint32_t N[4])
|
||||
// Add s[] to itself in decimal, doubling it
|
||||
for (j = sizeof(s) - 2; j >= 0; j--)
|
||||
{
|
||||
s[j] += s[j] - '0' + carry;
|
||||
s[j] += s[j] - '0' + carry; // NOLINT(cppcoreguidelines-narrowing-conversions)
|
||||
|
||||
carry = (s[j] > '9');
|
||||
|
||||
@@ -265,7 +265,7 @@ SQFloat GetEntryAsFloat(const MMDB_entry_data_s & ed)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj GetEntryAsLong(const MMDB_entry_data_s & ed)
|
||||
SQInteger GetEntryAsLong(const MMDB_entry_data_s & ed)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
// Identify the type of entry data
|
||||
@@ -315,7 +315,7 @@ LightObj GetEntryAsLong(const MMDB_entry_data_s & ed)
|
||||
STHROWF("Unsupported conversion from ({}) to (long)", AsTypeStr(ed.type));
|
||||
}
|
||||
// Return a long integer instance with the requested value
|
||||
return LightObj(SqTypeIdentity< ULongInt >{}, SqVM(), value);
|
||||
return static_cast< SQInteger >(value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -338,7 +338,7 @@ LightObj GetEntryAsString(const MMDB_entry_data_s & ed)
|
||||
sq_pushstring(vm, fmt::format("{}", ed.double_value).c_str(), -1);
|
||||
} break;
|
||||
case MMDB_DATA_TYPE_BYTES: {
|
||||
sq_pushstring(vm, reinterpret_cast< const SQChar * >(ed.bytes), ed.data_size / sizeof(SQChar));
|
||||
sq_pushstring(vm, reinterpret_cast< const SQChar * >(ed.bytes), static_cast< SQInteger >(ed.data_size) / sizeof(SQChar));
|
||||
} break;
|
||||
case MMDB_DATA_TYPE_UINT16: {
|
||||
sq_pushstring(vm, fmt::format("{}", ed.uint16).c_str(), -1);
|
||||
@@ -444,7 +444,7 @@ void SockAddr::Validate(const SQChar * file, int32_t line) const
|
||||
{
|
||||
if (!m_Handle)
|
||||
{
|
||||
SqThrowF("Invalid sockaddr structure handle =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid sockaddr structure handle =>[{}:{}]"), file, line);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -551,7 +551,7 @@ void Database::Validate(const SQChar * file, int32_t line) const
|
||||
{
|
||||
if (!m_Handle)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind database reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind database reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -687,7 +687,7 @@ void Description::Validate(const SQChar * file, int32_t line) const
|
||||
{
|
||||
if (!m_Handle)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind database reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind database reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -708,7 +708,7 @@ Description::Pointer Description::GetValid(const SQChar * file, int32_t line) co
|
||||
// Validate the referenced description
|
||||
if (!m_Description)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind meta-data description reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind meta-data description reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
// Return the description pointer
|
||||
return m_Description;
|
||||
@@ -747,7 +747,7 @@ void EntryData::Validate(const SQChar * file, int32_t line) const
|
||||
{
|
||||
if (!m_Handle)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind database reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind database reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -768,7 +768,7 @@ EntryData::ConstRef EntryData::GetValid(const SQChar * file, int32_t line) const
|
||||
// See if the entry has any data
|
||||
if (!m_Entry.has_data)
|
||||
{
|
||||
SqThrowF("The referenced entry has no data =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("The referenced entry has no data =>[{}:{}]"), file, line);
|
||||
}
|
||||
// Return the entry
|
||||
return m_Entry;
|
||||
@@ -821,7 +821,7 @@ void EntryDataList::Validate(const SQChar * file, int32_t line) const
|
||||
{
|
||||
if (!m_Handle)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind database reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind database reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -842,7 +842,7 @@ EntryDataList::Pointer EntryDataList::GetValid(const SQChar * file, int32_t line
|
||||
// Validate the managed list
|
||||
if (!m_List)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind entry data list reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind entry data list reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
// return the list
|
||||
return m_List;
|
||||
@@ -869,7 +869,7 @@ EntryDataList::Pointer EntryDataList::GetValidElem(const SQChar * file, int32_t
|
||||
// Validate the current element
|
||||
if (!m_List)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind entry data element reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind entry data element reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
// return the element
|
||||
return m_Elem;
|
||||
@@ -979,7 +979,7 @@ void LookupResult::Validate(const SQChar * file, int32_t line) const
|
||||
{
|
||||
if (!m_Handle)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind database reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind database reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -1051,7 +1051,7 @@ Object LookupResult::GetEntryDataList()
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger LookupResult::GetValue(HSQUIRRELVM vm)
|
||||
{
|
||||
const int32_t top = sq_gettop(vm);
|
||||
const auto top = sq_gettop(vm);
|
||||
// The lookup result instance
|
||||
LookupResult * lookup;
|
||||
// Attempt to extract the lookup result instance
|
||||
@@ -1139,7 +1139,7 @@ void Metadata::Validate(const SQChar * file, int32_t line) const
|
||||
{
|
||||
if (!m_Handle)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind database reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind database reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -1160,7 +1160,7 @@ Metadata::Pointer Metadata::GetValid(const SQChar * file, int32_t line) const
|
||||
// Validate the referenced meta-data
|
||||
if (!m_Metadata)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind meta-data reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind meta-data reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
// Return the meta-data pointer
|
||||
return m_Metadata;
|
||||
@@ -1211,7 +1211,7 @@ void SearchNode::Validate(const SQChar * file, int32_t line) const
|
||||
{
|
||||
if (!m_Handle)
|
||||
{
|
||||
SqThrowF("Invalid Maxmind database reference =>[{}:{}]", file, line);
|
||||
SqThrowF(SQMOD_RTFMT("Invalid Maxmind database reference =>[{}:{}]"), file, line);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -1294,7 +1294,7 @@ Object SearchNode::GetRightRecordEntryDataList()
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger SearchNode::GetRecordEntryData(HSQUIRRELVM vm, bool right)
|
||||
{
|
||||
const int32_t top = sq_gettop(vm);
|
||||
const auto top = sq_gettop(vm);
|
||||
// The search node result instance
|
||||
SearchNode * node;
|
||||
// Attempt to extract the search node result instance
|
||||
|
||||
+9
-10
@@ -5,7 +5,6 @@
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/IO/Buffer.hpp"
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <vector>
|
||||
@@ -76,7 +75,7 @@ SQFloat GetEntryAsFloat(const MMDB_entry_data_s & ed);
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the value from the specified entry data as a long integer.
|
||||
*/
|
||||
LightObj GetEntryAsLong(const MMDB_entry_data_s & ed);
|
||||
SQInteger GetEntryAsLong(const MMDB_entry_data_s & ed);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the value from the specified entry data as a string.
|
||||
@@ -811,7 +810,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value from the current element as a long integer.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj GetLong() const
|
||||
SQMOD_NODISCARD SQInteger GetLong() const
|
||||
{
|
||||
return GetEntryAsLong(SQMOD_GET_VALID(*this));
|
||||
}
|
||||
@@ -1105,7 +1104,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value from the current element as a long integer.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj GetLong() const
|
||||
SQMOD_NODISCARD SQInteger GetLong() const
|
||||
{
|
||||
return GetEntryAsLong(SQMOD_GET_VALID_ELEM(*this)->entry_data);
|
||||
}
|
||||
@@ -1492,9 +1491,9 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the build epoch.
|
||||
*/
|
||||
SQMOD_NODISCARD Object GetBuildEpoch() const
|
||||
SQMOD_NODISCARD SQInteger GetBuildEpoch() const
|
||||
{
|
||||
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), ConvTo< uint64_t >::From(SQMOD_GET_VALID(*this)->build_epoch));
|
||||
return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this)->build_epoch);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1662,17 +1661,17 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the left record value.
|
||||
*/
|
||||
Object GetLeftRecord()
|
||||
SQInteger GetLeftRecord()
|
||||
{
|
||||
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), ConvTo< uint64_t >::From(SQMOD_GET_VALID(*this).left_record));
|
||||
return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this).left_record);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the right record value.
|
||||
*/
|
||||
Object GetRightRecord()
|
||||
SQInteger GetRightRecord()
|
||||
{
|
||||
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), ConvTo< uint64_t >::From(SQMOD_GET_VALID(*this).right_record));
|
||||
return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this).right_record);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
|
||||
+455
-425
File diff suppressed because it is too large
Load Diff
+255
-198
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,217 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/Net.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqratConst.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_DECL_TYPENAME(SqWebSocketClient, _SC("SqWebSocketClient"))
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static std::thread::id sMainThreadID{}; // Main thread ID
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void InitializeNet()
|
||||
{
|
||||
int f = MG_FEATURES_DEFAULT;
|
||||
#ifndef NO_FILES
|
||||
f |= MG_FEATURES_FILES;
|
||||
#endif
|
||||
#ifndef NO_SSL
|
||||
f |= MG_FEATURES_SSL;
|
||||
#else
|
||||
OutputMessage("Network compiled without SSL support.");
|
||||
#endif
|
||||
#ifndef NO_CGI
|
||||
f |= MG_FEATURES_CGI;
|
||||
#endif
|
||||
#ifndef NO_CACHING
|
||||
f |= MG_FEATURES_CACHE;
|
||||
#endif
|
||||
#ifdef USE_IPV6
|
||||
f |= MG_FEATURES_CGI;
|
||||
#endif
|
||||
#ifdef USE_WEBSOCKET
|
||||
f |= MG_FEATURES_WEBSOCKET;
|
||||
#endif
|
||||
#ifdef USE_SERVER_STATS
|
||||
f |= MG_FEATURES_STATS;
|
||||
#endif
|
||||
#ifdef USE_ZLIB
|
||||
f |= MG_FEATURES_COMPRESSION;
|
||||
#endif
|
||||
#ifdef USE_HTTP2
|
||||
f |= MG_FEATURES_HTTP2;
|
||||
#endif
|
||||
#ifdef USE_X_DOM_SOCKET
|
||||
f |= MG_FEATURES_X_DOMAIN_SOCKET;
|
||||
#endif
|
||||
mg_init_library(f);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TerminateNet()
|
||||
{
|
||||
// Go over all connections and try to terminate them
|
||||
for (WebSocketClient * inst = WebSocketClient::sHead; inst && inst->mNext != WebSocketClient::sHead; inst = inst->mNext)
|
||||
{
|
||||
inst->Terminate(); // Terminate() the connection
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ProcessNet()
|
||||
{
|
||||
// Go over all connections and allow them to process data
|
||||
for (WebSocketClient * inst = WebSocketClient::sHead; inst && inst->mNext != WebSocketClient::sHead; inst = inst->mNext)
|
||||
{
|
||||
inst->Process();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
WebSocketClient & WebSocketClient::Connect()
|
||||
{
|
||||
// Make sure another connection does not exist
|
||||
Invalid();
|
||||
// Error buffer
|
||||
char err_buf[128] = {0};
|
||||
// Connect to the given WS or WSS (WS secure) server
|
||||
mHandle = mg_connect_websocket_client(mHost.c_str(), mPort, mSecure?1:0,
|
||||
err_buf, sizeof(err_buf), mPath.c_str(),
|
||||
mOrigin.empty() ? nullptr : mOrigin.c_str(),
|
||||
&WebSocketClient::DataHandler_,
|
||||
&WebSocketClient::CloseHandler_,
|
||||
this);
|
||||
// Check if connection was possible
|
||||
if (!mHandle)
|
||||
{
|
||||
STHROWF("Connection failed: {}", err_buf);
|
||||
}
|
||||
// Reset memebrs
|
||||
mClosing.store(false);
|
||||
mClosed.store(false);
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
WebSocketClient & WebSocketClient::ConnectExt()
|
||||
{
|
||||
// Make sure another connection does not exist
|
||||
Invalid();
|
||||
// Error buffer
|
||||
char err_buf[128] = {0};
|
||||
// Connect to the given WS or WSS (WS secure) server
|
||||
mHandle = mg_connect_websocket_client_extensions(mHost.c_str(), mPort, mSecure?1:0,
|
||||
err_buf, sizeof(err_buf), mPath.c_str(),
|
||||
mOrigin.empty() ? nullptr : mOrigin.c_str(),
|
||||
mExtensions.empty() ? nullptr : mExtensions.c_str(),
|
||||
&WebSocketClient::DataHandler_,
|
||||
&WebSocketClient::CloseHandler_,
|
||||
this);
|
||||
// Check if connection was possible
|
||||
if (!mHandle)
|
||||
{
|
||||
STHROWF("Connection failed: {}", err_buf);
|
||||
}
|
||||
// Reset memebrs
|
||||
mClosing.store(false);
|
||||
mClosed.store(false);
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int WebSocketClient::DataHandler(int flags, char * data, size_t data_len) noexcept
|
||||
{
|
||||
// Create a frame instance to store information and queue it
|
||||
try
|
||||
{
|
||||
mQueue.enqueue(std::make_unique< Frame >(data, data_len, flags));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
LogFtl("Failed to queue web-socket data");
|
||||
}
|
||||
// Should we auto-close the connection
|
||||
if (((flags & 0xF) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE) && mAutoClose.load() == true)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Return 1 to keep the connection open
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void WebSocketClient::CloseHandler() noexcept
|
||||
{
|
||||
mClosing.store(true);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_Net(HSQUIRRELVM vm)
|
||||
{
|
||||
Table ns(vm);
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ns.Bind(_SC("WebSocketClient"),
|
||||
Class< WebSocketClient, NoCopy< WebSocketClient > >(ns.GetVM(), SqWebSocketClient::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< StackStrF &, uint16_t, StackStrF & >()
|
||||
.Ctor< StackStrF &, uint16_t, StackStrF &, bool >()
|
||||
.Ctor< StackStrF &, uint16_t, StackStrF &, bool, StackStrF & >()
|
||||
.Ctor< StackStrF &, uint16_t, StackStrF &, bool, StackStrF &, StackStrF & >()
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_typename"), &SqWebSocketClient::Fn)
|
||||
// Properties
|
||||
.Prop(_SC("Tag"), &WebSocketClient::GetTag, &WebSocketClient::SetTag)
|
||||
.Prop(_SC("Data"), &WebSocketClient::GetData, &WebSocketClient::SetData)
|
||||
.Prop(_SC("Host"), &WebSocketClient::GetHost, &WebSocketClient::SetHost)
|
||||
.Prop(_SC("Port"), &WebSocketClient::GetPort, &WebSocketClient::SetPort)
|
||||
.Prop(_SC("Path"), &WebSocketClient::GetPath, &WebSocketClient::SetPath)
|
||||
.Prop(_SC("Secure"), &WebSocketClient::GetSecure, &WebSocketClient::SetSecure)
|
||||
.Prop(_SC("Origin"), &WebSocketClient::GetOrigin, &WebSocketClient::SetOrigin)
|
||||
.Prop(_SC("Extensions"), &WebSocketClient::GetExtensions, &WebSocketClient::SetExtensions)
|
||||
.Prop(_SC("OnData"), &WebSocketClient::GetOnData, &WebSocketClient::SetOnData)
|
||||
.Prop(_SC("OnClose"), &WebSocketClient::GetOnClose, &WebSocketClient::SetOnClose)
|
||||
.Prop(_SC("Valid"), &WebSocketClient::IsValid)
|
||||
.Prop(_SC("Closing"), &WebSocketClient::IsClosing)
|
||||
.Prop(_SC("AutoClose"), &WebSocketClient::GetAutoClose, &WebSocketClient::SetAutoClose)
|
||||
// Member Methods
|
||||
.FmtFunc(_SC("SetTag"), &WebSocketClient::ApplyTag)
|
||||
.FmtFunc(_SC("SetData"), &WebSocketClient::ApplyData)
|
||||
.FmtFunc(_SC("SetHost"), &WebSocketClient::ApplyHost)
|
||||
.Func(_SC("SetPort"), &WebSocketClient::ApplyPort)
|
||||
.FmtFunc(_SC("SetPath"), &WebSocketClient::ApplyPath)
|
||||
.Func(_SC("SetSecure"), &WebSocketClient::ApplySecure)
|
||||
.FmtFunc(_SC("SetOrigin"), &WebSocketClient::ApplyOrigin)
|
||||
.FmtFunc(_SC("SetExtensions"), &WebSocketClient::ApplyExtensions)
|
||||
.CbFunc(_SC("BindOnData"), &WebSocketClient::BindOnData)
|
||||
.CbFunc(_SC("BindOnClose"), &WebSocketClient::BindOnClose)
|
||||
.Func(_SC("Connect"), &WebSocketClient::Connect)
|
||||
.Func(_SC("ConnectExt"), &WebSocketClient::ConnectExt)
|
||||
.Func(_SC("SendOpCode"), &WebSocketClient::SendOpCode)
|
||||
.Func(_SC("SendBuffer"), &WebSocketClient::SendBuffer)
|
||||
.FmtFunc(_SC("SendString"), &WebSocketClient::SendString)
|
||||
.Func(_SC("Close"), &WebSocketClient::Close)
|
||||
);
|
||||
// --------------------------------------------------------------------------------------------
|
||||
RootTable(vm).Bind(_SC("SqNet"), ns);
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ConstTable(vm).Enum(_SC("SqWsOpCode"), Enumeration(vm)
|
||||
.Const(_SC("Continuation"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_CONTINUATION))
|
||||
.Const(_SC("Text"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_TEXT))
|
||||
.Const(_SC("Binary"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_BINARY))
|
||||
.Const(_SC("ConnectionClose"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE))
|
||||
.Const(_SC("Ping"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_PING))
|
||||
.Const(_SC("Pong"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_PONG))
|
||||
);
|
||||
// Main thread ID
|
||||
sMainThreadID = std::this_thread::get_id();
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
@@ -0,0 +1,791 @@
|
||||
#pragma once
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/IO/Buffer.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <atomic>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqratFunction.h>
|
||||
#include <concurrentqueue.h>
|
||||
#include <civetweb.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* WebSocket client implementation.
|
||||
*/
|
||||
struct WebSocketClient : public SqChainedInstances< WebSocketClient >
|
||||
{
|
||||
using Base = SqChainedInstances< WebSocketClient >;
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* WebSocket frame.
|
||||
*/
|
||||
struct Frame
|
||||
{
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Frame data.
|
||||
*/
|
||||
char * mData{nullptr};
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Frame data capacity.
|
||||
*/
|
||||
uint32_t mSize{0};
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Frame flags.
|
||||
*/
|
||||
int mFlags{0};
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
Frame() = default;
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
Frame(char * data, size_t size, int flags)
|
||||
: mData(nullptr), mSize(static_cast< uint32_t >(size)), mFlags(flags)
|
||||
{
|
||||
// Do we need to allocate a buffer?
|
||||
if (mSize != 0)
|
||||
{
|
||||
// Allocate the memory buffer.
|
||||
mData = new char[mSize];
|
||||
// Copy the data into the buffer we own
|
||||
std::memcpy(mData, data, mSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Copy constructor (disabled).
|
||||
*/
|
||||
Frame(const Frame & o) = delete;
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Move constructor (disabled).
|
||||
*/
|
||||
Frame(Frame && o) noexcept = delete;
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~Frame()
|
||||
{
|
||||
delete[] mData;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Copy assignment operator (disabled).
|
||||
*/
|
||||
Frame & operator = (const Frame & o) = delete;
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Move assignment operator (disabled).
|
||||
*/
|
||||
Frame & operator = (Frame && o) noexcept = delete;
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Forget about the associated memory buffer.
|
||||
*/
|
||||
void ForgetBuffer() noexcept
|
||||
{
|
||||
mData = nullptr;
|
||||
mSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Smart frame pointer.
|
||||
*/
|
||||
using FramePtr = std::unique_ptr< Frame >;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Queue of frames written from other threads.
|
||||
*/
|
||||
using FrameQueue = moodycamel::ConcurrentQueue< FramePtr >;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Connection handle.
|
||||
*/
|
||||
struct mg_connection * mHandle{nullptr};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Queue of frames that must be processed.
|
||||
*/
|
||||
FrameQueue mQueue{1024};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Callback to invoke when receiving data.
|
||||
*/
|
||||
Function mOnData{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Callback to invoke when the socket is shutting down.
|
||||
*/
|
||||
Function mOnClose{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* User tag associated with this instance.
|
||||
*/
|
||||
String mTag{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* User data associated with this instance.
|
||||
*/
|
||||
LightObj mData{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Server port.
|
||||
*/
|
||||
int mPort{0};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Make a secure connection to server.
|
||||
*/
|
||||
bool mSecure{false};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Whether the connection is currently closing.
|
||||
*/
|
||||
std::atomic< bool > mClosing{false};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Whether the closing callback was inoked (avoid recursive calls).
|
||||
*/
|
||||
std::atomic< bool > mClosed{false};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Whether to not keep the connection open after receiving the close event.
|
||||
* Internally this event is ignored but if set to true the connection is immediatelly closed
|
||||
* in the internal event handler, before the event may reach the script callback.
|
||||
*/
|
||||
std::atomic< bool > mAutoClose{false};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Server host to connect to, i.e. "echo.websocket.org" or "192.168.1.1" or "localhost".
|
||||
*/
|
||||
String mHost{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Server path you are trying to connect to, i.e. if connection to localhost/app, path should be "/app".
|
||||
*/
|
||||
String mPath{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Value of the Origin HTTP header.
|
||||
*/
|
||||
String mOrigin{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Extensions to include in the connection.
|
||||
*/
|
||||
String mExtensions{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
WebSocketClient()
|
||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||
, mPort(0), mSecure(false), mClosing(false), mClosed(false), mAutoClose(false)
|
||||
, mHost(), mPath(), mOrigin(), mExtensions()
|
||||
{
|
||||
ChainInstance(); // Remember this instance
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path)
|
||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||
, mPort(port), mSecure(false), mClosing(false), mClosed(false), mAutoClose(false)
|
||||
, mHost(host.mPtr, host.GetSize())
|
||||
, mPath(path.mPtr, path.GetSize())
|
||||
, mOrigin(), mExtensions()
|
||||
{
|
||||
ChainInstance(); // Remember this instance
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure)
|
||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||
, mPort(port), mSecure(secure), mClosing(false), mClosed(false), mAutoClose(false)
|
||||
, mHost(host.mPtr, host.GetSize())
|
||||
, mPath(path.mPtr, path.GetSize())
|
||||
, mOrigin(), mExtensions()
|
||||
{
|
||||
ChainInstance(); // Remember this instance
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure, StackStrF & origin)
|
||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||
, mPort(port), mSecure(secure), mClosing(false), mClosed(false), mAutoClose(false)
|
||||
, mHost(host.mPtr, host.GetSize())
|
||||
, mPath(path.mPtr, path.GetSize())
|
||||
, mOrigin(origin.mPtr, origin.GetSize())
|
||||
, mExtensions()
|
||||
{
|
||||
ChainInstance(); // Remember this instance
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure, StackStrF & origin, StackStrF & ext)
|
||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||
, mPort(port), mSecure(secure), mClosing(false), mClosed(false), mAutoClose(false)
|
||||
, mHost(host.mPtr, host.GetSize())
|
||||
, mPath(path.mPtr, path.GetSize())
|
||||
, mOrigin(origin.mPtr, origin.GetSize())
|
||||
, mExtensions(ext.mPtr, ext.GetSize())
|
||||
{
|
||||
ChainInstance(); // Remember this instance
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
WebSocketClient(const WebSocketClient &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
WebSocketClient(WebSocketClient &&) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor. Closes the connection.
|
||||
*/
|
||||
~WebSocketClient()
|
||||
{
|
||||
// Is there a connection left to close?
|
||||
if (mHandle != nullptr)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
// Forget about this instance
|
||||
UnchainInstance();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
WebSocketClient & operator = (const WebSocketClient &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
WebSocketClient & operator = (WebSocketClient &&) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return whether the associated connection handle is valid.
|
||||
*/
|
||||
SQMOD_NODISCARD bool IsValid() const
|
||||
{
|
||||
return mHandle != nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return whether the associated connection is closing.
|
||||
* This is only valid inside the OnClose callback.
|
||||
*/
|
||||
SQMOD_NODISCARD bool IsClosing() const
|
||||
{
|
||||
return mClosing.load();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve whether auto-closing is enabled or not.
|
||||
*/
|
||||
SQMOD_NODISCARD bool GetAutoClose() const
|
||||
{
|
||||
return mAutoClose.load();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify whether auto-closing is enabled or not.
|
||||
*/
|
||||
void SetAutoClose(bool toggle)
|
||||
{
|
||||
mAutoClose.store(toggle);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated user tag.
|
||||
*/
|
||||
SQMOD_NODISCARD const String & GetTag() const
|
||||
{
|
||||
return mTag;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated user tag.
|
||||
*/
|
||||
void SetTag(StackStrF & tag)
|
||||
{
|
||||
if (tag.mLen > 0)
|
||||
{
|
||||
mTag.assign(tag.mPtr, static_cast< size_t >(tag.mLen));
|
||||
}
|
||||
else
|
||||
{
|
||||
mTag.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated user tag.
|
||||
*/
|
||||
WebSocketClient & ApplyTag(StackStrF & tag)
|
||||
{
|
||||
SetTag(tag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated user data.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj & GetData()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated user data.
|
||||
*/
|
||||
void SetData(LightObj & data)
|
||||
{
|
||||
mData = data;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated user data.
|
||||
*/
|
||||
WebSocketClient & ApplyData(LightObj & data)
|
||||
{
|
||||
mData = data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Make sure a connection exists.
|
||||
*/
|
||||
void Validate() const
|
||||
{
|
||||
if (mHandle == nullptr)
|
||||
{
|
||||
STHROWF("No connection was made to server ({}:{}{})", mHost, mPort, mPath);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return a valid connection.
|
||||
*/
|
||||
SQMOD_NODISCARD struct mg_connection * Valid() const
|
||||
{
|
||||
Validate();
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Make sure a connection does not exist.
|
||||
*/
|
||||
void Invalid() const
|
||||
{
|
||||
if (mHandle != nullptr)
|
||||
{
|
||||
STHROWF("Connection already made to server ({}:{}{})", mHost, mPort, mPath);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated server host.
|
||||
*/
|
||||
SQMOD_NODISCARD const String & GetHost() const
|
||||
{
|
||||
return mHost;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated server host.
|
||||
*/
|
||||
void SetHost(StackStrF & host)
|
||||
{
|
||||
Invalid();
|
||||
// Is there a valid host?
|
||||
if (host.mLen > 0)
|
||||
{
|
||||
mHost.assign(host.mPtr, static_cast< size_t >(host.mLen));
|
||||
}
|
||||
else
|
||||
{
|
||||
mHost.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated server host.
|
||||
*/
|
||||
WebSocketClient & ApplyHost(StackStrF & host)
|
||||
{
|
||||
SetHost(host);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated server path.
|
||||
*/
|
||||
SQMOD_NODISCARD const String & GetPath() const
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated server path.
|
||||
*/
|
||||
void SetPath(StackStrF & path)
|
||||
{
|
||||
Invalid();
|
||||
// Is there a valid path?
|
||||
if (path.mLen > 0)
|
||||
{
|
||||
mPath.assign(path.mPtr, static_cast< size_t >(path.mLen));
|
||||
}
|
||||
else
|
||||
{
|
||||
mPath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated server path.
|
||||
*/
|
||||
WebSocketClient & ApplyPath(StackStrF & path)
|
||||
{
|
||||
SetPath(path);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated origin value.
|
||||
*/
|
||||
SQMOD_NODISCARD const String & GetOrigin() const
|
||||
{
|
||||
return mOrigin;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated origin value.
|
||||
*/
|
||||
void SetOrigin(StackStrF & origin)
|
||||
{
|
||||
Invalid();
|
||||
// Is there a valid origin?
|
||||
if (origin.mLen > 0)
|
||||
{
|
||||
mOrigin.assign(origin.mPtr, static_cast< size_t >(origin.mLen));
|
||||
}
|
||||
else
|
||||
{
|
||||
mOrigin.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated origin value.
|
||||
*/
|
||||
WebSocketClient & ApplyOrigin(StackStrF & origin)
|
||||
{
|
||||
SetOrigin(origin);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated connection extensions.
|
||||
*/
|
||||
SQMOD_NODISCARD const String & GetExtensions() const
|
||||
{
|
||||
return mExtensions;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated connection extensions.
|
||||
*/
|
||||
void SetExtensions(StackStrF & ext)
|
||||
{
|
||||
Invalid();
|
||||
// Is there a valid extension?
|
||||
if (ext.mLen > 0)
|
||||
{
|
||||
mExtensions.assign(ext.mPtr, static_cast< size_t >(ext.mLen));
|
||||
}
|
||||
else
|
||||
{
|
||||
mExtensions.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated connection extensions.
|
||||
*/
|
||||
WebSocketClient & ApplyExtensions(StackStrF & ext)
|
||||
{
|
||||
SetExtensions(ext);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated server port number.
|
||||
*/
|
||||
SQMOD_NODISCARD int GetPort() const
|
||||
{
|
||||
return mPort;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated server port number.
|
||||
*/
|
||||
void SetPort(int port)
|
||||
{
|
||||
Invalid();
|
||||
// Is there a valid port?
|
||||
if (port < 0 || port > 65535)
|
||||
{
|
||||
STHROWF("Invalid port number: {0} < 0 || {0} > 65535", port);
|
||||
}
|
||||
else
|
||||
{
|
||||
mPort = port;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated server port number.
|
||||
*/
|
||||
WebSocketClient & ApplyPort(int port)
|
||||
{
|
||||
SetPort(port);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated SSL status.
|
||||
*/
|
||||
SQMOD_NODISCARD bool GetSecure() const
|
||||
{
|
||||
return mSecure;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated SSL status.
|
||||
*/
|
||||
void SetSecure(bool secure)
|
||||
{
|
||||
Invalid();
|
||||
mSecure = secure;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated SSL status.
|
||||
*/
|
||||
WebSocketClient & ApplySecure(bool secure)
|
||||
{
|
||||
SetSecure(secure);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated data callback.
|
||||
*/
|
||||
SQMOD_NODISCARD Function & GetOnData()
|
||||
{
|
||||
return mOnData;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated data callback.
|
||||
*/
|
||||
void SetOnData(Function & cb)
|
||||
{
|
||||
mOnData = cb;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated data callback.
|
||||
*/
|
||||
WebSocketClient & BindOnData(Function & cb)
|
||||
{
|
||||
mOnData = cb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated close callback.
|
||||
*/
|
||||
SQMOD_NODISCARD Function & GetOnClose()
|
||||
{
|
||||
return mOnClose;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated close callback.
|
||||
*/
|
||||
void SetOnClose(Function & cb)
|
||||
{
|
||||
mOnClose = cb;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated close callback.
|
||||
*/
|
||||
WebSocketClient & BindOnClose(Function & cb)
|
||||
{
|
||||
mOnClose = cb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Connect to a web-socket as a client.
|
||||
*/
|
||||
WebSocketClient & Connect();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Connect to a web-socket as a client with specific extensions.
|
||||
*/
|
||||
WebSocketClient & ConnectExt();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Close client connection.
|
||||
*/
|
||||
void Close()
|
||||
{
|
||||
mg_close_connection(Valid());
|
||||
// Prevent further use
|
||||
mHandle = nullptr;
|
||||
// Process pending events
|
||||
Process(true);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Sends the contents of the given buffer through the socket as a single frame.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger SendOpCode(SQInteger opcode)
|
||||
{
|
||||
return mg_websocket_client_write(Valid(), static_cast< int >(opcode), nullptr, 0);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Sends the contents of the given buffer through the socket as a single frame.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger SendBuffer(SqBuffer & buf, SQInteger opcode)
|
||||
{
|
||||
return mg_websocket_client_write(Valid(), static_cast< int >(opcode), buf.Valid().Data(), buf.Valid().Position());
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Sends the contents of the given string through the socket as a single frame.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger SendString(SQInteger opcode, StackStrF & str)
|
||||
{
|
||||
return mg_websocket_client_write(Valid(), static_cast< int >(opcode), str.mPtr, static_cast< size_t >(str.mLen));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Process received data.
|
||||
*/
|
||||
void Process(bool force = false)
|
||||
{
|
||||
// Is there a valid connection?
|
||||
if (mHandle == nullptr && !force)
|
||||
{
|
||||
return; // No point in going forward
|
||||
}
|
||||
FramePtr frame;
|
||||
// See if connection is closing
|
||||
const bool closing = mClosing.load();
|
||||
// Is the connection closing?
|
||||
if (closing)
|
||||
{
|
||||
mHandle = nullptr; // Prevent further use
|
||||
}
|
||||
// Retrieve each frame individually and process it
|
||||
for (size_t count = mQueue.size_approx(), n = 0; n <= count; ++n)
|
||||
{
|
||||
// Try to get a frame from the queue
|
||||
if (mQueue.try_dequeue(frame) && !mOnData.IsNull())
|
||||
{
|
||||
// Obtain a buffer from the frame
|
||||
Buffer b(frame->mData, frame->mSize, frame->mSize, Buffer::OwnIt{});
|
||||
// Backup the frame size before forgetting about it
|
||||
const SQInteger size = static_cast< SQInteger >(frame->mSize);
|
||||
// Take ownership of the memory
|
||||
frame->ForgetBuffer();
|
||||
// Transform the buffer into a script object
|
||||
LightObj obj(SqTypeIdentity< SqBuffer >{}, SqVM(), std::move(b));
|
||||
// Forward the event to the callback
|
||||
mOnData.Execute(obj, size, frame->mFlags);
|
||||
}
|
||||
}
|
||||
// Is the server closing the connection?
|
||||
if (closing && !mClosed.load() && !mOnClose.IsNull())
|
||||
{
|
||||
// Let the user know
|
||||
mOnClose.Execute();
|
||||
// Prevent calling this callback again
|
||||
mClosed.store(true);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used internally to release script resources, if any. The VM is about to be closed.
|
||||
* If you don't close the connection yourself don't care about what is received after this.
|
||||
*/
|
||||
void Terminate()
|
||||
{
|
||||
// Process pending data
|
||||
Process(true);
|
||||
// Release callbacks
|
||||
mOnData.Release();
|
||||
mOnClose.Release();
|
||||
// Release user data
|
||||
mData.Release();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Callback for handling data received from the server
|
||||
*/
|
||||
int DataHandler(int flags, char * data, size_t data_len) noexcept;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Callback for handling a close message received from the server.
|
||||
*/
|
||||
void CloseHandler() noexcept;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Proxy for DataHandler()
|
||||
*/
|
||||
static int DataHandler_(struct mg_connection * SQ_UNUSED_ARG(c), int f, char * d, size_t n, void * u) noexcept
|
||||
{
|
||||
return reinterpret_cast< WebSocketClient * >(u)->DataHandler(f, d, n);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Proxy for CloseHandler();
|
||||
*/
|
||||
static void CloseHandler_(const struct mg_connection * SQ_UNUSED_ARG(c), void * u) noexcept
|
||||
{
|
||||
reinterpret_cast< WebSocketClient * >(u)->CloseHandler();
|
||||
}
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
@@ -5,14 +5,12 @@
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
extern void Register_LongInt(HSQUIRRELVM vm);
|
||||
extern void Register_Math(HSQUIRRELVM vm);
|
||||
extern void Register_Random(HSQUIRRELVM vm);
|
||||
|
||||
// ================================================================================================
|
||||
void Register_Numeric(HSQUIRRELVM vm)
|
||||
{
|
||||
Register_LongInt(vm);
|
||||
Register_Math(vm);
|
||||
Register_Random(vm);
|
||||
}
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
#include "Library/Numeric/Random.hpp"
|
||||
#include "Base/DynArg.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_DECL_TYPENAME(TypenameS, _SC("SLongInt"))
|
||||
SQMOD_DECL_TYPENAME(TypenameU, _SC("ULongInt"))
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LongInt< signed long long >::LongInt(const SQChar * text)
|
||||
: m_Data(0), m_Text()
|
||||
{
|
||||
m_Data = std::strtoll(text, nullptr, 10);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LongInt< signed long long >::LongInt(const SQChar * text, uint32_t base)
|
||||
: m_Data(0), m_Text()
|
||||
{
|
||||
m_Data = std::strtoll(text, nullptr, base);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LongInt< signed long long > & LongInt< signed long long >::operator = (const SQChar * text)
|
||||
{
|
||||
m_Data = std::strtoll(text, nullptr, 10);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const SQChar * LongInt< signed long long >::ToString()
|
||||
{
|
||||
if (std::snprintf(m_Text, sizeof(m_Text), "%llu", m_Data) < 0)
|
||||
{
|
||||
m_Text[0] = 0;
|
||||
}
|
||||
|
||||
return m_Text;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LongInt< signed long long >::Random()
|
||||
{
|
||||
m_Data = GetRandomInt64();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LongInt< signed long long >::Random(Type n)
|
||||
{
|
||||
m_Data = GetRandomInt64(n);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LongInt< signed long long >::Random(Type m, Type n)
|
||||
{
|
||||
m_Data = GetRandomInt64(m, n);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LongInt< unsigned long long >::LongInt(const SQChar * text)
|
||||
: m_Data(0), m_Text()
|
||||
{
|
||||
m_Data = std::strtoull(text, nullptr, 10);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LongInt< unsigned long long >::LongInt(const SQChar * text, uint32_t base)
|
||||
: m_Data(0), m_Text()
|
||||
{
|
||||
m_Data = std::strtoull(text, nullptr, base);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LongInt< unsigned long long > & LongInt< unsigned long long >::operator = (const SQChar * text)
|
||||
{
|
||||
m_Data = std::strtoull(text, nullptr, 10);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const SQChar * LongInt< unsigned long long >::ToString()
|
||||
{
|
||||
if (std::snprintf(m_Text, sizeof(m_Text), "%llu", m_Data) < 0)
|
||||
{
|
||||
m_Text[0] = 0;
|
||||
}
|
||||
|
||||
return m_Text;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LongInt< unsigned long long >::Random()
|
||||
{
|
||||
m_Data = GetRandomUint64();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LongInt< unsigned long long >::Random(Type n)
|
||||
{
|
||||
m_Data = GetRandomUint64(n);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LongInt< unsigned long long >::Random(Type m, Type n)
|
||||
{
|
||||
m_Data = GetRandomUint64(m, n);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
signed long long PopStackSLong(HSQUIRRELVM vm, SQInteger idx)
|
||||
{
|
||||
// Identify which type must be extracted
|
||||
switch (sq_gettype(vm, idx))
|
||||
{
|
||||
case OT_INTEGER:
|
||||
{
|
||||
SQInteger val;
|
||||
sq_getinteger(vm, idx, &val);
|
||||
return static_cast< signed long long >(val);
|
||||
}
|
||||
case OT_FLOAT:
|
||||
{
|
||||
SQFloat val;
|
||||
sq_getfloat(vm, idx, &val);
|
||||
return ConvTo< signed long long >::From(val);
|
||||
}
|
||||
case OT_BOOL:
|
||||
{
|
||||
SQBool val;
|
||||
sq_getbool(vm, idx, &val);
|
||||
return static_cast< signed long long >(val);
|
||||
}
|
||||
case OT_STRING:
|
||||
{
|
||||
const SQChar * 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< signed long long >(sq_getsize(vm, idx));
|
||||
}
|
||||
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< signed long long >::From(Var< const ULongInt & >(vm, idx).value.GetNum());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Just ignore it...
|
||||
}
|
||||
// Attempt to get the size of the instance as a fall back
|
||||
return static_cast< signed long long >(sq_getsize(vm, idx));
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
// Default to 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned long long PopStackULong(HSQUIRRELVM vm, SQInteger idx)
|
||||
{
|
||||
// Identify which type must be extracted
|
||||
switch (sq_gettype(vm, idx))
|
||||
{
|
||||
case OT_INTEGER:
|
||||
{
|
||||
SQInteger val;
|
||||
sq_getinteger(vm, idx, &val);
|
||||
return ConvTo< unsigned long long >::From(val);
|
||||
}
|
||||
case OT_FLOAT:
|
||||
{
|
||||
SQFloat val;
|
||||
sq_getfloat(vm, idx, &val);
|
||||
return ConvTo< unsigned long long >::From(val);
|
||||
}
|
||||
case OT_BOOL:
|
||||
{
|
||||
SQBool val;
|
||||
sq_getbool(vm, idx, &val);
|
||||
return ConvTo< unsigned long long >::From(val);
|
||||
}
|
||||
case OT_STRING:
|
||||
{
|
||||
const SQChar * 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< unsigned long long >::From(sq_getsize(vm, idx));
|
||||
}
|
||||
case OT_INSTANCE:
|
||||
{
|
||||
// Attempt to treat the value as a signed long instance
|
||||
try
|
||||
{
|
||||
return ConvTo< unsigned long long >::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 fall back
|
||||
return ConvTo< unsigned long long >::From(sq_getsize(vm, idx));
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
// Default to 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const SLongInt & GetSLongInt()
|
||||
{
|
||||
static SLongInt l;
|
||||
l.SetNum(0);
|
||||
return l;
|
||||
}
|
||||
|
||||
const SLongInt & GetSLongInt(signed long long n)
|
||||
{
|
||||
static SLongInt l;
|
||||
l.SetNum(n);
|
||||
return l;
|
||||
}
|
||||
|
||||
const SLongInt & GetSLongInt(const SQChar * s)
|
||||
{
|
||||
static SLongInt l;
|
||||
l = s;
|
||||
return l;
|
||||
}
|
||||
|
||||
const ULongInt & GetULongInt()
|
||||
{
|
||||
static ULongInt l;
|
||||
l.SetNum(0);
|
||||
return l;
|
||||
}
|
||||
|
||||
const ULongInt & GetULongInt(unsigned long long n)
|
||||
{
|
||||
static ULongInt l;
|
||||
l.SetNum(n);
|
||||
return l;
|
||||
}
|
||||
|
||||
const ULongInt & GetULongInt(const SQChar * s)
|
||||
{
|
||||
static ULongInt l;
|
||||
l = s;
|
||||
return l;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_LongInt(HSQUIRRELVM vm)
|
||||
{
|
||||
RootTable(vm).Bind(TypenameS::Str,
|
||||
Class< SLongInt >(vm, TypenameS::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< SLongInt::Type >()
|
||||
.template Ctor< const char *, SQInteger >()
|
||||
// Properties
|
||||
.Prop(_SC("Str"), &SLongInt::GetCStr, &SLongInt::SetStr)
|
||||
.Prop(_SC("Num"), &SLongInt::GetSNum, &SLongInt::SetNum)
|
||||
// Core Meta-methods
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
|
||||
.SquirrelFunc(_SC("_typename"), &TypenameS::Fn)
|
||||
.Func(_SC("_tostring"), &SLongInt::ToString)
|
||||
// Core Functions
|
||||
.Func(_SC("tointeger"), &SLongInt::ToSqInteger)
|
||||
.Func(_SC("tofloat"), &SLongInt::ToSqFloat)
|
||||
.Func(_SC("tostring"), &SLongInt::ToSqString)
|
||||
.Func(_SC("tobool"), &SLongInt::ToSqBool)
|
||||
.Func(_SC("tochar"), &SLongInt::ToSqChar)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
|
||||
.SquirrelFunc(_SC("_mul"), &SqDynArgFwd< SqDynArgMulFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
|
||||
.SquirrelFunc(_SC("_div"), &SqDynArgFwd< SqDynArgDivFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
|
||||
.SquirrelFunc(_SC("_modulo"), &SqDynArgFwd< SqDynArgModFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
|
||||
.Func< SLongInt (SLongInt::*)(void) const >(_SC("_unm"), &SLongInt::operator -)
|
||||
// Functions
|
||||
.Func(_SC("GetStr"), &SLongInt::GetCStr)
|
||||
.Func(_SC("SetStr"), &SLongInt::SetStr)
|
||||
.Func(_SC("GetNum"), &SLongInt::GetSNum)
|
||||
.Func(_SC("SetNum"), &SLongInt::SetNum)
|
||||
// Overloads
|
||||
.Overload< void (SLongInt::*)(void) >(_SC("Random"), &SLongInt::Random)
|
||||
.Overload< void (SLongInt::*)(SLongInt::Type) >(_SC("Random"), &SLongInt::Random)
|
||||
.Overload< void (SLongInt::*)(SLongInt::Type, SLongInt::Type) >(_SC("Random"), &SLongInt::Random)
|
||||
);
|
||||
|
||||
RootTable(vm).Bind(TypenameU::Str,
|
||||
Class< ULongInt >(vm, TypenameU::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< ULongInt::Type >()
|
||||
.Ctor< const char *, SQInteger >()
|
||||
// Properties
|
||||
.Prop(_SC("Str"), &ULongInt::GetCStr, &ULongInt::SetStr)
|
||||
.Prop(_SC("Num"), &ULongInt::GetSNum, &ULongInt::SetNum)
|
||||
// Core Meta-methods
|
||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
|
||||
.SquirrelFunc(_SC("_typename"), &TypenameU::Fn)
|
||||
.Func(_SC("_tostring"), &ULongInt::ToString)
|
||||
// Core Functions
|
||||
.Func(_SC("tointeger"), &ULongInt::ToSqInteger)
|
||||
.Func(_SC("tofloat"), &ULongInt::ToSqFloat)
|
||||
.Func(_SC("tostring"), &ULongInt::ToSqString)
|
||||
.Func(_SC("tobool"), &ULongInt::ToSqBool)
|
||||
.Func(_SC("tochar"), &ULongInt::ToSqChar)
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
|
||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
|
||||
.SquirrelFunc(_SC("_mul"), &SqDynArgFwd< SqDynArgMulFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
|
||||
.SquirrelFunc(_SC("_div"), &SqDynArgFwd< SqDynArgDivFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
|
||||
.SquirrelFunc(_SC("_modulo"), &SqDynArgFwd< SqDynArgModFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
|
||||
.Func< ULongInt (ULongInt::*)(void) const >(_SC("_unm"), &ULongInt::operator -)
|
||||
// Functions
|
||||
.Func(_SC("GetStr"), &ULongInt::GetCStr)
|
||||
.Func(_SC("SetStr"), &ULongInt::SetStr)
|
||||
.Func(_SC("GetNum"), &ULongInt::GetSNum)
|
||||
.Func(_SC("SetNum"), &ULongInt::SetNum)
|
||||
// Overloads
|
||||
.Overload< void (ULongInt::*)(void) >(_SC("Random"), &ULongInt::Random)
|
||||
.Overload< void (ULongInt::*)(ULongInt::Type) >(_SC("Random"), &ULongInt::Random)
|
||||
.Overload< void (ULongInt::*)(ULongInt::Type, ULongInt::Type) >(_SC("Random"), &ULongInt::Random)
|
||||
);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/Numeric/Math.hpp"
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cmath>
|
||||
@@ -66,7 +65,7 @@ static SQInteger SqRemainder(HSQUIRRELVM vm)
|
||||
// Are we both arguments integers?
|
||||
else if ((sq_gettype(vm, 2) == OT_INTEGER) && sq_gettype(vm, 3) == OT_INTEGER)
|
||||
{ // NOLINT(bugprone-branch-clone)
|
||||
sq_pushinteger(vm, std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3)));
|
||||
sq_pushinteger(vm, static_cast< SQInteger >(std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3))));
|
||||
}
|
||||
// Is the first argument float?
|
||||
else if ((sq_gettype(vm, 2) == OT_FLOAT))
|
||||
@@ -76,7 +75,7 @@ static SQInteger SqRemainder(HSQUIRRELVM vm)
|
||||
// Is the first argument integer?
|
||||
else if ((sq_gettype(vm, 2) == OT_INTEGER))
|
||||
{
|
||||
sq_pushinteger(vm, std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3)));
|
||||
sq_pushinteger(vm, static_cast< SQInteger >(std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3))));
|
||||
}
|
||||
// Default to both arguments as float so we don't loos precision from the float one
|
||||
else
|
||||
@@ -184,18 +183,7 @@ static SQInteger SqNanL(HSQUIRRELVM vm)
|
||||
return val.mRes; // Propagate the error!
|
||||
}
|
||||
// Fetch the arguments from the stack and perform the requested operation
|
||||
try
|
||||
{
|
||||
Var< SLongInt * >::push(vm, new SLongInt(std::nanl(val.mPtr)));
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
return sq_throwerror(vm, e.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return sq_throwerror(vm, _SC("Failed to create a long integer instance"));
|
||||
}
|
||||
sq_pushinteger(vm, static_cast< SQInteger >(std::nanl(val.mPtr)));
|
||||
// Specify that we have a value on the stack
|
||||
return 1;
|
||||
}
|
||||
@@ -659,11 +647,11 @@ static SQInteger SqRoundI(HSQUIRRELVM vm)
|
||||
// Fetch the arguments from the stack and perform the requested operation
|
||||
if (sq_gettype(vm, 2) == OT_FLOAT)
|
||||
{
|
||||
sq_pushinteger(vm, ConvTo< SQInteger >::From(std::llround(PopStackFloat(vm, 2))));
|
||||
sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackFloat(vm, 2))));
|
||||
}
|
||||
else
|
||||
{
|
||||
sq_pushinteger(vm, ConvTo< SQInteger >::From(std::llround(PopStackInteger(vm, 2))));
|
||||
sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackInteger(vm, 2))));
|
||||
}
|
||||
// Specify that we have a value on the stack
|
||||
return 1;
|
||||
@@ -678,24 +666,13 @@ static SQInteger SqRoundL(HSQUIRRELVM vm)
|
||||
return sq_throwerror(vm, "Wrong number of arguments");
|
||||
}
|
||||
// Fetch the arguments from the stack and perform the requested operation
|
||||
try
|
||||
if (sq_gettype(vm, 2) == OT_FLOAT)
|
||||
{
|
||||
if (sq_gettype(vm, 2) == OT_FLOAT)
|
||||
{
|
||||
Var< SLongInt * >::push(vm, new SLongInt(std::llround(PopStackFloat(vm, 2))));
|
||||
}
|
||||
else
|
||||
{
|
||||
Var< SLongInt * >::push(vm, new SLongInt(std::llround(PopStackInteger(vm, 2))));
|
||||
}
|
||||
sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackFloat(vm, 2))));
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
else
|
||||
{
|
||||
return sq_throwerror(vm, e.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return sq_throwerror(vm, _SC("Failed to create a long integer instance"));
|
||||
sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackInteger(vm, 2))));
|
||||
}
|
||||
// Specify that we have a value on the stack
|
||||
return 1;
|
||||
@@ -760,7 +737,7 @@ static SQInteger SqLdexp(HSQUIRRELVM vm)
|
||||
return sq_throwerror(vm, "Wrong number of arguments");
|
||||
}
|
||||
// Fetch the arguments from the stack and perform the requested operation
|
||||
sq_pushfloat(vm, std::ldexp(PopStackFloat(vm, 2), PopStackInteger(vm, 3)));
|
||||
sq_pushfloat(vm, std::ldexp(PopStackFloat(vm, 2), static_cast< int >(PopStackInteger(vm, 3))));
|
||||
// Specify that we have a value on the stack
|
||||
return 1;
|
||||
}
|
||||
@@ -811,9 +788,9 @@ static SQInteger SqScalbn(HSQUIRRELVM vm)
|
||||
}
|
||||
// Fetch the arguments from the stack and perform the requested operation
|
||||
#ifdef _SQ64
|
||||
sq_pushfloat(vm, std::scalbln(PopStackFloat(vm, 2), PopStackInteger(vm, 3)));
|
||||
sq_pushfloat(vm, std::scalbln(PopStackFloat(vm, 2), static_cast< int >(PopStackInteger(vm, 3))));
|
||||
#else
|
||||
sq_pushfloat(vm, std::scalbn(PopStackFloat(vm, 2), PopStackInteger(vm, 3)));
|
||||
sq_pushfloat(vm, std::scalbn(PopStackFloat(vm, 2), static_cast< int >(PopStackInteger(vm, 3))));
|
||||
#endif // _SQ64
|
||||
// Specify that we have a value on the stack
|
||||
return 1;
|
||||
@@ -1066,7 +1043,7 @@ static SQInteger SqDigits1(HSQUIRRELVM vm)
|
||||
return sq_throwerror(vm, "Wrong number of arguments");
|
||||
}
|
||||
// Fetch the integer value from the stack
|
||||
int64_t n = std::llabs(PopStackSLong(vm, 2));
|
||||
int64_t n = std::llabs(PopStackInteger(vm, 2));
|
||||
// Start with 0 digits
|
||||
uint8_t d = 0;
|
||||
// Identify the number of digits
|
||||
@@ -1090,7 +1067,7 @@ static SQInteger SqDigits0(HSQUIRRELVM vm)
|
||||
return sq_throwerror(vm, "Wrong number of arguments");
|
||||
}
|
||||
// Fetch the integer value from the stack
|
||||
int64_t n = std::llabs(PopStackSLong(vm, 2));
|
||||
int64_t n = std::llabs(PopStackInteger(vm, 2));
|
||||
// Start with 0 digits
|
||||
uint8_t d = 0;
|
||||
// Identify the number of digits
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Core/Common.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/RegEx.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqratConst.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_DECL_TYPENAME(SqRxMatchTypename, _SC("SqRxMatch"))
|
||||
SQMOD_DECL_TYPENAME(SqRxMatchesTypename, _SC("SqRxMatches"))
|
||||
SQMOD_DECL_TYPENAME(SqRxInstanceTypename, _SC("SqRxInstance"))
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool RxInstance::STUDY = true;
|
||||
int RxInstance::OPTIONS = 0;
|
||||
int RxInstance::STUDY_OPTIONS = 0;
|
||||
|
||||
// ================================================================================================
|
||||
void Register_RegEx(HSQUIRRELVM vm)
|
||||
{
|
||||
RootTable(vm).Bind(SqRxMatchTypename::Str,
|
||||
Class< RxMatch >(vm, SqRxMatchTypename::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< SQInteger >()
|
||||
.Ctor< SQInteger, SQInteger >()
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_typename"), &SqRxMatchTypename::Fn)
|
||||
// Properties
|
||||
.Prop(_SC("Offset"), &RxMatch::GetOffset, &RxMatch::SetOffset)
|
||||
.Prop(_SC("Length"), &RxMatch::GetLength, &RxMatch::SetLength)
|
||||
.Prop(_SC("End"), &RxMatch::GetEnd)
|
||||
// Member Methods
|
||||
.Func(_SC("SubStr"), &RxMatch::SubStr)
|
||||
);
|
||||
RootTable(vm).Bind(SqRxMatchesTypename::Str,
|
||||
Class< RxMatches >(vm, SqRxMatchesTypename::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_typename"), &SqRxMatchesTypename::Fn)
|
||||
// Properties
|
||||
.Prop(_SC("Front"), &RxMatches::Front)
|
||||
.Prop(_SC("Back"), &RxMatches::Back)
|
||||
.Prop(_SC("Empty"), &RxMatches::Empty)
|
||||
.Prop(_SC("Size"), &RxMatches::Size)
|
||||
.Prop(_SC("Capacity"), &RxMatches::Capacity, &RxMatches::Reserve)
|
||||
// Member Methods
|
||||
.Func(_SC("Get"), &RxMatches::Get)
|
||||
.Func(_SC("Reserve"), &RxMatches::Reserve)
|
||||
.Func(_SC("Compact"), &RxMatches::Compact)
|
||||
.Func(_SC("Clear"), &RxMatches::Clear)
|
||||
.Func(_SC("Pop"), &RxMatches::Pop)
|
||||
.Func(_SC("EraseAt"), &RxMatches::EraseAt)
|
||||
.Func(_SC("EraseFrom"), &RxMatches::EraseFrom)
|
||||
.Func(_SC("Each"), &RxMatches::Each)
|
||||
.Func(_SC("EachRange"), &RxMatches::EachRange)
|
||||
.Func(_SC("While"), &RxMatches::While)
|
||||
.Func(_SC("WhileRange"), &RxMatches::WhileRange)
|
||||
.Func(_SC("SubStr"), &RxMatches::SubStr)
|
||||
);
|
||||
RootTable(vm).Bind(_SC("SqRx"),
|
||||
Class< RxInstance, NoCopy< RxInstance > >(vm, SqRxInstanceTypename::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< StackStrF & >()
|
||||
.Ctor< int, StackStrF & >()
|
||||
.Ctor< int, bool, StackStrF & >()
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_typename"), &SqRxInstanceTypename::Fn)
|
||||
//.Func(_SC("_tostring"), &CPlayer::ToString)
|
||||
// Static Values
|
||||
.SetStaticValue(_SC("STUDY"), RxInstance::STUDY)
|
||||
.SetStaticValue(_SC("OPTIONS"), RxInstance::OPTIONS)
|
||||
.SetStaticValue(_SC("STUDY_OPTIONS"), RxInstance::STUDY_OPTIONS)
|
||||
// Properties
|
||||
.Prop(_SC("Valid"), &RxInstance::IsValid)
|
||||
.Prop(_SC("Studied"), &RxInstance::IsStudied)
|
||||
// Member Methods
|
||||
.FmtFunc(_SC("CompileF"), &RxInstance::Compile1)
|
||||
.FmtFunc(_SC("CompileExF"), &RxInstance::Compile2)
|
||||
.FmtFunc(_SC("TryCompileF"), &RxInstance::TryCompile1)
|
||||
.FmtFunc(_SC("TryCompileExF"), &RxInstance::TryCompile2)
|
||||
.FmtFunc(_SC("MatchFirst"), &RxInstance::MatchFirst)
|
||||
.FmtFunc(_SC("MatchFirstEx"), &RxInstance::MatchFirst_)
|
||||
.FmtFunc(_SC("MatchFirstFrom"), &RxInstance::MatchFirstFrom)
|
||||
.FmtFunc(_SC("MatchFirstFromEx"), &RxInstance::MatchFirstFrom_)
|
||||
.FmtFunc(_SC("Match"), &RxInstance::Match)
|
||||
.FmtFunc(_SC("MatchEx"), &RxInstance::Match_)
|
||||
.FmtFunc(_SC("MatchFrom"), &RxInstance::MatchFrom)
|
||||
.FmtFunc(_SC("MatchFromEx"), &RxInstance::MatchFrom_)
|
||||
.FmtFunc(_SC("Matches"), &RxInstance::Matches)
|
||||
.FmtFunc(_SC("MatchesEx"), &RxInstance::Matches_)
|
||||
.FmtFunc(_SC("MatchesEx2"), &RxInstance::MatchesEx)
|
||||
// Member Overloads
|
||||
.Overload(_SC("Compile"), &RxInstance::Compile1)
|
||||
.Overload(_SC("Compile"), &RxInstance::Compile2)
|
||||
.Overload(_SC("TryCompile"), &RxInstance::TryCompile1)
|
||||
.Overload(_SC("TryCompile"), &RxInstance::TryCompile2)
|
||||
.Overload(_SC("Study"), &RxInstance::Study0)
|
||||
.Overload(_SC("Study"), &RxInstance::Study1)
|
||||
);
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ConstTable(vm).Enum(_SC("SqRxOption"), Enumeration(vm)
|
||||
.Const(_SC("Caseless"), static_cast< SQInteger >(PCRE_CASELESS))
|
||||
.Const(_SC("Multiline"), static_cast< SQInteger >(PCRE_MULTILINE))
|
||||
.Const(_SC("Dotall"), static_cast< SQInteger >(PCRE_DOTALL))
|
||||
.Const(_SC("Extended"), static_cast< SQInteger >(PCRE_EXTENDED))
|
||||
.Const(_SC("Anchored"), static_cast< SQInteger >(PCRE_ANCHORED))
|
||||
.Const(_SC("DollarEndOnly"), static_cast< SQInteger >(PCRE_DOLLAR_ENDONLY))
|
||||
.Const(_SC("Extra"), static_cast< SQInteger >(PCRE_EXTRA))
|
||||
.Const(_SC("NotBOL"), static_cast< SQInteger >(PCRE_NOTBOL))
|
||||
.Const(_SC("NotEOL"), static_cast< SQInteger >(PCRE_NOTEOL))
|
||||
.Const(_SC("UnGreedy"), static_cast< SQInteger >(PCRE_UNGREEDY))
|
||||
.Const(_SC("NotEmpty"), static_cast< SQInteger >(PCRE_NOTEMPTY))
|
||||
.Const(_SC("UTF8"), static_cast< SQInteger >(PCRE_UTF8))
|
||||
.Const(_SC("UTF16"), static_cast< SQInteger >(PCRE_UTF16))
|
||||
.Const(_SC("UTF32"), static_cast< SQInteger >(PCRE_UTF32))
|
||||
.Const(_SC("NoAutoCapture"), static_cast< SQInteger >(PCRE_NO_AUTO_CAPTURE))
|
||||
.Const(_SC("NoUTF8Check"), static_cast< SQInteger >(PCRE_NO_UTF8_CHECK))
|
||||
.Const(_SC("NoUTF16Check"), static_cast< SQInteger >(PCRE_NO_UTF16_CHECK))
|
||||
.Const(_SC("NoUTF32Check"), static_cast< SQInteger >(PCRE_NO_UTF32_CHECK))
|
||||
.Const(_SC("AutoCallout"), static_cast< SQInteger >(PCRE_AUTO_CALLOUT))
|
||||
.Const(_SC("PartialSoft"), static_cast< SQInteger >(PCRE_PARTIAL_SOFT))
|
||||
.Const(_SC("Partial"), static_cast< SQInteger >(PCRE_PARTIAL))
|
||||
.Const(_SC("NeverUTF"), static_cast< SQInteger >(PCRE_NEVER_UTF))
|
||||
.Const(_SC("DfaShortest"), static_cast< SQInteger >(PCRE_DFA_SHORTEST))
|
||||
.Const(_SC("NoAutoPossess"), static_cast< SQInteger >(PCRE_NO_AUTO_POSSESS))
|
||||
.Const(_SC("DfaRestart"), static_cast< SQInteger >(PCRE_DFA_RESTART))
|
||||
.Const(_SC("FirstLine"), static_cast< SQInteger >(PCRE_FIRSTLINE))
|
||||
.Const(_SC("DupNames"), static_cast< SQInteger >(PCRE_DUPNAMES))
|
||||
.Const(_SC("NewLineCR"), static_cast< SQInteger >(PCRE_NEWLINE_CR))
|
||||
.Const(_SC("NewLineLF"), static_cast< SQInteger >(PCRE_NEWLINE_LF))
|
||||
.Const(_SC("NewLineCRLF"), static_cast< SQInteger >(PCRE_NEWLINE_CRLF))
|
||||
.Const(_SC("NewLineAny"), static_cast< SQInteger >(PCRE_NEWLINE_ANY))
|
||||
.Const(_SC("NewLineAnyCRLF"), static_cast< SQInteger >(PCRE_NEWLINE_ANYCRLF))
|
||||
.Const(_SC("BsrAnyCRLF"), static_cast< SQInteger >(PCRE_BSR_ANYCRLF))
|
||||
.Const(_SC("BsrUnicode"), static_cast< SQInteger >(PCRE_BSR_UNICODE))
|
||||
.Const(_SC("JavaScriptCompat"), static_cast< SQInteger >(PCRE_JAVASCRIPT_COMPAT))
|
||||
.Const(_SC("NoStartOptimize"), static_cast< SQInteger >(PCRE_NO_START_OPTIMIZE))
|
||||
.Const(_SC("NoStartOptimise"), static_cast< SQInteger >(PCRE_NO_START_OPTIMISE))
|
||||
.Const(_SC("PartialHard"), static_cast< SQInteger >(PCRE_PARTIAL_HARD))
|
||||
.Const(_SC("NotEmptyAtStart"), static_cast< SQInteger >(PCRE_NOTEMPTY_ATSTART))
|
||||
.Const(_SC("UCP"), static_cast< SQInteger >(PCRE_UCP))
|
||||
);
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ConstTable(vm).Enum(_SC("SqRxError"), Enumeration(vm)
|
||||
.Const(_SC("NoMatch"), static_cast< SQInteger >(PCRE_ERROR_NOMATCH))
|
||||
.Const(_SC("Null"), static_cast< SQInteger >(PCRE_ERROR_NULL))
|
||||
.Const(_SC("BadOption"), static_cast< SQInteger >(PCRE_ERROR_BADOPTION))
|
||||
.Const(_SC("BadMagic"), static_cast< SQInteger >(PCRE_ERROR_BADMAGIC))
|
||||
.Const(_SC("UnknownOpCode"), static_cast< SQInteger >(PCRE_ERROR_UNKNOWN_OPCODE))
|
||||
.Const(_SC("UnknownNode"), static_cast< SQInteger >(PCRE_ERROR_UNKNOWN_NODE))
|
||||
.Const(_SC("NoMemory"), static_cast< SQInteger >(PCRE_ERROR_NOMEMORY))
|
||||
.Const(_SC("NoSubstring"), static_cast< SQInteger >(PCRE_ERROR_NOSUBSTRING))
|
||||
.Const(_SC("MatchLimit"), static_cast< SQInteger >(PCRE_ERROR_MATCHLIMIT))
|
||||
.Const(_SC("Callout"), static_cast< SQInteger >(PCRE_ERROR_CALLOUT))
|
||||
.Const(_SC("BadUTF8"), static_cast< SQInteger >(PCRE_ERROR_BADUTF8))
|
||||
.Const(_SC("BadUTF16"), static_cast< SQInteger >(PCRE_ERROR_BADUTF16))
|
||||
.Const(_SC("BadUTF32"), static_cast< SQInteger >(PCRE_ERROR_BADUTF32))
|
||||
.Const(_SC("BadUTF8Offset"), static_cast< SQInteger >(PCRE_ERROR_BADUTF8_OFFSET))
|
||||
.Const(_SC("BadUTF16Offset"), static_cast< SQInteger >(PCRE_ERROR_BADUTF16_OFFSET))
|
||||
.Const(_SC("Partial"), static_cast< SQInteger >(PCRE_ERROR_PARTIAL))
|
||||
.Const(_SC("BadPartial"), static_cast< SQInteger >(PCRE_ERROR_BADPARTIAL))
|
||||
.Const(_SC("Internal"), static_cast< SQInteger >(PCRE_ERROR_INTERNAL))
|
||||
.Const(_SC("BadCount"), static_cast< SQInteger >(PCRE_ERROR_BADCOUNT))
|
||||
.Const(_SC("DfaUitem"), static_cast< SQInteger >(PCRE_ERROR_DFA_UITEM))
|
||||
.Const(_SC("DfaUcond"), static_cast< SQInteger >(PCRE_ERROR_DFA_UCOND))
|
||||
.Const(_SC("DfaUmLimit"), static_cast< SQInteger >(PCRE_ERROR_DFA_UMLIMIT))
|
||||
.Const(_SC("DfaWsSize"), static_cast< SQInteger >(PCRE_ERROR_DFA_WSSIZE))
|
||||
.Const(_SC("DfaRecurse"), static_cast< SQInteger >(PCRE_ERROR_DFA_RECURSE))
|
||||
.Const(_SC("RecursionLimit"), static_cast< SQInteger >(PCRE_ERROR_RECURSIONLIMIT))
|
||||
.Const(_SC("NullWsLimit"), static_cast< SQInteger >(PCRE_ERROR_NULLWSLIMIT))
|
||||
.Const(_SC("BadNewLine"), static_cast< SQInteger >(PCRE_ERROR_BADNEWLINE))
|
||||
.Const(_SC("BadOffset"), static_cast< SQInteger >(PCRE_ERROR_BADOFFSET))
|
||||
.Const(_SC("ShortUTF8"), static_cast< SQInteger >(PCRE_ERROR_SHORTUTF8))
|
||||
.Const(_SC("ShortUTF16"), static_cast< SQInteger >(PCRE_ERROR_SHORTUTF16))
|
||||
.Const(_SC("RecurseLoop"), static_cast< SQInteger >(PCRE_ERROR_RECURSELOOP))
|
||||
.Const(_SC("JitStackLimit"), static_cast< SQInteger >(PCRE_ERROR_JIT_STACKLIMIT))
|
||||
.Const(_SC("BadMode"), static_cast< SQInteger >(PCRE_ERROR_BADMODE))
|
||||
.Const(_SC("BadEndianness"), static_cast< SQInteger >(PCRE_ERROR_BADENDIANNESS))
|
||||
.Const(_SC("DfaBadRestart"), static_cast< SQInteger >(PCRE_ERROR_DFA_BADRESTART))
|
||||
.Const(_SC("JitBadOption"), static_cast< SQInteger >(PCRE_ERROR_JIT_BADOPTION))
|
||||
.Const(_SC("BadLength"), static_cast< SQInteger >(PCRE_ERROR_BADLENGTH))
|
||||
.Const(_SC("Unset"), static_cast< SQInteger >(PCRE_ERROR_UNSET))
|
||||
);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
@@ -0,0 +1,885 @@
|
||||
#pragma once
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Core/Utility.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#ifdef POCO_UNBUNDLED
|
||||
#include <pcre.h>
|
||||
#else
|
||||
#include "pcre_config.h"
|
||||
#include "pcre.h"
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <utility>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
struct RxMatch
|
||||
{
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQInteger mOffset{0};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
SQInteger mLength{0};
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
RxMatch() noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Offset constructor.
|
||||
*/
|
||||
explicit RxMatch(SQInteger offset) noexcept
|
||||
: mOffset{offset}
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
RxMatch(SQInteger offset, SQInteger length) noexcept
|
||||
: mOffset{offset}, mLength{length}
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
RxMatch(const RxMatch & o) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
RxMatch(RxMatch && o) noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
RxMatch & operator = (const RxMatch & o) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
RxMatch & operator = (RxMatch && o) noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve offset.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger GetOffset() const noexcept
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify offset.
|
||||
*/
|
||||
void SetOffset(SQInteger value) noexcept
|
||||
{
|
||||
mOffset = value;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve length.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger GetLength() const noexcept
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify length.
|
||||
*/
|
||||
void SetLength(SQInteger value) noexcept
|
||||
{
|
||||
mLength = value;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve match end.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger GetEnd() const noexcept
|
||||
{
|
||||
return mOffset + mLength;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Extract a sub-string.
|
||||
*/
|
||||
[[nodiscard]] LightObj SubStr(StackStrF & str) const
|
||||
{
|
||||
if ((mOffset + mLength) > str.mLen)
|
||||
{
|
||||
STHROWF("Rx: Match is outside the range of the specified string.");
|
||||
}
|
||||
// Return the sub-string
|
||||
return LightObj{str.mPtr + mOffset, mLength};
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
struct RxMatches
|
||||
{
|
||||
using List = std::vector< RxMatch >;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Internal RegularExpression instance.
|
||||
*/
|
||||
List mList;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
RxMatches() = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy list constructor.
|
||||
*/
|
||||
explicit RxMatches(const List & l) // NOLINT(modernize-pass-by-value)
|
||||
: mList{l}
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move list constructor.
|
||||
*/
|
||||
explicit RxMatches(List && m) noexcept
|
||||
: mList{std::move(m)}
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
RxMatches(const RxMatches & o) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
RxMatches(RxMatches && o) noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
RxMatches & operator = (const RxMatches & o) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
RxMatches & operator = (RxMatches && o) noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Make sure an index is within range and return the container. Container must exist.
|
||||
*/
|
||||
List & ValidIdx(SQInteger i)
|
||||
{
|
||||
if (static_cast< size_t >(i) >= mList.size())
|
||||
{
|
||||
STHROWF("Invalid Regular Expression match list index({})", i);
|
||||
}
|
||||
return mList;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Make sure an index is within range and return the container. Container must exist.
|
||||
*/
|
||||
SQMOD_NODISCARD const List & ValidIdx(SQInteger i) const
|
||||
{
|
||||
if (static_cast< size_t >(i) >= mList.size())
|
||||
{
|
||||
STHROWF("Invalid Regular Expression match list index({})", i);
|
||||
}
|
||||
return mList;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Make sure a container instance is populated, then return it.
|
||||
*/
|
||||
SQMOD_NODISCARD List & ValidPop()
|
||||
{
|
||||
if (mList.empty())
|
||||
{
|
||||
STHROWF("Regular Expression match list container is empty");
|
||||
}
|
||||
return mList;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve a value from the container.
|
||||
*/
|
||||
SQMOD_NODISCARD List::reference Get(SQInteger i)
|
||||
{
|
||||
return ValidIdx(i).at(ClampL< SQInteger, size_t >(i));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the first element in the container.
|
||||
*/
|
||||
SQMOD_NODISCARD List::reference Front()
|
||||
{
|
||||
return ValidPop().front();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the last element in the container.
|
||||
*/
|
||||
SQMOD_NODISCARD List::reference Back()
|
||||
{
|
||||
return mList.back();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Check if the container has no elements.
|
||||
*/
|
||||
SQMOD_NODISCARD bool Empty() const
|
||||
{
|
||||
return mList.empty();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the number of elements in the container.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger Size() const
|
||||
{
|
||||
return static_cast< SQInteger >(mList.size());
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the number of elements that the container has currently allocated space for.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger Capacity() const
|
||||
{
|
||||
return static_cast< SQInteger >(mList.capacity());
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Increase the capacity of the container to a value that's greater or equal to the one specified.
|
||||
*/
|
||||
RxMatches & Reserve(SQInteger n)
|
||||
{
|
||||
mList.reserve(ClampL< SQInteger, size_t >(n));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Request the removal of unused capacity.
|
||||
*/
|
||||
void Compact()
|
||||
{
|
||||
mList.shrink_to_fit();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Erase all elements from the container.
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
mList.clear();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Pop the last element in the container.
|
||||
*/
|
||||
void Pop()
|
||||
{
|
||||
ValidPop().pop_back();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Erase the element at a certain position.
|
||||
*/
|
||||
void EraseAt(SQInteger i)
|
||||
{
|
||||
mList.erase(ValidIdx(i).begin() + static_cast< size_t >(i)); // NOLINT(cppcoreguidelines-narrowing-conversions)
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Erase a certain amount of elements starting from a specific position.
|
||||
*/
|
||||
void EraseFrom(SQInteger i, SQInteger n)
|
||||
{
|
||||
mList.erase(ValidIdx(i).begin() + static_cast< size_t >(i), // NOLINT(cppcoreguidelines-narrowing-conversions)
|
||||
ValidIdx(i + n).begin() + static_cast< size_t >(i + n)); // NOLINT(cppcoreguidelines-narrowing-conversions)
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Iterate all values through a functor.
|
||||
*/
|
||||
void Each(Function & fn) const
|
||||
{
|
||||
for (const auto & e : mList)
|
||||
{
|
||||
fn.Execute(static_cast< SQInteger >(e.mOffset), static_cast< SQInteger >(e.mLength));
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Iterate values in range through a functor.
|
||||
*/
|
||||
void EachRange(SQInteger p, SQInteger n, Function & fn) const
|
||||
{
|
||||
std::for_each(ValidIdx(p).begin() + static_cast< size_t >(p), // NOLINT(cppcoreguidelines-narrowing-conversions)
|
||||
ValidIdx(p + n).begin() + static_cast< size_t >(p + n), // NOLINT(cppcoreguidelines-narrowing-conversions)
|
||||
[&](List::const_reference & e) {
|
||||
fn.Execute(static_cast< SQInteger >(e.mOffset), static_cast< SQInteger >(e.mLength));
|
||||
});
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Iterate all values through a functor until stopped (i.e. false is returned).
|
||||
*/
|
||||
void While(Function & fn) const
|
||||
{
|
||||
for (const auto & e : mList)
|
||||
{
|
||||
auto ret = fn.Eval(static_cast< SQInteger >(e.mOffset), static_cast< SQInteger >(e.mLength));
|
||||
// (null || true) == continue & false == break
|
||||
if (!ret.IsNull() || !ret.template Cast< bool >())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Iterate values in range through a functor until stopped (i.e. false is returned).
|
||||
*/
|
||||
void WhileRange(SQInteger p, SQInteger n, Function & fn) const
|
||||
{
|
||||
auto itr = ValidIdx(p).begin() + static_cast< size_t >(p); // NOLINT(cppcoreguidelines-narrowing-conversions)
|
||||
auto end = ValidIdx(p + n).begin() + static_cast< size_t >(p + n); // NOLINT(cppcoreguidelines-narrowing-conversions)
|
||||
for (; itr != end; ++itr)
|
||||
{
|
||||
auto ret = fn.Eval(static_cast< SQInteger >(itr->mOffset), static_cast< SQInteger >(itr->mLength));
|
||||
// (null || true) == continue & false == break
|
||||
if (!ret.IsNull() || !ret.template Cast< bool >())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Extract a sub-string.
|
||||
*/
|
||||
[[nodiscard]] LightObj SubStr(SQInteger i, StackStrF & str) const
|
||||
{
|
||||
const RxMatch & m = ValidIdx(i)[i];
|
||||
// Check if match is within range
|
||||
if ((m.mOffset + m.mLength) > str.mLen)
|
||||
{
|
||||
STHROWF("Rx: Match is outside the range of the specified string.");
|
||||
}
|
||||
// Return the sub-string
|
||||
return LightObj{str.mPtr + m.mOffset, m.mLength};
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
struct RxInstance
|
||||
{
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Whether to analyze and optimize the pattern by default for evey new instance (true).
|
||||
*/
|
||||
static bool STUDY;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default options for every new instance (0).
|
||||
*/
|
||||
static int OPTIONS;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default study options for every new instance (0).
|
||||
*/
|
||||
static int STUDY_OPTIONS;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default offset vector size (must be multiple of 3).
|
||||
*/
|
||||
static constexpr int OVEC_SIZE = 63;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Internal vector type used for offsets buffer.
|
||||
*/
|
||||
using OVEC_t = std::vector< int >;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Internal RegularExpression instance.
|
||||
*/
|
||||
pcre * mPCRE{nullptr};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Internal RegularExpression instance.
|
||||
*/
|
||||
pcre_extra * mExtra{nullptr};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Internal buffer used for offsets.
|
||||
*/
|
||||
OVEC_t mOVEC{};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
RxInstance() noexcept = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor (disabled).
|
||||
*/
|
||||
RxInstance(const RxInstance &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
RxInstance(RxInstance && o) noexcept
|
||||
: mPCRE(o.mPCRE), mExtra(o.mExtra), mOVEC(std::move(o.mOVEC)) // Replicate it
|
||||
{
|
||||
o.mPCRE = nullptr; // Take ownership
|
||||
o.mExtra = nullptr; // Take ownership
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Basic constructor.
|
||||
*/
|
||||
explicit RxInstance(StackStrF & pattern)
|
||||
: RxInstance(OPTIONS, STUDY, pattern)
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Basic constructor. With specific options.
|
||||
*/
|
||||
explicit RxInstance(int options, StackStrF & pattern)
|
||||
: RxInstance(options, STUDY, pattern)
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Basic constructor. With specific options.
|
||||
*/
|
||||
explicit RxInstance(int options, bool study, StackStrF & pattern)
|
||||
: mPCRE(Compile_(pattern.mPtr, options)), mExtra(nullptr)
|
||||
{
|
||||
if (study)
|
||||
{
|
||||
Study0();
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Internal constructor.
|
||||
*/
|
||||
RxInstance(const char * pattern, int options, bool study)
|
||||
: mPCRE(Compile_(pattern, options)), mExtra(nullptr)
|
||||
{
|
||||
if (study)
|
||||
{
|
||||
Study0();
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~RxInstance()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator (disabled).
|
||||
*/
|
||||
RxInstance & operator = (const RxInstance &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
RxInstance & operator = (RxInstance && o) noexcept
|
||||
{
|
||||
// Prevent self assignment
|
||||
if (this != &o)
|
||||
{
|
||||
// Release current instance, if any
|
||||
Destroy();
|
||||
// Replicate it
|
||||
mPCRE = o.mPCRE;
|
||||
mExtra = o.mExtra;
|
||||
mOVEC = std::move(o.mOVEC);
|
||||
// Take ownership
|
||||
o.mPCRE = nullptr;
|
||||
o.mExtra = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Estimate the size necessary for the offsets vector buffer.
|
||||
*/
|
||||
void EstimateOVEC(bool force = false)
|
||||
{
|
||||
if (mOVEC.empty() || force)
|
||||
{
|
||||
int size = 0;
|
||||
// Attempt to estimate the size of the offsets vector buffer
|
||||
const int r = pcre_fullinfo(ValidPCRE(), mExtra, PCRE_INFO_CAPTURECOUNT, &size);
|
||||
// Check for errors
|
||||
if (r != 0)
|
||||
{
|
||||
STHROWF("Rx: Offsets vector buffer estimation failed ({})", r);
|
||||
}
|
||||
// Attempt to scale the vector (must be multiple of 3)
|
||||
mOVEC.resize((size + 1) * 3);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return a valid `pcre` instance pointer or throw an exception.
|
||||
*/
|
||||
SQMOD_NODISCARD pcre * ValidPCRE() const
|
||||
{
|
||||
// Do we manage a valid instance?
|
||||
if (mPCRE == nullptr)
|
||||
{
|
||||
STHROWF("Uninitialized Regular Expression instance.");
|
||||
}
|
||||
// Return it
|
||||
return mPCRE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return a valid `pcre_extra` instance pointer or throw an exception.
|
||||
*/
|
||||
SQMOD_NODISCARD pcre_extra * ValidExtra() const
|
||||
{
|
||||
// Do we manage a valid instance?
|
||||
if (mExtra == nullptr)
|
||||
{
|
||||
STHROWF("Regular Expression was not studied and optimized.");
|
||||
}
|
||||
// Return it
|
||||
return mExtra;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Compile the specified pattern.
|
||||
*/
|
||||
SQMOD_NODISCARD static pcre * Compile_(const char * pattern, int options = OPTIONS)
|
||||
{
|
||||
const char * error_msg = nullptr;
|
||||
int error_code, error_offset = 0;
|
||||
// Attempt to compile the specified pattern
|
||||
pcre * ptr = pcre_compile2(pattern, options, &error_code, &error_msg, &error_offset, nullptr);
|
||||
// Did the compilation failed?
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
STHROWF("Rx: {s} (code {}) (at offset {})", error_msg, error_code, error_offset);
|
||||
}
|
||||
// Return the `pcre` instance
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to compile the specified pattern. Error information is returned instead of thrown.
|
||||
*/
|
||||
SQMOD_NODISCARD static std::pair< pcre *, Table > TryCompile_(const char * pattern, int options = OPTIONS)
|
||||
{
|
||||
const char * error_msg = nullptr;
|
||||
int error_code, error_offset = 0;
|
||||
// Attempt to compile the specified pattern
|
||||
pcre * ptr = pcre_compile2(pattern, options, &error_code, &error_msg, &error_offset, nullptr);
|
||||
// Did the compilation failed?
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
Table t;
|
||||
t.SetValue("message", error_msg);
|
||||
t.SetValue("code", error_code);
|
||||
t.SetValue("offset", error_offset);
|
||||
// Return the table with error information
|
||||
return std::make_pair(ptr, std::move(t));
|
||||
}
|
||||
// Return the `pcre` instance with no error information
|
||||
return std::make_pair(ptr, Table{});
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Compile the specified pattern.
|
||||
*/
|
||||
RxInstance & Compile1(StackStrF & pattern)
|
||||
{
|
||||
return Compile2(OPTIONS, pattern);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Compile the specified pattern. With specific options.
|
||||
*/
|
||||
RxInstance & Compile2(int options, StackStrF & pattern)
|
||||
{
|
||||
// Release current instance, if any
|
||||
Destroy();
|
||||
// Attempt to compile
|
||||
mPCRE = Compile_(pattern.mPtr, options);
|
||||
// Allocate offsets vector buffer
|
||||
EstimateOVEC();
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Compile the specified pattern.
|
||||
*/
|
||||
Table TryCompile1(StackStrF & pattern)
|
||||
{
|
||||
return TryCompile2(OPTIONS, pattern);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Compile the specified pattern. With specific options.
|
||||
*/
|
||||
Table TryCompile2(int options, StackStrF & pattern)
|
||||
{
|
||||
// Release current instance, if any
|
||||
Destroy();
|
||||
// Attempt to compile
|
||||
auto p = TryCompile_(pattern.mPtr, options);
|
||||
// Were there any compilation errors?
|
||||
if (p.first != nullptr)
|
||||
{
|
||||
mPCRE = p.first;
|
||||
}
|
||||
// Return compilation info
|
||||
return p.second;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Analyze the managed pattern and optimized it.
|
||||
*/
|
||||
RxInstance & Study0()
|
||||
{
|
||||
return Study1(STUDY_OPTIONS);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Analyze the managed pattern and optimized it. With specific options.
|
||||
*/
|
||||
RxInstance & Study1(int options)
|
||||
{
|
||||
if (mExtra != nullptr)
|
||||
{
|
||||
STHROWF("Regular Expression was already analyzed and optimized");
|
||||
}
|
||||
const char * error = nullptr;
|
||||
// Study and optimize the expression
|
||||
mExtra = pcre_study(ValidPCRE(), options, &error);
|
||||
// If there was an error studying the expression then throw it
|
||||
if (mExtra == nullptr && error != nullptr)
|
||||
{
|
||||
STHROWF("Rx: {s}", error);
|
||||
}
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Release managed resources and revert to uninitialized instance.
|
||||
*/
|
||||
SQMOD_NODISCARD bool IsValid() const
|
||||
{
|
||||
return (mPCRE != nullptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Release managed resources and revert to uninitialized instance.
|
||||
*/
|
||||
SQMOD_NODISCARD bool IsStudied() const
|
||||
{
|
||||
return (mExtra != nullptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Release managed resources and revert to uninitialized instance.
|
||||
*/
|
||||
void Destroy()
|
||||
{
|
||||
// Do we manage any instance?
|
||||
if (mPCRE != nullptr)
|
||||
{
|
||||
pcre_free(mPCRE);
|
||||
mPCRE = nullptr;
|
||||
}
|
||||
// Is the expression optimized?
|
||||
if (mExtra != nullptr)
|
||||
{
|
||||
pcre_free(mExtra);
|
||||
mExtra = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Matches the given subject string against the pattern.
|
||||
* Returns the position of the first captured sub-string in m.
|
||||
* If no part of the subject matches the pattern, m.mOffset is -1 and m.mLength is 0.
|
||||
* Returns the number of matches. Throws a exception in case of an error.
|
||||
*/
|
||||
SQMOD_NODISCARD int MatchFirstFrom(SQInteger o, RxMatch & m, StackStrF & s)
|
||||
{
|
||||
return MatchFirstFrom_(OPTIONS, o, m, s);
|
||||
}
|
||||
SQMOD_NODISCARD int MatchFirstFrom_(int f, SQInteger o, RxMatch & m, StackStrF & s)
|
||||
{
|
||||
if (o > s.mLen)
|
||||
{
|
||||
STHROWF("Rx: Offset is out of range");
|
||||
}
|
||||
EstimateOVEC();
|
||||
// Attempt to execute the expression on the specified subject
|
||||
const int rc = pcre_exec(ValidPCRE(), mExtra, s.mPtr, static_cast< int >(s.mLen), static_cast< int >(o), f & 0xFFFF, mOVEC.data(), static_cast< int >(mOVEC.size()));
|
||||
// Was there a match?
|
||||
if (rc == PCRE_ERROR_NOMATCH)
|
||||
{
|
||||
m.mOffset = -1;
|
||||
m.mLength = 0;
|
||||
// No match found
|
||||
return 0;
|
||||
}
|
||||
// Bad options/flags?
|
||||
else if (rc == PCRE_ERROR_BADOPTION)
|
||||
{
|
||||
STHROWF("Rx: Bad option");
|
||||
}
|
||||
// Overflow?
|
||||
else if (rc == 0)
|
||||
{
|
||||
STHROWF("Rx: too many captured sub-strings");
|
||||
}
|
||||
// Some other error?
|
||||
else if (rc < 0)
|
||||
{
|
||||
STHROWF("Rx: error {}", rc);
|
||||
}
|
||||
// Store match
|
||||
m.mOffset = mOVEC[0];
|
||||
m.mLength = mOVEC[1] - mOVEC[0];
|
||||
// Yield result back to script
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Matches the given subject string against the pattern.
|
||||
* Returns the position of the first captured sub-string in m.
|
||||
* If no part of the subject matches the pattern, m.mOffset is -1 and m.mLength is 0.
|
||||
* Returns the number of matches. Throws a exception in case of an error.
|
||||
*/
|
||||
SQMOD_NODISCARD int MatchFirst(RxMatch & m, StackStrF & s)
|
||||
{
|
||||
return MatchFirstFrom_(OPTIONS, 0, m, s);
|
||||
}
|
||||
SQMOD_NODISCARD int MatchFirst_(int f, RxMatch & m, StackStrF & s)
|
||||
{
|
||||
return MatchFirstFrom_(f, 0, m, s);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Matches the given subject string against the pattern.
|
||||
* The first entry in m contains the position of the captured sub-string.
|
||||
* The following entries identify matching sub-patterns. See the PCRE documentation for a more detailed explanation.
|
||||
* If no part of the subject matches the pattern, m is empty.
|
||||
* Returns the number of matches. Throws an exception in case of an error.
|
||||
*/
|
||||
SQMOD_NODISCARD int MatchFrom(SQInteger o, RxMatches & m, StackStrF & s)
|
||||
{
|
||||
return MatchFrom_(OPTIONS, o, m, s);
|
||||
}
|
||||
SQMOD_NODISCARD int MatchFrom_(int f, SQInteger o, RxMatches & m, StackStrF & s)
|
||||
{
|
||||
if (o > s.mLen)
|
||||
{
|
||||
STHROWF("Rx: Offset is out of range");
|
||||
}
|
||||
EstimateOVEC();
|
||||
// Clear previous matches, if any
|
||||
m.mList.clear();
|
||||
// Attempt to execute the expression on the specified subject
|
||||
const int rc = pcre_exec(ValidPCRE(), mExtra, s.mPtr, static_cast< int >(s.mLen), static_cast< int >(o), f & 0xFFFF, mOVEC.data(), static_cast< int >(mOVEC.size()));
|
||||
// Was there a match?
|
||||
if (rc == PCRE_ERROR_NOMATCH)
|
||||
{
|
||||
return 0; // No match found
|
||||
}
|
||||
// Bad options/flags?
|
||||
else if (rc == PCRE_ERROR_BADOPTION)
|
||||
{
|
||||
STHROWF("Rx: Bad option");
|
||||
}
|
||||
// Overflow?
|
||||
else if (rc == 0)
|
||||
{
|
||||
STHROWF("Rx: too many captured sub-strings");
|
||||
}
|
||||
// Some other error?
|
||||
else if (rc < 0)
|
||||
{
|
||||
STHROWF("Rx: error {}", rc);
|
||||
}
|
||||
// Reserve space in advance
|
||||
m.mList.reserve(static_cast< size_t >(rc));
|
||||
// Transfer matches to match-list
|
||||
for (int i = 0; i < rc; ++i)
|
||||
{
|
||||
m.mList.emplace_back(mOVEC[i*2], mOVEC[i*2+1] - mOVEC[i*2]);
|
||||
}
|
||||
// Yield result back to script
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Matches the given subject string against the pattern.
|
||||
* The first entry in m contains the position of the captured sub-string.
|
||||
* The following entries identify matching sub-patterns. See the PCRE documentation for a more detailed explanation.
|
||||
* If no part of the subject matches the pattern, m is empty.
|
||||
* Returns the number of matches. Throws an exception in case of an error.
|
||||
*/
|
||||
SQMOD_NODISCARD int Match(RxMatches & m, StackStrF & s)
|
||||
{
|
||||
return MatchFrom_(OPTIONS, 0, m, s);
|
||||
}
|
||||
SQMOD_NODISCARD int Match_(int f, RxMatches & m, StackStrF & s)
|
||||
{
|
||||
return MatchFrom_(f, 0, m, s);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Returns true if and only if the subject matches the regular expression.
|
||||
* Internally, this method sets the RE_ANCHORED and RE_NOTEMPTY options for matching,
|
||||
* which means that the empty string will never match and the pattern is treated as if it starts with a ^.
|
||||
*/
|
||||
SQMOD_NODISCARD bool Matches(StackStrF & s)
|
||||
{
|
||||
return Matches_(PCRE_ANCHORED | PCRE_NOTEMPTY, s);
|
||||
}
|
||||
SQMOD_NODISCARD bool Matches_(SQInteger o, StackStrF & s)
|
||||
{
|
||||
return MatchesEx(PCRE_ANCHORED | PCRE_NOTEMPTY, 0, s);
|
||||
}
|
||||
SQMOD_NODISCARD bool MatchesEx(int f, SQInteger o, StackStrF & s)
|
||||
{
|
||||
RxMatch m;
|
||||
const int rc = MatchFirstFrom_(f, o, m, s);
|
||||
return (rc > 0) && (m.mOffset == o) && (m.mLength == (s.mLen - o));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // Namespace:: SqMod
|
||||
+189
-149
File diff suppressed because it is too large
Load Diff
+130
-66
@@ -2,15 +2,19 @@
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Core/Utility.hpp"
|
||||
#include "Core/ThreadPool.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/IO/Buffer.hpp"
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
#include "Library/Chrono/Date.hpp"
|
||||
#include "Library/Chrono/Datetime.hpp"
|
||||
#include "Library/Chrono/Time.hpp"
|
||||
#include "Library/Chrono/Timestamp.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/Data/SessionImpl.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -79,28 +83,28 @@ struct SQLiteStmtHnd;
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Common typedefs.
|
||||
*/
|
||||
typedef SharedPtr< SQLiteConnHnd > ConnRef;
|
||||
typedef SharedPtr< SQLiteStmtHnd > StmtRef;
|
||||
typedef SharedPtr< SQLiteConnHnd > SQLiteConnRef;
|
||||
typedef SharedPtr< SQLiteStmtHnd > SQLiteStmtRef;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Obtain a script object from a connection handle. (meant to avoid having to include the header)
|
||||
*/
|
||||
Object GetConnectionObj(const ConnRef & conn);
|
||||
Object GetConnectionObj(const SQLiteConnRef & conn);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Obtain a script object from a statement handle. (meant to avoid having to include the header)
|
||||
*/
|
||||
Object GetStatementObj(const StmtRef & stmt);
|
||||
Object GetStatementObj(const SQLiteStmtRef & stmt);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Tests if a certain query string is empty.
|
||||
*/
|
||||
bool IsQueryEmpty(const SQChar * str);
|
||||
SQMOD_NODISCARD bool IsQueryEmpty(const SQChar * str);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the string representation of a certain status code.
|
||||
*/
|
||||
const SQChar * GetErrStr(int32_t status);
|
||||
SQMOD_NODISCARD const SQChar * GetErrStr(int32_t status);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Set a specific heap limit.
|
||||
@@ -115,32 +119,32 @@ int32_t ReleaseMemory(int32_t bytes);
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the current memory usage.
|
||||
*/
|
||||
Object GetMemoryUsage();
|
||||
SQMOD_NODISCARD SQInteger GetMemoryUsage();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the memory high watermark.
|
||||
*/
|
||||
Object GetMemoryHighwaterMark(bool reset);
|
||||
SQMOD_NODISCARD SQInteger GetMemoryHighwaterMark(bool reset);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the escaped version of the specified string.
|
||||
*/
|
||||
LightObj EscapeString(StackStrF & str);
|
||||
SQMOD_NODISCARD LightObj EscapeString(StackStrF & str);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the escaped version of the specified string using the supplied format specifier.
|
||||
*/
|
||||
LightObj EscapeStringEx(SQChar spec, StackStrF & str);
|
||||
SQMOD_NODISCARD LightObj EscapeStringEx(SQChar spec, StackStrF & str);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Convert the values from the specified array to a list of column names string.
|
||||
*/
|
||||
LightObj ArrayToQueryColumns(Array & arr);
|
||||
SQMOD_NODISCARD LightObj ArrayToQueryColumns(Array & arr);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Convert the keys from the specified array to a list of column names string.
|
||||
*/
|
||||
LightObj TableToQueryColumns(Table & tbl);
|
||||
SQMOD_NODISCARD LightObj TableToQueryColumns(Table & tbl);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* The structure that holds the data associated with a certain connection.
|
||||
@@ -179,6 +183,9 @@ public:
|
||||
String mName; // The specified name to be used as the database file.
|
||||
String mVFS; // The specified virtual file system.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Poco::AutoPtr< Poco::Data::SessionImpl > mSession; // POCO session when this connection comes from a pool.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
bool mMemory; // Whether the database exists in memory and not disk.
|
||||
bool mTrace; // Whether tracing was activated on the database.
|
||||
@@ -189,6 +196,16 @@ public:
|
||||
*/
|
||||
SQLiteConnHnd();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
explicit SQLiteConnHnd(Poco::Data::SessionImpl * session);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
explicit SQLiteConnHnd(Poco::AutoPtr< Poco::Data::SessionImpl > && session);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
*/
|
||||
@@ -255,6 +272,20 @@ public:
|
||||
{
|
||||
return sqlite3_extended_errcode(mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Access the connection pointer.
|
||||
*/
|
||||
SQMOD_NODISCARD Pointer Access() const
|
||||
{
|
||||
if (!mSession.isNull()) {
|
||||
// Only reason this is necessary is to dirty the connection handle access time-stamp
|
||||
// So it won't be closed/collected when it comes from a connection/session-pool
|
||||
[[maybe_unused]] auto _ = mSession->isConnected();
|
||||
}
|
||||
// We yield access to the pointer anyway
|
||||
return mPtr;
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -287,7 +318,7 @@ public:
|
||||
int32_t mStatus; // The last status code of this connection handle.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ConnRef mConn; // The handle to the associated database connection.
|
||||
SQLiteConnRef mConnection; // The handle to the associated database connection.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
String mQuery; // The query string used to create this statement.
|
||||
@@ -304,7 +335,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
explicit SQLiteStmtHnd(ConnRef conn);
|
||||
explicit SQLiteStmtHnd(SQLiteConnRef conn);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
@@ -376,6 +407,20 @@ public:
|
||||
* Return the extended numeric result code for the most recent failed API call (if any).
|
||||
*/
|
||||
SQMOD_NODISCARD int32_t ExErrNo() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Access the statement pointer.
|
||||
*/
|
||||
SQMOD_NODISCARD Pointer Access() const
|
||||
{
|
||||
if (bool(mConnection) && !(mConnection->mSession.isNull())) {
|
||||
// Only reason this is necessary is to dirty the connection handle access time-stamp
|
||||
// So it won't be closed/collected when it comes from a connection/session-pool
|
||||
[[maybe_unused]] auto _ = mConnection->mSession->isConnected();
|
||||
}
|
||||
// We yield access to the pointer anyway
|
||||
return mPtr;
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -386,7 +431,7 @@ class SQLiteConnection
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ConnRef m_Handle; // Reference to the managed connection.
|
||||
SQLiteConnRef m_Handle; // Reference to the managed connection.
|
||||
|
||||
protected:
|
||||
|
||||
@@ -422,18 +467,18 @@ protected:
|
||||
* Validate the managed connection handle and throw an error if invalid.
|
||||
*/
|
||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
||||
SQMOD_NODISCARD const ConnRef & GetValid(const char * file, int32_t line) const;
|
||||
SQMOD_NODISCARD const SQLiteConnRef & GetValid(const char * file, int32_t line) const;
|
||||
#else
|
||||
SQMOD_NODISCARD const ConnRef & GetValid() const;
|
||||
SQMOD_NODISCARD const SQLiteConnRef & GetValid() const;
|
||||
#endif // _DEBUG
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the managed connection handle and throw an error if invalid.
|
||||
*/
|
||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
||||
SQMOD_NODISCARD const ConnRef & GetCreated(const char * file, int32_t line) const;
|
||||
SQMOD_NODISCARD const SQLiteConnRef & GetCreated(const char * file, int32_t line) const;
|
||||
#else
|
||||
SQMOD_NODISCARD const ConnRef & GetCreated() const;
|
||||
SQMOD_NODISCARD const SQLiteConnRef & GetCreated() const;
|
||||
#endif // _DEBUG
|
||||
|
||||
public:
|
||||
@@ -480,7 +525,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Direct handle constructor.
|
||||
*/
|
||||
explicit SQLiteConnection(ConnRef c)
|
||||
explicit SQLiteConnection(SQLiteConnRef c)
|
||||
: m_Handle(std::move(c))
|
||||
{
|
||||
/* ... */
|
||||
@@ -527,7 +572,7 @@ public:
|
||||
*/
|
||||
operator sqlite3 * () //NOLINT (intentionally implicit)
|
||||
{
|
||||
return m_Handle ? m_Handle->mPtr : nullptr;
|
||||
return m_Handle ? m_Handle->Access() : nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -535,7 +580,7 @@ public:
|
||||
*/
|
||||
operator sqlite3 * () const //NOLINT (intentionally implicit)
|
||||
{
|
||||
return m_Handle ? m_Handle->mPtr : nullptr;
|
||||
return m_Handle ? m_Handle->Access() : nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -549,7 +594,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated connection handle.
|
||||
*/
|
||||
SQMOD_NODISCARD const ConnRef & GetHandle() const
|
||||
SQMOD_NODISCARD const SQLiteConnRef & GetHandle() const
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
@@ -567,7 +612,7 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD bool IsConnected() const
|
||||
{
|
||||
return m_Handle && (m_Handle->mPtr != nullptr);
|
||||
return m_Handle && (m_Handle->Access() != nullptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -680,6 +725,16 @@ public:
|
||||
*/
|
||||
Object Query(StackStrF & str) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to execute the specified query asynchronously.
|
||||
*/
|
||||
LightObj AsyncExec(StackStrF & str);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to create a statement from the specified query asynchronously.
|
||||
*/
|
||||
LightObj AsyncQuery(StackStrF & str) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See if the database connection was opened in read-only mode.
|
||||
*/
|
||||
@@ -701,9 +756,9 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Get the row-id of the most recent successful INSERT into the database from the current connection.
|
||||
*/
|
||||
SQMOD_NODISCARD Object GetLastInsertRowID() const
|
||||
SQMOD_NODISCARD SQInteger GetLastInsertRowID() const
|
||||
{
|
||||
return Object(new SLongInt(sqlite3_last_insert_rowid(SQMOD_GET_CREATED(*this)->mPtr)));
|
||||
return sqlite3_last_insert_rowid(SQMOD_GET_CREATED(*this)->mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -858,8 +913,8 @@ class SQLiteParameter
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
int32_t m_Index{0}; // The index of the managed parameter.
|
||||
StmtRef m_Handle{}; // Reference to the managed statement.
|
||||
int32_t m_Index{0}; // The index of the managed parameter.
|
||||
SQLiteStmtRef m_Handle{}; // Reference to the managed statement.
|
||||
|
||||
protected:
|
||||
|
||||
@@ -885,18 +940,18 @@ protected:
|
||||
* Validate the managed statement handle and throw an error if invalid.
|
||||
*/
|
||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
||||
SQMOD_NODISCARD const StmtRef & GetValid(const char * file, int32_t line) const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetValid(const char * file, int32_t line) const;
|
||||
#else
|
||||
SQMOD_NODISCARD const StmtRef & GetValid() const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetValid() const;
|
||||
#endif // _DEBUG
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the managed statement handle and throw an error if invalid.
|
||||
*/
|
||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
||||
SQMOD_NODISCARD const StmtRef & GetCreated(const char * file, int32_t line) const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetCreated(const char * file, int32_t line) const;
|
||||
#else
|
||||
SQMOD_NODISCARD const StmtRef & GetCreated() const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetCreated() const;
|
||||
#endif // _DEBUG
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -944,7 +999,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* No parameter constructor.
|
||||
*/
|
||||
explicit SQLiteParameter(StmtRef stmt)
|
||||
explicit SQLiteParameter(SQLiteStmtRef stmt)
|
||||
: m_Index(0), m_Handle(std::move(stmt))
|
||||
{
|
||||
/* ... */
|
||||
@@ -953,7 +1008,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Index constructor.
|
||||
*/
|
||||
SQLiteParameter(StmtRef stmt, int32_t idx)
|
||||
SQLiteParameter(SQLiteStmtRef stmt, int32_t idx)
|
||||
: m_Index(idx), m_Handle(std::move(stmt))
|
||||
{
|
||||
SQMOD_VALIDATE_PARAM(*this, m_Index);
|
||||
@@ -962,7 +1017,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Name constructor.
|
||||
*/
|
||||
SQLiteParameter(const StmtRef & stmt, const SQChar * name)
|
||||
SQLiteParameter(const SQLiteStmtRef & stmt, const SQChar * name)
|
||||
: m_Index(stmt ? sqlite3_bind_parameter_index(stmt->mPtr, name) : 0), m_Handle(stmt)
|
||||
{
|
||||
SQMOD_VALIDATE_PARAM(*this, m_Index);
|
||||
@@ -971,7 +1026,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Dynamic constructor.
|
||||
*/
|
||||
SQLiteParameter(StmtRef stmt, const Object & param)
|
||||
SQLiteParameter(SQLiteStmtRef stmt, const Object & param)
|
||||
: m_Index(0), m_Handle(std::move(stmt))
|
||||
{
|
||||
if (!m_Handle)
|
||||
@@ -1034,7 +1089,7 @@ public:
|
||||
// Can we attempt to return the parameter name?
|
||||
if (m_Handle && m_Index)
|
||||
{
|
||||
const SQChar * val = sqlite3_bind_parameter_name(m_Handle->mPtr, m_Index);
|
||||
const SQChar * val = sqlite3_bind_parameter_name(m_Handle->Access(), m_Index);
|
||||
// Return the value if valid
|
||||
return val ? val : String{};
|
||||
}
|
||||
@@ -1148,12 +1203,12 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind a signed 64 bit integer value at the referenced parameter index.
|
||||
*/
|
||||
void SetInt64(const Object & value);
|
||||
void SetInt64(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind an unsigned 64 bit integer value at the referenced parameter index.
|
||||
*/
|
||||
void SetUint64(const Object & value);
|
||||
void SetUint64(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind a native floating point value at the referenced parameter index.
|
||||
@@ -1253,7 +1308,7 @@ private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
int32_t m_Index{-1}; // The index of the managed column.
|
||||
StmtRef m_Handle{}; // The statement where the column exist.
|
||||
SQLiteStmtRef m_Handle{}; // The statement where the column exist.
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1279,18 +1334,18 @@ protected:
|
||||
* Validate the managed statement handle and throw an error if invalid.
|
||||
*/
|
||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
||||
SQMOD_NODISCARD const StmtRef & GetValid(const char * file, int32_t line) const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetValid(const char * file, int32_t line) const;
|
||||
#else
|
||||
SQMOD_NODISCARD const StmtRef & GetValid() const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetValid() const;
|
||||
#endif // _DEBUG
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the managed statement handle and throw an error if invalid.
|
||||
*/
|
||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
||||
SQMOD_NODISCARD const StmtRef & GetCreated(const char * file, int32_t line) const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetCreated(const char * file, int32_t line) const;
|
||||
#else
|
||||
SQMOD_NODISCARD const StmtRef & GetCreated() const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetCreated() const;
|
||||
#endif // _DEBUG
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1347,7 +1402,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* No column constructor.
|
||||
*/
|
||||
explicit SQLiteColumn(StmtRef stmt)
|
||||
explicit SQLiteColumn(SQLiteStmtRef stmt)
|
||||
: m_Index(-1), m_Handle(std::move(stmt))
|
||||
{
|
||||
/* ... */
|
||||
@@ -1356,7 +1411,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Index constructor.
|
||||
*/
|
||||
SQLiteColumn(StmtRef stmt, int32_t idx)
|
||||
SQLiteColumn(SQLiteStmtRef stmt, int32_t idx)
|
||||
: m_Index(idx), m_Handle(std::move(stmt))
|
||||
{
|
||||
SQMOD_VALIDATE_COLUMN(*this, m_Index);
|
||||
@@ -1365,7 +1420,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Name constructor.
|
||||
*/
|
||||
SQLiteColumn(const StmtRef & stmt, const SQChar * name)
|
||||
SQLiteColumn(const SQLiteStmtRef & stmt, const SQChar * name)
|
||||
: m_Index(stmt ? stmt->GetColumnIndex(name) : -1), m_Handle(stmt)
|
||||
{
|
||||
SQMOD_VALIDATE_COLUMN(*this, m_Index);
|
||||
@@ -1374,7 +1429,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Dynamic constructor.
|
||||
*/
|
||||
SQLiteColumn(StmtRef stmt, const Object & column)
|
||||
SQLiteColumn(SQLiteStmtRef stmt, const Object & column)
|
||||
: m_Index(-1), m_Handle(std::move(stmt))
|
||||
{
|
||||
if (!m_Handle)
|
||||
@@ -1437,7 +1492,7 @@ public:
|
||||
// Can we attempt to return the parameter name?
|
||||
if (m_Handle && m_Index)
|
||||
{
|
||||
const SQChar * val = sqlite3_column_name(m_Handle->mPtr, m_Index);
|
||||
const SQChar * val = sqlite3_column_name(m_Handle->Access(), m_Index);
|
||||
// Return the value if valid
|
||||
return val ? val : String{};
|
||||
}
|
||||
@@ -1538,7 +1593,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the referenced column as a long integer.
|
||||
*/
|
||||
SQMOD_NODISCARD Object GetLong() const;
|
||||
SQMOD_NODISCARD SQInteger GetLong() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the referenced column as a string.
|
||||
@@ -1574,7 +1629,7 @@ class SQLiteStatement
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
StmtRef m_Handle; // Reference to the managed statement.
|
||||
SQLiteStmtRef m_Handle; // Reference to the managed statement.
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1600,18 +1655,18 @@ protected:
|
||||
* Validate the managed statement handle and throw an error if invalid.
|
||||
*/
|
||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
||||
SQMOD_NODISCARD const StmtRef & GetValid(const char * file, int32_t line) const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetValid(const char * file, int32_t line) const;
|
||||
#else
|
||||
SQMOD_NODISCARD const StmtRef & GetValid() const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetValid() const;
|
||||
#endif // _DEBUG
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the managed statement handle and throw an error if invalid.
|
||||
*/
|
||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
||||
SQMOD_NODISCARD const StmtRef & GetCreated(const char * file, int32_t line) const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetCreated(const char * file, int32_t line) const;
|
||||
#else
|
||||
SQMOD_NODISCARD const StmtRef & GetCreated() const;
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetCreated() const;
|
||||
#endif // _DEBUG
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1655,12 +1710,21 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Construct a statement under the specified connection using the specified string.
|
||||
*/
|
||||
SQLiteStatement(const ConnRef & connection, StackStrF & query)
|
||||
SQLiteStatement(const SQLiteConnRef & connection, StackStrF & query)
|
||||
: m_Handle(new SQLiteStmtHnd(connection))
|
||||
{
|
||||
SQMOD_GET_VALID(*this)->Create(query.mPtr, query.mLen);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Construct a statement under the specified connection using the specified string.
|
||||
*/
|
||||
SQLiteStatement(const SQLiteConnRef & connection, const SQChar * query, SQInteger length)
|
||||
: m_Handle(new SQLiteStmtHnd(connection))
|
||||
{
|
||||
SQMOD_GET_VALID(*this)->Create(query, length);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Construct a statement under the specified connection using the specified string.
|
||||
*/
|
||||
@@ -1669,7 +1733,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Direct handle constructor.
|
||||
*/
|
||||
explicit SQLiteStatement(StmtRef s)
|
||||
explicit SQLiteStatement(SQLiteStmtRef s)
|
||||
: m_Handle(std::move(s))
|
||||
{
|
||||
/* ... */
|
||||
@@ -1716,7 +1780,7 @@ public:
|
||||
*/
|
||||
operator sqlite3_stmt * () // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
{
|
||||
return m_Handle ? m_Handle->mPtr : nullptr;
|
||||
return m_Handle ? m_Handle->Access() : nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1724,7 +1788,7 @@ public:
|
||||
*/
|
||||
operator sqlite3_stmt * () const // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
{
|
||||
return m_Handle ? m_Handle->mPtr : nullptr;
|
||||
return m_Handle ? m_Handle->Access() : nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1738,7 +1802,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated statement handle.
|
||||
*/
|
||||
SQMOD_NODISCARD const StmtRef & GetHandle() const
|
||||
SQMOD_NODISCARD const SQLiteStmtRef & GetHandle() const
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
@@ -1756,7 +1820,7 @@ public:
|
||||
*/
|
||||
SQMOD_NODISCARD bool IsPrepared() const
|
||||
{
|
||||
return m_Handle && (m_Handle->mPtr != nullptr);
|
||||
return m_Handle && (m_Handle->Access() != nullptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -2101,7 +2165,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind a signed 64 bit integer value at the specified parameter index.
|
||||
*/
|
||||
SQLiteStatement & SetInt64(const Object & param, const Object & value)
|
||||
SQLiteStatement & SetInt64(const Object & param, SQInteger value)
|
||||
{
|
||||
SQLiteParameter(SQMOD_GET_CREATED(*this), param).SetInt64(value);
|
||||
// Allow chaining of operations
|
||||
@@ -2111,7 +2175,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind an unsigned 64 bit integer value at the specified parameter index.
|
||||
*/
|
||||
SQLiteStatement & SetUint64(const Object & param, const Object & value)
|
||||
SQLiteStatement & SetUint64(const Object & param, SQInteger value)
|
||||
{
|
||||
SQLiteParameter(SQMOD_GET_CREATED(*this), param).SetUint64(value);
|
||||
// Allow chaining of operations
|
||||
@@ -2437,7 +2501,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Construct using the direct connection handle.
|
||||
*/
|
||||
explicit SQLiteTransaction(ConnRef db);
|
||||
explicit SQLiteTransaction(SQLiteConnRef db);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
@@ -2496,7 +2560,7 @@ public:
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ConnRef m_Handle{}; // The database connection handle where the transaction began.
|
||||
SQLiteConnRef m_Handle{}; // The database connection handle where the transaction began.
|
||||
bool m_Committed{false}; // Whether changes were successfully committed to the database.
|
||||
};
|
||||
|
||||
|
||||
+175
-10
@@ -189,7 +189,7 @@ static LightObj SqCenterStr(SQChar f, uint32_t w, StackStrF & s)
|
||||
else
|
||||
{
|
||||
// Calculate the insert position
|
||||
const int32_t p = ((w/2) - (s.mLen/2));
|
||||
const auto p = ((w/2) - (s.mLen/2));
|
||||
// Insert only the fill character first
|
||||
std::memset(b.Data(), f, w);
|
||||
// Overwrite with the specified string
|
||||
@@ -287,7 +287,7 @@ static Buffer StrToLowercaseImpl(const SQChar * str, uint32_t len)
|
||||
while (*str != '\0')
|
||||
{
|
||||
// Convert it and move to the next one
|
||||
b.At(n++) = std::tolower(*(str++));
|
||||
b.At(n++) = static_cast< char >(std::tolower(*(str++)));
|
||||
}
|
||||
// End the resulted string
|
||||
b.At(n) = '\0';
|
||||
@@ -349,7 +349,7 @@ static Buffer StrToUppercaseImpl(const SQChar * str, uint32_t len)
|
||||
while (*str != '\0')
|
||||
{
|
||||
// Convert it and move to the next one
|
||||
b.At(n++) = std::toupper(*(str++));
|
||||
b.At(n++) = static_cast< char >(std::toupper(*(str++)));
|
||||
}
|
||||
// End the resulted string
|
||||
b.At(n) = '\0';
|
||||
@@ -594,7 +594,7 @@ static bool OnlyDelimiter(const SQChar * str, SQChar chr)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqStrExplode(HSQUIRRELVM vm)
|
||||
{
|
||||
const int32_t top = sq_gettop(vm);
|
||||
const auto top = sq_gettop(vm);
|
||||
// Was the delimiter character specified?
|
||||
if (top <= 1)
|
||||
{
|
||||
@@ -899,17 +899,79 @@ static String StrCharacterSwap(SQInteger a, SQInteger b, StackStrF & val)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqStrToI(SQInteger base, StackStrF & s)
|
||||
// Returns a size_t, depicting the difference between `a` and `b`. See: https://github.com/wooorm/levenshtein.c
|
||||
// See <https://en.wikipedia.org/wiki/Levenshtein_distance> for more information.
|
||||
SQMOD_NODISCARD static size_t Levenshtein_n(const char * a, const size_t a_length, const char * b, const size_t b_length) noexcept
|
||||
{
|
||||
// Shortcut optimizations / degenerate cases.
|
||||
if (a == b)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (a_length == 0)
|
||||
{
|
||||
return b_length;
|
||||
}
|
||||
else if (b_length == 0)
|
||||
{
|
||||
return a_length;
|
||||
}
|
||||
auto cache = reinterpret_cast< size_t * >(calloc(a_length, sizeof(size_t)));
|
||||
size_t index = 0;
|
||||
size_t b_index = 0;
|
||||
size_t distance;
|
||||
size_t b_distance;
|
||||
size_t result;
|
||||
char code;
|
||||
// initialize the vector.
|
||||
while (index < a_length)
|
||||
{
|
||||
cache[index] = index + 1;
|
||||
index++;
|
||||
}
|
||||
// Loop
|
||||
while (b_index < b_length)
|
||||
{
|
||||
code = b[b_index];
|
||||
result = distance = b_index++;
|
||||
index = SIZE_MAX;
|
||||
|
||||
while (++index < a_length)
|
||||
{
|
||||
b_distance = code == a[index] ? distance : distance + 1;
|
||||
distance = cache[index];
|
||||
|
||||
cache[index] = result = distance > result
|
||||
? b_distance > result
|
||||
? result + 1
|
||||
: b_distance
|
||||
: b_distance > distance
|
||||
? distance + 1
|
||||
: b_distance;
|
||||
}
|
||||
}
|
||||
free(cache);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqLevenshtein(StackStrF & a, StackStrF & b)
|
||||
{
|
||||
return static_cast< SQInteger >(Levenshtein_n(a.mPtr, static_cast< size_t >(a.mLen), b.mPtr, static_cast< size_t >(b.mLen)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQInteger SqStringToInt(SQInteger base, StackStrF & s)
|
||||
{
|
||||
#ifdef _SQ64
|
||||
return std::stoll(s.mPtr, nullptr, ConvTo< int >::From((base)));
|
||||
return std::stoll(s.ToStr(), nullptr, ConvTo< int >::From((base)));
|
||||
#else
|
||||
return std::stoi(s.mPtr, nullptr, ConvTo< int >::From((base)));
|
||||
return std::stoi(s.ToStr(), nullptr, ConvTo< int >::From((base)));
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQFloat SqStrToF(StackStrF & s)
|
||||
static SQFloat SqStringToFloat(StackStrF & s)
|
||||
{
|
||||
#ifdef SQUSEDOUBLE
|
||||
return std::strtod(s.mPtr, nullptr);
|
||||
@@ -918,6 +980,102 @@ static SQFloat SqStrToF(StackStrF & s)
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static Table SqStringToL(SQInteger base, StackStrF & s)
|
||||
{
|
||||
SQChar * end = nullptr;
|
||||
// Attempt to process the specified string
|
||||
const auto r = std::strtol(s.mPtr, &end, ConvTo< int >::From((base)));
|
||||
// Allocate a table for the result
|
||||
Table t(SqVM(), 2);
|
||||
// Insert the resulted value
|
||||
t.SetValue(_SC("value"), r);
|
||||
// Insert the end of the value
|
||||
t.SetValue(_SC("end"), static_cast< intptr_t >(end - s.mPtr));
|
||||
// Return the table containing the results
|
||||
return t;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static Table SqStringToLL(SQInteger base, StackStrF & s)
|
||||
{
|
||||
SQChar * end = nullptr;
|
||||
// Attempt to process the specified string
|
||||
const auto r = std::strtoll(s.mPtr, &end, ConvTo< int >::From((base)));
|
||||
// Allocate a table for the result
|
||||
Table t(SqVM(), 2);
|
||||
// Insert the resulted value
|
||||
t.SetValue(_SC("value"), r);
|
||||
// Insert the end of the value
|
||||
t.SetValue(_SC("end"), static_cast< intptr_t >(end - s.mPtr));
|
||||
// Return the table containing the results
|
||||
return t;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static Table SqStringToUL(SQInteger base, StackStrF & s)
|
||||
{
|
||||
SQChar * end = nullptr;
|
||||
// Attempt to process the specified string
|
||||
const auto r = std::strtoul(s.mPtr, &end, ConvTo< int >::From((base)));
|
||||
// Allocate a table for the result
|
||||
Table t(SqVM(), 2);
|
||||
// Insert the resulted value
|
||||
t.SetValue(_SC("value"), r);
|
||||
// Insert the end of the value
|
||||
t.SetValue(_SC("end"), static_cast< intptr_t >(end - s.mPtr));
|
||||
// Return the table containing the results
|
||||
return t;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static Table SqStringToULL(SQInteger base, StackStrF & s)
|
||||
{
|
||||
SQChar * end = nullptr;
|
||||
// Attempt to process the specified string
|
||||
const auto r = std::strtoull(s.mPtr, &end, ConvTo< int >::From((base)));
|
||||
// Allocate a table for the result
|
||||
Table t(SqVM(), 2);
|
||||
// Insert the resulted value
|
||||
t.SetValue(_SC("value"), r);
|
||||
// Insert the end of the value
|
||||
t.SetValue(_SC("end"), static_cast< intptr_t >(end - s.mPtr));
|
||||
// Return the table containing the results
|
||||
return t;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static Table SqStringToF(StackStrF & s)
|
||||
{
|
||||
SQChar * end = nullptr;
|
||||
// Attempt to process the specified string
|
||||
const auto r = std::strtof(s.mPtr, &end);
|
||||
// Allocate a table for the result
|
||||
Table t(SqVM(), 2);
|
||||
// Insert the resulted value
|
||||
t.SetValue(_SC("value"), r);
|
||||
// Insert the end of the value
|
||||
t.SetValue(_SC("end"), static_cast< intptr_t >(end - s.mPtr));
|
||||
// Return the table containing the results
|
||||
return t;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static Table SqStringToD(StackStrF & s)
|
||||
{
|
||||
SQChar * end = nullptr;
|
||||
// Attempt to process the specified string
|
||||
const auto r = std::strtod(s.mPtr, &end);
|
||||
// Allocate a table for the result
|
||||
Table t(SqVM(), 2);
|
||||
// Insert the resulted value
|
||||
t.SetValue(_SC("value"), r);
|
||||
// Insert the end of the value
|
||||
t.SetValue(_SC("end"), static_cast< intptr_t >(end - s.mPtr));
|
||||
// Return the table containing the results
|
||||
return t;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_String(HSQUIRRELVM vm)
|
||||
{
|
||||
@@ -938,8 +1096,15 @@ void Register_String(HSQUIRRELVM vm)
|
||||
.FmtFunc(_SC("Lowercase"), &SqToLowercase)
|
||||
.FmtFunc(_SC("Uppercase"), &SqToUppercase)
|
||||
.FmtFunc(_SC("JustAlnum"), &SqJustAlphaNum)
|
||||
.FmtFunc(_SC("ToInt"), &SqStrToI)
|
||||
.FmtFunc(_SC("ToFloat"), &SqStrToF)
|
||||
.FmtFunc(_SC("ToInt"), &SqStringToInt)
|
||||
.FmtFunc(_SC("ToFloat"), &SqStringToFloat)
|
||||
.FmtFunc(_SC("ToL"), &SqStringToL)
|
||||
.FmtFunc(_SC("ToLL"), &SqStringToLL)
|
||||
.FmtFunc(_SC("ToUL"), &SqStringToUL)
|
||||
.FmtFunc(_SC("ToULL"), &SqStringToULL)
|
||||
.FmtFunc(_SC("ToF"), &SqStringToF)
|
||||
.FmtFunc(_SC("ToD"), &SqStringToD)
|
||||
.FmtFunc(_SC("Levenshtein"), &SqLevenshtein)
|
||||
.FmtFunc(_SC("AreAllSpace"), &SqAllChars< std::isspace >)
|
||||
.FmtFunc(_SC("AreAllPrint"), &SqAllChars< std::isprint >)
|
||||
.FmtFunc(_SC("AreAllCntrl"), &SqAllChars< std::iscntrl >)
|
||||
|
||||
@@ -594,7 +594,7 @@ public:
|
||||
#if defined(UNICODE) || defined(_UNICODE)
|
||||
return String(mHandle->extension, mHandle->extension + std::wcslen(mHandle->extension));
|
||||
#else
|
||||
return String(mHandle->name);
|
||||
return String(mHandle->extension);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/UTF8.hpp"
|
||||
#include "Core/Buffer.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static SQInteger SqStrLenUTF8(StackStrF & str)
|
||||
{
|
||||
// Is the string empty or invalid?
|
||||
if (str.mLen <= 0)
|
||||
{
|
||||
return str.mLen; // Return same value
|
||||
}
|
||||
// Perform the request and return the result
|
||||
return static_cast< SQInteger >(utf8len(str.mPtr));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static SQInteger SqStrNLenUTF8(SQInteger len, StackStrF & str)
|
||||
{
|
||||
// Is the string empty or invalid?
|
||||
if (str.mLen <= 0)
|
||||
{
|
||||
return str.mLen; // Return same value
|
||||
}
|
||||
// Is the specified length within bounds?
|
||||
else if (std::abs(len) > str.mLen)
|
||||
{
|
||||
STHROWF("Specified range {} is out of bounds {}", len, str.mLen);
|
||||
}
|
||||
// Should we compute the length backwards?
|
||||
else if (len < 0)
|
||||
{
|
||||
len = str.mLen - std::abs(len); // Subtract from actual length
|
||||
}
|
||||
// Did we trim all of it?
|
||||
else if (len == 0)
|
||||
{
|
||||
return 0; // Nothing to search for
|
||||
}
|
||||
// Perform the request and return the result
|
||||
return static_cast< SQInteger >(utf8nlen(str.mPtr, static_cast< size_t >(len)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static SQInteger SqStrChrUTF8(SQInteger chr, StackStrF & str)
|
||||
{
|
||||
// Is the string empty or invalid?
|
||||
if (str.mLen <= 0)
|
||||
{
|
||||
return -1; // Let the user know that we could not search for this
|
||||
}
|
||||
// Look for the specified character in the string
|
||||
auto * p = reinterpret_cast< const SQChar * >(utf8chr(str.mPtr, static_cast< utf8_int32_t >(chr)));
|
||||
// Return the distance in bytes where the character was found
|
||||
return static_cast< SQInteger >(p - str.mPtr);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static SQInteger SqCaseCmpUTF8(StackStrF & a, StackStrF & b)
|
||||
{
|
||||
// Is the left string invalid?
|
||||
if (a.mLen < 0)
|
||||
{
|
||||
STHROWF("Invalid string on the left {}", a.mLen);
|
||||
}
|
||||
// Is the right string invalid?
|
||||
else if (b.mLen < 0)
|
||||
{
|
||||
STHROWF("Invalid string on the right {}", b.mLen);
|
||||
}
|
||||
// Perform the request and return the result
|
||||
return utf8casecmp(a.mPtr, b.mPtr);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static SQInteger SqNCaseCmpUTF8(StackStrF & a, StackStrF & b)
|
||||
{
|
||||
// Is the left string invalid?
|
||||
if (a.mLen < 0)
|
||||
{
|
||||
STHROWF("Invalid string on the left {}", a.mLen);
|
||||
}
|
||||
// Is the right string invalid?
|
||||
else if (b.mLen < 0)
|
||||
{
|
||||
STHROWF("Invalid string on the right {}", b.mLen);
|
||||
}
|
||||
// See if we can decide this based on length differences
|
||||
else if (a.mLen < b.mLen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (a.mLen > b.mLen)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
// Perform the request and return the result
|
||||
return utf8ncasecmp(a.mPtr, b.mPtr, static_cast< size_t >(a.mLen));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_NODISCARD static SQInteger SqCaseStrUTF8(StackStrF & hs, StackStrF & nd)
|
||||
{
|
||||
// Is the haystack or needle string empty or invalid?
|
||||
if (hs.mLen <= 0 || nd.mLen <= 0)
|
||||
{
|
||||
return -1; // Let the user know that we could not search for this
|
||||
}
|
||||
// Look for the specified needle string in the haystack string
|
||||
auto * p = reinterpret_cast< const SQChar * >(utf8casestr(hs.mPtr, nd.mPtr));
|
||||
// Return the distance in bytes where the string was found
|
||||
return static_cast< SQInteger >(p - hs.mPtr);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_UTF8(HSQUIRRELVM vm)
|
||||
{
|
||||
Table ns(vm);
|
||||
|
||||
ns
|
||||
.FmtFunc(_SC("StrLen"), &SqStrLenUTF8)
|
||||
.FmtFunc(_SC("StrNLen"), &SqStrNLenUTF8)
|
||||
.FmtFunc(_SC("StrChr"), &SqStrChrUTF8)
|
||||
.FmtFunc(_SC("CaseCmp"), &SqCaseCmpUTF8)
|
||||
.FmtFunc(_SC("NCaseCmp"), &SqNCaseCmpUTF8)
|
||||
.FmtFunc(_SC("CaseStr"), &SqCaseStrUTF8)
|
||||
;
|
||||
|
||||
RootTable(vm).Bind(_SC("SqUTF8"), ns);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Core/Common.hpp"
|
||||
#include "Core/Utility.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <utf8.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
@@ -8,6 +8,9 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQMOD_DECL_TYPENAME(SqIdPoolTypename, _SC("SqIdPool"))
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Probably not the best implementation but should cover all sorts of weird cases.
|
||||
*/
|
||||
@@ -83,15 +86,18 @@ static SQInteger SqExtractIPv4(HSQUIRRELVM vm)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
extern void Register_IdPool(HSQUIRRELVM vm, Table & ns);
|
||||
extern void Register_Vector(HSQUIRRELVM vm, Table & ns);
|
||||
extern void Register_Native_String(HSQUIRRELVM vm, Table & ns);
|
||||
extern void Register_ServerAnnouncer(HSQUIRRELVM vm, Table & ns);
|
||||
|
||||
|
||||
// ================================================================================================
|
||||
void Register_Utils(HSQUIRRELVM vm)
|
||||
{
|
||||
Table ns(vm);
|
||||
|
||||
Register_IdPool(vm, ns);
|
||||
Register_Vector(vm, ns);
|
||||
Register_Native_String(vm, ns);
|
||||
Register_ServerAnnouncer(vm, ns);
|
||||
@@ -101,4 +107,35 @@ void Register_Utils(HSQUIRRELVM vm)
|
||||
RootTable(vm).Bind(_SC("SqUtils"), ns);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Register_IdPool(HSQUIRRELVM vm, Table & ns)
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ns.Bind(_SC("IdPool"),
|
||||
Class< SqIdPool, NoCopy< SqIdPool > >(vm, SqIdPoolTypename::Str)
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.template Ctor< SqIdPool::Type >()
|
||||
.template Ctor< SqIdPool::Type, SqIdPool::Type >()
|
||||
// Meta-methods
|
||||
.SquirrelFunc(_SC("_typename"), &SqIdPoolTypename::Fn)
|
||||
// Member Variables
|
||||
.ConstVar(_SC("Next"), &SqIdPool::mNext)
|
||||
.ConstVar(_SC("Step"), &SqIdPool::mStep)
|
||||
.ConstVar(_SC("Start"), &SqIdPool::mStart)
|
||||
// Properties
|
||||
.Prop(_SC("FreeCount"), &SqIdPool::FreeCount)
|
||||
.Prop(_SC("UsedCount"), &SqIdPool::UsedCount)
|
||||
// Member Methods
|
||||
.Func(_SC("Reset"), &SqIdPool::Reset)
|
||||
.Func(_SC("Acquire"), &SqIdPool::Acquire)
|
||||
.Func(_SC("Release"), &SqIdPool::Release)
|
||||
.Func(_SC("Using"), &SqIdPool::Using)
|
||||
.Func(_SC("EachUsed"), &SqIdPool::EachUsed)
|
||||
.Func(_SC("WhileUsed"), &SqIdPool::WhileUsed)
|
||||
.Func(_SC("EachFree"), &SqIdPool::EachFree)
|
||||
.Func(_SC("WhileFree"), &SqIdPool::WhileFree)
|
||||
);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
@@ -6,4 +6,187 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Helper utility used to provide reusable unique IDs of signed integer type.
|
||||
* It is not thread-safe since the script runs in single-threaded mode.
|
||||
*/
|
||||
struct SqIdPool
|
||||
{
|
||||
using Type = SQInteger; // Type that is used to represent an ID.
|
||||
using Pool = std::vector< Type >; // Container for both used and unused IDs.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Pool of available IDs.
|
||||
Pool mPool{};
|
||||
// Pool of currently used IDs.
|
||||
Pool mUsed{};
|
||||
// The ID that will be generated next time the pool is empty.
|
||||
Type mNext{0};
|
||||
// How much to increment with each ID.
|
||||
Type mStep{1};
|
||||
// Where to start generating IDs.
|
||||
Type mStart{0};
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructors.
|
||||
*/
|
||||
SqIdPool() noexcept = default;
|
||||
SqIdPool(Type start) noexcept
|
||||
: SqIdPool(start, 1)
|
||||
{
|
||||
}
|
||||
SqIdPool(Type start, Type step) noexcept
|
||||
: mPool(), mUsed(), mNext(start), mStep(step), mStart(start)
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy/Move constructors (disabled).
|
||||
*/
|
||||
SqIdPool(const SqIdPool &) noexcept = delete;
|
||||
SqIdPool(SqIdPool &&) noexcept = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy/Move assignment operators (disabled).
|
||||
*/
|
||||
SqIdPool & operator = (const SqIdPool &) noexcept = delete;
|
||||
SqIdPool & operator = (SqIdPool &&) noexcept = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Discard all current IDs (free and used) and reset the start to the specified start.
|
||||
* This invalidates all IDs that are currently left in use.
|
||||
*/
|
||||
void Reset()
|
||||
{
|
||||
mNext = mStart;
|
||||
mPool.clear();
|
||||
mUsed.clear();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Acquire a unique ID from the pool.
|
||||
*/
|
||||
SQMOD_NODISCARD Type Acquire()
|
||||
{
|
||||
Type id = mNext;
|
||||
// Do we have some reusable IDs?
|
||||
if (mPool.empty())
|
||||
{
|
||||
mNext += mStep; // Create a new one and update the next one
|
||||
}
|
||||
else
|
||||
{
|
||||
id = mPool.back(); // Get one from the back of the pool
|
||||
mPool.pop_back(); // Remove it from the free pool
|
||||
}
|
||||
// Store it in the list of active IDs
|
||||
mUsed.push_back(id);
|
||||
// Return this ID
|
||||
return id;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Release a unique ID back to the pool.
|
||||
*/
|
||||
bool Release(Type id)
|
||||
{
|
||||
// Find the specified ID into
|
||||
for (Pool::size_type i = 0; i < mUsed.size(); ++i)
|
||||
{
|
||||
// Is this the ID we're looking for?
|
||||
if (mUsed[i] == id)
|
||||
{
|
||||
// Swap the element with the last one
|
||||
std::swap(mUsed[i], mUsed.back());
|
||||
// Remove the last element
|
||||
mUsed.pop_back();
|
||||
// Make this ID available, again
|
||||
mPool.push_back(id);
|
||||
// We actually found this ID
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// This ID does not belong to this pool
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Check if the pool has the specified ID currently in use.
|
||||
*/
|
||||
SQMOD_NODISCARD bool Using(Type id)
|
||||
{
|
||||
return std::find(mUsed.begin(), mUsed.end(), id) != mUsed.end();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the number of IDs that are currently available in the free pool.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger FreeCount() const
|
||||
{
|
||||
return mPool.size();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the number of IDs that are currently in use.
|
||||
*/
|
||||
SQMOD_NODISCARD SQInteger UsedCount() const
|
||||
{
|
||||
return mUsed.size();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Iterate all used IDs through a functor.
|
||||
*/
|
||||
void EachUsed(Function & fn) const
|
||||
{
|
||||
for (const auto & id : mUsed)
|
||||
{
|
||||
fn.Execute(id);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Iterate all used IDs through a functor until stopped (i.e false is returned).
|
||||
*/
|
||||
void WhileUsed(Function & fn) const
|
||||
{
|
||||
for (const auto & id : mUsed)
|
||||
{
|
||||
auto ret = fn.Eval(id);
|
||||
// (null || true) == continue & false == break
|
||||
if (!ret.IsNull() || !ret.template Cast< bool >())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Iterate all free IDs through a functor.
|
||||
*/
|
||||
void EachFree(Function & fn) const
|
||||
{
|
||||
for (const auto & id : mPool)
|
||||
{
|
||||
fn.Execute(id);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Iterate all free IDs through a functor until stopped (i.e false is returned).
|
||||
*/
|
||||
void WhileFree(Function & fn) const
|
||||
{
|
||||
for (const auto & id : mPool)
|
||||
{
|
||||
auto ret = fn.Eval(id);
|
||||
// (null || true) == continue & false == break
|
||||
if (!ret.IsNull() || !ret.template Cast< bool >())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
@@ -40,8 +40,9 @@ using Poco::StreamCopier;
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Helper utility that can be used to announce the server to a master-list.
|
||||
*/
|
||||
struct SqAnnouncer : SqChainedInstances< SqAnnouncer >
|
||||
struct SqAnnouncer : public SqChainedInstances< SqAnnouncer >
|
||||
{
|
||||
using Base = SqChainedInstances< SqAnnouncer >;
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Announcer status.
|
||||
*/
|
||||
@@ -114,7 +115,7 @@ struct SqAnnouncer : SqChainedInstances< SqAnnouncer >
|
||||
* Explicit constructor.
|
||||
*/
|
||||
SqAnnouncer(SQInteger interval, StackStrF & uri)
|
||||
: mRun(false), mLog(true)
|
||||
: Base(), mRun(false), mLog(true)
|
||||
, mCount(0)
|
||||
, mSuccess(0)
|
||||
, mFailures(0)
|
||||
@@ -125,8 +126,7 @@ struct SqAnnouncer : SqChainedInstances< SqAnnouncer >
|
||||
, mURI(uri.mPtr)
|
||||
, mMtx(), mThread()
|
||||
{
|
||||
// Remember this instance
|
||||
ChainInstance();
|
||||
ChainInstance(); // Remember this instance
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -164,6 +164,22 @@ template < class T > struct SqVector
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor from container.
|
||||
*/
|
||||
explicit SqVector(const Container & v)
|
||||
: mC(Poco::makeShared< Container >(v))
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor from container.
|
||||
*/
|
||||
explicit SqVector(Container && v) noexcept
|
||||
: mC(Poco::makeShared< Container >(std::move(v)))
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
|
||||
+45
-41
@@ -108,99 +108,103 @@ bool XmlNode::RemoveAttrInst(const XmlAttribute & attr)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj XmlAttribute::AsLong(const SLongInt & def) const
|
||||
SQInteger XmlAttribute::AsLong(SQInteger def) const
|
||||
{
|
||||
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Attr.as_llong(def.GetNum()));
|
||||
return m_Attr.as_llong(def);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj XmlAttribute::AsUlong(const ULongInt & def) const
|
||||
SQInteger XmlAttribute::AsUlong(SQInteger def) const
|
||||
{
|
||||
return LightObj(SqTypeIdentity< ULongInt >{}, SqVM(), m_Attr.as_ullong(def.GetNum()));
|
||||
return static_cast< SQInteger >(m_Attr.as_ullong(static_cast< uint64_t >(def)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool XmlAttribute::ApplyLong(const SLongInt & value)
|
||||
bool XmlAttribute::ApplyLong(SQInteger value)
|
||||
{
|
||||
return m_Attr.set_value(value.GetNum());
|
||||
return m_Attr.set_value(value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool XmlAttribute::ApplyUlong(const ULongInt & value)
|
||||
bool XmlAttribute::ApplyUlong(SQInteger value)
|
||||
{
|
||||
return m_Attr.set_value(value.GetNum());
|
||||
return m_Attr.set_value(value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj XmlAttribute::GetLong() const
|
||||
SQInteger XmlAttribute::GetLong() const
|
||||
{
|
||||
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Attr.as_llong());
|
||||
return m_Attr.as_llong();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void XmlAttribute::SetLong(const SLongInt & value)
|
||||
XmlAttribute & XmlAttribute::SetLong(SQInteger value)
|
||||
{
|
||||
m_Attr = value.GetNum();
|
||||
m_Attr = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj XmlAttribute::GetUlong() const
|
||||
SQInteger XmlAttribute::GetUlong() const
|
||||
{
|
||||
return LightObj(SqTypeIdentity< ULongInt >{}, SqVM(), m_Attr.as_ullong());
|
||||
return static_cast< SQInteger >(m_Attr.as_ullong());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void XmlAttribute::SetUlong(const ULongInt & value)
|
||||
XmlAttribute & XmlAttribute::SetUlong(SQInteger value)
|
||||
{
|
||||
m_Attr = value.GetNum();
|
||||
m_Attr = static_cast< uint64_t >(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj XmlText::AsLong(const SLongInt & def) const
|
||||
SQInteger XmlText::AsLong(SQInteger def) const
|
||||
{
|
||||
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Text.as_llong(def.GetNum()));
|
||||
return m_Text.as_llong(def);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj XmlText::AsUlong(const ULongInt & def) const
|
||||
SQInteger XmlText::AsUlong(SQInteger def) const
|
||||
{
|
||||
return LightObj(SqTypeIdentity< ULongInt >{}, SqVM(), m_Text.as_ullong(def.GetNum()));
|
||||
return static_cast< SQInteger >(m_Text.as_ullong(static_cast< uint64_t >(def)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool XmlText::ApplyLong(const SLongInt & value)
|
||||
bool XmlText::ApplyLong(SQInteger value)
|
||||
{
|
||||
return m_Text.set(value.GetNum());
|
||||
return m_Text.set(value);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool XmlText::ApplyUlong(const ULongInt & value)
|
||||
bool XmlText::ApplyUlong(SQInteger value)
|
||||
{
|
||||
return m_Text.set(value.GetNum());
|
||||
return m_Text.set(static_cast< uint64_t >(value));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj XmlText::GetLong() const
|
||||
SQInteger XmlText::GetLong() const
|
||||
{
|
||||
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Text.as_llong());
|
||||
return m_Text.as_llong();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void XmlText::SetLong(const SLongInt & value)
|
||||
XmlText & XmlText::SetLong(SQInteger value)
|
||||
{
|
||||
m_Text = value.GetNum();
|
||||
m_Text = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LightObj XmlText::GetUlong() const
|
||||
SQInteger XmlText::GetUlong() const
|
||||
{
|
||||
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Text.as_ullong());
|
||||
return static_cast< SQInteger >(m_Text.as_ullong());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void XmlText::SetUlong(const ULongInt & value)
|
||||
XmlText & XmlText::SetUlong(SQInteger value)
|
||||
{
|
||||
m_Text = value.GetNum();
|
||||
m_Text = static_cast< uint64_t >(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -259,8 +263,8 @@ void Register_XML(HSQUIRRELVM vm)
|
||||
.Prop(_SC("Next"), &XmlAttribute::NextAttribute)
|
||||
.Prop(_SC("Prev"), &XmlAttribute::PrevAttribute)
|
||||
// Member Methods
|
||||
.Func(_SC("SetName"), &XmlAttribute::ApplyName)
|
||||
.Func(_SC("SetValue"), &XmlAttribute::ApplyValue)
|
||||
.FmtFunc(_SC("SetName"), &XmlAttribute::SetName)
|
||||
.FmtFunc(_SC("SetValue"), &XmlAttribute::ApplyValue)
|
||||
.Func(_SC("AsString"), &XmlAttribute::AsString)
|
||||
.Func(_SC("AsInt"), &XmlAttribute::AsInt)
|
||||
.Func(_SC("AsUint"), &XmlAttribute::AsUint)
|
||||
@@ -350,8 +354,8 @@ void Register_XML(HSQUIRRELVM vm)
|
||||
.Overload(_SC("AppendBuffer"), &XmlNode::AppendBuffer1)
|
||||
.Overload(_SC("AppendBuffer"), &XmlNode::AppendBuffer2)
|
||||
.Overload(_SC("AppendBuffer"), &XmlNode::AppendBuffer3)
|
||||
.Func(_SC("SetName"), &XmlNode::ApplyName)
|
||||
.Func(_SC("SetValue"), &XmlNode::ApplyValue)
|
||||
.FmtFunc(_SC("SetName"), &XmlNode::SetName)
|
||||
.FmtFunc(_SC("SetValue"), &XmlNode::ApplyValue)
|
||||
.Func(_SC("GetChild"), &XmlNode::Child)
|
||||
.Func(_SC("GetAttr"), &XmlNode::GetAttribute)
|
||||
.Func(_SC("GetAttribute"), &XmlNode::GetAttribute)
|
||||
@@ -368,8 +372,8 @@ void Register_XML(HSQUIRRELVM vm)
|
||||
.Func(_SC("PrependAttrCopy"), &XmlNode::PrependAttrCopy)
|
||||
.Func(_SC("InsertAttrCopyAfter"), &XmlNode::InsertAttrCopyAfter)
|
||||
.Func(_SC("InsertAttrCopyBefore"), &XmlNode::InsertAttrCopyBefore)
|
||||
.Func(_SC("AppendChild"), &XmlNode::AppendChild)
|
||||
.Func(_SC("PrependChild"), &XmlNode::PrependChild)
|
||||
.FmtFunc(_SC("AppendChild"), &XmlNode::AppendChild)
|
||||
.FmtFunc(_SC("PrependChild"), &XmlNode::PrependChild)
|
||||
.Func(_SC("AppendChildNode"), &XmlNode::AppendChildNode)
|
||||
.Func(_SC("PrependChildNode"), &XmlNode::PrependChildNode)
|
||||
.Func(_SC("AppendChildType"), &XmlNode::AppendChildType)
|
||||
@@ -386,9 +390,9 @@ void Register_XML(HSQUIRRELVM vm)
|
||||
.Func(_SC("PrependMove"), &XmlNode::PrependMove)
|
||||
.Func(_SC("InsertMoveAfter"), &XmlNode::InsertMoveAfter)
|
||||
.Func(_SC("InsertMoveBefore"), &XmlNode::InsertMoveBefore)
|
||||
.Func(_SC("RemoveAttr"), &XmlNode::RemoveAttr)
|
||||
.FmtFunc(_SC("RemoveAttr"), &XmlNode::RemoveAttr)
|
||||
.Func(_SC("RemoveAttrInst"), &XmlNode::RemoveAttrInst)
|
||||
.Func(_SC("RemoveChild"), &XmlNode::RemoveChild)
|
||||
.FmtFunc(_SC("RemoveChild"), &XmlNode::RemoveChild)
|
||||
.Func(_SC("RemoveChildInst"), &XmlNode::RemoveChildInst)
|
||||
.Overload(_SC("FindChildByAttr"), &XmlNode::FindChildByAttr2)
|
||||
.Overload(_SC("FindChildByAttr"), &XmlNode::FindChildByAttr3)
|
||||
@@ -421,7 +425,7 @@ void Register_XML(HSQUIRRELVM vm)
|
||||
.Overload(_SC("SaveFile"), &XmlDocument::SaveFile4)
|
||||
);
|
||||
|
||||
RootTable(vm).Bind(_SC("SqXml"), xmlns);
|
||||
RootTable(vm).Bind(_SC("SqXML"), xmlns);
|
||||
|
||||
ConstTable(vm).Enum(_SC("SqXmlNodeType"), Enumeration(vm)
|
||||
.Const(_SC("Null"), static_cast< int32_t >(node_null))
|
||||
|
||||
+52
-55
@@ -3,9 +3,6 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Core/Utility.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <pugixml.hpp>
|
||||
#include <utility>
|
||||
@@ -666,7 +663,7 @@ protected:
|
||||
* Explicit constructor.
|
||||
*/
|
||||
XmlNode(DocumentRef doc, const Type & node)
|
||||
: m_Doc(std::move(doc)), m_Node(node)
|
||||
: m_Node(node), m_Doc(std::move(doc))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -674,8 +671,8 @@ protected:
|
||||
private:
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
DocumentRef m_Doc{}; // The main xml document instance.
|
||||
Type m_Node{}; // The managed document node.
|
||||
DocumentRef m_Doc{}; // The main xml document instance.
|
||||
|
||||
public:
|
||||
|
||||
@@ -780,20 +777,13 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify node name.
|
||||
*/
|
||||
void SetName(StackStrF & name)
|
||||
XmlNode & SetName(StackStrF & name)
|
||||
{
|
||||
if (!m_Node.set_name(name.mPtr))
|
||||
{
|
||||
STHROWF("Unable to set XML node name");
|
||||
STHROWF("Unable to set XML node name `{}`", name.ToStr());
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the node name.
|
||||
*/
|
||||
bool ApplyName(StackStrF & name)
|
||||
{
|
||||
return m_Node.set_name(name.mPtr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -807,12 +797,13 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify node value.
|
||||
*/
|
||||
void SetValue(StackStrF & name)
|
||||
XmlNode & SetValue(StackStrF & name)
|
||||
{
|
||||
if (!m_Node.set_value(name.mPtr))
|
||||
{
|
||||
STHROWF("Unable to set XML node value");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1334,20 +1325,13 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve attribute name.
|
||||
*/
|
||||
void SetName(StackStrF & name)
|
||||
XmlAttribute & SetName(StackStrF & name)
|
||||
{
|
||||
if (!m_Attr.set_name(name.mPtr))
|
||||
{
|
||||
STHROWF("Unable to set XML attribute name");
|
||||
STHROWF("Unable to set XML attribute name `{}`", name.ToStr());
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the attribute name.
|
||||
*/
|
||||
bool ApplyName(StackStrF & name)
|
||||
{
|
||||
return m_Attr.set_name(name.mPtr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1361,12 +1345,13 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve attribute value.
|
||||
*/
|
||||
void SetValue(StackStrF & name)
|
||||
XmlAttribute SetValue(StackStrF & name)
|
||||
{
|
||||
if (!m_Attr.set_value(name.mPtr))
|
||||
{
|
||||
STHROWF("Unable to set XML attribute value");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1420,12 +1405,12 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a long integer or the specified default value if empty.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj AsLong(const SLongInt & def) const;
|
||||
SQMOD_NODISCARD SQInteger AsLong(SQInteger def) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a unsigned long integer or the specified default value if empty.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj AsUlong(const ULongInt & def) const;
|
||||
SQMOD_NODISCARD SQInteger AsUlong(SQInteger def) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a boolean or the specified default value if empty.
|
||||
@@ -1478,12 +1463,12 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a long integer.
|
||||
*/
|
||||
bool ApplyLong(const SLongInt & value);
|
||||
bool ApplyLong(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a unsigned long integer.
|
||||
*/
|
||||
bool ApplyUlong(const ULongInt & value);
|
||||
bool ApplyUlong(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a boolean.
|
||||
@@ -1504,9 +1489,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a string.
|
||||
*/
|
||||
void SetString(StackStrF & value)
|
||||
XmlAttribute & SetString(StackStrF & value)
|
||||
{
|
||||
m_Attr = value.mPtr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1520,9 +1506,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a integer.
|
||||
*/
|
||||
void SetInt(int32_t value)
|
||||
XmlAttribute & SetInt(int32_t value)
|
||||
{
|
||||
m_Attr = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1536,9 +1523,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a unsigned integer.
|
||||
*/
|
||||
void SetUint(uint32_t value)
|
||||
XmlAttribute & SetUint(uint32_t value)
|
||||
{
|
||||
m_Attr = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1552,9 +1540,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a floating point.
|
||||
*/
|
||||
void SetFloat(SQFloat value)
|
||||
XmlAttribute & SetFloat(SQFloat value)
|
||||
{
|
||||
m_Attr = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1568,30 +1557,31 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a double floating point.
|
||||
*/
|
||||
void SetDouble(SQFloat value)
|
||||
XmlAttribute & SetDouble(SQFloat value)
|
||||
{
|
||||
m_Attr = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a long integer.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj GetLong() const;
|
||||
SQMOD_NODISCARD SQInteger GetLong() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a long integer.
|
||||
*/
|
||||
void SetLong(const SLongInt & value);
|
||||
XmlAttribute & SetLong(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a unsigned long integer.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj GetUlong() const;
|
||||
SQMOD_NODISCARD SQInteger GetUlong() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a unsigned long integer.
|
||||
*/
|
||||
void SetUlong(const ULongInt & value);
|
||||
XmlAttribute & SetUlong(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a boolean.
|
||||
@@ -1604,9 +1594,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a boolean.
|
||||
*/
|
||||
void SetBool(bool value)
|
||||
XmlAttribute & SetBool(bool value)
|
||||
{
|
||||
m_Attr = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1772,12 +1763,12 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a long integer or the specified default value if empty.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj AsLong(const SLongInt & def) const;
|
||||
SQMOD_NODISCARD SQInteger AsLong(SQInteger def) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a unsigned long integer or the specified default value if empty.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj AsUlong(const ULongInt & def) const;
|
||||
SQMOD_NODISCARD SQInteger AsUlong(SQInteger def) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a boolean or the specified default value if empty.
|
||||
@@ -1830,12 +1821,12 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a long integer.
|
||||
*/
|
||||
bool ApplyLong(const SLongInt & value);
|
||||
bool ApplyLong(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a unsigned long integer.
|
||||
*/
|
||||
bool ApplyUlong(const ULongInt & value);
|
||||
bool ApplyUlong(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a boolean.
|
||||
@@ -1856,9 +1847,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a string.
|
||||
*/
|
||||
void SetString(StackStrF & value)
|
||||
XmlText & SetString(StackStrF & value)
|
||||
{
|
||||
m_Text = value.mPtr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1872,9 +1864,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a integer.
|
||||
*/
|
||||
void SetInt(int32_t value)
|
||||
XmlText & SetInt(int32_t value)
|
||||
{
|
||||
m_Text = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1888,9 +1881,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a unsigned integer.
|
||||
*/
|
||||
void SetUint(uint32_t value)
|
||||
XmlText & SetUint(uint32_t value)
|
||||
{
|
||||
m_Text = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1904,9 +1898,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a floating point.
|
||||
*/
|
||||
void SetFloat(SQFloat value)
|
||||
XmlText & SetFloat(SQFloat value)
|
||||
{
|
||||
m_Text = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -1920,30 +1915,31 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a double floating point.
|
||||
*/
|
||||
void SetDouble(SQFloat value)
|
||||
XmlText & SetDouble(SQFloat value)
|
||||
{
|
||||
m_Text = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a long integer.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj GetLong() const;
|
||||
SQMOD_NODISCARD SQInteger GetLong() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a long integer.
|
||||
*/
|
||||
void SetLong(const SLongInt & value);
|
||||
XmlText & SetLong(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a unsigned long integer.
|
||||
*/
|
||||
SQMOD_NODISCARD LightObj GetUlong() const;
|
||||
SQMOD_NODISCARD SQInteger GetUlong() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a unsigned long integer.
|
||||
*/
|
||||
void SetUlong(const ULongInt & value);
|
||||
XmlText & SetUlong(SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value as a boolean.
|
||||
@@ -1956,9 +1952,10 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the value as a boolean.
|
||||
*/
|
||||
void SetBool(bool value)
|
||||
XmlText & SetBool(bool value)
|
||||
{
|
||||
m_Text = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -556,6 +556,21 @@ void Logger::ProcessMessage()
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Logger::Send(uint8_t level, bool sub, const char * msg)
|
||||
{
|
||||
// Is this level even allowed?
|
||||
if ((m_ConsoleLevels & level) || (m_LogFileLevels & level))
|
||||
{
|
||||
// Create a new message builder
|
||||
MsgPtr message(new Message(level, sub));
|
||||
// Generate the log message
|
||||
message->Append(msg);
|
||||
// Process the message in the buffer
|
||||
PushMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Logger::Send(uint8_t level, bool sub, const char * msg, size_t len)
|
||||
{
|
||||
|
||||
@@ -409,6 +409,11 @@ public:
|
||||
*/
|
||||
void BindCb(uint8_t level, Function & func);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Send a log message.
|
||||
*/
|
||||
void Send(uint8_t level, bool sub, const char * msg);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Send a log message.
|
||||
*/
|
||||
|
||||
+15
-3
@@ -17,11 +17,13 @@ namespace SqMod {
|
||||
static bool g_Reload = false;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
//extern void InitExports();
|
||||
extern void InitExports();
|
||||
extern void InitializeNet();
|
||||
extern void InitializePocoDataConnectors();
|
||||
extern void ProcessRoutines();
|
||||
extern void ProcessTasks();
|
||||
extern void ProcessThreads();
|
||||
extern void ProcessNet();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Will the scripts be reloaded at the end of the current event?
|
||||
@@ -95,7 +97,7 @@ static uint8_t OnServerInitialise()
|
||||
{
|
||||
SQMOD_SV_EV_TRACEBACK("[TRACE<] OnServerInitialise")
|
||||
// Signal outside plug-ins to do fetch our proxies
|
||||
//_Func->SendPluginCommand(0xDABBAD00, "%d", 1);
|
||||
_Func->SendPluginCommand(SQMOD_INITIALIZE_CMD, "%d", 1);
|
||||
// Attempt to load the module core
|
||||
if (Core::Get().Execute())
|
||||
{
|
||||
@@ -168,6 +170,8 @@ static void OnServerFrame(float elapsed_time)
|
||||
ProcessTasks();
|
||||
// Process threads
|
||||
ProcessThreads();
|
||||
// Process network
|
||||
ProcessNet();
|
||||
// Process log messages from other threads
|
||||
Logger::Get().ProcessQueue();
|
||||
// See if a reload was requested
|
||||
@@ -961,6 +965,11 @@ static void OnServerPerformanceReport(size_t /*entry_count*/, const char * * /*d
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Automatically terminate the third-party allocator.
|
||||
*/
|
||||
static std::unique_ptr< SqMod::RPMallocInit > gsRPMallocInit;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Plug-in initialization procedure.
|
||||
*/
|
||||
@@ -985,12 +994,15 @@ SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs * funcs, PluginCallback
|
||||
_Info->apiMinorVersion = PLUGIN_API_MINOR;
|
||||
// Assign the plug-in name
|
||||
std::snprintf(_Info->name, sizeof(_Info->name), "%s", SQMOD_HOST_NAME);
|
||||
// Initialize third-party allocator
|
||||
gsRPMallocInit = std::make_unique< RPMallocInit >();
|
||||
// Attempt to initialize the logger before anything else
|
||||
Logger::Get().Initialize(nullptr);
|
||||
// Attempt to initialize the plug-in core
|
||||
try
|
||||
{
|
||||
// External plugs that need to happen (once) before initialization
|
||||
InitializeNet();
|
||||
InitializePocoDataConnectors();
|
||||
// Proceed with plug-in initialization
|
||||
if (!Core::Get().Initialize())
|
||||
@@ -1071,7 +1083,7 @@ SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs * funcs, PluginCallback
|
||||
_Clbk->OnEntityStreamingChange = OnEntityStreamingChange;
|
||||
#endif
|
||||
// Attempt to initialize the plug-in exports
|
||||
//InitExports();
|
||||
InitExports();
|
||||
// Dummy spacing
|
||||
puts("");
|
||||
// Initialization was successful
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "Base/Color3.hpp"
|
||||
#include "Base/Vector2.hpp"
|
||||
#include "Entity/Player.hpp"
|
||||
#include "Library/Numeric/Long.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
@@ -173,9 +172,9 @@ void SendPluginCommand(uint32_t identifier, StackStrF & payload)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const ULongInt & GetTime()
|
||||
SQInteger GetTime()
|
||||
{
|
||||
return GetULongInt(_Func->GetTime());
|
||||
return static_cast< SQInteger >(_Func->GetTime());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -218,7 +217,7 @@ const SQChar * GetPluginAuthor()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int32_t GetPluginID()
|
||||
uint32_t GetPluginID()
|
||||
{
|
||||
return _Info->pluginId;
|
||||
}
|
||||
@@ -242,7 +241,7 @@ uint32_t GetServerFlags()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int32_t GetMaxPlayers()
|
||||
uint32_t GetMaxPlayers()
|
||||
{
|
||||
return _Func->GetMaxPlayers();
|
||||
}
|
||||
@@ -468,7 +467,7 @@ int32_t GetTimeRate()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SetTimeRate(uint32_t rate)
|
||||
void SetTimeRate(int32_t rate)
|
||||
{
|
||||
_Func->SetTimeRate(rate);
|
||||
}
|
||||
@@ -763,7 +762,7 @@ void SetSpawnCameraPositionEx(float x, float y, float z)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SetSpawnCameraLookAtEx(float x, float y, float z)
|
||||
{
|
||||
_Func->SetSpawnPlayerPosition(x, y, z);
|
||||
_Func->SetSpawnCameraLookAt(x, y, z);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -49,7 +49,7 @@ void SendPluginCommand(uint32_t identifier, StackStrF & payload);
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the server time.
|
||||
*/
|
||||
const ULongInt & GetTime();
|
||||
SQInteger GetTime();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Send a log message to the server.
|
||||
@@ -84,7 +84,7 @@ SQMOD_NODISCARD const SQChar * GetPluginAuthor();
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the id of the host Squirrel plug-in.
|
||||
*/
|
||||
SQMOD_NODISCARD int32_t GetPluginID();
|
||||
SQMOD_NODISCARD uint32_t GetPluginID();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the port onto which the server was binded.
|
||||
@@ -99,7 +99,7 @@ SQMOD_NODISCARD uint32_t GetServerFlags();
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the maximum number of clients allowed on the server.
|
||||
*/
|
||||
SQMOD_NODISCARD int32_t GetMaxPlayers();
|
||||
SQMOD_NODISCARD uint32_t GetMaxPlayers();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Modify the maximum number of clients allowed on the server.
|
||||
@@ -205,7 +205,7 @@ SQMOD_NODISCARD int32_t GetTimeRate();
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Modify the current time-rate.
|
||||
*/
|
||||
void SetTimeRate(uint32_t rate);
|
||||
void SetTimeRate(int32_t rate);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the game hour.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user