GCC Code Coverage Report


Directory: ./
File: firmware/controllers/lua/luaaa/luaaa.hpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 81.0% 323 0 399
Functions: 76.2% 64 0 84
Branches: 50.4% 143 0 284
Decisions: 44.4% 4 - 9

Line Branch Decision Exec Source
1
2 /*
3 Copyright (c) 2019 gengyong
4 https://github.com/gengyong/luaaa
5 licensed under MIT License.
6 */
7
8 #ifndef HEADER_LUAAA_HPP
9 #define HEADER_LUAAA_HPP
10
11 #define LUAAA_NS luaaa
12
13 /// set LUAAA_WITHOUT_CPP_STDLIB to disable C++ std libs.
14 //#define LUAAA_WITHOUT_CPP_STDLIB 1
15
16 extern "C"
17 {
18 #include "lua.h"
19 #include "lualib.h"
20 #include "lauxlib.h"
21 }
22
23 #if !defined LUA_VERSION_NUM || LUA_VERSION_NUM <= 501
24 inline void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
25 luaL_checkstack(L, nup + 1, "too many upvalues");
26 for (; l->name != NULL; l++) {
27 int i;
28 lua_pushstring(L, l->name);
29 for (i = 0; i < nup; i++)
30 lua_pushvalue(L, -(nup + 1));
31 lua_pushcclosure(L, l->func, nup);
32 lua_settable(L, -(nup + 3));
33 }
34 lua_pop(L, nup);
35 }
36 #endif
37
38 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
39 # define USE_NEW_MODULE_REGISTRY 1
40 #else
41 # define USE_NEW_MODULE_REGISTRY 0
42 #endif
43
44 #include <cstring>
45 #include <typeinfo>
46 #include <utility>
47
48 #if defined(_MSC_VER)
49 # define RTTI_CLASS_NAME(a) typeid(a).name() //vc always has this operator even if RTTI was disabled.
50 //#elif __GXX_RTTI
51 //# define RTTI_CLASS_NAME(a) typeid(a).name()
52 //#elif _HAS_STATIC_RTTI
53 //# define RTTI_CLASS_NAME(a) typeid(a).name()
54 #else
55 # define RTTI_CLASS_NAME(a) "?"
56 #endif
57
58 #ifndef LUAAA_WITHOUT_CPP_STDLIB
59 # include <string>
60 #else
61 # include <type_traits>
62 # include <cstring>
63 #endif
64
65
66 inline void LUAAA_DUMP(lua_State * state, const char * name = "") {
67 printf(">>>>>>>>>>>>>>>>>>>>>>>>>[%s]\n", name);
68 int top = lua_gettop(state);
69 for (int i = 1; i <= top; i++) {
70 printf("%d\t%s\t", i, luaL_typename(state, i));
71 switch (lua_type(state, i)) {
72 case LUA_TNUMBER:
73 printf("%g\n", lua_tonumber(state, i));
74 break;
75 case LUA_TSTRING:
76 printf("%s\n", lua_tostring(state, i));
77 break;
78 case LUA_TBOOLEAN:
79 printf("%s\n", (lua_toboolean(state, i) ? "true" : "false"));
80 break;
81 case LUA_TNIL:
82 printf("%s\n", "nil");
83 break;
84 default:
85 printf("%p\n", lua_topointer(state, i));
86 break;
87 }
88 }
89 printf("<<<<<<<<<<<<<<<<<<<<<<<<<\n");
90 }
91
92 namespace LUAAA_NS
93 {
94 //========================================================
95 // Lua Class
96 //========================================================
97
98 template <typename> struct LuaClass;
99
100 //========================================================
101 // Lua stack operator
102 //========================================================
103
104 template <typename T> struct LuaStack
105 {
106 40 inline static T& get(lua_State * state, int idx)
107 {
108 #ifndef LUAAA_WITHOUT_CPP_STDLIB
109 luaL_argcheck(state, LuaClass<T>::klassName != nullptr, 1, (std::string("cpp class `") + RTTI_CLASS_NAME(T) + "` not export").c_str());
110 #else
111
4/24
luaaa::LuaStack<SignalDebounce>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaIndustrialPid>::get(lua_State*, int):
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaPid>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaBiQuad>::get(lua_State*, int):
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaSensor>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<Timer>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
40 luaL_argcheck(state, LuaClass<T>::klassName != nullptr, 1, "cpp class not export");
112 #endif
113 40 T ** t = (T**)luaL_checkudata(state, idx, LuaClass<T>::klassName);
114
4/24
luaaa::LuaStack<SignalDebounce>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaIndustrialPid>::get(lua_State*, int):
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaPid>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaBiQuad>::get(lua_State*, int):
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaSensor>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<Timer>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
40 luaL_argcheck(state, t != NULL, 1, "invalid user data");
115
4/24
luaaa::LuaStack<SignalDebounce>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaIndustrialPid>::get(lua_State*, int):
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaPid>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaBiQuad>::get(lua_State*, int):
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<LuaSensor>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
luaaa::LuaStack<Timer>::get(lua_State*, int):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
40 luaL_argcheck(state, *t != NULL, 1, "invalid user data");
116 40 return (**t);
117 }
118
119 inline static void put(lua_State * L, T * t)
120 {
121 lua_pushlightuserdata(L, t);
122 }
123 };
124
125 template <typename T> struct LuaStack<const T> : public LuaStack<T> {};
126 template <typename T> struct LuaStack<T&> : public LuaStack<T> {};
127 template <typename T> struct LuaStack<const T&> : public LuaStack<T> {};
128
129 template <typename T> struct LuaStack<volatile T&> : public LuaStack<T>
130 {
131 inline static void put(lua_State * L, volatile T & t)
132 {
133 LuaStack<T>::put(L, const_cast<const T &>(t));
134 }
135 };
136
137 template <typename T> struct LuaStack<const volatile T&> : public LuaStack<T>
138 {
139 inline static void put(lua_State * L, const volatile T & t)
140 {
141 LuaStack<T>::put(L, const_cast<const T &>(t));
142 }
143 };
144
145 template <typename T> struct LuaStack<T&&> : public LuaStack<T>
146 {
147 inline static void put(lua_State * L, T && t)
148 {
149 LuaStack<T>::put(L, std::forward<T>(t));
150 }
151 };
152
153 template <typename T> struct LuaStack<T*>
154 {
155 inline static T * get(lua_State * state, int idx)
156 {
157 if (lua_islightuserdata(state, idx))
158 {
159 T * t = (T*)lua_touserdata(state, idx);
160 return t;
161 }
162 else if (lua_isuserdata(state, idx))
163 {
164 if (LuaClass<T*>::klassName != nullptr)
165 {
166 T ** t = (T**)luaL_checkudata(state, idx, LuaClass<T*>::klassName);
167 luaL_argcheck(state, t != NULL, 1, "invalid user data");
168 luaL_argcheck(state, *t != NULL, 1, "invalid user data");
169 return *t;
170 }
171 if (LuaClass<T>::klassName != nullptr)
172 {
173 T ** t = (T**)luaL_checkudata(state, idx, LuaClass<T>::klassName);
174 luaL_argcheck(state, t != NULL, 1, "invalid user data");
175 luaL_argcheck(state, *t != NULL, 1, "invalid user data");
176 return *t;
177 }
178 }
179 return nullptr;
180 }
181
182 inline static void put(lua_State * L, T * t)
183 {
184 lua_pushlightuserdata(L, t);
185 }
186 };
187
188 template<>
189 struct LuaStack<float>
190 {
191
1/1
✓ Decision 'true' taken 23 times.
23 inline static float get(lua_State * L, int idx)
192 {
193
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
1/2
✓ Decision 'true' taken 23 times.
✗ Decision 'false' not taken.
23 if (lua_isnumber(L, idx) || lua_isstring(L, idx))
194 {
195 23 return float(lua_tonumber(L, idx));
196 }
197 else
198 {
199 luaL_checktype(L, idx, LUA_TNUMBER);
200 }
201 return 0;
202 }
203
204 6 inline static void put(lua_State * L, const float & t)
205 {
206 6 lua_pushnumber(L, t);
207 6 }
208 };
209
210 template<>
211 struct LuaStack<double>
212 {
213 inline static double get(lua_State * L, int idx)
214 {
215 if (lua_isnumber(L, idx) || lua_isstring(L, idx))
216 {
217 return double(lua_tonumber(L, idx));
218 }
219 else
220 {
221 luaL_checktype(L, idx, LUA_TNUMBER);
222 }
223 return 0;
224 }
225
226 inline static void put(lua_State * L, const double & t)
227 {
228 lua_pushnumber(L, t);
229 }
230 };
231
232 template<>
233 struct LuaStack<int>
234 {
235 1 inline static int get(lua_State * L, int idx)
236 {
237
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 7 not taken.
1/2
✓ Decision 'true' taken 1 time.
✗ Decision 'false' not taken.
1 if (lua_isnumber(L, idx) || lua_isstring(L, idx))
238 {
239 1 return int(lua_tointeger(L, idx));
240 }
241 else
242 {
243 luaL_checktype(L, idx, LUA_TNUMBER);
244 }
245 return 0;
246 }
247
248 inline static void put(lua_State * L, const int & t)
249 {
250 lua_pushinteger(L, t);
251 }
252 };
253
254 template<>
255 struct LuaStack<bool>
256 {
257 15 inline static bool get(lua_State * L, int idx)
258 {
259 15 luaL_checktype(L, idx, LUA_TBOOLEAN);
260 15 return lua_toboolean(L, idx) != 0;
261 }
262
263 14 inline static void put(lua_State * L, const bool & t)
264 {
265 14 lua_pushboolean(L, t);
266 14 }
267 };
268
269 template<>
270 struct LuaStack<const char *>
271 {
272 2 inline static const char * get(lua_State * L, int idx)
273 {
274
1/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 switch (lua_type(L, idx))
275 {
276 case LUA_TBOOLEAN:
277 return (lua_toboolean(L, idx) ? "true" : "false");
278 case LUA_TNUMBER:
279 return lua_tostring(L, idx);
280
1/1
✓ Decision 'true' taken 2 times.
2 case LUA_TSTRING:
281 2 return lua_tostring(L, idx);
282 default:
283 luaL_checktype(L, idx, LUA_TSTRING);
284 break;
285 }
286 return "";
287 }
288
289 inline static void put(lua_State * L, const char * s)
290 {
291 lua_pushstring(L, s);
292 }
293 };
294
295 template<>
296 struct LuaStack<char *>
297 {
298 inline static char * get(lua_State * L, int idx)
299 {
300 return const_cast<char*>(LuaStack<const char *>::get(L, idx));
301 }
302
303 inline static void put(lua_State * L, const char * s)
304 {
305 LuaStack<const char *>::put(L, s);
306 }
307 };
308
309 #ifndef LUAAA_WITHOUT_CPP_STDLIB
310 template<>
311 struct LuaStack<std::string>
312 {
313 inline static std::string get(lua_State * L, int idx)
314 {
315 return LuaStack<const char *>::get(L, idx);
316 }
317
318 inline static void put(lua_State * L, const std::string& s)
319 {
320 LuaStack<const char *>::put(L, s.c_str());
321 }
322 };
323 #endif
324
325 template<>
326 struct LuaStack<lua_State *>
327 {
328 inline static lua_State * get(lua_State * L, int)
329 {
330 return L;
331 }
332
333 inline static void put(lua_State *, lua_State *)
334 {
335 }
336 };
337
338 // push ret data to stack
339 template <typename T>
340 20 inline void LuaStackReturn(lua_State * L, T t)
341 {
342 20 lua_settop(L, 0);
343 20 LuaStack<T>::put(L, t);
344 20 }
345
346 #define IMPLEMENT_CALLBACK_INVOKER(CALLCONV) \
347 template<typename RET, typename ...ARGS> \
348 struct LuaStack<RET(CALLCONV*)(ARGS...)> \
349 { \
350 typedef RET(CALLCONV*FTYPE)(ARGS...); \
351 inline static FTYPE get(lua_State * L, int idx) \
352 { \
353 static lua_State * cacheLuaState = nullptr; \
354 static int cacheLuaFuncId = 0; \
355 struct HelperClass \
356 { \
357 static RET CALLCONV f_callback(ARGS... args) \
358 { \
359 lua_rawgeti(cacheLuaState, LUA_REGISTRYINDEX, cacheLuaFuncId); \
360 if (lua_isfunction(cacheLuaState, -1)) \
361 { \
362 int initParams[] = { (LuaStack<ARGS>::put(cacheLuaState, args), 0)..., 0 }; \
363 if (lua_pcall(cacheLuaState, sizeof...(ARGS), 1, 0) != 0) \
364 { \
365 lua_error(cacheLuaState); \
366 } \
367 luaL_unref(cacheLuaState, LUA_REGISTRYINDEX, cacheLuaFuncId); \
368 } \
369 else \
370 { \
371 lua_pushnil(cacheLuaState); \
372 } \
373 return LuaStack<RET>::get(cacheLuaState, lua_gettop(cacheLuaState)); \
374 } \
375 }; \
376 if (lua_isfunction(L, idx)) \
377 { \
378 cacheLuaState = L; \
379 lua_pushvalue(L, idx); \
380 cacheLuaFuncId = luaL_ref(L, LUA_REGISTRYINDEX); \
381 return HelperClass::f_callback; \
382 } \
383 return nullptr; \
384 } \
385 inline void put(lua_State * L, FTYPE f) \
386 { \
387 lua_pushcfunction(L, NonMemberFunctionCaller(f)); \
388 } \
389 }; \
390 template<typename ...ARGS> \
391 struct LuaStack<void(CALLCONV*)(ARGS...)> \
392 { \
393 typedef void(CALLCONV*FTYPE)(ARGS...); \
394 inline static FTYPE get(lua_State * L, int idx) \
395 { \
396 static lua_State * cacheLuaState = nullptr; \
397 static int cacheLuaFuncId = 0; \
398 struct HelperClass \
399 { \
400 static void CALLCONV f_callback(ARGS... args) \
401 { \
402 lua_rawgeti(cacheLuaState, LUA_REGISTRYINDEX, cacheLuaFuncId); \
403 if (lua_isfunction(cacheLuaState, -1)) \
404 { \
405 int initParams[] = { (LuaStack<ARGS>::put(cacheLuaState, args), 0)..., 0 }; \
406 if (lua_pcall(cacheLuaState, sizeof...(ARGS), 1, 0) != 0) \
407 { \
408 lua_error(cacheLuaState); \
409 } \
410 luaL_unref(cacheLuaState, LUA_REGISTRYINDEX, cacheLuaFuncId); \
411 } \
412 return; \
413 } \
414 }; \
415 if (lua_isfunction(L, idx)) \
416 { \
417 cacheLuaState = L; \
418 lua_pushvalue(L, idx); \
419 cacheLuaFuncId = luaL_ref(L, LUA_REGISTRYINDEX); \
420 return HelperClass::f_callback; \
421 } \
422 return nullptr; \
423 } \
424 inline void put(lua_State * L, FTYPE f) \
425 { \
426 lua_pushcfunction(L, NonMemberFunctionCaller(f)); \
427 } \
428 };
429
430 //========================================================
431 // index generation helper
432 //========================================================
433 template<std::size_t... Ns>
434 struct indices
435 {
436 using next = indices<Ns..., sizeof...(Ns)>;
437 };
438
439 template<std::size_t N>
440 struct make_indices
441 {
442 using type = typename make_indices<N - 1>::type::next;
443 };
444
445 template<>
446 struct make_indices<0>
447 {
448 using type = indices<>;
449 };
450
451 //========================================================
452 // non-member function caller & static member function caller
453 //========================================================
454 template<typename FTYPE, typename ...ARGS, std::size_t... Ns>
455 void LuaInvokeVoidImpl(lua_State* state, void* calleePtr, size_t skip, indices<Ns...>)
456 {
457 (*(FTYPE*)(calleePtr))(LuaStack<ARGS>::get(state, Ns + 1 + skip)...);
458 }
459
460 template<typename FTYPE, typename ...ARGS>
461 inline void LuaInvokeVoid(lua_State* state, void* calleePtr, size_t skip)
462 {
463 LuaInvokeVoidImpl<FTYPE, ARGS...>(state, calleePtr, skip, typename make_indices<sizeof...(ARGS)>::type());
464 }
465
466 template<typename TRET, typename FTYPE, typename ...ARGS, std::size_t... Ns>
467 TRET LuaInvokeImpl(lua_State* state, void* calleePtr, size_t skip, indices<Ns...>)
468 {
469 return (*(FTYPE*)(calleePtr))(LuaStack<ARGS>::get(state, Ns + 1 + skip)...);
470 }
471
472 template<typename TRET, typename FTYPE, typename ...ARGS>
473 inline TRET LuaInvoke(lua_State* state, void* calleePtr, size_t skip)
474 {
475 return LuaInvokeImpl<TRET, FTYPE, ARGS...>(state, calleePtr, skip, typename make_indices<sizeof...(ARGS)>::type());
476 }
477
478 #define IMPLEMENT_FUNCTION_CALLER(CALLERNAME, CALLCONV, SKIPPARAM) \
479 template<typename TRET, typename ...ARGS> \
480 lua_CFunction CALLERNAME(TRET(CALLCONV*func)(ARGS...)) \
481 { \
482 typedef decltype(func) FTYPE; (void)(func); \
483 struct HelperClass \
484 { \
485 static int Invoke(lua_State* state) \
486 { \
487 void * calleePtr = lua_touserdata(state, lua_upvalueindex(1)); \
488 luaL_argcheck(state, calleePtr, 1, "cpp closure function not found."); \
489 if (calleePtr) \
490 { \
491 LuaStackReturn<TRET>(state, LuaInvoke<TRET, FTYPE, ARGS...>(state, calleePtr, SKIPPARAM)); \
492 return 1; \
493 } \
494 return 0; \
495 } \
496 }; \
497 return HelperClass::Invoke; \
498 } \
499 template<typename ...ARGS> \
500 lua_CFunction CALLERNAME(void(CALLCONV*func)(ARGS...)) \
501 { \
502 typedef decltype(func) FTYPE; (void)(func); \
503 struct HelperClass \
504 { \
505 static int Invoke(lua_State* state) \
506 { \
507 void * calleePtr = lua_touserdata(state, lua_upvalueindex(1)); \
508 luaL_argcheck(state, calleePtr, 1, "cpp closure function not found."); \
509 if (calleePtr) \
510 { \
511 LuaInvokeVoid<FTYPE, ARGS...>(state, calleePtr, SKIPPARAM); \
512 } \
513 return 0; \
514 } \
515 }; \
516 return HelperClass::Invoke; \
517 }
518
519 #if defined(_MSC_VER)
520 IMPLEMENT_FUNCTION_CALLER(NonMemberFunctionCaller, __cdecl, 0);
521 IMPLEMENT_FUNCTION_CALLER(MemberFunctionCaller, __cdecl, 1);
522 IMPLEMENT_CALLBACK_INVOKER(__cdecl);
523
524 # ifdef _M_CEE
525 IMPLEMENT_FUNCTION_CALLER(NonMemberFunctionCaller, __clrcall, 0);
526 IMPLEMENT_FUNCTION_CALLER(MemberFunctionCaller, __clrcall, 1);
527 IMPLEMENT_CALLBACK_INVOKER(__clrcall);
528 # endif
529
530 # if defined(_M_IX86) && !defined(_M_CEE)
531 IMPLEMENT_FUNCTION_CALLER(NonMemberFunctionCaller, __fastcall, 0);
532 IMPLEMENT_FUNCTION_CALLER(MemberFunctionCaller, __fastcall, 1);
533 IMPLEMENT_CALLBACK_INVOKER(__fastcall);
534 # endif
535
536 # ifdef _M_IX86
537 IMPLEMENT_FUNCTION_CALLER(NonMemberFunctionCaller, __stdcall, 0);
538 IMPLEMENT_FUNCTION_CALLER(MemberFunctionCaller, __stdcall, 1);
539 IMPLEMENT_CALLBACK_INVOKER(__stdcall);
540 # endif
541
542 # if ((defined(_M_IX86) && _M_IX86_FP >= 2) || defined(_M_X64)) && !defined(_M_CEE)
543 IMPLEMENT_FUNCTION_CALLER(NonMemberFunctionCaller, __vectorcall, 0);
544 IMPLEMENT_FUNCTION_CALLER(MemberFunctionCaller, __vectorcall, 1);
545 IMPLEMENT_CALLBACK_INVOKER(__vectorcall);
546 # endif
547 #elif defined(__clang__)
548 # define _NOTHING
549 IMPLEMENT_FUNCTION_CALLER(NonMemberFunctionCaller, _NOTHING, 0);
550 IMPLEMENT_FUNCTION_CALLER(MemberFunctionCaller, _NOTHING, 1);
551 IMPLEMENT_CALLBACK_INVOKER(_NOTHING);
552 # undef _NOTHING
553 #elif defined(__GNUC__)
554 # define _NOTHING
555 IMPLEMENT_FUNCTION_CALLER(NonMemberFunctionCaller, _NOTHING, 0);
556 IMPLEMENT_FUNCTION_CALLER(MemberFunctionCaller, _NOTHING, 1);
557 IMPLEMENT_CALLBACK_INVOKER(_NOTHING);
558 # undef _NOTHING
559 #else
560 # define _NOTHING
561 IMPLEMENT_FUNCTION_CALLER(NonMemberFunctionCaller, _NOTHING, 0);
562 IMPLEMENT_FUNCTION_CALLER(MemberFunctionCaller, _NOTHING, 1);
563 IMPLEMENT_CALLBACK_INVOKER(_NOTHING);
564 # undef _NOTHING
565 #endif
566
567 //========================================================
568 // member function invoker
569 //========================================================
570 template<typename TCLASS, typename TRET, typename FTYPE, typename ...ARGS, std::size_t... Ns>
571 20 TRET LuaInvokeInstanceMemberImpl(lua_State* state, void* calleePtr, indices<Ns...>)
572 {
573
1/4
bool luaaa::LuaInvokeInstanceMemberImpl<SignalDebounce, bool, bool (SignalDebounce::*)() const>(lua_State*, void*, luaaa::indices<>):
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
float luaaa::LuaInvokeInstanceMemberImpl<LuaBiQuad, float, float (LuaBiQuad::*)(float), float, 0ul>(lua_State*, void*, luaaa::indices<0ul>):
✗ Branch 1 not taken.
✗ Branch 2 not taken.
20 return (LuaStack<TCLASS>::get(state, 1).**(FTYPE*)(calleePtr))(LuaStack<ARGS>::get(state, Ns + 2)...);
574 }
575
576 template<typename TCLASS, typename TRET, typename FTYPE, typename ...ARGS>
577 20 inline TRET LuaInvokeInstanceMember(lua_State* state, void* calleePtr)
578 {
579 20 return LuaInvokeInstanceMemberImpl<TCLASS, TRET, FTYPE, ARGS...>(state, calleePtr, typename make_indices<sizeof...(ARGS)>::type());
580 }
581
582 template<typename TCLASS, typename FTYPE, typename ...ARGS, std::size_t... Ns>
583 20 void LuaInvokeInstanceMemberVoidImpl(lua_State* state, void* calleePtr, indices<Ns...>)
584 {
585
4/12
void luaaa::LuaInvokeInstanceMemberVoidImpl<SignalDebounce, void (SignalDebounce::*)(bool), bool, 0ul>(lua_State*, void*, luaaa::indices<0ul>):
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
void luaaa::LuaInvokeInstanceMemberVoidImpl<LuaBiQuad, void (LuaBiQuad::*)(float, float), float, float, 0ul, 1ul>(lua_State*, void*, luaaa::indices<0ul, 1ul>):
✗ Branch 1 not taken.
✗ Branch 2 not taken.
void luaaa::LuaInvokeInstanceMemberVoidImpl<LuaSensor, void (LuaSensor::*)()>(lua_State*, void*, luaaa::indices<>):
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
void luaaa::LuaInvokeInstanceMemberVoidImpl<LuaSensor, void (LuaSensor::*)(int), int, 0ul>(lua_State*, void*, luaaa::indices<0ul>):
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
void luaaa::LuaInvokeInstanceMemberVoidImpl<LuaSensor, void (LuaSensor::*)(bool), bool, 0ul>(lua_State*, void*, luaaa::indices<0ul>):
✗ Branch 1 not taken.
✗ Branch 2 not taken.
void luaaa::LuaInvokeInstanceMemberVoidImpl<LuaSensor, void (LuaSensor::*)(float), float, 0ul>(lua_State*, void*, luaaa::indices<0ul>):
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
20 (LuaStack<TCLASS>::get(state, 1).**(FTYPE*)(calleePtr))(LuaStack<ARGS>::get(state, Ns + 2)...);
586 20 }
587
588 template<typename TCLASS, typename FTYPE, typename ...ARGS>
589 20 inline void LuaInvokeInstanceMemberVoid(lua_State* state, void* calleePtr)
590 {
591 20 LuaInvokeInstanceMemberVoidImpl<TCLASS, FTYPE, ARGS...>(state, calleePtr, typename make_indices<sizeof...(ARGS)>::type());
592 20 }
593
594 template<typename TCLASS, typename TRET, typename ...ARGS>
595 927 lua_CFunction MemberFunctionCaller(TRET(TCLASS::*func)(ARGS...))
596 {
597 typedef decltype(func) FTYPE; (void)(func);
598 struct HelperClass
599 {
600 static int Invoke(lua_State* state)
601 {
602 void * calleePtr = lua_touserdata(state, lua_upvalueindex(1));
603 luaL_argcheck(state, calleePtr, 1, "cpp closure function not found.");
604 if (calleePtr)
605 {
606 LuaStackReturn<TRET>(state, LuaInvokeInstanceMember<TCLASS, TRET, FTYPE, ARGS...>(state, calleePtr));
607 return 1;
608 }
609 return 0;
610 }
611 };
612 927 return HelperClass::Invoke;
613 }
614
615 template<typename TCLASS, typename TRET, typename ...ARGS>
616 618 lua_CFunction MemberFunctionCaller(TRET(TCLASS::*func)(ARGS...)const)
617 {
618 typedef decltype(func) FTYPE; (void)(func);
619 struct HelperClass
620 {
621 static int Invoke(lua_State* state)
622 {
623 void * calleePtr = lua_touserdata(state, lua_upvalueindex(1));
624 luaL_argcheck(state, calleePtr, 1, "cpp closure function not found.");
625 if (calleePtr)
626 {
627 LuaStackReturn<TRET>(state, LuaInvokeInstanceMember<TCLASS, TRET, FTYPE, ARGS...>(state, calleePtr));
628 return 1;
629 }
630 return 0;
631 }
632 };
633 618 return HelperClass::Invoke;
634 }
635
636 template<typename TCLASS, typename ...ARGS>
637 4017 lua_CFunction MemberFunctionCaller(void(TCLASS::*func)(ARGS...))
638 {
639 typedef decltype(func) FTYPE; (void)(func);
640 struct HelperClass
641 {
642 static int Invoke(lua_State* state)
643 {
644 void * calleePtr = lua_touserdata(state, lua_upvalueindex(1));
645 luaL_argcheck(state, calleePtr, 1, "cpp closure function not found.");
646 if (calleePtr)
647 {
648 LuaInvokeInstanceMemberVoid<TCLASS, FTYPE, ARGS...>(state, calleePtr);
649 }
650 return 0;
651 }
652 };
653 4017 return HelperClass::Invoke;
654 }
655
656 template<typename TCLASS, typename ...ARGS>
657 lua_CFunction MemberFunctionCaller(void(TCLASS::*func)(ARGS...)const)
658 {
659 typedef decltype(func) FTYPE; (void)(func);
660 struct HelperClass
661 {
662 static int Invoke(lua_State* state)
663 {
664 void * calleePtr = lua_touserdata(state, lua_upvalueindex(1));
665 luaL_argcheck(state, calleePtr, 1, "cpp closure function not found.");
666 if (calleePtr)
667 {
668 LuaInvokeInstanceMemberVoid<TCLASS, FTYPE, ARGS...>(state, calleePtr);
669 }
670 return 0;
671 }
672 };
673 return HelperClass::Invoke;
674 }
675
676 //========================================================
677 // constructor invoker
678 //========================================================
679 template<typename TCLASS, typename ...ARGS>
680 struct PlacementConstructorCaller
681 {
682 4 static TCLASS * Invoke(lua_State * state, void * mem)
683 {
684 4 return InvokeImpl(state, mem, typename make_indices<sizeof...(ARGS)>::type());
685 }
686
687 private:
688 template<std::size_t ...Ns>
689 4 static TCLASS * InvokeImpl(lua_State * state, void * mem, indices<Ns...>)
690 {
691 (void)state;
692
7/22
SignalDebounce* luaaa::PlacementConstructorCaller<SignalDebounce, float>::InvokeImpl<0ul>(lua_State*, void*, luaaa::indices<0ul>):
✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
LuaIndustrialPid* luaaa::PlacementConstructorCaller<LuaIndustrialPid, float, float, float, float, float>::InvokeImpl<0ul, 1ul, 2ul, 3ul, 4ul>(lua_State*, void*, luaaa::indices<0ul, 1ul, 2ul, 3ul, 4ul>):
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
LuaPid* luaaa::PlacementConstructorCaller<LuaPid, float, float, float, float, float>::InvokeImpl<0ul, 1ul, 2ul, 3ul, 4ul>(lua_State*, void*, luaaa::indices<0ul, 1ul, 2ul, 3ul, 4ul>):
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 8 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 14 taken 2 times.
✓ Branch 17 taken 2 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
LuaBiQuad* luaaa::PlacementConstructorCaller<LuaBiQuad>::InvokeImpl<>(lua_State*, void*, luaaa::indices<>):
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 return new(mem) TCLASS(LuaStack<ARGS>::get(state, Ns + 1)...);
693 }
694 };
695
696 //========================================================
697 // Destructor invoker
698 //========================================================
699 template<typename TCLASS, bool = std::is_destructible<TCLASS>::value>
700 struct DestructorCaller {
701 static void Invoke(TCLASS * obj) {
702 delete obj;
703 }
704 };
705
706 template<typename TCLASS>
707 struct DestructorCaller<TCLASS, false> {
708 static void Invoke(TCLASS * obj) {
709 }
710 };
711
712 //========================================================
713 // export class
714 //========================================================
715 template <typename TCLASS>
716 struct LuaClass
717 {
718 friend struct DestructorCaller<TCLASS>;
719 template<typename> friend struct LuaStack;
720 public:
721 1854 LuaClass(lua_State * state, const char * name, const luaL_Reg * functions = nullptr)
722 1854 : m_state(state)
723 {
724 //assert(state != nullptr);
725 //assert(klassName == nullptr);
726
727 #ifndef LUAAA_WITHOUT_CPP_STDLIB
728 luaL_argcheck(state, (klassName == nullptr), 1, (std::string("C++ class `") + RTTI_CLASS_NAME(TCLASS) + "` bind to conflict lua name `" + name + "`, origin name: " + klassName).c_str());
729 #else
730
6/30
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1854 luaL_argcheck(state, (klassName == nullptr), 1, "C++ class bind to conflict lua class name");
731 #endif
732
733 struct HelperClass {
734 static int f__clsgc(lua_State*) {
735 LuaClass<TCLASS>::klassName = nullptr;
736 return 0;
737 }
738 };
739
740 1854 size_t strBufLen = strlen(name) + 1;
741
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 klassName = reinterpret_cast<char *>(lua_newuserdata(state, strBufLen + 1));
742 1854 memcpy(klassName, name, strBufLen);
743
744 1854 klassName[strBufLen - 1] = '$';
745 1854 klassName[strBufLen] = 0;
746
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 luaL_newmetatable(state, klassName);
747 1854 luaL_Reg destructor[] = { { "__gc", HelperClass::f__clsgc },{ nullptr, nullptr } };
748
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 luaL_setfuncs(state, destructor, 0);
749
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 lua_setmetatable(state, -2);
750
751 1854 klassName[strBufLen - 1] = 0;
752
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 luaL_newmetatable(state, klassName);
753
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 lua_pushvalue(state, -1);
754
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 lua_setfield(state, -2, "__index");
755
756
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 lua_pushvalue(state, -2);
757
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 lua_setfield(state, -2, "$");
758
759
6/12
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
1854 if (functions)
760 {
761 luaL_setfuncs(state, functions, 0);
762 }
763
764
6/6
luaaa::LuaClass<SignalDebounce>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>::LuaClass(lua_State*, char const*, luaL_Reg const*):
✓ Branch 1 taken 309 times.
1854 lua_pop(state, 2);
765 1854 }
766
767 #ifndef LUAAA_WITHOUT_CPP_STDLIB
768 LuaClass(lua_State * state, const std::string& name, const luaL_Reg * functions = nullptr)
769 : LuaClass(state, name.c_str(), functions)
770 {}
771 #endif
772
773 template<typename ...ARGS>
774 1854 inline LuaClass<TCLASS>& ctor(const char * name = "new")
775 {
776 struct HelperClass {
777 static int f_gc(lua_State* state) {
778 TCLASS ** objPtr = (TCLASS**)luaL_checkudata(state, -1, LuaClass<TCLASS>::klassName);
779 if (objPtr && *objPtr)
780 {
781 (*objPtr)->~TCLASS();
782 }
783 return 0;
784 }
785
786 static int f_new(lua_State* state) {
787 TCLASS ** objPtr = (TCLASS **)lua_newuserdata(state, sizeof(TCLASS*) + sizeof(TCLASS));
788 if (objPtr)
789 {
790 TCLASS * obj = PlacementConstructorCaller<TCLASS, ARGS...>::Invoke(state, (void*)(objPtr + 1));
791
792 *objPtr = obj;
793 luaL_Reg destructor[] = { { "__gc", HelperClass::f_gc },{ nullptr, nullptr } };
794 luaL_getmetatable(state, LuaClass<TCLASS>::klassName);
795 luaL_setfuncs(state, destructor, 0);
796 lua_setmetatable(state, -2);
797 return 1;
798 }
799 lua_pushnil(state);
800 return 1;
801 }
802 };
803
804 1854 luaL_Reg constructor[] = { { name, HelperClass::f_new },{ nullptr, nullptr } };
805 #if USE_NEW_MODULE_REGISTRY
806
6/6
luaaa::LuaClass<SignalDebounce>& luaaa::LuaClass<SignalDebounce>::ctor<float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>& luaaa::LuaClass<LuaIndustrialPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>& luaaa::LuaClass<LuaPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>& luaaa::LuaClass<LuaBiQuad>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>& luaaa::LuaClass<LuaSensor>::ctor<lua_State*, char const*>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>& luaaa::LuaClass<Timer>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
1854 lua_getglobal(m_state, klassName);
807
12/18
luaaa::LuaClass<SignalDebounce>& luaaa::LuaClass<SignalDebounce>::ctor<float>(char const*):
✓ Branch 1 taken 309 times.
✓ Branch 3 taken 309 times.
✗ Branch 4 not taken.
luaaa::LuaClass<LuaIndustrialPid>& luaaa::LuaClass<LuaIndustrialPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
✓ Branch 3 taken 309 times.
✗ Branch 4 not taken.
luaaa::LuaClass<LuaPid>& luaaa::LuaClass<LuaPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
✓ Branch 3 taken 309 times.
✗ Branch 4 not taken.
luaaa::LuaClass<LuaBiQuad>& luaaa::LuaClass<LuaBiQuad>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
✓ Branch 3 taken 309 times.
✗ Branch 4 not taken.
luaaa::LuaClass<LuaSensor>& luaaa::LuaClass<LuaSensor>::ctor<lua_State*, char const*>(char const*):
✓ Branch 1 taken 309 times.
✓ Branch 3 taken 309 times.
✗ Branch 4 not taken.
luaaa::LuaClass<Timer>& luaaa::LuaClass<Timer>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
✓ Branch 3 taken 309 times.
✗ Branch 4 not taken.
1854 if (lua_isnil(m_state, -1))
808 {
809
6/6
luaaa::LuaClass<SignalDebounce>& luaaa::LuaClass<SignalDebounce>::ctor<float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>& luaaa::LuaClass<LuaIndustrialPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>& luaaa::LuaClass<LuaPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>& luaaa::LuaClass<LuaBiQuad>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>& luaaa::LuaClass<LuaSensor>::ctor<lua_State*, char const*>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>& luaaa::LuaClass<Timer>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
1854 lua_pop(m_state, 1);
810
6/6
luaaa::LuaClass<SignalDebounce>& luaaa::LuaClass<SignalDebounce>::ctor<float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>& luaaa::LuaClass<LuaIndustrialPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>& luaaa::LuaClass<LuaPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>& luaaa::LuaClass<LuaBiQuad>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>& luaaa::LuaClass<LuaSensor>::ctor<lua_State*, char const*>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>& luaaa::LuaClass<Timer>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
1854 lua_newtable(m_state);
811 }
812
6/6
luaaa::LuaClass<SignalDebounce>& luaaa::LuaClass<SignalDebounce>::ctor<float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>& luaaa::LuaClass<LuaIndustrialPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>& luaaa::LuaClass<LuaPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>& luaaa::LuaClass<LuaBiQuad>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>& luaaa::LuaClass<LuaSensor>::ctor<lua_State*, char const*>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>& luaaa::LuaClass<Timer>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
1854 luaL_setfuncs(m_state, constructor, 0);
813
6/6
luaaa::LuaClass<SignalDebounce>& luaaa::LuaClass<SignalDebounce>::ctor<float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaIndustrialPid>& luaaa::LuaClass<LuaIndustrialPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaPid>& luaaa::LuaClass<LuaPid>::ctor<float, float, float, float, float>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaBiQuad>& luaaa::LuaClass<LuaBiQuad>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<LuaSensor>& luaaa::LuaClass<LuaSensor>::ctor<lua_State*, char const*>(char const*):
✓ Branch 1 taken 309 times.
luaaa::LuaClass<Timer>& luaaa::LuaClass<Timer>::ctor<>(char const*):
✓ Branch 1 taken 309 times.
1854 lua_setglobal(m_state, klassName);
814 #else
815 luaL_openlib(m_state, klassName, constructor, 0);
816 #endif
817
818 1854 return (*this);
819 }
820
821 template<typename ...ARGS>
822 inline LuaClass<TCLASS>& ctor(const char * name, TCLASS*(*spawner)(ARGS...)) {
823 typedef decltype(spawner) SPAWNERFTYPE;
824 struct HelperClass {
825 static int f_gc(lua_State* state) {
826 TCLASS ** objPtr = (TCLASS**)luaL_checkudata(state, -1, LuaClass<TCLASS>::klassName);
827 if (objPtr)
828 {
829 DestructorCaller<TCLASS>::Invoke(*objPtr);
830 }
831 return 0;
832 }
833
834 static int f_new(lua_State* state) {
835 void * spawner = lua_touserdata(state, lua_upvalueindex(1));
836 luaL_argcheck(state, spawner, 1, "cpp closure spawner not found.");
837 if (spawner) {
838 auto obj = LuaInvoke<TCLASS*, SPAWNERFTYPE, ARGS...>(state, spawner, 0);
839 if (obj)
840 {
841 TCLASS ** objPtr = (TCLASS**)lua_newuserdata(state, sizeof(TCLASS*));
842 if (objPtr)
843 {
844 *objPtr = obj;
845
846 luaL_Reg destructor[] = { { "__gc", HelperClass::f_gc }, { nullptr, nullptr } };
847 luaL_getmetatable(state, LuaClass<TCLASS>::klassName);
848 luaL_setfuncs(state, destructor, 0);
849 lua_setmetatable(state, -2);
850
851 return 1;
852 }
853 else
854 {
855 DestructorCaller<TCLASS>::Invoke(obj);
856 }
857 }
858 }
859 lua_pushnil(state);
860 return 1;
861 }
862
863 };
864
865 luaL_Reg constructor[] = { { name, HelperClass::f_new },{ nullptr, nullptr } };
866 #if USE_NEW_MODULE_REGISTRY
867 lua_getglobal(m_state, klassName);
868 if (lua_isnil(m_state, -1))
869 {
870 lua_pop(m_state, 1);
871 lua_newtable(m_state);
872 }
873 #endif
874
875 SPAWNERFTYPE * spawnerPtr = (SPAWNERFTYPE*)lua_newuserdata(m_state, sizeof(SPAWNERFTYPE));
876 # ifndef LUAAA_WITHOUT_CPP_STDLIB
877 luaL_argcheck(m_state, spawnerPtr != nullptr, 1, (std::string("faild to alloc mem to store spawner for ctor `") + name + "`").c_str());
878 # else
879 luaL_argcheck(m_state, spawnerPtr != nullptr, 1, "faild to alloc mem to store spawner for ctor");
880 # endif
881 *spawnerPtr = spawner;
882
883 #if USE_NEW_MODULE_REGISTRY
884 luaL_setfuncs(m_state, constructor, 1);
885 lua_setglobal(m_state, klassName);
886 #else
887 luaL_openlib(m_state, klassName, constructor, 1);
888 #endif
889
890 return (*this);
891 }
892
893 template<typename TRET, typename ...ARGS>
894 inline LuaClass<TCLASS>& ctor(const char * name, TCLASS*(*spawner)(ARGS...), TRET(*deleter)(TCLASS*)){
895 typedef decltype(spawner) SPAWNERFTYPE;
896 typedef decltype(deleter) DELETERFTYPE;
897
898 struct HelperClass {
899 static int f_gc(lua_State* state) {
900 void * deleter = lua_touserdata(state, lua_upvalueindex(1));
901 luaL_argcheck(state, deleter, 1, "cpp closure deleter not found.");
902 if (deleter) {
903 TCLASS ** objPtr = (TCLASS**)luaL_checkudata(state, -1, LuaClass<TCLASS>::klassName);
904 if (objPtr)
905 {
906 (*(DELETERFTYPE*)(deleter))(*objPtr);
907 }
908 }
909
910 return 0;
911 }
912
913 static int f_new(lua_State* state) {
914 void * spawner = lua_touserdata(state, lua_upvalueindex(1));
915 luaL_argcheck(state, spawner, 1, "cpp closure spawner not found.");
916
917 void * deleter = lua_touserdata(state, lua_upvalueindex(2));
918 luaL_argcheck(state, deleter, 1, "cpp closure deleter not found.");
919
920 if (spawner) {
921 auto obj = LuaInvoke<TCLASS*, SPAWNERFTYPE, ARGS...>(state, spawner, 0);
922 if (obj)
923 {
924 TCLASS ** objPtr = (TCLASS**)lua_newuserdata(state, sizeof(TCLASS*));
925 if (objPtr)
926 {
927 *objPtr = obj;
928
929 luaL_Reg destructor[] = { { "__gc", HelperClass::f_gc }, { nullptr, nullptr } };
930
931
932 luaL_getmetatable(state, LuaClass<TCLASS>::klassName);
933
934 DELETERFTYPE * deleterPtr = (DELETERFTYPE*)lua_newuserdata(state, sizeof(DELETERFTYPE));
935 # ifndef LUAAA_WITHOUT_CPP_STDLIB
936 luaL_argcheck(state, deleterPtr != nullptr, 1, (std::string("faild to alloc mem to store deleter for ctor meta table `") + LuaClass<TCLASS>::klassName + "`").c_str());
937 # else
938 luaL_argcheck(state, deleterPtr != nullptr, 1, "faild to alloc mem to store deleter for ctor meta table");
939 # endif
940 *deleterPtr = *(DELETERFTYPE*)(deleter);
941 luaL_setfuncs(state, destructor, 1);
942 lua_setmetatable(state, -2);
943 return 1;
944 }
945 else
946 {
947 if (deleter) {
948 (*(DELETERFTYPE*)(deleter))(obj);
949 }
950 }
951 }
952 }
953 lua_pushnil(state);
954 return 1;
955 }
956
957 };
958
959 luaL_Reg constructor[] = { { name, HelperClass::f_new },{ nullptr, nullptr } };
960
961 #if USE_NEW_MODULE_REGISTRY
962 lua_getglobal(m_state, klassName);
963 if (lua_isnil(m_state, -1))
964 {
965 lua_pop(m_state, 1);
966 lua_newtable(m_state);
967 }
968 #endif
969
970 SPAWNERFTYPE * spawnerPtr = (SPAWNERFTYPE*)lua_newuserdata(m_state, sizeof(SPAWNERFTYPE));
971 # ifndef LUAAA_WITHOUT_CPP_STDLIB
972 luaL_argcheck(m_state, spawnerPtr != nullptr, 1, (std::string("faild to alloc mem to store spawner for ctor `") + name + "`").c_str());
973 # else
974 luaL_argcheck(m_state, spawnerPtr != nullptr, 1, ("faild to alloc mem to store spawner for ctor"));
975 # endif
976 *spawnerPtr = spawner;
977
978 DELETERFTYPE * deleterPtr = (DELETERFTYPE*)lua_newuserdata(m_state, sizeof(DELETERFTYPE));
979 # ifndef LUAAA_WITHOUT_CPP_STDLIB
980 luaL_argcheck(m_state, deleterPtr != nullptr, 1, (std::string("faild to alloc mem to store deleter for ctor `") + name + "`").c_str());
981 # else
982 luaL_argcheck(m_state, spawnerPtr != nullptr, 1, ("faild to alloc mem to store deleter for ctor"));
983 # endif
984 *deleterPtr = deleter;
985
986 #if USE_NEW_MODULE_REGISTRY
987 luaL_setfuncs(m_state, constructor, 2);
988 lua_setglobal(m_state, klassName);
989 #else
990 luaL_openlib(m_state, klassName, constructor, 2);
991 #endif
992
993 return (*this);
994 }
995
996 template<typename ...ARGS>
997 inline LuaClass<TCLASS>& ctor(const char * name, TCLASS*(*spawner)(ARGS...), std::nullptr_t) {
998 typedef decltype(spawner) SPAWNERFTYPE;
999
1000 struct HelperClass {
1001 static int f_nogc(lua_State* state) {
1002 return 0;
1003 }
1004
1005 static int f_new(lua_State* state) {
1006 void * spawner = lua_touserdata(state, lua_upvalueindex(1));
1007 luaL_argcheck(state, spawner, 1, "cpp closure spawner not found.");
1008 if (spawner) {
1009 auto obj = LuaInvoke<TCLASS*, SPAWNERFTYPE, ARGS...>(state, spawner, 0);
1010 if (obj)
1011 {
1012 TCLASS ** objPtr = (TCLASS**)lua_newuserdata(state, sizeof(TCLASS*));
1013 if (objPtr)
1014 {
1015 *objPtr = obj;
1016
1017 luaL_Reg destructor[] = {
1018 { "__gc", HelperClass::f_nogc },
1019 { nullptr, nullptr }
1020 };
1021
1022 luaL_getmetatable(state, LuaClass<TCLASS>::klassName);
1023 luaL_setfuncs(state, destructor, 0);
1024 lua_setmetatable(state, -2);
1025 return 1;
1026 }
1027 }
1028 }
1029 lua_pushnil(state);
1030 return 1;
1031 }
1032
1033 };
1034
1035 luaL_Reg constructor[] = { { name, HelperClass::f_new },{ nullptr, nullptr } };
1036
1037 #if USE_NEW_MODULE_REGISTRY
1038 lua_getglobal(m_state, klassName);
1039 if (lua_isnil(m_state, -1))
1040 {
1041 lua_pop(m_state, 1);
1042 lua_newtable(m_state);
1043 }
1044 #endif
1045 SPAWNERFTYPE * spawnerPtr = (SPAWNERFTYPE*)lua_newuserdata(m_state, sizeof(SPAWNERFTYPE));
1046 #ifndef LUAAA_WITHOUT_CPP_STDLIB
1047 luaL_argcheck(m_state, spawnerPtr != nullptr, 1, (std::string("faild to alloc mem to store spawner for ctor `") + name + "`").c_str());
1048 #else
1049 luaL_argcheck(m_state, spawnerPtr != nullptr, 1, "faild to alloc mem to store spawner for ctor of cpp class");
1050 #endif
1051 *spawnerPtr = spawner;
1052
1053 #if USE_NEW_MODULE_REGISTRY
1054 luaL_setfuncs(m_state, constructor, 1);
1055 lua_setglobal(m_state, klassName);
1056 #else
1057 luaL_openlib(m_state, klassName, constructor, 1);
1058 #endif
1059
1060 return (*this);
1061 }
1062
1063
1064 #ifndef LUAAA_WITHOUT_CPP_STDLIB
1065 template<typename ...ARGS>
1066 inline LuaClass<TCLASS>& ctor(const std::string& name)
1067 {
1068 return ctor<ARGS...>(name.c_str());
1069 }
1070
1071 template<typename ...ARGS>
1072 inline LuaClass<TCLASS>& ctor(const std::string& name, TCLASS*(*spawner)(ARGS...)) {
1073 return ctor(name.c_str(), spawner);
1074 }
1075
1076 template<typename TRET, typename ...ARGS>
1077 inline LuaClass<TCLASS>& ctor(const std::string& name, TCLASS*(*spawner)(ARGS...), TRET(*deleter)(TCLASS*)) {
1078 return ctor(name.c_str(), spawner, deleter);
1079 }
1080
1081 template<typename ...ARGS>
1082 inline LuaClass<TCLASS>& ctor(const std::string& name, TCLASS*(*spawner)(ARGS...), std::nullptr_t) {
1083 return ctor(name.c_str(), spawner, nullptr);
1084 }
1085 #endif
1086
1087 template<typename F>
1088 inline LuaClass<TCLASS>& fun(const char * name, F f)
1089 {
1090 luaL_getmetatable(m_state, klassName);
1091 lua_pushstring(m_state, name);
1092
1093 F * funPtr = (F*)lua_newuserdata(m_state, sizeof(F));
1094 #ifndef LUAAA_WITHOUT_CPP_STDLIB
1095 luaL_argcheck(m_state, funPtr != nullptr, 1, (std::string("faild to alloc mem to store function `") + name + "`").c_str());
1096 #else
1097 luaL_argcheck(m_state, funPtr != nullptr, 1, "faild to alloc mem to store function");
1098 #endif
1099 *funPtr = f;
1100 lua_pushcclosure(m_state, MemberFunctionCaller(f), 1);
1101 lua_settable(m_state, -3);
1102 lua_pop(m_state, 1);
1103 return (*this);
1104 }
1105
1106 inline LuaClass<TCLASS>& fun(const char * name, lua_CFunction f)
1107 {
1108 luaL_getmetatable(m_state, klassName);
1109 lua_pushstring(m_state, name);
1110 lua_pushcclosure(m_state, f, 0);
1111 lua_settable(m_state, -3);
1112 lua_pop(m_state, 1);
1113 return (*this);
1114 }
1115
1116 #ifndef LUAAA_WITHOUT_CPP_STDLIB
1117 template <typename F>
1118 inline LuaClass<TCLASS>& fun(const std::string& name, F f)
1119 {
1120 return fun(name.c_str(), f);
1121 }
1122 #endif
1123
1124 template <typename V>
1125 inline LuaClass<TCLASS>& def(const char * name, const V& val)
1126 {
1127 luaL_getmetatable(m_state, klassName);
1128 lua_pushstring(m_state, name);
1129 LuaStack<V>::put(m_state, val);
1130 lua_settable(m_state, -3);
1131 lua_pop(m_state, 1);
1132 return (*this);
1133 }
1134
1135 // disable cast from "const char [#]" to "char (*)[#]"
1136 inline LuaClass<TCLASS>& def(const char * name, const char * str)
1137 {
1138 luaL_getmetatable(m_state, klassName);
1139 lua_pushstring(m_state, name);
1140 LuaStack<decltype(str)>::put(m_state, str);
1141 lua_settable(m_state, -3);
1142 lua_pop(m_state, 1);
1143 return (*this);
1144 }
1145
1146 #ifndef LUAAA_WITHOUT_CPP_STDLIB
1147 template <typename V>
1148 inline LuaClass<TCLASS>& def(const std::string& name, const V& val)
1149 {
1150 return def(name.c_str(), val);
1151 }
1152 #endif
1153
1154 private:
1155 lua_State * m_state;
1156
1157 private:
1158 static char * klassName;
1159 };
1160
1161 template <typename TCLASS> char * LuaClass<TCLASS>::klassName = nullptr;
1162
1163
1164 // -----------------------------------
1165 // export module
1166 // -----------------------------------
1167 struct LuaModule
1168 {
1169 public:
1170
1171 LuaModule(lua_State * state, const char * name = "_G")
1172 : m_state(state)
1173 {
1174 size_t strBufLen = strlen(name) + 1;
1175 m_moduleName = reinterpret_cast<char *>(lua_newuserdata(state, strBufLen));
1176 memcpy(m_moduleName, name, strBufLen);
1177 }
1178
1179 #ifndef LUAAA_WITHOUT_CPP_STDLIB
1180 LuaModule(lua_State * state, const std::string& name)
1181 : LuaModule(state, name.empty() ? "_G" : name.c_str())
1182 {}
1183 #endif
1184
1185 public:
1186 template<typename F>
1187 inline LuaModule& fun(const char * name, F f)
1188 {
1189 luaL_Reg regtab[] = { { name, NonMemberFunctionCaller(f) },{ nullptr, nullptr } };
1190
1191 #if USE_NEW_MODULE_REGISTRY
1192 lua_getglobal(m_state, m_moduleName);
1193 if (lua_isnil(m_state, -1))
1194 {
1195 lua_pop(m_state, 1);
1196 lua_newtable(m_state);
1197 }
1198
1199 F * funPtr = (F*)lua_newuserdata(m_state, sizeof(F));
1200 # ifndef LUAAA_WITHOUT_CPP_STDLIB
1201 luaL_argcheck(m_state, funPtr != nullptr, 1, (std::string("faild to alloc mem to store function `") + name + "`").c_str());
1202 # else
1203 luaL_argcheck(m_state, funPtr != nullptr, 1, "faild to alloc mem to store function of module");
1204 # endif
1205 *funPtr = f;
1206
1207 luaL_setfuncs(m_state, regtab, 1);
1208 lua_setglobal(m_state, m_moduleName);
1209 #else
1210 F * funPtr = (F*)lua_newuserdata(m_state, sizeof(F));
1211 # ifndef LUAAA_WITHOUT_CPP_STDLIB
1212 luaL_argcheck(m_state, funPtr != nullptr, 1, (std::string("faild to alloc mem to store function `") + name + "`").c_str());
1213 # else
1214 luaL_argcheck(m_state, funPtr != nullptr, 1, "faild to alloc mem to store function of module");
1215 # endif
1216 *funPtr = f;
1217
1218 luaL_openlib(m_state, m_moduleName, regtab, 1);
1219 #endif
1220
1221 return (*this);
1222 }
1223
1224 inline LuaModule& fun(const char * name, lua_CFunction f)
1225 {
1226 luaL_Reg regtab[] = { { name, f },{ nullptr, nullptr } };
1227 #if USE_NEW_MODULE_REGISTRY
1228 lua_getglobal(m_state, m_moduleName);
1229 if (lua_isnil(m_state, -1))
1230 {
1231 lua_pop(m_state, 1);
1232 lua_newtable(m_state);
1233 }
1234 luaL_setfuncs(m_state, regtab, 0);
1235 lua_setglobal(m_state, m_moduleName);
1236 #else
1237 luaL_openlib(m_state, m_moduleName, regtab, 0);
1238 #endif
1239 return (*this);
1240 }
1241
1242 template <typename V>
1243 inline LuaModule& def(const char * name, const V& val)
1244 {
1245 #if USE_NEW_MODULE_REGISTRY
1246 lua_getglobal(m_state, m_moduleName);
1247 if (lua_isnil(m_state, -1))
1248 {
1249 lua_pop(m_state, 1);
1250 lua_newtable(m_state);
1251 }
1252 LuaStack<V>::put(m_state, val);
1253 lua_setfield(m_state, -2, name);
1254 lua_setglobal(m_state, m_moduleName);
1255 #else
1256 luaL_Reg regtab = { nullptr, nullptr };
1257 luaL_openlib(m_state, m_moduleName, &regtab, 0);
1258 LuaStack<V>::put(m_state, val);
1259 lua_setfield(m_state, -2, name);
1260 #endif
1261 return (*this);
1262 }
1263
1264 template <typename V>
1265 inline LuaModule& def(const char * name, const V val[], size_t length)
1266 {
1267 #if USE_NEW_MODULE_REGISTRY
1268 lua_getglobal(m_state, m_moduleName);
1269 if (lua_isnil(m_state, -1))
1270 {
1271 lua_pop(m_state, 1);
1272 lua_newtable(m_state);
1273 }
1274 lua_newtable(m_state);
1275 for (size_t idx = 0; idx < length; ++idx)
1276 {
1277 LuaStack<V>::put(m_state, val[idx]);
1278 lua_rawseti(m_state, -2, idx + 1);
1279 }
1280 lua_setfield(m_state, -2, name);
1281 lua_setglobal(m_state, m_moduleName);
1282 #else
1283 luaL_Reg regtab = { nullptr, nullptr };
1284 luaL_openlib(m_state, m_moduleName, &regtab, 0);
1285 lua_newtable(m_state);
1286 for (size_t idx = 0; idx < length; ++idx)
1287 {
1288 LuaStack<V>::put(m_state, val[idx]);
1289 lua_rawseti(m_state, -2, idx + 1);
1290 }
1291 lua_setfield(m_state, -2, name);
1292 #endif
1293 return (*this);
1294 }
1295
1296 // disable the cast from "const char [#]" to "char (*)[#]"
1297 inline LuaModule& def(const char * name, const char * str)
1298 {
1299
1300 #if USE_NEW_MODULE_REGISTRY
1301 lua_getglobal(m_state, m_moduleName);
1302 if (lua_isnil(m_state, -1))
1303 {
1304 lua_pop(m_state, 1);
1305 lua_newtable(m_state);
1306 }
1307 LuaStack<decltype(str)>::put(m_state, str);
1308 lua_setfield(m_state, -2, name);
1309 lua_setglobal(m_state, m_moduleName);
1310 #else
1311 luaL_Reg regtab = { nullptr, nullptr };
1312 luaL_openlib(m_state, m_moduleName.c_str(), &regtab, 0);
1313 LuaStack<decltype(str)>::put(m_state, str);
1314 lua_setfield(m_state, -2, name);
1315 #endif
1316 return (*this);
1317 }
1318
1319 #ifndef LUAAA_WITHOUT_CPP_STDLIB
1320 template <typename V>
1321 inline LuaModule& def(const std::string& name, const V& val)
1322 {
1323 return def(name.c_str(), val);
1324 }
1325 #endif
1326
1327 private:
1328 lua_State * m_state;
1329 char * m_moduleName;
1330 };
1331
1332 }
1333
1334
1335
1336 #ifndef LUAAA_WITHOUT_CPP_STDLIB
1337
1338 #include <array>
1339 #include <vector>
1340 #include <deque>
1341 #include <list>
1342 #include <forward_list>
1343 #include <set>
1344 #include <map>
1345 #include <unordered_set>
1346 #include <unordered_map>
1347
1348 namespace LUAAA_NS
1349 {
1350 // array
1351 template<typename K, size_t N>
1352 struct LuaStack<std::array<K, N>>
1353 {
1354 typedef std::array<K, N> Container;
1355 inline static Container get(lua_State * L, int idx)
1356 {
1357 Container result;
1358
1359 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1360 if (lua_istable(L, idx))
1361 {
1362 int index = 0;
1363 lua_pushnil(L);
1364 while (0 != lua_next(L, idx) && index < N)
1365 {
1366 result[index++] = LuaStack<typename Container::value_type>::get(L, lua_gettop(L));
1367 lua_pop(L, 1);
1368 }
1369 lua_pop(L, 0);
1370 }
1371 return result;
1372 }
1373 inline static void put(lua_State * L, const Container& s)
1374 {
1375 lua_newtable(L);
1376 int index = 1;
1377 for (auto it = s.begin(); it != s.end(); ++it)
1378 {
1379 LuaStack<typename Container::value_type>::put(L, *it);
1380 lua_rawseti(L, -2, index++);
1381 }
1382 }
1383 };
1384
1385 // vector
1386 template<typename K, typename ...ARGS>
1387 struct LuaStack<std::vector<K, ARGS...>>
1388 {
1389 typedef std::vector<K, ARGS...> Container;
1390 inline static Container get(lua_State * L, int idx)
1391 {
1392 Container result;
1393 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1394 if (lua_istable(L, idx))
1395 {
1396 lua_pushnil(L);
1397 while (0 != lua_next(L, idx))
1398 {
1399 result.push_back(LuaStack<typename Container::value_type>::get(L, lua_gettop(L)));
1400 lua_pop(L, 1);
1401 }
1402 lua_pop(L, 0);
1403 }
1404 return result;
1405 }
1406 inline static void put(lua_State * L, const Container& s)
1407 {
1408 lua_newtable(L);
1409 int index = 1;
1410 for (auto it = s.begin(); it != s.end(); ++it)
1411 {
1412 LuaStack<typename Container::value_type>::put(L, *it);
1413 lua_rawseti(L, -2, index++);
1414 }
1415 }
1416 };
1417
1418 // deque
1419 template<typename K, typename ...ARGS>
1420 struct LuaStack<std::deque<K, ARGS...>>
1421 {
1422 typedef std::deque<K, ARGS...> Container;
1423 inline static Container get(lua_State * L, int idx)
1424 {
1425 Container result;
1426 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1427 if (lua_istable(L, idx))
1428 {
1429 lua_pushnil(L);
1430 while (0 != lua_next(L, idx))
1431 {
1432 result.push_back(LuaStack<typename Container::value_type>::get(L, lua_gettop(L)));
1433 lua_pop(L, 1);
1434 }
1435 lua_pop(L, 0);
1436 }
1437 return result;
1438 }
1439 inline static void put(lua_State * L, const Container& s)
1440 {
1441 lua_newtable(L);
1442 int index = 1;
1443 for (auto it = s.begin(); it != s.end(); ++it)
1444 {
1445 LuaStack<typename Container::value_type>::put(L, *it);
1446 lua_rawseti(L, -2, index++);
1447 }
1448 }
1449 };
1450
1451 // list
1452 template<typename K, typename ...ARGS>
1453 struct LuaStack<std::list<K, ARGS...>>
1454 {
1455 typedef std::list<K, ARGS...> Container;
1456 inline static Container get(lua_State * L, int idx)
1457 {
1458 Container result;
1459 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1460 if (lua_istable(L, idx))
1461 {
1462 lua_pushnil(L);
1463 while (0 != lua_next(L, idx))
1464 {
1465 result.push_back(LuaStack<typename Container::value_type>::get(L, lua_gettop(L)));
1466 lua_pop(L, 1);
1467 }
1468 lua_pop(L, 0);
1469 }
1470 return result;
1471 }
1472 inline static void put(lua_State * L, const Container& s)
1473 {
1474 lua_newtable(L);
1475 int index = 1;
1476 for (auto it = s.begin(); it != s.end(); ++it)
1477 {
1478 LuaStack<typename Container::value_type>::put(L, *it);
1479 lua_rawseti(L, -2, index++);
1480 }
1481 }
1482 };
1483
1484 // forward_list
1485 template<typename K, typename ...ARGS>
1486 struct LuaStack<std::forward_list<K, ARGS...>>
1487 {
1488 typedef std::forward_list<K, ARGS...> Container;
1489 inline static Container get(lua_State * L, int idx)
1490 {
1491 Container result;
1492 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1493 if (lua_istable(L, idx))
1494 {
1495 lua_pushnil(L);
1496 while (0 != lua_next(L, idx))
1497 {
1498 result.push_back(LuaStack<typename Container::value_type>::get(L, lua_gettop(L)));
1499 lua_pop(L, 1);
1500 }
1501 lua_pop(L, 0);
1502 }
1503 return result;
1504 }
1505 inline static void put(lua_State * L, const Container& s)
1506 {
1507 lua_newtable(L);
1508 int index = 1;
1509 for (auto it = s.begin(); it != s.end(); ++it)
1510 {
1511 LuaStack<typename Container::value_type>::put(L, *it);
1512 lua_rawseti(L, -2, index++);
1513 }
1514 }
1515 };
1516
1517 // set
1518 template<typename K, typename ...ARGS>
1519 struct LuaStack<std::set<K, ARGS...>>
1520 {
1521 typedef std::set<K, ARGS...> Container;
1522 inline static Container get(lua_State * L, int idx)
1523 {
1524 Container result;
1525 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1526 if (lua_istable(L, idx))
1527 {
1528 lua_pushnil(L);
1529 while (0 != lua_next(L, idx))
1530 {
1531 result.insert(LuaStack<typename Container::value_type>::get(L, lua_gettop(L)));
1532 lua_pop(L, 1);
1533 }
1534 lua_pop(L, 0);
1535 }
1536 return result;
1537 }
1538 inline static void put(lua_State * L, const Container& s)
1539 {
1540 lua_newtable(L);
1541 int index = 1;
1542 for (auto it = s.begin(); it != s.end(); ++it)
1543 {
1544 LuaStack<typename Container::value_type>::put(L, *it);
1545 lua_rawseti(L, -2, index++);
1546 }
1547 }
1548 };
1549
1550 // multiset
1551 template<typename K, typename ...ARGS>
1552 struct LuaStack<std::multiset<K, ARGS...>>
1553 {
1554 typedef std::multiset<K, ARGS...> Container;
1555 inline static Container get(lua_State * L, int idx)
1556 {
1557 Container result;
1558 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1559 if (lua_istable(L, idx))
1560 {
1561 lua_pushnil(L);
1562 while (0 != lua_next(L, idx))
1563 {
1564 result.insert(LuaStack<typename Container::value_type>::get(L, lua_gettop(L)));
1565 lua_pop(L, 1);
1566 }
1567 lua_pop(L, 0);
1568 }
1569 return result;
1570 }
1571 inline static void put(lua_State * L, const Container& s)
1572 {
1573 lua_newtable(L);
1574 int index = 1;
1575 for (auto it = s.begin(); it != s.end(); ++it)
1576 {
1577 LuaStack<typename Container::value_type>::put(L, *it);
1578 lua_rawseti(L, -2, index++);
1579 }
1580 }
1581 };
1582
1583 // unordered_set
1584 template<typename K, typename ...ARGS>
1585 struct LuaStack<std::unordered_set<K, ARGS...>>
1586 {
1587 typedef std::unordered_set<K, ARGS...> Container;
1588 inline static Container get(lua_State * L, int idx)
1589 {
1590 Container result;
1591 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1592 if (lua_istable(L, idx))
1593 {
1594 lua_pushnil(L);
1595 while (0 != lua_next(L, idx))
1596 {
1597 result.insert(LuaStack<typename Container::value_type>::get(L, lua_gettop(L)));
1598 lua_pop(L, 1);
1599 }
1600 lua_pop(L, 0);
1601 }
1602 return result;
1603 }
1604
1605 inline static void put(lua_State * L, const Container& s)
1606 {
1607 lua_newtable(L);
1608 int index = 1;
1609 for (auto it = s.begin(); it != s.end(); ++it)
1610 {
1611 LuaStack<typename Container::value_type>::put(L, *it);
1612 lua_rawseti(L, -2, index++);
1613 }
1614 }
1615 };
1616
1617 // unordered_multiset
1618 template<typename K, typename ...ARGS>
1619 struct LuaStack<std::unordered_multiset<K, ARGS...>>
1620 {
1621 typedef std::unordered_multiset<K, ARGS...> Container;
1622 inline static Container get(lua_State * L, int idx)
1623 {
1624 Container result;
1625 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1626 if (lua_istable(L, idx))
1627 {
1628 lua_pushnil(L);
1629 while (0 != lua_next(L, idx))
1630 {
1631 result.insert(LuaStack<typename Container::value_type>::get(L, lua_gettop(L)));
1632 lua_pop(L, 1);
1633 }
1634 lua_pop(L, 0);
1635 }
1636 return result;
1637 }
1638
1639 inline static void put(lua_State * L, const Container& s)
1640 {
1641 lua_newtable(L);
1642 int index = 1;
1643 for (auto it = s.begin(); it != s.end(); ++it)
1644 {
1645 LuaStack<typename Container::value_type>::put(L, *it);
1646 lua_rawseti(L, -2, index++);
1647 }
1648 }
1649 };
1650
1651 // map
1652 template<typename K, typename V, typename ...ARGS>
1653 struct LuaStack<std::map<K, V, ARGS...>>
1654 {
1655 typedef std::map<K, V, ARGS...> Container;
1656 inline static Container get(lua_State * L, int idx)
1657 {
1658 Container result;
1659 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1660 if (lua_istable(L, idx))
1661 {
1662 lua_pushnil(L);
1663 while (0 != lua_next(L, idx))
1664 {
1665 const int top = lua_gettop(L);
1666 result[LuaStack<typename Container::key_type>::get(L, top - 1)] = LuaStack<typename Container::mapped_type>::get(L, top);
1667 lua_pop(L, 1);
1668 }
1669 lua_pop(L, 0);
1670 }
1671 return result;
1672 }
1673 inline static void put(lua_State * L, const Container& s)
1674 {
1675 lua_newtable(L);
1676 for (auto it = s.begin(); it != s.end(); ++it)
1677 {
1678 LuaStack<typename Container::key_type>::put(L, it->first);
1679 LuaStack<typename Container::mapped_type>::put(L, it->second);
1680 lua_rawset(L, -3);
1681 }
1682 }
1683 };
1684
1685 // multimap
1686 template<typename K, typename V, typename ...ARGS>
1687 struct LuaStack<std::multimap<K, V, ARGS...>>
1688 {
1689 typedef std::multimap<K, V, ARGS...> Container;
1690 inline static Container get(lua_State * L, int idx)
1691 {
1692 Container result;
1693 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1694 if (lua_istable(L, idx))
1695 {
1696 lua_pushnil(L);
1697 while (0 != lua_next(L, idx))
1698 {
1699 const int top = lua_gettop(L);
1700 result[LuaStack<typename Container::key_type>::get(L, top - 1)] = LuaStack<typename Container::mapped_type>::get(L, top);
1701 lua_pop(L, 1);
1702 }
1703 lua_pop(L, 0);
1704 }
1705 return result;
1706 }
1707 inline static void put(lua_State * L, const Container& s)
1708 {
1709 lua_newtable(L);
1710 for (auto it = s.begin(); it != s.end(); ++it)
1711 {
1712 LuaStack<typename Container::key_type>::put(L, it->first);
1713 LuaStack<typename Container::mapped_type>::put(L, it->second);
1714 lua_rawset(L, -3);
1715 }
1716 }
1717 };
1718
1719 // unordered_map
1720 template<typename K, typename V, typename ...ARGS>
1721 struct LuaStack<std::unordered_map<K, V, ARGS...>>
1722 {
1723 typedef std::unordered_map<K, V, ARGS...> Container;
1724 inline static Container get(lua_State * L, int idx)
1725 {
1726 Container result;
1727 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1728 if (lua_istable(L, idx))
1729 {
1730 lua_pushnil(L);
1731 while (0 != lua_next(L, idx))
1732 {
1733 const int top = lua_gettop(L);
1734 result[LuaStack<typename Container::key_type>::get(L, top - 1)] = LuaStack<typename Container::mapped_type>::get(L, top);
1735 lua_pop(L, 1);
1736 }
1737 lua_pop(L, 0);
1738 }
1739 return result;
1740 }
1741 inline static void put(lua_State * L, const Container& s)
1742 {
1743 lua_newtable(L);
1744 for (auto it = s.begin(); it != s.end(); ++it)
1745 {
1746 LuaStack<typename Container::key_type>::put(L, it->first);
1747 LuaStack<typename Container::mapped_type>::put(L, it->second);
1748 lua_rawset(L, -3);
1749 }
1750 }
1751 };
1752
1753 // unordered_multimap
1754 template<typename K, typename V, typename ...ARGS>
1755 struct LuaStack<std::unordered_multimap<K, V, ARGS...>>
1756 {
1757 typedef std::unordered_multimap<K, V, ARGS...> Container;
1758 inline static Container get(lua_State * L, int idx)
1759 {
1760 Container result;
1761 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1762 if (lua_istable(L, idx))
1763 {
1764 lua_pushnil(L);
1765 while (0 != lua_next(L, idx))
1766 {
1767 const int top = lua_gettop(L);
1768 result[LuaStack<typename Container::key_type>::get(L, top - 1)] = LuaStack<typename Container::mapped_type>::get(L, top);
1769 lua_pop(L, 1);
1770 }
1771 lua_pop(L, 0);
1772 }
1773 return result;
1774 }
1775 inline static void put(lua_State * L, const Container& s)
1776 {
1777 lua_newtable(L);
1778 for (auto it = s.begin(); it != s.end(); ++it)
1779 {
1780 LuaStack<typename Container::key_type>::put(L, it->first);
1781 LuaStack<typename Container::mapped_type>::put(L, it->second);
1782 lua_rawset(L, -3);
1783 }
1784 }
1785 };
1786
1787
1788 // std::pair
1789 template<typename U, typename V>
1790 struct LuaStack<std::pair<U, V>>
1791 {
1792 typedef std::pair<U, V> Container;
1793 inline static Container get(lua_State * L, int idx)
1794 {
1795 Container result;
1796 luaL_argcheck(L, lua_istable(L, idx), 1, "required table not found on stack.");
1797 if (lua_istable(L, idx))
1798 {
1799 result.first = LuaStack<typename Container::first_type>::get(L, idx + 1);
1800 result.second = LuaStack<typename Container::second_type>::get(L, idx + 2);
1801 }
1802 return result;
1803 }
1804
1805 inline static void put(lua_State * L, const Container& s)
1806 {
1807 lua_newtable(L);
1808 LuaStack<typename Container::first_type>::put(L, s.first);
1809 lua_rawseti(L, -2, 1);
1810 LuaStack<typename Container::second_type>::put(L, s.second);
1811 lua_rawseti(L, -2, 2);
1812 }
1813 };
1814 }
1815
1816 #endif //#if !defined(LUAAA_WITHOUT_CPP_STDLIB)
1817
1818 #endif
1819