diff options
Diffstat (limited to '')
-rw-r--r-- | deep_test/deep_test.cpp | 135 | ||||
-rw-r--r-- | deep_test/deep_test.vcxproj | 2 | ||||
-rw-r--r-- | deep_test/deep_test.vcxproj.user | 13 | ||||
-rw-r--r-- | deep_test/deeptest.lua | 19 | ||||
-rw-r--r-- | src/compat.h | 64 |
5 files changed, 152 insertions, 81 deletions
diff --git a/deep_test/deep_test.cpp b/deep_test/deep_test.cpp index 0a09921..da467f3 100644 --- a/deep_test/deep_test.cpp +++ b/deep_test/deep_test.cpp | |||
@@ -1,18 +1,12 @@ | |||
1 | #include "lanes/src/deep.h" | 1 | #include "lanes/src/deep.h" |
2 | #include "lanes/src/compat.h" | 2 | #include "lanes/src/compat.h" |
3 | 3 | ||
4 | #include <malloc.h> | ||
5 | #include <memory.h> | ||
6 | #include <assert.h> | ||
7 | |||
8 | class MyDeepFactory : public DeepFactory | 4 | class MyDeepFactory : public DeepFactory |
9 | { | 5 | { |
10 | public: | 6 | public: |
11 | |||
12 | static MyDeepFactory Instance; | 7 | static MyDeepFactory Instance; |
13 | 8 | ||
14 | private: | 9 | private: |
15 | |||
16 | void createMetatable(lua_State* const L_) const override | 10 | void createMetatable(lua_State* const L_) const override |
17 | { | 11 | { |
18 | luaL_getmetatable(L_, "deep"); | 12 | luaL_getmetatable(L_, "deep"); |
@@ -28,6 +22,7 @@ class MyDeepFactory : public DeepFactory | |||
28 | // a lanes-deep userdata. needs DeepPrelude and luaG_newdeepuserdata from Lanes code. | 22 | // a lanes-deep userdata. needs DeepPrelude and luaG_newdeepuserdata from Lanes code. |
29 | struct MyDeepUserdata : public DeepPrelude // Deep userdata MUST start with a DeepPrelude | 23 | struct MyDeepUserdata : public DeepPrelude // Deep userdata MUST start with a DeepPrelude |
30 | { | 24 | { |
25 | std::atomic<int> inUse{}; | ||
31 | lua_Integer val{ 0 }; | 26 | lua_Integer val{ 0 }; |
32 | }; | 27 | }; |
33 | 28 | ||
@@ -49,22 +44,20 @@ void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* c | |||
49 | 44 | ||
50 | // ################################################################################################# | 45 | // ################################################################################################# |
51 | 46 | ||
52 | [[nodiscard]] static int deep_set(lua_State* const L_) | 47 | [[nodiscard]] static int deep_gc(lua_State* L) |
53 | { | 48 | { |
54 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, 1)) }; | 49 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; |
55 | lua_Integer i = lua_tointeger(L_, 2); | ||
56 | _self->val = i; | ||
57 | return 0; | 50 | return 0; |
58 | } | 51 | } |
59 | 52 | ||
60 | // ################################################################################################# | 53 | // ################################################################################################# |
61 | 54 | ||
62 | [[nodiscard]] static int deep_setuv(lua_State* L) | 55 | [[nodiscard]] static int deep_tostring(lua_State* L) |
63 | { | 56 | { |
64 | MyDeepUserdata* const self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; | 57 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; |
65 | int uv = (int) luaL_optinteger(L, 2, 1); | 58 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); |
66 | lua_settop( L, 3); | 59 | lua_pushfstring(L, "%p:deep(%d)", lua_topointer(L, 1), _self->val); |
67 | lua_pushboolean( L, lua_setiuservalue( L, 1, uv) != 0); | 60 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); |
68 | return 1; | 61 | return 1; |
69 | } | 62 | } |
70 | 63 | ||
@@ -73,44 +66,53 @@ void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* c | |||
73 | // won't actually do anything as deep userdata don't have uservalue slots | 66 | // won't actually do anything as deep userdata don't have uservalue slots |
74 | [[nodiscard]] static int deep_getuv(lua_State* L) | 67 | [[nodiscard]] static int deep_getuv(lua_State* L) |
75 | { | 68 | { |
76 | MyDeepUserdata* const self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; | 69 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; |
77 | int uv = (int) luaL_optinteger(L, 2, 1); | 70 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); |
78 | lua_getiuservalue( L, 1, uv); | 71 | int _uv = (int) luaL_optinteger(L, 2, 1); |
72 | lua_getiuservalue(L, 1, _uv); | ||
73 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); | ||
79 | return 1; | 74 | return 1; |
80 | } | 75 | } |
81 | 76 | ||
82 | // ################################################################################################# | 77 | // ################################################################################################# |
83 | 78 | ||
84 | [[nodiscard]] static int deep_tostring(lua_State* L) | 79 | [[nodiscard]] static int deep_set(lua_State* const L_) |
85 | { | 80 | { |
86 | MyDeepUserdata* const self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; | 81 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, 1)) }; |
87 | lua_pushfstring(L, "%p:deep(%d)", lua_topointer(L, 1), self->val); | 82 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); |
88 | return 1; | 83 | lua_Integer _i = lua_tointeger(L_, 2); |
84 | _self->val = _i; | ||
85 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); | ||
86 | return 0; | ||
89 | } | 87 | } |
90 | 88 | ||
91 | // ################################################################################################# | 89 | // ################################################################################################# |
92 | 90 | ||
93 | [[nodiscard]] static int deep_gc(lua_State* L) | 91 | [[nodiscard]] static int deep_setuv(lua_State* L) |
94 | { | 92 | { |
95 | MyDeepUserdata* const self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; | 93 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; |
96 | return 0; | 94 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); |
95 | int _uv = (int) luaL_optinteger(L, 2, 1); | ||
96 | lua_settop(L, 3); | ||
97 | lua_pushboolean(L, lua_setiuservalue(L, 1, _uv) != 0); | ||
98 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); | ||
99 | return 1; | ||
97 | } | 100 | } |
98 | 101 | ||
99 | // ################################################################################################# | 102 | // ################################################################################################# |
100 | 103 | ||
101 | static luaL_Reg const deep_mt[] = | 104 | static luaL_Reg const deep_mt[] = { |
102 | { | 105 | { "__gc", deep_gc }, |
103 | { "__tostring", deep_tostring}, | 106 | { "__tostring", deep_tostring }, |
104 | { "__gc", deep_gc}, | 107 | { "getuv", deep_getuv }, |
105 | { "set", deep_set}, | 108 | { "set", deep_set }, |
106 | { "setuv", deep_setuv}, | 109 | { "setuv", deep_setuv }, |
107 | { "getuv", deep_getuv}, | ||
108 | { nullptr, nullptr } | 110 | { nullptr, nullptr } |
109 | }; | 111 | }; |
110 | 112 | ||
111 | // ################################################################################################# | 113 | // ################################################################################################# |
112 | 114 | ||
113 | int luaD_new_deep( lua_State* L) | 115 | int luaD_new_deep(lua_State* L) |
114 | { | 116 | { |
115 | int const nuv{ static_cast<int>(luaL_optinteger(L, 1, 0)) }; | 117 | int const nuv{ static_cast<int>(luaL_optinteger(L, 1, 0)) }; |
116 | lua_settop(L, 0); | 118 | lua_settop(L, 0); |
@@ -141,8 +143,8 @@ struct MyClonableUserdata | |||
141 | { | 143 | { |
142 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); | 144 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); |
143 | int uv = (int) luaL_optinteger(L, 2, 1); | 145 | int uv = (int) luaL_optinteger(L, 2, 1); |
144 | lua_settop( L, 3); | 146 | lua_settop(L, 3); |
145 | lua_pushboolean( L, lua_setiuservalue( L, 1, uv) != 0); | 147 | lua_pushboolean(L, lua_setiuservalue(L, 1, uv) != 0); |
146 | return 1; | 148 | return 1; |
147 | } | 149 | } |
148 | 150 | ||
@@ -152,7 +154,7 @@ struct MyClonableUserdata | |||
152 | { | 154 | { |
153 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); | 155 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); |
154 | int uv = (int) luaL_optinteger(L, 2, 1); | 156 | int uv = (int) luaL_optinteger(L, 2, 1); |
155 | lua_getiuservalue( L, 1, uv); | 157 | lua_getiuservalue(L, 1, uv); |
156 | return 1; | 158 | return 1; |
157 | } | 159 | } |
158 | 160 | ||
@@ -178,19 +180,18 @@ struct MyClonableUserdata | |||
178 | // this is all we need to make a userdata lanes-clonable. no dependency on Lanes code. | 180 | // this is all we need to make a userdata lanes-clonable. no dependency on Lanes code. |
179 | [[nodiscard]] static int clonable_lanesclone(lua_State* L) | 181 | [[nodiscard]] static int clonable_lanesclone(lua_State* L) |
180 | { | 182 | { |
181 | switch( lua_gettop(L)) | 183 | switch (lua_gettop(L)) { |
182 | { | 184 | case 3: |
183 | case 3: | ||
184 | { | 185 | { |
185 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); | 186 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); |
186 | MyClonableUserdata* from = static_cast<MyClonableUserdata*>(lua_touserdata(L, 2)); | 187 | MyClonableUserdata* from = static_cast<MyClonableUserdata*>(lua_touserdata(L, 2)); |
187 | size_t len = lua_tointeger(L, 3); | 188 | size_t len = lua_tointeger(L, 3); |
188 | assert( len == sizeof(MyClonableUserdata)); | 189 | assert(len == sizeof(MyClonableUserdata)); |
189 | *self = *from; | 190 | *self = *from; |
190 | } | 191 | } |
191 | return 0; | 192 | return 0; |
192 | 193 | ||
193 | default: | 194 | default: |
194 | raise_luaL_error(L, "Lanes called clonable_lanesclone with unexpected parameters"); | 195 | raise_luaL_error(L, "Lanes called clonable_lanesclone with unexpected parameters"); |
195 | } | 196 | } |
196 | return 0; | 197 | return 0; |
@@ -198,34 +199,32 @@ struct MyClonableUserdata | |||
198 | 199 | ||
199 | // ################################################################################################# | 200 | // ################################################################################################# |
200 | 201 | ||
201 | static luaL_Reg const clonable_mt[] = | 202 | static luaL_Reg const clonable_mt[] = { |
202 | { | 203 | { "__tostring", clonable_tostring }, |
203 | { "__tostring", clonable_tostring}, | 204 | { "__gc", clonable_gc }, |
204 | { "__gc", clonable_gc}, | 205 | { "__lanesclone", clonable_lanesclone }, |
205 | { "__lanesclone", clonable_lanesclone}, | 206 | { "set", clonable_set }, |
206 | { "set", clonable_set}, | 207 | { "setuv", clonable_setuv }, |
207 | { "setuv", clonable_setuv}, | 208 | { "getuv", clonable_getuv }, |
208 | { "getuv", clonable_getuv}, | ||
209 | { nullptr, nullptr } | 209 | { nullptr, nullptr } |
210 | }; | 210 | }; |
211 | 211 | ||
212 | // ################################################################################################# | 212 | // ################################################################################################# |
213 | 213 | ||
214 | int luaD_new_clonable( lua_State* L) | 214 | int luaD_new_clonable(lua_State* L) |
215 | { | 215 | { |
216 | int const nuv{ static_cast<int>(luaL_optinteger(L, 1, 1)) }; | 216 | int const _nuv{ static_cast<int>(luaL_optinteger(L, 1, 1)) }; |
217 | lua_newuserdatauv( L, sizeof(MyClonableUserdata), nuv); | 217 | lua_newuserdatauv(L, sizeof(MyClonableUserdata), _nuv); |
218 | luaL_setmetatable( L, "clonable"); | 218 | luaG_setmetatable(L, "clonable"); |
219 | return 1; | 219 | return 1; |
220 | } | 220 | } |
221 | 221 | ||
222 | // ################################################################################################# | 222 | // ################################################################################################# |
223 | // ################################################################################################# | 223 | // ################################################################################################# |
224 | 224 | ||
225 | static luaL_Reg const deep_module[] = | 225 | static luaL_Reg const deep_module[] = { |
226 | { | 226 | { "new_deep", luaD_new_deep }, |
227 | { "new_deep", luaD_new_deep}, | 227 | { "new_clonable", luaD_new_clonable }, |
228 | { "new_clonable", luaD_new_clonable}, | ||
229 | { nullptr, nullptr } | 228 | { nullptr, nullptr } |
230 | }; | 229 | }; |
231 | 230 | ||
@@ -233,24 +232,24 @@ static luaL_Reg const deep_module[] = | |||
233 | 232 | ||
234 | LANES_API int luaopen_deep_test(lua_State* L) | 233 | LANES_API int luaopen_deep_test(lua_State* L) |
235 | { | 234 | { |
236 | luaL_newlib( L, deep_module); // M | 235 | luaG_newlib<std::size(deep_module)>(L, deep_module); // M |
237 | 236 | ||
238 | // preregister the metatables for the types we can instantiate so that Lanes can know about them | 237 | // preregister the metatables for the types we can instantiate so that Lanes can know about them |
239 | if (luaL_newmetatable( L, "clonable")) // M mt | 238 | if (luaL_newmetatable(L, "clonable")) // M mt |
240 | { | 239 | { |
241 | luaL_setfuncs( L, clonable_mt, 0); | 240 | luaG_registerlibfuncs(L, clonable_mt); |
242 | lua_pushvalue(L, -1); // M mt mt | 241 | lua_pushvalue(L, -1); // M mt mt |
243 | lua_setfield(L, -2, "__index"); // M mt | 242 | lua_setfield(L, -2, "__index"); // M mt |
244 | } | 243 | } |
245 | lua_setfield(L, -2, "__clonableMT"); // M | 244 | lua_setfield(L, -2, "__clonableMT"); // M |
246 | 245 | ||
247 | if (luaL_newmetatable( L, "deep")) // mt | 246 | if (luaL_newmetatable(L, "deep")) // mt |
248 | { | 247 | { |
249 | luaL_setfuncs( L, deep_mt, 0); | 248 | luaG_registerlibfuncs(L, deep_mt); |
250 | lua_pushvalue(L, -1); // mt mt | 249 | lua_pushvalue(L, -1); // mt mt |
251 | lua_setfield(L, -2, "__index"); // mt | 250 | lua_setfield(L, -2, "__index"); // mt |
252 | } | 251 | } |
253 | lua_setfield(L, -2, "__deepMT"); // M | 252 | lua_setfield(L, -2, "__deepMT"); // M |
254 | 253 | ||
255 | return 1; | 254 | return 1; |
256 | } | 255 | } |
diff --git a/deep_test/deep_test.vcxproj b/deep_test/deep_test.vcxproj index 43b7ce0..298594e 100644 --- a/deep_test/deep_test.vcxproj +++ b/deep_test/deep_test.vcxproj | |||
@@ -556,7 +556,7 @@ | |||
556 | </ClCompile> | 556 | </ClCompile> |
557 | <PostBuildEvent> | 557 | <PostBuildEvent> |
558 | <Command>xcopy /R /F /Y /I "$(TargetPath)" $(SolutionDir)..\Lua51\bin\$(Platform)\Debug\</Command> | 558 | <Command>xcopy /R /F /Y /I "$(TargetPath)" $(SolutionDir)..\Lua51\bin\$(Platform)\Debug\</Command> |
559 | <Message>Copy to Lua 5.2</Message> | 559 | <Message>Copy to Lua 5.1</Message> |
560 | </PostBuildEvent> | 560 | </PostBuildEvent> |
561 | <Link> | 561 | <Link> |
562 | <AdditionalDependencies>lua51.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> | 562 | <AdditionalDependencies>lua51.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> |
diff --git a/deep_test/deep_test.vcxproj.user b/deep_test/deep_test.vcxproj.user index 24e3d31..257d4e9 100644 --- a/deep_test/deep_test.vcxproj.user +++ b/deep_test/deep_test.vcxproj.user | |||
@@ -3,20 +3,23 @@ | |||
3 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'"> | 3 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'"> |
4 | <LocalDebuggerCommand>$(SolutionDir)..\Lua53\bin\$(Platform)\Debug\lua53.exe</LocalDebuggerCommand> | 4 | <LocalDebuggerCommand>$(SolutionDir)..\Lua53\bin\$(Platform)\Debug\lua53.exe</LocalDebuggerCommand> |
5 | <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> | 5 | <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> |
6 | <LocalDebuggerCommandArguments>-i</LocalDebuggerCommandArguments> | 6 | <LocalDebuggerCommandArguments>deeptest.lua</LocalDebuggerCommandArguments> |
7 | <LocalDebuggerWorkingDirectory>$(SolutionDir)Lanes\lanes\deep_test\</LocalDebuggerWorkingDirectory> | 7 | <LocalDebuggerWorkingDirectory>$(SolutionDir)Lanes\lanes\deep_test\</LocalDebuggerWorkingDirectory> |
8 | <RemoteDebuggerCommandArguments>deeptest.lua</RemoteDebuggerCommandArguments> | ||
8 | </PropertyGroup> | 9 | </PropertyGroup> |
9 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'"> | 10 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'"> |
10 | <LocalDebuggerCommand>$(SolutionDir)..\Lua52\bin\$(Platform)\Debug\lua51.exe</LocalDebuggerCommand> | 11 | <LocalDebuggerCommand>$(SolutionDir)..\Lua51\bin\$(Platform)\Debug\lua51.exe</LocalDebuggerCommand> |
11 | <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> | 12 | <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> |
12 | <LocalDebuggerCommandArguments>-i</LocalDebuggerCommandArguments> | 13 | <LocalDebuggerCommandArguments>-i deeptest.lua</LocalDebuggerCommandArguments> |
13 | <LocalDebuggerWorkingDirectory>$(SolutionDir)Lanes\lanes\deep_test\</LocalDebuggerWorkingDirectory> | 14 | <LocalDebuggerWorkingDirectory>$(SolutionDir)Lanes\lanes\deep_test\</LocalDebuggerWorkingDirectory> |
15 | <RemoteDebuggerCommandArguments>-i deeptest.lua</RemoteDebuggerCommandArguments> | ||
14 | </PropertyGroup> | 16 | </PropertyGroup> |
15 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'"> | 17 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'"> |
16 | <LocalDebuggerCommand>$(SolutionDir)..\Lua51\bin\$(Platform)\Debug\lua52.exe</LocalDebuggerCommand> | 18 | <LocalDebuggerCommand>$(SolutionDir)..\Lua52\bin\$(Platform)\Debug\lua52.exe</LocalDebuggerCommand> |
17 | <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> | 19 | <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> |
18 | <LocalDebuggerCommandArguments>-i</LocalDebuggerCommandArguments> | 20 | <LocalDebuggerCommandArguments>-i deeptest.lua</LocalDebuggerCommandArguments> |
19 | <LocalDebuggerWorkingDirectory>$(SolutionDir)Lanes\lanes\deep_test\</LocalDebuggerWorkingDirectory> | 21 | <LocalDebuggerWorkingDirectory>$(SolutionDir)Lanes\lanes\deep_test\</LocalDebuggerWorkingDirectory> |
22 | <RemoteDebuggerCommandArguments>-i deeptest.lua</RemoteDebuggerCommandArguments> | ||
20 | </PropertyGroup> | 23 | </PropertyGroup> |
21 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LuaJIT 2.1.0-beta3|x64'"> | 24 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LuaJIT 2.1.0-beta3|x64'"> |
22 | <LocalDebuggerCommand>$(SolutionDir)..\LuaJIT-2.1.0-beta3\bin\$(Platform)\luajit210.exe</LocalDebuggerCommand> | 25 | <LocalDebuggerCommand>$(SolutionDir)..\LuaJIT-2.1.0-beta3\bin\$(Platform)\luajit210.exe</LocalDebuggerCommand> |
diff --git a/deep_test/deeptest.lua b/deep_test/deeptest.lua index 09b638c..89e6f0d 100644 --- a/deep_test/deeptest.lua +++ b/deep_test/deeptest.lua | |||
@@ -6,16 +6,21 @@ local dt = lanes.require "deep_test" | |||
6 | 6 | ||
7 | local test_deep = true | 7 | local test_deep = true |
8 | local test_clonable = true | 8 | local test_clonable = true |
9 | local test_uvtype = "string" | 9 | -- lua 5.1->5.2 support a single table uservalue |
10 | -- lua 5.3->5.4 supports an arbitrary type uservalue | ||
11 | local test_uvtype = (_VERSION == "Lua 5.4") and "function" or (_VERSION == "Lua 5.3") and "string" or "table" | ||
12 | -- lua 5.4 supports multiple uservalues | ||
10 | local nupvals = _VERSION == "Lua 5.4" and 3 or 1 | 13 | local nupvals = _VERSION == "Lua 5.4" and 3 or 1 |
11 | 14 | ||
12 | local makeUserValue = function( obj_) | 15 | local makeUserValue = function( obj_) |
13 | if test_uvtype == "string" then | 16 | if test_uvtype == "table" then |
17 | return {"some uservalue"} | ||
18 | elseif test_uvtype == "string" then | ||
14 | return "some uservalue" | 19 | return "some uservalue" |
15 | elseif test_uvtype == "function" then | 20 | elseif test_uvtype == "function" then |
16 | -- a function that pull the userdata as upvalue | 21 | -- a function that pull the userdata as upvalue |
17 | local f = function() | 22 | local f = function() |
18 | return tostring( obj_) | 23 | return "-> '" .. tostring( obj_) .. "'" |
19 | end | 24 | end |
20 | return f | 25 | return f |
21 | end | 26 | end |
@@ -25,7 +30,7 @@ local printDeep = function( prefix_, obj_, t_) | |||
25 | print( prefix_, obj_) | 30 | print( prefix_, obj_) |
26 | for uvi = 1, nupvals do | 31 | for uvi = 1, nupvals do |
27 | local uservalue = obj_:getuv(uvi) | 32 | local uservalue = obj_:getuv(uvi) |
28 | print ( "uv #" .. uvi, uservalue, type( uservalue) == "function" and uservalue() or "") | 33 | print ("uv #" .. uvi, type( uservalue), uservalue, type(uservalue) == "function" and uservalue() or "") |
29 | end | 34 | end |
30 | if t_ then | 35 | if t_ then |
31 | for k, v in pairs( t_) do | 36 | for k, v in pairs( t_) do |
@@ -38,10 +43,7 @@ end | |||
38 | local performTest = function( obj_) | 43 | local performTest = function( obj_) |
39 | -- setup the userdata with some value and a uservalue | 44 | -- setup the userdata with some value and a uservalue |
40 | obj_:set( 666) | 45 | obj_:set( 666) |
41 | -- lua 5.1->5.2 support a single table uservalue | ||
42 | -- lua 5.3 supports an arbitrary type uservalue | ||
43 | obj_:setuv( 1, makeUserValue( obj_)) | 46 | obj_:setuv( 1, makeUserValue( obj_)) |
44 | -- lua 5.4 supports multiple uservalues of arbitrary types | ||
45 | if nupvals > 1 then | 47 | if nupvals > 1 then |
46 | -- keep uv #2 as nil | 48 | -- keep uv #2 as nil |
47 | obj_:setuv( 3, "ENDUV") | 49 | obj_:setuv( 3, "ENDUV") |
@@ -95,3 +97,6 @@ if test_clonable then | |||
95 | print "CLONABLE" | 97 | print "CLONABLE" |
96 | performTest( dt.new_clonable(nupvals)) | 98 | performTest( dt.new_clonable(nupvals)) |
97 | end | 99 | end |
100 | |||
101 | print "================================================================" | ||
102 | print "TEST OK" \ No newline at end of file | ||
diff --git a/src/compat.h b/src/compat.h index 1789a8b..58af985 100644 --- a/src/compat.h +++ b/src/compat.h | |||
@@ -172,10 +172,22 @@ struct Wrap | |||
172 | return ::lua_dump(L_, writer_, data_, strip_); | 172 | return ::lua_dump(L_, writer_, data_, strip_); |
173 | } | 173 | } |
174 | 174 | ||
175 | template <size_t N> | ||
176 | static inline void (luaL_newlib)(lua_State* const L_, luaL_Reg const (&funcs_)[N]) | ||
177 | { | ||
178 | lua_createtable(L_, 0, N - 1); | ||
179 | ::luaL_setfuncs(L_, funcs_, 0); | ||
180 | } | ||
181 | |||
175 | static void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], int nup_) | 182 | static void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], int nup_) |
176 | { | 183 | { |
177 | ::luaL_setfuncs(L_, funcs_, nup_); | 184 | ::luaL_setfuncs(L_, funcs_, nup_); |
178 | } | 185 | } |
186 | |||
187 | static void luaL_setmetatable(lua_State* const L_, std::string_view const& tname_) | ||
188 | { | ||
189 | ::luaL_setmetatable(L_, tname_.data()); | ||
190 | } | ||
179 | }; | 191 | }; |
180 | 192 | ||
181 | // ################################################################################################# | 193 | // ################################################################################################# |
@@ -188,10 +200,22 @@ struct Wrap<VERSION, typename std::enable_if<VERSION == 503>::type> | |||
188 | return ::lua_dump(L_, writer_, data_, strip_); | 200 | return ::lua_dump(L_, writer_, data_, strip_); |
189 | } | 201 | } |
190 | 202 | ||
203 | template <size_t N> | ||
204 | static inline void (luaL_newlib)(lua_State* const L_, luaL_Reg const (&funcs_)[N]) | ||
205 | { | ||
206 | lua_createtable(L_, 0, N - 1); | ||
207 | ::luaL_setfuncs(L_, funcs_, 0); | ||
208 | } | ||
209 | |||
191 | static void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], int const nup_) | 210 | static void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], int const nup_) |
192 | { | 211 | { |
193 | ::luaL_setfuncs(L_, funcs_, nup_); | 212 | ::luaL_setfuncs(L_, funcs_, nup_); |
194 | } | 213 | } |
214 | |||
215 | static void luaL_setmetatable(lua_State* const L_, std::string_view const& tname_) | ||
216 | { | ||
217 | ::luaL_setmetatable(L_, tname_.data()); | ||
218 | } | ||
195 | }; | 219 | }; |
196 | 220 | ||
197 | // ################################################################################################# | 221 | // ################################################################################################# |
@@ -204,10 +228,22 @@ struct Wrap<VERSION, typename std::enable_if<VERSION == 502>::type> | |||
204 | return ::lua_dump(L_, writer_, data_); | 228 | return ::lua_dump(L_, writer_, data_); |
205 | } | 229 | } |
206 | 230 | ||
231 | template <size_t N> | ||
232 | static inline void (luaL_newlib)(lua_State* const L_, luaL_Reg const (&funcs_)[N]) | ||
233 | { | ||
234 | lua_createtable(L_, 0, N - 1); | ||
235 | ::luaL_setfuncs(L_, funcs_, 0); | ||
236 | } | ||
237 | |||
207 | static void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], int const nup_) | 238 | static void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], int const nup_) |
208 | { | 239 | { |
209 | ::luaL_setfuncs(L_, funcs_, nup_); | 240 | ::luaL_setfuncs(L_, funcs_, nup_); |
210 | } | 241 | } |
242 | |||
243 | static void luaL_setmetatable(lua_State* const L_, std::string_view const& tname_) | ||
244 | { | ||
245 | ::luaL_setmetatable(L_, tname_.data()); | ||
246 | } | ||
211 | }; | 247 | }; |
212 | 248 | ||
213 | // ################################################################################################# | 249 | // ################################################################################################# |
@@ -220,10 +256,23 @@ struct Wrap<VERSION, typename std::enable_if<VERSION == 501>::type> | |||
220 | return ::lua_dump(L_, writer_, data_); | 256 | return ::lua_dump(L_, writer_, data_); |
221 | } | 257 | } |
222 | 258 | ||
259 | template<size_t N> | ||
260 | static inline void (luaL_newlib)(lua_State* const L_, luaL_Reg const (&funcs_)[N]) | ||
261 | { | ||
262 | lua_createtable(L_, 0, N - 1); | ||
263 | ::luaL_register(L_, nullptr, funcs_); | ||
264 | } | ||
265 | |||
223 | static void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], [[maybe_unused]] int const nup_) | 266 | static void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], [[maybe_unused]] int const nup_) |
224 | { | 267 | { |
225 | ::luaL_register(L_, nullptr, funcs_); | 268 | ::luaL_register(L_, nullptr, funcs_); |
226 | } | 269 | } |
270 | |||
271 | static void luaL_setmetatable(lua_State* const L_, std::string_view const& tname_) | ||
272 | { | ||
273 | luaL_getmetatable(L_, tname_.data()); | ||
274 | lua_setmetatable(L_, -2); | ||
275 | } | ||
227 | }; | 276 | }; |
228 | 277 | ||
229 | // ################################################################################################# | 278 | // ################################################################################################# |
@@ -248,11 +297,26 @@ LuaType luaG_getmodule(lua_State* L_, std::string_view const& name_); | |||
248 | 297 | ||
249 | // ------------------------------------------------------------------------------------------------- | 298 | // ------------------------------------------------------------------------------------------------- |
250 | 299 | ||
300 | template<size_t N> | ||
301 | inline void luaG_newlib(lua_State* const L_, luaL_Reg const (&funcs_)[N]) | ||
302 | { | ||
303 | (Wrap<LUA_VERSION_NUM>::luaL_newlib)(L_, funcs_); | ||
304 | } | ||
305 | |||
306 | // ------------------------------------------------------------------------------------------------- | ||
307 | |||
251 | inline void luaG_registerlibfuncs(lua_State* L_, luaL_Reg const funcs_[]) | 308 | inline void luaG_registerlibfuncs(lua_State* L_, luaL_Reg const funcs_[]) |
252 | { | 309 | { |
253 | Wrap<LUA_VERSION_NUM>::luaL_setfuncs(L_, funcs_, 0); | 310 | Wrap<LUA_VERSION_NUM>::luaL_setfuncs(L_, funcs_, 0); |
254 | } | 311 | } |
255 | 312 | ||
313 | // ------------------------------------------------------------------------------------------------- | ||
314 | |||
315 | inline void luaG_setmetatable(lua_State* const L_, std::string_view const& tname_) | ||
316 | { | ||
317 | return Wrap<LUA_VERSION_NUM>::luaL_setmetatable(L_, tname_); | ||
318 | } | ||
319 | |||
256 | // ################################################################################################# | 320 | // ################################################################################################# |
257 | 321 | ||
258 | // must keep as a macro as long as we do constant string concatenations | 322 | // must keep as a macro as long as we do constant string concatenations |