summary refs log tree commit diff stats
path: root/vendor
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2021-02-05 20:20:21 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2021-02-05 20:20:21 -0500
commitbd1a66887f00e186ab86a5195ebb3271ea732b38 (patch)
treed3fc0335d98f386877b991f538e2645ff6d74fd1 /vendor
parentccf0fab9f7b8057afc5884e70fff29109f707bf8 (diff)
downloadtanetane-bd1a66887f00e186ab86a5195ebb3271ea732b38.tar.gz
tanetane-bd1a66887f00e186ab86a5195ebb3271ea732b38.tar.bz2
tanetane-bd1a66887f00e186ab86a5195ebb3271ea732b38.zip
Created script system
Diffstat (limited to 'vendor')
-rw-r--r--vendor/sol/config.hpp53
-rw-r--r--vendor/sol/sol.hpp26674
2 files changed, 26727 insertions, 0 deletions
diff --git a/vendor/sol/config.hpp b/vendor/sol/config.hpp new file mode 100644 index 0000000..90ec711 --- /dev/null +++ b/vendor/sol/config.hpp
@@ -0,0 +1,53 @@
1// The MIT License (MIT)
2
3// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors
4
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9// the Software, and to permit persons to whom the Software is furnished to do so,
10// subject to the following conditions:
11
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22// This file was generated with a script.
23// Generated 2020-10-03 21:34:25.034794 UTC
24// This header was generated with sol v3.2.1 (revision 48eea7b5)
25// https://github.com/ThePhD/sol2
26
27#ifndef SOL_SINGLE_CONFIG_HPP
28#define SOL_SINGLE_CONFIG_HPP
29
30// beginning of sol/config.hpp
31
32/* Base, empty configuration file!
33
34 To override, place a file in your include paths of the form:
35
36. (your include path here)
37| sol (directory, or equivalent)
38 | config.hpp (your config.hpp file)
39
40 So that when sol2 includes the file
41
42#include <sol/config.hpp>
43
44 it gives you the configuration values you desire. Configuration values can be
45seen in the safety.rst of the doc/src, or at
46https://sol2.readthedocs.io/en/latest/safety.html ! You can also pass them through
47the build system, or the command line options of your compiler.
48
49*/
50
51// end of sol/config.hpp
52
53#endif // SOL_SINGLE_CONFIG_HPP
diff --git a/vendor/sol/sol.hpp b/vendor/sol/sol.hpp new file mode 100644 index 0000000..c25fd54 --- /dev/null +++ b/vendor/sol/sol.hpp
@@ -0,0 +1,26674 @@
1// The MIT License (MIT)
2
3// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors
4
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9// the Software, and to permit persons to whom the Software is furnished to do so,
10// subject to the following conditions:
11
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22// This file was generated with a script.
23// Generated 2020-10-03 21:34:24.496436 UTC
24// This header was generated with sol v3.2.1 (revision 48eea7b5)
25// https://github.com/ThePhD/sol2
26
27#ifndef SOL_SINGLE_INCLUDE_HPP
28#define SOL_SINGLE_INCLUDE_HPP
29
30// beginning of sol/sol.hpp
31
32#ifndef SOL_HPP
33#define SOL_HPP
34
35// beginning of sol/version.hpp
36
37#include <sol/config.hpp>
38
39#include <cstdint>
40
41#define SOL_VERSION_MAJOR 3
42#define SOL_VERSION_MINOR 5
43#define SOL_VERSION_PATCH 0
44#define SOL_VERSION_STRING "3.5.0"
45#define SOL_VERSION ((SOL_VERSION_MAJOR * 100000) + (SOL_VERSION_MINOR * 100) + (SOL_VERSION_PATCH))
46
47#define SOL_IS_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) != 0)
48#define SOL_IS_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3) == 0)
49#define SOL_IS_DEFAULT_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) > 3)
50#define SOL_IS_DEFAULT_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3 OP_SYMBOL 3) < 0)
51
52#define SOL_ON |
53#define SOL_OFF ^
54#define SOL_DEFAULT_ON +
55#define SOL_DEFAULT_OFF -
56
57#if defined(_MSC_VER)
58 #define SOL_COMPILER_CLANG_I_ SOL_OFF
59 #define SOL_COMPILER_GCC_I_ SOL_OFF
60 #define SOL_COMPILER_EDG_I_ SOL_OFF
61 #define SOL_COMPILER_VCXX_I_ SOL_ON
62#elif defined(__clang__)
63 #define SOL_COMPILER_CLANG_I_ SOL_ON
64 #define SOL_COMPILER_GCC_I_ SOL_OFF
65 #define SOL_COMPILER_EDG_I_ SOL_OFF
66 #define SOL_COMPILER_VCXX_I_ SOL_OFF
67#elif defined(__GNUC__)
68 #define SOL_COMPILER_CLANG_I_ SOL_OFF
69 #define SOL_COMPILER_GCC_I_ SOL_ON
70 #define SOL_COMPILER_EDG_I_ SOL_OFF
71 #define SOL_COMPILER_VCXX_I_ SOL_OFF
72#else
73 #define SOL_COMPILER_CLANG_I_ SOL_OFF
74 #define SOL_COMPILER_GCC_I_ SOL_OFF
75 #define SOL_COMPILER_EDG_I_ SOL_OFF
76 #define SOL_COMPILER_VCXX_I_ SOL_OFF
77#endif
78
79#if defined(__MINGW32__)
80 #define SOL_COMPILER_FRONTEND_MINGW_I_ SOL_ON
81#else
82 #define SOL_COMPILER_FRONTEND_MINGW_I_ SOL_OFF
83#endif
84
85#if SIZE_MAX <= 0xFFFFULL
86 #define SOL_PLATFORM_X16_I_ SOL_ON
87 #define SOL_PLATFORM_X86_I_ SOL_OFF
88 #define SOL_PLATFORM_X64_I_ SOL_OFF
89#elif SIZE_MAX <= 0xFFFFFFFFULL
90 #define SOL_PLATFORM_X16_I_ SOL_OFF
91 #define SOL_PLATFORM_X86_I_ SOL_ON
92 #define SOL_PLATFORM_X64_I_ SOL_OFF
93#else
94 #define SOL_PLATFORM_X16_I_ SOL_OFF
95 #define SOL_PLATFORM_X86_I_ SOL_OFF
96 #define SOL_PLATFORM_X64_I_ SOL_ON
97#endif
98
99#define SOL_PLATFORM_ARM32_I_ SOL_OFF
100#define SOL_PLATFORM_ARM64_I_ SOL_OFF
101
102#if defined(_WIN32)
103 #define SOL_PLATFORM_WINDOWS_I_ SOL_ON
104#else
105 #define SOL_PLATFORM_WINDOWS_I_ SOL_OFF
106#endif
107#if defined(__APPLE__)
108 #define SOL_PLATFORM_APPLE_I_ SOL_ON
109#else
110 #define SOL_PLATFORM_APPLE_I_ SOL_OFF
111#endif
112#if defined(__unix__)
113 #define SOL_PLATFORM_UNIXLIKE_I_ SOL_ON
114#else
115 #define SOL_PLATFORM_UNIXLIKE_I_ SOL_OFF
116#endif
117#if defined(__linux__)
118 #define SOL_PLATFORM_LINUXLIKE_I_ SOL_ON
119#else
120 #define SOL_PLATFORM_LINUXLIKE_I_ SOL_OFF
121#endif
122
123#define SOL_PLATFORM_APPLE_IPHONE_I_ SOL_OFF
124#define SOL_PLATFORM_BSDLIKE_I_ SOL_OFF
125
126#if defined(SOL_IN_DEBUG_DETECTED)
127 #if SOL_IN_DEBUG_DETECTED != 0
128 #define SOL_DEBUG_BUILD_I_ SOL_ON
129 #else
130 #define SOL_DEBUG_BUILD_I_ SOL_OFF
131 #endif
132#elif !defined(NDEBUG)
133 #if SOL_IS_ON(SOL_COMPILER_VCXX_I_) && defined(_DEBUG)
134 #define SOL_DEBUG_BUILD_I_ SOL_ON
135 #elif (SOL_IS_ON(SOL_COMPILER_CLANG_I_) || SOL_IS_ON(SOL_COMPILER_GCC_I_)) && !defined(__OPTIMIZE__)
136 #define SOL_DEBUG_BUILD_I_ SOL_ON
137 #else
138 #define SOL_DEBUG_BUILD_I_ SOL_OFF
139 #endif
140#else
141 #define SOL_DEBUG_BUILD_I_ SOL_DEFAULT_OFF
142#endif // We are in a debug mode of some sort
143
144#if defined(SOL_NO_EXCEPTIONS)
145 #if (SOL_NO_EXCEPTIONS != 0)
146 #define SOL_EXCEPTIONS_I_ SOL_OFF
147 #else
148 #define SOL_EXCEPTIONS_I_ SOL_ON
149 #endif
150#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_)
151 #if !defined(_CPPUNWIND)
152 #define SOL_EXCEPTIONS_I_ SOL_OFF
153 #else
154 #define SOL_EXCEPTIONS_I_ SOL_ON
155 #endif
156#elif SOL_IS_ON(SOL_COMPILER_CLANG_I_) || SOL_IS_ON(SOL_COMPILER_GCC_I_)
157 #if !defined(__EXCEPTIONS)
158 #define SOL_EXCEPTIONS_I_ SOL_OFF
159 #else
160 #define SOL_EXCEPTIONS_I_ SOL_ON
161 #endif
162#else
163 #define SOL_EXCEPTIONS_I_ SOL_DEFAULT_ON
164#endif
165
166#if defined(SOL_NO_RTTI)
167 #if (SOL_NO_RTTI != 0)
168 #define SOL_RTTI_I_ SOL_OFF
169 #else
170 #define SOL_RTTI_I_ SOL_ON
171 #endif
172#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_)
173 #if !defined(_CPPRTTI)
174 #define SOL_RTTI_I_ SOL_OFF
175 #else
176 #define SOL_RTTI_I_ SOL_ON
177 #endif
178#elif SOL_IS_ON(SOL_COMPILER_CLANG_I_) || SOL_IS_ON(SOL_COMPILER_GCC_I_)
179 #if !defined(__GXX_RTTI)
180 #define SOL_RTTI_I_ SOL_OFF
181 #else
182 #define SOL_RTTI_I_ SOL_ON
183 #endif
184#else
185 #define SOL_RTTI_I_ SOL_DEFAULT_ON
186#endif
187
188#if defined(SOL_NO_THREAD_LOCAL) && (SOL_NO_THREAD_LOCAL != 0)
189 #define SOL_USE_THREAD_LOCAL_I_ SOL_OFF
190#else
191 #define SOL_USE_THREAD_LOCAL_I_ SOL_DEFAULT_ON
192#endif // thread_local keyword is bjorked on some platforms
193
194#if defined(SOL_ALL_SAFETIES_ON) && (SOL_ALL_SAFETIES_ON != 0)
195 #define SOL_ALL_SAFETIES_ON_I_ SOL_ON
196#else
197 #define SOL_ALL_SAFETIES_ON_I_ SOL_DEFAULT_OFF
198#endif
199
200#if defined(SOL_SAFE_GETTER) && (SOL_SAFE_GETTER != 0)
201 #define SOL_SAFE_GETTER_I_ SOL_ON
202#else
203 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
204 #define SOL_SAFE_GETTER_I_ SOL_ON
205 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
206 #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_ON
207 #else
208 #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_OFF
209 #endif
210#endif
211
212#if defined(SOL_SAFE_USERTYPE) && (SOL_SAFE_USERTYPE != 0)
213 #define SOL_SAFE_USERTYPE_I_ SOL_ON
214#else
215 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
216 #define SOL_SAFE_USERTYPE_I_ SOL_ON
217 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
218 #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_ON
219 #else
220 #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_OFF
221 #endif
222#endif
223
224#if defined(SOL_SAFE_REFERENCES) && (SOL_SAFE_REFERENCES != 0)
225 #define SOL_SAFE_REFERENCES_I_ SOL_ON
226#else
227 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
228 #define SOL_SAFE_REFERENCES_I_ SOL_ON
229 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
230 #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_ON
231 #else
232 #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_OFF
233 #endif
234#endif
235
236#if (defined(SOL_SAFE_FUNCTIONS) && (SOL_SAFE_FUNCTIONS != 0)) \
237 || (defined(SOL_SAFE_FUNCTION_OBJECTS) && (SOL_SAFE_FUNCTION_OBJECTS != 0))
238 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON
239#else
240 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
241 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON
242 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
243 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_ON
244 #else
245 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_OFF
246 #endif
247#endif
248
249#if defined(SOL_SAFE_FUNCTION_CALLS) && (SOL_SAFE_FUNCTION_CALLS != 0)
250 #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON
251#else
252 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
253 #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON
254 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
255 #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_ON
256 #else
257 #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_OFF
258 #endif
259#endif
260
261#if defined(SOL_SAFE_PROXIES) && (SOL_SAFE_PROXIES != 0)
262 #define SOL_SAFE_PROXIES_I_ SOL_ON
263#else
264 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
265 #define SOL_SAFE_PROXIES_I_ SOL_ON
266 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
267 #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_ON
268 #else
269 #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_OFF
270 #endif
271#endif
272
273#if defined(SOL_SAFE_NUMERICS) && (SOL_SAFE_NUMERICS != 0)
274 #define SOL_SAFE_NUMERICS_I_ SOL_ON
275#else
276 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
277 #define SOL_SAFE_NUMERICS_I_ SOL_ON
278 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
279 #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_ON
280 #else
281 #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_OFF
282 #endif
283#endif
284
285#if defined(SOL_SAFE_STACK_CHECK) && (SOL_SAFE_STACK_CHECK != 0)
286 #define SOL_SAFE_STACK_CHECK_I_ SOL_ON
287#else
288 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
289 #define SOL_SAFE_STACK_CHECK_I_ SOL_ON
290 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
291 #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_ON
292 #else
293 #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_OFF
294 #endif
295#endif
296
297#if (defined(SOL_NO_CHECK_NUMBER_PRECISION) && (SOL_NO_CHECK_NUMBER_PRECISION != 0)) \
298 || (defined(SOL_NO_CHECKING_NUMBER_PRECISION) && (SOL_NO_CHECKING_NUMBER_PRECISION != 0))
299 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF
300#else
301 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
302 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON
303 #elif SOL_IS_ON(SOL_SAFE_NUMERICS_I_)
304 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON
305 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
306 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_ON
307 #else
308 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_OFF
309 #endif
310#endif
311
312#if defined(SOL_STRINGS_ARE_NUMBERS)
313 #if (SOL_STRINGS_ARE_NUMBERS != 0)
314 #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_ON
315 #else
316 #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_OFF
317 #endif
318#else
319 #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_DEFAULT_OFF
320#endif
321
322#if defined(SOL_ENABLE_INTEROP) && (SOL_ENABLE_INTEROP != 0) \
323 || defined(SOL_USE_INTEROP) && (SOL_USE_INTEROP != 0)
324 #define SOL_USE_INTEROP_I_ SOL_ON
325#else
326 #define SOL_USE_INTEROP_I_ SOL_DEFAULT_OFF
327#endif
328
329#if defined(SOL_NO_NIL)
330 #if (SOL_NO_NIL != 0)
331 #define SOL_NIL_I_ SOL_OFF
332 #else
333 #define SOL_NIL_I_ SOL_ON
334 #endif
335#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil)
336 #define SOL_NIL_I_ SOL_DEFAULT_OFF
337#else
338 #define SOL_NIL_I_ SOL_DEFAULT_ON
339#endif
340
341#if defined(SOL_USERTYPE_TYPE_BINDING_INFO)
342 #if (SOL_USERTYPE_TYPE_BINDING_INFO != 0)
343 #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_ON
344 #else
345 #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_OFF
346 #endif
347#else
348 #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_DEFAULT_ON
349#endif // We should generate a my_type.__type table with lots of class information for usertypes
350
351#if defined(SOL_AUTOMAGICAL_TYPES_BY_DEFAULT)
352 #if (SOL_AUTOMAGICAL_TYPES_BY_DEFAULT != 0)
353 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON
354 #else
355 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF
356 #endif
357#elif defined(SOL_DEFAULT_AUTOMAGICAL_USERTYPES)
358 #if (SOL_DEFAULT_AUTOMAGICAL_USERTYPES != 0)
359 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON
360 #else
361 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF
362 #endif
363#else
364 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_DEFAULT_ON
365#endif // make is_automagical on/off by default
366
367#if defined(SOL_STD_VARIANT)
368 #if (SOL_STD_VARIANT != 0)
369 #define SOL_STD_VARIANT_I_ SOL_ON
370 #else
371 #define SOL_STD_VARIANT_I_ SOL_OFF
372 #endif
373#else
374 #if SOL_IS_ON(SOL_COMPILER_CLANG_I_) && SOL_IS_ON(SOL_PLATFORM_APPLE_I_)
375 #if defined(__has_include)
376 #if __has_include(<variant>)
377 #define SOL_STD_VARIANT_I_ SOL_ON
378 #else
379 #define SOL_STD_VARIANT_I_ SOL_OFF
380 #endif
381 #else
382 #define SOL_STD_VARIANT_I_ SOL_OFF
383 #endif
384 #else
385 #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON
386 #endif
387#endif // make is_automagical on/off by default
388
389#if defined(SOL_NOEXCEPT_FUNCTION_TYPE)
390 #if (SOL_NOEXCEPT_FUNCTION_TYPE != 0)
391 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON
392 #else
393 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF
394 #endif
395#else
396 #if defined(__cpp_noexcept_function_type)
397 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON
398 #elif SOL_IS_ON(SOL_COMPILER_VCXX_I_) && (defined(_MSVC_LANG) && (_MSVC_LANG < 201403L))
399 // There is a bug in the VC++ compiler??
400 // on /std:c++latest under x86 conditions (VS 15.5.2),
401 // compiler errors are tossed for noexcept markings being on function types
402 // that are identical in every other way to their non-noexcept marked types function types...
403 // VS 2019: There is absolutely a bug.
404 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF
405 #else
406 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_DEFAULT_ON
407 #endif
408#endif // noexcept is part of a function's type
409
410#if defined(SOL_STACK_STRING_OPTIMIZATION_SIZE) && SOL_STACK_STRING_OPTIMIZATION_SIZE > 0
411 #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ SOL_STACK_STRING_OPTIMIZATION_SIZE
412#else
413 #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ 1024
414#endif
415
416#if defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0
417 #define SOL_ID_SIZE_I_ SOL_ID_SIZE
418#else
419 #define SOL_ID_SIZE_I_ 512
420#endif
421
422#if defined(LUA_IDSIZE) && LUA_IDSIZE > 0
423 #define SOL_FILE_ID_SIZE_I_ LUA_IDSIZE
424#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0
425 #define SOL_FILE_ID_SIZE_I_ SOL_FILE_ID_SIZE
426#else
427 #define SOL_FILE_ID_SIZE_I_ 2048
428#endif
429
430#if defined(SOL_PRINT_ERRORS)
431 #if (SOL_PRINT_ERRORS != 0)
432 #define SOL_PRINT_ERRORS_I_ SOL_ON
433 #else
434 #define SOL_PRINT_ERRORS_I_ SOL_OFF
435 #endif
436#else
437 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
438 #define SOL_PRINT_ERRORS_I_ SOL_ON
439 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
440 #define SOL_PRINT_ERRORS_I_ SOL_DEFAULT_ON
441 #else
442 #define SOL_PRINT_ERRORS_I_ SOL_OFF
443 #endif
444#endif
445
446#if defined(SOL_DEFAULT_PASS_ON_ERROR) && (SOL_DEFAULT_PASS_ON_ERROR != 0)
447 #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_ON
448#else
449 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON_I_)
450 #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_ON
451 #elif SOL_IS_ON(SOL_DEBUG_BUILD_I_)
452 #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_DEFAULT_ON
453 #else
454 #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_OFF
455 #endif
456#endif
457
458#if defined(SOL_USING_CXX_LUA)
459 #if (SOL_USING_CXX_LUA != 0)
460 #define SOL_USE_CXX_LUA_I_ SOL_ON
461 #else
462 #define SOL_USE_CXX_LUA_I_ SOL_OFF
463 #endif
464#elif defined(SOL_USE_CXX_LUA)
465 #if (SOL_USE_CXX_LUA != 0)
466 #define SOL_USE_CXX_LUA_I_ SOL_ON
467 #else
468 #define SOL_USE_CXX_LUA_I_ SOL_OFF
469 #endif
470#else
471 #define SOL_USE_CXX_LUA_I_ SOL_OFF
472#endif
473
474#if defined(SOL_USING_CXX_LUAJIT)
475 #if (SOL_USING_CXX_LUA != 0)
476 #define SOL_USE_CXX_LUAJIT_I_ SOL_ON
477 #else
478 #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF
479 #endif
480#elif defined(SOL_USE_CXX_LUAJIT)
481 #if (SOL_USE_CXX_LUA != 0)
482 #define SOL_USE_CXX_LUAJIT_I_ SOL_ON
483 #else
484 #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF
485 #endif
486#else
487 #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF
488#endif
489
490#if defined(SOL_NO_LUA_HPP)
491 #if (SOL_NO_LUA_HPP != 0)
492 #define SOL_USE_LUA_HPP_I_ SOL_OFF
493 #else
494 #define SOL_USE_LUA_HPP_I_ SOL_ON
495 #endif
496#elif defined(SOL_USING_CXX_LUA)
497 #define SOL_USE_LUA_HPP_I_ SOL_OFF
498#elif defined(__has_include)
499 #if __has_include(<lua.hpp>)
500 #define SOL_USE_LUA_HPP_I_ SOL_ON
501 #else
502 #define SOL_USE_LUA_HPP_I_ SOL_OFF
503 #endif
504#else
505 #define SOL_USE_LUA_HPP_I_ SOL_DEFAULT_ON
506#endif
507
508#if defined(SOL_CONTAINERS_START)
509 #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START
510#elif defined(SOL_CONTAINERS_START_INDEX)
511 #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START_INDEX
512#elif defined(SOL_CONTAINER_START_INDEX)
513 #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINER_START_INDEX
514#else
515 #define SOL_CONTAINER_START_INDEX_I_ 1
516#endif
517
518#if defined (SOL_NO_MEMORY_ALIGNMENT)
519 #if (SOL_NO_MEMORY_ALIGNMENT != 0)
520 #define SOL_ALIGN_MEMORY_I_ SOL_OFF
521 #else
522 #define SOL_ALIGN_MEMORY_I_ SOL_ON
523 #endif
524#else
525 #define SOL_ALIGN_MEMORY_I_ SOL_DEFAULT_ON
526#endif
527
528#if defined(SOL_USE_BOOST)
529 #if (SOL_USE_BOOST != 0)
530 #define SOL_USE_BOOST_I_ SOL_ON
531 #else
532 #define SOL_USE_BOOST_I_ SOL_OFF
533 #endif
534#else
535 #define SOL_USE_BOOST_I_ SOL_OFF
536#endif
537
538#if defined(SOL_USE_UNSAFE_BASE_LOOKUP)
539 #if (SOL_USE_UNSAFE_BASE_LOOKUP != 0)
540 #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_ON
541 #else
542 #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_OFF
543 #endif
544#else
545 #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_OFF
546#endif
547
548#if defined(SOL_INSIDE_UNREAL)
549 #if (SOL_INSIDE_UNREAL != 0)
550 #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_ON
551 #else
552 #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_OFF
553 #endif
554#else
555 #if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER)
556 #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_ON
557 #else
558 #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_OFF
559 #endif
560#endif
561
562#if defined(SOL_NO_COMPAT)
563 #if (SOL_NO_COMPAT != 0)
564 #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_OFF
565 #else
566 #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_ON
567 #endif
568#else
569 #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON
570#endif
571
572#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE)
573 #if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0)
574 #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON
575 #else
576 #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF
577 #endif
578#else
579 #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF
580#endif
581
582#if SOL_IS_ON(SOL_COMPILER_FRONTEND_MINGW_I_) && defined(__GNUC__) && (__GNUC__ < 6)
583 // MinGW is off its rocker in some places...
584 #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON
585#else
586 #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_OFF
587#endif
588
589// end of sol/version.hpp
590
591#if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE_I_)
592#ifdef check
593#pragma push_macro("check")
594#undef check
595#endif
596#endif // Unreal Engine 4 Bullshit
597
598#if SOL_IS_ON(SOL_COMPILER_GCC_I_)
599#pragma GCC diagnostic push
600#pragma GCC diagnostic ignored "-Wshadow"
601#pragma GCC diagnostic ignored "-Wconversion"
602#if __GNUC__ > 6
603#pragma GCC diagnostic ignored "-Wnoexcept-type"
604#endif
605#elif SOL_IS_ON(SOL_COMPILER_CLANG_I_)
606#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_)
607#pragma warning(push)
608#pragma warning(disable : 4505) // unreferenced local function has been removed GEE THANKS
609#endif // clang++ vs. g++ vs. VC++
610
611// beginning of sol/forward.hpp
612
613#ifndef SOL_FORWARD_HPP
614#define SOL_FORWARD_HPP
615
616#include <utility>
617#include <type_traits>
618#include <string_view>
619
620#if SOL_IS_ON(SOL_USE_CXX_LUA_I_) || SOL_IS_ON(SOL_USE_CXX_LUAJIT_I_)
621struct lua_State;
622#else
623extern "C" {
624struct lua_State;
625}
626#endif // C++ Mangling for Lua vs. Not
627
628namespace sol {
629
630 enum class type;
631
632 class stateless_reference;
633 template <bool b>
634 class basic_reference;
635 using reference = basic_reference<false>;
636 using main_reference = basic_reference<true>;
637 class stateless_stack_reference;
638 class stack_reference;
639
640 template <typename A>
641 class basic_bytecode;
642
643 struct lua_value;
644
645 struct proxy_base_tag;
646 template <typename>
647 struct proxy_base;
648 template <typename, typename>
649 struct table_proxy;
650
651 template <bool, typename>
652 class basic_table_core;
653 template <bool b>
654 using table_core = basic_table_core<b, reference>;
655 template <bool b>
656 using main_table_core = basic_table_core<b, main_reference>;
657 template <bool b>
658 using stack_table_core = basic_table_core<b, stack_reference>;
659 template <typename base_type>
660 using basic_table = basic_table_core<false, base_type>;
661 using table = table_core<false>;
662 using global_table = table_core<true>;
663 using main_table = main_table_core<false>;
664 using main_global_table = main_table_core<true>;
665 using stack_table = stack_table_core<false>;
666 using stack_global_table = stack_table_core<true>;
667
668 template <typename>
669 struct basic_lua_table;
670 using lua_table = basic_lua_table<reference>;
671 using stack_lua_table = basic_lua_table<stack_reference>;
672
673 template <typename T, typename base_type>
674 class basic_usertype;
675 template <typename T>
676 using usertype = basic_usertype<T, reference>;
677 template <typename T>
678 using stack_usertype = basic_usertype<T, stack_reference>;
679
680 template <typename base_type>
681 class basic_metatable;
682 using metatable = basic_metatable<reference>;
683 using stack_metatable = basic_metatable<stack_reference>;
684
685 template <typename base_t>
686 struct basic_environment;
687 using environment = basic_environment<reference>;
688 using main_environment = basic_environment<main_reference>;
689 using stack_environment = basic_environment<stack_reference>;
690
691 template <typename T, bool>
692 class basic_function;
693 template <typename T, bool, typename H>
694 class basic_protected_function;
695 using unsafe_function = basic_function<reference, false>;
696 using safe_function = basic_protected_function<reference, false, reference>;
697 using main_unsafe_function = basic_function<main_reference, false>;
698 using main_safe_function = basic_protected_function<main_reference, false, reference>;
699 using stack_unsafe_function = basic_function<stack_reference, false>;
700 using stack_safe_function = basic_protected_function<stack_reference, false, reference>;
701 using stack_aligned_unsafe_function = basic_function<stack_reference, true>;
702 using stack_aligned_safe_function = basic_protected_function<stack_reference, true, reference>;
703 using protected_function = safe_function;
704 using main_protected_function = main_safe_function;
705 using stack_protected_function = stack_safe_function;
706 using stack_aligned_protected_function = stack_aligned_safe_function;
707#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS_I_)
708 using function = protected_function;
709 using main_function = main_protected_function;
710 using stack_function = stack_protected_function;
711 using stack_aligned_function = stack_aligned_safe_function;
712#else
713 using function = unsafe_function;
714 using main_function = main_unsafe_function;
715 using stack_function = stack_unsafe_function;
716 using stack_aligned_function = stack_aligned_unsafe_function;
717#endif
718 using stack_aligned_stack_handler_function = basic_protected_function<stack_reference, true, stack_reference>;
719
720 struct unsafe_function_result;
721 struct protected_function_result;
722 using safe_function_result = protected_function_result;
723#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS_I_)
724 using function_result = safe_function_result;
725#else
726 using function_result = unsafe_function_result;
727#endif
728
729 template <typename base_t>
730 class basic_object_base;
731 template <typename base_t>
732 class basic_object;
733 template <typename base_t>
734 class basic_userdata;
735 template <typename base_t>
736 class basic_lightuserdata;
737 template <typename base_t>
738 class basic_coroutine;
739 template <typename base_t>
740 class basic_thread;
741
742 using object = basic_object<reference>;
743 using userdata = basic_userdata<reference>;
744 using lightuserdata = basic_lightuserdata<reference>;
745 using thread = basic_thread<reference>;
746 using coroutine = basic_coroutine<reference>;
747 using main_object = basic_object<main_reference>;
748 using main_userdata = basic_userdata<main_reference>;
749 using main_lightuserdata = basic_lightuserdata<main_reference>;
750 using main_coroutine = basic_coroutine<main_reference>;
751 using stack_object = basic_object<stack_reference>;
752 using stack_userdata = basic_userdata<stack_reference>;
753 using stack_lightuserdata = basic_lightuserdata<stack_reference>;
754 using stack_thread = basic_thread<stack_reference>;
755 using stack_coroutine = basic_coroutine<stack_reference>;
756
757 struct stack_proxy_base;
758 struct stack_proxy;
759 struct variadic_args;
760 struct variadic_results;
761 struct stack_count;
762 struct this_state;
763 struct this_main_state;
764 struct this_environment;
765
766 class state_view;
767 class state;
768
769 template <typename T>
770 struct as_table_t;
771 template <typename T>
772 struct as_container_t;
773 template <typename T>
774 struct nested;
775 template <typename T>
776 struct light;
777 template <typename T>
778 struct user;
779 template <typename T>
780 struct as_args_t;
781 template <typename T>
782 struct protect_t;
783 template <typename F, typename... Policies>
784 struct policy_wrapper;
785
786 template <typename T>
787 struct usertype_traits;
788 template <typename T>
789 struct unique_usertype_traits;
790
791 template <typename... Args>
792 struct types {
793 typedef std::make_index_sequence<sizeof...(Args)> indices;
794 static constexpr std::size_t size() {
795 return sizeof...(Args);
796 }
797 };
798
799 template <typename T>
800 struct derive : std::false_type {
801 typedef types<> type;
802 };
803
804 template <typename T>
805 struct base : std::false_type {
806 typedef types<> type;
807 };
808
809 template <typename T>
810 struct weak_derive {
811 static bool value;
812 };
813
814 template <typename T>
815 bool weak_derive<T>::value = false;
816
817 namespace stack {
818 struct record;
819 }
820
821#if SOL_IS_OFF(SOL_USE_BOOST_I_)
822 template <class T>
823 class optional;
824
825 template <class T>
826 class optional<T&>;
827#endif
828
829 using check_handler_type = int(lua_State*, int, type, type, const char*);
830
831} // namespace sol
832
833#define SOL_BASE_CLASSES(T, ...) \
834 namespace sol { \
835 template <> \
836 struct base<T> : std::true_type { \
837 typedef ::sol::types<__VA_ARGS__> type; \
838 }; \
839 } \
840 void a_sol3_detail_function_decl_please_no_collide()
841#define SOL_DERIVED_CLASSES(T, ...) \
842 namespace sol { \
843 template <> \
844 struct derive<T> : std::true_type { \
845 typedef ::sol::types<__VA_ARGS__> type; \
846 }; \
847 } \
848 void a_sol3_detail_function_decl_please_no_collide()
849
850#endif // SOL_FORWARD_HPP
851// end of sol/forward.hpp
852
853// beginning of sol/forward_detail.hpp
854
855#ifndef SOL_FORWARD_DETAIL_HPP
856#define SOL_FORWARD_DETAIL_HPP
857
858// beginning of sol/traits.hpp
859
860// beginning of sol/tuple.hpp
861
862// beginning of sol/base_traits.hpp
863
864#include <type_traits>
865
866namespace sol {
867 namespace detail {
868 struct unchecked_t {};
869 const unchecked_t unchecked = unchecked_t{};
870 } // namespace detail
871
872 namespace meta {
873 using sfinae_yes_t = std::true_type;
874 using sfinae_no_t = std::false_type;
875
876 template <typename T>
877 using void_t = void;
878
879 template <typename T>
880 using unqualified = std::remove_cv<std::remove_reference_t<T>>;
881
882 template <typename T>
883 using unqualified_t = typename unqualified<T>::type;
884
885 namespace meta_detail {
886 template <typename T>
887 struct unqualified_non_alias : unqualified<T> {};
888
889 template <template <class...> class Test, class, class... Args>
890 struct is_detected : std::false_type {};
891
892 template <template <class...> class Test, class... Args>
893 struct is_detected<Test, void_t<Test<Args...>>, Args...> : std::true_type {};
894 } // namespace meta_detail
895
896 template <template <class...> class Trait, class... Args>
897 using is_detected = typename meta_detail::is_detected<Trait, void, Args...>::type;
898
899 template <template <class...> class Trait, class... Args>
900 constexpr inline bool is_detected_v = is_detected<Trait, Args...>::value;
901
902 template <std::size_t I>
903 using index_value = std::integral_constant<std::size_t, I>;
904
905 template <bool>
906 struct conditional {
907 template <typename T, typename U>
908 using type = T;
909 };
910
911 template <>
912 struct conditional<false> {
913 template <typename T, typename U>
914 using type = U;
915 };
916
917 template <bool B, typename T, typename U>
918 using conditional_t = typename conditional<B>::template type<T, U>;
919
920 namespace meta_detail {
921 template <typename T, template <typename...> class Templ>
922 struct is_specialization_of : std::false_type {};
923 template <typename... T, template <typename...> class Templ>
924 struct is_specialization_of<Templ<T...>, Templ> : std::true_type {};
925 } // namespace meta_detail
926
927 template <typename T, template <typename...> class Templ>
928 using is_specialization_of = meta_detail::is_specialization_of<std::remove_cv_t<T>, Templ>;
929
930 template <typename T, template <typename...> class Templ>
931 inline constexpr bool is_specialization_of_v = is_specialization_of<std::remove_cv_t<T>, Templ>::value;
932
933 template <typename T>
934 struct identity {
935 typedef T type;
936 };
937
938 template <typename T>
939 using identity_t = typename identity<T>::type;
940
941 template <typename T>
942 using is_builtin_type = std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value>;
943
944 } // namespace meta
945} // namespace sol
946
947// end of sol/base_traits.hpp
948
949#include <tuple>
950#include <cstddef>
951
952namespace sol {
953 namespace detail {
954 using swallow = std::initializer_list<int>;
955 } // namespace detail
956
957 namespace meta {
958 template <typename T>
959 using is_tuple = is_specialization_of<T, std::tuple>;
960
961 template <typename T>
962 constexpr inline bool is_tuple_v = is_tuple<T>::value;
963
964 namespace detail {
965 template <typename... Args>
966 struct tuple_types_ { typedef types<Args...> type; };
967
968 template <typename... Args>
969 struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; };
970 } // namespace detail
971
972 template <typename... Args>
973 using tuple_types = typename detail::tuple_types_<Args...>::type;
974
975 template <typename Arg>
976 struct pop_front_type;
977
978 template <typename Arg>
979 using pop_front_type_t = typename pop_front_type<Arg>::type;
980
981 template <typename... Args>
982 struct pop_front_type<types<Args...>> {
983 typedef void front_type;
984 typedef types<Args...> type;
985 };
986
987 template <typename Arg, typename... Args>
988 struct pop_front_type<types<Arg, Args...>> {
989 typedef Arg front_type;
990 typedef types<Args...> type;
991 };
992
993 template <std::size_t N, typename Tuple>
994 using tuple_element = std::tuple_element<N, std::remove_reference_t<Tuple>>;
995
996 template <std::size_t N, typename Tuple>
997 using tuple_element_t = std::tuple_element_t<N, std::remove_reference_t<Tuple>>;
998
999 template <std::size_t N, typename Tuple>
1000 using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>;
1001
1002 template <std::size_t N, typename Tuple>
1003 using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>;
1004
1005 } // namespace meta
1006} // namespace sol
1007
1008// end of sol/tuple.hpp
1009
1010// beginning of sol/bind_traits.hpp
1011
1012namespace sol { namespace meta {
1013 namespace meta_detail {
1014
1015 template <class F>
1016 struct check_deducible_signature {
1017 struct nat {};
1018 template <class G>
1019 static auto test(int) -> decltype(&G::operator(), void());
1020 template <class>
1021 static auto test(...) -> nat;
1022
1023 using type = std::is_void<decltype(test<F>(0))>;
1024 };
1025 } // namespace meta_detail
1026
1027 template <class F>
1028 struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type {};
1029
1030 namespace meta_detail {
1031
1032 template <std::size_t I, typename T>
1033 struct void_tuple_element : meta::tuple_element<I, T> {};
1034
1035 template <std::size_t I>
1036 struct void_tuple_element<I, std::tuple<>> {
1037 typedef void type;
1038 };
1039
1040 template <std::size_t I, typename T>
1041 using void_tuple_element_t = typename void_tuple_element<I, T>::type;
1042
1043 template <bool it_is_noexcept, bool has_c_variadic, typename T, typename R, typename... Args>
1044 struct basic_traits {
1045 private:
1046 using first_type = meta::conditional_t<std::is_void<T>::value, int, T>&;
1047
1048 public:
1049 inline static constexpr const bool is_noexcept = it_is_noexcept;
1050 inline static constexpr bool is_member_function = std::is_void<T>::value;
1051 inline static constexpr bool has_c_var_arg = has_c_variadic;
1052 inline static constexpr std::size_t arity = sizeof...(Args);
1053 inline static constexpr std::size_t free_arity = sizeof...(Args) + static_cast<std::size_t>(!std::is_void<T>::value);
1054 typedef types<Args...> args_list;
1055 typedef std::tuple<Args...> args_tuple;
1056 typedef T object_type;
1057 typedef R return_type;
1058 typedef tuple_types<R> returns_list;
1059 typedef R(function_type)(Args...);
1060 typedef meta::conditional_t<std::is_void<T>::value, args_list, types<first_type, Args...>> free_args_list;
1061 typedef meta::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type;
1062 typedef meta::conditional_t<std::is_void<T>::value, R (*)(Args...), R (*)(first_type, Args...)> free_function_pointer_type;
1063 typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
1064 template <std::size_t i>
1065 using arg_at = void_tuple_element_t<i, args_tuple>;
1066 };
1067
1068 template <typename Signature, bool b = has_deducible_signature<Signature>::value>
1069 struct fx_traits : basic_traits<false, false, void, void> {};
1070
1071 // Free Functions
1072 template <typename R, typename... Args>
1073 struct fx_traits<R(Args...), false> : basic_traits<false, false, void, R, Args...> {
1074 typedef R (*function_pointer_type)(Args...);
1075 };
1076
1077 template <typename R, typename... Args>
1078 struct fx_traits<R (*)(Args...), false> : basic_traits<false, false, void, R, Args...> {
1079 typedef R (*function_pointer_type)(Args...);
1080 };
1081
1082 template <typename R, typename... Args>
1083 struct fx_traits<R(Args..., ...), false> : basic_traits<false, true, void, R, Args...> {
1084 typedef R (*function_pointer_type)(Args..., ...);
1085 };
1086
1087 template <typename R, typename... Args>
1088 struct fx_traits<R (*)(Args..., ...), false> : basic_traits<false, true, void, R, Args...> {
1089 typedef R (*function_pointer_type)(Args..., ...);
1090 };
1091
1092 // Member Functions
1093 /* C-Style Variadics */
1094 template <typename T, typename R, typename... Args>
1095 struct fx_traits<R (T::*)(Args...), false> : basic_traits<false, false, T, R, Args...> {
1096 typedef R (T::*function_pointer_type)(Args...);
1097 };
1098
1099 template <typename T, typename R, typename... Args>
1100 struct fx_traits<R (T::*)(Args..., ...), false> : basic_traits<false, true, T, R, Args...> {
1101 typedef R (T::*function_pointer_type)(Args..., ...);
1102 };
1103
1104 /* Const Volatile */
1105 template <typename T, typename R, typename... Args>
1106 struct fx_traits<R (T::*)(Args...) const, false> : basic_traits<false, false, T, R, Args...> {
1107 typedef R (T::*function_pointer_type)(Args...) const;
1108 };
1109
1110 template <typename T, typename R, typename... Args>
1111 struct fx_traits<R (T::*)(Args..., ...) const, false> : basic_traits<false, true, T, R, Args...> {
1112 typedef R (T::*function_pointer_type)(Args..., ...) const;
1113 };
1114
1115 template <typename T, typename R, typename... Args>
1116 struct fx_traits<R (T::*)(Args...) const volatile, false> : basic_traits<false, false, T, R, Args...> {
1117 typedef R (T::*function_pointer_type)(Args...) const volatile;
1118 };
1119
1120 template <typename T, typename R, typename... Args>
1121 struct fx_traits<R (T::*)(Args..., ...) const volatile, false> : basic_traits<false, true, T, R, Args...> {
1122 typedef R (T::*function_pointer_type)(Args..., ...) const volatile;
1123 };
1124
1125 /* Member Function Qualifiers */
1126 template <typename T, typename R, typename... Args>
1127 struct fx_traits<R (T::*)(Args...)&, false> : basic_traits<false, false, T, R, Args...> {
1128 typedef R (T::*function_pointer_type)(Args...) &;
1129 };
1130
1131 template <typename T, typename R, typename... Args>
1132 struct fx_traits<R (T::*)(Args..., ...)&, false> : basic_traits<false, true, T, R, Args...> {
1133 typedef R (T::*function_pointer_type)(Args..., ...) &;
1134 };
1135
1136 template <typename T, typename R, typename... Args>
1137 struct fx_traits<R (T::*)(Args...) const&, false> : basic_traits<false, false, T, R, Args...> {
1138 typedef R (T::*function_pointer_type)(Args...) const&;
1139 };
1140
1141 template <typename T, typename R, typename... Args>
1142 struct fx_traits<R (T::*)(Args..., ...) const&, false> : basic_traits<false, true, T, R, Args...> {
1143 typedef R (T::*function_pointer_type)(Args..., ...) const&;
1144 };
1145
1146 template <typename T, typename R, typename... Args>
1147 struct fx_traits<R (T::*)(Args...) const volatile&, false> : basic_traits<false, false, T, R, Args...> {
1148 typedef R (T::*function_pointer_type)(Args...) const volatile&;
1149 };
1150
1151 template <typename T, typename R, typename... Args>
1152 struct fx_traits<R (T::*)(Args..., ...) const volatile&, false> : basic_traits<false, true, T, R, Args...> {
1153 typedef R (T::*function_pointer_type)(Args..., ...) const volatile&;
1154 };
1155
1156 template <typename T, typename R, typename... Args>
1157 struct fx_traits<R (T::*)(Args...)&&, false> : basic_traits<false, false, T, R, Args...> {
1158 typedef R (T::*function_pointer_type)(Args...) &&;
1159 };
1160
1161 template <typename T, typename R, typename... Args>
1162 struct fx_traits<R (T::*)(Args..., ...)&&, false> : basic_traits<false, true, T, R, Args...> {
1163 typedef R (T::*function_pointer_type)(Args..., ...) &&;
1164 };
1165
1166 template <typename T, typename R, typename... Args>
1167 struct fx_traits<R (T::*)(Args...) const&&, false> : basic_traits<false, false, T, R, Args...> {
1168 typedef R (T::*function_pointer_type)(Args...) const&&;
1169 };
1170
1171 template <typename T, typename R, typename... Args>
1172 struct fx_traits<R (T::*)(Args..., ...) const&&, false> : basic_traits<false, true, T, R, Args...> {
1173 typedef R (T::*function_pointer_type)(Args..., ...) const&&;
1174 };
1175
1176 template <typename T, typename R, typename... Args>
1177 struct fx_traits<R (T::*)(Args...) const volatile&&, false> : basic_traits<false, false, T, R, Args...> {
1178 typedef R (T::*function_pointer_type)(Args...) const volatile&&;
1179 };
1180
1181 template <typename T, typename R, typename... Args>
1182 struct fx_traits<R (T::*)(Args..., ...) const volatile&&, false> : basic_traits<false, true, T, R, Args...> {
1183 typedef R (T::*function_pointer_type)(Args..., ...) const volatile&&;
1184 };
1185
1186#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
1187
1188 template <typename R, typename... Args>
1189 struct fx_traits<R(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
1190 typedef R (*function_pointer_type)(Args...) noexcept;
1191 };
1192
1193 template <typename R, typename... Args>
1194 struct fx_traits<R (*)(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
1195 typedef R (*function_pointer_type)(Args...) noexcept;
1196 };
1197
1198 template <typename R, typename... Args>
1199 struct fx_traits<R(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
1200 typedef R (*function_pointer_type)(Args..., ...) noexcept;
1201 };
1202
1203 template <typename R, typename... Args>
1204 struct fx_traits<R (*)(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
1205 typedef R (*function_pointer_type)(Args..., ...) noexcept;
1206 };
1207
1208 template <typename T, typename R, typename... Args>
1209 struct fx_traits<R (T::*)(Args...) noexcept, false> : basic_traits<true, false, T, R, Args...> {
1210 typedef R (T::*function_pointer_type)(Args...) noexcept;
1211 };
1212
1213 template <typename T, typename R, typename... Args>
1214 struct fx_traits<R (T::*)(Args..., ...) noexcept, false> : basic_traits<true, true, T, R, Args...> {
1215 typedef R (T::*function_pointer_type)(Args..., ...) noexcept;
1216 };
1217
1218 /* Const Volatile */
1219 template <typename T, typename R, typename... Args>
1220 struct fx_traits<R (T::*)(Args...) const noexcept, false> : basic_traits<true, false, T, R, Args...> {
1221 typedef R (T::*function_pointer_type)(Args...) const noexcept;
1222 };
1223
1224 template <typename T, typename R, typename... Args>
1225 struct fx_traits<R (T::*)(Args..., ...) const noexcept, false> : basic_traits<true, true, T, R, Args...> {
1226 typedef R (T::*function_pointer_type)(Args..., ...) const noexcept;
1227 };
1228
1229 template <typename T, typename R, typename... Args>
1230 struct fx_traits<R (T::*)(Args...) const volatile noexcept, false> : basic_traits<true, false, T, R, Args...> {
1231 typedef R (T::*function_pointer_type)(Args...) const volatile noexcept;
1232 };
1233
1234 template <typename T, typename R, typename... Args>
1235 struct fx_traits<R (T::*)(Args..., ...) const volatile noexcept, false> : basic_traits<true, true, T, R, Args...> {
1236 typedef R (T::*function_pointer_type)(Args..., ...) const volatile noexcept;
1237 };
1238
1239 template <typename T, typename R, typename... Args>
1240 struct fx_traits<R (T::*)(Args...) & noexcept, false> : basic_traits<true, false, T, R, Args...> {
1241 typedef R (T::*function_pointer_type)(Args...) & noexcept;
1242 };
1243
1244 template <typename T, typename R, typename... Args>
1245 struct fx_traits<R (T::*)(Args..., ...) & noexcept, false> : basic_traits<true, true, T, R, Args...> {
1246 typedef R (T::*function_pointer_type)(Args..., ...) & noexcept;
1247 };
1248
1249 template <typename T, typename R, typename... Args>
1250 struct fx_traits<R (T::*)(Args...) const& noexcept, false> : basic_traits<true, false, T, R, Args...> {
1251 typedef R (T::*function_pointer_type)(Args...) const& noexcept;
1252 };
1253
1254 template <typename T, typename R, typename... Args>
1255 struct fx_traits<R (T::*)(Args..., ...) const& noexcept, false> : basic_traits<true, true, T, R, Args...> {
1256 typedef R (T::*function_pointer_type)(Args..., ...) const& noexcept;
1257 };
1258
1259 template <typename T, typename R, typename... Args>
1260 struct fx_traits<R (T::*)(Args...) const volatile& noexcept, false> : basic_traits<true, false, T, R, Args...> {
1261 typedef R (T::*function_pointer_type)(Args...) const volatile& noexcept;
1262 };
1263
1264 template <typename T, typename R, typename... Args>
1265 struct fx_traits<R (T::*)(Args..., ...) const volatile& noexcept, false> : basic_traits<true, true, T, R, Args...> {
1266 typedef R (T::*function_pointer_type)(Args..., ...) const volatile& noexcept;
1267 };
1268
1269 template <typename T, typename R, typename... Args>
1270 struct fx_traits<R (T::*)(Args...) && noexcept, false> : basic_traits<true, false, T, R, Args...> {
1271 typedef R (T::*function_pointer_type)(Args...) && noexcept;
1272 };
1273
1274 template <typename T, typename R, typename... Args>
1275 struct fx_traits<R (T::*)(Args..., ...) && noexcept, false> : basic_traits<true, true, T, R, Args...> {
1276 typedef R (T::*function_pointer_type)(Args..., ...) && noexcept;
1277 };
1278
1279 template <typename T, typename R, typename... Args>
1280 struct fx_traits<R (T::*)(Args...) const&& noexcept, false> : basic_traits<true, false, T, R, Args...> {
1281 typedef R (T::*function_pointer_type)(Args...) const&& noexcept;
1282 };
1283
1284 template <typename T, typename R, typename... Args>
1285 struct fx_traits<R (T::*)(Args..., ...) const&& noexcept, false> : basic_traits<true, true, T, R, Args...> {
1286 typedef R (T::*function_pointer_type)(Args..., ...) const&& noexcept;
1287 };
1288
1289 template <typename T, typename R, typename... Args>
1290 struct fx_traits<R (T::*)(Args...) const volatile&& noexcept, false> : basic_traits<true, false, T, R, Args...> {
1291 typedef R (T::*function_pointer_type)(Args...) const volatile&& noexcept;
1292 };
1293
1294 template <typename T, typename R, typename... Args>
1295 struct fx_traits<R (T::*)(Args..., ...) const volatile&& noexcept, false> : basic_traits<true, true, T, R, Args...> {
1296 typedef R (T::*function_pointer_type)(Args..., ...) const volatile&& noexcept;
1297 };
1298
1299#endif // noexcept is part of a function's type
1300
1301#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) && SOL_IS_ON(SOL_PLATFORM_X86_I_)
1302 template <typename R, typename... Args>
1303 struct fx_traits<R __stdcall(Args...), false> : basic_traits<false, false, void, R, Args...> {
1304 typedef R(__stdcall* function_pointer_type)(Args...);
1305 };
1306
1307 template <typename R, typename... Args>
1308 struct fx_traits<R(__stdcall*)(Args...), false> : basic_traits<false, false, void, R, Args...> {
1309 typedef R(__stdcall* function_pointer_type)(Args...);
1310 };
1311
1312 template <typename T, typename R, typename... Args>
1313 struct fx_traits<R (__stdcall T::*)(Args...), false> : basic_traits<false, false, T, R, Args...> {
1314 typedef R (__stdcall T::*function_pointer_type)(Args...);
1315 };
1316
1317 /* Const Volatile */
1318 template <typename T, typename R, typename... Args>
1319 struct fx_traits<R (__stdcall T::*)(Args...) const, false> : basic_traits<false, false, T, R, Args...> {
1320 typedef R (__stdcall T::*function_pointer_type)(Args...) const;
1321 };
1322
1323 template <typename T, typename R, typename... Args>
1324 struct fx_traits<R (__stdcall T::*)(Args...) const volatile, false> : basic_traits<false, false, T, R, Args...> {
1325 typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile;
1326 };
1327
1328 /* Member Function Qualifiers */
1329 template <typename T, typename R, typename... Args>
1330 struct fx_traits<R (__stdcall T::*)(Args...)&, false> : basic_traits<false, false, T, R, Args...> {
1331 typedef R (__stdcall T::*function_pointer_type)(Args...) &;
1332 };
1333
1334 template <typename T, typename R, typename... Args>
1335 struct fx_traits<R (__stdcall T::*)(Args...) const&, false> : basic_traits<false, false, T, R, Args...> {
1336 typedef R (__stdcall T::*function_pointer_type)(Args...) const&;
1337 };
1338
1339 template <typename T, typename R, typename... Args>
1340 struct fx_traits<R (__stdcall T::*)(Args...) const volatile&, false> : basic_traits<false, false, T, R, Args...> {
1341 typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&;
1342 };
1343
1344 template <typename T, typename R, typename... Args>
1345 struct fx_traits<R (__stdcall T::*)(Args...)&&, false> : basic_traits<false, false, T, R, Args...> {
1346 typedef R (__stdcall T::*function_pointer_type)(Args...) &&;
1347 };
1348
1349 template <typename T, typename R, typename... Args>
1350 struct fx_traits<R (__stdcall T::*)(Args...) const&&, false> : basic_traits<false, false, T, R, Args...> {
1351 typedef R (__stdcall T::*function_pointer_type)(Args...) const&&;
1352 };
1353
1354 template <typename T, typename R, typename... Args>
1355 struct fx_traits<R (__stdcall T::*)(Args...) const volatile&&, false> : basic_traits<false, false, T, R, Args...> {
1356 typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&&;
1357 };
1358
1359#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
1360
1361 template <typename R, typename... Args>
1362 struct fx_traits<R __stdcall(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
1363 typedef R(__stdcall* function_pointer_type)(Args...) noexcept;
1364 };
1365
1366 template <typename R, typename... Args>
1367 struct fx_traits<R(__stdcall*)(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
1368 typedef R(__stdcall* function_pointer_type)(Args...) noexcept;
1369 };
1370
1371 /* __stdcall cannot be applied to functions with varargs*/
1372 /*template <typename R, typename... Args>
1373 struct fx_traits<__stdcall R(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
1374 typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept;
1375 };
1376
1377 template <typename R, typename... Args>
1378 struct fx_traits<R (__stdcall *)(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
1379 typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept;
1380 };*/
1381
1382 template <typename T, typename R, typename... Args>
1383 struct fx_traits<R (__stdcall T::*)(Args...) noexcept, false> : basic_traits<true, false, T, R, Args...> {
1384 typedef R (__stdcall T::*function_pointer_type)(Args...) noexcept;
1385 };
1386
1387 /* __stdcall does not work with varargs */
1388 /*template <typename T, typename R, typename... Args>
1389 struct fx_traits<R (__stdcall T::*)(Args..., ...) noexcept, false> : basic_traits<true, true, T, R, Args...> {
1390 typedef R (__stdcall T::*function_pointer_type)(Args..., ...) noexcept;
1391 };*/
1392
1393 /* Const Volatile */
1394 template <typename T, typename R, typename... Args>
1395 struct fx_traits<R (__stdcall T::*)(Args...) const noexcept, false> : basic_traits<true, false, T, R, Args...> {
1396 typedef R (__stdcall T::*function_pointer_type)(Args...) const noexcept;
1397 };
1398
1399 /* __stdcall does not work with varargs */
1400 /*template <typename T, typename R, typename... Args>
1401 struct fx_traits<R (__stdcall T::*)(Args..., ...) const noexcept, false> : basic_traits<true, true, T, R, Args...> {
1402 typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const noexcept;
1403 };*/
1404
1405 template <typename T, typename R, typename... Args>
1406 struct fx_traits<R (__stdcall T::*)(Args...) const volatile noexcept, false> : basic_traits<true, false, T, R, Args...> {
1407 typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile noexcept;
1408 };
1409
1410 /* __stdcall does not work with varargs */
1411 /*template <typename T, typename R, typename... Args>
1412 struct fx_traits<R (__stdcall T::*)(Args..., ...) const volatile noexcept, false> : basic_traits<true, true, T, R, Args...> {
1413 typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile noexcept;
1414 };*/
1415
1416 template <typename T, typename R, typename... Args>
1417 struct fx_traits<R (__stdcall T::*)(Args...) & noexcept, false> : basic_traits<true, false, T, R, Args...> {
1418 typedef R (__stdcall T::*function_pointer_type)(Args...) & noexcept;
1419 };
1420
1421 /* __stdcall does not work with varargs */
1422 /*template <typename T, typename R, typename... Args>
1423 struct fx_traits<R (__stdcall T::*)(Args..., ...) & noexcept, false> : basic_traits<true, true, T, R, Args...> {
1424 typedef R (__stdcall T::*function_pointer_type)(Args..., ...) & noexcept;
1425 };*/
1426
1427 template <typename T, typename R, typename... Args>
1428 struct fx_traits<R (__stdcall T::*)(Args...) const& noexcept, false> : basic_traits<true, false, T, R, Args...> {
1429 typedef R (__stdcall T::*function_pointer_type)(Args...) const& noexcept;
1430 };
1431
1432 /* __stdcall does not work with varargs */
1433 /*template <typename T, typename R, typename... Args>
1434 struct fx_traits<R (__stdcall T::*)(Args..., ...) const& noexcept, false> : basic_traits<true, true, T, R, Args...> {
1435 typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const& noexcept;
1436 };*/
1437
1438 template <typename T, typename R, typename... Args>
1439 struct fx_traits<R (__stdcall T::*)(Args...) const volatile& noexcept, false> : basic_traits<true, false, T, R, Args...> {
1440 typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile& noexcept;
1441 };
1442
1443 /* __stdcall does not work with varargs */
1444 /*template <typename T, typename R, typename... Args>
1445 struct fx_traits<R (__stdcall T::*)(Args..., ...) const volatile& noexcept, false> : basic_traits<true, true, T, R, Args...> {
1446 typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile& noexcept;
1447 };*/
1448
1449 template <typename T, typename R, typename... Args>
1450 struct fx_traits<R (__stdcall T::*)(Args...) && noexcept, false> : basic_traits<true, false, T, R, Args...> {
1451 typedef R (__stdcall T::*function_pointer_type)(Args...) && noexcept;
1452 };
1453
1454 /* __stdcall does not work with varargs */
1455 /*template <typename T, typename R, typename... Args>
1456 struct fx_traits<R (__stdcall T::*)(Args..., ...) && noexcept, false> : basic_traits<true, true, T, R, Args...> {
1457 typedef R (__stdcall T::*function_pointer_type)(Args..., ...) && noexcept;
1458 };*/
1459
1460 template <typename T, typename R, typename... Args>
1461 struct fx_traits<R (__stdcall T::*)(Args...) const&& noexcept, false> : basic_traits<true, false, T, R, Args...> {
1462 typedef R (__stdcall T::*function_pointer_type)(Args...) const&& noexcept;
1463 };
1464
1465 /* __stdcall does not work with varargs */
1466 /*template <typename T, typename R, typename... Args>
1467 struct fx_traits<R (__stdcall T::*)(Args..., ...) const&& noexcept, false> : basic_traits<true, true, T, R, Args...> {
1468 typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const&& noexcept;
1469 };*/
1470
1471 template <typename T, typename R, typename... Args>
1472 struct fx_traits<R (__stdcall T::*)(Args...) const volatile&& noexcept, false> : basic_traits<true, false, T, R, Args...> {
1473 typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&& noexcept;
1474 };
1475
1476 /* __stdcall does not work with varargs */
1477 /*template <typename T, typename R, typename... Args>
1478 struct fx_traits<R (__stdcall T::*)(Args..., ...) const volatile&& noexcept, false> : basic_traits<true, true, T, R, Args...> {
1479 typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile&& noexcept;
1480 };*/
1481#endif // noexcept is part of a function's type
1482#endif // __stdcall x86 VC++ bug
1483
1484 template <typename Signature>
1485 struct fx_traits<Signature, true>
1486 : public fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {};
1487
1488 template <typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
1489 struct callable_traits
1490 : public fx_traits<std::decay_t<Signature>> {};
1491
1492 template <typename R, typename T>
1493 struct callable_traits<R(T::*), true> {
1494 typedef meta::conditional_t<std::is_array_v<R>, std::add_lvalue_reference_t<R>, R> return_type;
1495 typedef return_type Arg;
1496 typedef T object_type;
1497 using signature_type = R(T::*);
1498 inline static constexpr bool is_noexcept = false;
1499 inline static constexpr bool is_member_function = false;
1500 inline static constexpr std::size_t arity = 1;
1501 inline static constexpr std::size_t free_arity = 2;
1502 typedef std::tuple<Arg> args_tuple;
1503 typedef types<Arg> args_list;
1504 typedef types<T, Arg> free_args_list;
1505 typedef meta::tuple_types<return_type> returns_list;
1506 typedef return_type(function_type)(T&, return_type);
1507 typedef return_type (*function_pointer_type)(T&, Arg);
1508 typedef return_type (*free_function_pointer_type)(T&, Arg);
1509 template <std::size_t i>
1510 using arg_at = void_tuple_element_t<i, args_tuple>;
1511 };
1512
1513 } // namespace meta_detail
1514
1515 template <typename Signature>
1516 struct bind_traits : meta_detail::callable_traits<Signature> {};
1517
1518 template <typename Signature>
1519 using function_args_t = typename bind_traits<Signature>::args_list;
1520
1521 template <typename Signature>
1522 using function_signature_t = typename bind_traits<Signature>::signature_type;
1523
1524 template <typename Signature>
1525 using function_return_t = typename bind_traits<Signature>::return_type;
1526}} // namespace sol::meta
1527
1528// end of sol/bind_traits.hpp
1529
1530// beginning of sol/pointer_like.hpp
1531
1532#include <utility>
1533#include <type_traits>
1534
1535namespace sol {
1536
1537 namespace meta {
1538 namespace meta_detail {
1539 template <typename T>
1540 using is_dereferenceable_test = decltype(*std::declval<T>());
1541
1542 template <typename T>
1543 using is_explicitly_dereferenceable_test = decltype(std::declval<T>().operator*());
1544 }
1545
1546 template <typename T>
1547 using is_pointer_like = std::integral_constant<bool, !std::is_array_v<T> && (std::is_pointer_v<T> || is_detected_v<meta_detail::is_explicitly_dereferenceable_test, T>)>;
1548
1549 template <typename T>
1550 constexpr inline bool is_pointer_like_v = is_pointer_like<T>::value;
1551 } // namespace meta
1552
1553 namespace detail {
1554
1555 template <typename T>
1556 auto unwrap(T&& item) -> decltype(std::forward<T>(item)) {
1557 return std::forward<T>(item);
1558 }
1559
1560 template <typename T>
1561 T& unwrap(std::reference_wrapper<T> arg) {
1562 return arg.get();
1563 }
1564
1565 template <typename T>
1566 inline decltype(auto) deref(T&& item) {
1567 using Tu = meta::unqualified_t<T>;
1568 if constexpr (meta::is_pointer_like_v<Tu>) {
1569 return *std::forward<T>(item);
1570 }
1571 else {
1572 return std::forward<T>(item);
1573 }
1574 }
1575
1576 template <typename T>
1577 inline decltype(auto) deref_move_only(T&& item) {
1578 using Tu = meta::unqualified_t<T>;
1579 if constexpr (meta::is_pointer_like_v<Tu> && !std::is_pointer_v<Tu> && !std::is_copy_constructible_v<Tu>) {
1580 return *std::forward<T>(item);
1581 }
1582 else {
1583 return std::forward<T>(item);
1584 }
1585 }
1586
1587 template <typename T>
1588 inline T* ptr(T& val) {
1589 return std::addressof(val);
1590 }
1591
1592 template <typename T>
1593 inline T* ptr(std::reference_wrapper<T> val) {
1594 return std::addressof(val.get());
1595 }
1596
1597 template <typename T>
1598 inline T* ptr(T* val) {
1599 return val;
1600 }
1601 } // namespace detail
1602} // namespace sol
1603
1604// end of sol/pointer_like.hpp
1605
1606// beginning of sol/string_view.hpp
1607
1608#include <cstddef>
1609#include <string>
1610#include <string_view>
1611#include <functional>
1612
1613namespace sol {
1614 template <typename C, typename T = std::char_traits<C>>
1615 using basic_string_view = std::basic_string_view<C, T>;
1616
1617 typedef std::string_view string_view;
1618 typedef std::wstring_view wstring_view;
1619 typedef std::u16string_view u16string_view;
1620 typedef std::u32string_view u32string_view;
1621 typedef std::hash<std::string_view> string_view_hash;
1622} // namespace sol
1623
1624// end of sol/string_view.hpp
1625
1626#include <type_traits>
1627#include <cstdint>
1628#include <memory>
1629#include <functional>
1630#include <array>
1631#include <iterator>
1632#include <iosfwd>
1633#if SOL_IS_ON(SOL_STD_VARIANT_I_)
1634#include <variant>
1635#endif // variant is weird on XCode, thanks XCode
1636
1637namespace sol { namespace meta {
1638 template <typename T>
1639 struct unwrapped {
1640 typedef T type;
1641 };
1642
1643 template <typename T>
1644 struct unwrapped<std::reference_wrapper<T>> {
1645 typedef T type;
1646 };
1647
1648 template <typename T>
1649 using unwrapped_t = typename unwrapped<T>::type;
1650
1651 template <typename T>
1652 struct unwrap_unqualified : unwrapped<unqualified_t<T>> {};
1653
1654 template <typename T>
1655 using unwrap_unqualified_t = typename unwrap_unqualified<T>::type;
1656
1657 template <typename T>
1658 struct remove_member_pointer;
1659
1660 template <typename R, typename T>
1661 struct remove_member_pointer<R T::*> {
1662 typedef R type;
1663 };
1664
1665 template <typename R, typename T>
1666 struct remove_member_pointer<R T::*const> {
1667 typedef R type;
1668 };
1669
1670 template <typename T>
1671 using remove_member_pointer_t = remove_member_pointer<T>;
1672
1673 template <typename T, typename...>
1674 struct all_same : std::true_type {};
1675
1676 template <typename T, typename U, typename... Args>
1677 struct all_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value && all_same<T, Args...>::value> {};
1678
1679 template <typename T, typename...>
1680 struct any_same : std::false_type {};
1681
1682 template <typename T, typename U, typename... Args>
1683 struct any_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value || any_same<T, Args...>::value> {};
1684
1685 template <typename T, typename... Args>
1686 constexpr inline bool any_same_v = any_same<T, Args...>::value;
1687
1688 template <bool B>
1689 using boolean = std::integral_constant<bool, B>;
1690
1691 template <bool B>
1692 constexpr inline bool boolean_v = boolean<B>::value;
1693
1694 template <typename T>
1695 using neg = boolean<!T::value>;
1696
1697 template <typename T>
1698 constexpr inline bool neg_v = neg<T>::value;
1699
1700 template <typename... Args>
1701 struct all : boolean<true> {};
1702
1703 template <typename T, typename... Args>
1704 struct all<T, Args...> : std::conditional_t<T::value, all<Args...>, boolean<false>> {};
1705
1706 template <typename... Args>
1707 struct any : boolean<false> {};
1708
1709 template <typename T, typename... Args>
1710 struct any<T, Args...> : std::conditional_t<T::value, boolean<true>, any<Args...>> {};
1711
1712 template <typename T, typename... Args>
1713 constexpr inline bool all_v = all<T, Args...>::value;
1714
1715 template <typename T, typename... Args>
1716 constexpr inline bool any_v = any<T, Args...>::value;
1717
1718 enum class enable_t { _ };
1719
1720 constexpr const auto enabler = enable_t::_;
1721
1722 template <bool value, typename T = void>
1723 using disable_if_t = std::enable_if_t<!value, T>;
1724
1725 template <typename... Args>
1726 using enable = std::enable_if_t<all<Args...>::value, enable_t>;
1727
1728 template <typename... Args>
1729 using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>;
1730
1731 template <typename... Args>
1732 using enable_any = std::enable_if_t<any<Args...>::value, enable_t>;
1733
1734 template <typename... Args>
1735 using disable_any = std::enable_if_t<neg<any<Args...>>::value, enable_t>;
1736
1737 template <typename V, typename... Vs>
1738 struct find_in_pack_v : boolean<false> {};
1739
1740 template <typename V, typename Vs1, typename... Vs>
1741 struct find_in_pack_v<V, Vs1, Vs...> : any<boolean<(V::value == Vs1::value)>, find_in_pack_v<V, Vs...>> {};
1742
1743 namespace meta_detail {
1744 template <std::size_t I, typename T, typename... Args>
1745 struct index_in_pack : std::integral_constant<std::size_t, SIZE_MAX> {};
1746
1747 template <std::size_t I, typename T, typename T1, typename... Args>
1748 struct index_in_pack<I, T, T1, Args...>
1749 : conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> {};
1750 } // namespace meta_detail
1751
1752 template <typename T, typename... Args>
1753 struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> {};
1754
1755 template <typename T, typename List>
1756 struct index_in : meta_detail::index_in_pack<0, T, List> {};
1757
1758 template <typename T, typename... Args>
1759 struct index_in<T, types<Args...>> : meta_detail::index_in_pack<0, T, Args...> {};
1760
1761 template <std::size_t I, typename... Args>
1762 struct at_in_pack {};
1763
1764 template <std::size_t I, typename... Args>
1765 using at_in_pack_t = typename at_in_pack<I, Args...>::type;
1766
1767 template <std::size_t I, typename Arg, typename... Args>
1768 struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> {};
1769
1770 template <typename Arg, typename... Args>
1771 struct at_in_pack<0, Arg, Args...> {
1772 typedef Arg type;
1773 };
1774
1775 namespace meta_detail {
1776 template <typename, typename TI>
1777 using on_even = meta::boolean<(TI::value % 2) == 0>;
1778
1779 template <typename, typename TI>
1780 using on_odd = meta::boolean<(TI::value % 2) == 1>;
1781
1782 template <typename, typename>
1783 using on_always = std::true_type;
1784
1785 template <template <typename...> class When, std::size_t Limit, std::size_t I, template <typename...> class Pred, typename... Ts>
1786 struct count_when_for_pack : std::integral_constant<std::size_t, 0> {};
1787 template <template <typename...> class When, std::size_t Limit, std::size_t I, template <typename...> class Pred, typename T, typename... Ts>
1788 struct count_when_for_pack<When, Limit, I, Pred, T, Ts...> : conditional_t < sizeof...(Ts)
1789 == 0
1790 || Limit<2, std::integral_constant<std::size_t, I + static_cast<std::size_t>(Limit != 0 && Pred<T>::value)>,
1791 count_when_for_pack<When, Limit - static_cast<std::size_t>(When<T, std::integral_constant<std::size_t, I>>::value),
1792 I + static_cast<std::size_t>(When<T, std::integral_constant<std::size_t, I>>::value&& Pred<T>::value), Pred, Ts...>> {};
1793 } // namespace meta_detail
1794
1795 template <template <typename...> class Pred, typename... Ts>
1796 struct count_for_pack : meta_detail::count_when_for_pack<meta_detail::on_always, sizeof...(Ts), 0, Pred, Ts...> {};
1797
1798 template <template <typename...> class Pred, typename... Ts>
1799 inline constexpr std::size_t count_for_pack_v = count_for_pack<Pred, Ts...>::value;
1800
1801 template <template <typename...> class Pred, typename List>
1802 struct count_for;
1803
1804 template <template <typename...> class Pred, typename... Args>
1805 struct count_for<Pred, types<Args...>> : count_for_pack<Pred, Args...> {};
1806
1807 template <std::size_t Limit, template <typename...> class Pred, typename... Ts>
1808 struct count_for_to_pack : meta_detail::count_when_for_pack<meta_detail::on_always, Limit, 0, Pred, Ts...> {};
1809
1810 template <std::size_t Limit, template <typename...> class Pred, typename... Ts>
1811 inline constexpr std::size_t count_for_to_pack_v = count_for_to_pack<Limit, Pred, Ts...>::value;
1812
1813 template <template <typename...> class When, std::size_t Limit, template <typename...> class Pred, typename... Ts>
1814 struct count_when_for_to_pack : meta_detail::count_when_for_pack<When, Limit, 0, Pred, Ts...> {};
1815
1816 template <template <typename...> class When, std::size_t Limit, template <typename...> class Pred, typename... Ts>
1817 inline constexpr std::size_t count_when_for_to_pack_v = count_when_for_to_pack<When, Limit, Pred, Ts...>::value;
1818
1819 template <template <typename...> class Pred, typename... Ts>
1820 using count_even_for_pack = count_when_for_to_pack<meta_detail::on_even, sizeof...(Ts), Pred, Ts...>;
1821
1822 template <template <typename...> class Pred, typename... Ts>
1823 inline constexpr std::size_t count_even_for_pack_v = count_even_for_pack<Pred, Ts...>::value;
1824
1825 template <template <typename...> class Pred, typename... Ts>
1826 using count_odd_for_pack = count_when_for_to_pack<meta_detail::on_odd, sizeof...(Ts), Pred, Ts...>;
1827
1828 template <template <typename...> class Pred, typename... Ts>
1829 inline constexpr std::size_t count_odd_for_pack_v = count_odd_for_pack<Pred, Ts...>::value;
1830
1831 template <typename... Args>
1832 struct return_type {
1833 typedef std::tuple<Args...> type;
1834 };
1835
1836 template <typename T>
1837 struct return_type<T> {
1838 typedef T type;
1839 };
1840
1841 template <>
1842 struct return_type<> {
1843 typedef void type;
1844 };
1845
1846 template <typename... Args>
1847 using return_type_t = typename return_type<Args...>::type;
1848
1849 namespace meta_detail {
1850 template <typename>
1851 struct always_true : std::true_type {};
1852 struct is_invokable_tester {
1853 template <typename Fun, typename... Args>
1854 static always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int);
1855 template <typename...>
1856 static std::false_type test(...);
1857 };
1858 } // namespace meta_detail
1859
1860 template <typename T>
1861 struct is_invokable;
1862 template <typename Fun, typename... Args>
1863 struct is_invokable<Fun(Args...)> : decltype(meta_detail::is_invokable_tester::test<Fun, Args...>(0)) {};
1864
1865 namespace meta_detail {
1866
1867 template <typename T, typename = void>
1868 struct is_callable : std::is_function<std::remove_pointer_t<T>> {};
1869
1870 template <typename T>
1871 struct is_callable<T,
1872 std::enable_if_t<std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value
1873 && std::is_same<decltype(void(&T::operator())), void>::value>> {};
1874
1875 template <typename T>
1876 struct is_callable<T,
1877 std::enable_if_t<!std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value
1878 && std::is_destructible<unqualified_t<T>>::value>> {
1879 struct F {
1880 void operator()() {};
1881 };
1882 struct Derived : T, F {};
1883 template <typename U, U>
1884 struct Check;
1885
1886 template <typename V>
1887 static sfinae_no_t test(Check<void (F::*)(), &V::operator()>*);
1888
1889 template <typename>
1890 static sfinae_yes_t test(...);
1891
1892 static constexpr bool value = std::is_same_v<decltype(test<Derived>(0)), sfinae_yes_t>;
1893 };
1894
1895 template <typename T>
1896 struct is_callable<T,
1897 std::enable_if_t<!std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value
1898 && !std::is_destructible<unqualified_t<T>>::value>> {
1899 struct F {
1900 void operator()() {};
1901 };
1902 struct Derived : T, F {
1903 ~Derived() = delete;
1904 };
1905 template <typename U, U>
1906 struct Check;
1907
1908 template <typename V>
1909 static sfinae_no_t test(Check<void (F::*)(), &V::operator()>*);
1910
1911 template <typename>
1912 static sfinae_yes_t test(...);
1913
1914 static constexpr bool value = std::is_same_v<decltype(test<Derived>(0)), sfinae_yes_t>;
1915 };
1916
1917 struct has_begin_end_impl {
1918 template <typename T, typename U = unqualified_t<T>, typename B = decltype(std::declval<U&>().begin()),
1919 typename E = decltype(std::declval<U&>().end())>
1920 static std::true_type test(int);
1921
1922 template <typename...>
1923 static std::false_type test(...);
1924 };
1925
1926 struct has_key_type_impl {
1927 template <typename T, typename U = unqualified_t<T>, typename V = typename U::key_type>
1928 static std::true_type test(int);
1929
1930 template <typename...>
1931 static std::false_type test(...);
1932 };
1933
1934 struct has_key_comp_impl {
1935 template <typename T, typename V = decltype(std::declval<unqualified_t<T>>().key_comp())>
1936 static std::true_type test(int);
1937
1938 template <typename...>
1939 static std::false_type test(...);
1940 };
1941
1942 struct has_load_factor_impl {
1943 template <typename T, typename V = decltype(std::declval<unqualified_t<T>>().load_factor())>
1944 static std::true_type test(int);
1945
1946 template <typename...>
1947 static std::false_type test(...);
1948 };
1949
1950 struct has_mapped_type_impl {
1951 template <typename T, typename V = typename unqualified_t<T>::mapped_type>
1952 static std::true_type test(int);
1953
1954 template <typename...>
1955 static std::false_type test(...);
1956 };
1957
1958 struct has_value_type_impl {
1959 template <typename T, typename V = typename unqualified_t<T>::value_type>
1960 static std::true_type test(int);
1961
1962 template <typename...>
1963 static std::false_type test(...);
1964 };
1965
1966 struct has_iterator_impl {
1967 template <typename T, typename V = typename unqualified_t<T>::iterator>
1968 static std::true_type test(int);
1969
1970 template <typename...>
1971 static std::false_type test(...);
1972 };
1973
1974 struct has_key_value_pair_impl {
1975 template <typename T, typename U = unqualified_t<T>, typename V = typename U::value_type, typename F = decltype(std::declval<V&>().first),
1976 typename S = decltype(std::declval<V&>().second)>
1977 static std::true_type test(int);
1978
1979 template <typename...>
1980 static std::false_type test(...);
1981 };
1982
1983 template <typename T>
1984 struct has_push_back_test {
1985 private:
1986 template <typename C>
1987 static sfinae_yes_t test(decltype(std::declval<C>().push_back(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
1988 template <typename C>
1989 static sfinae_no_t test(...);
1990
1991 public:
1992 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
1993 };
1994
1995 template <typename T>
1996 struct has_insert_test {
1997 private:
1998 template <typename C>
1999 static sfinae_yes_t test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(),
2000 std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
2001 template <typename C>
2002 static sfinae_no_t test(...);
2003
2004 public:
2005 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2006 };
2007
2008 template <typename T>
2009 struct has_insert_after_test {
2010 private:
2011 template <typename C>
2012 static sfinae_yes_t test(decltype(std::declval<C>().insert_after(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(),
2013 std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
2014 template <typename C>
2015 static sfinae_no_t test(...);
2016
2017 public:
2018 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2019 };
2020
2021 template <typename T>
2022 struct has_size_test {
2023 private:
2024 template <typename C>
2025 static sfinae_yes_t test(decltype(std::declval<C>().size())*);
2026 template <typename C>
2027 static sfinae_no_t test(...);
2028
2029 public:
2030 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2031 };
2032
2033 template <typename T>
2034 struct has_max_size_test {
2035 private:
2036 template <typename C>
2037 static sfinae_yes_t test(decltype(std::declval<C>().max_size())*);
2038 template <typename C>
2039 static sfinae_no_t test(...);
2040
2041 public:
2042 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2043 };
2044
2045 template <typename T>
2046 struct has_to_string_test {
2047 private:
2048 template <typename C>
2049 static sfinae_yes_t test(decltype(std::declval<C>().to_string())*);
2050 template <typename C>
2051 static sfinae_no_t test(...);
2052
2053 public:
2054 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2055 };
2056
2057 template <typename T, typename U, typename = void>
2058 class supports_op_less_test : public std::false_type {};
2059 template <typename T, typename U>
2060 class supports_op_less_test<T, U, void_t<decltype(std::declval<T&>() < std::declval<U&>())>>
2061 : public std::integral_constant<bool,
2062 !is_specialization_of_v<unqualified_t<T>, std::variant> && !is_specialization_of_v<unqualified_t<U>, std::variant>> {};
2063
2064 template <typename T, typename U, typename = void>
2065 class supports_op_equal_test : public std::false_type {};
2066 template <typename T, typename U>
2067 class supports_op_equal_test<T, U, void_t<decltype(std::declval<T&>() == std::declval<U&>())>>
2068 : public std::integral_constant<bool,
2069 !is_specialization_of_v<unqualified_t<T>, std::variant> && !is_specialization_of_v<unqualified_t<U>, std::variant>> {};
2070
2071 template <typename T, typename U, typename = void>
2072 class supports_op_less_equal_test : public std::false_type {};
2073 template <typename T, typename U>
2074 class supports_op_less_equal_test<T, U, void_t<decltype(std::declval<T&>() <= std::declval<U&>())>>
2075 : public std::integral_constant<bool,
2076 !is_specialization_of_v<unqualified_t<T>, std::variant> && !is_specialization_of_v<unqualified_t<U>, std::variant>> {};
2077
2078 template <typename T, typename U, typename = void>
2079 class supports_op_left_shift_test : public std::false_type {};
2080 template <typename T, typename U>
2081 class supports_op_left_shift_test<T, U, void_t<decltype(std::declval<T&>() << std::declval<U&>())>> : public std::true_type {};
2082
2083 template <typename T, typename = void>
2084 class supports_adl_to_string_test : public std::false_type {};
2085 template <typename T>
2086 class supports_adl_to_string_test<T, void_t<decltype(to_string(std::declval<const T&>()))>> : public std::true_type {};
2087
2088 template <typename T, bool b>
2089 struct is_matched_lookup_impl : std::false_type {};
2090 template <typename T>
2091 struct is_matched_lookup_impl<T, true> : std::is_same<typename T::key_type, typename T::value_type> {};
2092
2093 template <typename T>
2094 using non_void_t = meta::conditional_t<std::is_void_v<T>, ::sol::detail::unchecked_t, T>;
2095 } // namespace meta_detail
2096
2097 template <typename T, typename U = T>
2098 class supports_op_less : public meta_detail::supports_op_less_test<T, U> {};
2099
2100 template <typename T, typename U = T>
2101 class supports_op_equal : public meta_detail::supports_op_equal_test<T, U> {};
2102
2103 template <typename T, typename U = T>
2104 class supports_op_less_equal : public meta_detail::supports_op_less_equal_test<T, U> {};
2105
2106 template <typename T, typename U = T>
2107 class supports_op_left_shift : public meta_detail::supports_op_left_shift_test<T, U> {};
2108
2109 template <typename T>
2110 class supports_adl_to_string : public meta_detail::supports_adl_to_string_test<T> {};
2111
2112 template <typename T>
2113 class supports_to_string_member : public meta::boolean<meta_detail::has_to_string_test<meta_detail::non_void_t<T>>::value> {};
2114
2115 template <typename T>
2116 using is_callable = boolean<meta_detail::is_callable<T>::value>;
2117
2118 template <typename T>
2119 constexpr inline bool is_callable_v = is_callable<T>::value;
2120
2121 template <typename T>
2122 struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) {};
2123
2124 template <typename T>
2125 constexpr inline bool has_begin_end_v = has_begin_end<T>::value;
2126
2127 template <typename T>
2128 struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {};
2129
2130 template <typename T>
2131 struct has_key_type : decltype(meta_detail::has_key_type_impl::test<T>(0)) {};
2132
2133 template <typename T>
2134 struct has_key_comp : decltype(meta_detail::has_key_comp_impl::test<T>(0)) {};
2135
2136 template <typename T>
2137 struct has_load_factor : decltype(meta_detail::has_load_factor_impl::test<T>(0)) {};
2138
2139 template <typename T>
2140 struct has_mapped_type : decltype(meta_detail::has_mapped_type_impl::test<T>(0)) {};
2141
2142 template <typename T>
2143 struct has_iterator : decltype(meta_detail::has_iterator_impl::test<T>(0)) {};
2144
2145 template <typename T>
2146 struct has_value_type : decltype(meta_detail::has_value_type_impl::test<T>(0)) {};
2147
2148 template <typename T>
2149 using has_push_back = meta::boolean<meta_detail::has_push_back_test<T>::value>;
2150
2151 template <typename T>
2152 using has_max_size = meta::boolean<meta_detail::has_max_size_test<T>::value>;
2153
2154 template <typename T>
2155 using has_insert = meta::boolean<meta_detail::has_insert_test<T>::value>;
2156
2157 template <typename T>
2158 using has_insert_after = meta::boolean<meta_detail::has_insert_after_test<T>::value>;
2159
2160 template <typename T>
2161 using has_size = meta::boolean<meta_detail::has_size_test<T>::value>;
2162
2163 template <typename T>
2164 using is_associative = meta::all<has_key_type<T>, has_key_value_pair<T>, has_mapped_type<T>>;
2165
2166 template <typename T>
2167 using is_lookup = meta::all<has_key_type<T>, has_value_type<T>>;
2168
2169 template <typename T>
2170 using is_ordered = meta::all<has_key_comp<T>, meta::neg<has_load_factor<T>>>;
2171
2172 template <typename T>
2173 using is_matched_lookup = meta_detail::is_matched_lookup_impl<T, is_lookup<T>::value>;
2174
2175 template <typename T>
2176 using is_initializer_list = meta::is_specialization_of<T, std::initializer_list>;
2177
2178 template <typename T>
2179 constexpr inline bool is_initializer_list_v = is_initializer_list<T>::value;
2180
2181 template <typename T, typename CharT = char>
2182 using is_string_literal_array_of = boolean<std::is_array_v<T> && std::is_same_v<std::remove_all_extents_t<T>, CharT>>;
2183
2184 template <typename T, typename CharT = char>
2185 constexpr inline bool is_string_literal_array_of_v = is_string_literal_array_of<T, CharT>::value;
2186
2187 template <typename T>
2188 using is_string_literal_array = boolean<std::is_array_v<T> && any_same_v<std::remove_all_extents_t<T>, char, char16_t, char32_t, wchar_t>>;
2189
2190 template <typename T>
2191 constexpr inline bool is_string_literal_array_v = is_string_literal_array<T>::value;
2192
2193 template <typename T, typename CharT>
2194 struct is_string_of : std::false_type {};
2195
2196 template <typename CharT, typename CharTargetT, typename TraitsT, typename AllocT>
2197 struct is_string_of<std::basic_string<CharT, TraitsT, AllocT>, CharTargetT> : std::is_same<CharT, CharTargetT> {};
2198
2199 template <typename T, typename CharT>
2200 constexpr inline bool is_string_of_v = is_string_of<T, CharT>::value;
2201
2202 template <typename T, typename CharT>
2203 struct is_string_view_of : std::false_type {};
2204
2205 template <typename CharT, typename CharTargetT, typename TraitsT>
2206 struct is_string_view_of<std::basic_string_view<CharT, TraitsT>, CharTargetT> : std::is_same<CharT, CharTargetT> {};
2207
2208 template <typename T, typename CharT>
2209 constexpr inline bool is_string_view_of_v = is_string_view_of<T, CharT>::value;
2210
2211 template <typename T>
2212 using is_string_like
2213 = meta::boolean<is_specialization_of_v<T, std::basic_string> || is_specialization_of_v<T, std::basic_string_view> || is_string_literal_array_v<T>>;
2214
2215 template <typename T>
2216 constexpr inline bool is_string_like_v = is_string_like<T>::value;
2217
2218 template <typename T, typename CharT = char>
2219 using is_string_constructible = meta::boolean<
2220 is_string_literal_array_of_v<T,
2221 CharT> || std::is_same_v<T, const CharT*> || std::is_same_v<T, CharT> || is_string_of_v<T, CharT> || std::is_same_v<T, std::initializer_list<CharT>> || is_string_view_of_v<T, CharT>>;
2222
2223 template <typename T, typename CharT = char>
2224 constexpr inline bool is_string_constructible_v = is_string_constructible<T, CharT>::value;
2225
2226 template <typename T>
2227 using is_string_like_or_constructible = meta::boolean<is_string_like_v<T> || is_string_constructible_v<T>>;
2228
2229 template <typename T>
2230 struct is_pair : std::false_type {};
2231
2232 template <typename T1, typename T2>
2233 struct is_pair<std::pair<T1, T2>> : std::true_type {};
2234
2235 template <typename T, typename Char>
2236 using is_c_str_of = any<std::is_same<T, const Char*>, std::is_same<T, Char const* const>, std::is_same<T, Char*>, is_string_of<T, Char>,
2237 is_string_literal_array_of<T, Char>>;
2238
2239 template <typename T, typename Char>
2240 constexpr inline bool is_c_str_of_v = is_c_str_of<T, Char>::value;
2241
2242 template <typename T>
2243 using is_c_str = is_c_str_of<T, char>;
2244
2245 template <typename T>
2246 constexpr inline bool is_c_str_v = is_c_str<T>::value;
2247
2248 template <typename T>
2249 struct is_move_only : all<neg<std::is_reference<T>>, neg<std::is_copy_constructible<unqualified_t<T>>>, std::is_move_constructible<unqualified_t<T>>> {};
2250
2251 template <typename T>
2252 using is_not_move_only = neg<is_move_only<T>>;
2253
2254 namespace meta_detail {
2255 template <typename T>
2256 decltype(auto) force_tuple(T&& x) {
2257 if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::tuple>) {
2258 return std::forward<T>(x);
2259 }
2260 else {
2261 return std::tuple<T>(std::forward<T>(x));
2262 }
2263 }
2264 } // namespace meta_detail
2265
2266 template <typename... X>
2267 decltype(auto) tuplefy(X&&... x) {
2268 return std::tuple_cat(meta_detail::force_tuple(std::forward<X>(x))...);
2269 }
2270
2271 template <typename T, typename = void>
2272 struct iterator_tag {
2273 using type = std::input_iterator_tag;
2274 };
2275
2276 template <typename T>
2277 struct iterator_tag<T, conditional_t<false, typename std::iterator_traits<T>::iterator_category, void>> {
2278 using type = typename std::iterator_traits<T>::iterator_category;
2279 };
2280
2281}} // namespace sol::meta
2282
2283// end of sol/traits.hpp
2284
2285namespace sol {
2286 namespace detail {
2287 const bool default_safe_function_calls =
2288#if SOL_IS_ON(SOL_SAFE_FUNCTION_CALLS_I_)
2289 true;
2290#else
2291 false;
2292#endif
2293 } // namespace detail
2294
2295 namespace meta { namespace meta_detail {
2296 }} // namespace meta::meta_detail
2297
2298 namespace stack { namespace stack_detail {
2299 using undefined_method_func = void (*)(stack_reference);
2300
2301 template <typename T>
2302 void set_undefined_methods_on(stack_reference);
2303
2304 struct undefined_metatable;
2305 }} // namespace stack::stack_detail
2306} // namespace sol
2307
2308#endif // SOL_FORWARD_DETAIL_HPP
2309// end of sol/forward_detail.hpp
2310
2311// beginning of sol/bytecode.hpp
2312
2313// beginning of sol/compatibility.hpp
2314
2315// beginning of sol/compatibility/lua_version.hpp
2316
2317#if SOL_IS_ON(SOL_USE_CXX_LUA_I_)
2318 #include <lua.h>
2319 #include <lualib.h>
2320 #include <lauxlib.h>
2321#elif SOL_IS_ON(SOL_USE_LUA_HPP_I_)
2322 #include <lua.hpp>
2323#else
2324 extern "C" {
2325 #include <lua.h>
2326 #include <lauxlib.h>
2327 #include <lualib.h>
2328 }
2329#endif // C++ Mangling for Lua vs. Not
2330
2331#if defined(SOL_LUAJIT)
2332 #if (SOL_LUAJIT != 0)
2333 #define SOL_USE_LUAJIT_I_ SOL_ON
2334 #else
2335 #define SOL_USE_LUAJIT_I_ SOL_OFF
2336 #endif
2337#elif defined(LUAJIT_VERSION)
2338 #define SOL_USE_LUAJIT_I_ SOL_OFF
2339#else
2340 #define SOL_USE_LUAJIT_I_ SOL_DEFAULT_OFF
2341#endif // luajit
2342
2343#if SOL_IS_ON(SOL_USE_CXX_LUAJIT_I_)
2344 #include <luajit.h>
2345#elif SOL_IS_ON(SOL_USE_LUAJIT_I_)
2346 extern "C" {
2347 #include <luajit.h>
2348 }
2349#endif // C++ LuaJIT ... whatever that means
2350
2351#if defined(SOL_LUAJIT_VERSION)
2352 #define SOL_LUAJIT_VERSION_I_ SOL_LUAJIT_VERSION
2353#elif SOL_IS_ON(SOL_USE_LUAJIT_I_)
2354 #define SOL_LUAJIT_VERSION_I_ LUAJIT_VERSION_NUM
2355#else
2356 #define SOL_LUAJIT_VERSION_I_ 0
2357#endif
2358
2359#if defined(MOONJIT_VERSION)
2360 #define SOL_USE_MOONJIT_I_ SOL_ON
2361#else
2362 #define SOL_USE_MOONJIT_I_ SOL_OFF
2363#endif
2364
2365#if !defined(SOL_LUA_VERSION)
2366 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502
2367 #define SOL_LUA_VERSION LUA_VERSION_NUM
2368 #elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
2369 #define SOL_LUA_VERSION LUA_VERSION_NUM
2370 #elif !defined(LUA_VERSION_NUM) || !(LUA_VERSION_NUM)
2371 // Definitely 5.0
2372 #define SOL_LUA_VERSION 500
2373 #else
2374 // ??? Not sure, assume latest?
2375 #define SOL_LUA_VERSION 504
2376 #endif // Lua Version 503, 502, 501 || luajit, 500
2377#endif // SOL_LUA_VERSION
2378
2379#if defined(SOL_LUA_VERSION)
2380 #define SOL_LUA_VESION_I_ SOL_LUA_VERSION
2381#else
2382 #define SOL_LUA_VESION_I_ 504
2383#endif
2384
2385#if defined(SOL_EXCEPTIONS_ALWAYS_UNSAFE)
2386 #if (SOL_EXCEPTIONS_ALWAYS_UNSAFE != 0)
2387 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF
2388 #else
2389 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_ON
2390 #endif
2391#elif defined(SOL_EXCEPTIONS_SAFE_PROPAGATION)
2392 #if (SOL_EXCEPTIONS_SAFE_PROPAGATION != 0)
2393 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_ON
2394 #else
2395 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF
2396 #endif
2397#elif SOL_LUAJIT_VERSION_I_ >= 20100
2398 // LuaJIT 2.1.0-beta3 and better have exception support locked in for all platforms (mostly)
2399 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON
2400#elif SOL_LUAJIT_VERSION_I_ >= 20000
2401 // LuaJIT 2.0.x have exception support only on x64 builds
2402 #if SOL_IS_ON(SOL_PLATFORM_X64_I_)
2403 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON
2404 #else
2405 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF
2406 #endif
2407#else
2408 // otherwise, there is no exception safety for
2409 // shoving exceptions through Lua and errors should
2410 // always be serialized
2411 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_OFF
2412#endif // LuaJIT beta 02.01.00 have better exception handling on all platforms since beta3
2413
2414#if defined(SOL_LUAJIT_USE_EXCEPTION_TRAMPOLINE)
2415 #if (SOL_LUAJIT_USE_EXCEPTION_TRAMPOLINE != 0)
2416 #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_ON
2417 #else
2418 #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_OFF
2419 #endif
2420#else
2421 #if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS_I_) && SOL_IS_ON(SOL_USE_LUAJIT_I_)
2422 #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_ON
2423 #else
2424 #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_DEFAULT_OFF
2425 #endif
2426#endif
2427
2428#if defined(SOL_LUAL_STREAM_HAS_CLOSE_FUNCTION)
2429 #if (SOL_LUAL_STREAM_HAS_CLOSE_FUNCTION != 0)
2430 #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_ON
2431 #else
2432 #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_OFF
2433 #endif
2434#else
2435 #if SOL_IS_OFF(SOL_USE_LUAJIT_I_) && (SOL_LUA_VERSION > 501)
2436 #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_ON
2437 #else
2438 #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_DEFAULT_OFF
2439 #endif
2440#endif
2441
2442// end of sol/compatibility/lua_version.hpp
2443
2444#if SOL_IS_ON(SOL_USE_COMPATIBILITY_LAYER_I_)
2445
2446#if SOL_IS_ON(SOL_USE_CXX_LUA_I_) || SOL_IS_ON(SOL_USE_CXX_LUAJIT_I_)
2447#ifndef COMPAT53_LUA_CPP
2448#define COMPAT53_LUA_CPP 1
2449#endif // Build Lua Compat layer as C++
2450#endif
2451#ifndef COMPAT53_INCLUDE_SOURCE
2452#define COMPAT53_INCLUDE_SOURCE 1
2453#endif // Build Compat Layer Inline
2454
2455// beginning of sol/compatibility/compat-5.3.h
2456
2457#ifndef KEPLER_PROJECT_COMPAT53_H_
2458#define KEPLER_PROJECT_COMPAT53_H_
2459
2460#include <stddef.h>
2461#include <limits.h>
2462#include <string.h>
2463#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
2464extern "C" {
2465#endif
2466#include <lua.h>
2467#include <lauxlib.h>
2468#include <lualib.h>
2469#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
2470}
2471#endif
2472
2473#ifndef COMPAT53_PREFIX
2474/* we chose this name because many other lua bindings / libs have
2475* their own compatibility layer, and that use the compat53 declaration
2476* frequently, causing all kinds of linker / compiler issues
2477*/
2478# define COMPAT53_PREFIX kp_compat53
2479#endif // COMPAT53_PREFIX
2480
2481#ifndef COMPAT53_API
2482# if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE
2483# if defined(__GNUC__) || defined(__clang__)
2484# define COMPAT53_API __attribute__((__unused__)) static inline
2485# else
2486# define COMPAT53_API static inline
2487# endif /* Clang/GCC */
2488# else /* COMPAT53_INCLUDE_SOURCE */
2489/* we are not including source, so everything is extern */
2490# define COMPAT53_API extern
2491# endif /* COMPAT53_INCLUDE_SOURCE */
2492#endif /* COMPAT53_PREFIX */
2493
2494#define COMPAT53_CONCAT_HELPER(a, b) a##b
2495#define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b)
2496
2497/* declarations for Lua 5.1 */
2498#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
2499
2500/* XXX not implemented:
2501* lua_arith (new operators)
2502* lua_upvalueid
2503* lua_upvaluejoin
2504* lua_version
2505* lua_yieldk
2506*/
2507
2508#ifndef LUA_OK
2509# define LUA_OK 0
2510#endif
2511#ifndef LUA_OPADD
2512# define LUA_OPADD 0
2513#endif
2514#ifndef LUA_OPSUB
2515# define LUA_OPSUB 1
2516#endif
2517#ifndef LUA_OPMUL
2518# define LUA_OPMUL 2
2519#endif
2520#ifndef LUA_OPDIV
2521# define LUA_OPDIV 3
2522#endif
2523#ifndef LUA_OPMOD
2524# define LUA_OPMOD 4
2525#endif
2526#ifndef LUA_OPPOW
2527# define LUA_OPPOW 5
2528#endif
2529#ifndef LUA_OPUNM
2530# define LUA_OPUNM 6
2531#endif
2532#ifndef LUA_OPEQ
2533# define LUA_OPEQ 0
2534#endif
2535#ifndef LUA_OPLT
2536# define LUA_OPLT 1
2537#endif
2538#ifndef LUA_OPLE
2539# define LUA_OPLE 2
2540#endif
2541
2542/* LuaJIT/Lua 5.1 does not have the updated
2543* error codes for thread status/function returns (but some patched versions do)
2544* define it only if it's not found
2545*/
2546#if !defined(LUA_ERRGCMM)
2547/* Use + 2 because in some versions of Lua (Lua 5.1)
2548* LUA_ERRFILE is defined as (LUA_ERRERR+1)
2549* so we need to avoid it (LuaJIT might have something at this
2550* integer value too)
2551*/
2552# define LUA_ERRGCMM (LUA_ERRERR + 2)
2553#endif /* LUA_ERRGCMM define */
2554
2555#if !defined(MOONJIT_VERSION)
2556typedef size_t lua_Unsigned;
2557#endif
2558
2559typedef struct luaL_Buffer_53 {
2560 luaL_Buffer b; /* make incorrect code crash! */
2561 char *ptr;
2562 size_t nelems;
2563 size_t capacity;
2564 lua_State *L2;
2565} luaL_Buffer_53;
2566#define luaL_Buffer luaL_Buffer_53
2567
2568/* In PUC-Rio 5.1, userdata is a simple FILE*
2569* In LuaJIT, it's a struct where the first member is a FILE*
2570* We can't support the `closef` member
2571*/
2572typedef struct luaL_Stream {
2573 FILE *f;
2574} luaL_Stream;
2575
2576#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
2577COMPAT53_API int lua_absindex(lua_State *L, int i);
2578
2579#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith)
2580COMPAT53_API void lua_arith(lua_State *L, int op);
2581
2582#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare)
2583COMPAT53_API int lua_compare(lua_State *L, int idx1, int idx2, int op);
2584
2585#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy)
2586COMPAT53_API void lua_copy(lua_State *L, int from, int to);
2587
2588#define lua_getuservalue(L, i) \
2589 (lua_getfenv((L), (i)), lua_type((L), -1))
2590#define lua_setuservalue(L, i) \
2591 (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i)))
2592
2593#define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len)
2594COMPAT53_API void lua_len(lua_State *L, int i);
2595
2596#define lua_pushstring(L, s) \
2597 (lua_pushstring((L), (s)), lua_tostring((L), -1))
2598
2599#define lua_pushlstring(L, s, len) \
2600 ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1))
2601
2602#ifndef luaL_newlibtable
2603# define luaL_newlibtable(L, l) \
2604 (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1))
2605#endif
2606#ifndef luaL_newlib
2607# define luaL_newlib(L, l) \
2608 (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l)))
2609#endif
2610
2611#ifndef lua_pushglobaltable
2612# define lua_pushglobaltable(L) \
2613 lua_pushvalue((L), LUA_GLOBALSINDEX)
2614#endif
2615#define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp)
2616COMPAT53_API int lua_rawgetp(lua_State *L, int i, const void *p);
2617
2618#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp)
2619COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p);
2620
2621#define lua_rawlen(L, i) lua_objlen((L), (i))
2622
2623#define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL)
2624
2625#define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx)
2626COMPAT53_API lua_Number lua_tonumberx(lua_State *L, int i, int *isnum);
2627
2628#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
2629COMPAT53_API void luaL_checkversion(lua_State *L);
2630
2631#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
2632COMPAT53_API int lua_load(lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode);
2633
2634#define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex)
2635COMPAT53_API int luaL_loadfilex(lua_State *L, const char *filename, const char *mode);
2636
2637#define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx)
2638COMPAT53_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
2639
2640#define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53)
2641COMPAT53_API void luaL_checkstack(lua_State *L, int sp, const char *msg);
2642
2643#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable)
2644COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char *name);
2645
2646#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len)
2647COMPAT53_API lua_Integer luaL_len(lua_State *L, int i);
2648
2649#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs)
2650COMPAT53_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup);
2651
2652#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable)
2653COMPAT53_API void luaL_setmetatable(lua_State *L, const char *tname);
2654
2655#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata)
2656COMPAT53_API void *luaL_testudata(lua_State *L, int i, const char *tname);
2657
2658#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback)
2659COMPAT53_API void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level);
2660
2661#define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult)
2662COMPAT53_API int luaL_fileresult(lua_State *L, int stat, const char *fname);
2663
2664#define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult)
2665COMPAT53_API int luaL_execresult(lua_State *L, int stat);
2666
2667#define lua_callk(L, na, nr, ctx, cont) \
2668 ((void)(ctx), (void)(cont), lua_call((L), (na), (nr)))
2669#define lua_pcallk(L, na, nr, err, ctx, cont) \
2670 ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err)))
2671
2672#define lua_resume(L, from, nargs) \
2673 ((void)(from), lua_resume((L), (nargs)))
2674
2675#define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53)
2676COMPAT53_API void luaL_buffinit(lua_State *L, luaL_Buffer_53 *B);
2677
2678#define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53)
2679COMPAT53_API char *luaL_prepbuffsize(luaL_Buffer_53 *B, size_t s);
2680
2681#define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53)
2682COMPAT53_API void luaL_addlstring(luaL_Buffer_53 *B, const char *s, size_t l);
2683
2684#define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53)
2685COMPAT53_API void luaL_addvalue(luaL_Buffer_53 *B);
2686
2687#define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53)
2688COMPAT53_API void luaL_pushresult(luaL_Buffer_53 *B);
2689
2690#undef luaL_buffinitsize
2691#define luaL_buffinitsize(L, B, s) \
2692 (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s)))
2693
2694#undef luaL_prepbuffer
2695#define luaL_prepbuffer(B) \
2696 luaL_prepbuffsize((B), LUAL_BUFFERSIZE)
2697
2698#undef luaL_addchar
2699#define luaL_addchar(B, c) \
2700 ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \
2701 ((B)->ptr[(B)->nelems++] = (c)))
2702
2703#undef luaL_addsize
2704#define luaL_addsize(B, s) \
2705 ((B)->nelems += (s))
2706
2707#undef luaL_addstring
2708#define luaL_addstring(B, s) \
2709 luaL_addlstring((B), (s), strlen((s)))
2710
2711#undef luaL_pushresultsize
2712#define luaL_pushresultsize(B, s) \
2713 (luaL_addsize((B), (s)), luaL_pushresult((B)))
2714
2715#if defined(LUA_COMPAT_APIINTCASTS)
2716#define lua_pushunsigned(L, n) \
2717 lua_pushinteger((L), (lua_Integer)(n))
2718#define lua_tounsignedx(L, i, is) \
2719 ((lua_Unsigned)lua_tointegerx((L), (i), (is)))
2720#define lua_tounsigned(L, i) \
2721 lua_tounsignedx((L), (i), NULL)
2722#define luaL_checkunsigned(L, a) \
2723 ((lua_Unsigned)luaL_checkinteger((L), (a)))
2724#define luaL_optunsigned(L, a, d) \
2725 ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d)))
2726#endif
2727
2728#endif /* Lua 5.1 only */
2729
2730/* declarations for Lua 5.1 and 5.2 */
2731#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
2732
2733typedef int lua_KContext;
2734
2735typedef int(*lua_KFunction)(lua_State *L, int status, lua_KContext ctx);
2736
2737#define lua_dump(L, w, d, s) \
2738 ((void)(s), lua_dump((L), (w), (d)))
2739
2740#define lua_getfield(L, i, k) \
2741 (lua_getfield((L), (i), (k)), lua_type((L), -1))
2742
2743#define lua_gettable(L, i) \
2744 (lua_gettable((L), (i)), lua_type((L), -1))
2745
2746#define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti)
2747COMPAT53_API int lua_geti(lua_State *L, int index, lua_Integer i);
2748
2749#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger)
2750COMPAT53_API int lua_isinteger(lua_State *L, int index);
2751
2752#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53)
2753COMPAT53_API lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum);
2754
2755#define lua_numbertointeger(n, p) \
2756 ((*(p) = (lua_Integer)(n)), 1)
2757
2758#define lua_rawget(L, i) \
2759 (lua_rawget((L), (i)), lua_type((L), -1))
2760
2761#define lua_rawgeti(L, i, n) \
2762 (lua_rawgeti((L), (i), (n)), lua_type((L), -1))
2763
2764#define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate)
2765COMPAT53_API void lua_rotate(lua_State *L, int idx, int n);
2766
2767#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti)
2768COMPAT53_API void lua_seti(lua_State *L, int index, lua_Integer i);
2769
2770#define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber)
2771COMPAT53_API size_t lua_stringtonumber(lua_State *L, const char *s);
2772
2773#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring)
2774COMPAT53_API const char *luaL_tolstring(lua_State *L, int idx, size_t *len);
2775
2776#define luaL_getmetafield(L, o, e) \
2777 (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL)
2778
2779#define luaL_newmetatable(L, tn) \
2780 (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0)
2781
2782#define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53)
2783COMPAT53_API void luaL_requiref(lua_State *L, const char *modname,
2784 lua_CFunction openf, int glb);
2785
2786#endif /* Lua 5.1 and Lua 5.2 */
2787
2788/* declarations for Lua 5.2 */
2789#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502
2790
2791/* XXX not implemented:
2792* lua_isyieldable
2793* lua_getextraspace
2794* lua_arith (new operators)
2795* lua_pushfstring (new formats)
2796*/
2797
2798#define lua_getglobal(L, n) \
2799 (lua_getglobal((L), (n)), lua_type((L), -1))
2800
2801#define lua_getuservalue(L, i) \
2802 (lua_getuservalue((L), (i)), lua_type((L), -1))
2803
2804#define lua_pushlstring(L, s, len) \
2805 (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len)))
2806
2807#define lua_rawgetp(L, i, p) \
2808 (lua_rawgetp((L), (i), (p)), lua_type((L), -1))
2809
2810#define LUA_KFUNCTION(_name) \
2811 static int (_name)(lua_State *L, int status, lua_KContext ctx); \
2812 static int (_name ## _52)(lua_State *L) { \
2813 lua_KContext ctx; \
2814 int status = lua_getctx(L, &ctx); \
2815 return (_name)(L, status, ctx); \
2816 } \
2817 static int (_name)(lua_State *L, int status, lua_KContext ctx)
2818
2819#define lua_pcallk(L, na, nr, err, ctx, cont) \
2820 lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52)
2821
2822#define lua_callk(L, na, nr, ctx, cont) \
2823 lua_callk((L), (na), (nr), (ctx), cont ## _52)
2824
2825#define lua_yieldk(L, nr, ctx, cont) \
2826 lua_yieldk((L), (nr), (ctx), cont ## _52)
2827
2828#ifdef lua_call
2829# undef lua_call
2830# define lua_call(L, na, nr) \
2831 (lua_callk)((L), (na), (nr), 0, NULL)
2832#endif
2833
2834#ifdef lua_pcall
2835# undef lua_pcall
2836# define lua_pcall(L, na, nr, err) \
2837 (lua_pcallk)((L), (na), (nr), (err), 0, NULL)
2838#endif
2839
2840#ifdef lua_yield
2841# undef lua_yield
2842# define lua_yield(L, nr) \
2843 (lua_yieldk)((L), (nr), 0, NULL)
2844#endif
2845
2846#endif /* Lua 5.2 only */
2847
2848/* other Lua versions */
2849#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504
2850
2851# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, or 5.4)"
2852
2853#endif /* other Lua versions except 5.1, 5.2, 5.3, and 5.4 */
2854
2855/* helper macro for defining continuation functions (for every version
2856* *except* Lua 5.2) */
2857#ifndef LUA_KFUNCTION
2858#define LUA_KFUNCTION(_name) \
2859 static int (_name)(lua_State *L, int status, lua_KContext ctx)
2860#endif
2861
2862#if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE == 1
2863// beginning of sol/compatibility/compat-5.3.c.h
2864
2865#include <stddef.h>
2866#include <stdlib.h>
2867#include <string.h>
2868#include <ctype.h>
2869#include <errno.h>
2870#include <stdio.h>
2871
2872/* don't compile it again if it already is included via compat53.h */
2873#ifndef KEPLER_PROJECT_COMPAT53_C_
2874#define KEPLER_PROJECT_COMPAT53_C_
2875
2876/* definitions for Lua 5.1 only */
2877#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
2878
2879#ifndef COMPAT53_FOPEN_NO_LOCK
2880#if defined(_MSC_VER)
2881#define COMPAT53_FOPEN_NO_LOCK 1
2882#else /* otherwise */
2883#define COMPAT53_FOPEN_NO_LOCK 0
2884#endif /* VC++ only so far */
2885#endif /* No-lock fopen_s usage if possible */
2886
2887#if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK
2888#include <share.h>
2889#endif /* VC++ _fsopen for share-allowed file read */
2890
2891#ifndef COMPAT53_HAVE_STRERROR_R
2892#if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || (!defined(__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6))
2893#define COMPAT53_HAVE_STRERROR_R 1
2894#else /* none of the defines matched: define to 0 */
2895#define COMPAT53_HAVE_STRERROR_R 0
2896#endif /* have strerror_r of some form */
2897#endif /* strerror_r */
2898
2899#ifndef COMPAT53_HAVE_STRERROR_S
2900#if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__)
2901#define COMPAT53_HAVE_STRERROR_S 1
2902#else /* not VC++ or C11 */
2903#define COMPAT53_HAVE_STRERROR_S 0
2904#endif /* strerror_s from VC++ or C11 */
2905#endif /* strerror_s */
2906
2907#ifndef COMPAT53_LUA_FILE_BUFFER_SIZE
2908#define COMPAT53_LUA_FILE_BUFFER_SIZE 4096
2909#endif /* Lua File Buffer Size */
2910
2911static char* compat53_strerror(int en, char* buff, size_t sz) {
2912#if COMPAT53_HAVE_STRERROR_R
2913 /* use strerror_r here, because it's available on these specific platforms */
2914 if (sz > 0) {
2915 buff[0] = '\0';
2916 /* we don't care whether the GNU version or the XSI version is used: */
2917 if (strerror_r(en, buff, sz)) {
2918 /* Yes, we really DO want to ignore the return value!
2919 * GCC makes that extra hard, not even a (void) cast will do. */
2920 }
2921 if (buff[0] == '\0') {
2922 /* Buffer is unchanged, so we probably have called GNU strerror_r which
2923 * returned a static constant string. Chances are that strerror will
2924 * return the same static constant string and therefore be thread-safe. */
2925 return strerror(en);
2926 }
2927 }
2928 return buff; /* sz is 0 *or* strerror_r wrote into the buffer */
2929#elif COMPAT53_HAVE_STRERROR_S
2930 /* for MSVC and other C11 implementations, use strerror_s since it's
2931 * provided by default by the libraries */
2932 strerror_s(buff, sz, en);
2933 return buff;
2934#else
2935 /* fallback, but strerror is not guaranteed to be threadsafe due to modifying
2936 * errno itself and some impls not locking a static buffer for it ... but most
2937 * known systems have threadsafe errno: this might only change if the locale
2938 * is changed out from under someone while this function is being called */
2939 (void)buff;
2940 (void)sz;
2941 return strerror(en);
2942#endif
2943}
2944
2945COMPAT53_API int lua_absindex(lua_State* L, int i) {
2946 if (i < 0 && i > LUA_REGISTRYINDEX)
2947 i += lua_gettop(L) + 1;
2948 return i;
2949}
2950
2951static void compat53_call_lua(lua_State* L, char const code[], size_t len, int nargs, int nret) {
2952 lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code);
2953 if (lua_type(L, -1) != LUA_TFUNCTION) {
2954 lua_pop(L, 1);
2955 if (luaL_loadbuffer(L, code, len, "=none"))
2956 lua_error(L);
2957 lua_pushvalue(L, -1);
2958 lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code);
2959 }
2960 lua_insert(L, -nargs - 1);
2961 lua_call(L, nargs, nret);
2962}
2963
2964static const char compat53_arith_code[]
2965 = "local op,a,b=...\n"
2966 "if op==0 then return a+b\n"
2967 "elseif op==1 then return a-b\n"
2968 "elseif op==2 then return a*b\n"
2969 "elseif op==3 then return a/b\n"
2970 "elseif op==4 then return a%b\n"
2971 "elseif op==5 then return a^b\n"
2972 "elseif op==6 then return -a\n"
2973 "end\n";
2974
2975COMPAT53_API void lua_arith(lua_State* L, int op) {
2976 if (op < LUA_OPADD || op > LUA_OPUNM)
2977 luaL_error(L, "invalid 'op' argument for lua_arith");
2978 luaL_checkstack(L, 5, "not enough stack slots");
2979 if (op == LUA_OPUNM)
2980 lua_pushvalue(L, -1);
2981 lua_pushnumber(L, op);
2982 lua_insert(L, -3);
2983 compat53_call_lua(L, compat53_arith_code, sizeof(compat53_arith_code) - 1, 3, 1);
2984}
2985
2986static const char compat53_compare_code[]
2987 = "local a,b=...\n"
2988 "return a<=b\n";
2989
2990COMPAT53_API int lua_compare(lua_State* L, int idx1, int idx2, int op) {
2991 int result = 0;
2992 switch (op) {
2993 case LUA_OPEQ:
2994 return lua_equal(L, idx1, idx2);
2995 case LUA_OPLT:
2996 return lua_lessthan(L, idx1, idx2);
2997 case LUA_OPLE:
2998 luaL_checkstack(L, 5, "not enough stack slots");
2999 idx1 = lua_absindex(L, idx1);
3000 idx2 = lua_absindex(L, idx2);
3001 lua_pushvalue(L, idx1);
3002 lua_pushvalue(L, idx2);
3003 compat53_call_lua(L, compat53_compare_code, sizeof(compat53_compare_code) - 1, 2, 1);
3004 result = lua_toboolean(L, -1);
3005 lua_pop(L, 1);
3006 return result;
3007 default:
3008 luaL_error(L, "invalid 'op' argument for lua_compare");
3009 }
3010 return 0;
3011}
3012
3013COMPAT53_API void lua_copy(lua_State* L, int from, int to) {
3014 int abs_to = lua_absindex(L, to);
3015 luaL_checkstack(L, 1, "not enough stack slots");
3016 lua_pushvalue(L, from);
3017 lua_replace(L, abs_to);
3018}
3019
3020COMPAT53_API void lua_len(lua_State* L, int i) {
3021 switch (lua_type(L, i)) {
3022 case LUA_TSTRING:
3023 lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
3024 break;
3025 case LUA_TTABLE:
3026 if (!luaL_callmeta(L, i, "__len"))
3027 lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
3028 break;
3029 case LUA_TUSERDATA:
3030 if (luaL_callmeta(L, i, "__len"))
3031 break;
3032 /* FALLTHROUGH */
3033 default:
3034 luaL_error(L, "attempt to get length of a %s value", lua_typename(L, lua_type(L, i)));
3035 }
3036}
3037
3038COMPAT53_API int lua_rawgetp(lua_State* L, int i, const void* p) {
3039 int abs_i = lua_absindex(L, i);
3040 lua_pushlightuserdata(L, (void*)p);
3041 lua_rawget(L, abs_i);
3042 return lua_type(L, -1);
3043}
3044
3045COMPAT53_API void lua_rawsetp(lua_State* L, int i, const void* p) {
3046 int abs_i = lua_absindex(L, i);
3047 luaL_checkstack(L, 1, "not enough stack slots");
3048 lua_pushlightuserdata(L, (void*)p);
3049 lua_insert(L, -2);
3050 lua_rawset(L, abs_i);
3051}
3052
3053COMPAT53_API lua_Number lua_tonumberx(lua_State* L, int i, int* isnum) {
3054 lua_Number n = lua_tonumber(L, i);
3055 if (isnum != NULL) {
3056 *isnum = (n != 0 || lua_isnumber(L, i));
3057 }
3058 return n;
3059}
3060
3061COMPAT53_API void luaL_checkversion(lua_State* L) {
3062 (void)L;
3063}
3064
3065COMPAT53_API void luaL_checkstack(lua_State* L, int sp, const char* msg) {
3066 if (!lua_checkstack(L, sp + LUA_MINSTACK)) {
3067 if (msg != NULL)
3068 luaL_error(L, "stack overflow (%s)", msg);
3069 else {
3070 lua_pushliteral(L, "stack overflow");
3071 lua_error(L);
3072 }
3073 }
3074}
3075
3076COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char* name) {
3077 int abs_i = lua_absindex(L, i);
3078 luaL_checkstack(L, 3, "not enough stack slots");
3079 lua_pushstring(L, name);
3080 lua_gettable(L, abs_i);
3081 if (lua_istable(L, -1))
3082 return 1;
3083 lua_pop(L, 1);
3084 lua_newtable(L);
3085 lua_pushstring(L, name);
3086 lua_pushvalue(L, -2);
3087 lua_settable(L, abs_i);
3088 return 0;
3089}
3090
3091COMPAT53_API lua_Integer luaL_len(lua_State* L, int i) {
3092 lua_Integer res = 0;
3093 int isnum = 0;
3094 luaL_checkstack(L, 1, "not enough stack slots");
3095 lua_len(L, i);
3096 res = lua_tointegerx(L, -1, &isnum);
3097 lua_pop(L, 1);
3098 if (!isnum)
3099 luaL_error(L, "object length is not an integer");
3100 return res;
3101}
3102
3103COMPAT53_API void luaL_setfuncs(lua_State* L, const luaL_Reg* l, int nup) {
3104 luaL_checkstack(L, nup + 1, "too many upvalues");
3105 for (; l->name != NULL; l++) { /* fill the table with given functions */
3106 int i;
3107 lua_pushstring(L, l->name);
3108 for (i = 0; i < nup; i++) /* copy upvalues to the top */
3109 lua_pushvalue(L, -(nup + 1));
3110 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
3111 lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */
3112 }
3113 lua_pop(L, nup); /* remove upvalues */
3114}
3115
3116COMPAT53_API void luaL_setmetatable(lua_State* L, const char* tname) {
3117 luaL_checkstack(L, 1, "not enough stack slots");
3118 luaL_getmetatable(L, tname);
3119 lua_setmetatable(L, -2);
3120}
3121
3122COMPAT53_API void* luaL_testudata(lua_State* L, int i, const char* tname) {
3123 void* p = lua_touserdata(L, i);
3124 luaL_checkstack(L, 2, "not enough stack slots");
3125 if (p == NULL || !lua_getmetatable(L, i))
3126 return NULL;
3127 else {
3128 int res = 0;
3129 luaL_getmetatable(L, tname);
3130 res = lua_rawequal(L, -1, -2);
3131 lua_pop(L, 2);
3132 if (!res)
3133 p = NULL;
3134 }
3135 return p;
3136}
3137
3138static int compat53_countlevels(lua_State* L) {
3139 lua_Debug ar;
3140 int li = 1, le = 1;
3141 /* find an upper bound */
3142 while (lua_getstack(L, le, &ar)) {
3143 li = le;
3144 le *= 2;
3145 }
3146 /* do a binary search */
3147 while (li < le) {
3148 int m = (li + le) / 2;
3149 if (lua_getstack(L, m, &ar))
3150 li = m + 1;
3151 else
3152 le = m;
3153 }
3154 return le - 1;
3155}
3156
3157static int compat53_findfield(lua_State* L, int objidx, int level) {
3158 if (level == 0 || !lua_istable(L, -1))
3159 return 0; /* not found */
3160 lua_pushnil(L); /* start 'next' loop */
3161 while (lua_next(L, -2)) { /* for each pair in table */
3162 if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */
3163 if (lua_rawequal(L, objidx, -1)) { /* found object? */
3164 lua_pop(L, 1); /* remove value (but keep name) */
3165 return 1;
3166 }
3167 else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */
3168 lua_remove(L, -2); /* remove table (but keep name) */
3169 lua_pushliteral(L, ".");
3170 lua_insert(L, -2); /* place '.' between the two names */
3171 lua_concat(L, 3);
3172 return 1;
3173 }
3174 }
3175 lua_pop(L, 1); /* remove value */
3176 }
3177 return 0; /* not found */
3178}
3179
3180static int compat53_pushglobalfuncname(lua_State* L, lua_Debug* ar) {
3181 int top = lua_gettop(L);
3182 lua_getinfo(L, "f", ar); /* push function */
3183 lua_pushvalue(L, LUA_GLOBALSINDEX);
3184 if (compat53_findfield(L, top + 1, 2)) {
3185 lua_copy(L, -1, top + 1); /* move name to proper place */
3186 lua_pop(L, 2); /* remove pushed values */
3187 return 1;
3188 }
3189 else {
3190 lua_settop(L, top); /* remove function and global table */
3191 return 0;
3192 }
3193}
3194
3195static void compat53_pushfuncname(lua_State* L, lua_Debug* ar) {
3196 if (*ar->namewhat != '\0') /* is there a name? */
3197 lua_pushfstring(L, "function " LUA_QS, ar->name);
3198 else if (*ar->what == 'm') /* main? */
3199 lua_pushliteral(L, "main chunk");
3200 else if (*ar->what == 'C') {
3201 if (compat53_pushglobalfuncname(L, ar)) {
3202 lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
3203 lua_remove(L, -2); /* remove name */
3204 }
3205 else
3206 lua_pushliteral(L, "?");
3207 }
3208 else
3209 lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
3210}
3211
3212#define COMPAT53_LEVELS1 12 /* size of the first part of the stack */
3213#define COMPAT53_LEVELS2 10 /* size of the second part of the stack */
3214
3215COMPAT53_API void luaL_traceback(lua_State* L, lua_State* L1, const char* msg, int level) {
3216 lua_Debug ar;
3217 int top = lua_gettop(L);
3218 int numlevels = compat53_countlevels(L1);
3219 int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0;
3220 if (msg)
3221 lua_pushfstring(L, "%s\n", msg);
3222 lua_pushliteral(L, "stack traceback:");
3223 while (lua_getstack(L1, level++, &ar)) {
3224 if (level == mark) { /* too many levels? */
3225 lua_pushliteral(L, "\n\t..."); /* add a '...' */
3226 level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */
3227 }
3228 else {
3229 lua_getinfo(L1, "Slnt", &ar);
3230 lua_pushfstring(L, "\n\t%s:", ar.short_src);
3231 if (ar.currentline > 0)
3232 lua_pushfstring(L, "%d:", ar.currentline);
3233 lua_pushliteral(L, " in ");
3234 compat53_pushfuncname(L, &ar);
3235 lua_concat(L, lua_gettop(L) - top);
3236 }
3237 }
3238 lua_concat(L, lua_gettop(L) - top);
3239}
3240
3241COMPAT53_API int luaL_fileresult(lua_State* L, int stat, const char* fname) {
3242 const char* serr = NULL;
3243 int en = errno; /* calls to Lua API may change this value */
3244 char buf[512] = { 0 };
3245 if (stat) {
3246 lua_pushboolean(L, 1);
3247 return 1;
3248 }
3249 else {
3250 lua_pushnil(L);
3251 serr = compat53_strerror(en, buf, sizeof(buf));
3252 if (fname)
3253 lua_pushfstring(L, "%s: %s", fname, serr);
3254 else
3255 lua_pushstring(L, serr);
3256 lua_pushnumber(L, (lua_Number)en);
3257 return 3;
3258 }
3259}
3260
3261static int compat53_checkmode(lua_State* L, const char* mode, const char* modename, int err) {
3262 if (mode && strchr(mode, modename[0]) == NULL) {
3263 lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode);
3264 return err;
3265 }
3266 return LUA_OK;
3267}
3268
3269typedef struct {
3270 lua_Reader reader;
3271 void* ud;
3272 int has_peeked_data;
3273 const char* peeked_data;
3274 size_t peeked_data_size;
3275} compat53_reader_data;
3276
3277static const char* compat53_reader(lua_State* L, void* ud, size_t* size) {
3278 compat53_reader_data* data = (compat53_reader_data*)ud;
3279 if (data->has_peeked_data) {
3280 data->has_peeked_data = 0;
3281 *size = data->peeked_data_size;
3282 return data->peeked_data;
3283 }
3284 else
3285 return data->reader(L, data->ud, size);
3286}
3287
3288COMPAT53_API int lua_load(lua_State* L, lua_Reader reader, void* data, const char* source, const char* mode) {
3289 int status = LUA_OK;
3290 compat53_reader_data compat53_data = { reader, data, 1, 0, 0 };
3291 compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size));
3292 if (compat53_data.peeked_data && compat53_data.peeked_data_size && compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */
3293 status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX);
3294 else
3295 status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX);
3296 if (status != LUA_OK)
3297 return status;
3298 /* we need to call the original 5.1 version of lua_load! */
3299#undef lua_load
3300 return lua_load(L, compat53_reader, &compat53_data, source);
3301#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
3302}
3303
3304typedef struct {
3305 int n; /* number of pre-read characters */
3306 FILE* f; /* file being read */
3307 char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */
3308} compat53_LoadF;
3309
3310static const char* compat53_getF(lua_State* L, void* ud, size_t* size) {
3311 compat53_LoadF* lf = (compat53_LoadF*)ud;
3312 (void)L; /* not used */
3313 if (lf->n > 0) { /* are there pre-read characters to be read? */
3314 *size = lf->n; /* return them (chars already in buffer) */
3315 lf->n = 0; /* no more pre-read characters */
3316 }
3317 else { /* read a block from file */
3318 /* 'fread' can return > 0 *and* set the EOF flag. If next call to
3319 'compat53_getF' called 'fread', it might still wait for user input.
3320 The next check avoids this problem. */
3321 if (feof(lf->f))
3322 return NULL;
3323 *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */
3324 }
3325 return lf->buff;
3326}
3327
3328static int compat53_errfile(lua_State* L, const char* what, int fnameindex) {
3329 char buf[512] = { 0 };
3330 const char* serr = compat53_strerror(errno, buf, sizeof(buf));
3331 const char* filename = lua_tostring(L, fnameindex) + 1;
3332 lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
3333 lua_remove(L, fnameindex);
3334 return LUA_ERRFILE;
3335}
3336
3337static int compat53_skipBOM(compat53_LoadF* lf) {
3338 const char* p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */
3339 int c;
3340 lf->n = 0;
3341 do {
3342 c = getc(lf->f);
3343 if (c == EOF || c != *(const unsigned char*)p++)
3344 return c;
3345 lf->buff[lf->n++] = (char)c; /* to be read by the parser */
3346 } while (*p != '\0');
3347 lf->n = 0; /* prefix matched; discard it */
3348 return getc(lf->f); /* return next character */
3349}
3350
3351/*
3352** reads the first character of file 'f' and skips an optional BOM mark
3353** in its beginning plus its first line if it starts with '#'. Returns
3354** true if it skipped the first line. In any case, '*cp' has the
3355** first "valid" character of the file (after the optional BOM and
3356** a first-line comment).
3357*/
3358static int compat53_skipcomment(compat53_LoadF* lf, int* cp) {
3359 int c = *cp = compat53_skipBOM(lf);
3360 if (c == '#') { /* first line is a comment (Unix exec. file)? */
3361 do { /* skip first line */
3362 c = getc(lf->f);
3363 } while (c != EOF && c != '\n');
3364 *cp = getc(lf->f); /* skip end-of-line, if present */
3365 return 1; /* there was a comment */
3366 }
3367 else
3368 return 0; /* no comment */
3369}
3370
3371COMPAT53_API int luaL_loadfilex(lua_State* L, const char* filename, const char* mode) {
3372 compat53_LoadF lf;
3373 int status, readstatus;
3374 int c;
3375 int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
3376 if (filename == NULL) {
3377 lua_pushliteral(L, "=stdin");
3378 lf.f = stdin;
3379 }
3380 else {
3381 lua_pushfstring(L, "@%s", filename);
3382#if defined(_MSC_VER)
3383 /* This code is here to stop a deprecation error that stops builds
3384 * if a certain macro is defined. While normally not caring would
3385 * be best, some header-only libraries and builds can't afford to
3386 * dictate this to the user. A quick check shows that fopen_s this
3387 * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET,
3388 * possibly even before that so we don't need to do any version
3389 * number checks, since this has been there since forever. */
3390
3391 /* TO USER: if you want the behavior of typical fopen_s/fopen,
3392 * which does lock the file on VC++, define the macro used below to 0 */
3393#if COMPAT53_FOPEN_NO_LOCK
3394 lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */
3395 if (lf.f == NULL)
3396 return compat53_errfile(L, "open", fnameindex);
3397#else /* use default locking version */
3398 if (fopen_s(&lf.f, filename, "r") != 0)
3399 return compat53_errfile(L, "open", fnameindex);
3400#endif /* Locking vs. No-locking fopen variants */
3401#else
3402 lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */
3403 if (lf.f == NULL)
3404 return compat53_errfile(L, "open", fnameindex);
3405#endif
3406 }
3407 if (compat53_skipcomment(&lf, &c)) /* read initial portion */
3408 lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */
3409 if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
3410#if defined(_MSC_VER)
3411 if (freopen_s(&lf.f, filename, "rb", lf.f) != 0)
3412 return compat53_errfile(L, "reopen", fnameindex);
3413#else
3414 lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
3415 if (lf.f == NULL)
3416 return compat53_errfile(L, "reopen", fnameindex);
3417#endif
3418 compat53_skipcomment(&lf, &c); /* re-read initial portion */
3419 }
3420 if (c != EOF)
3421 lf.buff[lf.n++] = (char)c; /* 'c' is the first character of the stream */
3422 status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode);
3423 readstatus = ferror(lf.f);
3424 if (filename)
3425 fclose(lf.f); /* close file (even in case of errors) */
3426 if (readstatus) {
3427 lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
3428 return compat53_errfile(L, "read", fnameindex);
3429 }
3430 lua_remove(L, fnameindex);
3431 return status;
3432}
3433
3434COMPAT53_API int luaL_loadbufferx(lua_State* L, const char* buff, size_t sz, const char* name, const char* mode) {
3435 int status = LUA_OK;
3436 if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) {
3437 status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX);
3438 }
3439 else {
3440 status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX);
3441 }
3442 if (status != LUA_OK)
3443 return status;
3444 return luaL_loadbuffer(L, buff, sz, name);
3445}
3446
3447#if !defined(l_inspectstat) \
3448 && (defined(unix) || defined(__unix) || defined(__unix__) || defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || (defined(__APPLE__) && defined(__MACH__)))
3449/* some form of unix; check feature macros in unistd.h for details */
3450#include <unistd.h>
3451/* check posix version; the relevant include files and macros probably
3452 * were available before 2001, but I'm not sure */
3453#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
3454#include <sys/wait.h>
3455#define l_inspectstat(stat, what) \
3456 if (WIFEXITED(stat)) { \
3457 stat = WEXITSTATUS(stat); \
3458 } \
3459 else if (WIFSIGNALED(stat)) { \
3460 stat = WTERMSIG(stat); \
3461 what = "signal"; \
3462 }
3463#endif
3464#endif
3465
3466/* provide default (no-op) version */
3467#if !defined(l_inspectstat)
3468#define l_inspectstat(stat, what) ((void)0)
3469#endif
3470
3471COMPAT53_API int luaL_execresult(lua_State* L, int stat) {
3472 const char* what = "exit";
3473 if (stat == -1)
3474 return luaL_fileresult(L, 0, NULL);
3475 else {
3476 l_inspectstat(stat, what);
3477 if (*what == 'e' && stat == 0)
3478 lua_pushboolean(L, 1);
3479 else
3480 lua_pushnil(L);
3481 lua_pushstring(L, what);
3482 lua_pushinteger(L, stat);
3483 return 3;
3484 }
3485}
3486
3487COMPAT53_API void luaL_buffinit(lua_State* L, luaL_Buffer_53* B) {
3488 /* make it crash if used via pointer to a 5.1-style luaL_Buffer */
3489 B->b.p = NULL;
3490 B->b.L = NULL;
3491 B->b.lvl = 0;
3492 /* reuse the buffer from the 5.1-style luaL_Buffer though! */
3493 B->ptr = B->b.buffer;
3494 B->capacity = LUAL_BUFFERSIZE;
3495 B->nelems = 0;
3496 B->L2 = L;
3497}
3498
3499COMPAT53_API char* luaL_prepbuffsize(luaL_Buffer_53* B, size_t s) {
3500 if (B->capacity - B->nelems < s) { /* needs to grow */
3501 char* newptr = NULL;
3502 size_t newcap = B->capacity * 2;
3503 if (newcap - B->nelems < s)
3504 newcap = B->nelems + s;
3505 if (newcap < B->capacity) /* overflow */
3506 luaL_error(B->L2, "buffer too large");
3507 newptr = (char*)lua_newuserdata(B->L2, newcap);
3508 memcpy(newptr, B->ptr, B->nelems);
3509 if (B->ptr != B->b.buffer)
3510 lua_replace(B->L2, -2); /* remove old buffer */
3511 B->ptr = newptr;
3512 B->capacity = newcap;
3513 }
3514 return B->ptr + B->nelems;
3515}
3516
3517COMPAT53_API void luaL_addlstring(luaL_Buffer_53* B, const char* s, size_t l) {
3518 memcpy(luaL_prepbuffsize(B, l), s, l);
3519 luaL_addsize(B, l);
3520}
3521
3522COMPAT53_API void luaL_addvalue(luaL_Buffer_53* B) {
3523 size_t len = 0;
3524 const char* s = lua_tolstring(B->L2, -1, &len);
3525 if (!s)
3526 luaL_error(B->L2, "cannot convert value to string");
3527 if (B->ptr != B->b.buffer)
3528 lua_insert(B->L2, -2); /* userdata buffer must be at stack top */
3529 luaL_addlstring(B, s, len);
3530 lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1);
3531}
3532
3533void luaL_pushresult(luaL_Buffer_53* B) {
3534 lua_pushlstring(B->L2, B->ptr, B->nelems);
3535 if (B->ptr != B->b.buffer)
3536 lua_replace(B->L2, -2); /* remove userdata buffer */
3537}
3538
3539#endif /* Lua 5.1 */
3540
3541/* definitions for Lua 5.1 and Lua 5.2 */
3542#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
3543
3544COMPAT53_API int lua_geti(lua_State* L, int index, lua_Integer i) {
3545 index = lua_absindex(L, index);
3546 lua_pushinteger(L, i);
3547 lua_gettable(L, index);
3548 return lua_type(L, -1);
3549}
3550
3551COMPAT53_API int lua_isinteger(lua_State* L, int index) {
3552 if (lua_type(L, index) == LUA_TNUMBER) {
3553 lua_Number n = lua_tonumber(L, index);
3554 lua_Integer i = lua_tointeger(L, index);
3555 if (i == n)
3556 return 1;
3557 }
3558 return 0;
3559}
3560
3561COMPAT53_API lua_Integer lua_tointegerx(lua_State* L, int i, int* isnum) {
3562 int ok = 0;
3563 lua_Number n = lua_tonumberx(L, i, &ok);
3564 if (ok) {
3565 if (n == (lua_Integer)n) {
3566 if (isnum)
3567 *isnum = 1;
3568 return (lua_Integer)n;
3569 }
3570 }
3571 if (isnum)
3572 *isnum = 0;
3573 return 0;
3574}
3575
3576static void compat53_reverse(lua_State* L, int a, int b) {
3577 for (; a < b; ++a, --b) {
3578 lua_pushvalue(L, a);
3579 lua_pushvalue(L, b);
3580 lua_replace(L, a);
3581 lua_replace(L, b);
3582 }
3583}
3584
3585COMPAT53_API void lua_rotate(lua_State* L, int idx, int n) {
3586 int n_elems = 0;
3587 idx = lua_absindex(L, idx);
3588 n_elems = lua_gettop(L) - idx + 1;
3589 if (n < 0)
3590 n += n_elems;
3591 if (n > 0 && n < n_elems) {
3592 luaL_checkstack(L, 2, "not enough stack slots available");
3593 n = n_elems - n;
3594 compat53_reverse(L, idx, idx + n - 1);
3595 compat53_reverse(L, idx + n, idx + n_elems - 1);
3596 compat53_reverse(L, idx, idx + n_elems - 1);
3597 }
3598}
3599
3600COMPAT53_API void lua_seti(lua_State* L, int index, lua_Integer i) {
3601 luaL_checkstack(L, 1, "not enough stack slots available");
3602 index = lua_absindex(L, index);
3603 lua_pushinteger(L, i);
3604 lua_insert(L, -2);
3605 lua_settable(L, index);
3606}
3607
3608#if !defined(lua_str2number)
3609#define lua_str2number(s, p) strtod((s), (p))
3610#endif
3611
3612COMPAT53_API size_t lua_stringtonumber(lua_State* L, const char* s) {
3613 char* endptr;
3614 lua_Number n = lua_str2number(s, &endptr);
3615 if (endptr != s) {
3616 while (*endptr != '\0' && isspace((unsigned char)*endptr))
3617 ++endptr;
3618 if (*endptr == '\0') {
3619 lua_pushnumber(L, n);
3620 return endptr - s + 1;
3621 }
3622 }
3623 return 0;
3624}
3625
3626COMPAT53_API const char* luaL_tolstring(lua_State* L, int idx, size_t* len) {
3627 if (!luaL_callmeta(L, idx, "__tostring")) {
3628 int t = lua_type(L, idx), tt = 0;
3629 char const* name = NULL;
3630 switch (t) {
3631 case LUA_TNIL:
3632 lua_pushliteral(L, "nil");
3633 break;
3634 case LUA_TSTRING:
3635 case LUA_TNUMBER:
3636 lua_pushvalue(L, idx);
3637 break;
3638 case LUA_TBOOLEAN:
3639 if (lua_toboolean(L, idx))
3640 lua_pushliteral(L, "true");
3641 else
3642 lua_pushliteral(L, "false");
3643 break;
3644 default:
3645 tt = luaL_getmetafield(L, idx, "__name");
3646 name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t);
3647 lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx));
3648 if (tt != LUA_TNIL)
3649 lua_replace(L, -2);
3650 break;
3651 }
3652 }
3653 else {
3654 if (!lua_isstring(L, -1))
3655 luaL_error(L, "'__tostring' must return a string");
3656 }
3657 return lua_tolstring(L, -1, len);
3658}
3659
3660COMPAT53_API void luaL_requiref(lua_State* L, const char* modname, lua_CFunction openf, int glb) {
3661 luaL_checkstack(L, 3, "not enough stack slots available");
3662 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
3663 if (lua_getfield(L, -1, modname) == LUA_TNIL) {
3664 lua_pop(L, 1);
3665 lua_pushcfunction(L, openf);
3666 lua_pushstring(L, modname);
3667 lua_call(L, 1, 1);
3668 lua_pushvalue(L, -1);
3669 lua_setfield(L, -3, modname);
3670 }
3671 if (glb) {
3672 lua_pushvalue(L, -1);
3673 lua_setglobal(L, modname);
3674 }
3675 lua_replace(L, -2);
3676}
3677
3678#endif /* Lua 5.1 and 5.2 */
3679
3680#endif /* KEPLER_PROJECT_COMPAT53_C_ */
3681
3682/*********************************************************************
3683 * This file contains parts of Lua 5.2's and Lua 5.3's source code:
3684 *
3685 * Copyright (C) 1994-2014 Lua.org, PUC-Rio.
3686 *
3687 * Permission is hereby granted, free of charge, to any person obtaining
3688 * a copy of this software and associated documentation files (the
3689 * "Software"), to deal in the Software without restriction, including
3690 * without limitation the rights to use, copy, modify, merge, publish,
3691 * distribute, sublicense, and/or sell copies of the Software, and to
3692 * permit persons to whom the Software is furnished to do so, subject to
3693 * the following conditions:
3694 *
3695 * The above copyright notice and this permission notice shall be
3696 * included in all copies or substantial portions of the Software.
3697 *
3698 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3699 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3700 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
3701 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
3702 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
3703 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
3704 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3705 *********************************************************************/
3706// end of sol/compatibility/compat-5.3.c.h
3707
3708#endif
3709
3710#endif /* KEPLER_PROJECT_COMPAT53_H_ */
3711
3712// end of sol/compatibility/compat-5.3.h
3713
3714// beginning of sol/compatibility/compat-5.4.h
3715
3716#ifndef NOT_KEPLER_PROJECT_COMPAT54_H_
3717#define NOT_KEPLER_PROJECT_COMPAT54_H_
3718
3719#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
3720extern "C" {
3721#endif
3722#include <lua.h>
3723#include <lauxlib.h>
3724#include <lualib.h>
3725#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
3726}
3727#endif
3728
3729#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 504
3730
3731#if !defined(LUA_ERRGCMM)
3732/* So Lua 5.4 actually removes this, which breaks sol2...
3733 man, this API is quite unstable...!
3734*/
3735# define LUA_ERRGCMM (LUA_ERRERR + 2)
3736#endif /* LUA_ERRGCMM define */
3737
3738#endif // Lua 5.4 only
3739
3740#endif // NOT_KEPLER_PROJECT_COMPAT54_H_// end of sol/compatibility/compat-5.4.h
3741
3742#endif
3743
3744// end of sol/compatibility.hpp
3745
3746#include <vector>
3747#include <cstdint>
3748#include <cstddef>
3749
3750namespace sol {
3751
3752 template <typename Allocator = std::allocator<std::byte>>
3753 class basic_bytecode : private std::vector<std::byte, Allocator> {
3754 private:
3755 using base_t = std::vector<std::byte, Allocator>;
3756
3757 public:
3758 using typename base_t::allocator_type;
3759 using typename base_t::const_iterator;
3760 using typename base_t::const_pointer;
3761 using typename base_t::const_reference;
3762 using typename base_t::const_reverse_iterator;
3763 using typename base_t::difference_type;
3764 using typename base_t::iterator;
3765 using typename base_t::pointer;
3766 using typename base_t::reference;
3767 using typename base_t::reverse_iterator;
3768 using typename base_t::size_type;
3769 using typename base_t::value_type;
3770
3771 using base_t::base_t;
3772 using base_t::operator=;
3773
3774 using base_t::data;
3775 using base_t::empty;
3776 using base_t::max_size;
3777 using base_t::size;
3778
3779 using base_t::at;
3780 using base_t::operator[];
3781 using base_t::back;
3782 using base_t::front;
3783
3784 using base_t::begin;
3785 using base_t::cbegin;
3786 using base_t::cend;
3787 using base_t::end;
3788
3789 using base_t::crbegin;
3790 using base_t::crend;
3791 using base_t::rbegin;
3792 using base_t::rend;
3793
3794 using base_t::get_allocator;
3795 using base_t::swap;
3796
3797 using base_t::clear;
3798 using base_t::emplace;
3799 using base_t::emplace_back;
3800 using base_t::erase;
3801 using base_t::insert;
3802 using base_t::pop_back;
3803 using base_t::push_back;
3804 using base_t::reserve;
3805 using base_t::resize;
3806 using base_t::shrink_to_fit;
3807
3808 string_view as_string_view() const {
3809 return string_view(reinterpret_cast<const char*>(this->data()), this->size());
3810 }
3811 };
3812
3813 template <typename Container>
3814 inline int basic_insert_dump_writer(lua_State*, const void* memory, size_t memory_size, void* userdata) {
3815 using storage_t = Container;
3816 const std::byte* p_code = static_cast<const std::byte*>(memory);
3817 storage_t& bc = *static_cast<storage_t*>(userdata);
3818#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
3819 bc.insert(bc.cend(), p_code, p_code + memory_size);
3820#else
3821 try {
3822 bc.insert(bc.cend(), p_code, p_code + memory_size);
3823 }
3824 catch (...) {
3825 return -1;
3826 }
3827#endif
3828 return 0;
3829 }
3830
3831 using bytecode = basic_bytecode<>;
3832
3833 constexpr inline auto bytecode_dump_writer = &basic_insert_dump_writer<bytecode>;
3834
3835} // namespace sol
3836
3837// end of sol/bytecode.hpp
3838
3839// beginning of sol/stack.hpp
3840
3841// beginning of sol/trampoline.hpp
3842
3843// beginning of sol/types.hpp
3844
3845// beginning of sol/error.hpp
3846
3847#include <stdexcept>
3848#include <string>
3849#include <array>
3850
3851namespace sol {
3852 namespace detail {
3853 struct direct_error_tag {};
3854 const auto direct_error = direct_error_tag{};
3855
3856 struct error_result {
3857 int results;
3858 const char* format_string;
3859 std::array<const char*, 4> args_strings;
3860
3861 error_result() : results(0), format_string(nullptr) {
3862 }
3863
3864 error_result(int results) : results(results), format_string(nullptr) {
3865 }
3866
3867 error_result(const char* fmt, const char* msg) : results(0), format_string(fmt) {
3868 args_strings[0] = msg;
3869 }
3870 };
3871
3872 inline int handle_errors(lua_State* L, const error_result& er) {
3873 if (er.format_string == nullptr) {
3874 return er.results;
3875 }
3876 return luaL_error(L, er.format_string, er.args_strings[0], er.args_strings[1], er.args_strings[2], er.args_strings[3]);
3877 }
3878 } // namespace detail
3879
3880 class error : public std::runtime_error {
3881 private:
3882 // Because VC++ is upsetting, most of the time!
3883 std::string what_reason;
3884
3885 public:
3886 error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {
3887 }
3888 error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {
3889 }
3890 error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), what_reason(str) {
3891 }
3892 error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), what_reason(std::move(str)) {
3893 }
3894
3895 error(const error& e) = default;
3896 error(error&& e) = default;
3897 error& operator=(const error& e) = default;
3898 error& operator=(error&& e) = default;
3899
3900 virtual const char* what() const noexcept override {
3901 return what_reason.c_str();
3902 }
3903 };
3904
3905} // namespace sol
3906
3907// end of sol/error.hpp
3908
3909// beginning of sol/optional.hpp
3910
3911// beginning of sol/in_place.hpp
3912
3913#include <cstddef>
3914#include <utility>
3915
3916namespace sol {
3917
3918 using in_place_t = std::in_place_t;
3919 constexpr std::in_place_t in_place {};
3920 constexpr std::in_place_t in_place_of {};
3921
3922 template <typename T>
3923 using in_place_type_t = std::in_place_type_t<T>;
3924 template <typename T>
3925 constexpr std::in_place_type_t<T> in_place_type {};
3926
3927 template <size_t I>
3928 using in_place_index_t = std::in_place_index_t<I>;
3929 template <size_t I>
3930 constexpr in_place_index_t<I> in_place_index {};
3931
3932} // namespace sol
3933
3934// end of sol/in_place.hpp
3935
3936#if SOL_IS_ON(SOL_USE_BOOST_I_)
3937#include <boost/optional.hpp>
3938#else
3939// beginning of sol/optional_implementation.hpp
3940
3941#define SOL_TL_OPTIONAL_VERSION_MAJOR 0
3942#define SOL_TL_OPTIONAL_VERSION_MINOR 5
3943
3944#include <exception>
3945#include <functional>
3946#include <new>
3947#include <type_traits>
3948#include <utility>
3949#include <cstdlib>
3950#include <optional>
3951
3952#if (defined(_MSC_VER) && _MSC_VER == 1900)
3953#define SOL_TL_OPTIONAL_MSVC2015
3954#endif
3955
3956#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
3957#define SOL_TL_OPTIONAL_GCC49
3958#endif
3959
3960#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__))
3961#define SOL_TL_OPTIONAL_GCC54
3962#endif
3963
3964#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__))
3965#define SOL_TL_OPTIONAL_GCC55
3966#endif
3967
3968#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
3969#define SOL_TL_OPTIONAL_NO_CONSTRR
3970
3971#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor<T>::value
3972#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value
3973
3974#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
3975
3976#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
3977#ifndef SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
3978#define SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
3979namespace sol { namespace detail {
3980 template <class T>
3981 struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T> {};
3982#ifdef _GLIBCXX_VECTOR
3983 template <class T, class A>
3984 struct is_trivially_copy_constructible<std::vector<T, A>> : std::is_trivially_copy_constructible<T> {};
3985#endif
3986}} // namespace sol::detail
3987#endif
3988
3989#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) sol::detail::is_trivially_copy_constructible<T>::value
3990#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value
3991#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
3992#else
3993#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible<T>::value
3994#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value
3995#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
3996#endif
3997
3998#if __cplusplus > 201103L
3999#define SOL_TL_OPTIONAL_CXX14
4000#endif
4001
4002#if (__cplusplus == 201103L || defined(SOL_TL_OPTIONAL_MSVC2015) || defined(SOL_TL_OPTIONAL_GCC49))
4003#define SOL_TL_OPTIONAL_11_CONSTEXPR
4004#else
4005 /// \exclude
4006#define SOL_TL_OPTIONAL_11_CONSTEXPR constexpr
4007#endif
4008
4009namespace sol {
4010#ifndef SOL_TL_MONOSTATE_INPLACE_MUTEX
4011#define SOL_TL_MONOSTATE_INPLACE_MUTEX
4012 /// \brief Used to represent an optional with no data; essentially a bool
4013 class monostate {};
4014#endif
4015
4016 template <class T>
4017 class optional;
4018
4019 /// \exclude
4020 namespace detail {
4021#ifndef SOL_TL_TRAITS_MUTEX
4022#define SOL_TL_TRAITS_MUTEX
4023 // C++14-style aliases for brevity
4024 template <class T>
4025 using remove_const_t = typename std::remove_const<T>::type;
4026 template <class T>
4027 using remove_reference_t = typename std::remove_reference<T>::type;
4028 template <class T>
4029 using decay_t = typename std::decay<T>::type;
4030 template <bool E, class T = void>
4031 using enable_if_t = typename std::enable_if<E, T>::type;
4032 template <bool B, class T, class F>
4033 using conditional_t = typename std::conditional<B, T, F>::type;
4034
4035 // std::conjunction from C++17
4036 template <class...>
4037 struct conjunction : std::true_type {};
4038 template <class B>
4039 struct conjunction<B> : B {};
4040 template <class B, class... Bs>
4041 struct conjunction<B, Bs...> : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
4042
4043#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
4044#define SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
4045#endif
4046
4047#ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
4048 template <class T>
4049 struct is_pointer_to_non_const_member_func : std::false_type {};
4050 template <class T, class Ret, class... Args>
4051 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)> : std::true_type {};
4052 template <class T, class Ret, class... Args>
4053 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)&> : std::true_type {};
4054 template <class T, class Ret, class... Args>
4055 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&> : std::true_type {};
4056 template <class T, class Ret, class... Args>
4057 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile> : std::true_type {};
4058 template <class T, class Ret, class... Args>
4059 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&> : std::true_type {};
4060 template <class T, class Ret, class... Args>
4061 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&&> : std::true_type {};
4062
4063 template <class T>
4064 struct is_const_or_const_ref : std::false_type {};
4065 template <class T>
4066 struct is_const_or_const_ref<T const&> : std::true_type {};
4067 template <class T>
4068 struct is_const_or_const_ref<T const> : std::true_type {};
4069#endif
4070
4071 // std::invoke from C++17
4072 // https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
4073 template <typename Fn, typename... Args,
4074#ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
4075 typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value && is_const_or_const_ref<Args...>::value)>,
4076#endif
4077 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>, int = 0>
4078 constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
4079 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
4080 return std::mem_fn(f)(std::forward<Args>(args)...);
4081 }
4082
4083 template <typename Fn, typename... Args, typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
4084 constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
4085 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
4086 return std::forward<Fn>(f)(std::forward<Args>(args)...);
4087 }
4088
4089 // std::invoke_result from C++17
4090 template <class F, class, class... Us>
4091 struct invoke_result_impl;
4092
4093 template <class F, class... Us>
4094 struct invoke_result_impl<F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()), Us...> {
4095 using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
4096 };
4097
4098 template <class F, class... Us>
4099 using invoke_result = invoke_result_impl<F, void, Us...>;
4100
4101 template <class F, class... Us>
4102 using invoke_result_t = typename invoke_result<F, Us...>::type;
4103#endif
4104
4105 // std::void_t from C++17
4106 template <class...>
4107 struct voider {
4108 using type = void;
4109 };
4110 template <class... Ts>
4111 using void_t = typename voider<Ts...>::type;
4112
4113 // Trait for checking if a type is a sol::optional
4114 template <class T>
4115 struct is_optional_impl : std::false_type {};
4116 template <class T>
4117 struct is_optional_impl<optional<T>> : std::true_type {};
4118 template <class T>
4119 using is_optional = is_optional_impl<decay_t<T>>;
4120
4121 // Change void to sol::monostate
4122 template <class U>
4123 using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;
4124
4125 template <class F, class U, class = invoke_result_t<F, U>>
4126 using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;
4127
4128 // Check if invoking F for some Us returns void
4129 template <class F, class = void, class... U>
4130 struct returns_void_impl;
4131 template <class F, class... U>
4132 struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...> : std::is_void<invoke_result_t<F, U...>> {};
4133 template <class F, class... U>
4134 using returns_void = returns_void_impl<F, void, U...>;
4135
4136 template <class T, class... U>
4137 using enable_if_ret_void = enable_if_t<returns_void<T&&, U...>::value>;
4138
4139 template <class T, class... U>
4140 using disable_if_ret_void = enable_if_t<!returns_void<T&&, U...>::value>;
4141
4142 template <class T, class U>
4143 using enable_forward_value = detail::enable_if_t<std::is_constructible<T, U&&>::value && !std::is_same<detail::decay_t<U>, in_place_t>::value
4144 && !std::is_same<optional<T>, detail::decay_t<U>>::value>;
4145
4146 template <class T, class U, class Other>
4147 using enable_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && !std::is_constructible<T, optional<U>&>::value
4148 && !std::is_constructible<T, optional<U>&&>::value && !std::is_constructible<T, const optional<U>&>::value
4149 && !std::is_constructible<T, const optional<U>&&>::value && !std::is_convertible<optional<U>&, T>::value
4150 && !std::is_convertible<optional<U>&&, T>::value && !std::is_convertible<const optional<U>&, T>::value
4151 && !std::is_convertible<const optional<U>&&, T>::value>;
4152
4153 template <class T, class U>
4154 using enable_assign_forward = detail::enable_if_t<!std::is_same<optional<T>, detail::decay_t<U>>::value
4155 && !detail::conjunction<std::is_scalar<T>, std::is_same<T, detail::decay_t<U>>>::value && std::is_constructible<T, U>::value
4156 && std::is_assignable<T&, U>::value>;
4157
4158 template <class T, class U, class Other>
4159 using enable_assign_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && std::is_assignable<T&, Other>::value
4160 && !std::is_constructible<T, optional<U>&>::value && !std::is_constructible<T, optional<U>&&>::value
4161 && !std::is_constructible<T, const optional<U>&>::value && !std::is_constructible<T, const optional<U>&&>::value
4162 && !std::is_convertible<optional<U>&, T>::value && !std::is_convertible<optional<U>&&, T>::value
4163 && !std::is_convertible<const optional<U>&, T>::value && !std::is_convertible<const optional<U>&&, T>::value
4164 && !std::is_assignable<T&, optional<U>&>::value && !std::is_assignable<T&, optional<U>&&>::value
4165 && !std::is_assignable<T&, const optional<U>&>::value && !std::is_assignable<T&, const optional<U>&&>::value>;
4166
4167#ifdef _MSC_VER
4168 // TODO make a version which works with MSVC
4169 template <class T, class U = T>
4170 struct is_swappable : std::true_type {};
4171
4172 template <class T, class U = T>
4173 struct is_nothrow_swappable : std::true_type {};
4174#else
4175 // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
4176 namespace swap_adl_tests {
4177 // if swap ADL finds this then it would call std::swap otherwise (same
4178 // signature)
4179 struct tag {};
4180
4181 template <class T>
4182 tag swap(T&, T&);
4183 template <class T, std::size_t N>
4184 tag swap(T (&a)[N], T (&b)[N]);
4185
4186 // helper functions to test if an unqualified swap is possible, and if it
4187 // becomes std::swap
4188 template <class, class>
4189 std::false_type can_swap(...) noexcept(false);
4190 template <class T, class U, class = decltype(swap(std::declval<T&>(), std::declval<U&>()))>
4191 std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T&>(), std::declval<U&>())));
4192
4193 template <class, class>
4194 std::false_type uses_std(...);
4195 template <class T, class U>
4196 std::is_same<decltype(swap(std::declval<T&>(), std::declval<U&>())), tag> uses_std(int);
4197
4198 template <class T>
4199 struct is_std_swap_noexcept
4200 : std::integral_constant<bool, std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value> {};
4201
4202 template <class T, std::size_t N>
4203 struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
4204
4205 template <class T, class U>
4206 struct is_adl_swap_noexcept : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
4207 } // namespace swap_adl_tests
4208
4209 template <class T, class U = T>
4210 struct is_swappable : std::integral_constant<bool,
4211 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value
4212 && (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
4213 || (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> {};
4214
4215 template <class T, std::size_t N>
4216 struct is_swappable<T[N], T[N]> : std::integral_constant<bool,
4217 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value
4218 && (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value || is_swappable<T, T>::value)> {};
4219
4220 template <class T, class U = T>
4221 struct is_nothrow_swappable
4222 : std::integral_constant<bool,
4223 is_swappable<T, U>::value
4224 && ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_std_swap_noexcept<T>::value)
4225 || (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
4226#endif
4227
4228 // The storage base manages the actual storage, and correctly propagates
4229 // trivial destruction from T. This case is for when T is not trivially
4230 // destructible.
4231 template <class T, bool = ::std::is_trivially_destructible<T>::value>
4232 struct optional_storage_base {
4233 SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) {
4234 }
4235
4236 template <class... U>
4237 SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(true) {
4238 }
4239
4240 ~optional_storage_base() {
4241 if (m_has_value) {
4242 m_value.~T();
4243 m_has_value = false;
4244 }
4245 }
4246
4247 struct dummy {};
4248 union {
4249 dummy m_dummy;
4250 T m_value;
4251 };
4252
4253 bool m_has_value;
4254 };
4255
4256 // This case is for when T is trivially destructible.
4257 template <class T>
4258 struct optional_storage_base<T, true> {
4259 SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) {
4260 }
4261
4262 template <class... U>
4263 SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(true) {
4264 }
4265
4266 // No destructor, so this class is trivially destructible
4267
4268 struct dummy {};
4269 union {
4270 dummy m_dummy;
4271 T m_value;
4272 };
4273
4274 bool m_has_value = false;
4275 };
4276
4277 // This base class provides some handy member functions which can be used in
4278 // further derived classes
4279 template <class T>
4280 struct optional_operations_base : optional_storage_base<T> {
4281 using optional_storage_base<T>::optional_storage_base;
4282
4283 void hard_reset() noexcept {
4284 get().~T();
4285 this->m_has_value = false;
4286 }
4287
4288 template <class... Args>
4289 void construct(Args&&... args) noexcept {
4290 new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);
4291 this->m_has_value = true;
4292 }
4293
4294 template <class Opt>
4295 void assign(Opt&& rhs) {
4296 if (this->has_value()) {
4297 if (rhs.has_value()) {
4298 this->m_value = std::forward<Opt>(rhs).get();
4299 }
4300 else {
4301 this->m_value.~T();
4302 this->m_has_value = false;
4303 }
4304 }
4305
4306 else if (rhs.has_value()) {
4307 construct(std::forward<Opt>(rhs).get());
4308 }
4309 }
4310
4311 bool has_value() const {
4312 return this->m_has_value;
4313 }
4314
4315 SOL_TL_OPTIONAL_11_CONSTEXPR T& get() & {
4316 return this->m_value;
4317 }
4318 SOL_TL_OPTIONAL_11_CONSTEXPR const T& get() const& {
4319 return this->m_value;
4320 }
4321 SOL_TL_OPTIONAL_11_CONSTEXPR T&& get() && {
4322 return std::move(this->m_value);
4323 }
4324#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4325 constexpr const T&& get() const&& {
4326 return std::move(this->m_value);
4327 }
4328#endif
4329 };
4330
4331 // This class manages conditionally having a trivial copy constructor
4332 // This specialization is for when T is trivially copy constructible
4333 template <class T, bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>
4334 struct optional_copy_base : optional_operations_base<T> {
4335 using optional_operations_base<T>::optional_operations_base;
4336 };
4337
4338 // This specialization is for when T is not trivially copy constructible
4339 template <class T>
4340 struct optional_copy_base<T, false> : optional_operations_base<T> {
4341 using base_t = optional_operations_base<T>;
4342
4343 using base_t::base_t;
4344
4345 optional_copy_base() = default;
4346 optional_copy_base(const optional_copy_base& rhs) : base_t() {
4347 if (rhs.has_value()) {
4348 this->construct(rhs.get());
4349 }
4350 else {
4351 this->m_has_value = false;
4352 }
4353 }
4354
4355 optional_copy_base(optional_copy_base&& rhs) = default;
4356 optional_copy_base& operator=(const optional_copy_base& rhs) = default;
4357 optional_copy_base& operator=(optional_copy_base&& rhs) = default;
4358 };
4359
4360#ifndef SOL_TL_OPTIONAL_GCC49
4361 template <class T, bool = std::is_trivially_move_constructible<T>::value>
4362 struct optional_move_base : optional_copy_base<T> {
4363 using optional_copy_base<T>::optional_copy_base;
4364 };
4365#else
4366 template <class T, bool = false>
4367 struct optional_move_base;
4368#endif
4369 template <class T>
4370 struct optional_move_base<T, false> : optional_copy_base<T> {
4371 using optional_copy_base<T>::optional_copy_base;
4372
4373 optional_move_base() = default;
4374 optional_move_base(const optional_move_base& rhs) = default;
4375
4376 optional_move_base(optional_move_base&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value) {
4377 if (rhs.has_value()) {
4378 this->construct(std::move(rhs.get()));
4379 }
4380 else {
4381 this->m_has_value = false;
4382 }
4383 }
4384 optional_move_base& operator=(const optional_move_base& rhs) = default;
4385 optional_move_base& operator=(optional_move_base&& rhs) = default;
4386 };
4387
4388 // This class manages conditionally having a trivial copy assignment operator
4389 template <class T,
4390 bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) && SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
4391 && SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)>
4392 struct optional_copy_assign_base : optional_move_base<T> {
4393 using optional_move_base<T>::optional_move_base;
4394 };
4395
4396 template <class T>
4397 struct optional_copy_assign_base<T, false> : optional_move_base<T> {
4398 using optional_move_base<T>::optional_move_base;
4399
4400 optional_copy_assign_base() = default;
4401 optional_copy_assign_base(const optional_copy_assign_base& rhs) = default;
4402
4403 optional_copy_assign_base(optional_copy_assign_base&& rhs) = default;
4404 optional_copy_assign_base& operator=(const optional_copy_assign_base& rhs) {
4405 this->assign(rhs);
4406 return *this;
4407 }
4408 optional_copy_assign_base& operator=(optional_copy_assign_base&& rhs) = default;
4409 };
4410
4411#ifndef SOL_TL_OPTIONAL_GCC49
4412 template <class T,
4413 bool = std::is_trivially_destructible<T>::value&& std::is_trivially_move_constructible<T>::value&& std::is_trivially_move_assignable<T>::value>
4414 struct optional_move_assign_base : optional_copy_assign_base<T> {
4415 using optional_copy_assign_base<T>::optional_copy_assign_base;
4416 };
4417#else
4418 template <class T, bool = false>
4419 struct optional_move_assign_base;
4420#endif
4421
4422 template <class T>
4423 struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
4424 using optional_copy_assign_base<T>::optional_copy_assign_base;
4425
4426 optional_move_assign_base() = default;
4427 optional_move_assign_base(const optional_move_assign_base& rhs) = default;
4428
4429 optional_move_assign_base(optional_move_assign_base&& rhs) = default;
4430
4431 optional_move_assign_base& operator=(const optional_move_assign_base& rhs) = default;
4432
4433 optional_move_assign_base& operator=(optional_move_assign_base&& rhs) noexcept(
4434 std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_assignable<T>::value) {
4435 this->assign(std::move(rhs));
4436 return *this;
4437 }
4438 };
4439
4440 // optional_delete_ctor_base will conditionally delete copy and move
4441 // constructors depending on whether T is copy/move constructible
4442 template <class T, bool EnableCopy = std::is_copy_constructible<T>::value, bool EnableMove = std::is_move_constructible<T>::value>
4443 struct optional_delete_ctor_base {
4444 optional_delete_ctor_base() = default;
4445 optional_delete_ctor_base(const optional_delete_ctor_base&) = default;
4446 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default;
4447 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
4448 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
4449 };
4450
4451 template <class T>
4452 struct optional_delete_ctor_base<T, true, false> {
4453 optional_delete_ctor_base() = default;
4454 optional_delete_ctor_base(const optional_delete_ctor_base&) = default;
4455 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete;
4456 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
4457 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
4458 };
4459
4460 template <class T>
4461 struct optional_delete_ctor_base<T, false, true> {
4462 optional_delete_ctor_base() = default;
4463 optional_delete_ctor_base(const optional_delete_ctor_base&) = delete;
4464 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default;
4465 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
4466 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
4467 };
4468
4469 template <class T>
4470 struct optional_delete_ctor_base<T, false, false> {
4471 optional_delete_ctor_base() = default;
4472 optional_delete_ctor_base(const optional_delete_ctor_base&) = delete;
4473 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete;
4474 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
4475 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
4476 };
4477
4478 // optional_delete_assign_base will conditionally delete copy and move
4479 // constructors depending on whether T is copy/move constructible + assignable
4480 template <class T, bool EnableCopy = (std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value),
4481 bool EnableMove = (std::is_move_constructible<T>::value && std::is_move_assignable<T>::value)>
4482 struct optional_delete_assign_base {
4483 optional_delete_assign_base() = default;
4484 optional_delete_assign_base(const optional_delete_assign_base&) = default;
4485 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
4486 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default;
4487 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default;
4488 };
4489
4490 template <class T>
4491 struct optional_delete_assign_base<T, true, false> {
4492 optional_delete_assign_base() = default;
4493 optional_delete_assign_base(const optional_delete_assign_base&) = default;
4494 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
4495 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default;
4496 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete;
4497 };
4498
4499 template <class T>
4500 struct optional_delete_assign_base<T, false, true> {
4501 optional_delete_assign_base() = default;
4502 optional_delete_assign_base(const optional_delete_assign_base&) = default;
4503 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
4504 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete;
4505 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default;
4506 };
4507
4508 template <class T>
4509 struct optional_delete_assign_base<T, false, false> {
4510 optional_delete_assign_base() = default;
4511 optional_delete_assign_base(const optional_delete_assign_base&) = default;
4512 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
4513 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete;
4514 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete;
4515 };
4516
4517 } // namespace detail
4518
4519 /// \brief A tag type to represent an empty optional
4520 using nullopt_t = std::nullopt_t;
4521
4522 /// \brief Represents an empty optional
4523 /// \synopsis static constexpr nullopt_t nullopt;
4524 ///
4525 /// *Examples*:
4526 /// ```
4527 /// sol::optional<int> a = sol::nullopt;
4528 /// void foo (sol::optional<int>);
4529 /// foo(sol::nullopt); //pass an empty optional
4530 /// ```
4531 using std::nullopt;
4532
4533 class bad_optional_access : public std::exception {
4534 public:
4535 bad_optional_access() = default;
4536 const char* what() const noexcept {
4537 return "Optional has no value";
4538 }
4539 };
4540
4541 /// An optional object is an object that contains the storage for another
4542 /// object and manages the lifetime of this contained object, if any. The
4543 /// contained object may be initialized after the optional object has been
4544 /// initialized, and may be destroyed before the optional object has been
4545 /// destroyed. The initialization state of the contained object is tracked by
4546 /// the optional object.
4547 template <class T>
4548 class optional : private detail::optional_move_assign_base<T>,
4549 private detail::optional_delete_ctor_base<T>,
4550 private detail::optional_delete_assign_base<T> {
4551 using base = detail::optional_move_assign_base<T>;
4552
4553 static_assert(!std::is_same<T, in_place_t>::value, "instantiation of optional with in_place_t is ill-formed");
4554 static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value, "instantiation of optional with nullopt_t is ill-formed");
4555
4556 public:
4557#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55)
4558 /// \group and_then
4559 /// Carries out some operation which returns an optional on the stored
4560 /// object if there is one. \requires `std::invoke(std::forward<F>(f),
4561 /// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be
4562 /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a
4563 /// `std::optional<U>`. The return value is empty if `*this` is empty,
4564 /// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
4565 /// is returned.
4566 /// \group and_then
4567 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
4568 template <class F>
4569 SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & {
4570 using result = detail::invoke_result_t<F, T&>;
4571 static_assert(detail::is_optional<result>::value, "F must return an optional");
4572
4573 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
4574 }
4575
4576 /// \group and_then
4577 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
4578 template <class F>
4579 SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && {
4580 using result = detail::invoke_result_t<F, T&&>;
4581 static_assert(detail::is_optional<result>::value, "F must return an optional");
4582
4583 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
4584 }
4585
4586 /// \group and_then
4587 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
4588 template <class F>
4589 constexpr auto and_then(F&& f) const& {
4590 using result = detail::invoke_result_t<F, const T&>;
4591 static_assert(detail::is_optional<result>::value, "F must return an optional");
4592
4593 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
4594 }
4595
4596#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4597 /// \group and_then
4598 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
4599 template <class F>
4600 constexpr auto and_then(F&& f) const&& {
4601 using result = detail::invoke_result_t<F, const T&&>;
4602 static_assert(detail::is_optional<result>::value, "F must return an optional");
4603
4604 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
4605 }
4606#endif
4607#else
4608 /// \group and_then
4609 /// Carries out some operation which returns an optional on the stored
4610 /// object if there is one. \requires `std::invoke(std::forward<F>(f),
4611 /// value())` returns a `std::optional<U>` for some `U`.
4612 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
4613 /// value())`. Returns a `std::optional<U>`. The return value is empty if
4614 /// `*this` is empty, otherwise the return value of
4615 /// `std::invoke(std::forward<F>(f), value())` is returned.
4616 /// \group and_then
4617 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
4618 template <class F>
4619 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & {
4620 using result = detail::invoke_result_t<F, T&>;
4621 static_assert(detail::is_optional<result>::value, "F must return an optional");
4622
4623 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
4624 }
4625
4626 /// \group and_then
4627 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
4628 template <class F>
4629 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&&> and_then(F&& f) && {
4630 using result = detail::invoke_result_t<F, T&&>;
4631 static_assert(detail::is_optional<result>::value, "F must return an optional");
4632
4633 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
4634 }
4635
4636 /// \group and_then
4637 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
4638 template <class F>
4639 constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& {
4640 using result = detail::invoke_result_t<F, const T&>;
4641 static_assert(detail::is_optional<result>::value, "F must return an optional");
4642
4643 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
4644 }
4645
4646#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4647 /// \group and_then
4648 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
4649 template <class F>
4650 constexpr detail::invoke_result_t<F, const T&&> and_then(F&& f) const&& {
4651 using result = detail::invoke_result_t<F, const T&&>;
4652 static_assert(detail::is_optional<result>::value, "F must return an optional");
4653
4654 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt);
4655 }
4656#endif
4657#endif
4658
4659#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55)
4660 /// \brief Carries out some operation on the stored object if there is one.
4661 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
4662 /// value())`. Returns a `std::optional<U>`. The return value is empty if
4663 /// `*this` is empty, otherwise an `optional<U>` is constructed from the
4664 /// return value of `std::invoke(std::forward<F>(f), value())` and is
4665 /// returned.
4666 ///
4667 /// \group map
4668 /// \synopsis template <class F> constexpr auto map(F &&f) &;
4669 template <class F>
4670 SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & {
4671 return optional_map_impl(*this, std::forward<F>(f));
4672 }
4673
4674 /// \group map
4675 /// \synopsis template <class F> constexpr auto map(F &&f) &&;
4676 template <class F>
4677 SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && {
4678 return optional_map_impl(std::move(*this), std::forward<F>(f));
4679 }
4680
4681 /// \group map
4682 /// \synopsis template <class F> constexpr auto map(F &&f) const&;
4683 template <class F>
4684 constexpr auto map(F&& f) const& {
4685 return optional_map_impl(*this, std::forward<F>(f));
4686 }
4687
4688 /// \group map
4689 /// \synopsis template <class F> constexpr auto map(F &&f) const&&;
4690 template <class F>
4691 constexpr auto map(F&& f) const&& {
4692 return optional_map_impl(std::move(*this), std::forward<F>(f));
4693 }
4694#else
4695 /// \brief Carries out some operation on the stored object if there is one.
4696 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
4697 /// value())`. Returns a `std::optional<U>`. The return value is empty if
4698 /// `*this` is empty, otherwise an `optional<U>` is constructed from the
4699 /// return value of `std::invoke(std::forward<F>(f), value())` and is
4700 /// returned.
4701 ///
4702 /// \group map
4703 /// \synopsis template <class F> auto map(F &&f) &;
4704 template <class F>
4705 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & {
4706 return optional_map_impl(*this, std::forward<F>(f));
4707 }
4708
4709 /// \group map
4710 /// \synopsis template <class F> auto map(F &&f) &&;
4711 template <class F>
4712 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && {
4713 return optional_map_impl(std::move(*this), std::forward<F>(f));
4714 }
4715
4716 /// \group map
4717 /// \synopsis template <class F> auto map(F &&f) const&;
4718 template <class F>
4719 constexpr decltype(optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& {
4720 return optional_map_impl(*this, std::forward<F>(f));
4721 }
4722
4723#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4724 /// \group map
4725 /// \synopsis template <class F> auto map(F &&f) const&&;
4726 template <class F>
4727 constexpr decltype(optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& {
4728 return optional_map_impl(std::move(*this), std::forward<F>(f));
4729 }
4730#endif
4731#endif
4732
4733 /// \brief Calls `f` if the optional is empty
4734 /// \requires `std::invoke_result_t<F>` must be void or convertible to
4735 /// `optional<T>`.
4736 /// \effects If `*this` has a value, returns `*this`.
4737 /// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns
4738 /// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`.
4739 ///
4740 /// \group or_else
4741 /// \synopsis template <class F> optional<T> or_else (F &&f) &;
4742 template <class F, detail::enable_if_ret_void<F>* = nullptr>
4743 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
4744 if (has_value())
4745 return *this;
4746
4747 std::forward<F>(f)();
4748 return nullopt;
4749 }
4750
4751 /// \exclude
4752 template <class F, detail::disable_if_ret_void<F>* = nullptr>
4753 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
4754 return has_value() ? *this : std::forward<F>(f)();
4755 }
4756
4757 /// \group or_else
4758 /// \synopsis template <class F> optional<T> or_else (F &&f) &&;
4759 template <class F, detail::enable_if_ret_void<F>* = nullptr>
4760 optional<T> or_else(F&& f) && {
4761 if (has_value())
4762 return std::move(*this);
4763
4764 std::forward<F>(f)();
4765 return nullopt;
4766 }
4767
4768 /// \exclude
4769 template <class F, detail::disable_if_ret_void<F>* = nullptr>
4770 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && {
4771 return has_value() ? std::move(*this) : std::forward<F>(f)();
4772 }
4773
4774 /// \group or_else
4775 /// \synopsis template <class F> optional<T> or_else (F &&f) const &;
4776 template <class F, detail::enable_if_ret_void<F>* = nullptr>
4777 optional<T> or_else(F&& f) const& {
4778 if (has_value())
4779 return *this;
4780
4781 std::forward<F>(f)();
4782 return nullopt;
4783 }
4784
4785 /// \exclude
4786 template <class F, detail::disable_if_ret_void<F>* = nullptr>
4787 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& {
4788 return has_value() ? *this : std::forward<F>(f)();
4789 }
4790
4791#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4792 /// \exclude
4793 template <class F, detail::enable_if_ret_void<F>* = nullptr>
4794 optional<T> or_else(F&& f) const&& {
4795 if (has_value())
4796 return std::move(*this);
4797
4798 std::forward<F>(f)();
4799 return nullopt;
4800 }
4801
4802 /// \exclude
4803 template <class F, detail::disable_if_ret_void<F>* = nullptr>
4804 optional<T> or_else(F&& f) const&& {
4805 return has_value() ? std::move(*this) : std::forward<F>(f)();
4806 }
4807#endif
4808
4809 /// \brief Maps the stored value with `f` if there is one, otherwise returns
4810 /// `u`.
4811 ///
4812 /// \details If there is a value stored, then `f` is called with `**this`
4813 /// and the value is returned. Otherwise `u` is returned.
4814 ///
4815 /// \group map_or
4816 template <class F, class U>
4817 U map_or(F&& f, U&& u) & {
4818 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
4819 }
4820
4821 /// \group map_or
4822 template <class F, class U>
4823 U map_or(F&& f, U&& u) && {
4824 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
4825 }
4826
4827 /// \group map_or
4828 template <class F, class U>
4829 U map_or(F&& f, U&& u) const& {
4830 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
4831 }
4832
4833#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4834 /// \group map_or
4835 template <class F, class U>
4836 U map_or(F&& f, U&& u) const&& {
4837 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
4838 }
4839#endif
4840
4841 /// \brief Maps the stored value with `f` if there is one, otherwise calls
4842 /// `u` and returns the result.
4843 ///
4844 /// \details If there is a value stored, then `f` is
4845 /// called with `**this` and the value is returned. Otherwise
4846 /// `std::forward<U>(u)()` is returned.
4847 ///
4848 /// \group map_or_else
4849 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) &;
4850 template <class F, class U>
4851 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & {
4852 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
4853 }
4854
4855 /// \group map_or_else
4856 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
4857 /// &&;
4858 template <class F, class U>
4859 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && {
4860 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
4861 }
4862
4863 /// \group map_or_else
4864 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
4865 /// const &;
4866 template <class F, class U>
4867 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& {
4868 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
4869 }
4870
4871#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4872 /// \group map_or_else
4873 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
4874 /// const &&;
4875 template <class F, class U>
4876 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& {
4877 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
4878 }
4879#endif
4880
4881 /// \returns `u` if `*this` has a value, otherwise an empty optional.
4882 template <class U>
4883 constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const {
4884 using result = optional<detail::decay_t<U>>;
4885 return has_value() ? result { u } : result { nullopt };
4886 }
4887
4888 /// \returns `rhs` if `*this` is empty, otherwise the current value.
4889 /// \group disjunction
4890 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & {
4891 return has_value() ? *this : rhs;
4892 }
4893
4894 /// \group disjunction
4895 constexpr optional disjunction(const optional& rhs) const& {
4896 return has_value() ? *this : rhs;
4897 }
4898
4899 /// \group disjunction
4900 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && {
4901 return has_value() ? std::move(*this) : rhs;
4902 }
4903
4904#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4905 /// \group disjunction
4906 constexpr optional disjunction(const optional& rhs) const&& {
4907 return has_value() ? std::move(*this) : rhs;
4908 }
4909#endif
4910
4911 /// \group disjunction
4912 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & {
4913 return has_value() ? *this : std::move(rhs);
4914 }
4915
4916 /// \group disjunction
4917 constexpr optional disjunction(optional&& rhs) const& {
4918 return has_value() ? *this : std::move(rhs);
4919 }
4920
4921 /// \group disjunction
4922 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && {
4923 return has_value() ? std::move(*this) : std::move(rhs);
4924 }
4925
4926#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4927 /// \group disjunction
4928 constexpr optional disjunction(optional&& rhs) const&& {
4929 return has_value() ? std::move(*this) : std::move(rhs);
4930 }
4931#endif
4932
4933 /// Takes the value out of the optional, leaving it empty
4934 /// \group take
4935 optional take() & {
4936 optional ret = *this;
4937 reset();
4938 return ret;
4939 }
4940
4941 /// \group take
4942 optional take() const& {
4943 optional ret = *this;
4944 reset();
4945 return ret;
4946 }
4947
4948 /// \group take
4949 optional take() && {
4950 optional ret = std::move(*this);
4951 reset();
4952 return ret;
4953 }
4954
4955#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
4956 /// \group take
4957 optional take() const&& {
4958 optional ret = std::move(*this);
4959 reset();
4960 return ret;
4961 }
4962#endif
4963
4964 using value_type = T;
4965
4966 /// Constructs an optional that does not contain a value.
4967 /// \group ctor_empty
4968 constexpr optional() noexcept = default;
4969
4970 /// \group ctor_empty
4971 constexpr optional(nullopt_t) noexcept {
4972 }
4973
4974 /// Copy constructor
4975 ///
4976 /// If `rhs` contains a value, the stored value is direct-initialized with
4977 /// it. Otherwise, the constructed optional is empty.
4978 SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) = default;
4979
4980 /// Move constructor
4981 ///
4982 /// If `rhs` contains a value, the stored value is direct-initialized with
4983 /// it. Otherwise, the constructed optional is empty.
4984 SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default;
4985
4986 /// Constructs the stored value in-place using the given arguments.
4987 /// \group in_place
4988 /// \synopsis template <class... Args> constexpr explicit optional(in_place_t, Args&&... args);
4989 template <class... Args>
4990 constexpr explicit optional(detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>, Args&&... args)
4991 : base(in_place, std::forward<Args>(args)...) {
4992 }
4993
4994 /// \group in_place
4995 /// \synopsis template <class U, class... Args>\nconstexpr explicit optional(in_place_t, std::initializer_list<U>&, Args&&... args);
4996 template <class U, class... Args>
4997 SOL_TL_OPTIONAL_11_CONSTEXPR explicit optional(detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, in_place_t>,
4998 std::initializer_list<U> il, Args&&... args) {
4999 this->construct(il, std::forward<Args>(args)...);
5000 }
5001
5002#if 0 // SOL_MODIFICATION
5003 /// Constructs the stored value with `u`.
5004 /// \synopsis template <class U=T> constexpr optional(U &&u);
5005 template <class U = T, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr, detail::enable_forward_value<T, U>* = nullptr>
5006 constexpr optional(U&& u) : base(in_place, std::forward<U>(u)) {
5007 }
5008
5009 /// \exclude
5010 template <class U = T, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr, detail::enable_forward_value<T, U>* = nullptr>
5011 constexpr explicit optional(U&& u) : base(in_place, std::forward<U>(u)) {
5012 }
5013#else
5014 /// Constructs the stored value with `u`.
5015 /// \synopsis template <class U=T> constexpr optional(U &&u);
5016 constexpr optional(T&& u) : base(in_place, std::move(u)) {
5017 }
5018
5019 /// \exclude
5020 constexpr optional(const T& u) : base(in_place, u) {
5021 }
5022#endif // sol3 modification
5023
5024 /// Converting copy constructor.
5025 /// \synopsis template <class U> optional(const optional<U> &rhs);
5026 template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
5027 optional(const optional<U>& rhs) {
5028 if (rhs.has_value()) {
5029 this->construct(*rhs);
5030 }
5031 }
5032
5033 /// \exclude
5034 template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
5035 explicit optional(const optional<U>& rhs) {
5036 if (rhs.has_value()) {
5037 this->construct(*rhs);
5038 }
5039 }
5040
5041 /// Converting move constructor.
5042 /// \synopsis template <class U> optional(optional<U> &&rhs);
5043 template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
5044 optional(optional<U>&& rhs) {
5045 if (rhs.has_value()) {
5046 this->construct(std::move(*rhs));
5047 }
5048 }
5049
5050 /// \exclude
5051 template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr>
5052 explicit optional(optional<U>&& rhs) {
5053 this->construct(std::move(*rhs));
5054 }
5055
5056 /// Destroys the stored value if there is one.
5057 ~optional() = default;
5058
5059 /// Assignment to empty.
5060 ///
5061 /// Destroys the current value if there is one.
5062 optional& operator=(nullopt_t) noexcept {
5063 if (has_value()) {
5064 this->m_value.~T();
5065 this->m_has_value = false;
5066 }
5067
5068 return *this;
5069 }
5070
5071 /// Copy assignment.
5072 ///
5073 /// Copies the value from `rhs` if there is one. Otherwise resets the stored
5074 /// value in `*this`.
5075 optional& operator=(const optional& rhs) = default;
5076
5077 /// Move assignment.
5078 ///
5079 /// Moves the value from `rhs` if there is one. Otherwise resets the stored
5080 /// value in `*this`.
5081 optional& operator=(optional&& rhs) = default;
5082
5083 /// Assigns the stored value from `u`, destroying the old value if there was
5084 /// one.
5085 /// \synopsis optional &operator=(U &&u);
5086 template <class U = T, detail::enable_assign_forward<T, U>* = nullptr>
5087 optional& operator=(U&& u) {
5088 if (has_value()) {
5089 this->m_value = std::forward<U>(u);
5090 }
5091 else {
5092 this->construct(std::forward<U>(u));
5093 }
5094
5095 return *this;
5096 }
5097
5098 /// Converting copy assignment operator.
5099 ///
5100 /// Copies the value from `rhs` if there is one. Otherwise resets the stored
5101 /// value in `*this`.
5102 /// \synopsis optional &operator=(const optional<U> & rhs);
5103 template <class U, detail::enable_assign_from_other<T, U, const U&>* = nullptr>
5104 optional& operator=(const optional<U>& rhs) {
5105 if (has_value()) {
5106 if (rhs.has_value()) {
5107 this->m_value = *rhs;
5108 }
5109 else {
5110 this->hard_reset();
5111 }
5112 }
5113
5114 if (rhs.has_value()) {
5115 this->construct(*rhs);
5116 }
5117
5118 return *this;
5119 }
5120
5121 // TODO check exception guarantee
5122 /// Converting move assignment operator.
5123 ///
5124 /// Moves the value from `rhs` if there is one. Otherwise resets the stored
5125 /// value in `*this`.
5126 /// \synopsis optional &operator=(optional<U> && rhs);
5127 template <class U, detail::enable_assign_from_other<T, U, U>* = nullptr>
5128 optional& operator=(optional<U>&& rhs) {
5129 if (has_value()) {
5130 if (rhs.has_value()) {
5131 this->m_value = std::move(*rhs);
5132 }
5133 else {
5134 this->hard_reset();
5135 }
5136 }
5137
5138 if (rhs.has_value()) {
5139 this->construct(std::move(*rhs));
5140 }
5141
5142 return *this;
5143 }
5144
5145 /// Constructs the value in-place, destroying the current one if there is
5146 /// one.
5147 /// \group emplace
5148 template <class... Args>
5149 T& emplace(Args&&... args) {
5150 static_assert(std::is_constructible<T, Args&&...>::value, "T must be constructible with Args");
5151
5152 *this = nullopt;
5153 this->construct(std::forward<Args>(args)...);
5154 return value();
5155 }
5156
5157 /// \group emplace
5158 /// \synopsis template <class U, class... Args>\nT& emplace(std::initializer_list<U> il, Args &&... args);
5159 template <class U, class... Args>
5160 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, T&> emplace(std::initializer_list<U> il, Args&&... args) {
5161 *this = nullopt;
5162 this->construct(il, std::forward<Args>(args)...);
5163 return value();
5164 }
5165
5166 /// Swaps this optional with the other.
5167 ///
5168 /// If neither optionals have a value, nothing happens.
5169 /// If both have a value, the values are swapped.
5170 /// If one has a value, it is moved to the other and the movee is left
5171 /// valueless.
5172 void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&& detail::is_nothrow_swappable<T>::value) {
5173 if (has_value()) {
5174 if (rhs.has_value()) {
5175 using std::swap;
5176 swap(**this, *rhs);
5177 }
5178 else {
5179 new (std::addressof(rhs.m_value)) T(std::move(this->m_value));
5180 this->m_value.T::~T();
5181 }
5182 }
5183 else if (rhs.has_value()) {
5184 new (std::addressof(this->m_value)) T(std::move(rhs.m_value));
5185 rhs.m_value.T::~T();
5186 }
5187 }
5188
5189 /// \returns a pointer to the stored value
5190 /// \requires a value is stored
5191 /// \group pointer
5192 /// \synopsis constexpr const T *operator->() const;
5193 constexpr const T* operator->() const {
5194 return std::addressof(this->m_value);
5195 }
5196
5197 /// \group pointer
5198 /// \synopsis constexpr T *operator->();
5199 SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() {
5200 return std::addressof(this->m_value);
5201 }
5202
5203 /// \returns the stored value
5204 /// \requires a value is stored
5205 /// \group deref
5206 /// \synopsis constexpr T &operator*();
5207 SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() & {
5208 return this->m_value;
5209 }
5210
5211 /// \group deref
5212 /// \synopsis constexpr const T &operator*() const;
5213 constexpr const T& operator*() const& {
5214 return this->m_value;
5215 }
5216
5217 /// \exclude
5218 SOL_TL_OPTIONAL_11_CONSTEXPR T&& operator*() && {
5219 return std::move(this->m_value);
5220 }
5221
5222#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5223 /// \exclude
5224 constexpr const T&& operator*() const&& {
5225 return std::move(this->m_value);
5226 }
5227#endif
5228
5229 /// \returns whether or not the optional has a value
5230 /// \group has_value
5231 constexpr bool has_value() const noexcept {
5232 return this->m_has_value;
5233 }
5234
5235 /// \group has_value
5236 constexpr explicit operator bool() const noexcept {
5237 return this->m_has_value;
5238 }
5239
5240 /// \returns the contained value if there is one, otherwise throws
5241 /// [bad_optional_access]
5242 /// \group value
5243 /// \synopsis constexpr T &value();
5244 SOL_TL_OPTIONAL_11_CONSTEXPR T& value() & {
5245 if (has_value())
5246 return this->m_value;
5247#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
5248 std::abort();
5249#else
5250 throw bad_optional_access();
5251#endif // No exceptions allowed
5252 }
5253 /// \group value
5254 /// \synopsis constexpr const T &value() const;
5255 SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const& {
5256 if (has_value())
5257 return this->m_value;
5258#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
5259 std::abort();
5260#else
5261 throw bad_optional_access();
5262#endif // No exceptions allowed
5263 }
5264 /// \exclude
5265 SOL_TL_OPTIONAL_11_CONSTEXPR T&& value() && {
5266 if (has_value())
5267 return std::move(this->m_value);
5268#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
5269 std::abort();
5270#else
5271 throw bad_optional_access();
5272#endif // No exceptions allowed
5273 }
5274
5275#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5276 /// \exclude
5277 SOL_TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& {
5278 if (has_value())
5279 return std::move(this->m_value);
5280#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
5281 std::abort();
5282#else
5283 throw bad_optional_access();
5284#endif // No exceptions allowed
5285 }
5286#endif
5287
5288 /// \returns the stored value if there is one, otherwise returns `u`
5289 /// \group value_or
5290 template <class U>
5291 constexpr T value_or(U&& u) const& {
5292 static_assert(std::is_copy_constructible<T>::value && std::is_convertible<U&&, T>::value, "T must be copy constructible and convertible from U");
5293 return has_value() ? **this : static_cast<T>(std::forward<U>(u));
5294 }
5295
5296 /// \group value_or
5297 template <class U>
5298 SOL_TL_OPTIONAL_11_CONSTEXPR T value_or(U&& u) && {
5299 static_assert(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value, "T must be move constructible and convertible from U");
5300 return has_value() ? **this : static_cast<T>(std::forward<U>(u));
5301 }
5302
5303 /// Destroys the stored value if one exists, making the optional empty
5304 void reset() noexcept {
5305 if (has_value()) {
5306 this->m_value.~T();
5307 this->m_has_value = false;
5308 }
5309 }
5310 }; // namespace sol
5311
5312 /// \group relop
5313 /// \brief Compares two optional objects
5314 /// \details If both optionals contain a value, they are compared with `T`s
5315 /// relational operators. Otherwise `lhs` and `rhs` are equal only if they are
5316 /// both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs`
5317 /// is not.
5318 template <class T, class U>
5319 inline constexpr bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
5320 return lhs.has_value() == rhs.has_value() && (!lhs.has_value() || *lhs == *rhs);
5321 }
5322 /// \group relop
5323 template <class T, class U>
5324 inline constexpr bool operator!=(const optional<T>& lhs, const optional<U>& rhs) {
5325 return lhs.has_value() != rhs.has_value() || (lhs.has_value() && *lhs != *rhs);
5326 }
5327 /// \group relop
5328 template <class T, class U>
5329 inline constexpr bool operator<(const optional<T>& lhs, const optional<U>& rhs) {
5330 return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
5331 }
5332 /// \group relop
5333 template <class T, class U>
5334 inline constexpr bool operator>(const optional<T>& lhs, const optional<U>& rhs) {
5335 return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
5336 }
5337 /// \group relop
5338 template <class T, class U>
5339 inline constexpr bool operator<=(const optional<T>& lhs, const optional<U>& rhs) {
5340 return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
5341 }
5342 /// \group relop
5343 template <class T, class U>
5344 inline constexpr bool operator>=(const optional<T>& lhs, const optional<U>& rhs) {
5345 return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
5346 }
5347
5348 /// \group relop_nullopt
5349 /// \brief Compares an optional to a `nullopt`
5350 /// \details Equivalent to comparing the optional to an empty optional
5351 template <class T>
5352 inline constexpr bool operator==(const optional<T>& lhs, nullopt_t) noexcept {
5353 return !lhs.has_value();
5354 }
5355 /// \group relop_nullopt
5356 template <class T>
5357 inline constexpr bool operator==(nullopt_t, const optional<T>& rhs) noexcept {
5358 return !rhs.has_value();
5359 }
5360 /// \group relop_nullopt
5361 template <class T>
5362 inline constexpr bool operator!=(const optional<T>& lhs, nullopt_t) noexcept {
5363 return lhs.has_value();
5364 }
5365 /// \group relop_nullopt
5366 template <class T>
5367 inline constexpr bool operator!=(nullopt_t, const optional<T>& rhs) noexcept {
5368 return rhs.has_value();
5369 }
5370 /// \group relop_nullopt
5371 template <class T>
5372 inline constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
5373 return false;
5374 }
5375 /// \group relop_nullopt
5376 template <class T>
5377 inline constexpr bool operator<(nullopt_t, const optional<T>& rhs) noexcept {
5378 return rhs.has_value();
5379 }
5380 /// \group relop_nullopt
5381 template <class T>
5382 inline constexpr bool operator<=(const optional<T>& lhs, nullopt_t) noexcept {
5383 return !lhs.has_value();
5384 }
5385 /// \group relop_nullopt
5386 template <class T>
5387 inline constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
5388 return true;
5389 }
5390 /// \group relop_nullopt
5391 template <class T>
5392 inline constexpr bool operator>(const optional<T>& lhs, nullopt_t) noexcept {
5393 return lhs.has_value();
5394 }
5395 /// \group relop_nullopt
5396 template <class T>
5397 inline constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
5398 return false;
5399 }
5400 /// \group relop_nullopt
5401 template <class T>
5402 inline constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
5403 return true;
5404 }
5405 /// \group relop_nullopt
5406 template <class T>
5407 inline constexpr bool operator>=(nullopt_t, const optional<T>& rhs) noexcept {
5408 return !rhs.has_value();
5409 }
5410
5411 /// \group relop_t
5412 /// \brief Compares the optional with a value.
5413 /// \details If the optional has a value, it is compared with the other value
5414 /// using `T`s relational operators. Otherwise, the optional is considered
5415 /// less than the value.
5416 template <class T, class U>
5417 inline constexpr bool operator==(const optional<T>& lhs, const U& rhs) {
5418 return lhs.has_value() ? *lhs == rhs : false;
5419 }
5420 /// \group relop_t
5421 template <class T, class U>
5422 inline constexpr bool operator==(const U& lhs, const optional<T>& rhs) {
5423 return rhs.has_value() ? lhs == *rhs : false;
5424 }
5425 /// \group relop_t
5426 template <class T, class U>
5427 inline constexpr bool operator!=(const optional<T>& lhs, const U& rhs) {
5428 return lhs.has_value() ? *lhs != rhs : true;
5429 }
5430 /// \group relop_t
5431 template <class T, class U>
5432 inline constexpr bool operator!=(const U& lhs, const optional<T>& rhs) {
5433 return rhs.has_value() ? lhs != *rhs : true;
5434 }
5435 /// \group relop_t
5436 template <class T, class U>
5437 inline constexpr bool operator<(const optional<T>& lhs, const U& rhs) {
5438 return lhs.has_value() ? *lhs < rhs : true;
5439 }
5440 /// \group relop_t
5441 template <class T, class U>
5442 inline constexpr bool operator<(const U& lhs, const optional<T>& rhs) {
5443 return rhs.has_value() ? lhs < *rhs : false;
5444 }
5445 /// \group relop_t
5446 template <class T, class U>
5447 inline constexpr bool operator<=(const optional<T>& lhs, const U& rhs) {
5448 return lhs.has_value() ? *lhs <= rhs : true;
5449 }
5450 /// \group relop_t
5451 template <class T, class U>
5452 inline constexpr bool operator<=(const U& lhs, const optional<T>& rhs) {
5453 return rhs.has_value() ? lhs <= *rhs : false;
5454 }
5455 /// \group relop_t
5456 template <class T, class U>
5457 inline constexpr bool operator>(const optional<T>& lhs, const U& rhs) {
5458 return lhs.has_value() ? *lhs > rhs : false;
5459 }
5460 /// \group relop_t
5461 template <class T, class U>
5462 inline constexpr bool operator>(const U& lhs, const optional<T>& rhs) {
5463 return rhs.has_value() ? lhs > *rhs : true;
5464 }
5465 /// \group relop_t
5466 template <class T, class U>
5467 inline constexpr bool operator>=(const optional<T>& lhs, const U& rhs) {
5468 return lhs.has_value() ? *lhs >= rhs : false;
5469 }
5470 /// \group relop_t
5471 template <class T, class U>
5472 inline constexpr bool operator>=(const U& lhs, const optional<T>& rhs) {
5473 return rhs.has_value() ? lhs >= *rhs : true;
5474 }
5475
5476 /// \synopsis template <class T>\nvoid swap(optional<T> &lhs, optional<T> &rhs);
5477 template <class T, detail::enable_if_t<std::is_move_constructible<T>::value>* = nullptr, detail::enable_if_t<detail::is_swappable<T>::value>* = nullptr>
5478 void swap(optional<T>& lhs, optional<T>& rhs) noexcept(noexcept(lhs.swap(rhs))) {
5479 return lhs.swap(rhs);
5480 }
5481
5482 namespace detail {
5483 struct i_am_secret {};
5484 } // namespace detail
5485
5486 template <class T = detail::i_am_secret, class U, class Ret = detail::conditional_t<std::is_same<T, detail::i_am_secret>::value, detail::decay_t<U>, T>>
5487 inline constexpr optional<Ret> make_optional(U&& v) {
5488 return optional<Ret>(std::forward<U>(v));
5489 }
5490
5491 template <class T, class... Args>
5492 inline constexpr optional<T> make_optional(Args&&... args) {
5493 return optional<T>(in_place, std::forward<Args>(args)...);
5494 }
5495 template <class T, class U, class... Args>
5496 inline constexpr optional<T> make_optional(std::initializer_list<U> il, Args&&... args) {
5497 return optional<T>(in_place, il, std::forward<Args>(args)...);
5498 }
5499
5500#if __cplusplus >= 201703L
5501 template <class T>
5502 optional(T)->optional<T>;
5503#endif
5504
5505 /// \exclude
5506 namespace detail {
5507#ifdef SOL_TL_OPTIONAL_CXX14
5508 template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
5509 detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr>
5510 constexpr auto optional_map_impl(Opt&& opt, F&& f) {
5511 return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt);
5512 }
5513
5514 template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
5515 detail::enable_if_t<std::is_void<Ret>::value>* = nullptr>
5516 auto optional_map_impl(Opt&& opt, F&& f) {
5517 if (opt.has_value()) {
5518 detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
5519 return make_optional(monostate {});
5520 }
5521
5522 return optional<monostate>(nullopt);
5523 }
5524#else
5525 template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
5526 detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr>
5527
5528 constexpr auto optional_map_impl(Opt&& opt, F&& f) -> optional<Ret> {
5529 return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt);
5530 }
5531
5532 template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
5533 detail::enable_if_t<std::is_void<Ret>::value>* = nullptr>
5534
5535 auto optional_map_impl(Opt&& opt, F&& f) -> optional<monostate> {
5536 if (opt.has_value()) {
5537 detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
5538 return monostate {};
5539 }
5540
5541 return nullopt;
5542 }
5543#endif
5544 } // namespace detail
5545
5546 /// Specialization for when `T` is a reference. `optional<T&>` acts similarly
5547 /// to a `T*`, but provides more operations and shows intent more clearly.
5548 ///
5549 /// *Examples*:
5550 ///
5551 /// ```
5552 /// int i = 42;
5553 /// sol::optional<int&> o = i;
5554 /// *o == 42; //true
5555 /// i = 12;
5556 /// *o = 12; //true
5557 /// &*o == &i; //true
5558 /// ```
5559 ///
5560 /// Assignment has rebind semantics rather than assign-through semantics:
5561 ///
5562 /// ```
5563 /// int j = 8;
5564 /// o = j;
5565 ///
5566 /// &*o == &j; //true
5567 /// ```
5568 template <class T>
5569 class optional<T&> {
5570 public:
5571#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55)
5572 /// \group and_then
5573 /// Carries out some operation which returns an optional on the stored
5574 /// object if there is one. \requires `std::invoke(std::forward<F>(f),
5575 /// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be
5576 /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a
5577 /// `std::optional<U>`. The return value is empty if `*this` is empty,
5578 /// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
5579 /// is returned.
5580 /// \group and_then
5581 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
5582 template <class F>
5583 SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & {
5584 using result = detail::invoke_result_t<F, T&>;
5585 static_assert(detail::is_optional<result>::value, "F must return an optional");
5586
5587 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
5588 }
5589
5590 /// \group and_then
5591 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
5592 template <class F>
5593 SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && {
5594 using result = detail::invoke_result_t<F, T&>;
5595 static_assert(detail::is_optional<result>::value, "F must return an optional");
5596
5597 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
5598 }
5599
5600 /// \group and_then
5601 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
5602 template <class F>
5603 constexpr auto and_then(F&& f) const& {
5604 using result = detail::invoke_result_t<F, const T&>;
5605 static_assert(detail::is_optional<result>::value, "F must return an optional");
5606
5607 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
5608 }
5609
5610#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5611 /// \group and_then
5612 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
5613 template <class F>
5614 constexpr auto and_then(F&& f) const&& {
5615 using result = detail::invoke_result_t<F, const T&>;
5616 static_assert(detail::is_optional<result>::value, "F must return an optional");
5617
5618 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
5619 }
5620#endif
5621#else
5622 /// \group and_then
5623 /// Carries out some operation which returns an optional on the stored
5624 /// object if there is one. \requires `std::invoke(std::forward<F>(f),
5625 /// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be
5626 /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a
5627 /// `std::optional<U>`. The return value is empty if `*this` is empty,
5628 /// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
5629 /// is returned.
5630 /// \group and_then
5631 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
5632 template <class F>
5633 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & {
5634 using result = detail::invoke_result_t<F, T&>;
5635 static_assert(detail::is_optional<result>::value, "F must return an optional");
5636
5637 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
5638 }
5639
5640 /// \group and_then
5641 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
5642 template <class F>
5643 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) && {
5644 using result = detail::invoke_result_t<F, T&>;
5645 static_assert(detail::is_optional<result>::value, "F must return an optional");
5646
5647 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
5648 }
5649
5650 /// \group and_then
5651 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
5652 template <class F>
5653 constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& {
5654 using result = detail::invoke_result_t<F, const T&>;
5655 static_assert(detail::is_optional<result>::value, "F must return an optional");
5656
5657 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
5658 }
5659
5660#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5661 /// \group and_then
5662 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
5663 template <class F>
5664 constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const&& {
5665 using result = detail::invoke_result_t<F, const T&>;
5666 static_assert(detail::is_optional<result>::value, "F must return an optional");
5667
5668 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
5669 }
5670#endif
5671#endif
5672
5673#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55)
5674 /// \brief Carries out some operation on the stored object if there is one.
5675 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
5676 /// value())`. Returns a `std::optional<U>`. The return value is empty if
5677 /// `*this` is empty, otherwise an `optional<U>` is constructed from the
5678 /// return value of `std::invoke(std::forward<F>(f), value())` and is
5679 /// returned.
5680 ///
5681 /// \group map
5682 /// \synopsis template <class F> constexpr auto map(F &&f) &;
5683 template <class F>
5684 SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & {
5685 return detail::optional_map_impl(*this, std::forward<F>(f));
5686 }
5687
5688 /// \group map
5689 /// \synopsis template <class F> constexpr auto map(F &&f) &&;
5690 template <class F>
5691 SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && {
5692 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
5693 }
5694
5695 /// \group map
5696 /// \synopsis template <class F> constexpr auto map(F &&f) const&;
5697 template <class F>
5698 constexpr auto map(F&& f) const& {
5699 return detail::optional_map_impl(*this, std::forward<F>(f));
5700 }
5701
5702 /// \group map
5703 /// \synopsis template <class F> constexpr auto map(F &&f) const&&;
5704 template <class F>
5705 constexpr auto map(F&& f) const&& {
5706 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
5707 }
5708#else
5709 /// \brief Carries out some operation on the stored object if there is one.
5710 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
5711 /// value())`. Returns a `std::optional<U>`. The return value is empty if
5712 /// `*this` is empty, otherwise an `optional<U>` is constructed from the
5713 /// return value of `std::invoke(std::forward<F>(f), value())` and is
5714 /// returned.
5715 ///
5716 /// \group map
5717 /// \synopsis template <class F> auto map(F &&f) &;
5718 template <class F>
5719 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & {
5720 return detail::optional_map_impl(*this, std::forward<F>(f));
5721 }
5722
5723 /// \group map
5724 /// \synopsis template <class F> auto map(F &&f) &&;
5725 template <class F>
5726 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && {
5727 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
5728 }
5729
5730 /// \group map
5731 /// \synopsis template <class F> auto map(F &&f) const&;
5732 template <class F>
5733 constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& {
5734 return detail::optional_map_impl(*this, std::forward<F>(f));
5735 }
5736
5737#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5738 /// \group map
5739 /// \synopsis template <class F> auto map(F &&f) const&&;
5740 template <class F>
5741 constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& {
5742 return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
5743 }
5744#endif
5745#endif
5746
5747 /// \brief Calls `f` if the optional is empty
5748 /// \requires `std::invoke_result_t<F>` must be void or convertible to
5749 /// `optional<T>`. \effects If `*this` has a value, returns `*this`.
5750 /// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns
5751 /// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`.
5752 ///
5753 /// \group or_else
5754 /// \synopsis template <class F> optional<T> or_else (F &&f) &;
5755 template <class F, detail::enable_if_ret_void<F>* = nullptr>
5756 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
5757 if (has_value())
5758 return *this;
5759
5760 std::forward<F>(f)();
5761 return nullopt;
5762 }
5763
5764 /// \exclude
5765 template <class F, detail::disable_if_ret_void<F>* = nullptr>
5766 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & {
5767 return has_value() ? *this : std::forward<F>(f)();
5768 }
5769
5770 /// \group or_else
5771 /// \synopsis template <class F> optional<T> or_else (F &&f) &&;
5772 template <class F, detail::enable_if_ret_void<F>* = nullptr>
5773 optional<T> or_else(F&& f) && {
5774 if (has_value())
5775 return std::move(*this);
5776
5777 std::forward<F>(f)();
5778 return nullopt;
5779 }
5780
5781 /// \exclude
5782 template <class F, detail::disable_if_ret_void<F>* = nullptr>
5783 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && {
5784 return has_value() ? std::move(*this) : std::forward<F>(f)();
5785 }
5786
5787 /// \group or_else
5788 /// \synopsis template <class F> optional<T> or_else (F &&f) const &;
5789 template <class F, detail::enable_if_ret_void<F>* = nullptr>
5790 optional<T> or_else(F&& f) const& {
5791 if (has_value())
5792 return *this;
5793
5794 std::forward<F>(f)();
5795 return nullopt;
5796 }
5797
5798 /// \exclude
5799 template <class F, detail::disable_if_ret_void<F>* = nullptr>
5800 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& {
5801 return has_value() ? *this : std::forward<F>(f)();
5802 }
5803
5804#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5805 /// \exclude
5806 template <class F, detail::enable_if_ret_void<F>* = nullptr>
5807 optional<T> or_else(F&& f) const&& {
5808 if (has_value())
5809 return std::move(*this);
5810
5811 std::forward<F>(f)();
5812 return nullopt;
5813 }
5814
5815 /// \exclude
5816 template <class F, detail::disable_if_ret_void<F>* = nullptr>
5817 optional<T> or_else(F&& f) const&& {
5818 return has_value() ? std::move(*this) : std::forward<F>(f)();
5819 }
5820#endif
5821
5822 /// \brief Maps the stored value with `f` if there is one, otherwise returns
5823 /// `u`.
5824 ///
5825 /// \details If there is a value stored, then `f` is called with `**this`
5826 /// and the value is returned. Otherwise `u` is returned.
5827 ///
5828 /// \group map_or
5829 template <class F, class U>
5830 U map_or(F&& f, U&& u) & {
5831 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
5832 }
5833
5834 /// \group map_or
5835 template <class F, class U>
5836 U map_or(F&& f, U&& u) && {
5837 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
5838 }
5839
5840 /// \group map_or
5841 template <class F, class U>
5842 U map_or(F&& f, U&& u) const& {
5843 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u);
5844 }
5845
5846#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5847 /// \group map_or
5848 template <class F, class U>
5849 U map_or(F&& f, U&& u) const&& {
5850 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u);
5851 }
5852#endif
5853
5854 /// \brief Maps the stored value with `f` if there is one, otherwise calls
5855 /// `u` and returns the result.
5856 ///
5857 /// \details If there is a value stored, then `f` is
5858 /// called with `**this` and the value is returned. Otherwise
5859 /// `std::forward<U>(u)()` is returned.
5860 ///
5861 /// \group map_or_else
5862 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) &;
5863 template <class F, class U>
5864 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & {
5865 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
5866 }
5867
5868 /// \group map_or_else
5869 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
5870 /// &&;
5871 template <class F, class U>
5872 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && {
5873 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
5874 }
5875
5876 /// \group map_or_else
5877 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
5878 /// const &;
5879 template <class F, class U>
5880 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& {
5881 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)();
5882 }
5883
5884#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5885 /// \group map_or_else
5886 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u)
5887 /// const &&;
5888 template <class F, class U>
5889 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& {
5890 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)();
5891 }
5892#endif
5893
5894 /// \returns `u` if `*this` has a value, otherwise an empty optional.
5895 template <class U>
5896 constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const {
5897 using result = optional<detail::decay_t<U>>;
5898 return has_value() ? result { u } : result { nullopt };
5899 }
5900
5901 /// \returns `rhs` if `*this` is empty, otherwise the current value.
5902 /// \group disjunction
5903 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & {
5904 return has_value() ? *this : rhs;
5905 }
5906
5907 /// \group disjunction
5908 constexpr optional disjunction(const optional& rhs) const& {
5909 return has_value() ? *this : rhs;
5910 }
5911
5912 /// \group disjunction
5913 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && {
5914 return has_value() ? std::move(*this) : rhs;
5915 }
5916
5917#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5918 /// \group disjunction
5919 constexpr optional disjunction(const optional& rhs) const&& {
5920 return has_value() ? std::move(*this) : rhs;
5921 }
5922#endif
5923
5924 /// \group disjunction
5925 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & {
5926 return has_value() ? *this : std::move(rhs);
5927 }
5928
5929 /// \group disjunction
5930 constexpr optional disjunction(optional&& rhs) const& {
5931 return has_value() ? *this : std::move(rhs);
5932 }
5933
5934 /// \group disjunction
5935 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && {
5936 return has_value() ? std::move(*this) : std::move(rhs);
5937 }
5938
5939#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5940 /// \group disjunction
5941 constexpr optional disjunction(optional&& rhs) const&& {
5942 return has_value() ? std::move(*this) : std::move(rhs);
5943 }
5944#endif
5945
5946 /// Takes the value out of the optional, leaving it empty
5947 /// \group take
5948 optional take() & {
5949 optional ret = *this;
5950 reset();
5951 return ret;
5952 }
5953
5954 /// \group take
5955 optional take() const& {
5956 optional ret = *this;
5957 reset();
5958 return ret;
5959 }
5960
5961 /// \group take
5962 optional take() && {
5963 optional ret = std::move(*this);
5964 reset();
5965 return ret;
5966 }
5967
5968#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
5969 /// \group take
5970 optional take() const&& {
5971 optional ret = std::move(*this);
5972 reset();
5973 return ret;
5974 }
5975#endif
5976
5977 using value_type = T&;
5978
5979 /// Constructs an optional that does not contain a value.
5980 /// \group ctor_empty
5981 constexpr optional() noexcept : m_value(nullptr) {
5982 }
5983
5984 /// \group ctor_empty
5985 constexpr optional(nullopt_t) noexcept : m_value(nullptr) {
5986 }
5987
5988 /// Copy constructor
5989 ///
5990 /// If `rhs` contains a value, the stored value is direct-initialized with
5991 /// it. Otherwise, the constructed optional is empty.
5992 SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) noexcept = default;
5993
5994 /// Move constructor
5995 ///
5996 /// If `rhs` contains a value, the stored value is direct-initialized with
5997 /// it. Otherwise, the constructed optional is empty.
5998 SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default;
5999
6000 /// Constructs the stored value with `u`.
6001 /// \synopsis template <class U=T> constexpr optional(U &&u);
6002 template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr>
6003 constexpr optional(U&& u) : m_value(std::addressof(u)) {
6004 static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
6005 }
6006
6007 /// \exclude
6008 template <class U>
6009 constexpr explicit optional(const optional<U>& rhs) : optional(*rhs) {
6010 }
6011
6012 /// No-op
6013 ~optional() = default;
6014
6015 /// Assignment to empty.
6016 ///
6017 /// Destroys the current value if there is one.
6018 optional& operator=(nullopt_t) noexcept {
6019 m_value = nullptr;
6020 return *this;
6021 }
6022
6023 /// Copy assignment.
6024 ///
6025 /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
6026 /// resets the stored value in `*this`.
6027 optional& operator=(const optional& rhs) = default;
6028
6029 /// Rebinds this optional to `u`.
6030 ///
6031 /// \requires `U` must be an lvalue reference.
6032 /// \synopsis optional &operator=(U &&u);
6033 template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr>
6034 optional& operator=(U&& u) {
6035 static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
6036 m_value = std::addressof(u);
6037 return *this;
6038 }
6039
6040 /// Converting copy assignment operator.
6041 ///
6042 /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
6043 /// resets the stored value in `*this`.
6044 template <class U>
6045 optional& operator=(const optional<U>& rhs) {
6046 m_value = std::addressof(rhs.value());
6047 return *this;
6048 }
6049
6050 /// Constructs the value in-place, destroying the current one if there is
6051 /// one.
6052 ///
6053 /// \group emplace
6054 template <class... Args>
6055 T& emplace(Args&&... args) noexcept {
6056 static_assert(std::is_constructible<T, Args&&...>::value, "T must be constructible with Args");
6057
6058 *this = nullopt;
6059 this->construct(std::forward<Args>(args)...);
6060 }
6061
6062 /// Swaps this optional with the other.
6063 ///
6064 /// If neither optionals have a value, nothing happens.
6065 /// If both have a value, the values are swapped.
6066 /// If one has a value, it is moved to the other and the movee is left
6067 /// valueless.
6068 void swap(optional& rhs) noexcept {
6069 std::swap(m_value, rhs.m_value);
6070 }
6071
6072 /// \returns a pointer to the stored value
6073 /// \requires a value is stored
6074 /// \group pointer
6075 /// \synopsis constexpr const T *operator->() const;
6076 constexpr const T* operator->() const {
6077 return m_value;
6078 }
6079
6080 /// \group pointer
6081 /// \synopsis constexpr T *operator->();
6082 SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() {
6083 return m_value;
6084 }
6085
6086 /// \returns the stored value
6087 /// \requires a value is stored
6088 /// \group deref
6089 /// \synopsis constexpr T &operator*();
6090 SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() {
6091 return *m_value;
6092 }
6093
6094 /// \group deref
6095 /// \synopsis constexpr const T &operator*() const;
6096 constexpr const T& operator*() const {
6097 return *m_value;
6098 }
6099
6100 /// \returns whether or not the optional has a value
6101 /// \group has_value
6102 constexpr bool has_value() const noexcept {
6103 return m_value != nullptr;
6104 }
6105
6106 /// \group has_value
6107 constexpr explicit operator bool() const noexcept {
6108 return m_value != nullptr;
6109 }
6110
6111 /// \returns the contained value if there is one, otherwise throws
6112 /// [bad_optional_access]
6113 /// \group value
6114 /// synopsis constexpr T &value();
6115 SOL_TL_OPTIONAL_11_CONSTEXPR T& value() {
6116 if (has_value())
6117 return *m_value;
6118#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
6119 std::abort();
6120#else
6121 throw bad_optional_access();
6122#endif // No exceptions allowed
6123 }
6124 /// \group value
6125 /// \synopsis constexpr const T &value() const;
6126 SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const {
6127 if (has_value())
6128 return *m_value;
6129#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
6130 std::abort();
6131#else
6132 throw bad_optional_access();
6133#endif // No exceptions allowed
6134 }
6135
6136 /// \returns the stored value if there is one, otherwise returns `u`
6137 /// \group value_or
6138 template <class U>
6139 constexpr T& value_or(U&& u) const {
6140 static_assert(std::is_convertible<U&&, T&>::value, "T must be convertible from U");
6141 return has_value() ? const_cast<T&>(**this) : static_cast<T&>(std::forward<U>(u));
6142 }
6143
6144 /// Destroys the stored value if one exists, making the optional empty
6145 void reset() noexcept {
6146 m_value = nullptr;
6147 }
6148
6149 private:
6150 T* m_value;
6151 };
6152
6153} // namespace sol
6154
6155namespace std {
6156 // TODO SFINAE
6157 template <class T>
6158 struct hash<::sol::optional<T>> {
6159 ::std::size_t operator()(const ::sol::optional<T>& o) const {
6160 if (!o.has_value())
6161 return 0;
6162
6163 return ::std::hash<::sol::detail::remove_const_t<T>>()(*o);
6164 }
6165 };
6166} // namespace std
6167
6168// end of sol/optional_implementation.hpp
6169
6170#endif // Boost vs. Better optional
6171
6172#include <optional>
6173
6174namespace sol {
6175
6176#if SOL_IS_ON(SOL_USE_BOOST_I_)
6177 template <typename T>
6178 using optional = boost::optional<T>;
6179 using nullopt_t = boost::none_t;
6180 const nullopt_t nullopt = boost::none;
6181#endif // Boost vs. Better optional
6182
6183 namespace meta {
6184 template <typename T>
6185 using is_optional = any<is_specialization_of<T, optional>, is_specialization_of<T, std::optional>>;
6186
6187 template <typename T>
6188 constexpr inline bool is_optional_v = is_optional<T>::value;
6189 } // namespace meta
6190
6191 namespace detail {
6192 template <typename T>
6193 struct associated_nullopt {
6194 inline static constexpr std::nullopt_t value = std::nullopt;
6195 };
6196
6197#if SOL_IS_ON(SOL_USE_BOOST_I_)
6198 template <typename T>
6199 struct associated_nullopt<boost::optional<T>> {
6200 inline static constexpr std::nullopt_t value = boost::nullopt;
6201 };
6202#endif // Boost nullopt
6203
6204 template <typename T>
6205 inline constexpr auto associated_nullopt_v = associated_nullopt<T>::value;
6206 } // namespace detail
6207} // namespace sol
6208
6209// end of sol/optional.hpp
6210
6211// beginning of sol/raii.hpp
6212
6213#include <memory>
6214
6215namespace sol {
6216 namespace detail {
6217 struct default_construct {
6218 template <typename T, typename... Args>
6219 static void construct(T&& obj, Args&&... args) {
6220 typedef meta::unqualified_t<T> Tu;
6221 std::allocator<Tu> alloc{};
6222 std::allocator_traits<std::allocator<Tu>>::construct(alloc, std::forward<T>(obj), std::forward<Args>(args)...);
6223 }
6224
6225 template <typename T, typename... Args>
6226 void operator()(T&& obj, Args&&... args) const {
6227 construct(std::forward<T>(obj), std::forward<Args>(args)...);
6228 }
6229 };
6230
6231 struct default_destruct {
6232 template <typename T>
6233 static void destroy(T&& obj) {
6234 std::allocator<meta::unqualified_t<T>> alloc{};
6235 alloc.destroy(obj);
6236 }
6237
6238 template <typename T>
6239 void operator()(T&& obj) const {
6240 destroy(std::forward<T>(obj));
6241 }
6242 };
6243
6244 struct deleter {
6245 template <typename T>
6246 void operator()(T* p) const {
6247 delete p;
6248 }
6249 };
6250
6251 struct state_deleter {
6252 void operator()(lua_State* L) const {
6253 lua_close(L);
6254 }
6255 };
6256
6257 template <typename T, typename Dx, typename... Args>
6258 inline std::unique_ptr<T, Dx> make_unique_deleter(Args&&... args) {
6259 return std::unique_ptr<T, Dx>(new T(std::forward<Args>(args)...));
6260 }
6261
6262 template <typename Tag, typename T>
6263 struct tagged {
6264 private:
6265 T value_;
6266
6267 public:
6268 template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, tagged>> = meta::enabler>
6269 tagged(Arg&& arg, Args&&... args)
6270 : value_(std::forward<Arg>(arg), std::forward<Args>(args)...) {
6271 }
6272
6273 T& value() & {
6274 return value_;
6275 }
6276
6277 T const& value() const& {
6278 return value_;
6279 }
6280
6281 T&& value() && {
6282 return std::move(value_);
6283 }
6284 };
6285 } // namespace detail
6286
6287 template <typename... Args>
6288 struct constructor_list {};
6289
6290 template <typename... Args>
6291 using constructors = constructor_list<Args...>;
6292
6293 const auto default_constructor = constructors<types<>>{};
6294
6295 struct no_construction {};
6296 const auto no_constructor = no_construction{};
6297
6298 struct call_construction {};
6299 const auto call_constructor = call_construction{};
6300
6301 template <typename... Functions>
6302 struct constructor_wrapper {
6303 std::tuple<Functions...> functions;
6304 template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, constructor_wrapper>> = meta::enabler>
6305 constructor_wrapper(Arg&& arg, Args&&... args)
6306 : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {
6307 }
6308 };
6309
6310 template <typename... Functions>
6311 inline auto initializers(Functions&&... functions) {
6312 return constructor_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...);
6313 }
6314
6315 template <typename... Functions>
6316 struct factory_wrapper {
6317 std::tuple<Functions...> functions;
6318 template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, factory_wrapper>> = meta::enabler>
6319 factory_wrapper(Arg&& arg, Args&&... args)
6320 : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {
6321 }
6322 };
6323
6324 template <typename... Functions>
6325 inline auto factories(Functions&&... functions) {
6326 return factory_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...);
6327 }
6328
6329 template <typename Function>
6330 struct destructor_wrapper {
6331 Function fx;
6332 destructor_wrapper(Function f)
6333 : fx(std::move(f)) {
6334 }
6335 };
6336
6337 template <>
6338 struct destructor_wrapper<void> {};
6339
6340 const destructor_wrapper<void> default_destructor{};
6341
6342 template <typename Fx>
6343 inline auto destructor(Fx&& fx) {
6344 return destructor_wrapper<std::decay_t<Fx>>(std::forward<Fx>(fx));
6345 }
6346
6347} // namespace sol
6348
6349// end of sol/raii.hpp
6350
6351// beginning of sol/policies.hpp
6352
6353#include <array>
6354
6355namespace sol {
6356 namespace detail {
6357 struct policy_base_tag {};
6358 } // namespace detail
6359
6360 template <int Target, int... In>
6361 struct static_stack_dependencies : detail::policy_base_tag {};
6362 typedef static_stack_dependencies<-1, 1> self_dependency;
6363 template <int... In>
6364 struct returns_self_with : detail::policy_base_tag {};
6365 typedef returns_self_with<> returns_self;
6366
6367 struct stack_dependencies : detail::policy_base_tag {
6368 int target;
6369 std::array<int, 64> stack_indices;
6370 std::size_t len;
6371
6372 template <typename... Args>
6373 stack_dependencies(int stack_target, Args&&... args) : target(stack_target), stack_indices(), len(sizeof...(Args)) {
6374 std::size_t i = 0;
6375 (void)detail::swallow{ int(), (stack_indices[i++] = static_cast<int>(std::forward<Args>(args)), int())... };
6376 }
6377
6378 int& operator[](std::size_t i) {
6379 return stack_indices[i];
6380 }
6381
6382 const int& operator[](std::size_t i) const {
6383 return stack_indices[i];
6384 }
6385
6386 std::size_t size() const {
6387 return len;
6388 }
6389 };
6390
6391 template <typename F, typename... Policies>
6392 struct policy_wrapper {
6393 typedef std::index_sequence_for<Policies...> indices;
6394
6395 F value;
6396 std::tuple<Policies...> policies;
6397
6398 template <typename Fx, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Fx>, policy_wrapper>>> = meta::enabler>
6399 policy_wrapper(Fx&& fx, Args&&... args) : value(std::forward<Fx>(fx)), policies(std::forward<Args>(args)...) {
6400 }
6401
6402 policy_wrapper(const policy_wrapper&) = default;
6403 policy_wrapper& operator=(const policy_wrapper&) = default;
6404 policy_wrapper(policy_wrapper&&) = default;
6405 policy_wrapper& operator=(policy_wrapper&&) = default;
6406 };
6407
6408 template <typename F, typename... Args>
6409 auto policies(F&& f, Args&&... args) {
6410 return policy_wrapper<std::decay_t<F>, std::decay_t<Args>...>(std::forward<F>(f), std::forward<Args>(args)...);
6411 }
6412
6413 namespace detail {
6414 template <typename T>
6415 using is_policy = meta::is_specialization_of<T, policy_wrapper>;
6416
6417 template <typename T>
6418 inline constexpr bool is_policy_v = is_policy<T>::value;
6419 } // namespace detail
6420} // namespace sol
6421
6422// end of sol/policies.hpp
6423
6424// beginning of sol/ebco.hpp
6425
6426#include <type_traits>
6427#include <utility>
6428
6429namespace sol { namespace detail {
6430
6431 template <typename T, std::size_t tag = 0, typename = void>
6432 struct ebco {
6433 T value_;
6434
6435 ebco() = default;
6436 ebco(const ebco&) = default;
6437 ebco(ebco&&) = default;
6438 ebco& operator=(const ebco&) = default;
6439 ebco& operator=(ebco&&) = default;
6440 ebco(const T& v) : value_(v){};
6441 ebco(T&& v) : value_(std::move(v)){};
6442 ebco& operator=(const T& v) {
6443 value_ = v;
6444 return *this;
6445 }
6446 ebco& operator=(T&& v) {
6447 value_ = std::move(v);
6448 return *this;
6449 };
6450 template <typename Arg, typename... Args,
6451 typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
6452 ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
6453 ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
6454
6455 T& value() & {
6456 return value_;
6457 }
6458
6459 T const& value() const & {
6460 return value_;
6461 }
6462
6463 T&& value() && {
6464 return std::move(value_);
6465 }
6466 };
6467
6468 template <typename T, std::size_t tag>
6469 struct ebco<T, tag, std::enable_if_t<!std::is_reference_v<T> && std::is_class_v<T> && !std::is_final_v<T>>> : T {
6470 ebco() = default;
6471 ebco(const ebco&) = default;
6472 ebco(ebco&&) = default;
6473 ebco(const T& v) : T(v){};
6474 ebco(T&& v) : T(std::move(v)){};
6475 template <typename Arg, typename... Args,
6476 typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
6477 ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
6478 ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...) {
6479 }
6480
6481 ebco& operator=(const ebco&) = default;
6482 ebco& operator=(ebco&&) = default;
6483 ebco& operator=(const T& v) {
6484 static_cast<T&>(*this) = v;
6485 return *this;
6486 }
6487 ebco& operator=(T&& v) {
6488 static_cast<T&>(*this) = std::move(v);
6489 return *this;
6490 };
6491
6492 T& value() & {
6493 return static_cast<T&>(*this);
6494 }
6495
6496 T const& value() const & {
6497 return static_cast<T const&>(*this);
6498 }
6499
6500 T&& value() && {
6501 return std::move(static_cast<T&>(*this));
6502 }
6503 };
6504
6505 template <typename T, std::size_t tag>
6506 struct ebco<T&, tag> {
6507 T& ref;
6508
6509 ebco() = default;
6510 ebco(const ebco&) = default;
6511 ebco(ebco&&) = default;
6512 ebco(T& v) : ref(v){};
6513
6514 ebco& operator=(const ebco&) = default;
6515 ebco& operator=(ebco&&) = default;
6516 ebco& operator=(T& v) {
6517 ref = v;
6518 return *this;
6519 }
6520
6521 T& value() const {
6522 return const_cast<ebco<T&, tag>&>(*this).ref;
6523 }
6524 };
6525
6526 template <typename T, std::size_t tag>
6527 struct ebco<T&&, tag> {
6528 T&& ref;
6529
6530 ebco() = default;
6531 ebco(const ebco&) = default;
6532 ebco(ebco&&) = default;
6533 ebco(T&& v) : ref(v){};
6534
6535 ebco& operator=(const ebco&) = default;
6536 ebco& operator=(ebco&&) = default;
6537 ebco& operator=(T&& v) {
6538 ref = std::move(v);
6539 return *this;
6540 }
6541
6542 T& value() & {
6543 return ref;
6544 }
6545
6546 const T& value() const & {
6547 return ref;
6548 }
6549
6550 T&& value() && {
6551 return std::move(ref);
6552 }
6553 };
6554
6555}} // namespace sol::detail
6556
6557// end of sol/ebco.hpp
6558
6559#include <array>
6560#include <initializer_list>
6561#include <string>
6562#include <string_view>
6563#include <optional>
6564#if SOL_IS_ON(SOL_STD_VARIANT_I_)
6565#include <variant>
6566#endif // variant shenanigans (thanks, Mac OSX)
6567
6568namespace sol {
6569 namespace detail {
6570#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
6571 typedef int (*lua_CFunction_noexcept)(lua_State* L) noexcept;
6572#else
6573 typedef int (*lua_CFunction_noexcept)(lua_State* L);
6574#endif // noexcept function type for lua_CFunction
6575
6576 template <typename T>
6577 struct unique_usertype { };
6578
6579 template <typename T>
6580 struct implicit_wrapper {
6581 T& item;
6582 implicit_wrapper(T* item) : item(*item) {
6583 }
6584 implicit_wrapper(T& item) : item(item) {
6585 }
6586 operator T&() {
6587 return item;
6588 }
6589 operator T*() {
6590 return std::addressof(item);
6591 }
6592 };
6593
6594 struct yield_tag_t { };
6595 const yield_tag_t yield_tag = yield_tag_t {};
6596 } // namespace detail
6597
6598 struct lua_nil_t { };
6599 inline constexpr lua_nil_t lua_nil {};
6600 inline bool operator==(lua_nil_t, lua_nil_t) {
6601 return true;
6602 }
6603 inline bool operator!=(lua_nil_t, lua_nil_t) {
6604 return false;
6605 }
6606#if SOL_IS_ON(SOL_NIL_I_)
6607 using nil_t = lua_nil_t;
6608 inline constexpr const nil_t& nil = lua_nil;
6609#endif
6610
6611 namespace detail {
6612 struct non_lua_nil_t { };
6613 } // namespace detail
6614
6615 struct metatable_key_t { };
6616 const metatable_key_t metatable_key = {};
6617
6618 struct env_key_t { };
6619 const env_key_t env_key = {};
6620
6621 struct no_metatable_t { };
6622 const no_metatable_t no_metatable = {};
6623
6624 template <typename T>
6625 struct yielding_t {
6626 T func;
6627
6628 yielding_t() = default;
6629 yielding_t(const yielding_t&) = default;
6630 yielding_t(yielding_t&&) = default;
6631 yielding_t& operator=(const yielding_t&) = default;
6632 yielding_t& operator=(yielding_t&&) = default;
6633 template <typename Arg,
6634 meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>, yielding_t>>,
6635 meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler>
6636 yielding_t(Arg&& arg) : func(std::forward<Arg>(arg)) {
6637 }
6638 template <typename Arg0, typename Arg1, typename... Args>
6639 yielding_t(Arg0&& arg0, Arg1&& arg1, Args&&... args) : func(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) {
6640 }
6641 };
6642
6643 template <typename F>
6644 inline yielding_t<std::decay_t<F>> yielding(F&& f) {
6645 return yielding_t<std::decay_t<F>>(std::forward<F>(f));
6646 }
6647
6648 typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref;
6649
6650 template <typename T>
6651 struct non_null { };
6652
6653 template <typename... Args>
6654 struct function_sig { };
6655
6656 struct upvalue_index {
6657 int index;
6658 upvalue_index(int idx) : index(lua_upvalueindex(idx)) {
6659 }
6660
6661 operator int() const {
6662 return index;
6663 }
6664 };
6665
6666 struct raw_index {
6667 int index;
6668 raw_index(int i) : index(i) {
6669 }
6670
6671 operator int() const {
6672 return index;
6673 }
6674 };
6675
6676 struct absolute_index {
6677 int index;
6678 absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {
6679 }
6680
6681 operator int() const {
6682 return index;
6683 }
6684 };
6685
6686 struct ref_index {
6687 int index;
6688 ref_index(int idx) : index(idx) {
6689 }
6690
6691 operator int() const {
6692 return index;
6693 }
6694 };
6695
6696 struct stack_count {
6697 int count;
6698
6699 stack_count(int cnt) : count(cnt) {
6700 }
6701 };
6702
6703 struct lightuserdata_value {
6704 void* value;
6705 lightuserdata_value(void* data) : value(data) {
6706 }
6707 operator void*() const {
6708 return value;
6709 }
6710 };
6711
6712 struct userdata_value {
6713 void* value;
6714 userdata_value(void* data) : value(data) {
6715 }
6716 operator void*() const {
6717 return value;
6718 }
6719 };
6720
6721 template <typename L>
6722 struct light {
6723 L* value;
6724
6725 light(L& x) : value(std::addressof(x)) {
6726 }
6727 light(L* x) : value(x) {
6728 }
6729 light(void* x) : value(static_cast<L*>(x)) {
6730 }
6731 operator L*() const {
6732 return value;
6733 }
6734 operator L&() const {
6735 return *value;
6736 }
6737 };
6738
6739 template <typename T>
6740 auto make_light(T& l) {
6741 typedef meta::unwrapped_t<std::remove_pointer_t<std::remove_pointer_t<T>>> L;
6742 return light<L>(l);
6743 }
6744
6745 template <typename U>
6746 struct user {
6747 U value;
6748
6749 user(U&& x) : value(std::forward<U>(x)) {
6750 }
6751 operator std::add_pointer_t<std::remove_reference_t<U>>() {
6752 return std::addressof(value);
6753 }
6754 operator std::add_lvalue_reference_t<U>() {
6755 return value;
6756 }
6757 operator std::add_const_t<std::add_lvalue_reference_t<U>> &() const {
6758 return value;
6759 }
6760 };
6761
6762 template <typename T>
6763 auto make_user(T&& u) {
6764 typedef meta::unwrapped_t<meta::unqualified_t<T>> U;
6765 return user<U>(std::forward<T>(u));
6766 }
6767
6768 template <typename T>
6769 struct metatable_registry_key {
6770 T key;
6771
6772 metatable_registry_key(T key) : key(std::forward<T>(key)) {
6773 }
6774 };
6775
6776 template <typename T>
6777 auto meta_registry_key(T&& key) {
6778 typedef meta::unqualified_t<T> K;
6779 return metatable_registry_key<K>(std::forward<T>(key));
6780 }
6781
6782 template <typename... Upvalues>
6783 struct closure {
6784 lua_CFunction c_function;
6785 std::tuple<Upvalues...> upvalues;
6786 closure(lua_CFunction f, Upvalues... targetupvalues) : c_function(f), upvalues(std::forward<Upvalues>(targetupvalues)...) {
6787 }
6788 };
6789
6790 template <>
6791 struct closure<> {
6792 lua_CFunction c_function;
6793 int upvalues;
6794 closure(lua_CFunction f, int upvalue_count = 0) : c_function(f), upvalues(upvalue_count) {
6795 }
6796 };
6797
6798 typedef closure<> c_closure;
6799
6800 template <typename... Args>
6801 closure<Args...> make_closure(lua_CFunction f, Args&&... args) {
6802 return closure<Args...>(f, std::forward<Args>(args)...);
6803 }
6804
6805 template <typename Sig, typename... Ps>
6806 struct function_arguments {
6807 std::tuple<Ps...> arguments;
6808 template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, function_arguments>> = meta::enabler>
6809 function_arguments(Arg&& arg, Args&&... args) : arguments(std::forward<Arg>(arg), std::forward<Args>(args)...) {
6810 }
6811 };
6812
6813 template <typename Sig = function_sig<>, typename... Args>
6814 auto as_function(Args&&... args) {
6815 return function_arguments<Sig, std::decay_t<Args>...>(std::forward<Args>(args)...);
6816 }
6817
6818 template <typename Sig = function_sig<>, typename... Args>
6819 auto as_function_reference(Args&&... args) {
6820 return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
6821 }
6822
6823 template <typename T>
6824 struct as_table_t {
6825 private:
6826 T value_;
6827
6828 public:
6829 as_table_t() = default;
6830 as_table_t(const as_table_t&) = default;
6831 as_table_t(as_table_t&&) = default;
6832 as_table_t& operator=(const as_table_t&) = default;
6833 as_table_t& operator=(as_table_t&&) = default;
6834 template <typename Arg,
6835 meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>, as_table_t>>,
6836 meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler>
6837 as_table_t(Arg&& arg) : value_(std::forward<Arg>(arg)) {
6838 }
6839 template <typename Arg0, typename Arg1, typename... Args>
6840 as_table_t(Arg0&& arg0, Arg1&& arg1, Args&&... args) : value_(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) {
6841 }
6842
6843 T& value() & {
6844 return value_;
6845 }
6846
6847 T&& value() && {
6848 return std::move(value_);
6849 }
6850
6851 const T& value() const& {
6852 return value_;
6853 }
6854
6855 operator std::add_lvalue_reference_t<T>() {
6856 return value_;
6857 }
6858 };
6859
6860 template <typename T>
6861 struct nested {
6862 private:
6863 T value_;
6864
6865 public:
6866 using nested_type = T;
6867
6868 nested() = default;
6869 nested(const nested&) = default;
6870 nested(nested&&) = default;
6871 nested& operator=(const nested&) = default;
6872 nested& operator=(nested&&) = default;
6873 template <typename Arg,
6874 meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>, nested>>,
6875 meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler>
6876 nested(Arg&& arg) : value_(std::forward<Arg>(arg)) {
6877 }
6878 template <typename Arg0, typename Arg1, typename... Args>
6879 nested(Arg0&& arg0, Arg1&& arg1, Args&&... args) : value_(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) {
6880 }
6881
6882 T& value() & {
6883 return value_;
6884 }
6885
6886 T&& value() && {
6887 return std::move(value_);
6888 }
6889
6890 const T& value() const& {
6891 return value_;
6892 }
6893
6894 operator std::add_lvalue_reference_t<T>() {
6895 return value_;
6896 }
6897 };
6898
6899 struct nested_tag_t { };
6900 constexpr inline nested_tag_t nested_tag {};
6901
6902 template <typename T>
6903 as_table_t<T> as_table_ref(T&& container) {
6904 return as_table_t<T>(std::forward<T>(container));
6905 }
6906
6907 template <typename T>
6908 as_table_t<meta::unqualified_t<T>> as_table(T&& container) {
6909 return as_table_t<meta::unqualified_t<T>>(std::forward<T>(container));
6910 }
6911
6912 template <typename T>
6913 nested<T> as_nested_ref(T&& container) {
6914 return nested<T>(std::forward<T>(container));
6915 }
6916
6917 template <typename T>
6918 nested<meta::unqualified_t<T>> as_nested(T&& container) {
6919 return nested<meta::unqualified_t<T>>(std::forward<T>(container));
6920 }
6921
6922 template <typename T>
6923 struct as_container_t {
6924 private:
6925 T value_;
6926
6927 public:
6928 using type = T;
6929
6930 as_container_t() = default;
6931 as_container_t(const as_container_t&) = default;
6932 as_container_t(as_container_t&&) = default;
6933 as_container_t& operator=(const as_container_t&) = default;
6934 as_container_t& operator=(as_container_t&&) = default;
6935 template <typename Arg,
6936 meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>, as_container_t>>,
6937 meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler>
6938 as_container_t(Arg&& arg) : value_(std::forward<Arg>(arg)) {
6939 }
6940 template <typename Arg0, typename Arg1, typename... Args>
6941 as_container_t(Arg0&& arg0, Arg1&& arg1, Args&&... args) : value_(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) {
6942 }
6943
6944 T& value() & {
6945 return value_;
6946 }
6947
6948 T&& value() && {
6949 return std::move(value_);
6950 }
6951
6952 const T& value() const& {
6953 return value_;
6954 }
6955 };
6956
6957 template <typename T>
6958 struct as_container_t<T&> {
6959 private:
6960 std::reference_wrapper<T> value_;
6961
6962 public:
6963 as_container_t(T& value) : value_(value) {
6964 }
6965
6966 T& value() {
6967 return value_;
6968 }
6969
6970 operator T&() {
6971 return value();
6972 }
6973 };
6974
6975 template <typename T>
6976 auto as_container(T&& value) {
6977 return as_container_t<T>(std::forward<T>(value));
6978 }
6979
6980 template <typename T>
6981 struct push_invoke_t {
6982 private:
6983 T value_;
6984
6985 public:
6986 push_invoke_t() = default;
6987 push_invoke_t(const push_invoke_t&) = default;
6988 push_invoke_t(push_invoke_t&&) = default;
6989 push_invoke_t& operator=(const push_invoke_t&) = default;
6990 push_invoke_t& operator=(push_invoke_t&&) = default;
6991 template <typename Arg,
6992 meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>, push_invoke_t>>,
6993 meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler>
6994 push_invoke_t(Arg&& arg) : value_(std::forward<Arg>(arg)) {
6995 }
6996 template <typename Arg0, typename Arg1, typename... Args>
6997 push_invoke_t(Arg0&& arg0, Arg1&& arg1, Args&&... args) : value_(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) {
6998 }
6999
7000 T& value() & {
7001 return value_;
7002 }
7003
7004 T&& value() && {
7005 return std::move(value_);
7006 }
7007
7008 const T& value() const& {
7009 return value_;
7010 }
7011 };
7012
7013 template <typename T>
7014 struct push_invoke_t<T&> {
7015 std::reference_wrapper<T> value_;
7016
7017 push_invoke_t(T& value) : value_(value) {
7018 }
7019
7020 T& value() {
7021 return value_;
7022 }
7023 };
7024
7025 template <typename Fx>
7026 auto push_invoke(Fx&& fx) {
7027 return push_invoke_t<Fx>(std::forward<Fx>(fx));
7028 }
7029
7030 struct override_value_t { };
7031 constexpr inline override_value_t override_value = override_value_t();
7032 struct update_if_empty_t { };
7033 constexpr inline update_if_empty_t update_if_empty = update_if_empty_t();
7034 struct create_if_nil_t { };
7035 constexpr inline create_if_nil_t create_if_nil = create_if_nil_t();
7036
7037 namespace detail {
7038 enum insert_mode { none = 0x0, update_if_empty = 0x01, override_value = 0x02, create_if_nil = 0x04 };
7039
7040 template <typename T, typename...>
7041 using is_insert_mode = std::integral_constant<bool,
7042 std::is_same_v<T, override_value_t> || std::is_same_v<T, update_if_empty_t> || std::is_same_v<T, create_if_nil_t>>;
7043
7044 template <typename T, typename...>
7045 using is_not_insert_mode = meta::neg<is_insert_mode<T>>;
7046 } // namespace detail
7047
7048 struct this_state {
7049 lua_State* L;
7050
7051 this_state(lua_State* Ls) : L(Ls) {
7052 }
7053
7054 operator lua_State*() const noexcept {
7055 return lua_state();
7056 }
7057
7058 lua_State* operator->() const noexcept {
7059 return lua_state();
7060 }
7061
7062 lua_State* lua_state() const noexcept {
7063 return L;
7064 }
7065 };
7066
7067 struct this_main_state {
7068 lua_State* L;
7069
7070 this_main_state(lua_State* Ls) : L(Ls) {
7071 }
7072
7073 operator lua_State*() const noexcept {
7074 return lua_state();
7075 }
7076
7077 lua_State* operator->() const noexcept {
7078 return lua_state();
7079 }
7080
7081 lua_State* lua_state() const noexcept {
7082 return L;
7083 }
7084 };
7085
7086 struct new_table {
7087 int sequence_hint = 0;
7088 int map_hint = 0;
7089
7090 new_table() = default;
7091 new_table(const new_table&) = default;
7092 new_table(new_table&&) = default;
7093 new_table& operator=(const new_table&) = default;
7094 new_table& operator=(new_table&&) = default;
7095
7096 new_table(int sequence_hint, int map_hint = 0) : sequence_hint(sequence_hint), map_hint(map_hint) {
7097 }
7098 };
7099
7100 const new_table create = {};
7101
7102 enum class lib : char {
7103 // print, assert, and other base functions
7104 base,
7105 // require and other package functions
7106 package,
7107 // coroutine functions and utilities
7108 coroutine,
7109 // string library
7110 string,
7111 // functionality from the OS
7112 os,
7113 // all things math
7114 math,
7115 // the table manipulator and observer functions
7116 table,
7117 // the debug library
7118 debug,
7119 // the bit library: different based on which you're using
7120 bit32,
7121 // input/output library
7122 io,
7123 // LuaJIT only
7124 ffi,
7125 // LuaJIT only
7126 jit,
7127 // library for handling utf8: new to Lua
7128 utf8,
7129 // do not use
7130 count
7131 };
7132
7133 enum class call_syntax { dot = 0, colon = 1 };
7134
7135 enum class load_mode {
7136 any = 0,
7137 text = 1,
7138 binary = 2,
7139 };
7140
7141 enum class call_status : int {
7142 ok = LUA_OK,
7143 yielded = LUA_YIELD,
7144 runtime = LUA_ERRRUN,
7145 memory = LUA_ERRMEM,
7146 handler = LUA_ERRERR,
7147 gc = LUA_ERRGCMM,
7148 syntax = LUA_ERRSYNTAX,
7149 file = LUA_ERRFILE,
7150 };
7151
7152 enum class thread_status : int {
7153 ok = LUA_OK,
7154 yielded = LUA_YIELD,
7155 runtime = LUA_ERRRUN,
7156 memory = LUA_ERRMEM,
7157 gc = LUA_ERRGCMM,
7158 handler = LUA_ERRERR,
7159 dead = -1,
7160 };
7161
7162 enum class load_status : int {
7163 ok = LUA_OK,
7164 syntax = LUA_ERRSYNTAX,
7165 memory = LUA_ERRMEM,
7166 gc = LUA_ERRGCMM,
7167 file = LUA_ERRFILE,
7168 };
7169
7170 enum class gc_mode : int {
7171 incremental = 0,
7172 generational = 1,
7173 default_value = incremental,
7174 };
7175
7176 enum class type : int {
7177 none = LUA_TNONE,
7178 lua_nil = LUA_TNIL,
7179#if SOL_IS_ON(SOL_NIL_I_)
7180 nil = lua_nil,
7181#endif // Objective C/C++ Keyword that's found in OSX SDK and OBJC -- check for all forms to protect
7182 string = LUA_TSTRING,
7183 number = LUA_TNUMBER,
7184 thread = LUA_TTHREAD,
7185 boolean = LUA_TBOOLEAN,
7186 function = LUA_TFUNCTION,
7187 userdata = LUA_TUSERDATA,
7188 lightuserdata = LUA_TLIGHTUSERDATA,
7189 table = LUA_TTABLE,
7190 poly = -0xFFFF
7191 };
7192
7193 inline const std::string& to_string(call_status c) {
7194 static const std::array<std::string, 10> names { { "ok",
7195 "yielded",
7196 "runtime",
7197 "memory",
7198 "handler",
7199 "gc",
7200 "syntax",
7201 "file",
7202 "CRITICAL_EXCEPTION_FAILURE",
7203 "CRITICAL_INDETERMINATE_STATE_FAILURE" } };
7204 switch (c) {
7205 case call_status::ok:
7206 return names[0];
7207 case call_status::yielded:
7208 return names[1];
7209 case call_status::runtime:
7210 return names[2];
7211 case call_status::memory:
7212 return names[3];
7213 case call_status::handler:
7214 return names[4];
7215 case call_status::gc:
7216 return names[5];
7217 case call_status::syntax:
7218 return names[6];
7219 case call_status::file:
7220 return names[7];
7221 }
7222 if (static_cast<std::ptrdiff_t>(c) == -1) {
7223 // One of the many cases where a critical exception error has occurred
7224 return names[8];
7225 }
7226 return names[9];
7227 }
7228
7229 inline bool is_indeterminate_call_failure(call_status c) {
7230 switch (c) {
7231 case call_status::ok:
7232 case call_status::yielded:
7233 case call_status::runtime:
7234 case call_status::memory:
7235 case call_status::handler:
7236 case call_status::gc:
7237 case call_status::syntax:
7238 case call_status::file:
7239 return false;
7240 }
7241 return true;
7242 }
7243
7244 inline const std::string& to_string(load_status c) {
7245 static const std::array<std::string, 7> names {
7246 { "ok", "memory", "gc", "syntax", "file", "CRITICAL_EXCEPTION_FAILURE", "CRITICAL_INDETERMINATE_STATE_FAILURE" }
7247 };
7248 switch (c) {
7249 case load_status::ok:
7250 return names[0];
7251 case load_status::memory:
7252 return names[1];
7253 case load_status::gc:
7254 return names[2];
7255 case load_status::syntax:
7256 return names[3];
7257 case load_status::file:
7258 return names[4];
7259 }
7260 if (static_cast<int>(c) == -1) {
7261 // One of the many cases where a critical exception error has occurred
7262 return names[5];
7263 }
7264 return names[6];
7265 }
7266
7267 inline const std::string& to_string(load_mode c) {
7268 static const std::array<std::string, 3> names { {
7269 "bt",
7270 "t",
7271 "b",
7272 } };
7273 return names[static_cast<std::size_t>(c)];
7274 }
7275
7276 enum class meta_function {
7277 construct,
7278 index,
7279 new_index,
7280 mode,
7281 call,
7282 call_function = call,
7283 metatable,
7284 to_string,
7285 length,
7286 unary_minus,
7287 addition,
7288 subtraction,
7289 multiplication,
7290 division,
7291 modulus,
7292 power_of,
7293 involution = power_of,
7294 concatenation,
7295 equal_to,
7296 less_than,
7297 less_than_or_equal_to,
7298 garbage_collect,
7299 floor_division,
7300 bitwise_left_shift,
7301 bitwise_right_shift,
7302 bitwise_not,
7303 bitwise_and,
7304 bitwise_or,
7305 bitwise_xor,
7306 pairs,
7307 ipairs,
7308 next,
7309 type,
7310 type_info,
7311 call_construct,
7312 storage,
7313 gc_names,
7314 static_index,
7315 static_new_index,
7316 };
7317
7318 typedef meta_function meta_method;
7319
7320 inline const std::array<std::string, 37>& meta_function_names() {
7321 static const std::array<std::string, 37> names = { { "new",
7322 "__index",
7323 "__newindex",
7324 "__mode",
7325 "__call",
7326 "__metatable",
7327 "__tostring",
7328 "__len",
7329 "__unm",
7330 "__add",
7331 "__sub",
7332 "__mul",
7333 "__div",
7334 "__mod",
7335 "__pow",
7336 "__concat",
7337 "__eq",
7338 "__lt",
7339 "__le",
7340 "__gc",
7341
7342 "__idiv",
7343 "__shl",
7344 "__shr",
7345 "__bnot",
7346 "__band",
7347 "__bor",
7348 "__bxor",
7349
7350 "__pairs",
7351 "__ipairs",
7352 "next",
7353
7354 "__type",
7355 "__typeinfo",
7356 "__sol.call_new",
7357 "__sol.storage",
7358 "__sol.gc_names",
7359 "__sol.static_index",
7360 "__sol.static_new_index" } };
7361 return names;
7362 }
7363
7364 inline const std::string& to_string(meta_function mf) {
7365 return meta_function_names()[static_cast<int>(mf)];
7366 }
7367
7368 inline type type_of(lua_State* L, int index) {
7369 return static_cast<type>(lua_type(L, index));
7370 }
7371
7372 inline std::string type_name(lua_State* L, type t) {
7373 return lua_typename(L, static_cast<int>(t));
7374 }
7375
7376 template <typename T>
7377 struct is_lua_reference
7378 : std::integral_constant<bool, std::is_base_of_v<reference, T> || std::is_base_of_v<main_reference, T> || std::is_base_of_v<stack_reference, T>> { };
7379
7380 template <typename T>
7381 inline constexpr bool is_lua_reference_v = is_lua_reference<T>::value;
7382
7383 template <typename T>
7384 struct is_lua_reference_or_proxy : std::integral_constant<bool, is_lua_reference_v<T> || meta::is_specialization_of_v<T, table_proxy>> { };
7385
7386 template <typename T>
7387 inline constexpr bool is_lua_reference_or_proxy_v = is_lua_reference_or_proxy<T>::value;
7388
7389 template <typename T>
7390 struct is_transparent_argument : std::false_type { };
7391
7392 template <typename T>
7393 constexpr inline bool is_transparent_argument_v = is_transparent_argument<T>::value;
7394
7395 template <>
7396 struct is_transparent_argument<this_state> : std::true_type { };
7397 template <>
7398 struct is_transparent_argument<this_main_state> : std::true_type { };
7399 template <>
7400 struct is_transparent_argument<this_environment> : std::true_type { };
7401 template <>
7402 struct is_transparent_argument<variadic_args> : std::true_type { };
7403 template <typename T>
7404 struct is_variadic_arguments : std::is_same<T, variadic_args> { };
7405
7406 template <typename T>
7407 struct is_container
7408 : std::integral_constant<bool,
7409 !std::is_same_v<state_view,
7410 T> && !std::is_same_v<state, T> && !meta::is_initializer_list_v<T> && !meta::is_string_like_v<T> && !meta::is_string_literal_array_v<T> && !is_transparent_argument_v<T> && !is_lua_reference_v<T> && (meta::has_begin_end_v<T> || std::is_array_v<T>)> {
7411 };
7412
7413 template <typename T>
7414 constexpr inline bool is_container_v = is_container<T>::value;
7415
7416 template <typename T>
7417 struct is_to_stringable : meta::any<meta::supports_to_string_member<meta::unqualified_t<T>>, meta::supports_adl_to_string<meta::unqualified_t<T>>,
7418 meta::supports_op_left_shift<std::ostream, meta::unqualified_t<T>>> { };
7419
7420 namespace detail {
7421 template <typename T, typename = void>
7422 struct lua_type_of : std::integral_constant<type, type::userdata> { };
7423
7424 template <typename C, typename T, typename A>
7425 struct lua_type_of<std::basic_string<C, T, A>> : std::integral_constant<type, type::string> { };
7426
7427 template <typename C, typename T>
7428 struct lua_type_of<basic_string_view<C, T>> : std::integral_constant<type, type::string> { };
7429
7430 template <std::size_t N>
7431 struct lua_type_of<char[N]> : std::integral_constant<type, type::string> { };
7432
7433 template <std::size_t N>
7434 struct lua_type_of<wchar_t[N]> : std::integral_constant<type, type::string> { };
7435
7436 template <std::size_t N>
7437 struct lua_type_of<char16_t[N]> : std::integral_constant<type, type::string> { };
7438
7439 template <std::size_t N>
7440 struct lua_type_of<char32_t[N]> : std::integral_constant<type, type::string> { };
7441
7442 template <>
7443 struct lua_type_of<char> : std::integral_constant<type, type::string> { };
7444
7445 template <>
7446 struct lua_type_of<wchar_t> : std::integral_constant<type, type::string> { };
7447
7448 template <>
7449 struct lua_type_of<char16_t> : std::integral_constant<type, type::string> { };
7450
7451 template <>
7452 struct lua_type_of<char32_t> : std::integral_constant<type, type::string> { };
7453
7454 template <>
7455 struct lua_type_of<const char*> : std::integral_constant<type, type::string> { };
7456
7457 template <>
7458 struct lua_type_of<const char16_t*> : std::integral_constant<type, type::string> { };
7459
7460 template <>
7461 struct lua_type_of<const char32_t*> : std::integral_constant<type, type::string> { };
7462
7463 template <>
7464 struct lua_type_of<bool> : std::integral_constant<type, type::boolean> { };
7465
7466 template <>
7467 struct lua_type_of<lua_nil_t> : std::integral_constant<type, type::lua_nil> { };
7468
7469 template <>
7470 struct lua_type_of<nullopt_t> : std::integral_constant<type, type::lua_nil> { };
7471
7472 template <>
7473 struct lua_type_of<lua_value> : std::integral_constant<type, type::poly> { };
7474
7475 template <>
7476 struct lua_type_of<detail::non_lua_nil_t> : std::integral_constant<type, type::poly> { };
7477
7478 template <>
7479 struct lua_type_of<std::nullptr_t> : std::integral_constant<type, type::lua_nil> { };
7480
7481 template <>
7482 struct lua_type_of<error> : std::integral_constant<type, type::string> { };
7483
7484 template <bool b, typename Base>
7485 struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> { };
7486
7487 template <typename Base>
7488 struct lua_type_of<basic_lua_table<Base>> : std::integral_constant<type, type::table> { };
7489
7490 template <typename Base>
7491 struct lua_type_of<basic_metatable<Base>> : std::integral_constant<type, type::table> { };
7492
7493 template <typename T, typename Base>
7494 struct lua_type_of<basic_usertype<T, Base>> : std::integral_constant<type, type::table> { };
7495
7496 template <>
7497 struct lua_type_of<metatable_key_t> : std::integral_constant<type, type::table> { };
7498
7499 template <typename B>
7500 struct lua_type_of<basic_environment<B>> : std::integral_constant<type, type::poly> { };
7501
7502 template <>
7503 struct lua_type_of<env_key_t> : std::integral_constant<type, type::poly> { };
7504
7505 template <>
7506 struct lua_type_of<new_table> : std::integral_constant<type, type::table> { };
7507
7508 template <typename T>
7509 struct lua_type_of<as_table_t<T>> : std::integral_constant<type, type::table> { };
7510
7511 template <typename T>
7512 struct lua_type_of<std::initializer_list<T>> : std::integral_constant<type, type::table> { };
7513
7514 template <bool b>
7515 struct lua_type_of<basic_reference<b>> : std::integral_constant<type, type::poly> { };
7516
7517 template <>
7518 struct lua_type_of<stack_reference> : std::integral_constant<type, type::poly> { };
7519
7520 template <typename Base>
7521 struct lua_type_of<basic_object<Base>> : std::integral_constant<type, type::poly> { };
7522
7523 template <typename... Args>
7524 struct lua_type_of<std::tuple<Args...>> : std::integral_constant<type, type::poly> { };
7525
7526 template <typename A, typename B>
7527 struct lua_type_of<std::pair<A, B>> : std::integral_constant<type, type::poly> { };
7528
7529 template <>
7530 struct lua_type_of<void*> : std::integral_constant<type, type::lightuserdata> { };
7531
7532 template <>
7533 struct lua_type_of<const void*> : std::integral_constant<type, type::lightuserdata> { };
7534
7535 template <>
7536 struct lua_type_of<lightuserdata_value> : std::integral_constant<type, type::lightuserdata> { };
7537
7538 template <>
7539 struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> { };
7540
7541 template <typename T>
7542 struct lua_type_of<light<T>> : std::integral_constant<type, type::lightuserdata> { };
7543
7544 template <typename T>
7545 struct lua_type_of<user<T>> : std::integral_constant<type, type::userdata> { };
7546
7547 template <typename Base>
7548 struct lua_type_of<basic_lightuserdata<Base>> : std::integral_constant<type, type::lightuserdata> { };
7549
7550 template <typename Base>
7551 struct lua_type_of<basic_userdata<Base>> : std::integral_constant<type, type::userdata> { };
7552
7553 template <>
7554 struct lua_type_of<lua_CFunction> : std::integral_constant<type, type::function> { };
7555
7556 template <>
7557 struct lua_type_of<std::remove_pointer_t<lua_CFunction>> : std::integral_constant<type, type::function> { };
7558
7559 template <typename Base, bool aligned>
7560 struct lua_type_of<basic_function<Base, aligned>> : std::integral_constant<type, type::function> { };
7561
7562 template <typename Base, bool aligned, typename Handler>
7563 struct lua_type_of<basic_protected_function<Base, aligned, Handler>> : std::integral_constant<type, type::function> { };
7564
7565 template <typename Base>
7566 struct lua_type_of<basic_coroutine<Base>> : std::integral_constant<type, type::function> { };
7567
7568 template <typename Base>
7569 struct lua_type_of<basic_thread<Base>> : std::integral_constant<type, type::thread> { };
7570
7571 template <typename Signature>
7572 struct lua_type_of<std::function<Signature>> : std::integral_constant<type, type::function> { };
7573
7574 template <typename T>
7575 struct lua_type_of<optional<T>> : std::integral_constant<type, type::poly> { };
7576
7577 template <typename T>
7578 struct lua_type_of<std::optional<T>> : std::integral_constant<type, type::poly> { };
7579
7580 template <>
7581 struct lua_type_of<variadic_args> : std::integral_constant<type, type::poly> { };
7582
7583 template <>
7584 struct lua_type_of<variadic_results> : std::integral_constant<type, type::poly> { };
7585
7586 template <>
7587 struct lua_type_of<stack_count> : std::integral_constant<type, type::poly> { };
7588
7589 template <>
7590 struct lua_type_of<this_state> : std::integral_constant<type, type::poly> { };
7591
7592 template <>
7593 struct lua_type_of<this_main_state> : std::integral_constant<type, type::poly> { };
7594
7595 template <>
7596 struct lua_type_of<this_environment> : std::integral_constant<type, type::poly> { };
7597
7598 template <>
7599 struct lua_type_of<type> : std::integral_constant<type, type::poly> { };
7600
7601#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
7602 template <typename T>
7603 struct lua_type_of<T*> : std::integral_constant<type, std::is_function_v<T> ? type::function : type::userdata> { };
7604#else
7605 template <typename T>
7606 struct lua_type_of<T*> : std::integral_constant<type, type::userdata> { };
7607#endif
7608
7609 template <typename T>
7610 struct lua_type_of<T, std::enable_if_t<std::is_arithmetic_v<T> || std::is_same_v<T, lua_Number> || std::is_same_v<T, lua_Integer>>>
7611 : std::integral_constant<type, type::number> { };
7612
7613 template <typename T>
7614 struct lua_type_of<T, std::enable_if_t<std::is_function_v<T>>> : std::integral_constant<type, type::function> { };
7615
7616 template <typename T>
7617 struct lua_type_of<T, std::enable_if_t<std::is_enum_v<T>>> : std::integral_constant<type, type::number> { };
7618
7619 template <>
7620 struct lua_type_of<meta_function> : std::integral_constant<type, type::string> { };
7621
7622#if SOL_IS_ON(SOL_STD_VARIANT_I_)
7623 template <typename... Tn>
7624 struct lua_type_of<std::variant<Tn...>> : std::integral_constant<type, type::poly> { };
7625#endif // std::variant deployment sucks on Clang
7626
7627 template <typename T>
7628 struct lua_type_of<nested<T>> : meta::conditional_t<::sol::is_container_v<T>, std::integral_constant<type, type::table>, lua_type_of<T>> { };
7629
7630 template <typename C, C v, template <typename...> class V, typename... Args>
7631 struct accumulate : std::integral_constant<C, v> { };
7632
7633 template <typename C, C v, template <typename...> class V, typename T, typename... Args>
7634 struct accumulate<C, v, V, T, Args...> : accumulate<C, v + V<T>::value, V, Args...> { };
7635
7636 template <typename C, C v, template <typename...> class V, typename List>
7637 struct accumulate_list;
7638
7639 template <typename C, C v, template <typename...> class V, typename... Args>
7640 struct accumulate_list<C, v, V, types<Args...>> : accumulate<C, v, V, Args...> { };
7641 } // namespace detail
7642
7643 template <typename T>
7644 struct lua_type_of : detail::lua_type_of<T> {
7645 typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
7646 };
7647
7648 template <typename T>
7649 inline constexpr type lua_type_of_v = lua_type_of<T>::value;
7650
7651 template <typename T>
7652 struct lua_size : std::integral_constant<int, 1> {
7653 typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
7654 };
7655
7656 template <typename A, typename B>
7657 struct lua_size<std::pair<A, B>> : std::integral_constant<int, lua_size<A>::value + lua_size<B>::value> { };
7658
7659 template <typename... Args>
7660 struct lua_size<std::tuple<Args...>> : std::integral_constant<int, detail::accumulate<int, 0, lua_size, Args...>::value> { };
7661
7662 template <typename T>
7663 inline constexpr int lua_size_v = lua_size<T>::value;
7664
7665 namespace detail {
7666 template <typename...>
7667 struct void_ {
7668 typedef void type;
7669 };
7670 template <typename T, typename = void>
7671 struct has_internal_marker_impl : std::false_type { };
7672 template <typename T>
7673 struct has_internal_marker_impl<T, typename void_<typename T::SOL_INTERNAL_UNSPECIALIZED_MARKER_>::type> : std::true_type { };
7674
7675 template <typename T>
7676 using has_internal_marker = has_internal_marker_impl<T>;
7677
7678 template <typename T>
7679 constexpr inline bool has_internal_marker_v = has_internal_marker<T>::value;
7680 } // namespace detail
7681
7682 template <typename T>
7683 struct is_lua_primitive
7684 : std::integral_constant<bool,
7685 type::userdata
7686 != lua_type_of_v<
7687 T> || ((type::userdata == lua_type_of_v<T>)&&detail::has_internal_marker_v<lua_type_of<T>> && !detail::has_internal_marker_v<lua_size<T>>)
7688 || is_lua_reference_or_proxy_v<T> || meta::is_specialization_of_v<T, std::tuple> || meta::is_specialization_of_v<T, std::pair>> { };
7689
7690 template <typename T>
7691 constexpr inline bool is_lua_primitive_v = is_lua_primitive<T>::value;
7692
7693 template <typename T>
7694 struct is_main_threaded : std::is_base_of<main_reference, T> { };
7695
7696 template <typename T>
7697 struct is_stack_based : std::is_base_of<stack_reference, T> { };
7698 template <>
7699 struct is_stack_based<variadic_args> : std::true_type { };
7700 template <>
7701 struct is_stack_based<unsafe_function_result> : std::true_type { };
7702 template <>
7703 struct is_stack_based<protected_function_result> : std::true_type { };
7704 template <>
7705 struct is_stack_based<stack_proxy> : std::true_type { };
7706 template <>
7707 struct is_stack_based<stack_proxy_base> : std::true_type { };
7708 template <>
7709 struct is_stack_based<stack_count> : std::true_type { };
7710
7711 template <typename T>
7712 constexpr inline bool is_stack_based_v = is_stack_based<T>::value;
7713
7714 template <typename T>
7715 struct is_lua_primitive<T*> : std::true_type { };
7716 template <>
7717 struct is_lua_primitive<unsafe_function_result> : std::true_type { };
7718 template <>
7719 struct is_lua_primitive<protected_function_result> : std::true_type { };
7720 template <typename T>
7721 struct is_lua_primitive<std::reference_wrapper<T>> : std::true_type { };
7722 template <typename T>
7723 struct is_lua_primitive<user<T>> : std::true_type { };
7724 template <typename T>
7725 struct is_lua_primitive<light<T>> : is_lua_primitive<T*> { };
7726 template <typename T>
7727 struct is_lua_primitive<optional<T>> : std::true_type { };
7728 template <typename T>
7729 struct is_lua_primitive<std::optional<T>> : std::true_type { };
7730 template <typename T>
7731 struct is_lua_primitive<as_table_t<T>> : std::true_type { };
7732 template <typename T>
7733 struct is_lua_primitive<nested<T>> : std::true_type { };
7734 template <>
7735 struct is_lua_primitive<userdata_value> : std::true_type { };
7736 template <>
7737 struct is_lua_primitive<lightuserdata_value> : std::true_type { };
7738 template <>
7739 struct is_lua_primitive<stack_proxy> : std::true_type { };
7740 template <>
7741 struct is_lua_primitive<stack_proxy_base> : std::true_type { };
7742 template <typename T>
7743 struct is_lua_primitive<non_null<T>> : is_lua_primitive<T*> { };
7744
7745 template <typename T>
7746 struct is_lua_index : std::is_integral<T> { };
7747 template <>
7748 struct is_lua_index<raw_index> : std::true_type { };
7749 template <>
7750 struct is_lua_index<absolute_index> : std::true_type { };
7751 template <>
7752 struct is_lua_index<ref_index> : std::true_type { };
7753 template <>
7754 struct is_lua_index<upvalue_index> : std::true_type { };
7755
7756 template <typename Signature>
7757 struct lua_bind_traits : meta::bind_traits<Signature> {
7758 private:
7759 typedef meta::bind_traits<Signature> base_t;
7760
7761 public:
7762 typedef std::integral_constant<bool, meta::count_for<is_variadic_arguments, typename base_t::args_list>::value != 0> runtime_variadics_t;
7763 static const std::size_t true_arity = base_t::arity;
7764 static const std::size_t arity = detail::accumulate_list<std::size_t, 0, lua_size, typename base_t::args_list>::value
7765 - meta::count_for<is_transparent_argument, typename base_t::args_list>::value;
7766 static const std::size_t true_free_arity = base_t::free_arity;
7767 static const std::size_t free_arity = detail::accumulate_list<std::size_t, 0, lua_size, typename base_t::free_args_list>::value
7768 - meta::count_for<is_transparent_argument, typename base_t::args_list>::value;
7769 };
7770
7771 template <typename T>
7772 struct is_table : std::false_type { };
7773 template <bool x, typename T>
7774 struct is_table<basic_table_core<x, T>> : std::true_type { };
7775 template <typename T>
7776 struct is_table<basic_lua_table<T>> : std::true_type { };
7777
7778 template <typename T>
7779 inline constexpr bool is_table_v = is_table<T>::value;
7780
7781 template <typename T>
7782 struct is_stack_table : std::false_type { };
7783 template <bool x, typename T>
7784 struct is_stack_table<basic_table_core<x, T>> : std::integral_constant<bool, std::is_base_of_v<stack_reference, T>> { };
7785 template <typename T>
7786 struct is_stack_table<basic_lua_table<T>> : std::integral_constant<bool, std::is_base_of_v<stack_reference, T>> { };
7787
7788 template <typename T>
7789 inline constexpr bool is_stack_table_v = is_stack_table<T>::value;
7790
7791 template <typename T>
7792 struct is_function : std::false_type { };
7793 template <typename T, bool aligned>
7794 struct is_function<basic_function<T, aligned>> : std::true_type { };
7795 template <typename T, bool aligned, typename Handler>
7796 struct is_function<basic_protected_function<T, aligned, Handler>> : std::true_type { };
7797
7798 template <typename T>
7799 using is_lightuserdata = meta::is_specialization_of<T, basic_lightuserdata>;
7800
7801 template <typename T>
7802 inline constexpr bool is_lightuserdata_v = is_lightuserdata<T>::value;
7803
7804 template <typename T>
7805 using is_userdata = meta::is_specialization_of<T, basic_userdata>;
7806
7807 template <typename T>
7808 inline constexpr bool is_userdata_v = is_userdata<T>::value;
7809
7810 template <typename T>
7811 using is_environment = std::integral_constant<bool, is_userdata_v<T> || is_table_v<T> || meta::is_specialization_of_v<T, basic_environment>>;
7812
7813 template <typename T>
7814 inline constexpr bool is_environment_v = is_environment<T>::value;
7815
7816 template <typename T>
7817 using is_table_like = std::integral_constant<bool, is_table_v<T> || is_environment_v<T> || is_userdata_v<T>>;
7818
7819 template <typename T>
7820 inline constexpr bool is_table_like_v = is_table_like<T>::value;
7821
7822 template <typename T>
7823 struct is_automagical
7824 : std::integral_constant<bool,
7825 (SOL_IS_ON(SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_))
7826 || (std::is_array_v<
7827 meta::unqualified_t<T>> || (!std::is_same_v<meta::unqualified_t<T>, state> && !std::is_same_v<meta::unqualified_t<T>, state_view>))> {
7828 };
7829
7830 template <typename T>
7831 inline type type_of() {
7832 return lua_type_of<meta::unqualified_t<T>>::value;
7833 }
7834
7835 namespace detail {
7836 template <typename T>
7837 struct is_non_factory_constructor : std::false_type { };
7838
7839 template <typename... Args>
7840 struct is_non_factory_constructor<constructors<Args...>> : std::true_type { };
7841
7842 template <typename... Args>
7843 struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type { };
7844
7845 template <>
7846 struct is_non_factory_constructor<no_construction> : std::true_type { };
7847
7848 template <typename T>
7849 inline constexpr bool is_non_factory_constructor_v = is_non_factory_constructor<T>::value;
7850
7851 template <typename T>
7852 struct is_constructor : is_non_factory_constructor<T> { };
7853
7854 template <typename... Args>
7855 struct is_constructor<factory_wrapper<Args...>> : std::true_type { };
7856
7857 template <typename T>
7858 struct is_constructor<protect_t<T>> : is_constructor<meta::unqualified_t<T>> { };
7859
7860 template <typename F, typename... Policies>
7861 struct is_constructor<policy_wrapper<F, Policies...>> : is_constructor<meta::unqualified_t<F>> { };
7862
7863 template <typename T>
7864 inline constexpr bool is_constructor_v = is_constructor<T>::value;
7865
7866 template <typename... Args>
7867 using any_is_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>;
7868
7869 template <typename... Args>
7870 inline constexpr bool any_is_constructor_v = any_is_constructor<Args...>::value;
7871
7872 template <typename T>
7873 struct is_destructor : std::false_type { };
7874
7875 template <typename Fx>
7876 struct is_destructor<destructor_wrapper<Fx>> : std::true_type { };
7877
7878 template <typename... Args>
7879 using any_is_destructor = meta::any<is_destructor<meta::unqualified_t<Args>>...>;
7880
7881 template <typename... Args>
7882 inline constexpr bool any_is_destructor_v = any_is_destructor<Args...>::value;
7883 } // namespace detail
7884
7885 template <typename T>
7886 using is_lua_c_function = meta::any<std::is_same<lua_CFunction, T>, std::is_same<detail::lua_CFunction_noexcept, T>, std::is_same<lua_CFunction_ref, T>>;
7887
7888 template <typename T>
7889 inline constexpr bool is_lua_c_function_v = is_lua_c_function<T>::value;
7890
7891 struct automagic_enrollments {
7892 bool default_constructor = true;
7893 bool destructor = true;
7894 bool pairs_operator = true;
7895 bool to_string_operator = true;
7896 bool call_operator = true;
7897 bool less_than_operator = true;
7898 bool less_than_or_equal_to_operator = true;
7899 bool length_operator = true;
7900 bool equal_to_operator = true;
7901 };
7902
7903} // namespace sol
7904
7905// end of sol/types.hpp
7906
7907#include <exception>
7908#include <cstring>
7909
7910#if SOL_IS_ON(SOL_PRINT_ERRORS_I_)
7911#include <iostream>
7912#endif
7913
7914namespace sol {
7915 // must push a single object to be the error object
7916 // NOTE: the VAST MAJORITY of all Lua libraries -- C or otherwise -- expect a string for the type of error
7917 // break this convention at your own risk
7918 using exception_handler_function = int (*)(lua_State*, optional<const std::exception&>, string_view);
7919
7920 namespace detail {
7921 inline const char (&default_exception_handler_name())[11] {
7922 static const char name[11] = "sol.\xE2\x98\xA2\xE2\x98\xA2";
7923 return name;
7924 }
7925
7926 // must push at least 1 object on the stack
7927 inline int default_exception_handler(lua_State* L, optional<const std::exception&>, string_view what) {
7928#if SOL_IS_ON(SOL_PRINT_ERRORS_I_)
7929 std::cerr << "[sol3] An exception occurred: ";
7930 std::cerr.write(what.data(), what.size());
7931 std::cerr << std::endl;
7932#endif
7933 lua_pushlstring(L, what.data(), what.size());
7934 return 1;
7935 }
7936
7937 inline int call_exception_handler(lua_State* L, optional<const std::exception&> maybe_ex, string_view what) {
7938 lua_getglobal(L, default_exception_handler_name());
7939 type t = static_cast<type>(lua_type(L, -1));
7940 if (t != type::lightuserdata) {
7941 lua_pop(L, 1);
7942 return default_exception_handler(L, std::move(maybe_ex), std::move(what));
7943 }
7944 void* vfunc = lua_touserdata(L, -1);
7945 lua_pop(L, 1);
7946 if (vfunc == nullptr) {
7947 return default_exception_handler(L, std::move(maybe_ex), std::move(what));
7948 }
7949 exception_handler_function exfunc = reinterpret_cast<exception_handler_function>(vfunc);
7950 return exfunc(L, std::move(maybe_ex), std::move(what));
7951 }
7952
7953#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
7954 template <lua_CFunction f>
7955 int static_trampoline(lua_State* L) noexcept {
7956 return f(L);
7957 }
7958
7959#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
7960 template <lua_CFunction_noexcept f>
7961 int static_trampoline_noexcept(lua_State* L) noexcept {
7962 return f(L);
7963 }
7964#else
7965 template <lua_CFunction f>
7966 int static_trampoline_noexcept(lua_State* L) noexcept {
7967 return f(L);
7968 }
7969#endif
7970
7971 template <typename Fx, typename... Args>
7972 int trampoline(lua_State* L, Fx&& f, Args&&... args) noexcept {
7973 return f(L, std::forward<Args>(args)...);
7974 }
7975
7976 inline int c_trampoline(lua_State* L, lua_CFunction f) noexcept {
7977 return trampoline(L, f);
7978 }
7979#else
7980
7981 inline int lua_cfunction_trampoline(lua_State* L, lua_CFunction f) {
7982#if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS_I_)
7983 return f(L);
7984
7985#else
7986 try {
7987 return f(L);
7988 }
7989 catch (const char* cs) {
7990 call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(cs));
7991 }
7992 catch (const std::string& s) {
7993 call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(s.c_str(), s.size()));
7994 }
7995 catch (const std::exception& e) {
7996 call_exception_handler(L, optional<const std::exception&>(e), e.what());
7997 }
7998#if SOL_IS_OFF(SOL_USE_LUAJIT_I_)
7999 // LuaJIT cannot have the catchall when the safe propagation is on
8000 // but LuaJIT will swallow all C++ errors
8001 // if we don't at least catch std::exception ones
8002 catch (...) {
8003 call_exception_handler(L, optional<const std::exception&>(nullopt), "caught (...) exception");
8004 }
8005#endif // LuaJIT cannot have the catchall, but we must catch std::exceps for it
8006 return lua_error(L);
8007#endif // Safe exceptions
8008 }
8009
8010 template <lua_CFunction f>
8011 int static_trampoline(lua_State* L) {
8012 return lua_cfunction_trampoline(L, f);
8013 }
8014
8015#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
8016 template <lua_CFunction_noexcept f>
8017 int static_trampoline_noexcept(lua_State* L) noexcept {
8018 return f(L);
8019 }
8020#else
8021 template <lua_CFunction f>
8022 int static_trampoline_noexcept(lua_State* L) noexcept {
8023 return f(L);
8024 }
8025#endif
8026
8027 template <typename Fx, typename... Args>
8028 int trampoline(lua_State* L, Fx&& f, Args&&... args) {
8029 if constexpr (meta::bind_traits<meta::unqualified_t<Fx>>::is_noexcept) {
8030 return f(L, std::forward<Args>(args)...);
8031 }
8032 else {
8033#if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS_I_)
8034 return f(L, std::forward<Args>(args)...);
8035#else
8036 try {
8037 return f(L, std::forward<Args>(args)...);
8038 }
8039 catch (const char* cs) {
8040 call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(cs));
8041 }
8042 catch (const std::string& s) {
8043 call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(s.c_str(), s.size()));
8044 }
8045 catch (const std::exception& e) {
8046 call_exception_handler(L, optional<const std::exception&>(e), e.what());
8047 }
8048#if SOL_IS_OFF(SOL_USE_LUAJIT_I_)
8049 // LuaJIT cannot have the catchall when the safe propagation is on
8050 // but LuaJIT will swallow all C++ errors
8051 // if we don't at least catch std::exception ones
8052 catch (...) {
8053 call_exception_handler(L, optional<const std::exception&>(nullopt), "caught (...) exception");
8054 }
8055#endif
8056 return lua_error(L);
8057#endif
8058 }
8059 }
8060
8061 inline int c_trampoline(lua_State* L, lua_CFunction f) {
8062 return trampoline(L, f);
8063 }
8064#endif // Exceptions vs. No Exceptions
8065
8066 template <typename F, F fx>
8067 inline int typed_static_trampoline(lua_State* L) {
8068 if constexpr (meta::bind_traits<F>::is_noexcept) {
8069 return static_trampoline_noexcept<fx>(L);
8070 }
8071 else {
8072 return static_trampoline<fx>(L);
8073 }
8074 }
8075 } // namespace detail
8076
8077 inline void set_default_exception_handler(lua_State* L, exception_handler_function exf = &detail::default_exception_handler) {
8078 static_assert(sizeof(void*) >= sizeof(exception_handler_function),
8079 "void* storage is too small to transport the exception handler: please file a bug on the sol2 issue tracker to get this looked at!");
8080 void* storage;
8081 std::memcpy(&storage, &exf, sizeof(exception_handler_function));
8082 lua_pushlightuserdata(L, storage);
8083 lua_setglobal(L, detail::default_exception_handler_name());
8084 }
8085} // namespace sol
8086
8087// end of sol/trampoline.hpp
8088
8089// beginning of sol/stack_core.hpp
8090
8091// beginning of sol/inheritance.hpp
8092
8093// beginning of sol/usertype_traits.hpp
8094
8095// beginning of sol/demangle.hpp
8096
8097#include <string>
8098#include <array>
8099#include <cctype>
8100#if SOL_IS_ON(SOL_MINGW_CCTYPE_IS_POISONED_I_)
8101extern "C" {
8102#include <ctype.h>
8103}
8104#endif // MinGW is on some stuff
8105#include <locale>
8106
8107namespace sol { namespace detail {
8108 inline constexpr std::array<string_view, 9> removals { { "{anonymous}",
8109 "(anonymous namespace)",
8110 "public:",
8111 "private:",
8112 "protected:",
8113 "struct ",
8114 "class ",
8115 "`anonymous-namespace'",
8116 "`anonymous namespace'" } };
8117
8118#if SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
8119 inline std::string ctti_get_type_name_from_sig(std::string name) {
8120 // cardinal sins from MINGW
8121 using namespace std;
8122 std::size_t start = name.find_first_of('[');
8123 start = name.find_first_of('=', start);
8124 std::size_t end = name.find_last_of(']');
8125 if (end == std::string::npos)
8126 end = name.size();
8127 if (start == std::string::npos)
8128 start = 0;
8129 if (start < name.size() - 1)
8130 start += 1;
8131 name = name.substr(start, end - start);
8132 start = name.rfind("seperator_mark");
8133 if (start != std::string::npos) {
8134 name.erase(start - 2, name.length());
8135 }
8136 while (!name.empty() && isblank(name.front()))
8137 name.erase(name.begin());
8138 while (!name.empty() && isblank(name.back()))
8139 name.pop_back();
8140
8141 for (std::size_t r = 0; r < removals.size(); ++r) {
8142 auto found = name.find(removals[r]);
8143 while (found != std::string::npos) {
8144 name.erase(found, removals[r].size());
8145 found = name.find(removals[r]);
8146 }
8147 }
8148
8149 return name;
8150 }
8151
8152 template <typename T, class seperator_mark = int>
8153 inline std::string ctti_get_type_name() {
8154 return ctti_get_type_name_from_sig(__PRETTY_FUNCTION__);
8155 }
8156#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_)
8157 inline std::string ctti_get_type_name_from_sig(std::string name) {
8158 std::size_t start = name.find("get_type_name");
8159 if (start == std::string::npos)
8160 start = 0;
8161 else
8162 start += 13;
8163 if (start < name.size() - 1)
8164 start += 1;
8165 std::size_t end = name.find_last_of('>');
8166 if (end == std::string::npos)
8167 end = name.size();
8168 name = name.substr(start, end - start);
8169 if (name.find("struct", 0) == 0)
8170 name.replace(0, 6, "", 0);
8171 if (name.find("class", 0) == 0)
8172 name.replace(0, 5, "", 0);
8173 while (!name.empty() && isblank(name.front()))
8174 name.erase(name.begin());
8175 while (!name.empty() && isblank(name.back()))
8176 name.pop_back();
8177
8178 for (std::size_t r = 0; r < removals.size(); ++r) {
8179 auto found = name.find(removals[r]);
8180 while (found != std::string::npos) {
8181 name.erase(found, removals[r].size());
8182 found = name.find(removals[r]);
8183 }
8184 }
8185
8186 return name;
8187 }
8188
8189 template <typename T>
8190 std::string ctti_get_type_name() {
8191 return ctti_get_type_name_from_sig(__FUNCSIG__);
8192 }
8193#else
8194#error Compiler not supported for demangling
8195#endif // compilers
8196
8197 template <typename T>
8198 std::string demangle_once() {
8199 std::string realname = ctti_get_type_name<T>();
8200 return realname;
8201 }
8202
8203 inline std::string short_demangle_from_type_name(std::string realname) {
8204 // This isn't the most complete but it'll do for now...?
8205 static const std::array<std::string, 10> ops = {
8206 { "operator<", "operator<<", "operator<<=", "operator<=", "operator>", "operator>>", "operator>>=", "operator>=", "operator->", "operator->*" }
8207 };
8208 int level = 0;
8209 std::ptrdiff_t idx = 0;
8210 for (idx = static_cast<std::ptrdiff_t>(realname.empty() ? 0 : realname.size() - 1); idx > 0; --idx) {
8211 if (level == 0 && realname[idx] == ':') {
8212 break;
8213 }
8214 bool isleft = realname[idx] == '<';
8215 bool isright = realname[idx] == '>';
8216 if (!isleft && !isright)
8217 continue;
8218 bool earlybreak = false;
8219 for (const auto& op : ops) {
8220 std::size_t nisop = realname.rfind(op, idx);
8221 if (nisop == std::string::npos)
8222 continue;
8223 std::size_t nisopidx = idx - op.size() + 1;
8224 if (nisop == nisopidx) {
8225 idx = static_cast<std::ptrdiff_t>(nisopidx);
8226 earlybreak = true;
8227 }
8228 break;
8229 }
8230 if (earlybreak) {
8231 continue;
8232 }
8233 level += isleft ? -1 : 1;
8234 }
8235 if (idx > 0) {
8236 realname.erase(0, realname.length() < static_cast<std::size_t>(idx) ? realname.length() : idx + 1);
8237 }
8238 return realname;
8239 }
8240
8241 template <typename T>
8242 std::string short_demangle_once() {
8243 std::string realname = ctti_get_type_name<T>();
8244 return short_demangle_from_type_name(realname);
8245 }
8246
8247 template <typename T>
8248 const std::string& demangle() {
8249 static const std::string d = demangle_once<T>();
8250 return d;
8251 }
8252
8253 template <typename T>
8254 const std::string& short_demangle() {
8255 static const std::string d = short_demangle_once<T>();
8256 return d;
8257 }
8258}} // namespace sol::detail
8259
8260// end of sol/demangle.hpp
8261
8262namespace sol {
8263
8264 template <typename T>
8265 struct usertype_traits {
8266 static const std::string& name() {
8267 static const std::string& n = detail::short_demangle<T>();
8268 return n;
8269 }
8270 static const std::string& qualified_name() {
8271 static const std::string& q_n = detail::demangle<T>();
8272 return q_n;
8273 }
8274 static const std::string& metatable() {
8275 static const std::string m = std::string("sol.").append(detail::demangle<T>());
8276 return m;
8277 }
8278 static const std::string& user_metatable() {
8279 static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user");
8280 return u_m;
8281 }
8282 static const std::string& user_gc_metatable() {
8283 static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB");
8284 return u_g_m;
8285 }
8286 static const std::string& gc_table() {
8287 static const std::string g_t = std::string("sol.").append(detail::demangle<T>()).append(".\xE2\x99\xBB");
8288 return g_t;
8289 }
8290 };
8291
8292} // namespace sol
8293
8294// end of sol/usertype_traits.hpp
8295
8296// beginning of sol/unique_usertype_traits.hpp
8297
8298#include <memory>
8299
8300namespace sol {
8301
8302 template <typename T>
8303 struct unique_usertype_traits {
8304 typedef T type;
8305 typedef T actual_type;
8306 template <typename X>
8307 using rebind_base = void;
8308
8309 static const bool value = false;
8310
8311 template <typename U>
8312 static bool is_null(U&&) {
8313 return false;
8314 }
8315
8316 template <typename U>
8317 static auto get(U&& value) {
8318 return std::addressof(detail::deref(value));
8319 }
8320 };
8321
8322 template <typename T>
8323 struct unique_usertype_traits<std::shared_ptr<T>> {
8324 typedef T type;
8325 typedef std::shared_ptr<T> actual_type;
8326 // rebind is non-void
8327 // if and only if unique usertype
8328 // is cast-capable
8329 template <typename X>
8330 using rebind_base = std::shared_ptr<X>;
8331
8332 static const bool value = true;
8333
8334 static bool is_null(const actual_type& p) {
8335 return p == nullptr;
8336 }
8337
8338 static type* get(const actual_type& p) {
8339 return p.get();
8340 }
8341 };
8342
8343 template <typename T, typename D>
8344 struct unique_usertype_traits<std::unique_ptr<T, D>> {
8345 using type = T;
8346 using actual_type = std::unique_ptr<T, D>;
8347
8348 static const bool value = true;
8349
8350 static bool is_null(const actual_type& p) {
8351 return p == nullptr;
8352 }
8353
8354 static type* get(const actual_type& p) {
8355 return p.get();
8356 }
8357 };
8358
8359 template <typename T>
8360 struct is_unique_usertype : std::integral_constant<bool, unique_usertype_traits<T>::value> {};
8361
8362 template <typename T>
8363 inline constexpr bool is_unique_usertype_v = is_unique_usertype<T>::value;
8364
8365 namespace detail {
8366 template <typename T, typename Rebind = void>
8367 using is_base_rebindable_test = typename T::template rebind_base<Rebind>;
8368 }
8369
8370 template <typename T>
8371 using is_base_rebindable = meta::is_detected<detail::is_base_rebindable_test, T>;
8372
8373 template <typename T>
8374 inline constexpr bool is_base_rebindable_v = is_base_rebindable<T>::value;
8375
8376 namespace detail {
8377 template <typename T, typename = void>
8378 struct is_base_rebindable_non_void_sfinae : std::false_type {};
8379
8380 template <typename T>
8381 struct is_base_rebindable_non_void_sfinae<T, std::enable_if_t<is_base_rebindable_v<T>>>
8382 : std::integral_constant<bool, !std::is_void_v<typename T::template rebind_base<void>>> {};
8383 } // namespace detail
8384
8385 template <typename T>
8386 using is_base_rebindable_non_void = meta::is_detected<detail::is_base_rebindable_test, T>;
8387
8388 template <typename T>
8389 inline constexpr bool is_base_rebindable_non_void_v = is_base_rebindable_non_void<T>::value;
8390
8391} // namespace sol
8392
8393// end of sol/unique_usertype_traits.hpp
8394
8395namespace sol {
8396 template <typename... Args>
8397 struct base_list {};
8398 template <typename... Args>
8399 using bases = base_list<Args...>;
8400
8401 typedef bases<> base_classes_tag;
8402 const auto base_classes = base_classes_tag();
8403
8404 template <typename... Args>
8405 struct is_to_stringable<base_list<Args...>> : std::false_type {};
8406
8407 namespace detail {
8408
8409 inline decltype(auto) base_class_check_key() {
8410 static const auto& key = "class_check";
8411 return key;
8412 }
8413
8414 inline decltype(auto) base_class_cast_key() {
8415 static const auto& key = "class_cast";
8416 return key;
8417 }
8418
8419 inline decltype(auto) base_class_index_propogation_key() {
8420 static const auto& key = u8"\xF0\x9F\x8C\xB2.index";
8421 return key;
8422 }
8423
8424 inline decltype(auto) base_class_new_index_propogation_key() {
8425 static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index";
8426 return key;
8427 }
8428
8429 template <typename T>
8430 struct inheritance {
8431 typedef typename base<T>::type bases_t;
8432
8433 static bool type_check_bases(types<>, const string_view&) {
8434 return false;
8435 }
8436
8437 template <typename Base, typename... Args>
8438 static bool type_check_bases(types<Base, Args...>, const string_view& ti) {
8439 return ti == usertype_traits<Base>::qualified_name() || type_check_bases(types<Args...>(), ti);
8440 }
8441
8442 static bool type_check(const string_view& ti) {
8443 return ti == usertype_traits<T>::qualified_name() || type_check_bases(bases_t(), ti);
8444 }
8445
8446 template <typename ...Bases>
8447 static bool type_check_with(const string_view& ti) {
8448 return ti == usertype_traits<T>::qualified_name() || type_check_bases(types<Bases...>(), ti);
8449 }
8450
8451 static void* type_cast_bases(types<>, T*, const string_view&) {
8452 return nullptr;
8453 }
8454
8455 template <typename Base, typename... Args>
8456 static void* type_cast_bases(types<Base, Args...>, T* data, const string_view& ti) {
8457 // Make sure to convert to T first, and then dynamic cast to the proper type
8458 return ti != usertype_traits<Base>::qualified_name() ? type_cast_bases(types<Args...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data));
8459 }
8460
8461 static void* type_cast(void* voiddata, const string_view& ti) {
8462 T* data = static_cast<T*>(voiddata);
8463 return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(bases_t(), data, ti) : data);
8464 }
8465
8466 template <typename... Bases>
8467 static void* type_cast_with(void* voiddata, const string_view& ti) {
8468 T* data = static_cast<T*>(voiddata);
8469 return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(types<Bases...>(), data, ti) : data);
8470 }
8471
8472 template <typename U>
8473 static bool type_unique_cast_bases(types<>, void*, void*, const string_view&) {
8474 return 0;
8475 }
8476
8477 template <typename U, typename Base, typename... Args>
8478 static int type_unique_cast_bases(types<Base, Args...>, void* source_data, void* target_data, const string_view& ti) {
8479 using uu_traits = unique_usertype_traits<U>;
8480 using base_ptr = typename uu_traits::template rebind_base<Base>;
8481 string_view base_ti = usertype_traits<Base>::qualified_name();
8482 if (base_ti == ti) {
8483 if (target_data != nullptr) {
8484 U* source = static_cast<U*>(source_data);
8485 base_ptr* target = static_cast<base_ptr*>(target_data);
8486 // perform proper derived -> base conversion
8487 *target = *source;
8488 }
8489 return 2;
8490 }
8491 return type_unique_cast_bases<U>(types<Args...>(), source_data, target_data, ti);
8492 }
8493
8494 template <typename U>
8495 static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
8496 typedef unique_usertype_traits<U> uu_traits;
8497 if constexpr (is_base_rebindable_v<uu_traits>) {
8498 typedef typename uu_traits::template rebind_base<void> rebind_t;
8499 typedef meta::conditional_t<std::is_void<rebind_t>::value, types<>, bases_t> cond_bases_t;
8500 string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
8501 if (rebind_ti != this_rebind_ti) {
8502 // this is not even of the same unique type
8503 return 0;
8504 }
8505 string_view this_ti = usertype_traits<T>::qualified_name();
8506 if (ti == this_ti) {
8507 // direct match, return 1
8508 return 1;
8509 }
8510 return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
8511 }
8512 else {
8513 (void)rebind_ti;
8514 string_view this_ti = usertype_traits<T>::qualified_name();
8515 if (ti == this_ti) {
8516 // direct match, return 1
8517 return 1;
8518 }
8519 return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
8520 }
8521 }
8522
8523 template <typename U, typename... Bases>
8524 static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
8525 using uc_bases_t = types<Bases...>;
8526 typedef unique_usertype_traits<U> uu_traits;
8527 if constexpr (is_base_rebindable_v<uu_traits>) {
8528 using rebind_t = typename uu_traits::template rebind_base<void>;
8529 using cond_bases_t = meta::conditional_t<std::is_void<rebind_t>::value, types<>, uc_bases_t>;
8530 string_view this_rebind_ti = usertype_traits<rebind_t>::qualified_name();
8531 if (rebind_ti != this_rebind_ti) {
8532 // this is not even of the same unique type
8533 return 0;
8534 }
8535 string_view this_ti = usertype_traits<T>::qualified_name();
8536 if (ti == this_ti) {
8537 // direct match, return 1
8538 return 1;
8539 }
8540 return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
8541 }
8542 else {
8543 (void)rebind_ti;
8544 string_view this_ti = usertype_traits<T>::qualified_name();
8545 if (ti == this_ti) {
8546 // direct match, return 1
8547 return 1;
8548 }
8549 return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
8550 }
8551 }
8552 };
8553
8554 using inheritance_check_function = decltype(&inheritance<void>::type_check);
8555 using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
8556 using inheritance_unique_cast_function = decltype(&inheritance<void>::type_unique_cast<void>);
8557 } // namespace detail
8558} // namespace sol
8559
8560// end of sol/inheritance.hpp
8561
8562// beginning of sol/error_handler.hpp
8563
8564#include <cstdio>
8565
8566namespace sol {
8567
8568 namespace detail {
8569 constexpr const char* not_a_number = "not a numeric type";
8570 constexpr const char* not_a_number_or_number_string = "not a numeric type or numeric string";
8571 constexpr const char* not_a_number_integral = "not a numeric type that fits exactly an integer (number maybe has significant decimals)";
8572 constexpr const char* not_a_number_or_number_string_integral
8573 = "not a numeric type or a numeric string that fits exactly an integer (e.g. number maybe has significant decimals)";
8574
8575 constexpr const char* not_enough_stack_space = "not enough space left on Lua stack";
8576 constexpr const char* not_enough_stack_space_floating = "not enough space left on Lua stack for a floating point number";
8577 constexpr const char* not_enough_stack_space_integral = "not enough space left on Lua stack for an integral number";
8578 constexpr const char* not_enough_stack_space_string = "not enough space left on Lua stack for a string";
8579 constexpr const char* not_enough_stack_space_meta_function_name = "not enough space left on Lua stack for the name of a meta_function";
8580 constexpr const char* not_enough_stack_space_userdata = "not enough space left on Lua stack to create a sol3 userdata";
8581 constexpr const char* not_enough_stack_space_generic = "not enough space left on Lua stack to push valuees";
8582 constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment";
8583 constexpr const char* protected_function_error = "caught (...) unknown error during protected_function call";
8584
8585 inline void accumulate_and_mark(const std::string& n, std::string& aux_message, int& marker) {
8586 if (marker > 0) {
8587 aux_message += ", ";
8588 }
8589 aux_message += n;
8590 ++marker;
8591 }
8592 } // namespace detail
8593
8594 inline std::string associated_type_name(lua_State* L, int index, type t) {
8595 switch (t) {
8596 case type::poly:
8597 return "anything";
8598 case type::userdata: {
8599#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
8600 luaL_checkstack(L, 2, "not enough space to push get the type name");
8601#endif // make sure stack doesn't overflow
8602 if (lua_getmetatable(L, index) == 0) {
8603 break;
8604 }
8605 lua_pushlstring(L, "__name", 6);
8606 lua_rawget(L, -2);
8607 size_t sz;
8608 const char* name = lua_tolstring(L, -1, &sz);
8609 std::string tn(name, static_cast<std::string::size_type>(sz));
8610 lua_pop(L, 2);
8611 return tn;
8612 }
8613 default:
8614 break;
8615 }
8616 return lua_typename(L, static_cast<int>(t));
8617 }
8618
8619 inline int push_type_panic_string(lua_State* L, int index, type expected, type actual, string_view message, string_view aux_message) noexcept {
8620 const char* err = message.size() == 0
8621 ? (aux_message.size() == 0 ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s")
8622 : "stack index %d, expected %s, received %s: %s %s";
8623 const char* type_name = expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected));
8624 {
8625 std::string actual_name = associated_type_name(L, index, actual);
8626 lua_pushfstring(L, err, index, type_name, actual_name.c_str(), message.data(), aux_message.data());
8627 }
8628 return 1;
8629 }
8630
8631 inline int type_panic_string(lua_State* L, int index, type expected, type actual, string_view message = "") noexcept(false) {
8632 push_type_panic_string(L, index, expected, actual, message, "");
8633 return lua_error(L);
8634 }
8635
8636 inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) {
8637 push_type_panic_string(L, index, expected, actual, message == nullptr ? "" : message, "");
8638 return lua_error(L);
8639 }
8640
8641 struct type_panic_t {
8642 int operator()(lua_State* L, int index, type expected, type actual) const noexcept(false) {
8643 return type_panic_c_str(L, index, expected, actual, nullptr);
8644 }
8645 int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
8646 return type_panic_c_str(L, index, expected, actual, message.data());
8647 }
8648 };
8649
8650 const type_panic_t type_panic = {};
8651
8652 struct constructor_handler {
8653 int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
8654 push_type_panic_string(L, index, expected, actual, message, "(type check failed in constructor)");
8655 return lua_error(L);
8656 }
8657 };
8658
8659 template <typename F = void>
8660 struct argument_handler {
8661 int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
8662 push_type_panic_string(L, index, expected, actual, message, "(bad argument to variable or function call)");
8663 return lua_error(L);
8664 }
8665 };
8666
8667 template <typename R, typename... Args>
8668 struct argument_handler<types<R, Args...>> {
8669 int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
8670 {
8671 std::string aux_message = "(bad argument into '";
8672 aux_message += detail::demangle<R>();
8673 aux_message += "(";
8674 int marker = 0;
8675 (void)detail::swallow { int(), (detail::accumulate_and_mark(detail::demangle<Args>(), aux_message, marker), int())... };
8676 aux_message += ")')";
8677 push_type_panic_string(L, index, expected, actual, message, aux_message);
8678 }
8679 return lua_error(L);
8680 }
8681 };
8682
8683 // Specify this function as the handler for lua::check if you know there's nothing wrong
8684 inline int no_panic(lua_State*, int, type, type, const char* = nullptr) noexcept {
8685 return 0;
8686 }
8687
8688 inline void type_error(lua_State* L, int expected, int actual) noexcept(false) {
8689 luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual));
8690 }
8691
8692 inline void type_error(lua_State* L, type expected, type actual) noexcept(false) {
8693 type_error(L, static_cast<int>(expected), static_cast<int>(actual));
8694 }
8695
8696 inline void type_assert(lua_State* L, int index, type expected, type actual) noexcept(false) {
8697 if (expected != type::poly && expected != actual) {
8698 type_panic_c_str(L, index, expected, actual, nullptr);
8699 }
8700 }
8701
8702 inline void type_assert(lua_State* L, int index, type expected) {
8703 type actual = type_of(L, index);
8704 type_assert(L, index, expected, actual);
8705 }
8706
8707} // namespace sol
8708
8709// end of sol/error_handler.hpp
8710
8711// beginning of sol/reference.hpp
8712
8713// beginning of sol/stack_reference.hpp
8714
8715namespace sol {
8716 namespace detail {
8717 inline bool xmovable(lua_State* leftL, lua_State* rightL) {
8718 if (rightL == nullptr || leftL == nullptr || leftL == rightL) {
8719 return false;
8720 }
8721 const void* leftregistry = lua_topointer(leftL, LUA_REGISTRYINDEX);
8722 const void* rightregistry = lua_topointer(rightL, LUA_REGISTRYINDEX);
8723 return leftregistry == rightregistry;
8724 }
8725 } // namespace detail
8726
8727 class stateless_stack_reference {
8728 private:
8729 friend class stack_reference;
8730
8731 int index = 0;
8732
8733 int registry_index() const noexcept {
8734 return LUA_NOREF;
8735 }
8736
8737 public:
8738 stateless_stack_reference() noexcept = default;
8739 stateless_stack_reference(lua_nil_t) noexcept : stateless_stack_reference(){};
8740 stateless_stack_reference(lua_State* L, int i) noexcept : stateless_stack_reference(absolute_index(L, i)) {
8741 }
8742 stateless_stack_reference(lua_State*, absolute_index i) noexcept : stateless_stack_reference(i) {
8743 }
8744 stateless_stack_reference(lua_State*, raw_index i) noexcept : stateless_stack_reference(i) {
8745 }
8746 stateless_stack_reference(absolute_index i) noexcept : index(i) {
8747 }
8748 stateless_stack_reference(raw_index i) noexcept : index(i) {
8749 }
8750 stateless_stack_reference(lua_State*, ref_index) noexcept = delete;
8751 stateless_stack_reference(ref_index) noexcept = delete;
8752 stateless_stack_reference(const reference&) noexcept = delete;
8753 stateless_stack_reference(const stateless_stack_reference&) noexcept = default;
8754 stateless_stack_reference(stateless_stack_reference&& o) noexcept = default;
8755 stateless_stack_reference& operator=(stateless_stack_reference&&) noexcept = default;
8756 stateless_stack_reference& operator=(const stateless_stack_reference&) noexcept = default;
8757
8758 int push(lua_State* L) const noexcept {
8759#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
8760 luaL_checkstack(L, 1, "not enough Lua stack space to push a single reference value");
8761#endif // make sure stack doesn't overflow
8762 lua_pushvalue(L, index);
8763 return 1;
8764 }
8765
8766 void pop(lua_State* L, int n = 1) const noexcept {
8767 lua_pop(L, n);
8768 }
8769
8770 int stack_index() const noexcept {
8771 return index;
8772 }
8773
8774 const void* pointer(lua_State* L) const noexcept {
8775 const void* vp = lua_topointer(L, stack_index());
8776 return vp;
8777 }
8778
8779 type get_type(lua_State* L) const noexcept {
8780 int result = lua_type(L, index);
8781 return static_cast<type>(result);
8782 }
8783
8784 bool valid(lua_State* L) const noexcept {
8785 type t = get_type(L);
8786 return t != type::lua_nil && t != type::none;
8787 }
8788
8789 void abandon(lua_State* = nullptr) {
8790 index = 0;
8791 }
8792 };
8793
8794 class stack_reference : public stateless_stack_reference {
8795 private:
8796 lua_State* luastate = nullptr;
8797
8798 public:
8799 stack_reference() noexcept = default;
8800 stack_reference(lua_nil_t) noexcept
8801 : stack_reference() {};
8802 stack_reference(lua_State* L, lua_nil_t) noexcept : stateless_stack_reference(L, 0), luastate(L) {
8803 }
8804 stack_reference(lua_State* L, int i) noexcept : stateless_stack_reference(L, i), luastate(L) {
8805 }
8806 stack_reference(lua_State* L, absolute_index i) noexcept : stateless_stack_reference(L, i), luastate(L) {
8807 }
8808 stack_reference(lua_State* L, raw_index i) noexcept : stateless_stack_reference(L, i), luastate(L) {
8809 }
8810 stack_reference(lua_State* L, ref_index i) noexcept = delete;
8811 stack_reference(lua_State* L, const reference& r) noexcept = delete;
8812 stack_reference(lua_State* L, const stack_reference& r) noexcept
8813 : luastate(L) {
8814 if (!r.valid()) {
8815 index = 0;
8816 return;
8817 }
8818 int i = r.stack_index();
8819 if (detail::xmovable(lua_state(), r.lua_state())) {
8820#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
8821 luaL_checkstack(L, 1, "not enough Lua stack space to push a single reference value");
8822#endif // make sure stack doesn't overflow
8823 lua_pushvalue(r.lua_state(), r.index);
8824 lua_xmove(r.lua_state(), luastate, 1);
8825 i = absolute_index(luastate, -1);
8826 }
8827 index = i;
8828 }
8829 stack_reference(stack_reference&& o) noexcept = default;
8830 stack_reference& operator=(stack_reference&&) noexcept = default;
8831 stack_reference(const stack_reference&) noexcept = default;
8832 stack_reference& operator=(const stack_reference&) noexcept = default;
8833
8834 int push() const noexcept {
8835 return push(lua_state());
8836 }
8837
8838 int push(lua_State* Ls) const noexcept {
8839 return stateless_stack_reference::push(Ls);
8840 }
8841
8842 void pop() const noexcept {
8843 pop(lua_state());
8844 }
8845
8846 void pop(lua_State* Ls, int n = 1) const noexcept {
8847 stateless_stack_reference::pop(Ls, n);
8848 }
8849
8850 const void* pointer() const noexcept {
8851 return stateless_stack_reference::pointer(lua_state());
8852 }
8853
8854 type get_type() const noexcept {
8855 return stateless_stack_reference::get_type(lua_state());
8856 }
8857
8858 lua_State* lua_state() const noexcept {
8859 return luastate;
8860 }
8861
8862 bool valid() const noexcept {
8863 return stateless_stack_reference::valid(lua_state());
8864 }
8865
8866 void abandon () {
8867 stateless_stack_reference::abandon(lua_state());
8868 }
8869 };
8870
8871 inline bool operator==(const stack_reference& l, const stack_reference& r) {
8872 return lua_compare(l.lua_state(), l.stack_index(), r.stack_index(), LUA_OPEQ) == 0;
8873 }
8874
8875 inline bool operator!=(const stack_reference& l, const stack_reference& r) {
8876 return !operator==(l, r);
8877 }
8878
8879 inline bool operator==(const stack_reference& lhs, const lua_nil_t&) {
8880 return !lhs.valid();
8881 }
8882
8883 inline bool operator==(const lua_nil_t&, const stack_reference& rhs) {
8884 return !rhs.valid();
8885 }
8886
8887 inline bool operator!=(const stack_reference& lhs, const lua_nil_t&) {
8888 return lhs.valid();
8889 }
8890
8891 inline bool operator!=(const lua_nil_t&, const stack_reference& rhs) {
8892 return rhs.valid();
8893 }
8894
8895 struct stack_reference_equals {
8896 bool operator()(const lua_nil_t& lhs, const stack_reference& rhs) const {
8897 return lhs == rhs;
8898 }
8899
8900 bool operator()(const stack_reference& lhs, const lua_nil_t& rhs) const {
8901 return lhs == rhs;
8902 }
8903
8904 bool operator()(const stack_reference& lhs, const stack_reference& rhs) const {
8905 return lhs == rhs;
8906 }
8907 };
8908
8909 struct stack_reference_hash {
8910 typedef stack_reference argument_type;
8911 typedef std::size_t result_type;
8912
8913 result_type operator()(const argument_type& lhs) const {
8914 std::hash<const void*> h;
8915 return h(lhs.pointer());
8916 }
8917 };
8918} // namespace sol
8919
8920// end of sol/stack_reference.hpp
8921
8922#include <functional>
8923
8924namespace sol {
8925 namespace detail {
8926 inline const char (&default_main_thread_name())[9] {
8927 static const char name[9] = "sol.\xF0\x9F\x93\x8C";
8928 return name;
8929 }
8930 } // namespace detail
8931
8932 namespace stack {
8933 inline void remove(lua_State* L, int rawindex, int count) {
8934 if (count < 1)
8935 return;
8936 int top = lua_gettop(L);
8937 if (top < 1) {
8938 return;
8939 }
8940 if (rawindex == -count || top == rawindex) {
8941 // Slice them right off the top
8942 lua_pop(L, static_cast<int>(count));
8943 return;
8944 }
8945
8946 // Remove each item one at a time using stack operations
8947 // Probably slower, maybe, haven't benchmarked,
8948 // but necessary
8949 int index = lua_absindex(L, rawindex);
8950 if (index < 0) {
8951 index = lua_gettop(L) + (index + 1);
8952 }
8953 int last = index + count;
8954 for (int i = index; i < last; ++i) {
8955 lua_remove(L, index);
8956 }
8957 }
8958
8959 struct push_popper_at {
8960 lua_State* L;
8961 int index;
8962 int count;
8963 push_popper_at(lua_State* luastate, int index = -1, int count = 1) : L(luastate), index(index), count(count) {
8964 }
8965 ~push_popper_at() {
8966 remove(L, index, count);
8967 }
8968 };
8969
8970 template <bool top_level>
8971 struct push_popper_n {
8972 lua_State* L;
8973 int t;
8974 push_popper_n(lua_State* luastate, int x) : L(luastate), t(x) {
8975 }
8976 push_popper_n(const push_popper_n&) = delete;
8977 push_popper_n(push_popper_n&&) = default;
8978 push_popper_n& operator=(const push_popper_n&) = delete;
8979 push_popper_n& operator=(push_popper_n&&) = default;
8980 ~push_popper_n() {
8981 lua_pop(L, t);
8982 }
8983 };
8984
8985 template <>
8986 struct push_popper_n<true> {
8987 push_popper_n(lua_State*, int) {
8988 }
8989 };
8990
8991 template <bool, typename T, typename = void>
8992 struct push_popper {
8993 using Tu = meta::unqualified_t<T>;
8994 T t;
8995 int idx;
8996
8997 push_popper(T x) : t(x), idx(lua_absindex(t.lua_state(), -t.push())) {
8998 }
8999
9000 int index_of(const Tu&) {
9001 return idx;
9002 }
9003
9004 ~push_popper() {
9005 t.pop();
9006 }
9007 };
9008
9009 template <typename T, typename C>
9010 struct push_popper<true, T, C> {
9011 using Tu = meta::unqualified_t<T>;
9012
9013 push_popper(T) {
9014 }
9015
9016 int index_of(const Tu&) {
9017 return -1;
9018 }
9019
9020 ~push_popper() {
9021 }
9022 };
9023
9024 template <typename T>
9025 struct push_popper<false, T, std::enable_if_t<is_stack_based_v<meta::unqualified_t<T>>>> {
9026 using Tu = meta::unqualified_t<T>;
9027
9028 push_popper(T) {
9029 }
9030
9031 int index_of(const Tu& r) {
9032 return r.stack_index();
9033 }
9034
9035 ~push_popper() {
9036 }
9037 };
9038
9039 template <bool top_level = false, typename T>
9040 push_popper<top_level, T> push_pop(T&& x) {
9041 return push_popper<top_level, T>(std::forward<T>(x));
9042 }
9043
9044 template <typename T>
9045 push_popper_at push_pop_at(T&& x) {
9046 int c = x.push();
9047 lua_State* L = x.lua_state();
9048 return push_popper_at(L, lua_absindex(L, -c), c);
9049 }
9050
9051 template <bool top_level = false>
9052 push_popper_n<top_level> pop_n(lua_State* L, int x) {
9053 return push_popper_n<top_level>(L, x);
9054 }
9055 } // namespace stack
9056
9057 inline lua_State* main_thread(lua_State* L, lua_State* backup_if_unsupported = nullptr) {
9058#if SOL_LUA_VESION_I_ < 502
9059 if (L == nullptr)
9060 return backup_if_unsupported;
9061 lua_getglobal(L, detail::default_main_thread_name());
9062 auto pp = stack::pop_n(L, 1);
9063 if (type_of(L, -1) == type::thread) {
9064 return lua_tothread(L, -1);
9065 }
9066 return backup_if_unsupported;
9067#else
9068 if (L == nullptr)
9069 return backup_if_unsupported;
9070 lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD);
9071 lua_State* Lmain = lua_tothread(L, -1);
9072 lua_pop(L, 1);
9073 return Lmain;
9074#endif // Lua 5.2+ has the main thread unqualified_getter
9075 }
9076
9077 namespace detail {
9078 struct global_tag {
9079 } const global_ {};
9080 struct no_safety_tag {
9081 } const no_safety {};
9082
9083 template <bool b>
9084 inline lua_State* pick_main_thread(lua_State* L, lua_State* backup_if_unsupported = nullptr) {
9085 (void)L;
9086 (void)backup_if_unsupported;
9087 if (b) {
9088 return main_thread(L, backup_if_unsupported);
9089 }
9090 return L;
9091 }
9092 } // namespace detail
9093
9094 class stateless_reference {
9095 private:
9096 template <bool o_main_only>
9097 friend class basic_reference;
9098
9099 int ref = LUA_NOREF;
9100
9101 int copy(lua_State* L) const noexcept {
9102 if (ref == LUA_NOREF)
9103 return LUA_NOREF;
9104 push(L);
9105 return luaL_ref(L, LUA_REGISTRYINDEX);
9106 }
9107
9108 lua_State* copy_assign(lua_State* L, lua_State* rL, const stateless_reference& r) {
9109 if (valid(L)) {
9110 deref(L);
9111 }
9112 ref = r.copy(L);
9113 return rL;
9114 }
9115
9116 lua_State* move_assign(lua_State* L, lua_State* rL, stateless_reference&& r) {
9117 if (valid(L)) {
9118 deref(L);
9119 }
9120 ref = r.ref;
9121 r.ref = LUA_NOREF;
9122 return rL;
9123 }
9124
9125 protected:
9126 int stack_index() const noexcept {
9127 return -1;
9128 }
9129
9130 stateless_reference(lua_State* L, detail::global_tag) noexcept {
9131#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
9132 luaL_checkstack(L, 1, "not enough Lua stack space to push this reference value");
9133#endif // make sure stack doesn't overflow
9134 lua_pushglobaltable(L);
9135 ref = luaL_ref(L, LUA_REGISTRYINDEX);
9136 }
9137
9138 stateless_reference(int raw_ref_index) noexcept : ref(raw_ref_index) {
9139 }
9140
9141 public:
9142 stateless_reference() noexcept = default;
9143 stateless_reference(lua_nil_t) noexcept : stateless_reference() {
9144 }
9145 stateless_reference(const stack_reference& r) noexcept : stateless_reference(r.lua_state(), r.stack_index()) {
9146 }
9147 stateless_reference(stack_reference&& r) noexcept : stateless_reference(r.lua_state(), r.stack_index()) {
9148 }
9149 stateless_reference(lua_State* L, const stateless_reference& r) noexcept {
9150 if (r.ref == LUA_REFNIL) {
9151 ref = LUA_REFNIL;
9152 return;
9153 }
9154 if (r.ref == LUA_NOREF || L == nullptr) {
9155 ref = LUA_NOREF;
9156 return;
9157 }
9158 ref = r.copy(L);
9159 }
9160
9161 stateless_reference(lua_State* L, stateless_reference&& r) noexcept {
9162 if (r.ref == LUA_REFNIL) {
9163 ref = LUA_REFNIL;
9164 return;
9165 }
9166 if (r.ref == LUA_NOREF || L == nullptr) {
9167 ref = LUA_NOREF;
9168 return;
9169 }
9170 ref = r.ref;
9171 r.ref = LUA_NOREF;
9172 }
9173
9174 stateless_reference(lua_State* L, const stack_reference& r) noexcept {
9175 if (L == nullptr || r.lua_state() == nullptr || r.get_type() == type::none) {
9176 ref = LUA_NOREF;
9177 return;
9178 }
9179 if (r.get_type() == type::lua_nil) {
9180 ref = LUA_REFNIL;
9181 return;
9182 }
9183 if (L != r.lua_state() && !detail::xmovable(L, r.lua_state())) {
9184 return;
9185 }
9186 r.push(L);
9187 ref = luaL_ref(L, LUA_REGISTRYINDEX);
9188 }
9189
9190 stateless_reference(lua_State* L, int index = -1) noexcept {
9191 // use L to stick with that state's execution stack
9192#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
9193 luaL_checkstack(L, 1, "not enough Lua stack space to push this reference value");
9194#endif // make sure stack doesn't overflow
9195 lua_pushvalue(L, index);
9196 ref = luaL_ref(L, LUA_REGISTRYINDEX);
9197 }
9198 stateless_reference(lua_State* L, ref_index index) noexcept {
9199 lua_rawgeti(L, LUA_REGISTRYINDEX, index.index);
9200 ref = luaL_ref(L, LUA_REGISTRYINDEX);
9201 }
9202 stateless_reference(lua_State*, lua_nil_t) noexcept {
9203 }
9204
9205 ~stateless_reference() noexcept = default;
9206
9207 stateless_reference(const stateless_reference& o) noexcept = delete;
9208 stateless_reference& operator=(const stateless_reference& r) noexcept = delete;
9209
9210 stateless_reference(stateless_reference&& o) noexcept : ref(o.ref) {
9211 o.ref = LUA_NOREF;
9212 }
9213
9214 stateless_reference& operator=(stateless_reference&& o) noexcept {
9215 ref = o.ref;
9216 o.ref = LUA_NOREF;
9217 return *this;
9218 }
9219
9220 int push(lua_State* L) const noexcept {
9221#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
9222 luaL_checkstack(L, 1, "not enough Lua stack space to push this reference value");
9223#endif // make sure stack doesn't overflow
9224 lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
9225 return 1;
9226 }
9227
9228 void pop(lua_State* L, int n = 1) const noexcept {
9229 lua_pop(L, n);
9230 }
9231
9232 int registry_index() const noexcept {
9233 return ref;
9234 }
9235
9236 bool valid(lua_State*) const noexcept {
9237 return !(ref == LUA_NOREF || ref == LUA_REFNIL);
9238 }
9239
9240 const void* pointer(lua_State* L) const noexcept {
9241 int si = push(L);
9242 const void* vp = lua_topointer(L, -si);
9243 lua_pop(L, si);
9244 return vp;
9245 }
9246
9247 type get_type(lua_State* L) const noexcept {
9248 int p = push(L);
9249 int result = lua_type(L, -1);
9250 pop(L, p);
9251 return static_cast<type>(result);
9252 }
9253
9254 void abandon(lua_State* = nullptr) {
9255 ref = LUA_NOREF;
9256 }
9257
9258 void deref(lua_State* L) const noexcept {
9259 luaL_unref(L, LUA_REGISTRYINDEX, ref);
9260 }
9261 };
9262
9263 template <bool main_only = false>
9264 class basic_reference : public stateless_reference {
9265 private:
9266 template <bool o_main_only>
9267 friend class basic_reference;
9268 lua_State* luastate = nullptr; // non-owning
9269
9270 template <bool r_main_only>
9271 void copy_assign(const basic_reference<r_main_only>& r) {
9272 if (valid()) {
9273 deref();
9274 }
9275 if (r.ref == LUA_REFNIL) {
9276 luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state());
9277 ref = LUA_REFNIL;
9278 return;
9279 }
9280 if (r.ref == LUA_NOREF) {
9281 luastate = r.luastate;
9282 ref = LUA_NOREF;
9283 return;
9284 }
9285 if (detail::xmovable(lua_state(), r.lua_state())) {
9286 r.push(lua_state());
9287 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
9288 return;
9289 }
9290 luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state());
9291 ref = r.copy();
9292 }
9293
9294 template <bool r_main_only>
9295 void move_assign(basic_reference<r_main_only>&& r) {
9296 if (valid()) {
9297 deref();
9298 }
9299 if (r.ref == LUA_REFNIL) {
9300 luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state());
9301 ref = LUA_REFNIL;
9302 return;
9303 }
9304 if (r.ref == LUA_NOREF) {
9305 luastate = r.luastate;
9306 ref = LUA_NOREF;
9307 return;
9308 }
9309 if (detail::xmovable(lua_state(), r.lua_state())) {
9310 r.push(lua_state());
9311 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
9312 return;
9313 }
9314
9315 luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state());
9316 ref = r.ref;
9317 r.ref = LUA_NOREF;
9318 r.luastate = nullptr;
9319 }
9320
9321 protected:
9322 basic_reference(lua_State* L, detail::global_tag) noexcept
9323 : basic_reference(detail::pick_main_thread<main_only>(L, L), detail::global_, detail::global_) {
9324 }
9325
9326 basic_reference(lua_State* L, detail::global_tag, detail::global_tag) noexcept : stateless_reference(L, detail::global_), luastate(L) {
9327 }
9328
9329 basic_reference(lua_State* oL, const basic_reference<!main_only>& o) noexcept : stateless_reference(oL, o), luastate(oL) {
9330 }
9331
9332 void deref() const noexcept {
9333 return stateless_reference::deref(lua_state());
9334 }
9335
9336 int copy() const noexcept {
9337 return copy(lua_state());
9338 }
9339
9340 int copy(lua_State* L) const noexcept {
9341 return stateless_reference::copy(L);
9342 }
9343
9344 public:
9345 basic_reference() noexcept = default;
9346 basic_reference(lua_nil_t) noexcept : basic_reference() {
9347 }
9348 basic_reference(const stack_reference& r) noexcept : basic_reference(r.lua_state(), r.stack_index()) {
9349 }
9350 basic_reference(stack_reference&& r) noexcept : basic_reference(r.lua_state(), r.stack_index()) {
9351 }
9352 template <bool r_main_only>
9353 basic_reference(lua_State* L, const basic_reference<r_main_only>& r) noexcept : luastate(detail::pick_main_thread<main_only>(L, L)) {
9354 if (r.ref == LUA_REFNIL) {
9355 ref = LUA_REFNIL;
9356 return;
9357 }
9358 if (r.ref == LUA_NOREF || lua_state() == nullptr) {
9359 ref = LUA_NOREF;
9360 return;
9361 }
9362 if (detail::xmovable(lua_state(), r.lua_state())) {
9363 r.push(lua_state());
9364 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
9365 return;
9366 }
9367 ref = r.copy();
9368 }
9369
9370 template <bool r_main_only>
9371 basic_reference(lua_State* L, basic_reference<r_main_only>&& r) noexcept : luastate(detail::pick_main_thread<main_only>(L, L)) {
9372 if (r.ref == LUA_REFNIL) {
9373 ref = LUA_REFNIL;
9374 return;
9375 }
9376 if (r.ref == LUA_NOREF || lua_state() == nullptr) {
9377 ref = LUA_NOREF;
9378 return;
9379 }
9380 if (detail::xmovable(lua_state(), r.lua_state())) {
9381 r.push(lua_state());
9382 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
9383 return;
9384 }
9385 ref = r.ref;
9386 r.ref = LUA_NOREF;
9387 r.luastate = nullptr;
9388 }
9389
9390 basic_reference(lua_State* L, const stack_reference& r) noexcept : luastate(detail::pick_main_thread<main_only>(L, L)) {
9391 if (lua_state() == nullptr || r.lua_state() == nullptr || r.get_type() == type::none) {
9392 ref = LUA_NOREF;
9393 return;
9394 }
9395 if (r.get_type() == type::lua_nil) {
9396 ref = LUA_REFNIL;
9397 return;
9398 }
9399 if (lua_state() != r.lua_state() && !detail::xmovable(lua_state(), r.lua_state())) {
9400 return;
9401 }
9402 r.push(lua_state());
9403 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
9404 }
9405 basic_reference(lua_State* L, int index = -1) noexcept : luastate(detail::pick_main_thread<main_only>(L, L)) {
9406 // use L to stick with that state's execution stack
9407#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
9408 luaL_checkstack(L, 1, "not enough Lua stack space to push this reference value");
9409#endif // make sure stack doesn't overflow
9410 lua_pushvalue(L, index);
9411 ref = luaL_ref(L, LUA_REGISTRYINDEX);
9412 }
9413 basic_reference(lua_State* L, ref_index index) noexcept : luastate(detail::pick_main_thread<main_only>(L, L)) {
9414 lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, index.index);
9415 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
9416 }
9417 basic_reference(lua_State* L, lua_nil_t) noexcept : luastate(detail::pick_main_thread<main_only>(L, L)) {
9418 }
9419
9420 ~basic_reference() noexcept {
9421 if (lua_state() == nullptr || ref == LUA_NOREF)
9422 return;
9423 deref();
9424 }
9425
9426 basic_reference(const basic_reference& o) noexcept : stateless_reference(o.copy()), luastate(o.lua_state()) {
9427 }
9428
9429 basic_reference(basic_reference&& o) noexcept : stateless_reference(std::move(o)), luastate(o.lua_state()) {
9430 o.luastate = nullptr;
9431 }
9432
9433 basic_reference(const basic_reference<!main_only>& o) noexcept
9434 : basic_reference(detail::pick_main_thread<main_only>(o.lua_state(), o.lua_state()), o) {
9435 }
9436
9437 basic_reference(basic_reference<!main_only>&& o) noexcept
9438 : stateless_reference(std::move(o)), luastate(detail::pick_main_thread<main_only>(o.lua_state(), o.lua_state())) {
9439 o.luastate = nullptr;
9440 o.ref = LUA_NOREF;
9441 }
9442
9443 basic_reference& operator=(basic_reference&& r) noexcept {
9444 move_assign(std::move(r));
9445 return *this;
9446 }
9447
9448 basic_reference& operator=(const basic_reference& r) noexcept {
9449 copy_assign(r);
9450 return *this;
9451 }
9452
9453 basic_reference& operator=(basic_reference<!main_only>&& r) noexcept {
9454 move_assign(std::move(r));
9455 return *this;
9456 }
9457
9458 basic_reference& operator=(const basic_reference<!main_only>& r) noexcept {
9459 copy_assign(r);
9460 return *this;
9461 }
9462
9463 basic_reference& operator=(const lua_nil_t&) noexcept {
9464 if (valid()) {
9465 deref();
9466 }
9467 luastate = nullptr;
9468 ref = LUA_NOREF;
9469 return *this;
9470 }
9471
9472 template <typename Super>
9473 basic_reference& operator=(proxy_base<Super>&& r);
9474
9475 template <typename Super>
9476 basic_reference& operator=(const proxy_base<Super>& r);
9477
9478 int push() const noexcept {
9479 return push(lua_state());
9480 }
9481
9482 int push(lua_State* L) const noexcept {
9483#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
9484 luaL_checkstack(L, 1, "not enough Lua stack space to push this reference value");
9485#endif // make sure stack doesn't overflow
9486 if (lua_state() == nullptr) {
9487 lua_pushnil(L);
9488 return 1;
9489 }
9490 lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, ref);
9491 if (L != lua_state()) {
9492 lua_xmove(lua_state(), L, 1);
9493 }
9494 return 1;
9495 }
9496
9497 void pop() const noexcept {
9498 pop(lua_state());
9499 }
9500
9501 void pop(lua_State* L, int n = 1) const noexcept {
9502 stateless_reference::pop(L, n);
9503 }
9504
9505 int registry_index() const noexcept {
9506 return stateless_reference::registry_index();
9507 }
9508
9509 bool valid() const noexcept {
9510 return stateless_reference::valid(lua_state());
9511 }
9512
9513 const void* pointer() const noexcept {
9514 return stateless_reference::pointer(lua_state());
9515 }
9516
9517 explicit operator bool() const noexcept {
9518 return valid();
9519 }
9520
9521 type get_type() const noexcept {
9522 return stateless_reference::get_type(lua_state());
9523 }
9524
9525 lua_State* lua_state() const noexcept {
9526 return luastate;
9527 }
9528 };
9529
9530 template <bool lb, bool rb>
9531 inline bool operator==(const basic_reference<lb>& l, const basic_reference<rb>& r) {
9532 auto ppl = stack::push_pop(l);
9533 auto ppr = stack::push_pop(r);
9534 return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1;
9535 }
9536
9537 template <bool lb, bool rb>
9538 inline bool operator!=(const basic_reference<lb>& l, const basic_reference<rb>& r) {
9539 return !operator==(l, r);
9540 }
9541
9542 template <bool lb>
9543 inline bool operator==(const basic_reference<lb>& l, const stack_reference& r) {
9544 auto ppl = stack::push_pop(l);
9545 return lua_compare(l.lua_state(), -1, r.stack_index(), LUA_OPEQ) == 1;
9546 }
9547
9548 template <bool lb>
9549 inline bool operator!=(const basic_reference<lb>& l, const stack_reference& r) {
9550 return !operator==(l, r);
9551 }
9552
9553 template <bool rb>
9554 inline bool operator==(const stack_reference& l, const basic_reference<rb>& r) {
9555 auto ppr = stack::push_pop(r);
9556 return lua_compare(l.lua_state(), -1, r.stack_index(), LUA_OPEQ) == 1;
9557 }
9558
9559 template <bool rb>
9560 inline bool operator!=(const stack_reference& l, const basic_reference<rb>& r) {
9561 return !operator==(l, r);
9562 }
9563
9564 template <bool lb>
9565 inline bool operator==(const basic_reference<lb>& lhs, const lua_nil_t&) {
9566 return !lhs.valid();
9567 }
9568
9569 template <bool rb>
9570 inline bool operator==(const lua_nil_t&, const basic_reference<rb>& rhs) {
9571 return !rhs.valid();
9572 }
9573
9574 template <bool lb>
9575 inline bool operator!=(const basic_reference<lb>& lhs, const lua_nil_t&) {
9576 return lhs.valid();
9577 }
9578
9579 template <bool rb>
9580 inline bool operator!=(const lua_nil_t&, const basic_reference<rb>& rhs) {
9581 return rhs.valid();
9582 }
9583
9584 struct reference_equals : public stack_reference_equals {
9585 template <bool rb>
9586 bool operator()(const lua_nil_t& lhs, const basic_reference<rb>& rhs) const {
9587 return lhs == rhs;
9588 }
9589
9590 template <bool lb>
9591 bool operator()(const basic_reference<lb>& lhs, const lua_nil_t& rhs) const {
9592 return lhs == rhs;
9593 }
9594
9595 template <bool lb, bool rb>
9596 bool operator()(const basic_reference<lb>& lhs, const basic_reference<rb>& rhs) const {
9597 return lhs == rhs;
9598 }
9599
9600 template <bool lb>
9601 bool operator()(const basic_reference<lb>& lhs, const stack_reference& rhs) const {
9602 return lhs == rhs;
9603 }
9604
9605 template <bool rb>
9606 bool operator()(const stack_reference& lhs, const basic_reference<rb>& rhs) const {
9607 return lhs == rhs;
9608 }
9609 };
9610
9611 struct reference_hash : public stack_reference_hash {
9612 typedef reference argument_type;
9613 typedef std::size_t result_type;
9614
9615 template <bool lb>
9616 result_type operator()(const basic_reference<lb>& lhs) const {
9617 std::hash<const void*> h;
9618 return h(lhs.pointer());
9619 }
9620 };
9621} // namespace sol
9622
9623// end of sol/reference.hpp
9624
9625// beginning of sol/tie.hpp
9626
9627namespace sol {
9628
9629 namespace detail {
9630 template <typename T>
9631 struct is_speshul : std::false_type {};
9632 } // namespace detail
9633
9634 template <typename T>
9635 struct tie_size : std::tuple_size<T> {};
9636
9637 template <typename T>
9638 struct is_tieable : std::integral_constant<bool, (::sol::tie_size<T>::value > 0)> {};
9639
9640 template <typename... Tn>
9641 struct tie_t : public std::tuple<std::add_lvalue_reference_t<Tn>...> {
9642 private:
9643 typedef std::tuple<std::add_lvalue_reference_t<Tn>...> base_t;
9644
9645 template <typename T>
9646 void set(std::false_type, T&& target) {
9647 std::get<0>(*this) = std::forward<T>(target);
9648 }
9649
9650 template <typename T>
9651 void set(std::true_type, T&& target) {
9652 typedef tie_size<meta::unqualified_t<T>> value_size;
9653 typedef tie_size<std::tuple<Tn...>> tie_size;
9654 typedef meta::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size;
9655 typedef std::make_index_sequence<indices_size::value> indices;
9656 set_extra(detail::is_speshul<meta::unqualified_t<T>>(), indices(), std::forward<T>(target));
9657 }
9658
9659 template <std::size_t... I, typename T>
9660 void set_extra(std::true_type, std::index_sequence<I...>, T&& target) {
9661 using std::get;
9662 (void)detail::swallow{0,
9663 (get<I>(static_cast<base_t&>(*this)) = get<I>(types<Tn...>(), target), 0)..., 0};
9664 }
9665
9666 template <std::size_t... I, typename T>
9667 void set_extra(std::false_type, std::index_sequence<I...>, T&& target) {
9668 using std::get;
9669 (void)detail::swallow{0,
9670 (get<I>(static_cast<base_t&>(*this)) = get<I>(target), 0)..., 0};
9671 }
9672
9673 public:
9674 using base_t::base_t;
9675
9676 template <typename T>
9677 tie_t& operator=(T&& value) {
9678 typedef is_tieable<meta::unqualified_t<T>> tieable;
9679 set(tieable(), std::forward<T>(value));
9680 return *this;
9681 }
9682 };
9683
9684 template <typename... Tn>
9685 struct tie_size<tie_t<Tn...>> : std::tuple_size<std::tuple<Tn...>> {};
9686
9687 namespace adl_barrier_detail {
9688 template <typename... Tn>
9689 inline tie_t<std::remove_reference_t<Tn>...> tie(Tn&&... argn) {
9690 return tie_t<std::remove_reference_t<Tn>...>(std::forward<Tn>(argn)...);
9691 }
9692 } // namespace adl_barrier_detail
9693
9694 using namespace adl_barrier_detail;
9695
9696} // namespace sol
9697
9698// end of sol/tie.hpp
9699
9700// beginning of sol/stack_guard.hpp
9701
9702#include <functional>
9703
9704namespace sol {
9705 namespace detail {
9706 inline void stack_fail(int, int) {
9707#if !(defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS)
9708 throw error(detail::direct_error, "imbalanced stack after operation finish");
9709#else
9710 // Lol, what do you want, an error printout? :3c
9711 // There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so
9712 // hopefully someone will register their own stack_fail thing for the `fx` parameter of stack_guard.
9713#endif // No Exceptions
9714 }
9715 } // namespace detail
9716
9717 struct stack_guard {
9718 lua_State* L;
9719 int top;
9720 std::function<void(int, int)> on_mismatch;
9721
9722 stack_guard(lua_State* L) : stack_guard(L, lua_gettop(L)) {
9723 }
9724 stack_guard(lua_State* L, int top, std::function<void(int, int)> fx = detail::stack_fail) : L(L), top(top), on_mismatch(std::move(fx)) {
9725 }
9726 bool check_stack(int modification = 0) const {
9727 int bottom = lua_gettop(L) + modification;
9728 if (top == bottom) {
9729 return true;
9730 }
9731 on_mismatch(top, bottom);
9732 return false;
9733 }
9734 ~stack_guard() {
9735 check_stack();
9736 }
9737 };
9738} // namespace sol
9739
9740// end of sol/stack_guard.hpp
9741
9742#include <vector>
9743#include <bitset>
9744#include <forward_list>
9745#include <string>
9746#include <algorithm>
9747#include <sstream>
9748#include <optional>
9749
9750namespace sol {
9751 namespace detail {
9752 struct with_function_tag { };
9753 struct as_reference_tag { };
9754 template <typename T>
9755 struct as_pointer_tag { };
9756 template <typename T>
9757 struct as_value_tag { };
9758 template <typename T>
9759 struct as_unique_tag { };
9760 template <typename T>
9761 struct as_table_tag { };
9762
9763 using lua_reg_table = luaL_Reg[64];
9764
9765 using unique_destructor = void (*)(void*);
9766 using unique_tag = detail::inheritance_unique_cast_function;
9767
9768 inline void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space, std::size_t& required_space) {
9769 // this handels arbitrary alignments...
9770 // make this into a power-of-2-only?
9771 // actually can't: this is a C++14-compatible framework,
9772 // power of 2 alignment is C++17
9773 std::uintptr_t initial = reinterpret_cast<std::uintptr_t>(ptr);
9774 std::uintptr_t offby = static_cast<std::uintptr_t>(initial % alignment);
9775 std::uintptr_t padding = (alignment - offby) % alignment;
9776 required_space += size + padding;
9777 if (space < required_space) {
9778 return nullptr;
9779 }
9780 ptr = static_cast<void*>(static_cast<char*>(ptr) + padding);
9781 space -= padding;
9782 return ptr;
9783 }
9784
9785 inline void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space) {
9786 std::size_t required_space = 0;
9787 return align(alignment, size, ptr, space, required_space);
9788 }
9789
9790 inline void align_one(std::size_t a, std::size_t s, void*& target_alignment) {
9791 std::size_t space = (std::numeric_limits<std::size_t>::max)();
9792 target_alignment = align(a, s, target_alignment, space);
9793 target_alignment = static_cast<void*>(static_cast<char*>(target_alignment) + s);
9794 }
9795
9796 template <typename... Args>
9797 std::size_t aligned_space_for(void* alignment = nullptr) {
9798 // use temporary storage to prevent strict UB shenanigans
9799 char alignment_shim[(std::max)({ sizeof(Args)... }) + (std::max)({ alignof(Args)... })] {};
9800 char* start = alignment == nullptr ? static_cast<char*>(alignment) : alignment_shim;
9801 (void)detail::swallow { int {}, (align_one(std::alignment_of_v<Args>, sizeof(Args), alignment), int {})... };
9802 return static_cast<char*>(alignment) - start;
9803 }
9804
9805 inline void* align_usertype_pointer(void* ptr) {
9806 using use_align = std::integral_constant<bool,
9807#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
9808 false
9809#else
9810 (std::alignment_of<void*>::value > 1)
9811#endif
9812 >;
9813 if (!use_align::value) {
9814 return ptr;
9815 }
9816 std::size_t space = (std::numeric_limits<std::size_t>::max)();
9817 return align(std::alignment_of<void*>::value, sizeof(void*), ptr, space);
9818 }
9819
9820 template <bool pre_aligned = false, bool pre_shifted = false>
9821 void* align_usertype_unique_destructor(void* ptr) {
9822 using use_align = std::integral_constant<bool,
9823#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
9824 false
9825#else
9826 (std::alignment_of<unique_destructor>::value > 1)
9827#endif
9828 >;
9829 if (!pre_aligned) {
9830 ptr = align_usertype_pointer(ptr);
9831 }
9832 if (!pre_shifted) {
9833 ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(void*));
9834 }
9835 if (!use_align::value) {
9836 return static_cast<void*>(static_cast<void**>(ptr) + 1);
9837 }
9838 std::size_t space = (std::numeric_limits<std::size_t>::max)();
9839 return align(std::alignment_of<unique_destructor>::value, sizeof(unique_destructor), ptr, space);
9840 }
9841
9842 template <bool pre_aligned = false, bool pre_shifted = false>
9843 void* align_usertype_unique_tag(void* ptr) {
9844 using use_align = std::integral_constant<bool,
9845#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
9846 false
9847#else
9848 (std::alignment_of<unique_tag>::value > 1)
9849#endif
9850 >;
9851 if (!pre_aligned) {
9852 ptr = align_usertype_unique_destructor(ptr);
9853 }
9854 if (!pre_shifted) {
9855 ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_destructor));
9856 }
9857 if (!use_align::value) {
9858 return ptr;
9859 }
9860 std::size_t space = (std::numeric_limits<std::size_t>::max)();
9861 return align(std::alignment_of<unique_tag>::value, sizeof(unique_tag), ptr, space);
9862 }
9863
9864 template <typename T, bool pre_aligned = false, bool pre_shifted = false>
9865 void* align_usertype_unique(void* ptr) {
9866 typedef std::integral_constant<bool,
9867#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
9868 false
9869#else
9870 (std::alignment_of_v<T> > 1)
9871#endif
9872 >
9873 use_align;
9874 if (!pre_aligned) {
9875 ptr = align_usertype_unique_tag(ptr);
9876 }
9877 if (!pre_shifted) {
9878 ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_tag));
9879 }
9880 if (!use_align::value) {
9881 return ptr;
9882 }
9883 std::size_t space = (std::numeric_limits<std::size_t>::max)();
9884 return align(std::alignment_of_v<T>, sizeof(T), ptr, space);
9885 }
9886
9887 template <typename T>
9888 void* align_user(void* ptr) {
9889 typedef std::integral_constant<bool,
9890#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
9891 false
9892#else
9893 (std::alignment_of_v<T> > 1)
9894#endif
9895 >
9896 use_align;
9897 if (!use_align::value) {
9898 return ptr;
9899 }
9900 std::size_t space = (std::numeric_limits<std::size_t>::max)();
9901 return align(std::alignment_of_v<T>, sizeof(T), ptr, space);
9902 }
9903
9904 template <typename T>
9905 T** usertype_allocate_pointer(lua_State* L) {
9906 typedef std::integral_constant<bool,
9907#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
9908 false
9909#else
9910 (std::alignment_of<T*>::value > 1)
9911#endif
9912 >
9913 use_align;
9914 if (!use_align::value) {
9915 T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
9916 return pointerpointer;
9917 }
9918 static const std::size_t initial_size = aligned_space_for<T*>(nullptr);
9919 static const std::size_t misaligned_size = aligned_space_for<T*>(reinterpret_cast<void*>(0x1));
9920
9921 std::size_t allocated_size = initial_size;
9922 void* unadjusted = lua_newuserdata(L, initial_size);
9923 void* adjusted = align(std::alignment_of<T*>::value, sizeof(T*), unadjusted, allocated_size);
9924 if (adjusted == nullptr) {
9925 lua_pop(L, 1);
9926 // what kind of absolute garbage trash allocator are we dealing with?
9927 // whatever, add some padding in the case of MAXIMAL alignment waste...
9928 allocated_size = misaligned_size;
9929 unadjusted = lua_newuserdata(L, allocated_size);
9930 adjusted = align(std::alignment_of<T*>::value, sizeof(T*), unadjusted, allocated_size);
9931 if (adjusted == nullptr) {
9932 // trash allocator can burn in hell
9933 lua_pop(L, 1);
9934 // luaL_error(L, "if you are the one that wrote this allocator you should feel bad for doing a
9935 // worse job than malloc/realloc and should go read some books, yeah?");
9936 luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T*>().data());
9937 }
9938 }
9939 return static_cast<T**>(adjusted);
9940 }
9941
9942 inline bool attempt_alloc(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t value_align, std::size_t value_size,
9943 std::size_t allocated_size, void*& pointer_adjusted, void*& data_adjusted) {
9944 void* adjusted = lua_newuserdata(L, allocated_size);
9945 pointer_adjusted = align(ptr_align, ptr_size, adjusted, allocated_size);
9946 if (pointer_adjusted == nullptr) {
9947 lua_pop(L, 1);
9948 return false;
9949 }
9950 // subtract size of what we're going to allocate there
9951 allocated_size -= ptr_size;
9952 adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + ptr_size);
9953 data_adjusted = align(value_align, value_size, adjusted, allocated_size);
9954 if (data_adjusted == nullptr) {
9955 lua_pop(L, 1);
9956 return false;
9957 }
9958 return true;
9959 }
9960
9961 inline bool attempt_alloc_unique(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t real_align, std::size_t real_size,
9962 std::size_t allocated_size, void*& pointer_adjusted, void*& dx_adjusted, void*& id_adjusted, void*& data_adjusted) {
9963 void* adjusted = lua_newuserdata(L, allocated_size);
9964 pointer_adjusted = align(ptr_align, ptr_size, adjusted, allocated_size);
9965 if (pointer_adjusted == nullptr) {
9966 lua_pop(L, 1);
9967 return false;
9968 }
9969 allocated_size -= ptr_size;
9970
9971 adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + ptr_size);
9972 dx_adjusted = align(std::alignment_of_v<unique_destructor>, sizeof(unique_destructor), adjusted, allocated_size);
9973 if (dx_adjusted == nullptr) {
9974 lua_pop(L, 1);
9975 return false;
9976 }
9977 allocated_size -= sizeof(unique_destructor);
9978
9979 adjusted = static_cast<void*>(static_cast<char*>(dx_adjusted) + sizeof(unique_destructor));
9980
9981 id_adjusted = align(std::alignment_of_v<unique_tag>, sizeof(unique_tag), adjusted, allocated_size);
9982 if (id_adjusted == nullptr) {
9983 lua_pop(L, 1);
9984 return false;
9985 }
9986 allocated_size -= sizeof(unique_tag);
9987
9988 adjusted = static_cast<void*>(static_cast<char*>(id_adjusted) + sizeof(unique_tag));
9989 data_adjusted = align(real_align, real_size, adjusted, allocated_size);
9990 if (data_adjusted == nullptr) {
9991 lua_pop(L, 1);
9992 return false;
9993 }
9994 return true;
9995 }
9996
9997 template <typename T>
9998 T* usertype_allocate(lua_State* L) {
9999 typedef std::integral_constant<bool,
10000#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
10001 false
10002#else
10003 (std::alignment_of<T*>::value > 1 || std::alignment_of_v<T> > 1)
10004#endif
10005 >
10006 use_align;
10007 if (!use_align::value) {
10008 T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
10009 T*& pointerreference = *pointerpointer;
10010 T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1);
10011 pointerreference = allocationtarget;
10012 return allocationtarget;
10013 }
10014
10015 /* the assumption is that `lua_newuserdata` -- unless someone
10016 passes a specific lua_Alloc that gives us bogus, un-aligned pointers
10017 -- uses malloc, which tends to hand out more or less aligned pointers to memory
10018 (most of the time, anyhow)
10019
10020 but it's not guaranteed, so we have to do a post-adjustment check and increase padding
10021
10022 we do this preliminarily with compile-time stuff, to see
10023 if we strike lucky with the allocator and alignment values
10024
10025 otherwise, we have to re-allocate the userdata and
10026 over-allocate some space for additional padding because
10027 compilers are optimized for aligned reads/writes
10028 (and clang will barf UBsan errors on us for not being aligned)
10029 */
10030 static const std::size_t initial_size = aligned_space_for<T*, T>(nullptr);
10031 static const std::size_t misaligned_size = aligned_space_for<T*, T>(reinterpret_cast<void*>(0x1));
10032
10033 void* pointer_adjusted;
10034 void* data_adjusted;
10035 bool result
10036 = attempt_alloc(L, std::alignment_of_v<T*>, sizeof(T*), std::alignment_of_v<T>, sizeof(T), initial_size, pointer_adjusted, data_adjusted);
10037 if (!result) {
10038 // we're likely to get something that fails to perform the proper allocation a second time,
10039 // so we use the suggested_new_size bump to help us out here
10040 pointer_adjusted = nullptr;
10041 data_adjusted = nullptr;
10042 result = attempt_alloc(
10043 L, std::alignment_of_v<T*>, sizeof(T*), std::alignment_of_v<T>, sizeof(T), misaligned_size, pointer_adjusted, data_adjusted);
10044 if (!result) {
10045 if (pointer_adjusted == nullptr) {
10046 luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str());
10047 }
10048 else {
10049 luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str());
10050 }
10051 return nullptr;
10052 }
10053 }
10054
10055 T** pointerpointer = reinterpret_cast<T**>(pointer_adjusted);
10056 T*& pointerreference = *pointerpointer;
10057 T* allocationtarget = reinterpret_cast<T*>(data_adjusted);
10058 pointerreference = allocationtarget;
10059 return allocationtarget;
10060 }
10061
10062 template <typename T, typename Real>
10063 Real* usertype_unique_allocate(lua_State* L, T**& pref, unique_destructor*& dx, unique_tag*& id) {
10064 typedef std::integral_constant<bool,
10065#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
10066 false
10067#else
10068 (std::alignment_of<T*>::value > 1 || std::alignment_of<unique_tag>::value > 1 || std::alignment_of<unique_destructor>::value > 1
10069 || std::alignment_of<Real>::value > 1)
10070#endif
10071 >
10072 use_align;
10073 if (!use_align::value) {
10074 pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(detail::unique_destructor) + sizeof(unique_tag) + sizeof(Real)));
10075 dx = static_cast<detail::unique_destructor*>(static_cast<void*>(pref + 1));
10076 id = static_cast<unique_tag*>(static_cast<void*>(dx + 1));
10077 Real* mem = static_cast<Real*>(static_cast<void*>(id + 1));
10078 return mem;
10079 }
10080
10081 static const std::size_t initial_size = aligned_space_for<T*, unique_destructor, unique_tag, Real>(nullptr);
10082 static const std::size_t misaligned_size = aligned_space_for<T*, unique_destructor, unique_tag, Real>(reinterpret_cast<void*>(0x1));
10083
10084 void* pointer_adjusted;
10085 void* dx_adjusted;
10086 void* id_adjusted;
10087 void* data_adjusted;
10088 bool result = attempt_alloc_unique(L,
10089 std::alignment_of_v<T*>,
10090 sizeof(T*),
10091 std::alignment_of_v<Real>,
10092 sizeof(Real),
10093 initial_size,
10094 pointer_adjusted,
10095 dx_adjusted,
10096 id_adjusted,
10097 data_adjusted);
10098 if (!result) {
10099 // we're likely to get something that fails to perform the proper allocation a second time,
10100 // so we use the suggested_new_size bump to help us out here
10101 pointer_adjusted = nullptr;
10102 dx_adjusted = nullptr;
10103 id_adjusted = nullptr;
10104 data_adjusted = nullptr;
10105 result = attempt_alloc_unique(L,
10106 std::alignment_of_v<T*>,
10107 sizeof(T*),
10108 std::alignment_of_v<Real>,
10109 sizeof(Real),
10110 misaligned_size,
10111 pointer_adjusted,
10112 dx_adjusted,
10113 id_adjusted,
10114 data_adjusted);
10115 if (!result) {
10116 if (pointer_adjusted == nullptr) {
10117 luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str());
10118 }
10119 else if (dx_adjusted == nullptr) {
10120 luaL_error(L, "aligned allocation of userdata block (deleter section) for '%s' failed", detail::demangle<T>().c_str());
10121 }
10122 else {
10123 luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str());
10124 }
10125 return nullptr;
10126 }
10127 }
10128
10129 pref = static_cast<T**>(pointer_adjusted);
10130 dx = static_cast<detail::unique_destructor*>(dx_adjusted);
10131 id = static_cast<unique_tag*>(id_adjusted);
10132 Real* mem = static_cast<Real*>(data_adjusted);
10133 return mem;
10134 }
10135
10136 template <typename T>
10137 T* user_allocate(lua_State* L) {
10138 typedef std::integral_constant<bool,
10139#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
10140 false
10141#else
10142 (std::alignment_of_v<T> > 1)
10143#endif
10144 >
10145 use_align;
10146 if (!use_align::value) {
10147 T* pointer = static_cast<T*>(lua_newuserdata(L, sizeof(T)));
10148 return pointer;
10149 }
10150
10151 static const std::size_t initial_size = aligned_space_for<T>(nullptr);
10152 static const std::size_t misaligned_size = aligned_space_for<T>(reinterpret_cast<void*>(0x1));
10153
10154 std::size_t allocated_size = initial_size;
10155 void* unadjusted = lua_newuserdata(L, allocated_size);
10156 void* adjusted = align(std::alignment_of_v<T>, sizeof(T), unadjusted, allocated_size);
10157 if (adjusted == nullptr) {
10158 lua_pop(L, 1);
10159 // try again, add extra space for alignment padding
10160 allocated_size = misaligned_size;
10161 unadjusted = lua_newuserdata(L, allocated_size);
10162 adjusted = align(std::alignment_of_v<T>, sizeof(T), unadjusted, allocated_size);
10163 if (adjusted == nullptr) {
10164 lua_pop(L, 1);
10165 luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T>().data());
10166 }
10167 }
10168 return static_cast<T*>(adjusted);
10169 }
10170
10171 template <typename T>
10172 int usertype_alloc_destruct(lua_State* L) {
10173 void* memory = lua_touserdata(L, 1);
10174 memory = align_usertype_pointer(memory);
10175 T** pdata = static_cast<T**>(memory);
10176 T* data = *pdata;
10177 std::allocator<T> alloc {};
10178 std::allocator_traits<std::allocator<T>>::destroy(alloc, data);
10179 return 0;
10180 }
10181
10182 template <typename T>
10183 int unique_destruct(lua_State* L) {
10184 void* memory = lua_touserdata(L, 1);
10185 memory = align_usertype_unique_destructor(memory);
10186 unique_destructor& dx = *static_cast<unique_destructor*>(memory);
10187 memory = align_usertype_unique_tag<true>(memory);
10188 (dx)(memory);
10189 return 0;
10190 }
10191
10192 template <typename T>
10193 int user_alloc_destruct(lua_State* L) {
10194 void* memory = lua_touserdata(L, 1);
10195 memory = align_user<T>(memory);
10196 T* data = static_cast<T*>(memory);
10197 std::allocator<T> alloc;
10198 std::allocator_traits<std::allocator<T>>::destroy(alloc, data);
10199 return 0;
10200 }
10201
10202 template <typename T, typename Real>
10203 void usertype_unique_alloc_destroy(void* memory) {
10204 memory = align_usertype_unique<Real, true>(memory);
10205 Real* target = static_cast<Real*>(memory);
10206 std::allocator<Real> alloc;
10207 std::allocator_traits<std::allocator<Real>>::destroy(alloc, target);
10208 }
10209
10210 template <typename T>
10211 int cannot_destruct(lua_State* L) {
10212 return luaL_error(L,
10213 "cannot call the destructor for '%s': it is either hidden (protected/private) or removed with '= "
10214 "delete' and thusly this type is being destroyed without properly destructing, invoking undefined "
10215 "behavior: please bind a usertype and specify a custom destructor to define the behavior properly",
10216 detail::demangle<T>().data());
10217 }
10218
10219 template <typename T>
10220 void reserve(T&, std::size_t) {
10221 }
10222
10223 template <typename T, typename Al>
10224 void reserve(std::vector<T, Al>& vec, std::size_t hint) {
10225 vec.reserve(hint);
10226 }
10227
10228 template <typename T, typename Tr, typename Al>
10229 void reserve(std::basic_string<T, Tr, Al>& str, std::size_t hint) {
10230 str.reserve(hint);
10231 }
10232
10233 inline bool property_always_true(meta_function) {
10234 return true;
10235 }
10236
10237 struct properties_enrollment_allowed {
10238 int& times_through;
10239 std::bitset<64>& properties;
10240 automagic_enrollments& enrollments;
10241
10242 properties_enrollment_allowed(int& times, std::bitset<64>& props, automagic_enrollments& enroll)
10243 : times_through(times), properties(props), enrollments(enroll) {
10244 }
10245
10246 bool operator()(meta_function mf) const {
10247 bool p = properties[static_cast<int>(mf)];
10248 if (times_through > 0) {
10249 return p;
10250 }
10251 switch (mf) {
10252 case meta_function::length:
10253 return enrollments.length_operator && !p;
10254 case meta_function::pairs:
10255 return enrollments.pairs_operator && !p;
10256 case meta_function::call:
10257 return enrollments.call_operator && !p;
10258 case meta_function::less_than:
10259 return enrollments.less_than_operator && !p;
10260 case meta_function::less_than_or_equal_to:
10261 return enrollments.less_than_or_equal_to_operator && !p;
10262 case meta_function::equal_to:
10263 return enrollments.equal_to_operator && !p;
10264 default:
10265 break;
10266 }
10267 return !p;
10268 }
10269 };
10270
10271 struct indexed_insert {
10272 lua_reg_table& l;
10273 int& index;
10274
10275 indexed_insert(lua_reg_table& cont, int& idx) : l(cont), index(idx) {
10276 }
10277 void operator()(meta_function mf, lua_CFunction f) {
10278 l[index] = luaL_Reg { to_string(mf).c_str(), f };
10279 ++index;
10280 }
10281 };
10282 } // namespace detail
10283
10284 namespace stack {
10285
10286 template <typename T, bool global = false, bool raw = false, typename = void>
10287 struct field_getter;
10288 template <typename T, typename P, bool global = false, bool raw = false, typename = void>
10289 struct probe_field_getter;
10290
10291 template <typename T, bool global = false, bool raw = false, typename = void>
10292 struct field_setter;
10293
10294 template <typename T, typename = void>
10295 struct unqualified_getter;
10296 template <typename T, typename = void>
10297 struct qualified_getter;
10298
10299 template <typename T, typename = void>
10300 struct qualified_interop_getter;
10301 template <typename T, typename = void>
10302 struct unqualified_interop_getter;
10303
10304 template <typename T, typename = void>
10305 struct popper;
10306
10307 template <typename T, typename = void>
10308 struct unqualified_pusher;
10309
10310 template <typename T, type t, typename = void>
10311 struct unqualified_checker;
10312 template <typename T, type t, typename = void>
10313 struct qualified_checker;
10314
10315 template <typename T, typename = void>
10316 struct unqualified_check_getter;
10317 template <typename T, typename = void>
10318 struct qualified_check_getter;
10319
10320 struct probe {
10321 bool success;
10322 int levels;
10323
10324 probe(bool s, int l) : success(s), levels(l) {
10325 }
10326
10327 operator bool() const {
10328 return success;
10329 };
10330 };
10331
10332 struct record {
10333 int last;
10334 int used;
10335
10336 record() noexcept : last(), used() {
10337 }
10338 void use(int count) noexcept {
10339 last = count;
10340 used += count;
10341 }
10342 };
10343
10344 namespace stack_detail {
10345 template <typename Function>
10346 Function* get_function_pointer(lua_State*, int, record&) noexcept;
10347 template <typename Function, typename Handler>
10348 bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept;
10349 } // namespace stack_detail
10350
10351 } // namespace stack
10352
10353 namespace meta { namespace meta_detail {
10354
10355 template <typename T>
10356 using adl_sol_lua_get_test_t = decltype(sol_lua_get(types<T>(), static_cast<lua_State*>(nullptr), -1, std::declval<stack::record&>()));
10357
10358 template <typename T>
10359 using adl_sol_lua_interop_get_test_t
10360 = decltype(sol_lua_interop_get(types<T>(), static_cast<lua_State*>(nullptr), -1, static_cast<void*>(nullptr), std::declval<stack::record&>()));
10361
10362 template <typename T>
10363 using adl_sol_lua_check_test_t = decltype(sol_lua_check(types<T>(), static_cast<lua_State*>(nullptr), -1, no_panic, std::declval<stack::record&>()));
10364
10365 template <typename T>
10366 using adl_sol_lua_interop_check_test_t
10367 = decltype(sol_lua_interop_check(types<T>(), static_cast<lua_State*>(nullptr), -1, type::none, no_panic, std::declval<stack::record&>()));
10368
10369 template <typename T>
10370 using adl_sol_lua_check_get_test_t
10371 = decltype(sol_lua_check_get(types<T>(), static_cast<lua_State*>(nullptr), -1, no_panic, std::declval<stack::record&>()));
10372
10373 template <typename... Args>
10374 using adl_sol_lua_push_test_t = decltype(sol_lua_push(static_cast<lua_State*>(nullptr), std::declval<Args>()...));
10375
10376 template <typename T, typename... Args>
10377 using adl_sol_lua_push_exact_test_t = decltype(sol_lua_push(types<T>(), static_cast<lua_State*>(nullptr), std::declval<Args>()...));
10378
10379 template <typename T>
10380 inline constexpr bool is_adl_sol_lua_get_v = meta::is_detected_v<adl_sol_lua_get_test_t, T>;
10381
10382 template <typename T>
10383 inline constexpr bool is_adl_sol_lua_interop_get_v = meta::is_detected_v<adl_sol_lua_interop_get_test_t, T>;
10384
10385 template <typename T>
10386 inline constexpr bool is_adl_sol_lua_check_v = meta::is_detected_v<adl_sol_lua_check_test_t, T>;
10387
10388 template <typename T>
10389 inline constexpr bool is_adl_sol_lua_interop_check_v = meta::is_detected_v<adl_sol_lua_interop_check_test_t, T>;
10390
10391 template <typename T>
10392 inline constexpr bool is_adl_sol_lua_check_get_v = meta::is_detected_v<adl_sol_lua_check_get_test_t, T>;
10393
10394 template <typename... Args>
10395 inline constexpr bool is_adl_sol_lua_push_v = meta::is_detected_v<adl_sol_lua_push_test_t, Args...>;
10396
10397 template <typename T, typename... Args>
10398 inline constexpr bool is_adl_sol_lua_push_exact_v = meta::is_detected_v<adl_sol_lua_push_exact_test_t, T, Args...>;
10399 }} // namespace meta::meta_detail
10400
10401 namespace stack {
10402 namespace stack_detail {
10403 constexpr const char* not_enough_stack_space = "not enough space left on Lua stack";
10404 constexpr const char* not_enough_stack_space_floating = "not enough space left on Lua stack for a floating point number";
10405 constexpr const char* not_enough_stack_space_integral = "not enough space left on Lua stack for an integral number";
10406 constexpr const char* not_enough_stack_space_string = "not enough space left on Lua stack for a string";
10407 constexpr const char* not_enough_stack_space_meta_function_name = "not enough space left on Lua stack for the name of a meta_function";
10408 constexpr const char* not_enough_stack_space_userdata = "not enough space left on Lua stack to create a sol3 userdata";
10409 constexpr const char* not_enough_stack_space_generic = "not enough space left on Lua stack to push valuees";
10410 constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment";
10411
10412 template <typename T>
10413 struct strip {
10414 typedef T type;
10415 };
10416 template <typename T>
10417 struct strip<std::reference_wrapper<T>> {
10418 typedef T& type;
10419 };
10420 template <typename T>
10421 struct strip<user<T>> {
10422 typedef T& type;
10423 };
10424 template <typename T>
10425 struct strip<non_null<T>> {
10426 typedef T type;
10427 };
10428 template <typename T>
10429 using strip_t = typename strip<T>::type;
10430
10431 template <typename C>
10432 static int get_size_hint(C& c) {
10433 return static_cast<int>(c.size());
10434 }
10435
10436 template <typename V, typename Al>
10437 static int get_size_hint(const std::forward_list<V, Al>&) {
10438 // forward_list makes me sad
10439 return static_cast<int>(32);
10440 }
10441
10442 template <typename T>
10443 decltype(auto) unchecked_unqualified_get(lua_State* L, int index, record& tracking) {
10444 using Tu = meta::unqualified_t<T>;
10445 if constexpr (meta::meta_detail::is_adl_sol_lua_get_v<Tu>) {
10446 return sol_lua_get(types<Tu>(), L, index, tracking);
10447 }
10448 else {
10449 unqualified_getter<Tu> g {};
10450 (void)g;
10451 return g.get(L, index, tracking);
10452 }
10453 }
10454
10455 template <typename T>
10456 decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) {
10457 if constexpr (meta::meta_detail::is_adl_sol_lua_get_v<T>) {
10458 return sol_lua_get(types<T>(), L, index, tracking);
10459 }
10460 else {
10461 qualified_getter<T> g {};
10462 (void)g;
10463 return g.get(L, index, tracking);
10464 }
10465 }
10466
10467 template <typename T>
10468 decltype(auto) unqualified_interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
10469 using Tu = meta::unqualified_t<T>;
10470 if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<Tu>) {
10471 return sol_lua_interop_get(types<Tu>(), L, index, unadjusted_pointer, tracking);
10472 }
10473 else {
10474 (void)L;
10475 (void)index;
10476 (void)unadjusted_pointer;
10477 (void)tracking;
10478 using Ti = stack_detail::strip_t<Tu>;
10479 return std::pair<bool, Ti*> { false, nullptr };
10480 }
10481 }
10482
10483 template <typename T>
10484 decltype(auto) interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
10485 if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<T>) {
10486 return sol_lua_interop_get(types<T>(), L, index, unadjusted_pointer, tracking);
10487 }
10488 else {
10489 return unqualified_interop_get<T>(L, index, unadjusted_pointer, tracking);
10490 }
10491 }
10492
10493 template <typename T, typename Handler>
10494 bool unqualified_interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
10495 using Tu = meta::unqualified_t<T>;
10496 if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<Tu>) {
10497 return sol_lua_interop_check(types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking);
10498 }
10499 else {
10500 (void)L;
10501 (void)index;
10502 (void)index_type;
10503 (void)handler;
10504 (void)tracking;
10505 return false;
10506 }
10507 }
10508
10509 template <typename T, typename Handler>
10510 bool interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
10511 if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<T>) {
10512 return sol_lua_interop_check(types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking);
10513 }
10514 else {
10515 return unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking);
10516 }
10517 }
10518
10519 using undefined_method_func = void (*)(stack_reference);
10520
10521 struct undefined_metatable {
10522 lua_State* L;
10523 const char* key;
10524 undefined_method_func on_new_table;
10525
10526 undefined_metatable(lua_State* l, const char* k, undefined_method_func umf) : L(l), key(k), on_new_table(umf) {
10527 }
10528
10529 void operator()() const {
10530 if (luaL_newmetatable(L, key) == 1) {
10531 on_new_table(stack_reference(L, -1));
10532 }
10533 lua_setmetatable(L, -2);
10534 }
10535 };
10536 } // namespace stack_detail
10537
10538 inline bool maybe_indexable(lua_State* L, int index = -1) {
10539 type t = type_of(L, index);
10540 return t == type::userdata || t == type::table;
10541 }
10542
10543 inline int top(lua_State* L) {
10544 return lua_gettop(L);
10545 }
10546
10547 inline bool is_main_thread(lua_State* L) {
10548 int ismainthread = lua_pushthread(L);
10549 lua_pop(L, 1);
10550 return ismainthread == 1;
10551 }
10552
10553 inline void coroutine_create_guard(lua_State* L) {
10554 if (is_main_thread(L)) {
10555 return;
10556 }
10557 int stacksize = lua_gettop(L);
10558 if (stacksize < 1) {
10559 return;
10560 }
10561 if (type_of(L, 1) != type::function) {
10562 return;
10563 }
10564 // well now we're screwed...
10565 // we can clean the stack and pray it doesn't destroy anything?
10566 lua_pop(L, stacksize);
10567 }
10568
10569 inline void clear(lua_State* L, int table_index) {
10570 lua_pushnil(L);
10571 while (lua_next(L, table_index) != 0) {
10572 // remove value
10573 lua_pop(L, 1);
10574 // duplicate key to protect form rawset
10575 lua_pushvalue(L, -1);
10576 // push new value
10577 lua_pushnil(L);
10578 // table_index%[key] = nil
10579 lua_rawset(L, table_index);
10580 }
10581 }
10582
10583 inline void clear(reference& r) {
10584 auto pp = push_pop<false>(r);
10585 int stack_index = pp.index_of(r);
10586 clear(r.lua_state(), stack_index);
10587 }
10588
10589 inline void clear(stack_reference& r) {
10590 clear(r.lua_state(), r.stack_index());
10591 }
10592
10593 template <typename T, typename... Args>
10594 int push(lua_State* L, T&& t, Args&&... args) {
10595 using Tu = meta::unqualified_t<T>;
10596 if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<T, T, Args...>) {
10597 return sol_lua_push(types<T>(), L, std::forward<T>(t), std::forward<Args>(args)...);
10598 }
10599 else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<Tu, T, Args...>) {
10600 return sol_lua_push(types<Tu>(), L, std::forward<T>(t), std::forward<Args>(args)...);
10601 }
10602 else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v<T, Args...>) {
10603 return sol_lua_push(L, std::forward<T>(t), std::forward<Args>(args)...);
10604 }
10605 else {
10606 unqualified_pusher<Tu> p {};
10607 (void)p;
10608 return p.push(L, std::forward<T>(t), std::forward<Args>(args)...);
10609 }
10610 }
10611
10612 // overload allows to use a pusher of a specific type, but pass in any kind of args
10613 template <typename T, typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same<T, Arg>::value>>
10614 int push(lua_State* L, Arg&& arg, Args&&... args) {
10615 using Tu = meta::unqualified_t<T>;
10616 if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<T, Arg, Args...>) {
10617 return sol_lua_push(types<T>(), L, std::forward<Arg>(arg), std::forward<Args>(args)...);
10618 }
10619 else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<Tu, Arg, Args...>) {
10620 return sol_lua_push(types<Tu>(), L, std::forward<Arg>(arg), std::forward<Args>(args)...);
10621 }
10622 else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v<Arg, Args...>) {
10623 return sol_lua_push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
10624 }
10625 else {
10626 unqualified_pusher<Tu> p {};
10627 (void)p;
10628 return p.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
10629 }
10630 }
10631
10632 template <typename T, typename... Args>
10633 int push_userdata(lua_State* L, T&& t, Args&&... args) {
10634 using U = meta::unqualified_t<T>;
10635 using Tr = meta::conditional_t<std::is_pointer_v<U>,
10636 detail::as_pointer_tag<std::remove_pointer_t<U>>,
10637 meta::conditional_t<is_unique_usertype_v<U>, detail::as_unique_tag<U>, detail::as_value_tag<U>>>;
10638 return stack::push<Tr>(L, std::forward<T>(t), std::forward<Args>(args)...);
10639 }
10640
10641 template <typename T, typename Arg, typename... Args>
10642 int push_userdata(lua_State* L, Arg&& arg, Args&&... args) {
10643 using U = meta::unqualified_t<T>;
10644 using Tr = meta::conditional_t<std::is_pointer_v<U>,
10645 detail::as_pointer_tag<std::remove_pointer_t<U>>,
10646 meta::conditional_t<is_unique_usertype_v<U>, detail::as_unique_tag<U>, detail::as_value_tag<U>>>;
10647 return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
10648 }
10649
10650 namespace stack_detail {
10651
10652 template <typename T, typename Arg, typename... Args>
10653 int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
10654 using use_reference_tag = meta::all<std::is_lvalue_reference<T>,
10655 meta::neg<std::is_const<std::remove_reference_t<T>>>,
10656 meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
10657 meta::neg<is_unique_usertype<meta::unqualified_t<T>>>>;
10658 using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>;
10659 return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
10660 }
10661
10662 } // namespace stack_detail
10663
10664 template <typename T, typename... Args>
10665 int push_reference(lua_State* L, T&& t, Args&&... args) {
10666 return stack_detail::push_reference<T>(L, std::forward<T>(t), std::forward<Args>(args)...);
10667 }
10668
10669 template <typename T, typename Arg, typename... Args>
10670 int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
10671 return stack_detail::push_reference<T>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
10672 }
10673
10674 inline int multi_push(lua_State*) {
10675 // do nothing
10676 return 0;
10677 }
10678
10679 template <typename T, typename... Args>
10680 int multi_push(lua_State* L, T&& t, Args&&... args) {
10681 int pushcount = push(L, std::forward<T>(t));
10682 void(detail::swallow { (pushcount += stack::push(L, std::forward<Args>(args)), 0)... });
10683 return pushcount;
10684 }
10685
10686 inline int multi_push_reference(lua_State*) {
10687 // do nothing
10688 return 0;
10689 }
10690
10691 template <typename T, typename... Args>
10692 int multi_push_reference(lua_State* L, T&& t, Args&&... args) {
10693 int pushcount = push_reference(L, std::forward<T>(t));
10694 void(detail::swallow { (pushcount += stack::push_reference(L, std::forward<Args>(args)), 0)... });
10695 return pushcount;
10696 }
10697
10698 template <typename T, typename Handler>
10699 bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
10700 using Tu = meta::unqualified_t<T>;
10701 if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
10702 return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
10703 }
10704 else {
10705 unqualified_checker<Tu, lua_type_of_v<Tu>> c;
10706 // VC++ has a bad warning here: shut it up
10707 (void)c;
10708 return c.check(L, index, std::forward<Handler>(handler), tracking);
10709 }
10710 }
10711
10712 template <typename T, typename Handler>
10713 bool unqualified_check(lua_State* L, int index, Handler&& handler) {
10714 record tracking {};
10715 return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
10716 }
10717
10718 template <typename T>
10719 bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
10720 auto handler = no_panic;
10721 return unqualified_check<T>(L, index, handler);
10722 }
10723
10724 template <typename T, typename Handler>
10725 bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
10726 if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) {
10727 return sol_lua_check(types<T>(), L, index, std::forward<Handler>(handler), tracking);
10728 }
10729 else {
10730 using Tu = meta::unqualified_t<T>;
10731 qualified_checker<T, lua_type_of_v<Tu>> c;
10732 // VC++ has a bad warning here: shut it up
10733 (void)c;
10734 return c.check(L, index, std::forward<Handler>(handler), tracking);
10735 }
10736 }
10737
10738 template <typename T, typename Handler>
10739 bool check(lua_State* L, int index, Handler&& handler) {
10740 record tracking {};
10741 return check<T>(L, index, std::forward<Handler>(handler), tracking);
10742 }
10743
10744 template <typename T>
10745 bool check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
10746 auto handler = no_panic;
10747 return check<T>(L, index, handler);
10748 }
10749
10750 template <typename T, typename Handler>
10751 bool check_usertype(lua_State* L, int index, type, Handler&& handler, record& tracking) {
10752 using Tu = meta::unqualified_t<T>;
10753 using detail_t = meta::conditional_t<std::is_pointer_v<T>, detail::as_pointer_tag<Tu>, detail::as_value_tag<Tu>>;
10754 return check<detail_t>(L, index, std::forward<Handler>(handler), tracking);
10755 }
10756
10757 template <typename T, typename Handler>
10758 bool check_usertype(lua_State* L, int index, Handler&& handler, record& tracking) {
10759 using Tu = meta::unqualified_t<T>;
10760 using detail_t = meta::conditional_t<std::is_pointer_v<T>, detail::as_pointer_tag<Tu>, detail::as_value_tag<Tu>>;
10761 return check<detail_t>(L, index, std::forward<Handler>(handler), tracking);
10762 }
10763
10764 template <typename T, typename Handler>
10765 bool check_usertype(lua_State* L, int index, Handler&& handler) {
10766 record tracking {};
10767 return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
10768 }
10769
10770 template <typename T>
10771 bool check_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
10772 auto handler = no_panic;
10773 return check_usertype<T>(L, index, handler);
10774 }
10775
10776 template <typename T, typename Handler>
10777 decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler, record& tracking) {
10778 using Tu = meta::unqualified_t<T>;
10779 if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<T>) {
10780 return sol_lua_check_get(types<T>(), L, index, std::forward<Handler>(handler), tracking);
10781 }
10782 else if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<Tu>) {
10783 return sol_lua_check_get(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
10784 }
10785 else {
10786 unqualified_check_getter<Tu> cg {};
10787 (void)cg;
10788 return cg.get(L, index, std::forward<Handler>(handler), tracking);
10789 }
10790 }
10791
10792 template <typename T, typename Handler>
10793 decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler) {
10794 record tracking {};
10795 return unqualified_check_get<T>(L, index, handler, tracking);
10796 }
10797
10798 template <typename T>
10799 decltype(auto) unqualified_check_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
10800 auto handler = no_panic;
10801 return unqualified_check_get<T>(L, index, handler);
10802 }
10803
10804 template <typename T, typename Handler>
10805 decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) {
10806 if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<T>) {
10807 return sol_lua_check_get(types<T>(), L, index, std::forward<Handler>(handler), tracking);
10808 }
10809 else {
10810 qualified_check_getter<T> cg {};
10811 (void)cg;
10812 return cg.get(L, index, std::forward<Handler>(handler), tracking);
10813 }
10814 }
10815
10816 template <typename T, typename Handler>
10817 decltype(auto) check_get(lua_State* L, int index, Handler&& handler) {
10818 record tracking {};
10819 return check_get<T>(L, index, handler, tracking);
10820 }
10821
10822 template <typename T>
10823 decltype(auto) check_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
10824 auto handler = no_panic;
10825 return check_get<T>(L, index, handler);
10826 }
10827
10828 namespace stack_detail {
10829
10830 template <typename Handler>
10831 bool check_types(lua_State*, int, Handler&&, record&) {
10832 return true;
10833 }
10834
10835 template <typename T, typename... Args, typename Handler>
10836 bool check_types(lua_State* L, int firstargument, Handler&& handler, record& tracking) {
10837 if (!stack::check<T>(L, firstargument + tracking.used, handler, tracking))
10838 return false;
10839 return check_types<Args...>(L, firstargument, std::forward<Handler>(handler), tracking);
10840 }
10841
10842 template <typename... Args, typename Handler>
10843 bool check_types(types<Args...>, lua_State* L, int index, Handler&& handler, record& tracking) {
10844 return check_types<Args...>(L, index, std::forward<Handler>(handler), tracking);
10845 }
10846
10847 } // namespace stack_detail
10848
10849 template <typename... Args, typename Handler>
10850 bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) {
10851 return stack_detail::check_types<Args...>(L, index, std::forward<Handler>(handler), tracking);
10852 }
10853
10854 template <typename... Args, typename Handler>
10855 bool multi_check(lua_State* L, int index, Handler&& handler) {
10856 record tracking {};
10857 return multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking);
10858 }
10859
10860 template <typename... Args>
10861 bool multi_check(lua_State* L, int index) {
10862 return multi_check<Args...>(L, index);
10863 }
10864
10865 template <typename T>
10866 auto unqualified_get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_unqualified_get<T>(L, index, tracking)) {
10867#if SOL_IS_ON(SOL_SAFE_GETTER_I_)
10868 static constexpr bool is_op = meta::is_optional_v<T>;
10869 if constexpr (is_op) {
10870 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
10871 }
10872 else {
10873 if (is_lua_reference<T>::value) {
10874 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
10875 }
10876 auto op = unqualified_check_get<T>(L, index, type_panic_c_str, tracking);
10877 return *std::move(op);
10878 }
10879#else
10880 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
10881#endif
10882 }
10883
10884 template <typename T>
10885 decltype(auto) unqualified_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
10886 record tracking {};
10887 return unqualified_get<T>(L, index, tracking);
10888 }
10889
10890 template <typename T>
10891 auto get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) {
10892#if SOL_IS_ON(SOL_SAFE_GETTER_I_)
10893 static constexpr bool is_op = meta::is_optional_v<T>;
10894 if constexpr (is_op) {
10895 return stack_detail::unchecked_get<T>(L, index, tracking);
10896 }
10897 else {
10898 if (is_lua_reference<T>::value) {
10899 return stack_detail::unchecked_get<T>(L, index, tracking);
10900 }
10901 auto op = check_get<T>(L, index, type_panic_c_str, tracking);
10902 return *std::move(op);
10903 }
10904#else
10905 return stack_detail::unchecked_get<T>(L, index, tracking);
10906#endif
10907 }
10908
10909 template <typename T>
10910 decltype(auto) get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
10911 record tracking {};
10912 return get<T>(L, index, tracking);
10913 }
10914
10915 template <typename T>
10916 decltype(auto) get_usertype(lua_State* L, int index, record& tracking) {
10917 using UT = meta::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>;
10918 return get<UT>(L, index, tracking);
10919 }
10920
10921 template <typename T>
10922 decltype(auto) get_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
10923 record tracking {};
10924 return get_usertype<T>(L, index, tracking);
10925 }
10926
10927 template <typename T>
10928 decltype(auto) pop(lua_State* L) {
10929 return popper<meta::unqualified_t<T>> {}.pop(L);
10930 }
10931
10932 template <bool global = false, bool raw = false, typename Key>
10933 void get_field(lua_State* L, Key&& key) {
10934 field_getter<meta::unqualified_t<Key>, global, raw> {}.get(L, std::forward<Key>(key));
10935 }
10936
10937 template <bool global = false, bool raw = false, typename Key>
10938 void get_field(lua_State* L, Key&& key, int tableindex) {
10939 field_getter<meta::unqualified_t<Key>, global, raw> {}.get(L, std::forward<Key>(key), tableindex);
10940 }
10941
10942 template <bool global = false, typename Key>
10943 void raw_get_field(lua_State* L, Key&& key) {
10944 get_field<global, true>(L, std::forward<Key>(key));
10945 }
10946
10947 template <bool global = false, typename Key>
10948 void raw_get_field(lua_State* L, Key&& key, int tableindex) {
10949 get_field<global, true>(L, std::forward<Key>(key), tableindex);
10950 }
10951
10952 template <bool global = false, bool raw = false, typename C = detail::non_lua_nil_t, typename Key>
10953 probe probe_get_field(lua_State* L, Key&& key) {
10954 return probe_field_getter<meta::unqualified_t<Key>, C, global, raw> {}.get(L, std::forward<Key>(key));
10955 }
10956
10957 template <bool global = false, bool raw = false, typename C = detail::non_lua_nil_t, typename Key>
10958 probe probe_get_field(lua_State* L, Key&& key, int tableindex) {
10959 return probe_field_getter<meta::unqualified_t<Key>, C, global, raw> {}.get(L, std::forward<Key>(key), tableindex);
10960 }
10961
10962 template <bool global = false, typename C = detail::non_lua_nil_t, typename Key>
10963 probe probe_raw_get_field(lua_State* L, Key&& key) {
10964 return probe_get_field<global, true, C>(L, std::forward<Key>(key));
10965 }
10966
10967 template <bool global = false, typename C = detail::non_lua_nil_t, typename Key>
10968 probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) {
10969 return probe_get_field<global, true, C>(L, std::forward<Key>(key), tableindex);
10970 }
10971
10972 template <bool global = false, bool raw = false, typename Key, typename Value>
10973 void set_field(lua_State* L, Key&& key, Value&& value) {
10974 field_setter<meta::unqualified_t<Key>, global, raw> {}.set(L, std::forward<Key>(key), std::forward<Value>(value));
10975 }
10976
10977 template <bool global = false, bool raw = false, typename Key, typename Value>
10978 void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) {
10979 field_setter<meta::unqualified_t<Key>, global, raw> {}.set(L, std::forward<Key>(key), std::forward<Value>(value), tableindex);
10980 }
10981
10982 template <bool global = false, typename Key, typename Value>
10983 void raw_set_field(lua_State* L, Key&& key, Value&& value) {
10984 set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value));
10985 }
10986
10987 template <bool global = false, typename Key, typename Value>
10988 void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) {
10989 set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value), tableindex);
10990 }
10991
10992 template <typename T, typename F>
10993 void modify_unique_usertype_as(const stack_reference& obj, F&& f) {
10994 using u_traits = unique_usertype_traits<T>;
10995 void* raw = lua_touserdata(obj.lua_state(), obj.stack_index());
10996 void* ptr_memory = detail::align_usertype_pointer(raw);
10997 void* uu_memory = detail::align_usertype_unique<T>(raw);
10998 T& uu = *static_cast<T*>(uu_memory);
10999 f(uu);
11000 *static_cast<void**>(ptr_memory) = static_cast<void*>(u_traits::get(uu));
11001 }
11002
11003 template <typename F>
11004 void modify_unique_usertype(const stack_reference& obj, F&& f) {
11005 using bt = meta::bind_traits<meta::unqualified_t<F>>;
11006 using T = typename bt::template arg_at<0>;
11007 using Tu = meta::unqualified_t<T>;
11008 modify_unique_usertype_as<Tu>(obj, std::forward<F>(f));
11009 }
11010
11011 } // namespace stack
11012
11013 namespace detail {
11014
11015 template <typename T>
11016 lua_CFunction make_destructor(std::true_type) {
11017 if constexpr (is_unique_usertype_v<T>) {
11018 return &unique_destruct<T>;
11019 }
11020 else if constexpr (!std::is_pointer_v<T>) {
11021 return &usertype_alloc_destruct<T>;
11022 }
11023 else {
11024 return &cannot_destruct<T>;
11025 }
11026 }
11027
11028 template <typename T>
11029 lua_CFunction make_destructor(std::false_type) {
11030 return &cannot_destruct<T>;
11031 }
11032
11033 template <typename T>
11034 lua_CFunction make_destructor() {
11035 return make_destructor<T>(std::is_destructible<T>());
11036 }
11037
11038 struct no_comp {
11039 template <typename A, typename B>
11040 bool operator()(A&&, B&&) const {
11041 return false;
11042 }
11043 };
11044
11045 template <typename T>
11046 int is_check(lua_State* L) {
11047 return stack::push(L, stack::check<T>(L, 1, &no_panic));
11048 }
11049
11050 template <typename T>
11051 int member_default_to_string(std::true_type, lua_State* L) {
11052 decltype(auto) ts = stack::get<T>(L, 1).to_string();
11053 return stack::push(L, std::forward<decltype(ts)>(ts));
11054 }
11055
11056 template <typename T>
11057 int member_default_to_string(std::false_type, lua_State* L) {
11058 return luaL_error(L,
11059 "cannot perform to_string on '%s': no 'to_string' overload in namespace, 'to_string' member "
11060 "function, or operator<<(ostream&, ...) present",
11061 detail::demangle<T>().data());
11062 }
11063
11064 template <typename T>
11065 int adl_default_to_string(std::true_type, lua_State* L) {
11066 using namespace std;
11067 decltype(auto) ts = to_string(stack::get<T>(L, 1));
11068 return stack::push(L, std::forward<decltype(ts)>(ts));
11069 }
11070
11071 template <typename T>
11072 int adl_default_to_string(std::false_type, lua_State* L) {
11073 return member_default_to_string<T>(meta::supports_to_string_member<T>(), L);
11074 }
11075
11076 template <typename T>
11077 int oss_default_to_string(std::true_type, lua_State* L) {
11078 std::ostringstream oss;
11079 oss << stack::unqualified_get<T>(L, 1);
11080 return stack::push(L, oss.str());
11081 }
11082
11083 template <typename T>
11084 int oss_default_to_string(std::false_type, lua_State* L) {
11085 return adl_default_to_string<T>(meta::supports_adl_to_string<T>(), L);
11086 }
11087
11088 template <typename T>
11089 int default_to_string(lua_State* L) {
11090 return oss_default_to_string<T>(meta::supports_op_left_shift<std::ostream, T>(), L);
11091 }
11092
11093 template <typename T>
11094 int default_size(lua_State* L) {
11095 decltype(auto) self = stack::unqualified_get<T>(L, 1);
11096 return stack::push(L, self.size());
11097 }
11098
11099 template <typename T, typename Op>
11100 int comparsion_operator_wrap(lua_State* L) {
11101 if constexpr (std::is_void_v<T>) {
11102 return stack::push(L, false);
11103 }
11104 else {
11105 auto maybel = stack::unqualified_check_get<T>(L, 1);
11106 if (!maybel) {
11107 return stack::push(L, false);
11108 }
11109 auto mayber = stack::unqualified_check_get<T>(L, 2);
11110 if (!mayber) {
11111 return stack::push(L, false);
11112 }
11113 decltype(auto) l = *maybel;
11114 decltype(auto) r = *mayber;
11115 if constexpr (std::is_same_v<no_comp, Op>) {
11116 std::equal_to<> op;
11117 return stack::push(L, op(detail::ptr(l), detail::ptr(r)));
11118 }
11119 else {
11120 if constexpr (std::is_same_v<std::equal_to<>, Op> // clang-format hack
11121 || std::is_same_v<std::less_equal<>, Op> //
11122 || std::is_same_v<std::less_equal<>, Op>) { //
11123 if (detail::ptr(l) == detail::ptr(r)) {
11124 return stack::push(L, true);
11125 }
11126 }
11127 Op op;
11128 return stack::push(L, op(detail::deref(l), detail::deref(r)));
11129 }
11130 }
11131 }
11132
11133 template <typename T, typename IFx, typename Fx>
11134 void insert_default_registrations(IFx&& ifx, Fx&& fx);
11135
11136 template <typename T, bool, bool>
11137 struct get_is_primitive : is_lua_primitive<T> { };
11138
11139 template <typename T>
11140 struct get_is_primitive<T, true, false>
11141 : meta::neg<std::is_reference<decltype(sol_lua_get(types<T>(), nullptr, -1, std::declval<stack::record&>()))>> { };
11142
11143 template <typename T>
11144 struct get_is_primitive<T, false, true>
11145 : meta::neg<std::is_reference<decltype(sol_lua_get(types<meta::unqualified_t<T>>(), nullptr, -1, std::declval<stack::record&>()))>> { };
11146
11147 template <typename T>
11148 struct get_is_primitive<T, true, true> : get_is_primitive<T, true, false> { };
11149
11150 } // namespace detail
11151
11152 template <typename T>
11153 struct is_proxy_primitive
11154 : detail::get_is_primitive<T, meta::meta_detail::is_adl_sol_lua_get_v<T>, meta::meta_detail::is_adl_sol_lua_get_v<meta::unqualified_t<T>>> { };
11155
11156} // namespace sol
11157
11158// end of sol/stack_core.hpp
11159
11160// beginning of sol/stack_check.hpp
11161
11162// beginning of sol/stack_check_unqualified.hpp
11163
11164#include <memory>
11165#include <functional>
11166#include <utility>
11167#include <cmath>
11168#include <optional>
11169#if SOL_IS_ON(SOL_STD_VARIANT_I_)
11170#include <variant>
11171#endif // variant shenanigans
11172
11173namespace sol { namespace stack {
11174 namespace stack_detail {
11175 inline bool impl_check_metatable(lua_State* L, int index, const std::string& metakey, bool poptable) {
11176 luaL_getmetatable(L, &metakey[0]);
11177 const type expectedmetatabletype = static_cast<type>(lua_type(L, -1));
11178 if (expectedmetatabletype != type::lua_nil) {
11179 if (lua_rawequal(L, -1, index) == 1) {
11180 lua_pop(L, 1 + static_cast<int>(poptable));
11181 return true;
11182 }
11183 }
11184 lua_pop(L, 1);
11185 return false;
11186 }
11187
11188 template <typename T, bool poptable = true>
11189 inline bool check_metatable(lua_State* L, int index = -2) {
11190 return impl_check_metatable(L, index, usertype_traits<T>::metatable(), poptable);
11191 }
11192
11193 template <type expected, int (*check_func)(lua_State*, int)>
11194 struct basic_check {
11195 template <typename Handler>
11196 static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
11197 tracking.use(1);
11198 bool success = check_func(L, index) == 1;
11199 if (!success) {
11200 // expected type, actual type
11201 handler(L, index, expected, type_of(L, index), "");
11202 }
11203 return success;
11204 }
11205 };
11206 } // namespace stack_detail
11207
11208 template <typename T, typename>
11209 struct unqualified_interop_checker {
11210 template <typename Handler>
11211 static bool check(lua_State*, int, type, Handler&&, record&) {
11212 return false;
11213 }
11214 };
11215
11216 template <typename T, typename>
11217 struct qualified_interop_checker {
11218 template <typename Handler>
11219 static bool check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
11220 return stack_detail::unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking);
11221 }
11222 };
11223
11224 template <typename T, type expected, typename>
11225 struct unqualified_checker {
11226 template <typename Handler>
11227 static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
11228 if constexpr (std::is_same_v<T, bool>) {
11229 tracking.use(1);
11230 bool success = lua_isboolean(L, index) == 1;
11231 if (!success) {
11232 // expected type, actual type
11233 handler(L, index, expected, type_of(L, index), "");
11234 }
11235 return success;
11236 }
11237 else if constexpr (meta::any_same_v<T, char /* , char8_t*/, char16_t, char32_t>) {
11238 return stack::check<std::basic_string<T>>(L, index, std::forward<Handler>(handler), tracking);
11239 }
11240 else if constexpr (std::is_integral_v<T> || std::is_same_v<T, lua_Integer>) {
11241 tracking.use(1);
11242#if SOL_LUA_VESION_I_ >= 503
11243 // Lua 5.3 and greater checks for numeric precision
11244#if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS_I_)
11245 // imprecise, sloppy conversions
11246 int isnum = 0;
11247 lua_tointegerx(L, index, &isnum);
11248 const bool success = isnum != 0;
11249 if (!success) {
11250 // expected type, actual type
11251 handler(L, index, type::number, type_of(L, index), detail::not_a_number_or_number_string_integral);
11252 }
11253#elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS_I_)
11254 // this check is precise, do not convert
11255 if (lua_isinteger(L, index) == 1) {
11256 return true;
11257 }
11258 const bool success = false;
11259 if (!success) {
11260 // expected type, actual type
11261 handler(L, index, type::number, type_of(L, index), detail::not_a_number_integral);
11262 }
11263#else
11264 // Numerics are neither safe nor string-convertible
11265 type t = type_of(L, index);
11266 const bool success = t == type::number;
11267#endif
11268 if (!success) {
11269 // expected type, actual type
11270 handler(L, index, type::number, type_of(L, index), detail::not_a_number);
11271 }
11272 return success;
11273#else
11274 // Lua 5.2 and below checks
11275#if SOL_IS_OFF(SOL_STRINGS_ARE_NUMBERS_I_)
11276 // must pre-check, because it will convert
11277 type t = type_of(L, index);
11278 if (t != type::number) {
11279 // expected type, actual type
11280 handler(L, index, type::number, t, detail::not_a_number);
11281 return false;
11282 }
11283#endif // Do not allow strings to be numbers
11284
11285#if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS_I_)
11286 int isnum = 0;
11287 const lua_Number v = lua_tonumberx(L, index, &isnum);
11288 const bool success = isnum != 0 && static_cast<lua_Number>(llround(v)) == v;
11289#else
11290 const bool success = true;
11291#endif // Safe numerics and number precision checking
11292 if (!success) {
11293 // Use defines to provide a better error message!
11294#if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS_I_)
11295 handler(L, index, type::number, type_of(L, index), detail::not_a_number_or_number_string);
11296#elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS_I_)
11297 handler(L, index, type::number, t, detail::not_a_number_or_number_string);
11298#else
11299 handler(L, index, type::number, t, detail::not_a_number);
11300#endif
11301 }
11302 return success;
11303#endif
11304 }
11305 else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) {
11306 tracking.use(1);
11307#if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS_I_)
11308 bool success = lua_isnumber(L, index) == 1;
11309 if (!success) {
11310 // expected type, actual type
11311 handler(L, index, type::number, type_of(L, index), detail::not_a_number_or_number_string);
11312 }
11313 return success;
11314#else
11315 type t = type_of(L, index);
11316 bool success = t == type::number;
11317 if (!success) {
11318 // expected type, actual type
11319 handler(L, index, type::number, t, detail::not_a_number);
11320 }
11321 return success;
11322#endif // Strings are Numbers
11323 }
11324 else if constexpr (meta::any_same_v<T, type, this_state, this_main_state, this_environment, variadic_args>) {
11325 (void)L;
11326 (void)index;
11327 (void)handler;
11328 tracking.use(0);
11329 return true;
11330 }
11331 else if constexpr (is_unique_usertype_v<T>) {
11332 using proper_T = typename unique_usertype_traits<T>::type;
11333 const type indextype = type_of(L, index);
11334 tracking.use(1);
11335 if (indextype != type::userdata) {
11336 handler(L, index, type::userdata, indextype, "value is not a userdata");
11337 return false;
11338 }
11339 if (lua_getmetatable(L, index) == 0) {
11340 return true;
11341 }
11342 int metatableindex = lua_gettop(L);
11343 if (stack_detail::check_metatable<detail::unique_usertype<proper_T>>(L, metatableindex)) {
11344 void* memory = lua_touserdata(L, index);
11345 memory = detail::align_usertype_unique_destructor(memory);
11346 detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
11347 bool success = &detail::usertype_unique_alloc_destroy<proper_T, T> == pdx;
11348 if (!success) {
11349 memory = detail::align_usertype_unique_tag<true>(memory);
11350#if 0
11351 // New version
11352#else
11353 const char*& name_tag = *static_cast<const char**>(memory);
11354 success = usertype_traits<T>::qualified_name() == name_tag;
11355#endif
11356 if (!success) {
11357 handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype");
11358 }
11359 }
11360 return success;
11361 }
11362 lua_pop(L, 1);
11363 handler(L, index, type::userdata, indextype, "unrecognized userdata (not pushed by sol?)");
11364 return false;
11365 }
11366 else if constexpr (meta::any_same_v<T, lua_nil_t, std::nullopt_t, nullopt_t>) {
11367 bool success = lua_isnil(L, index);
11368 if (success) {
11369 tracking.use(1);
11370 return success;
11371 }
11372 tracking.use(0);
11373 success = lua_isnone(L, index);
11374 if (!success) {
11375 // expected type, actual type
11376 handler(L, index, expected, type_of(L, index), "");
11377 }
11378 return success;
11379 }
11380 else if constexpr (std::is_same_v<T, env_key_t>) {
11381 tracking.use(1);
11382 type t = type_of(L, index);
11383 if (t == type::table || t == type::none || t == type::lua_nil || t == type::userdata) {
11384 return true;
11385 }
11386 handler(L, index, type::table, t, "value cannot not have a valid environment");
11387 return true;
11388 }
11389 else if constexpr (std::is_same_v<T, detail::non_lua_nil_t>) {
11390 return !stack::unqualified_check<lua_nil_t>(L, index, std::forward<Handler>(handler), tracking);
11391 }
11392 else if constexpr (meta::is_specialization_of_v<T, basic_lua_table>) {
11393 tracking.use(1);
11394 type t = type_of(L, index);
11395 if (t != type::table) {
11396 handler(L, index, type::table, t, "value is not a table");
11397 return false;
11398 }
11399 return true;
11400 }
11401 else if constexpr (meta::is_specialization_of_v<T, basic_bytecode>) {
11402 tracking.use(1);
11403 type t = type_of(L, index);
11404 if (t != type::function) {
11405 handler(L, index, type::function, t, "value is not a function that can be dumped");
11406 return false;
11407 }
11408 return true;
11409 }
11410 else if constexpr (meta::is_specialization_of_v<T, basic_environment>) {
11411 tracking.use(1);
11412 if (lua_getmetatable(L, index) == 0) {
11413 return true;
11414 }
11415 type t = type_of(L, -1);
11416 if (t == type::table || t == type::none || t == type::lua_nil) {
11417 lua_pop(L, 1);
11418 return true;
11419 }
11420 if (t != type::userdata) {
11421 lua_pop(L, 1);
11422 handler(L, index, type::table, t, "value does not have a valid metatable");
11423 return false;
11424 }
11425 return true;
11426 }
11427 else if constexpr (std::is_same_v<T, metatable_key_t>) {
11428 tracking.use(1);
11429 if (lua_getmetatable(L, index) == 0) {
11430 return true;
11431 }
11432 type t = type_of(L, -1);
11433 if (t == type::table || t == type::none || t == type::lua_nil) {
11434 lua_pop(L, 1);
11435 return true;
11436 }
11437 if (t != type::userdata) {
11438 lua_pop(L, 1);
11439 handler(L, index, expected, t, "value does not have a valid metatable");
11440 return false;
11441 }
11442 return true;
11443 }
11444 else if constexpr (std::is_same_v<T, luaL_Stream*> || std::is_same_v<T, luaL_Stream>) {
11445 if (lua_getmetatable(L, index) == 0) {
11446 type t = type_of(L, index);
11447 handler(L, index, expected, t, "value is not a valid luaL_Stream (has no metatable/is not a valid value)");
11448 return false;
11449 }
11450 luaL_getmetatable(L, LUA_FILEHANDLE);
11451 if (type_of(L, index) != type::table) {
11452 type t = type_of(L, index);
11453 lua_pop(L, 1);
11454 handler(L,
11455 index,
11456 expected,
11457 t,
11458 "value is not a valid luaL_Stream (there is no metatable for luaL_Stream -- did you forget to "
11459 "my_lua_state.open_libraries(sol::lib::state) or equivalent?)");
11460 return false;
11461 }
11462 int is_stream_table = lua_compare(L, -1, -2, LUA_OPEQ);
11463 lua_pop(L, 2);
11464 if (is_stream_table == 0) {
11465 type t = type_of(L, index);
11466 handler(L, index, expected, t, "value is not a valid luaL_Stream (incorrect metatable)");
11467 return false;
11468 }
11469 return true;
11470 }
11471 else if constexpr (meta::is_optional_v<T>) {
11472 using ValueType = typename T::value_type;
11473 (void)handler;
11474 type t = type_of(L, index);
11475 if (t == type::none) {
11476 tracking.use(0);
11477 return true;
11478 }
11479 if (t == type::lua_nil) {
11480 tracking.use(1);
11481 return true;
11482 }
11483 return stack::unqualified_check<ValueType>(L, index, no_panic, tracking);
11484 }
11485#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
11486 else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
11487 return stack_detail::check_function_pointer<std::remove_pointer_t<T>>(L, index, std::forward<Handler>(handler), tracking);
11488 }
11489#endif
11490 else if constexpr (expected == type::userdata) {
11491 if constexpr (meta::any_same_v<T, userdata_value> || meta::is_specialization_of_v<T, basic_userdata>) {
11492 tracking.use(1);
11493 type t = type_of(L, index);
11494 bool success = t == type::userdata;
11495 if (!success) {
11496 // expected type, actual type
11497 handler(L, index, type::userdata, t, "");
11498 }
11499 return success;
11500 }
11501 else if constexpr (meta::is_specialization_of_v<T, user>) {
11502 unqualified_checker<lightuserdata_value, type::userdata> c;
11503 (void)c;
11504 return c.check(L, index, std::forward<Handler>(handler), tracking);
11505 }
11506 else {
11507 if constexpr (std::is_pointer_v<T>) {
11508 return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
11509 }
11510 else if constexpr (meta::is_specialization_of_v<T, std::reference_wrapper>) {
11511 using T_internal = typename T::type;
11512 return stack::check<T_internal>(L, index, std::forward<Handler>(handler), tracking);
11513 }
11514 else {
11515 return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
11516 }
11517 }
11518 }
11519 else if constexpr (expected == type::poly) {
11520 tracking.use(1);
11521 bool success = is_lua_reference_v<T> || !lua_isnone(L, index);
11522 if (!success) {
11523 // expected type, actual type
11524 handler(L, index, type::poly, type_of(L, index), "");
11525 }
11526 return success;
11527 }
11528 else if constexpr (expected == type::lightuserdata) {
11529 tracking.use(1);
11530 type t = type_of(L, index);
11531 bool success = t == type::userdata || t == type::lightuserdata;
11532 if (!success) {
11533 // expected type, actual type
11534 handler(L, index, type::lightuserdata, t, "");
11535 }
11536 return success;
11537 }
11538 else if constexpr (expected == type::function) {
11539 if constexpr (meta::any_same_v<T, lua_CFunction, std::remove_pointer_t<lua_CFunction>, c_closure>) {
11540 tracking.use(1);
11541 bool success = lua_iscfunction(L, index) == 1;
11542 if (!success) {
11543 // expected type, actual type
11544 handler(L, index, expected, type_of(L, index), "");
11545 }
11546 return success;
11547 }
11548 else {
11549 tracking.use(1);
11550 type t = type_of(L, index);
11551 if (t == type::lua_nil || t == type::none || t == type::function) {
11552 // allow for lua_nil to be returned
11553 return true;
11554 }
11555 if (t != type::userdata && t != type::table) {
11556 handler(L, index, type::function, t, "must be a function or table or a userdata");
11557 return false;
11558 }
11559 // Do advanced check for call-style userdata?
11560 static const auto& callkey = to_string(meta_function::call);
11561 if (lua_getmetatable(L, index) == 0) {
11562 // No metatable, no __call key possible
11563 handler(L, index, type::function, t, "value is not a function and does not have overriden metatable");
11564 return false;
11565 }
11566 if (lua_isnoneornil(L, -1)) {
11567 lua_pop(L, 1);
11568 handler(L, index, type::function, t, "value is not a function and does not have valid metatable");
11569 return false;
11570 }
11571 lua_getfield(L, -1, &callkey[0]);
11572 if (lua_isnoneornil(L, -1)) {
11573 lua_pop(L, 2);
11574 handler(L, index, type::function, t, "value's metatable does not have __call overridden in metatable, cannot call this type");
11575 return false;
11576 }
11577 // has call, is definitely a function
11578 lua_pop(L, 2);
11579 return true;
11580 }
11581 }
11582 else if constexpr (expected == type::table) {
11583 tracking.use(1);
11584 type t = type_of(L, index);
11585 if (t == type::table) {
11586 return true;
11587 }
11588 if (t != type::userdata) {
11589 handler(L, index, type::table, t, "value is not a table or a userdata that can behave like one");
11590 return false;
11591 }
11592 return true;
11593 }
11594 else {
11595 tracking.use(1);
11596 const type indextype = type_of(L, index);
11597 bool success = expected == indextype;
11598 if (!success) {
11599 // expected type, actual type, message
11600 handler(L, index, expected, indextype, "");
11601 }
11602 return success;
11603 }
11604 }
11605 };
11606
11607 template <typename T>
11608 struct unqualified_checker<non_null<T>, type::userdata> : unqualified_checker<T, lua_type_of_v<T>> { };
11609
11610 template <typename T>
11611 struct unqualified_checker<detail::as_value_tag<T>, type::userdata> {
11612 template <typename Handler>
11613 static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
11614 const type indextype = type_of(L, index);
11615 return check(types<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
11616 }
11617
11618 template <typename U, typename Handler>
11619 static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
11620 if constexpr (
11621 std::is_same_v<T,
11622 lightuserdata_value> || std::is_same_v<T, userdata_value> || std::is_same_v<T, userdata> || std::is_same_v<T, lightuserdata>) {
11623 tracking.use(1);
11624 if (indextype != type::userdata) {
11625 handler(L, index, type::userdata, indextype, "value is not a valid userdata");
11626 return false;
11627 }
11628 return true;
11629 }
11630 else {
11631#if SOL_IS_ON(SOL_USE_INTEROP_I_)
11632 if (stack_detail::interop_check<U>(L, index, indextype, handler, tracking)) {
11633 return true;
11634 }
11635#endif // interop extensibility
11636 tracking.use(1);
11637 if (indextype != type::userdata) {
11638 handler(L, index, type::userdata, indextype, "value is not a valid userdata");
11639 return false;
11640 }
11641 if (lua_getmetatable(L, index) == 0) {
11642 return true;
11643 }
11644 int metatableindex = lua_gettop(L);
11645 if (stack_detail::check_metatable<U>(L, metatableindex))
11646 return true;
11647 if (stack_detail::check_metatable<U*>(L, metatableindex))
11648 return true;
11649 if (stack_detail::check_metatable<detail::unique_usertype<U>>(L, metatableindex))
11650 return true;
11651 if (stack_detail::check_metatable<as_container_t<U>>(L, metatableindex))
11652 return true;
11653 bool success = false;
11654 bool has_derived = derive<T>::value || weak_derive<T>::value;
11655 if (has_derived) {
11656#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
11657 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
11658#endif // make sure stack doesn't overflow
11659 auto pn = stack::pop_n(L, 1);
11660 lua_pushstring(L, &detail::base_class_check_key()[0]);
11661 lua_rawget(L, metatableindex);
11662 if (type_of(L, -1) != type::lua_nil) {
11663 void* basecastdata = lua_touserdata(L, -1);
11664 detail::inheritance_check_function ic = reinterpret_cast<detail::inheritance_check_function>(basecastdata);
11665 success = ic(usertype_traits<T>::qualified_name());
11666 }
11667 }
11668 lua_pop(L, 1);
11669 if (!success) {
11670 handler(L, index, type::userdata, indextype, "value at this index does not properly reflect the desired type");
11671 return false;
11672 }
11673 return true;
11674 }
11675 }
11676 };
11677
11678 template <typename T>
11679 struct unqualified_checker<detail::as_pointer_tag<T>, type::userdata> {
11680 template <typename Handler>
11681 static bool check(lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
11682 if (indextype == type::lua_nil) {
11683 tracking.use(1);
11684 return true;
11685 }
11686 return check_usertype<std::remove_pointer_t<T>>(L, index, std::forward<Handler>(handler), tracking);
11687 }
11688
11689 template <typename Handler>
11690 static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
11691 const type indextype = type_of(L, index);
11692 return check(L, index, indextype, std::forward<Handler>(handler), tracking);
11693 }
11694 };
11695
11696 template <typename... Args>
11697 struct unqualified_checker<std::tuple<Args...>, type::poly> {
11698 template <typename Handler>
11699 static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
11700 return stack::multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking);
11701 }
11702 };
11703
11704 template <typename A, typename B>
11705 struct unqualified_checker<std::pair<A, B>, type::poly> {
11706 template <typename Handler>
11707 static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
11708 return stack::multi_check<A, B>(L, index, std::forward<Handler>(handler), tracking);
11709 }
11710 };
11711
11712#if SOL_IS_ON(SOL_STD_VARIANT_I_)
11713
11714 template <typename... Tn>
11715 struct unqualified_checker<std::variant<Tn...>, type::poly> {
11716 typedef std::variant<Tn...> V;
11717 typedef std::variant_size<V> V_size;
11718 typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
11719
11720 template <typename Handler>
11721 static bool is_one(std::integral_constant<std::size_t, 0>, lua_State* L, int index, Handler&& handler, record& tracking) {
11722 if constexpr (V_is_empty::value) {
11723 if (lua_isnone(L, index)) {
11724 return true;
11725 }
11726 }
11727 tracking.use(1);
11728 handler(L, index, type::poly, type_of(L, index), "value does not fit any type present in the variant");
11729 return false;
11730 }
11731
11732 template <std::size_t I, typename Handler>
11733 static bool is_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, Handler&& handler, record& tracking) {
11734 typedef std::variant_alternative_t<I - 1, V> T;
11735 record temp_tracking = tracking;
11736 if (stack::check<T>(L, index, no_panic, temp_tracking)) {
11737 tracking = temp_tracking;
11738 return true;
11739 }
11740 return is_one(std::integral_constant<std::size_t, I - 1>(), L, index, std::forward<Handler>(handler), tracking);
11741 }
11742
11743 template <typename Handler>
11744 static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
11745 return is_one(std::integral_constant<std::size_t, V_size::value>(), L, index, std::forward<Handler>(handler), tracking);
11746 }
11747 };
11748
11749#endif // variant shenanigans
11750
11751}} // namespace sol::stack
11752
11753// end of sol/stack_check_unqualified.hpp
11754
11755// beginning of sol/stack_check_qualified.hpp
11756
11757namespace sol {
11758namespace stack {
11759
11760 template <typename X, type expected, typename>
11761 struct qualified_checker {
11762 template <typename Handler>
11763 static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
11764 if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<X>) {
11765 using u_traits = unique_usertype_traits<meta::unqualified_t<X>>;
11766 using T = typename u_traits::type;
11767 if constexpr (is_base_rebindable_non_void_v<u_traits>) {
11768 using rebind_t = typename u_traits::template rebind_base<void>;
11769 // we have a unique pointer type that can be
11770 // rebound to a base/derived type
11771 const type indextype = type_of(L, index);
11772 tracking.use(1);
11773 if (indextype != type::userdata) {
11774 handler(L, index, type::userdata, indextype, "value is not a userdata");
11775 return false;
11776 }
11777 void* memory = lua_touserdata(L, index);
11778 memory = detail::align_usertype_unique_destructor(memory);
11779 detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
11780 if (&detail::usertype_unique_alloc_destroy<T, X> == pdx) {
11781 return true;
11782 }
11783 if constexpr (derive<T>::value) {
11784 memory = detail::align_usertype_unique_tag<true, false>(memory);
11785 detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
11786 string_view ti = usertype_traits<T>::qualified_name();
11787 string_view rebind_ti = usertype_traits<rebind_t>::qualified_name();
11788 if (ic(nullptr, nullptr, ti, rebind_ti) != 0) {
11789 return true;
11790 }
11791 }
11792 handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype");
11793 return false;
11794 }
11795 else {
11796 return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
11797 }
11798 }
11799 else if constexpr (!std::is_reference_v<X> && is_container_v<X>) {
11800 if (type_of(L, index) == type::userdata) {
11801 return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
11802 }
11803 else {
11804 return stack::unqualified_check<nested<X>>(L, index, std::forward<Handler>(handler), tracking);
11805 }
11806 }
11807 else if constexpr (!std::is_reference_v<X> && meta::is_specialization_of_v<X, nested>) {
11808 using NestedX = typename meta::unqualified_t<X>::nested_type;
11809 return stack::check<NestedX>(L, index, ::std::forward<Handler>(handler), tracking);
11810 }
11811 else {
11812 return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
11813 }
11814 }
11815 };
11816}
11817} // namespace sol::stack
11818
11819// end of sol/stack_check_qualified.hpp
11820
11821// end of sol/stack_check.hpp
11822
11823// beginning of sol/stack_get.hpp
11824
11825// beginning of sol/stack_get_unqualified.hpp
11826
11827// beginning of sol/overload.hpp
11828
11829#include <utility>
11830
11831namespace sol {
11832 template <typename... Functions>
11833 struct overload_set {
11834 std::tuple<Functions...> functions;
11835 template <typename Arg, typename... Args, meta::disable<std::is_same<overload_set, meta::unqualified_t<Arg>>> = meta::enabler>
11836 overload_set(Arg&& arg, Args&&... args)
11837 : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {
11838 }
11839 overload_set(const overload_set&) = default;
11840 overload_set(overload_set&&) = default;
11841 overload_set& operator=(const overload_set&) = default;
11842 overload_set& operator=(overload_set&&) = default;
11843 };
11844
11845 template <typename... Args>
11846 decltype(auto) overload(Args&&... args) {
11847 return overload_set<std::decay_t<Args>...>(std::forward<Args>(args)...);
11848 }
11849} // namespace sol
11850
11851// end of sol/overload.hpp
11852
11853// beginning of sol/unicode.hpp
11854
11855#include <array>
11856#include <cstring>
11857
11858namespace sol {
11859 // Everything here was lifted pretty much straight out of
11860 // ogonek, because fuck figuring it out=
11861 namespace unicode {
11862 enum class error_code {
11863 ok = 0,
11864 invalid_code_point,
11865 invalid_code_unit,
11866 invalid_leading_surrogate,
11867 invalid_trailing_surrogate,
11868 sequence_too_short,
11869 overlong_sequence,
11870 };
11871
11872 inline const string_view& to_string(error_code ec) {
11873 static const string_view storage[7] = {
11874 "ok",
11875 "invalid code points",
11876 "invalid code unit",
11877 "invalid leading surrogate",
11878 "invalid trailing surrogate",
11879 "sequence too short",
11880 "overlong sequence"
11881 };
11882 return storage[static_cast<std::size_t>(ec)];
11883 }
11884
11885 template <typename It>
11886 struct decoded_result {
11887 error_code error;
11888 char32_t codepoint;
11889 It next;
11890 };
11891
11892 template <typename C>
11893 struct encoded_result {
11894 error_code error;
11895 std::size_t code_units_size;
11896 std::array<C, 4> code_units;
11897 };
11898
11899 struct unicode_detail {
11900 // codepoint related
11901 static constexpr char32_t last_code_point = 0x10FFFF;
11902
11903 static constexpr char32_t first_lead_surrogate = 0xD800;
11904 static constexpr char32_t last_lead_surrogate = 0xDBFF;
11905
11906 static constexpr char32_t first_trail_surrogate = 0xDC00;
11907 static constexpr char32_t last_trail_surrogate = 0xDFFF;
11908
11909 static constexpr char32_t first_surrogate = first_lead_surrogate;
11910 static constexpr char32_t last_surrogate = last_trail_surrogate;
11911
11912 static constexpr bool is_lead_surrogate(char32_t u) {
11913 return u >= first_lead_surrogate && u <= last_lead_surrogate;
11914 }
11915 static constexpr bool is_trail_surrogate(char32_t u) {
11916 return u >= first_trail_surrogate && u <= last_trail_surrogate;
11917 }
11918 static constexpr bool is_surrogate(char32_t u) {
11919 return u >= first_surrogate && u <= last_surrogate;
11920 }
11921
11922 // utf8 related
11923 static constexpr auto last_1byte_value = 0x7Fu;
11924 static constexpr auto last_2byte_value = 0x7FFu;
11925 static constexpr auto last_3byte_value = 0xFFFFu;
11926
11927 static constexpr auto start_2byte_mask = 0x80u;
11928 static constexpr auto start_3byte_mask = 0xE0u;
11929 static constexpr auto start_4byte_mask = 0xF0u;
11930
11931 static constexpr auto continuation_mask = 0xC0u;
11932 static constexpr auto continuation_signature = 0x80u;
11933
11934 static constexpr bool is_invalid(unsigned char b) {
11935 return b == 0xC0 || b == 0xC1 || b > 0xF4;
11936 }
11937
11938 static constexpr bool is_continuation(unsigned char b) {
11939 return (b & unicode_detail::continuation_mask) == unicode_detail::continuation_signature;
11940 }
11941
11942 static constexpr bool is_overlong(char32_t u, std::size_t bytes) {
11943 return u <= unicode_detail::last_1byte_value || (u <= unicode_detail::last_2byte_value && bytes > 2)
11944 || (u <= unicode_detail::last_3byte_value && bytes > 3);
11945 }
11946
11947 static constexpr int sequence_length(unsigned char b) {
11948 return (b & start_2byte_mask) == 0 ? 1
11949 : (b & start_3byte_mask) != start_3byte_mask ? 2
11950 : (b & start_4byte_mask) != start_4byte_mask ? 3
11951 : 4;
11952 }
11953
11954 static constexpr char32_t decode(unsigned char b0, unsigned char b1) {
11955 return ((b0 & 0x1F) << 6) | (b1 & 0x3F);
11956 }
11957 static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2) {
11958 return ((b0 & 0x0F) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F);
11959 }
11960 static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3) {
11961 return ((b0 & 0x07) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F);
11962 }
11963
11964 // utf16 related
11965 static constexpr char32_t last_bmp_value = 0xFFFF;
11966 static constexpr char32_t normalizing_value = 0x10000;
11967 static constexpr int lead_surrogate_bitmask = 0xFFC00;
11968 static constexpr int trail_surrogate_bitmask = 0x3FF;
11969 static constexpr int lead_shifted_bits = 10;
11970 static constexpr char32_t replacement = 0xFFFD;
11971
11972 static char32_t combine_surrogates(char16_t lead, char16_t trail) {
11973 auto hi = lead - first_lead_surrogate;
11974 auto lo = trail - first_trail_surrogate;
11975 return normalizing_value + ((hi << lead_shifted_bits) | lo);
11976 }
11977 };
11978
11979 inline encoded_result<char> code_point_to_utf8(char32_t codepoint) {
11980 encoded_result<char> er;
11981 er.error = error_code::ok;
11982 if (codepoint <= unicode_detail::last_1byte_value) {
11983 er.code_units_size = 1;
11984 er.code_units = std::array<char, 4>{ { static_cast<char>(codepoint) } };
11985 }
11986 else if (codepoint <= unicode_detail::last_2byte_value) {
11987 er.code_units_size = 2;
11988 er.code_units = std::array<char, 4>{{
11989 static_cast<char>(0xC0 | ((codepoint & 0x7C0) >> 6)),
11990 static_cast<char>(0x80 | (codepoint & 0x3F)),
11991 }};
11992 }
11993 else if (codepoint <= unicode_detail::last_3byte_value) {
11994 er.code_units_size = 3;
11995 er.code_units = std::array<char, 4>{{
11996 static_cast<char>(0xE0 | ((codepoint & 0xF000) >> 12)),
11997 static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)),
11998 static_cast<char>(0x80 | (codepoint & 0x3F)),
11999 }};
12000 }
12001 else {
12002 er.code_units_size = 4;
12003 er.code_units = std::array<char, 4>{ {
12004 static_cast<char>(0xF0 | ((codepoint & 0x1C0000) >> 18)),
12005 static_cast<char>(0x80 | ((codepoint & 0x3F000) >> 12)),
12006 static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)),
12007 static_cast<char>(0x80 | (codepoint & 0x3F)),
12008 } };
12009 }
12010 return er;
12011 }
12012
12013 inline encoded_result<char16_t> code_point_to_utf16(char32_t codepoint) {
12014 encoded_result<char16_t> er;
12015
12016 if (codepoint <= unicode_detail::last_bmp_value) {
12017 er.code_units_size = 1;
12018 er.code_units = std::array<char16_t, 4>{ { static_cast<char16_t>(codepoint) } };
12019 er.error = error_code::ok;
12020 }
12021 else {
12022 auto normal = codepoint - unicode_detail::normalizing_value;
12023 auto lead = unicode_detail::first_lead_surrogate + ((normal & unicode_detail::lead_surrogate_bitmask) >> unicode_detail::lead_shifted_bits);
12024 auto trail = unicode_detail::first_trail_surrogate + (normal & unicode_detail::trail_surrogate_bitmask);
12025 er.code_units = std::array<char16_t, 4>{ {
12026 static_cast<char16_t>(lead),
12027 static_cast<char16_t>(trail)
12028 } };
12029 er.code_units_size = 2;
12030 er.error = error_code::ok;
12031 }
12032 return er;
12033 }
12034
12035 inline encoded_result<char32_t> code_point_to_utf32(char32_t codepoint) {
12036 encoded_result<char32_t> er;
12037 er.code_units_size = 1;
12038 er.code_units[0] = codepoint;
12039 er.error = error_code::ok;
12040 return er;
12041 }
12042
12043 template <typename It>
12044 inline decoded_result<It> utf8_to_code_point(It it, It last) {
12045 decoded_result<It> dr;
12046 if (it == last) {
12047 dr.next = it;
12048 dr.error = error_code::sequence_too_short;
12049 return dr;
12050 }
12051
12052 unsigned char b0 = *it;
12053 std::size_t length = unicode_detail::sequence_length(b0);
12054
12055 if (length == 1) {
12056 dr.codepoint = static_cast<char32_t>(b0);
12057 dr.error = error_code::ok;
12058 ++it;
12059 dr.next = it;
12060 return dr;
12061 }
12062
12063 if (unicode_detail::is_invalid(b0) || unicode_detail::is_continuation(b0)) {
12064 dr.error = error_code::invalid_code_unit;
12065 dr.next = it;
12066 return dr;
12067 }
12068
12069 ++it;
12070 std::array<unsigned char, 4> b;
12071 b[0] = b0;
12072 for (std::size_t i = 1; i < length; ++i) {
12073 b[i] = *it;
12074 if (!unicode_detail::is_continuation(b[i])) {
12075 dr.error = error_code::invalid_code_unit;
12076 dr.next = it;
12077 return dr;
12078 }
12079 ++it;
12080 }
12081
12082 char32_t decoded;
12083 switch (length) {
12084 case 2:
12085 decoded = unicode_detail::decode(b[0], b[1]);
12086 break;
12087 case 3:
12088 decoded = unicode_detail::decode(b[0], b[1], b[2]);
12089 break;
12090 default:
12091 decoded = unicode_detail::decode(b[0], b[1], b[2], b[3]);
12092 break;
12093 }
12094
12095 if (unicode_detail::is_overlong(decoded, length)) {
12096 dr.error = error_code::overlong_sequence;
12097 return dr;
12098 }
12099 if (unicode_detail::is_surrogate(decoded) || decoded > unicode_detail::last_code_point) {
12100 dr.error = error_code::invalid_code_point;
12101 return dr;
12102 }
12103
12104 // then everything is fine
12105 dr.codepoint = decoded;
12106 dr.error = error_code::ok;
12107 dr.next = it;
12108 return dr;
12109 }
12110
12111 template <typename It>
12112 inline decoded_result<It> utf16_to_code_point(It it, It last) {
12113 decoded_result<It> dr;
12114 if (it == last) {
12115 dr.next = it;
12116 dr.error = error_code::sequence_too_short;
12117 return dr;
12118 }
12119
12120 char16_t lead = static_cast<char16_t>(*it);
12121
12122 if (!unicode_detail::is_surrogate(lead)) {
12123 ++it;
12124 dr.codepoint = static_cast<char32_t>(lead);
12125 dr.next = it;
12126 dr.error = error_code::ok;
12127 return dr;
12128 }
12129 if (!unicode_detail::is_lead_surrogate(lead)) {
12130 dr.error = error_code::invalid_leading_surrogate;
12131 dr.next = it;
12132 return dr;
12133 }
12134
12135 ++it;
12136 auto trail = *it;
12137 if (!unicode_detail::is_trail_surrogate(trail)) {
12138 dr.error = error_code::invalid_trailing_surrogate;
12139 dr.next = it;
12140 return dr;
12141 }
12142
12143 dr.codepoint = unicode_detail::combine_surrogates(lead, trail);
12144 dr.next = ++it;
12145 dr.error = error_code::ok;
12146 return dr;
12147 }
12148
12149 template <typename It>
12150 inline decoded_result<It> utf32_to_code_point(It it, It last) {
12151 decoded_result<It> dr;
12152 if (it == last) {
12153 dr.next = it;
12154 dr.error = error_code::sequence_too_short;
12155 return dr;
12156 }
12157 dr.codepoint = static_cast<char32_t>(*it);
12158 dr.next = ++it;
12159 dr.error = error_code::ok;
12160 return dr;
12161 }
12162 }
12163}
12164// end of sol/unicode.hpp
12165
12166#include <memory>
12167#include <functional>
12168#include <utility>
12169#include <cstdlib>
12170#include <cmath>
12171#include <string_view>
12172#if SOL_IS_ON(SOL_STD_VARIANT_I_)
12173#include <variant>
12174#endif // Apple clang screwed up
12175
12176namespace sol { namespace stack {
12177
12178 namespace stack_detail {
12179 template <typename Ch>
12180 struct count_code_units_utf {
12181 std::size_t needed_size;
12182
12183 count_code_units_utf() : needed_size(0) {
12184 }
12185
12186 void operator()(const unicode::encoded_result<Ch> er) {
12187 needed_size += er.code_units_size;
12188 }
12189 };
12190
12191 template <typename Ch, typename ErCh>
12192 struct copy_code_units_utf {
12193 Ch* target_;
12194
12195 copy_code_units_utf(Ch* target) : target_(target) {
12196 }
12197
12198 void operator()(const unicode::encoded_result<ErCh> er) {
12199 std::memcpy(target_, er.code_units.data(), er.code_units_size * sizeof(ErCh));
12200 target_ += er.code_units_size;
12201 }
12202 };
12203
12204 template <typename Ch, typename F>
12205 inline void convert(const char* strb, const char* stre, F&& f) {
12206 char32_t cp = 0;
12207 for (const char* strtarget = strb; strtarget < stre;) {
12208 auto dr = unicode::utf8_to_code_point(strtarget, stre);
12209 if (dr.error != unicode::error_code::ok) {
12210 cp = unicode::unicode_detail::replacement;
12211 ++strtarget;
12212 }
12213 else {
12214 cp = dr.codepoint;
12215 strtarget = dr.next;
12216 }
12217 if constexpr (std::is_same_v<Ch, char32_t>) {
12218 auto er = unicode::code_point_to_utf32(cp);
12219 f(er);
12220 }
12221 else {
12222 auto er = unicode::code_point_to_utf16(cp);
12223 f(er);
12224 }
12225 }
12226 }
12227
12228 template <typename BaseCh, typename S>
12229 inline S get_into(lua_State* L, int index, record& tracking) {
12230 using Ch = typename S::value_type;
12231 tracking.use(1);
12232 size_t len;
12233 auto utf8p = lua_tolstring(L, index, &len);
12234 if (len < 1)
12235 return S();
12236 const char* strb = utf8p;
12237 const char* stre = utf8p + len;
12238 stack_detail::count_code_units_utf<BaseCh> count_units;
12239 convert<BaseCh>(strb, stre, count_units);
12240 S r(count_units.needed_size, static_cast<Ch>(0));
12241 r.resize(count_units.needed_size);
12242 Ch* target = &r[0];
12243 stack_detail::copy_code_units_utf<Ch, BaseCh> copy_units(target);
12244 convert<BaseCh>(strb, stre, copy_units);
12245 return r;
12246 }
12247 } // namespace stack_detail
12248
12249 template <typename T, typename>
12250 struct unqualified_getter {
12251 static decltype(auto) get(lua_State* L, int index, record& tracking) {
12252 if constexpr (std::is_same_v<T, bool>) {
12253 tracking.use(1);
12254 return lua_toboolean(L, index) != 0;
12255 }
12256 else if constexpr (std::is_enum_v<T>) {
12257 tracking.use(1);
12258 return static_cast<T>(lua_tointegerx(L, index, nullptr));
12259 }
12260 else if constexpr (std::is_integral_v<T> || std::is_same_v<T, lua_Integer>) {
12261 tracking.use(1);
12262#if SOL_LUA_VESION_I_ >= 503
12263 if (lua_isinteger(L, index) != 0) {
12264 return static_cast<T>(lua_tointeger(L, index));
12265 }
12266#endif
12267 return static_cast<T>(llround(lua_tonumber(L, index)));
12268 }
12269 else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) {
12270 tracking.use(1);
12271 return static_cast<T>(lua_tonumber(L, index));
12272 }
12273 else if constexpr (is_lua_reference_v<T>) {
12274 tracking.use(1);
12275 return T(L, index);
12276 }
12277 else if constexpr (is_unique_usertype_v<T>) {
12278 using Real = typename unique_usertype_traits<T>::actual_type;
12279
12280 tracking.use(1);
12281 void* memory = lua_touserdata(L, index);
12282 memory = detail::align_usertype_unique<Real>(memory);
12283 Real* mem = static_cast<Real*>(memory);
12284 return *mem;
12285 }
12286 else if constexpr (meta::is_optional_v<T>) {
12287 using ValueType = typename T::value_type;
12288 return unqualified_check_getter<ValueType>::template get_using<T>(L, index, no_panic, tracking);
12289 }
12290 else if constexpr (std::is_same_v<T, luaL_Stream*>) {
12291 luaL_Stream* pstream = static_cast<luaL_Stream*>(lua_touserdata(L, index));
12292 return pstream;
12293 }
12294 else if constexpr (std::is_same_v<T, luaL_Stream>) {
12295 luaL_Stream* pstream = static_cast<luaL_Stream*>(lua_touserdata(L, index));
12296 return *pstream;
12297 }
12298#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
12299 else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
12300 return stack_detail::get_function_pointer<std::remove_pointer_t<T>>(L, index, tracking);
12301 }
12302#endif
12303 else {
12304 return stack_detail::unchecked_unqualified_get<detail::as_value_tag<T>>(L, index, tracking);
12305 }
12306 }
12307 };
12308
12309 template <typename X, typename>
12310 struct qualified_getter {
12311 static decltype(auto) get(lua_State* L, int index, record& tracking) {
12312 using Tu = meta::unqualified_t<X>;
12313 static constexpr bool is_userdata_of_some_kind
12314 = !std::is_reference_v<
12315 X> && is_container_v<Tu> && std::is_default_constructible_v<Tu> && !is_lua_primitive_v<Tu> && !is_transparent_argument_v<Tu>;
12316 if constexpr (is_userdata_of_some_kind) {
12317 if (type_of(L, index) == type::userdata) {
12318 return static_cast<Tu>(stack_detail::unchecked_unqualified_get<Tu>(L, index, tracking));
12319 }
12320 else {
12321 return stack_detail::unchecked_unqualified_get<sol::nested<Tu>>(L, index, tracking);
12322 }
12323 }
12324 else if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<Tu> && !is_base_rebindable_non_void_v<unique_usertype_traits<Tu>>) {
12325 using u_traits = unique_usertype_traits<Tu>;
12326 using T = typename u_traits::type;
12327 using Real = typename u_traits::actual_type;
12328 tracking.use(1);
12329 void* memory = lua_touserdata(L, index);
12330 memory = detail::align_usertype_unique_destructor(memory);
12331 detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
12332 if (&detail::usertype_unique_alloc_destroy<T, X> == pdx) {
12333 memory = detail::align_usertype_unique_tag<true, false>(memory);
12334 memory = detail::align_usertype_unique<Real, true, false>(memory);
12335 Real* mem = static_cast<Real*>(memory);
12336 return static_cast<Real>(*mem);
12337 }
12338 Real r(nullptr);
12339 if constexpr (!derive<T>::value) {
12340 // TODO: abort / terminate, maybe only in debug modes?
12341 return static_cast<Real>(std::move(r));
12342 }
12343 else {
12344 memory = detail::align_usertype_unique_tag<true, false>(memory);
12345 detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
12346 memory = detail::align_usertype_unique<Real, true, false>(memory);
12347 string_view ti = usertype_traits<T>::qualified_name();
12348 int cast_operation;
12349 if constexpr (is_base_rebindable_v<u_traits>) {
12350 using rebind_t = typename u_traits::template rebind_base<void>;
12351 string_view rebind_ti = usertype_traits<rebind_t>::qualified_name();
12352 cast_operation = ic(memory, &r, ti, rebind_ti);
12353 }
12354 else {
12355 string_view rebind_ti("");
12356 cast_operation = ic(memory, &r, ti, rebind_ti);
12357 }
12358 switch (cast_operation) {
12359 case 1: {
12360 // it's a perfect match,
12361 // alias memory directly
12362 Real* mem = static_cast<Real*>(memory);
12363 return static_cast<Real>(*mem);
12364 }
12365 case 2:
12366 // it's a base match, return the
12367 // aliased creation
12368 return static_cast<Real>(std::move(r));
12369 default:
12370 // uh oh..
12371 break;
12372 }
12373 // TODO: abort / terminate, maybe only in debug modes?
12374 return static_cast<Real>(r);
12375 }
12376 }
12377 else {
12378 return stack_detail::unchecked_unqualified_get<Tu>(L, index, tracking);
12379 }
12380 }
12381 };
12382
12383 template <typename T>
12384 struct unqualified_getter<as_table_t<T>> {
12385 using Tu = meta::unqualified_t<T>;
12386
12387 template <typename V>
12388 static void push_back_at_end(std::true_type, types<V>, lua_State* L, T& cont, std::size_t) {
12389 cont.push_back(stack::get<V>(L, -lua_size<V>::value));
12390 }
12391
12392 template <typename V>
12393 static void push_back_at_end(std::false_type, types<V> t, lua_State* L, T& cont, std::size_t idx) {
12394 insert_at_end(meta::has_insert<Tu>(), t, L, cont, idx);
12395 }
12396
12397 template <typename V>
12398 static void insert_at_end(std::true_type, types<V>, lua_State* L, T& cont, std::size_t) {
12399 using std::cend;
12400 cont.insert(cend(cont), stack::get<V>(L, -lua_size<V>::value));
12401 }
12402
12403 template <typename V>
12404 static void insert_at_end(std::false_type, types<V>, lua_State* L, T& cont, std::size_t idx) {
12405 cont[idx] = stack::get<V>(L, -lua_size<V>::value);
12406 }
12407
12408 static bool max_size_check(std::false_type, T&, std::size_t) {
12409 return false;
12410 }
12411
12412 static bool max_size_check(std::true_type, T& cont, std::size_t idx) {
12413 return idx >= cont.max_size();
12414 }
12415
12416 static T get(lua_State* L, int relindex, record& tracking) {
12417 return get(meta::is_associative<Tu>(), L, relindex, tracking);
12418 }
12419
12420 static T get(std::false_type, lua_State* L, int relindex, record& tracking) {
12421 typedef typename Tu::value_type V;
12422 return get(types<V>(), L, relindex, tracking);
12423 }
12424
12425 template <typename V>
12426 static T get(types<V> t, lua_State* L, int relindex, record& tracking) {
12427 tracking.use(1);
12428
12429 // the W4 flag is really great,
12430 // so great that it can tell my for loops (twice nested)
12431 // below never actually terminate
12432 // without hitting where the gotos have infested
12433
12434 // so now I would get the error W4XXX unreachable
12435 // me that the return cont at the end of this function
12436 // which is fair until other compilers complain
12437 // that there isn't a return and that based on
12438 // SOME MAGICAL FORCE
12439 // control flow falls off the end of a non-void function
12440 // so it needs to be there for the compilers that are
12441 // too flimsy to analyze the basic blocks...
12442 // (I'm sure I should file a bug but those compilers are already
12443 // in the wild; it doesn't matter if I fix them,
12444 // someone else is still going to get some old-ass compiler
12445 // and then bother me about the unclean build for the 30th
12446 // time)
12447
12448 // "Why not an IIFE?"
12449 // Because additional lambdas / functions which serve as
12450 // capture-all-and-then-invoke bloat binary sizes
12451 // by an actually detectable amount
12452 // (one user uses sol2 pretty heavily and 22 MB of binary size
12453 // was saved by reducing reliance on lambdas in templates)
12454
12455 // This would really be solved by having break N;
12456 // be a real, proper thing...
12457 // but instead, we have to use labels and gotos
12458 // and earn the universal vitriol of the dogmatic
12459 // programming community
12460
12461 // all in all: W4 is great!~
12462
12463 int index = lua_absindex(L, relindex);
12464 T cont;
12465 std::size_t idx = 0;
12466#if SOL_LUA_VESION_I_ >= 503
12467 // This method is HIGHLY performant over regular table iteration
12468 // thanks to the Lua API changes in 5.3
12469 // Questionable in 5.4
12470 for (lua_Integer i = 0;; i += lua_size<V>::value) {
12471 if (max_size_check(meta::has_max_size<Tu>(), cont, idx)) {
12472 // see above comment
12473 goto done;
12474 }
12475 bool isnil = false;
12476 for (int vi = 0; vi < lua_size<V>::value; ++vi) {
12477#if defined(LUA_NILINTABLE) && LUA_NILINTABLE && SOL_LUA_VESION_I_ >= 600
12478#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
12479 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
12480#endif // make sure stack doesn't overflow
12481 lua_pushinteger(L, static_cast<lua_Integer>(i + vi));
12482 if (lua_keyin(L, index) == 0) {
12483 // it's time to stop
12484 isnil = true;
12485 }
12486 else {
12487 // we have a key, have to get the value
12488 lua_geti(L, index, i + vi);
12489 }
12490#else
12491 type vt = static_cast<type>(lua_geti(L, index, i + vi));
12492 isnil = vt == type::none || vt == type::lua_nil;
12493#endif
12494 if (isnil) {
12495 if (i == 0) {
12496 break;
12497 }
12498#if defined(LUA_NILINTABLE) && LUA_NILINTABLE && SOL_LUA_VESION_I_ >= 600
12499 lua_pop(L, vi);
12500#else
12501 lua_pop(L, (vi + 1));
12502#endif
12503 // see above comment
12504 goto done;
12505 }
12506 }
12507 if (isnil) {
12508#if defined(LUA_NILINTABLE) && LUA_NILINTABLE && SOL_LUA_VESION_I_ >= 600
12509#else
12510 lua_pop(L, lua_size<V>::value);
12511#endif
12512 continue;
12513 }
12514
12515 push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx);
12516 ++idx;
12517 lua_pop(L, lua_size<V>::value);
12518 }
12519#else
12520 // Zzzz slower but necessary thanks to the lower version API and missing functions qq
12521 for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) {
12522 if (idx >= cont.max_size()) {
12523 // see above comment
12524 goto done;
12525 }
12526#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
12527 luaL_checkstack(L, 2, detail::not_enough_stack_space_generic);
12528#endif // make sure stack doesn't overflow
12529 bool isnil = false;
12530 for (int vi = 0; vi < lua_size<V>::value; ++vi) {
12531 lua_pushinteger(L, i);
12532 lua_gettable(L, index);
12533 type vt = type_of(L, -1);
12534 isnil = vt == type::lua_nil;
12535 if (isnil) {
12536 if (i == 0) {
12537 break;
12538 }
12539 lua_pop(L, (vi + 1));
12540 // see above comment
12541 goto done;
12542 }
12543 }
12544 if (isnil)
12545 continue;
12546 push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx);
12547 ++idx;
12548 }
12549#endif
12550 done:
12551 return cont;
12552 }
12553
12554 static T get(std::true_type, lua_State* L, int index, record& tracking) {
12555 typedef typename Tu::value_type P;
12556 typedef typename P::first_type K;
12557 typedef typename P::second_type V;
12558 return get(types<K, V>(), L, index, tracking);
12559 }
12560
12561 template <typename K, typename V>
12562 static T get(types<K, V>, lua_State* L, int relindex, record& tracking) {
12563 tracking.use(1);
12564
12565#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
12566 luaL_checkstack(L, 3, detail::not_enough_stack_space_generic);
12567#endif // make sure stack doesn't overflow
12568
12569 T associative;
12570 int index = lua_absindex(L, relindex);
12571 lua_pushnil(L);
12572 while (lua_next(L, index) != 0) {
12573 decltype(auto) key = stack::check_get<K>(L, -2);
12574 if (!key) {
12575 lua_pop(L, 1);
12576 continue;
12577 }
12578 associative.emplace(std::forward<decltype(*key)>(*key), stack::get<V>(L, -1));
12579 lua_pop(L, 1);
12580 }
12581 return associative;
12582 }
12583 };
12584
12585 template <typename T, typename Al>
12586 struct unqualified_getter<as_table_t<std::forward_list<T, Al>>> {
12587 typedef std::forward_list<T, Al> C;
12588
12589 static C get(lua_State* L, int relindex, record& tracking) {
12590 return get(meta::has_key_value_pair<C>(), L, relindex, tracking);
12591 }
12592
12593 static C get(std::true_type, lua_State* L, int index, record& tracking) {
12594 typedef typename T::value_type P;
12595 typedef typename P::first_type K;
12596 typedef typename P::second_type V;
12597 return get(types<K, V>(), L, index, tracking);
12598 }
12599
12600 static C get(std::false_type, lua_State* L, int relindex, record& tracking) {
12601 typedef typename C::value_type V;
12602 return get(types<V>(), L, relindex, tracking);
12603 }
12604
12605 template <typename V>
12606 static C get(types<V>, lua_State* L, int relindex, record& tracking) {
12607 tracking.use(1);
12608#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
12609 luaL_checkstack(L, 3, detail::not_enough_stack_space_generic);
12610#endif // make sure stack doesn't overflow
12611
12612 int index = lua_absindex(L, relindex);
12613 C cont;
12614 auto at = cont.cbefore_begin();
12615 std::size_t idx = 0;
12616#if SOL_LUA_VESION_I_ >= 503
12617 // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3
12618 for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) {
12619 if (idx >= cont.max_size()) {
12620 goto done;
12621 }
12622 bool isnil = false;
12623 for (int vi = 0; vi < lua_size<V>::value; ++vi) {
12624 type t = static_cast<type>(lua_geti(L, index, i + vi));
12625 isnil = t == type::lua_nil;
12626 if (isnil) {
12627 if (i == 0) {
12628 break;
12629 }
12630 lua_pop(L, (vi + 1));
12631 goto done;
12632 }
12633 }
12634 if (isnil)
12635 continue;
12636 at = cont.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
12637 ++idx;
12638 }
12639#else
12640 // Zzzz slower but necessary thanks to the lower version API and missing functions qq
12641 for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) {
12642 if (idx >= cont.max_size()) {
12643 goto done;
12644 }
12645 bool isnil = false;
12646 for (int vi = 0; vi < lua_size<V>::value; ++vi) {
12647 lua_pushinteger(L, i);
12648 lua_gettable(L, index);
12649 type t = type_of(L, -1);
12650 isnil = t == type::lua_nil;
12651 if (isnil) {
12652 if (i == 0) {
12653 break;
12654 }
12655 lua_pop(L, (vi + 1));
12656 goto done;
12657 }
12658 }
12659 if (isnil)
12660 continue;
12661 at = cont.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
12662 ++idx;
12663 }
12664#endif
12665 done:
12666 return cont;
12667 }
12668
12669 template <typename K, typename V>
12670 static C get(types<K, V>, lua_State* L, int relindex, record& tracking) {
12671 tracking.use(1);
12672
12673#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
12674 luaL_checkstack(L, 3, detail::not_enough_stack_space_generic);
12675#endif // make sure stack doesn't overflow
12676
12677 C associative;
12678 auto at = associative.cbefore_begin();
12679 int index = lua_absindex(L, relindex);
12680 lua_pushnil(L);
12681 while (lua_next(L, index) != 0) {
12682 decltype(auto) key = stack::check_get<K>(L, -2);
12683 if (!key) {
12684 lua_pop(L, 1);
12685 continue;
12686 }
12687 at = associative.emplace_after(at, std::forward<decltype(*key)>(*key), stack::get<V>(L, -1));
12688 lua_pop(L, 1);
12689 }
12690 return associative;
12691 }
12692 };
12693
12694 template <typename T>
12695 struct unqualified_getter<nested<T>> {
12696 static T get(lua_State* L, int index, record& tracking) {
12697 using Tu = meta::unqualified_t<T>;
12698 if constexpr (is_container_v<Tu>) {
12699 if constexpr (meta::is_associative<Tu>::value) {
12700 typedef typename T::value_type P;
12701 typedef typename P::first_type K;
12702 typedef typename P::second_type V;
12703 unqualified_getter<as_table_t<T>> g;
12704 // VC++ has a bad warning here: shut it up
12705 (void)g;
12706 return g.get(types<K, nested<V>>(), L, index, tracking);
12707 }
12708 else {
12709 typedef typename T::value_type V;
12710 unqualified_getter<as_table_t<T>> g;
12711 // VC++ has a bad warning here: shut it up
12712 (void)g;
12713 return g.get(types<nested<V>>(), L, index, tracking);
12714 }
12715 }
12716 else {
12717 unqualified_getter<Tu> g;
12718 // VC++ has a bad warning here: shut it up
12719 (void)g;
12720 return g.get(L, index, tracking);
12721 }
12722 }
12723 };
12724
12725 template <typename T>
12726 struct unqualified_getter<as_container_t<T>> {
12727 static decltype(auto) get(lua_State* L, int index, record& tracking) {
12728 return stack::unqualified_get<T>(L, index, tracking);
12729 }
12730 };
12731
12732 template <typename T>
12733 struct unqualified_getter<as_container_t<T>*> {
12734 static decltype(auto) get(lua_State* L, int index, record& tracking) {
12735 return stack::unqualified_get<T*>(L, index, tracking);
12736 }
12737 };
12738
12739 template <>
12740 struct unqualified_getter<userdata_value> {
12741 static userdata_value get(lua_State* L, int index, record& tracking) {
12742 tracking.use(1);
12743 return userdata_value(lua_touserdata(L, index));
12744 }
12745 };
12746
12747 template <>
12748 struct unqualified_getter<lightuserdata_value> {
12749 static lightuserdata_value get(lua_State* L, int index, record& tracking) {
12750 tracking.use(1);
12751 return lightuserdata_value(lua_touserdata(L, index));
12752 }
12753 };
12754
12755 template <typename T>
12756 struct unqualified_getter<light<T>> {
12757 static light<T> get(lua_State* L, int index, record& tracking) {
12758 tracking.use(1);
12759 void* memory = lua_touserdata(L, index);
12760 return light<T>(static_cast<T*>(memory));
12761 }
12762 };
12763
12764 template <typename T>
12765 struct unqualified_getter<user<T>> {
12766 static std::add_lvalue_reference_t<T> get(lua_State* L, int index, record& tracking) {
12767 tracking.use(1);
12768 void* memory = lua_touserdata(L, index);
12769 memory = detail::align_user<T>(memory);
12770 return *static_cast<std::remove_reference_t<T>*>(memory);
12771 }
12772 };
12773
12774 template <typename T>
12775 struct unqualified_getter<user<T*>> {
12776 static T* get(lua_State* L, int index, record& tracking) {
12777 tracking.use(1);
12778 void* memory = lua_touserdata(L, index);
12779 memory = detail::align_user<T*>(memory);
12780 return static_cast<T*>(memory);
12781 }
12782 };
12783
12784 template <>
12785 struct unqualified_getter<type> {
12786 static type get(lua_State* L, int index, record& tracking) {
12787 tracking.use(1);
12788 return static_cast<type>(lua_type(L, index));
12789 }
12790 };
12791
12792 template <>
12793 struct unqualified_getter<std::string> {
12794 static std::string get(lua_State* L, int index, record& tracking) {
12795 tracking.use(1);
12796 std::size_t len;
12797 auto str = lua_tolstring(L, index, &len);
12798 return std::string(str, len);
12799 }
12800 };
12801
12802 template <>
12803 struct unqualified_getter<const char*> {
12804 static const char* get(lua_State* L, int index, record& tracking) {
12805 tracking.use(1);
12806 size_t sz;
12807 return lua_tolstring(L, index, &sz);
12808 }
12809 };
12810
12811 template <>
12812 struct unqualified_getter<char> {
12813 static char get(lua_State* L, int index, record& tracking) {
12814 tracking.use(1);
12815 size_t len;
12816 auto str = lua_tolstring(L, index, &len);
12817 return len > 0 ? str[0] : '\0';
12818 }
12819 };
12820
12821 template <typename Traits>
12822 struct unqualified_getter<basic_string_view<char, Traits>> {
12823 static string_view get(lua_State* L, int index, record& tracking) {
12824 tracking.use(1);
12825 size_t sz;
12826 const char* str = lua_tolstring(L, index, &sz);
12827 return basic_string_view<char, Traits>(str, sz);
12828 }
12829 };
12830
12831 template <typename Traits, typename Al>
12832 struct unqualified_getter<std::basic_string<wchar_t, Traits, Al>> {
12833 using S = std::basic_string<wchar_t, Traits, Al>;
12834 static S get(lua_State* L, int index, record& tracking) {
12835 using Ch = meta::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t>;
12836 return stack_detail::get_into<Ch, S>(L, index, tracking);
12837 }
12838 };
12839
12840 template <typename Traits, typename Al>
12841 struct unqualified_getter<std::basic_string<char16_t, Traits, Al>> {
12842 static std::basic_string<char16_t, Traits, Al> get(lua_State* L, int index, record& tracking) {
12843 return stack_detail::get_into<char16_t, std::basic_string<char16_t, Traits, Al>>(L, index, tracking);
12844 }
12845 };
12846
12847 template <typename Traits, typename Al>
12848 struct unqualified_getter<std::basic_string<char32_t, Traits, Al>> {
12849 static std::basic_string<char32_t, Traits, Al> get(lua_State* L, int index, record& tracking) {
12850 return stack_detail::get_into<char32_t, std::basic_string<char32_t, Traits, Al>>(L, index, tracking);
12851 }
12852 };
12853
12854 template <>
12855 struct unqualified_getter<char16_t> {
12856 static char16_t get(lua_State* L, int index, record& tracking) {
12857 string_view utf8 = stack::get<string_view>(L, index, tracking);
12858 const char* strb = utf8.data();
12859 const char* stre = utf8.data() + utf8.size();
12860 char32_t cp = 0;
12861 auto dr = unicode::utf8_to_code_point(strb, stre);
12862 if (dr.error != unicode::error_code::ok) {
12863 cp = unicode::unicode_detail::replacement;
12864 }
12865 else {
12866 cp = dr.codepoint;
12867 }
12868 auto er = unicode::code_point_to_utf16(cp);
12869 return er.code_units[0];
12870 }
12871 };
12872
12873 template <>
12874 struct unqualified_getter<char32_t> {
12875 static char32_t get(lua_State* L, int index, record& tracking) {
12876 string_view utf8 = stack::get<string_view>(L, index, tracking);
12877 const char* strb = utf8.data();
12878 const char* stre = utf8.data() + utf8.size();
12879 char32_t cp = 0;
12880 auto dr = unicode::utf8_to_code_point(strb, stre);
12881 if (dr.error != unicode::error_code::ok) {
12882 cp = unicode::unicode_detail::replacement;
12883 }
12884 else {
12885 cp = dr.codepoint;
12886 }
12887 auto er = unicode::code_point_to_utf32(cp);
12888 return er.code_units[0];
12889 }
12890 };
12891
12892 template <>
12893 struct unqualified_getter<wchar_t> {
12894 static wchar_t get(lua_State* L, int index, record& tracking) {
12895 typedef meta::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t> Ch;
12896 unqualified_getter<Ch> g;
12897 (void)g;
12898 auto c = g.get(L, index, tracking);
12899 return static_cast<wchar_t>(c);
12900 }
12901 };
12902
12903 template <>
12904 struct unqualified_getter<meta_function> {
12905 static meta_function get(lua_State* L, int index, record& tracking) {
12906 tracking.use(1);
12907 const char* name = unqualified_getter<const char*> {}.get(L, index, tracking);
12908 const auto& mfnames = meta_function_names();
12909 for (std::size_t i = 0; i < mfnames.size(); ++i)
12910 if (mfnames[i] == name)
12911 return static_cast<meta_function>(i);
12912 return meta_function::construct;
12913 }
12914 };
12915
12916 template <>
12917 struct unqualified_getter<lua_nil_t> {
12918 static lua_nil_t get(lua_State*, int, record& tracking) {
12919 tracking.use(1);
12920 return lua_nil;
12921 }
12922 };
12923
12924 template <>
12925 struct unqualified_getter<std::nullptr_t> {
12926 static std::nullptr_t get(lua_State*, int, record& tracking) {
12927 tracking.use(1);
12928 return nullptr;
12929 }
12930 };
12931
12932 template <>
12933 struct unqualified_getter<nullopt_t> {
12934 static nullopt_t get(lua_State*, int, record& tracking) {
12935 tracking.use(1);
12936 return nullopt;
12937 }
12938 };
12939
12940 template <>
12941 struct unqualified_getter<this_state> {
12942 static this_state get(lua_State* L, int, record& tracking) {
12943 tracking.use(0);
12944 return this_state(L);
12945 }
12946 };
12947
12948 template <>
12949 struct unqualified_getter<this_main_state> {
12950 static this_main_state get(lua_State* L, int, record& tracking) {
12951 tracking.use(0);
12952 return this_main_state(main_thread(L, L));
12953 }
12954 };
12955
12956 template <>
12957 struct unqualified_getter<lua_CFunction> {
12958 static lua_CFunction get(lua_State* L, int index, record& tracking) {
12959 tracking.use(1);
12960 return lua_tocfunction(L, index);
12961 }
12962 };
12963
12964 template <>
12965 struct unqualified_getter<c_closure> {
12966 static c_closure get(lua_State* L, int index, record& tracking) {
12967 tracking.use(1);
12968 return c_closure(lua_tocfunction(L, index), -1);
12969 }
12970 };
12971
12972 template <>
12973 struct unqualified_getter<error> {
12974 static error get(lua_State* L, int index, record& tracking) {
12975 tracking.use(1);
12976 size_t sz = 0;
12977 const char* err = lua_tolstring(L, index, &sz);
12978 if (err == nullptr) {
12979 return error(detail::direct_error, "");
12980 }
12981 return error(detail::direct_error, std::string(err, sz));
12982 }
12983 };
12984
12985 template <>
12986 struct unqualified_getter<void*> {
12987 static void* get(lua_State* L, int index, record& tracking) {
12988 tracking.use(1);
12989 return lua_touserdata(L, index);
12990 }
12991 };
12992
12993 template <>
12994 struct unqualified_getter<const void*> {
12995 static const void* get(lua_State* L, int index, record& tracking) {
12996 tracking.use(1);
12997 return lua_touserdata(L, index);
12998 }
12999 };
13000
13001 template <typename T>
13002 struct unqualified_getter<detail::as_value_tag<T>> {
13003 static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
13004 void* memory = lua_touserdata(L, index);
13005#if SOL_IS_ON(SOL_USE_INTEROP_I_)
13006 auto ugr = stack_detail::interop_get<T>(L, index, memory, tracking);
13007 if (ugr.first) {
13008 return ugr.second;
13009 }
13010#endif // interop extensibility
13011 tracking.use(1);
13012 void* rawdata = detail::align_usertype_pointer(memory);
13013 void** pudata = static_cast<void**>(rawdata);
13014 void* udata = *pudata;
13015 return get_no_lua_nil_from(L, udata, index, tracking);
13016 }
13017
13018 static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) {
13019 bool has_derived = derive<T>::value || weak_derive<T>::value;
13020 if (has_derived) {
13021 if (lua_getmetatable(L, index) == 1) {
13022 lua_getfield(L, -1, &detail::base_class_cast_key()[0]);
13023 if (type_of(L, -1) != type::lua_nil) {
13024 void* basecastdata = lua_touserdata(L, -1);
13025 detail::inheritance_cast_function ic = reinterpret_cast<detail::inheritance_cast_function>(basecastdata);
13026 // use the casting function to properly adjust the pointer for the desired T
13027 udata = ic(udata, usertype_traits<T>::qualified_name());
13028 }
13029 lua_pop(L, 2);
13030 }
13031 }
13032 T* obj = static_cast<T*>(udata);
13033 return obj;
13034 }
13035
13036 static T& get(lua_State* L, int index, record& tracking) {
13037 return *get_no_lua_nil(L, index, tracking);
13038 }
13039 };
13040
13041 template <typename T>
13042 struct unqualified_getter<detail::as_pointer_tag<T>> {
13043 static T* get(lua_State* L, int index, record& tracking) {
13044 type t = type_of(L, index);
13045 if (t == type::lua_nil) {
13046 tracking.use(1);
13047 return nullptr;
13048 }
13049 unqualified_getter<detail::as_value_tag<T>> g;
13050 // Avoid VC++ warning
13051 (void)g;
13052 return g.get_no_lua_nil(L, index, tracking);
13053 }
13054 };
13055
13056 template <typename T>
13057 struct unqualified_getter<non_null<T*>> {
13058 static T* get(lua_State* L, int index, record& tracking) {
13059 unqualified_getter<detail::as_value_tag<T>> g;
13060 // Avoid VC++ warning
13061 (void)g;
13062 return g.get_no_lua_nil(L, index, tracking);
13063 }
13064 };
13065
13066 template <typename T>
13067 struct unqualified_getter<T&> {
13068 static T& get(lua_State* L, int index, record& tracking) {
13069 unqualified_getter<detail::as_value_tag<T>> g;
13070 // Avoid VC++ warning
13071 (void)g;
13072 return g.get(L, index, tracking);
13073 }
13074 };
13075
13076 template <typename T>
13077 struct unqualified_getter<std::reference_wrapper<T>> {
13078 static T& get(lua_State* L, int index, record& tracking) {
13079 unqualified_getter<T&> g;
13080 // Avoid VC++ warning
13081 (void)g;
13082 return g.get(L, index, tracking);
13083 }
13084 };
13085
13086 template <typename T>
13087 struct unqualified_getter<T*> {
13088 static T* get(lua_State* L, int index, record& tracking) {
13089#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
13090 if constexpr (std::is_function_v<T>) {
13091 return stack_detail::get_function_pointer<T>(L, index, tracking);
13092 }
13093 else {
13094 unqualified_getter<detail::as_pointer_tag<T>> g;
13095 // Avoid VC++ warning
13096 (void)g;
13097 return g.get(L, index, tracking);
13098 }
13099#else
13100 unqualified_getter<detail::as_pointer_tag<T>> g;
13101 // Avoid VC++ warning
13102 (void)g;
13103 return g.get(L, index, tracking);
13104#endif
13105 }
13106 };
13107
13108 template <typename... Tn>
13109 struct unqualified_getter<std::tuple<Tn...>> {
13110 typedef std::tuple<decltype(stack::get<Tn>(nullptr, 0))...> R;
13111
13112 template <typename... Args>
13113 static R apply(std::index_sequence<>, lua_State*, int, record&, Args&&... args) {
13114 // Fuck you too, VC++
13115 return R { std::forward<Args>(args)... };
13116 }
13117
13118 template <std::size_t I, std::size_t... Ix, typename... Args>
13119 static R apply(std::index_sequence<I, Ix...>, lua_State* L, int index, record& tracking, Args&&... args) {
13120 // Fuck you too, VC++
13121 typedef std::tuple_element_t<I, std::tuple<Tn...>> T;
13122 return apply(std::index_sequence<Ix...>(), L, index, tracking, std::forward<Args>(args)..., stack::get<T>(L, index + tracking.used, tracking));
13123 }
13124
13125 static R get(lua_State* L, int index, record& tracking) {
13126 return apply(std::make_index_sequence<sizeof...(Tn)>(), L, index, tracking);
13127 }
13128 };
13129
13130 template <typename A, typename B>
13131 struct unqualified_getter<std::pair<A, B>> {
13132 static decltype(auto) get(lua_State* L, int index, record& tracking) {
13133 return std::pair<decltype(stack::get<A>(L, index)), decltype(stack::get<B>(L, index))> { stack::get<A>(L, index, tracking),
13134 stack::get<B>(L, index + tracking.used, tracking) };
13135 }
13136 };
13137
13138#if SOL_IS_ON(SOL_STD_VARIANT_I_)
13139
13140 template <typename... Tn>
13141 struct unqualified_getter<std::variant<Tn...>> {
13142 using V = std::variant<Tn...>;
13143
13144 static V get_one(std::integral_constant<std::size_t, std::variant_size_v<V>>, lua_State* L, int index, record& tracking) {
13145 (void)L;
13146 (void)index;
13147 (void)tracking;
13148 if constexpr (std::variant_size_v<V> == 0) {
13149 return V();
13150 }
13151 else {
13152 // using T = std::variant_alternative_t<0, V>;
13153 std::abort();
13154 // return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));
13155 }
13156 }
13157
13158 template <std::size_t I>
13159 static V get_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, record& tracking) {
13160 typedef std::variant_alternative_t<I, V> T;
13161 record temp_tracking = tracking;
13162 if (stack::check<T>(L, index, no_panic, temp_tracking)) {
13163 tracking = temp_tracking;
13164 return V(std::in_place_index<I>, stack::get<T>(L, index));
13165 }
13166 return get_one(std::integral_constant<std::size_t, I + 1>(), L, index, tracking);
13167 }
13168
13169 static V get(lua_State* L, int index, record& tracking) {
13170 return get_one(std::integral_constant<std::size_t, 0>(), L, index, tracking);
13171 }
13172 };
13173#endif // variant
13174
13175}} // namespace sol::stack
13176
13177// end of sol/stack_get_unqualified.hpp
13178
13179// beginning of sol/stack_get_qualified.hpp
13180
13181namespace sol {
13182namespace stack {
13183
13184 // There are no more enable_ifs that can be used here,
13185 // so this is just for posterity, I guess?
13186 // maybe I'll fill this file in later.
13187
13188}
13189} // namespace sol::stack
13190
13191// end of sol/stack_get_qualified.hpp
13192
13193// end of sol/stack_get.hpp
13194
13195// beginning of sol/stack_check_get.hpp
13196
13197// beginning of sol/stack_check_get_unqualified.hpp
13198
13199#include <cstdlib>
13200#include <cmath>
13201#include <optional>
13202#if SOL_IS_ON(SOL_STD_VARIANT_I_)
13203#include <variant>
13204#endif // variant shenanigans (thanks, Mac OSX)
13205
13206namespace sol { namespace stack {
13207 template <typename T, typename>
13208 struct unqualified_check_getter {
13209 typedef decltype(stack_detail::unchecked_unqualified_get<T>(nullptr, -1, std::declval<record&>())) R;
13210
13211 template <typename Optional, typename Handler>
13212 static Optional get_using(lua_State* L, int index, Handler&& handler, record& tracking) {
13213 if constexpr (!meta::meta_detail::is_adl_sol_lua_check_v<T> && !meta::meta_detail::is_adl_sol_lua_get_v<T>) {
13214 if constexpr (is_lua_reference_v<T>) {
13215 // actually check if it's none here, otherwise
13216 // we'll have a none object inside an optional!
13217 bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, no_panic);
13218 if (!success) {
13219 // expected type, actual type
13220 tracking.use(static_cast<int>(success));
13221 handler(L, index, type::poly, type_of(L, index), "");
13222 return detail::associated_nullopt_v<Optional>;
13223 }
13224 return stack_detail::unchecked_get<T>(L, index, tracking);
13225 }
13226 else if constexpr ((std::is_integral_v<T> || std::is_same_v<T, lua_Integer>)&&!std::is_same_v<T, bool>) {
13227#if SOL_LUA_VESION_I_ >= 503
13228 if (lua_isinteger(L, index) != 0) {
13229 tracking.use(1);
13230 return static_cast<T>(lua_tointeger(L, index));
13231 }
13232#endif
13233 int isnum = 0;
13234 const lua_Number value = lua_tonumberx(L, index, &isnum);
13235 if (isnum != 0) {
13236#if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS_I_)
13237 const auto integer_value = llround(value);
13238 if (static_cast<lua_Number>(integer_value) == value) {
13239 tracking.use(1);
13240 return static_cast<T>(integer_value);
13241 }
13242#else
13243 tracking.use(1);
13244 return static_cast<T>(value);
13245#endif
13246 }
13247 const type t = type_of(L, index);
13248 tracking.use(static_cast<int>(t != type::none));
13249 handler(L, index, type::number, t, "not an integer");
13250 return detail::associated_nullopt_v<Optional>;
13251 }
13252 else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) {
13253 int isnum = 0;
13254 lua_Number value = lua_tonumberx(L, index, &isnum);
13255 if (isnum == 0) {
13256 type t = type_of(L, index);
13257 tracking.use(static_cast<int>(t != type::none));
13258 handler(L, index, type::number, t, "not a valid floating point number");
13259 return detail::associated_nullopt_v<Optional>;
13260 }
13261 tracking.use(1);
13262 return static_cast<T>(value);
13263 }
13264 else if constexpr (std::is_enum_v<T> && !meta::any_same_v<T, meta_function, type>) {
13265 int isnum = 0;
13266 lua_Integer value = lua_tointegerx(L, index, &isnum);
13267 if (isnum == 0) {
13268 type t = type_of(L, index);
13269 tracking.use(static_cast<int>(t != type::none));
13270 handler(L, index, type::number, t, "not a valid enumeration value");
13271 return detail::associated_nullopt_v<Optional>;
13272 }
13273 tracking.use(1);
13274 return static_cast<T>(value);
13275 }
13276 else {
13277 if (!unqualified_check<T>(L, index, std::forward<Handler>(handler))) {
13278 tracking.use(static_cast<int>(!lua_isnone(L, index)));
13279 return detail::associated_nullopt_v<Optional>;
13280 }
13281 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
13282 }
13283 }
13284 else {
13285 if (!unqualified_check<T>(L, index, std::forward<Handler>(handler))) {
13286 tracking.use(static_cast<int>(!lua_isnone(L, index)));
13287 return detail::associated_nullopt_v<Optional>;
13288 }
13289 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
13290 }
13291 }
13292
13293 template <typename Handler>
13294 static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) {
13295 return get_using<optional<R>>(L, index, std::forward<Handler>(handler), tracking);
13296 }
13297 };
13298
13299#if SOL_IS_ON(SOL_STD_VARIANT_I_)
13300 template <typename... Tn, typename C>
13301 struct unqualified_check_getter<std::variant<Tn...>, C> {
13302 typedef std::variant<Tn...> V;
13303 typedef std::variant_size<V> V_size;
13304 typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
13305
13306 template <typename Handler>
13307 static optional<V> get_empty(std::true_type, lua_State*, int, Handler&&, record&) {
13308 return nullopt;
13309 }
13310
13311 template <typename Handler>
13312 static optional<V> get_empty(std::false_type, lua_State* L, int index, Handler&& handler, record&) {
13313 // This should never be reached...
13314 // please check your code and understand what you did to bring yourself here
13315 // maybe file a bug report, or 5
13316 handler(
13317 L, index, type::poly, type_of(L, index), "this variant code should never be reached: if it has, you have done something so terribly wrong");
13318 return nullopt;
13319 }
13320
13321 template <typename Handler>
13322 static optional<V> get_one(std::integral_constant<std::size_t, 0>, lua_State* L, int index, Handler&& handler, record& tracking) {
13323 return get_empty(V_is_empty(), L, index, std::forward<Handler>(handler), tracking);
13324 }
13325
13326 template <std::size_t I, typename Handler>
13327 static optional<V> get_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, Handler&& handler, record& tracking) {
13328 typedef std::variant_alternative_t<I - 1, V> T;
13329 if (stack::check<T>(L, index, no_panic, tracking)) {
13330 return V(std::in_place_index<I - 1>, stack::get<T>(L, index));
13331 }
13332 return get_one(std::integral_constant<std::size_t, I - 1>(), L, index, std::forward<Handler>(handler), tracking);
13333 }
13334
13335 template <typename Handler>
13336 static optional<V> get(lua_State* L, int index, Handler&& handler, record& tracking) {
13337 return get_one(std::integral_constant<std::size_t, V_size::value>(), L, index, std::forward<Handler>(handler), tracking);
13338 }
13339 };
13340#endif // standard variant
13341}} // namespace sol::stack
13342
13343// end of sol/stack_check_get_unqualified.hpp
13344
13345// beginning of sol/stack_check_get_qualified.hpp
13346
13347namespace sol { namespace stack {
13348 template <typename T, typename C>
13349 struct qualified_check_getter {
13350 typedef decltype(stack_detail::unchecked_get<T>(nullptr, -1, std::declval<record&>())) R;
13351
13352 template <typename Handler>
13353 static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) {
13354 if constexpr (is_lua_reference_v<T>) {
13355 // actually check if it's none here, otherwise
13356 // we'll have a none object inside an optional!
13357 bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, no_panic);
13358 if (!success) {
13359 // expected type, actual type
13360 tracking.use(static_cast<int>(success));
13361 handler(L, index, type::poly, type_of(L, index), "");
13362 return nullopt;
13363 }
13364 return stack_detail::unchecked_get<T>(L, index, tracking);
13365 }
13366 else {
13367 if (!check<T>(L, index, std::forward<Handler>(handler))) {
13368 tracking.use(static_cast<int>(!lua_isnone(L, index)));
13369 return nullopt;
13370 }
13371 return stack_detail::unchecked_get<T>(L, index, tracking);
13372 }
13373 }
13374 };
13375
13376 template <typename T>
13377 struct qualified_getter<T, std::enable_if_t<meta::is_optional_v<T>>> {
13378 static T get(lua_State* L, int index, record& tracking) {
13379 using ValueType = typename meta::unqualified_t<T>::value_type;
13380 if constexpr (is_lua_reference_v<ValueType>) {
13381 // actually check if it's none here, otherwise
13382 // we'll have a none object inside an optional!
13383 bool success = lua_isnoneornil(L, index) == 0 && stack::check<ValueType>(L, index, no_panic);
13384 if (!success) {
13385 // expected type, actual type
13386 tracking.use(static_cast<int>(success));
13387 return {};
13388 }
13389 return stack_detail::unchecked_get<ValueType>(L, index, tracking);
13390 }
13391 else {
13392 if (!check<ValueType>(L, index, &no_panic)) {
13393 tracking.use(static_cast<int>(!lua_isnone(L, index)));
13394 return {};
13395 }
13396 return stack_detail::unchecked_get<ValueType>(L, index, tracking);
13397 }
13398 }
13399 };
13400
13401}} // namespace sol::stack
13402
13403// end of sol/stack_check_get_qualified.hpp
13404
13405// end of sol/stack_check_get.hpp
13406
13407// beginning of sol/stack_push.hpp
13408
13409#include <memory>
13410#include <type_traits>
13411#include <cassert>
13412#include <limits>
13413#include <cmath>
13414#include <string_view>
13415#if SOL_IS_ON(SOL_STD_VARIANT_I_)
13416#include <variant>
13417#endif // Can use variant
13418
13419namespace sol { namespace stack {
13420 namespace stack_detail {
13421 template <typename T>
13422 inline bool integer_value_fits(const T& value) {
13423 if constexpr (sizeof(T) < sizeof(lua_Integer) || (std::is_signed_v<T> && sizeof(T) == sizeof(lua_Integer))) {
13424 (void)value;
13425 return true;
13426 }
13427 else {
13428 auto u_min = static_cast<std::intmax_t>((std::numeric_limits<lua_Integer>::min)());
13429 auto u_max = static_cast<std::uintmax_t>((std::numeric_limits<lua_Integer>::max)());
13430 auto t_min = static_cast<std::intmax_t>((std::numeric_limits<T>::min)());
13431 auto t_max = static_cast<std::uintmax_t>((std::numeric_limits<T>::max)());
13432 return (u_min <= t_min || value >= static_cast<T>(u_min)) && (u_max >= t_max || value <= static_cast<T>(u_max));
13433 }
13434 }
13435
13436 template <typename T>
13437 int msvc_is_ass_with_if_constexpr_push_enum(std::true_type, lua_State* L, const T& value) {
13438 if constexpr (meta::any_same_v<std::underlying_type_t<T>, char /*, char8_t*/, char16_t, char32_t>) {
13439 if constexpr (std::is_signed_v<T>) {
13440 return stack::push(L, static_cast<std::int_least32_t>(value));
13441 }
13442 else {
13443 return stack::push(L, static_cast<std::uint_least32_t>(value));
13444 }
13445 }
13446 else {
13447 return stack::push(L, static_cast<std::underlying_type_t<T>>(value));
13448 }
13449 }
13450
13451 template <typename T>
13452 int msvc_is_ass_with_if_constexpr_push_enum(std::false_type, lua_State*, const T&) {
13453 return 0;
13454 }
13455 } // namespace stack_detail
13456
13457 inline int push_environment_of(lua_State* L, int index = -1) {
13458#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13459 luaL_checkstack(L, 1, detail::not_enough_stack_space_environment);
13460#endif // make sure stack doesn't overflow
13461#if SOL_LUA_VESION_I_ < 502
13462 // Use lua_getfenv
13463 lua_getfenv(L, index);
13464#else
13465 // Use upvalues as explained in Lua 5.2 and beyond's manual
13466 if (lua_getupvalue(L, index, 1) == nullptr) {
13467 push(L, lua_nil);
13468 return 1;
13469 }
13470#endif
13471 return 1;
13472 }
13473
13474 template <typename T>
13475 int push_environment_of(const T& target) {
13476 target.push();
13477 return push_environment_of(target.lua_state(), -1) + 1;
13478 }
13479
13480 template <typename T>
13481 struct unqualified_pusher<detail::as_value_tag<T>> {
13482 template <typename F, typename... Args>
13483 static int push_fx(lua_State* L, F&& f, Args&&... args) {
13484#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13485 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
13486#endif // make sure stack doesn't overflow
13487 // Basically, we store all user-data like this:
13488 // If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new
13489 // data in the first sizeof(T*) bytes, and then however many bytes it takes to
13490 // do the actual object. Things that are std::ref or plain T* are stored as
13491 // just the sizeof(T*), and nothing else.
13492 T* obj = detail::usertype_allocate<T>(L);
13493 f();
13494 std::allocator<T> alloc {};
13495 std::allocator_traits<std::allocator<T>>::construct(alloc, obj, std::forward<Args>(args)...);
13496 return 1;
13497 }
13498
13499 template <typename K, typename... Args>
13500 static int push_keyed(lua_State* L, K&& k, Args&&... args) {
13501 stack_detail::undefined_metatable fx(L, &k[0], &stack::stack_detail::set_undefined_methods_on<T>);
13502 return push_fx(L, fx, std::forward<Args>(args)...);
13503 }
13504
13505 template <typename Arg, typename... Args>
13506 static int push(lua_State* L, Arg&& arg, Args&&... args) {
13507 if constexpr (std::is_same_v<meta::unqualified_t<Arg>, detail::with_function_tag>) {
13508 (void)arg;
13509 return push_fx(L, std::forward<Args>(args)...);
13510 }
13511 else {
13512 return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Arg>(arg), std::forward<Args>(args)...);
13513 }
13514 }
13515
13516 static int push(lua_State* L) {
13517 return push_keyed(L, usertype_traits<T>::metatable());
13518 }
13519 };
13520
13521 template <typename T>
13522 struct unqualified_pusher<detail::as_pointer_tag<T>> {
13523 typedef meta::unqualified_t<T> U;
13524
13525 template <typename F>
13526 static int push_fx(lua_State* L, F&& f, T* obj) {
13527 if (obj == nullptr)
13528 return stack::push(L, lua_nil);
13529#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13530 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
13531#endif // make sure stack doesn't overflow
13532 T** pref = detail::usertype_allocate_pointer<T>(L);
13533 f();
13534 *pref = obj;
13535 return 1;
13536 }
13537
13538 template <typename K>
13539 static int push_keyed(lua_State* L, K&& k, T* obj) {
13540 stack_detail::undefined_metatable fx(L, &k[0], &stack::stack_detail::set_undefined_methods_on<U*>);
13541 return push_fx(L, fx, obj);
13542 }
13543
13544 template <typename Arg, typename... Args>
13545 static int push(lua_State* L, Arg&& arg, Args&&... args) {
13546 if constexpr (std::is_same_v<meta::unqualified_t<Arg>, detail::with_function_tag>) {
13547 (void)arg;
13548 return push_fx(L, std::forward<Args>(args)...);
13549 }
13550 else {
13551 return push_keyed(L, usertype_traits<U*>::metatable(), std::forward<Arg>(arg), std::forward<Args>(args)...);
13552 }
13553 }
13554 };
13555
13556 template <>
13557 struct unqualified_pusher<detail::as_reference_tag> {
13558 template <typename T>
13559 static int push(lua_State* L, T&& obj) {
13560 return stack::push(L, detail::ptr(obj));
13561 }
13562 };
13563
13564 namespace stack_detail {
13565 template <typename T>
13566 struct uu_pusher {
13567 using u_traits = unique_usertype_traits<T>;
13568 using P = typename u_traits::type;
13569 using Real = typename u_traits::actual_type;
13570
13571 template <typename Arg, typename... Args>
13572 static int push(lua_State* L, Arg&& arg, Args&&... args) {
13573 if constexpr (std::is_base_of_v<Real, meta::unqualified_t<Arg>>) {
13574 if (u_traits::is_null(arg)) {
13575 return stack::push(L, lua_nil);
13576 }
13577 return push_deep(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
13578 }
13579 else {
13580 return push_deep(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
13581 }
13582 }
13583
13584 template <typename... Args>
13585 static int push_deep(lua_State* L, Args&&... args) {
13586#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13587 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
13588#endif // make sure stack doesn't overflow
13589 P** pref = nullptr;
13590 detail::unique_destructor* fx = nullptr;
13591 detail::unique_tag* id = nullptr;
13592 Real* mem = detail::usertype_unique_allocate<P, Real>(L, pref, fx, id);
13593 if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<std::remove_cv_t<P>>>::metatable()[0]) == 1) {
13594 detail::lua_reg_table l {};
13595 int index = 0;
13596 detail::indexed_insert insert_fx(l, index);
13597 detail::insert_default_registrations<P>(insert_fx, detail::property_always_true);
13598 l[index] = { to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<T>() };
13599 luaL_setfuncs(L, l, 0);
13600 }
13601 lua_setmetatable(L, -2);
13602 *fx = detail::usertype_unique_alloc_destroy<P, Real>;
13603 *id = &detail::inheritance<P>::template type_unique_cast<Real>;
13604 detail::default_construct::construct(mem, std::forward<Args>(args)...);
13605 *pref = unique_usertype_traits<T>::get(*mem);
13606 return 1;
13607 }
13608 };
13609 } // namespace stack_detail
13610
13611 template <typename T>
13612 struct unqualified_pusher<detail::as_unique_tag<T>> {
13613 template <typename... Args>
13614 static int push(lua_State* L, Args&&... args) {
13615 stack_detail::uu_pusher<T> p;
13616 (void)p;
13617 return p.push(L, std::forward<Args>(args)...);
13618 }
13619 };
13620
13621 template <typename T, typename>
13622 struct unqualified_pusher {
13623 template <typename... Args>
13624 static int push(lua_State* L, Args&&... args) {
13625 using Tu = meta::unqualified_t<T>;
13626 if constexpr (is_lua_reference_v<Tu>) {
13627 using int_arr = int[];
13628 int_arr p { (std::forward<Args>(args).push(L))... };
13629 return p[0];
13630 }
13631 else if constexpr (std::is_same_v<Tu, bool>) {
13632#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13633 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13634#endif // make sure stack doesn't overflow
13635 lua_pushboolean(L, std::forward<Args>(args)...);
13636 return 1;
13637 }
13638 else if constexpr (std::is_integral_v<Tu> || std::is_same_v<Tu, lua_Integer>) {
13639 const Tu& value(std::forward<Args>(args)...);
13640#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13641 luaL_checkstack(L, 1, detail::not_enough_stack_space_integral);
13642#endif // make sure stack doesn't overflow
13643#if SOL_LUA_VESION_I_ >= 503
13644 if (stack_detail::integer_value_fits<Tu>(value)) {
13645 lua_pushinteger(L, static_cast<lua_Integer>(value));
13646 return 1;
13647 }
13648#endif // Lua 5.3 and above
13649#if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS_I_)
13650 if (static_cast<T>(llround(static_cast<lua_Number>(value))) != value) {
13651#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
13652 // Is this really worth it?
13653 assert(false && "integer value will be misrepresented in lua");
13654 lua_pushinteger(L, static_cast<lua_Integer>(value));
13655 return 1;
13656#else
13657 throw error(detail::direct_error, "integer value will be misrepresented in lua");
13658#endif // No Exceptions
13659 }
13660#endif // Safe Numerics and Number Precision Check
13661 lua_pushnumber(L, static_cast<lua_Number>(value));
13662 return 1;
13663 }
13664 else if constexpr (std::is_floating_point_v<Tu> || std::is_same_v<Tu, lua_Number>) {
13665#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13666 luaL_checkstack(L, 1, detail::not_enough_stack_space_floating);
13667#endif // make sure stack doesn't overflow
13668 lua_pushnumber(L, std::forward<Args>(args)...);
13669 return 1;
13670 }
13671 else if constexpr (std::is_same_v<Tu, luaL_Stream*>) {
13672 luaL_Stream* source { std::forward<Args>(args)... };
13673 luaL_Stream* stream = static_cast<luaL_Stream*>(lua_newuserdata(L, sizeof(luaL_Stream)));
13674 stream->f = source->f;
13675#if SOL_IS_ON(SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_)
13676 stream->closef = source->closef;
13677#endif // LuaJIT and Lua 5.1 and below do not have
13678 return 1;
13679 }
13680 else if constexpr (std::is_same_v<Tu, luaL_Stream>) {
13681 luaL_Stream& source(std::forward<Args>(args)...);
13682 luaL_Stream* stream = static_cast<luaL_Stream*>(lua_newuserdata(L, sizeof(luaL_Stream)));
13683 stream->f = source.f;
13684#if SOL_IS_ON(SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_)
13685 stream->closef = source.closef;
13686#endif // LuaJIT and Lua 5.1 and below do not have
13687 return 1;
13688 }
13689 else if constexpr (std::is_enum_v<Tu>) {
13690 return stack_detail::msvc_is_ass_with_if_constexpr_push_enum(std::true_type(), L, std::forward<Args>(args)...);
13691 }
13692 else if constexpr (std::is_pointer_v<Tu>) {
13693 return stack::push<detail::as_pointer_tag<std::remove_pointer_t<T>>>(L, std::forward<Args>(args)...);
13694 }
13695 else if constexpr (is_unique_usertype_v<Tu>) {
13696 return stack::push<detail::as_unique_tag<T>>(L, std::forward<Args>(args)...);
13697 }
13698 else {
13699 return stack::push<detail::as_value_tag<T>>(L, std::forward<Args>(args)...);
13700 }
13701 }
13702 };
13703
13704 template <typename T>
13705 struct unqualified_pusher<std::reference_wrapper<T>> {
13706 static int push(lua_State* L, const std::reference_wrapper<T>& t) {
13707 return stack::push(L, std::addressof(detail::deref(t.get())));
13708 }
13709 };
13710
13711 template <typename T>
13712 struct unqualified_pusher<detail::as_table_tag<T>> {
13713 using has_kvp = meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>>;
13714
13715 static int push(lua_State* L, const T& tablecont) {
13716 return push(has_kvp(), std::false_type(), L, tablecont);
13717 }
13718
13719 static int push(lua_State* L, const T& tablecont, nested_tag_t) {
13720 return push(has_kvp(), std::true_type(), L, tablecont);
13721 }
13722
13723 static int push(std::true_type, lua_State* L, const T& tablecont) {
13724 return push(has_kvp(), std::true_type(), L, tablecont);
13725 }
13726
13727 static int push(std::false_type, lua_State* L, const T& tablecont) {
13728 return push(has_kvp(), std::false_type(), L, tablecont);
13729 }
13730
13731 template <bool is_nested>
13732 static int push(std::true_type, std::integral_constant<bool, is_nested>, lua_State* L, const T& tablecont) {
13733 auto& cont = detail::deref(detail::unwrap(tablecont));
13734 lua_createtable(L, static_cast<int>(cont.size()), 0);
13735 int tableindex = lua_gettop(L);
13736 for (const auto& pair : cont) {
13737 if (is_nested) {
13738 set_field(L, pair.first, as_nested_ref(pair.second), tableindex);
13739 }
13740 else {
13741 set_field(L, pair.first, pair.second, tableindex);
13742 }
13743 }
13744 return 1;
13745 }
13746
13747 template <bool is_nested>
13748 static int push(std::false_type, std::integral_constant<bool, is_nested>, lua_State* L, const T& tablecont) {
13749 auto& cont = detail::deref(detail::unwrap(tablecont));
13750 lua_createtable(L, stack_detail::get_size_hint(cont), 0);
13751 int tableindex = lua_gettop(L);
13752 std::size_t index = 1;
13753 for (const auto& i : cont) {
13754#if SOL_LUA_VESION_I_ >= 503
13755 int p = is_nested ? stack::push(L, as_nested_ref(i)) : stack::push(L, i);
13756 for (int pi = 0; pi < p; ++pi) {
13757 lua_seti(L, tableindex, static_cast<lua_Integer>(index++));
13758 }
13759#else
13760#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13761 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13762#endif // make sure stack doesn't overflow
13763 lua_pushinteger(L, static_cast<lua_Integer>(index));
13764 int p = is_nested ? stack::push(L, as_nested_ref(i)) : stack::push(L, i);
13765 if (p == 1) {
13766 ++index;
13767 lua_settable(L, tableindex);
13768 }
13769 else {
13770 int firstindex = tableindex + 1 + 1;
13771 for (int pi = 0; pi < p; ++pi) {
13772 stack::push(L, index);
13773#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13774 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13775#endif // make sure stack doesn't overflow
13776 lua_pushvalue(L, firstindex);
13777 lua_settable(L, tableindex);
13778 ++index;
13779 ++firstindex;
13780 }
13781 lua_pop(L, 1 + p);
13782 }
13783#endif // Lua Version 5.3 and others
13784 }
13785 // TODO: figure out a better way to do this...?
13786 // set_field(L, -1, cont.size());
13787 return 1;
13788 }
13789 };
13790
13791 template <typename T>
13792 struct unqualified_pusher<as_table_t<T>> {
13793 static int push(lua_State* L, const T& v) {
13794 using inner_t = std::remove_pointer_t<meta::unwrap_unqualified_t<T>>;
13795 if constexpr (is_container_v<inner_t>) {
13796 return stack::push<detail::as_table_tag<T>>(L, v);
13797 }
13798 else {
13799 return stack::push(L, v);
13800 }
13801 }
13802 };
13803
13804 template <typename T>
13805 struct unqualified_pusher<nested<T>> {
13806 static int push(lua_State* L, const T& tablecont) {
13807 using Tu = meta::unwrap_unqualified_t<T>;
13808 using inner_t = std::remove_pointer_t<Tu>;
13809 if constexpr (is_container_v<inner_t>) {
13810 return stack::push<detail::as_table_tag<T>>(L, tablecont, nested_tag);
13811 }
13812 else {
13813 return stack::push<Tu>(L, tablecont);
13814 }
13815 }
13816 };
13817
13818 template <typename T>
13819 struct unqualified_pusher<std::initializer_list<T>> {
13820 static int push(lua_State* L, const std::initializer_list<T>& il) {
13821 unqualified_pusher<detail::as_table_tag<std::initializer_list<T>>> p {};
13822 // silence annoying VC++ warning
13823 (void)p;
13824 return p.push(L, il);
13825 }
13826 };
13827
13828 template <>
13829 struct unqualified_pusher<lua_nil_t> {
13830 static int push(lua_State* L, lua_nil_t) {
13831#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13832 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13833#endif // make sure stack doesn't overflow
13834 lua_pushnil(L);
13835 return 1;
13836 }
13837 };
13838
13839 template <>
13840 struct unqualified_pusher<stack_count> {
13841 static int push(lua_State*, stack_count st) {
13842 return st.count;
13843 }
13844 };
13845
13846 template <>
13847 struct unqualified_pusher<metatable_key_t> {
13848 static int push(lua_State* L, metatable_key_t) {
13849#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13850 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13851#endif // make sure stack doesn't overflow
13852 lua_pushlstring(L, to_string(meta_function::metatable).c_str(), 4);
13853 return 1;
13854 }
13855 };
13856
13857 template <>
13858 struct unqualified_pusher<std::remove_pointer_t<lua_CFunction>> {
13859 static int push(lua_State* L, lua_CFunction func, int n = 0) {
13860#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13861 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13862#endif // make sure stack doesn't overflow
13863 lua_pushcclosure(L, func, n);
13864 return 1;
13865 }
13866 };
13867
13868 template <>
13869 struct unqualified_pusher<lua_CFunction> {
13870 static int push(lua_State* L, lua_CFunction func, int n = 0) {
13871#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13872 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13873#endif // make sure stack doesn't overflow
13874 lua_pushcclosure(L, func, n);
13875 return 1;
13876 }
13877 };
13878
13879#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
13880 template <>
13881 struct unqualified_pusher<std::remove_pointer_t<detail::lua_CFunction_noexcept>> {
13882 static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) {
13883#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13884 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13885#endif // make sure stack doesn't overflow
13886 lua_pushcclosure(L, func, n);
13887 return 1;
13888 }
13889 };
13890
13891 template <>
13892 struct unqualified_pusher<detail::lua_CFunction_noexcept> {
13893 static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) {
13894#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13895 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13896#endif // make sure stack doesn't overflow
13897 lua_pushcclosure(L, func, n);
13898 return 1;
13899 }
13900 };
13901#endif // noexcept function type
13902
13903 template <>
13904 struct unqualified_pusher<c_closure> {
13905 static int push(lua_State* L, c_closure cc) {
13906#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13907 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13908#endif // make sure stack doesn't overflow
13909 lua_pushcclosure(L, cc.c_function, cc.upvalues);
13910 return 1;
13911 }
13912 };
13913
13914 template <typename Arg, typename... Args>
13915 struct unqualified_pusher<closure<Arg, Args...>> {
13916 template <std::size_t... I, typename T>
13917 static int push(std::index_sequence<I...>, lua_State* L, T&& c) {
13918 using f_tuple = decltype(std::forward<T>(c).upvalues);
13919 int pushcount = multi_push(L, std::get<I>(std::forward<f_tuple>(std::forward<T>(c).upvalues))...);
13920 return stack::push(L, c_closure(c.c_function, pushcount));
13921 }
13922
13923 template <typename T>
13924 static int push(lua_State* L, T&& c) {
13925 return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward<T>(c));
13926 }
13927 };
13928
13929 template <>
13930 struct unqualified_pusher<void*> {
13931 static int push(lua_State* L, void* userdata) {
13932#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13933 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13934#endif // make sure stack doesn't overflow
13935 lua_pushlightuserdata(L, userdata);
13936 return 1;
13937 }
13938 };
13939
13940 template <>
13941 struct unqualified_pusher<const void*> {
13942 static int push(lua_State* L, const void* userdata) {
13943#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13944 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13945#endif // make sure stack doesn't overflow
13946 lua_pushlightuserdata(L, const_cast<void*>(userdata));
13947 return 1;
13948 }
13949 };
13950
13951 template <>
13952 struct unqualified_pusher<lightuserdata_value> {
13953 static int push(lua_State* L, lightuserdata_value userdata) {
13954#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13955 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13956#endif // make sure stack doesn't overflow
13957 lua_pushlightuserdata(L, userdata);
13958 return 1;
13959 }
13960 };
13961
13962 template <typename T>
13963 struct unqualified_pusher<light<T>> {
13964 static int push(lua_State* L, light<T> l) {
13965#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13966 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13967#endif // make sure stack doesn't overflow
13968 lua_pushlightuserdata(L, static_cast<void*>(l.value));
13969 return 1;
13970 }
13971 };
13972
13973 template <typename T>
13974 struct unqualified_pusher<user<T>> {
13975 template <bool with_meta = true, typename Key, typename... Args>
13976 static int push_with(lua_State* L, Key&& name, Args&&... args) {
13977#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13978 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
13979#endif // make sure stack doesn't overflow
13980 // A dumb pusher
13981 T* data = detail::user_allocate<T>(L);
13982 if (with_meta) {
13983 // Make sure we have a plain GC set for this data
13984#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
13985 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13986#endif // make sure stack doesn't overflow
13987 if (luaL_newmetatable(L, name) != 0) {
13988 lua_CFunction cdel = detail::user_alloc_destruct<T>;
13989 lua_pushcclosure(L, cdel, 0);
13990 lua_setfield(L, -2, "__gc");
13991 }
13992 lua_setmetatable(L, -2);
13993 }
13994 std::allocator<T> alloc {};
13995 std::allocator_traits<std::allocator<T>>::construct(alloc, data, std::forward<Args>(args)...);
13996 return 1;
13997 }
13998
13999 template <typename Arg, typename... Args>
14000 static int push(lua_State* L, Arg&& arg, Args&&... args) {
14001 if constexpr (std::is_same_v<meta::unqualified_t<Arg>, metatable_key_t>) {
14002 const auto name = &arg[0];
14003 return push_with<true>(L, name, std::forward<Args>(args)...);
14004 }
14005 else if constexpr (std::is_same_v<meta::unqualified_t<Arg>, no_metatable_t>) {
14006 (void)arg;
14007 const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
14008 return push_with<false>(L, name, std::forward<Args>(args)...);
14009 }
14010 else {
14011 const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
14012 return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...);
14013 }
14014 }
14015
14016 static int push(lua_State* L, const user<T>& u) {
14017 const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
14018 return push_with(L, name, u.value);
14019 }
14020
14021 static int push(lua_State* L, user<T>&& u) {
14022 const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
14023 return push_with(L, name, std::move(u.value));
14024 }
14025
14026 static int push(lua_State* L, no_metatable_t, const user<T>& u) {
14027 const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
14028 return push_with<false>(L, name, u.value);
14029 }
14030
14031 static int push(lua_State* L, no_metatable_t, user<T>&& u) {
14032 const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
14033 return push_with<false>(L, name, std::move(u.value));
14034 }
14035 };
14036
14037 template <>
14038 struct unqualified_pusher<userdata_value> {
14039 static int push(lua_State* L, userdata_value data) {
14040#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14041 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
14042#endif // make sure stack doesn't overflow
14043 void** ud = detail::usertype_allocate_pointer<void>(L);
14044 *ud = data.value;
14045 return 1;
14046 }
14047 };
14048
14049 template <>
14050 struct unqualified_pusher<const char*> {
14051 static int push_sized(lua_State* L, const char* str, std::size_t len) {
14052#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14053 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
14054#endif // make sure stack doesn't overflow
14055 lua_pushlstring(L, str, len);
14056 return 1;
14057 }
14058
14059 static int push(lua_State* L, const char* str) {
14060 if (str == nullptr)
14061 return stack::push(L, lua_nil);
14062 return push_sized(L, str, std::char_traits<char>::length(str));
14063 }
14064
14065 static int push(lua_State* L, const char* strb, const char* stre) {
14066 return push_sized(L, strb, stre - strb);
14067 }
14068
14069 static int push(lua_State* L, const char* str, std::size_t len) {
14070 return push_sized(L, str, len);
14071 }
14072 };
14073
14074 template <>
14075 struct unqualified_pusher<char*> {
14076 static int push_sized(lua_State* L, const char* str, std::size_t len) {
14077 unqualified_pusher<const char*> p {};
14078 (void)p;
14079 return p.push_sized(L, str, len);
14080 }
14081
14082 static int push(lua_State* L, const char* str) {
14083 unqualified_pusher<const char*> p {};
14084 (void)p;
14085 return p.push(L, str);
14086 }
14087
14088 static int push(lua_State* L, const char* strb, const char* stre) {
14089 unqualified_pusher<const char*> p {};
14090 (void)p;
14091 return p.push(L, strb, stre);
14092 }
14093
14094 static int push(lua_State* L, const char* str, std::size_t len) {
14095 unqualified_pusher<const char*> p {};
14096 (void)p;
14097 return p.push(L, str, len);
14098 }
14099 };
14100
14101 template <size_t N>
14102 struct unqualified_pusher<char[N]> {
14103 static int push(lua_State* L, const char (&str)[N]) {
14104#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14105 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
14106#endif // make sure stack doesn't overflow
14107 lua_pushlstring(L, str, std::char_traits<char>::length(str));
14108 return 1;
14109 }
14110
14111 static int push(lua_State* L, const char (&str)[N], std::size_t sz) {
14112#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14113 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
14114#endif // make sure stack doesn't overflow
14115 lua_pushlstring(L, str, sz);
14116 return 1;
14117 }
14118 };
14119
14120 template <>
14121 struct unqualified_pusher<char> {
14122 static int push(lua_State* L, char c) {
14123 const char str[2] = { c, '\0' };
14124 return stack::push(L, static_cast<const char*>(str), 1);
14125 }
14126 };
14127
14128 template <typename Ch, typename Traits, typename Al>
14129 struct unqualified_pusher<std::basic_string<Ch, Traits, Al>> {
14130 static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& str) {
14131 if constexpr (!std::is_same_v<Ch, char>) {
14132 return stack::push(L, str.data(), str.size());
14133 }
14134 else {
14135#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14136 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
14137#endif // make sure stack doesn't overflow
14138 lua_pushlstring(L, str.c_str(), str.size());
14139 return 1;
14140 }
14141 }
14142
14143 static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& str, std::size_t sz) {
14144 if constexpr (!std::is_same_v<Ch, char>) {
14145 return stack::push(L, str.data(), sz);
14146 }
14147 else {
14148#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14149 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
14150#endif // make sure stack doesn't overflow
14151 lua_pushlstring(L, str.c_str(), sz);
14152 return 1;
14153 }
14154 }
14155 };
14156
14157 template <typename Ch, typename Traits>
14158 struct unqualified_pusher<basic_string_view<Ch, Traits>> {
14159 static int push(lua_State* L, const basic_string_view<Ch, Traits>& sv) {
14160 return stack::push(L, sv.data(), sv.length());
14161 }
14162
14163 static int push(lua_State* L, const basic_string_view<Ch, Traits>& sv, std::size_t n) {
14164 return stack::push(L, sv.data(), n);
14165 }
14166 };
14167
14168 template <>
14169 struct unqualified_pusher<meta_function> {
14170 static int push(lua_State* L, meta_function m) {
14171#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14172 luaL_checkstack(L, 1, detail::not_enough_stack_space_meta_function_name);
14173#endif // make sure stack doesn't overflow
14174 const std::string& str = to_string(m);
14175 lua_pushlstring(L, str.c_str(), str.size());
14176 return 1;
14177 }
14178 };
14179
14180 template <>
14181 struct unqualified_pusher<absolute_index> {
14182 static int push(lua_State* L, absolute_index ai) {
14183#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14184 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
14185#endif // make sure stack doesn't overflow
14186 lua_pushvalue(L, ai);
14187 return 1;
14188 }
14189 };
14190
14191 template <>
14192 struct unqualified_pusher<raw_index> {
14193 static int push(lua_State* L, raw_index ri) {
14194#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14195 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
14196#endif // make sure stack doesn't overflow
14197 lua_pushvalue(L, ri);
14198 return 1;
14199 }
14200 };
14201
14202 template <>
14203 struct unqualified_pusher<ref_index> {
14204 static int push(lua_State* L, ref_index ri) {
14205#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14206 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
14207#endif // make sure stack doesn't overflow
14208 lua_rawgeti(L, LUA_REGISTRYINDEX, ri);
14209 return 1;
14210 }
14211 };
14212
14213 template <>
14214 struct unqualified_pusher<const wchar_t*> {
14215 static int push(lua_State* L, const wchar_t* wstr) {
14216 return push(L, wstr, std::char_traits<wchar_t>::length(wstr));
14217 }
14218
14219 static int push(lua_State* L, const wchar_t* wstr, std::size_t sz) {
14220 return push(L, wstr, wstr + sz);
14221 }
14222
14223 static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) {
14224 if constexpr (sizeof(wchar_t) == 2) {
14225 const char16_t* sb = reinterpret_cast<const char16_t*>(strb);
14226 const char16_t* se = reinterpret_cast<const char16_t*>(stre);
14227 return stack::push(L, sb, se);
14228 }
14229 else {
14230 const char32_t* sb = reinterpret_cast<const char32_t*>(strb);
14231 const char32_t* se = reinterpret_cast<const char32_t*>(stre);
14232 return stack::push(L, sb, se);
14233 }
14234 }
14235 };
14236
14237 template <>
14238 struct unqualified_pusher<wchar_t*> {
14239 static int push(lua_State* L, const wchar_t* str) {
14240 unqualified_pusher<const wchar_t*> p {};
14241 (void)p;
14242 return p.push(L, str);
14243 }
14244
14245 static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) {
14246 unqualified_pusher<const wchar_t*> p {};
14247 (void)p;
14248 return p.push(L, strb, stre);
14249 }
14250
14251 static int push(lua_State* L, const wchar_t* str, std::size_t len) {
14252 unqualified_pusher<const wchar_t*> p {};
14253 (void)p;
14254 return p.push(L, str, len);
14255 }
14256 };
14257
14258 template <>
14259 struct unqualified_pusher<const char16_t*> {
14260 static int convert_into(lua_State* L, char* start, std::size_t, const char16_t* strb, const char16_t* stre) {
14261 char* target = start;
14262 char32_t cp = 0;
14263 for (const char16_t* strtarget = strb; strtarget < stre;) {
14264 auto dr = unicode::utf16_to_code_point(strtarget, stre);
14265 if (dr.error != unicode::error_code::ok) {
14266 cp = unicode::unicode_detail::replacement;
14267 }
14268 else {
14269 cp = dr.codepoint;
14270 }
14271 auto er = unicode::code_point_to_utf8(cp);
14272 const char* utf8data = er.code_units.data();
14273 std::memcpy(target, utf8data, er.code_units_size);
14274 target += er.code_units_size;
14275 strtarget = dr.next;
14276 }
14277
14278 return stack::push(L, start, target);
14279 }
14280
14281 static int push(lua_State* L, const char16_t* u16str) {
14282 return push(L, u16str, std::char_traits<char16_t>::length(u16str));
14283 }
14284
14285 static int push(lua_State* L, const char16_t* u16str, std::size_t sz) {
14286 return push(L, u16str, u16str + sz);
14287 }
14288
14289 static int push(lua_State* L, const char16_t* strb, const char16_t* stre) {
14290 char sbo[SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_];
14291 // if our max string space is small enough, use SBO
14292 // right off the bat
14293 std::size_t max_possible_code_units = (stre - strb) * 4;
14294 if (max_possible_code_units <= SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) {
14295 return convert_into(L, sbo, max_possible_code_units, strb, stre);
14296 }
14297 // otherwise, we must manually count/check size
14298 std::size_t needed_size = 0;
14299 for (const char16_t* strtarget = strb; strtarget < stre;) {
14300 auto dr = unicode::utf16_to_code_point(strtarget, stre);
14301 auto er = unicode::code_point_to_utf8(dr.codepoint);
14302 needed_size += er.code_units_size;
14303 strtarget = dr.next;
14304 }
14305 if (needed_size < SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) {
14306 return convert_into(L, sbo, needed_size, strb, stre);
14307 }
14308 std::string u8str("", 0);
14309 u8str.resize(needed_size);
14310 char* target = const_cast<char*>(u8str.data());
14311 return convert_into(L, target, needed_size, strb, stre);
14312 }
14313 };
14314
14315 template <>
14316 struct unqualified_pusher<char16_t*> {
14317 static int push(lua_State* L, const char16_t* str) {
14318 unqualified_pusher<const char16_t*> p {};
14319 (void)p;
14320 return p.push(L, str);
14321 }
14322
14323 static int push(lua_State* L, const char16_t* strb, const char16_t* stre) {
14324 unqualified_pusher<const char16_t*> p {};
14325 (void)p;
14326 return p.push(L, strb, stre);
14327 }
14328
14329 static int push(lua_State* L, const char16_t* str, std::size_t len) {
14330 unqualified_pusher<const char16_t*> p {};
14331 (void)p;
14332 return p.push(L, str, len);
14333 }
14334 };
14335
14336 template <>
14337 struct unqualified_pusher<const char32_t*> {
14338 static int convert_into(lua_State* L, char* start, std::size_t, const char32_t* strb, const char32_t* stre) {
14339 char* target = start;
14340 char32_t cp = 0;
14341 for (const char32_t* strtarget = strb; strtarget < stre;) {
14342 auto dr = unicode::utf32_to_code_point(strtarget, stre);
14343 if (dr.error != unicode::error_code::ok) {
14344 cp = unicode::unicode_detail::replacement;
14345 }
14346 else {
14347 cp = dr.codepoint;
14348 }
14349 auto er = unicode::code_point_to_utf8(cp);
14350 const char* data = er.code_units.data();
14351 std::memcpy(target, data, er.code_units_size);
14352 target += er.code_units_size;
14353 strtarget = dr.next;
14354 }
14355 return stack::push(L, start, target);
14356 }
14357
14358 static int push(lua_State* L, const char32_t* u32str) {
14359 return push(L, u32str, u32str + std::char_traits<char32_t>::length(u32str));
14360 }
14361
14362 static int push(lua_State* L, const char32_t* u32str, std::size_t sz) {
14363 return push(L, u32str, u32str + sz);
14364 }
14365
14366 static int push(lua_State* L, const char32_t* strb, const char32_t* stre) {
14367 char sbo[SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_];
14368 // if our max string space is small enough, use SBO
14369 // right off the bat
14370 std::size_t max_possible_code_units = (stre - strb) * 4;
14371 if (max_possible_code_units <= SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) {
14372 return convert_into(L, sbo, max_possible_code_units, strb, stre);
14373 }
14374 // otherwise, we must manually count/check size
14375 std::size_t needed_size = 0;
14376 for (const char32_t* strtarget = strb; strtarget < stre;) {
14377 auto dr = unicode::utf32_to_code_point(strtarget, stre);
14378 auto er = unicode::code_point_to_utf8(dr.codepoint);
14379 needed_size += er.code_units_size;
14380 strtarget = dr.next;
14381 }
14382 if (needed_size < SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) {
14383 return convert_into(L, sbo, needed_size, strb, stre);
14384 }
14385 std::string u8str("", 0);
14386 u8str.resize(needed_size);
14387 char* target = const_cast<char*>(u8str.data());
14388 return convert_into(L, target, needed_size, strb, stre);
14389 }
14390 };
14391
14392 template <>
14393 struct unqualified_pusher<char32_t*> {
14394 static int push(lua_State* L, const char32_t* str) {
14395 unqualified_pusher<const char32_t*> p {};
14396 (void)p;
14397 return p.push(L, str);
14398 }
14399
14400 static int push(lua_State* L, const char32_t* strb, const char32_t* stre) {
14401 unqualified_pusher<const char32_t*> p {};
14402 (void)p;
14403 return p.push(L, strb, stre);
14404 }
14405
14406 static int push(lua_State* L, const char32_t* str, std::size_t len) {
14407 unqualified_pusher<const char32_t*> p {};
14408 (void)p;
14409 return p.push(L, str, len);
14410 }
14411 };
14412
14413 template <size_t N>
14414 struct unqualified_pusher<wchar_t[N]> {
14415 static int push(lua_State* L, const wchar_t (&str)[N]) {
14416 return push(L, str, std::char_traits<wchar_t>::length(str));
14417 }
14418
14419 static int push(lua_State* L, const wchar_t (&str)[N], std::size_t sz) {
14420 const wchar_t* str_ptr = static_cast<const wchar_t*>(str);
14421 return stack::push<const wchar_t*>(L, str_ptr, str_ptr + sz);
14422 }
14423 };
14424
14425 template <size_t N>
14426 struct unqualified_pusher<char16_t[N]> {
14427 static int push(lua_State* L, const char16_t (&str)[N]) {
14428 return push(L, str, std::char_traits<char16_t>::length(str));
14429 }
14430
14431 static int push(lua_State* L, const char16_t (&str)[N], std::size_t sz) {
14432 const char16_t* str_ptr = static_cast<const char16_t*>(str);
14433 return stack::push<const char16_t*>(L, str_ptr, str_ptr + sz);
14434 }
14435 };
14436
14437 template <size_t N>
14438 struct unqualified_pusher<char32_t[N]> {
14439 static int push(lua_State* L, const char32_t (&str)[N]) {
14440 return push(L, str, std::char_traits<char32_t>::length(str));
14441 }
14442
14443 static int push(lua_State* L, const char32_t (&str)[N], std::size_t sz) {
14444 const char32_t* str_ptr = static_cast<const char32_t*>(str);
14445 return stack::push<const char32_t*>(L, str_ptr, str_ptr + sz);
14446 }
14447 };
14448
14449 template <>
14450 struct unqualified_pusher<wchar_t> {
14451 static int push(lua_State* L, wchar_t c) {
14452 const wchar_t str[2] = { c, '\0' };
14453 return stack::push(L, static_cast<const wchar_t*>(str), 1);
14454 }
14455 };
14456
14457 template <>
14458 struct unqualified_pusher<char16_t> {
14459 static int push(lua_State* L, char16_t c) {
14460 const char16_t str[2] = { c, '\0' };
14461 return stack::push(L, static_cast<const char16_t*>(str), 1);
14462 }
14463 };
14464
14465 template <>
14466 struct unqualified_pusher<char32_t> {
14467 static int push(lua_State* L, char32_t c) {
14468 const char32_t str[2] = { c, '\0' };
14469 return stack::push(L, static_cast<const char32_t*>(str), 1);
14470 }
14471 };
14472
14473 template <typename... Args>
14474 struct unqualified_pusher<std::tuple<Args...>> {
14475 template <std::size_t... I, typename T>
14476 static int push(std::index_sequence<I...>, lua_State* L, T&& t) {
14477#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
14478 luaL_checkstack(L, static_cast<int>(sizeof...(I)), detail::not_enough_stack_space_generic);
14479#endif // make sure stack doesn't overflow
14480 int pushcount = 0;
14481 (void)detail::swallow { 0, (pushcount += stack::push(L, std::get<I>(std::forward<T>(t))), 0)... };
14482 return pushcount;
14483 }
14484
14485 template <typename T>
14486 static int push(lua_State* L, T&& t) {
14487 return push(std::index_sequence_for<Args...>(), L, std::forward<T>(t));
14488 }
14489 };
14490
14491 template <typename A, typename B>
14492 struct unqualified_pusher<std::pair<A, B>> {
14493 template <typename T>
14494 static int push(lua_State* L, T&& t) {
14495 int pushcount = stack::push(L, std::get<0>(std::forward<T>(t)));
14496 pushcount += stack::push(L, std::get<1>(std::forward<T>(t)));
14497 return pushcount;
14498 }
14499 };
14500
14501 template <typename T>
14502 struct unqualified_pusher<T, std::enable_if_t<meta::is_optional_v<T>>> {
14503 using ValueType = typename meta::unqualified_t<T>::value_type;
14504
14505 template <typename Optional>
14506 static int push(lua_State* L, Optional&& op) {
14507 using QualifiedValueType = meta::conditional_t<std::is_lvalue_reference_v<Optional>, ValueType&, ValueType&&>;
14508 if (!op) {
14509 return stack::push(L, nullopt);
14510 }
14511 return stack::push(L, static_cast<QualifiedValueType>(op.value()));
14512 }
14513 };
14514
14515 template <>
14516 struct unqualified_pusher<nullopt_t> {
14517 static int push(lua_State* L, nullopt_t) {
14518 return stack::push(L, lua_nil);
14519 }
14520 };
14521
14522 template <>
14523 struct unqualified_pusher<std::nullptr_t> {
14524 static int push(lua_State* L, std::nullptr_t) {
14525 return stack::push(L, lua_nil);
14526 }
14527 };
14528
14529 template <>
14530 struct unqualified_pusher<this_state> {
14531 static int push(lua_State*, const this_state&) {
14532 return 0;
14533 }
14534 };
14535
14536 template <>
14537 struct unqualified_pusher<this_main_state> {
14538 static int push(lua_State*, const this_main_state&) {
14539 return 0;
14540 }
14541 };
14542
14543 template <>
14544 struct unqualified_pusher<new_table> {
14545 static int push(lua_State* L, const new_table& nt) {
14546 lua_createtable(L, nt.sequence_hint, nt.map_hint);
14547 return 1;
14548 }
14549 };
14550
14551 template <typename Allocator>
14552 struct unqualified_pusher<basic_bytecode<Allocator>> {
14553 template <typename T>
14554 static int push(lua_State* L, T&& bc, const char* bytecode_name) {
14555 const auto first = bc.data();
14556 const auto bcsize = bc.size();
14557 // pushes either the function, or an error
14558 // if it errors, shit goes south, and people can test that upstream
14559 (void)luaL_loadbuffer(
14560 L, reinterpret_cast<const char*>(first), static_cast<std::size_t>(bcsize * (sizeof(*first) / sizeof(const char))), bytecode_name);
14561 return 1;
14562 }
14563
14564 template <typename T>
14565 static int push(lua_State* L, T&& bc) {
14566 return push(L, std::forward<bc>(bc), "bytecode");
14567 }
14568 };
14569
14570#if SOL_IS_ON(SOL_STD_VARIANT_I_)
14571 namespace stack_detail {
14572
14573 struct push_function {
14574 lua_State* L;
14575
14576 push_function(lua_State* L) : L(L) {
14577 }
14578
14579 template <typename T>
14580 int operator()(T&& value) const {
14581 return stack::push<T>(L, std::forward<T>(value));
14582 }
14583 };
14584
14585 } // namespace stack_detail
14586
14587 template <typename... Tn>
14588 struct unqualified_pusher<std::variant<Tn...>> {
14589 static int push(lua_State* L, const std::variant<Tn...>& v) {
14590 return std::visit(stack_detail::push_function(L), v);
14591 }
14592
14593 static int push(lua_State* L, std::variant<Tn...>&& v) {
14594 return std::visit(stack_detail::push_function(L), std::move(v));
14595 }
14596 };
14597#endif // Variant because Clang is terrible
14598
14599}} // namespace sol::stack
14600
14601// end of sol/stack_push.hpp
14602
14603// beginning of sol/stack_pop.hpp
14604
14605#include <utility>
14606#include <tuple>
14607
14608namespace sol {
14609namespace stack {
14610 template <typename T, typename>
14611 struct popper {
14612 inline static decltype(auto) pop(lua_State* L) {
14613 if constexpr (is_stack_based_v<meta::unqualified_t<T>>) {
14614 static_assert(!is_stack_based_v<meta::unqualified_t<T>>,
14615 "You cannot pop something that lives solely on the stack: it will not remain on the stack when popped and thusly will go out of "
14616 "scope!");
14617 }
14618 else {
14619 record tracking{};
14620 decltype(auto) r = get<T>(L, -lua_size<T>::value, tracking);
14621 lua_pop(L, tracking.used);
14622 return r;
14623 }
14624 }
14625 };
14626}
14627} // namespace sol::stack
14628
14629// end of sol/stack_pop.hpp
14630
14631// beginning of sol/stack_field.hpp
14632
14633namespace sol { namespace stack {
14634 template <typename T, bool global, bool raw, typename>
14635 struct field_getter {
14636 static constexpr int default_table_index = meta::conditional_t < meta::is_c_str_v<T>
14637#if SOL_LUA_VESION_I_ >= 503
14638 || (std::is_integral_v<T> && !std::is_same_v<T, bool>)
14639#endif // integer global keys 5.3 or better
14640 || (raw && std::is_void_v<std::remove_pointer_t<T>>),
14641 std::integral_constant<int, -1>, std::integral_constant<int, -2> > ::value;
14642
14643 template <typename Key>
14644 void get(lua_State* L, Key&& key, int tableindex = default_table_index) {
14645 if constexpr (std::is_same_v<T, update_if_empty_t> || std::is_same_v<T, override_value_t> || std::is_same_v<T, create_if_nil_t>) {
14646 (void)L;
14647 (void)key;
14648 (void)tableindex;
14649 }
14650 else if constexpr (std::is_same_v<T, env_key_t>) {
14651 (void)key;
14652#if SOL_LUA_VESION_I_ < 502
14653 // Use lua_setfenv
14654 lua_getfenv(L, tableindex);
14655#else
14656 // Use upvalues as explained in Lua 5.2 and beyond's manual
14657 if (lua_getupvalue(L, tableindex, 1) == nullptr) {
14658 push(L, lua_nil);
14659 }
14660#endif
14661 }
14662 else if constexpr (std::is_same_v<T, metatable_key_t>) {
14663 (void)key;
14664 if (lua_getmetatable(L, tableindex) == 0)
14665 push(L, lua_nil);
14666 }
14667 else if constexpr (raw) {
14668 if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) {
14669 lua_rawgeti(L, tableindex, static_cast<lua_Integer>(key));
14670 }
14671#if SOL_LUA_VESION_I_ >= 502
14672 else if constexpr (std::is_void_v<std::remove_pointer_t<T>>) {
14673 lua_rawgetp(L, tableindex, key);
14674 }
14675#endif // Lua 5.2.x+
14676 else {
14677 push(L, std::forward<Key>(key));
14678 lua_rawget(L, tableindex);
14679 }
14680 }
14681 else {
14682 if constexpr (meta::is_c_str_v<T>) {
14683 if constexpr (global) {
14684 (void)tableindex;
14685 lua_getglobal(L, &key[0]);
14686 }
14687 else {
14688 lua_getfield(L, tableindex, &key[0]);
14689 }
14690 }
14691#if SOL_LUA_VESION_I_ >= 503
14692 else if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) {
14693 lua_geti(L, tableindex, static_cast<lua_Integer>(key));
14694 }
14695#endif // Lua 5.3.x+
14696 else {
14697 push(L, std::forward<Key>(key));
14698 lua_gettable(L, tableindex);
14699 }
14700 }
14701 }
14702 };
14703
14704 template <typename... Args, bool b, bool raw, typename C>
14705 struct field_getter<std::tuple<Args...>, b, raw, C> {
14706 template <std::size_t... I, typename Keys>
14707 void apply(std::index_sequence<0, I...>, lua_State* L, Keys&& keys, int tableindex) {
14708 get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)), tableindex);
14709 void(detail::swallow { (get_field<false, raw>(L, std::get<I>(std::forward<Keys>(keys))), 0)... });
14710 reference saved(L, -1);
14711 lua_pop(L, static_cast<int>(sizeof...(I)));
14712 saved.push();
14713 }
14714
14715 template <typename Keys>
14716 void get(lua_State* L, Keys&& keys) {
14717 apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), lua_absindex(L, -1));
14718 }
14719
14720 template <typename Keys>
14721 void get(lua_State* L, Keys&& keys, int tableindex) {
14722 apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), tableindex);
14723 }
14724 };
14725
14726 template <typename A, typename B, bool b, bool raw, typename C>
14727 struct field_getter<std::pair<A, B>, b, raw, C> {
14728 template <typename Keys>
14729 void get(lua_State* L, Keys&& keys, int tableindex) {
14730 get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)), tableindex);
14731 get_field<false, raw>(L, std::get<1>(std::forward<Keys>(keys)));
14732 reference saved(L, -1);
14733 lua_pop(L, static_cast<int>(2));
14734 saved.push();
14735 }
14736
14737 template <typename Keys>
14738 void get(lua_State* L, Keys&& keys) {
14739 get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)));
14740 get_field<false, raw>(L, std::get<1>(std::forward<Keys>(keys)));
14741 reference saved(L, -1);
14742 lua_pop(L, static_cast<int>(2));
14743 saved.push();
14744 }
14745 };
14746
14747 template <typename T, bool global, bool raw, typename>
14748 struct field_setter {
14749 static constexpr int default_table_index
14750 = meta::conditional_t < (meta::is_c_str_v<T> || meta::is_string_of_v<T, char>) || (std::is_integral_v<T> && !std::is_same_v<T, bool>)
14751 || (std::is_integral_v<T> && !std::is_same_v<T, bool>) || (raw && std::is_void_v<std::remove_pointer_t<T>>),
14752 std::integral_constant<int, -2>, std::integral_constant<int, -3> > ::value;
14753
14754 template <typename Key, typename Value>
14755 void set(lua_State* L, Key&& key, Value&& value, int tableindex = default_table_index) {
14756 if constexpr (std::is_same_v<T, update_if_empty_t> || std::is_same_v<T, override_value_t>) {
14757 (void)L;
14758 (void)key;
14759 (void)value;
14760 (void)tableindex;
14761 }
14762 else if constexpr (std::is_same_v<T, metatable_key_t>) {
14763 (void)key;
14764 push(L, std::forward<Value>(value));
14765 lua_setmetatable(L, tableindex);
14766 }
14767 else if constexpr (raw) {
14768 if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) {
14769 push(L, std::forward<Value>(value));
14770 lua_rawseti(L, tableindex, static_cast<lua_Integer>(key));
14771 }
14772#if SOL_LUA_VESION_I_ >= 502
14773 else if constexpr (std::is_void_v<std::remove_pointer_t<T>>) {
14774 push(L, std::forward<Value>(value));
14775 lua_rawsetp(L, tableindex, std::forward<Key>(key));
14776 }
14777#endif // Lua 5.2.x
14778 else {
14779 push(L, std::forward<Key>(key));
14780 push(L, std::forward<Value>(value));
14781 lua_rawset(L, tableindex);
14782 }
14783 }
14784 else {
14785 if constexpr (meta::is_c_str_v<T> || meta::is_string_of_v<T, char>) {
14786 if constexpr (global) {
14787 push(L, std::forward<Value>(value));
14788 lua_setglobal(L, &key[0]);
14789 (void)tableindex;
14790 }
14791 else {
14792 push(L, std::forward<Value>(value));
14793 lua_setfield(L, tableindex, &key[0]);
14794 }
14795 }
14796#if SOL_LUA_VESION_I_ >= 503
14797 else if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) {
14798 push(L, std::forward<Value>(value));
14799 lua_seti(L, tableindex, static_cast<lua_Integer>(key));
14800 }
14801#endif // Lua 5.3.x
14802 else {
14803 push(L, std::forward<Key>(key));
14804 push(L, std::forward<Value>(value));
14805 lua_settable(L, tableindex);
14806 }
14807 }
14808 }
14809 };
14810
14811 template <typename... Args, bool b, bool raw, typename C>
14812 struct field_setter<std::tuple<Args...>, b, raw, C> {
14813 template <bool g, std::size_t I, typename Keys, typename Value>
14814 void apply(std::index_sequence<I>, lua_State* L, Keys&& keys, Value&& value, int tableindex) {
14815 I < 1 ? set_field<g, raw>(L, std::get<I>(std::forward<Keys>(keys)), std::forward<Value>(value), tableindex)
14816 : set_field<g, raw>(L, std::get<I>(std::forward<Keys>(keys)), std::forward<Value>(value));
14817 }
14818
14819 template <bool g, std::size_t I0, std::size_t I1, std::size_t... I, typename Keys, typename Value>
14820 void apply(std::index_sequence<I0, I1, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) {
14821 I0 < 1 ? get_field<g, raw>(L, std::get<I0>(std::forward<Keys>(keys)), tableindex)
14822 : get_field<g, raw>(L, std::get<I0>(std::forward<Keys>(keys)), -1);
14823 apply<false>(std::index_sequence<I1, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), -1);
14824 }
14825
14826 template <bool g, std::size_t I0, std::size_t... I, typename Keys, typename Value>
14827 void top_apply(std::index_sequence<I0, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) {
14828 apply<g>(std::index_sequence<I0, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex);
14829 lua_pop(L, static_cast<int>(sizeof...(I)));
14830 }
14831
14832 template <typename Keys, typename Value>
14833 void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) {
14834 top_apply<b>(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex);
14835 }
14836 };
14837
14838 template <typename A, typename B, bool b, bool raw, typename C>
14839 struct field_setter<std::pair<A, B>, b, raw, C> {
14840 template <typename Keys, typename Value>
14841 void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) {
14842 get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)), tableindex);
14843 set_field<false, raw>(L, std::get<1>(std::forward<Keys>(keys)), std::forward<Value>(value), lua_gettop(L));
14844 lua_pop(L, 1);
14845 }
14846 };
14847}} // namespace sol::stack
14848
14849// end of sol/stack_field.hpp
14850
14851// beginning of sol/stack_probe.hpp
14852
14853namespace sol {
14854namespace stack {
14855 template <typename T, typename P, bool b, bool raw, typename>
14856 struct probe_field_getter {
14857 template <typename Key>
14858 probe get(lua_State* L, Key&& key, int tableindex = -2) {
14859 if constexpr(!b) {
14860 if (!maybe_indexable(L, tableindex)) {
14861 return probe(false, 0);
14862 }
14863 }
14864 get_field<b, raw>(L, std::forward<Key>(key), tableindex);
14865 return probe(check<P>(L), 1);
14866 }
14867 };
14868
14869 template <typename A, typename B, typename P, bool b, bool raw, typename C>
14870 struct probe_field_getter<std::pair<A, B>, P, b, raw, C> {
14871 template <typename Keys>
14872 probe get(lua_State* L, Keys&& keys, int tableindex = -2) {
14873 if (!b && !maybe_indexable(L, tableindex)) {
14874 return probe(false, 0);
14875 }
14876 get_field<b, raw>(L, std::get<0>(keys), tableindex);
14877 if (!maybe_indexable(L)) {
14878 return probe(false, 1);
14879 }
14880 get_field<false, raw>(L, std::get<1>(keys), tableindex);
14881 return probe(check<P>(L), 2);
14882 }
14883 };
14884
14885 template <typename... Args, typename P, bool b, bool raw, typename C>
14886 struct probe_field_getter<std::tuple<Args...>, P, b, raw, C> {
14887 template <std::size_t I, typename Keys>
14888 probe apply(std::index_sequence<I>, int sofar, lua_State* L, Keys&& keys, int tableindex) {
14889 get_field<(I<1) && b, raw>(L, std::get<I>(keys), tableindex);
14890 return probe(check<P>(L), sofar);
14891 }
14892
14893 template <std::size_t I, std::size_t I1, std::size_t... In, typename Keys>
14894 probe apply(std::index_sequence<I, I1, In...>, int sofar, lua_State* L, Keys&& keys, int tableindex) {
14895 get_field < I<1 && b, raw>(L, std::get<I>(keys), tableindex);
14896 if (!maybe_indexable(L)) {
14897 return probe(false, sofar);
14898 }
14899 return apply(std::index_sequence<I1, In...>(), sofar + 1, L, std::forward<Keys>(keys), -1);
14900 }
14901
14902 template <typename Keys>
14903 probe get(lua_State* L, Keys&& keys, int tableindex = -2) {
14904 if constexpr (!b) {
14905 if (!maybe_indexable(L, tableindex)) {
14906 return probe(false, 0);
14907 }
14908 return apply(std::index_sequence_for<Args...>(), 1, L, std::forward<Keys>(keys), tableindex);
14909 }
14910 else {
14911 return apply(std::index_sequence_for<Args...>(), 1, L, std::forward<Keys>(keys), tableindex);
14912 }
14913 }
14914 };
14915}
14916} // namespace sol::stack
14917
14918// end of sol/stack_probe.hpp
14919
14920#include <cstring>
14921#include <array>
14922
14923namespace sol {
14924 namespace detail {
14925 using typical_chunk_name_t = char[SOL_ID_SIZE_I_];
14926 using typical_file_chunk_name_t = char[SOL_FILE_ID_SIZE_I_];
14927
14928 inline const std::string& default_chunk_name() {
14929 static const std::string name = "";
14930 return name;
14931 }
14932
14933 template <std::size_t N>
14934 const char* make_chunk_name(const string_view& code, const std::string& chunkname, char (&basechunkname)[N]) {
14935 if (chunkname.empty()) {
14936 auto it = code.cbegin();
14937 auto e = code.cend();
14938 std::size_t i = 0;
14939 static const std::size_t n = N - 4;
14940 for (i = 0; i < n && it != e; ++i, ++it) {
14941 basechunkname[i] = *it;
14942 }
14943 if (it != e) {
14944 for (std::size_t c = 0; c < 3; ++i, ++c) {
14945 basechunkname[i] = '.';
14946 }
14947 }
14948 basechunkname[i] = '\0';
14949 return &basechunkname[0];
14950 }
14951 else {
14952 return chunkname.c_str();
14953 }
14954 }
14955
14956 inline void clear_entries(stack_reference r) {
14957 stack::push(r.lua_state(), lua_nil);
14958 while (lua_next(r.lua_state(), -2)) {
14959 absolute_index key(r.lua_state(), -2);
14960 auto pn = stack::pop_n(r.lua_state(), 1);
14961 stack::set_field<false, true>(r.lua_state(), key, lua_nil, r.stack_index());
14962 }
14963 }
14964
14965 inline void clear_entries(const reference& registry_reference) {
14966 auto pp = stack::push_pop(registry_reference);
14967 stack_reference ref(registry_reference.lua_state(), -1);
14968 clear_entries(ref);
14969 }
14970 } // namespace detail
14971
14972 namespace stack {
14973 namespace stack_detail {
14974 template <typename T>
14975 inline int push_as_upvalues(lua_State* L, T& item) {
14976 typedef std::decay_t<T> TValue;
14977 static const std::size_t itemsize = sizeof(TValue);
14978 static const std::size_t voidsize = sizeof(void*);
14979 static const std::size_t voidsizem1 = voidsize - 1;
14980 static const std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize;
14981 typedef std::array<void*, data_t_count> data_t;
14982
14983 data_t data { {} };
14984 std::memcpy(&data[0], std::addressof(item), itemsize);
14985 int pushcount = 0;
14986 for (const auto& v : data) {
14987 lua_pushlightuserdata(L, v);
14988 pushcount += 1;
14989 }
14990 return pushcount;
14991 }
14992
14993 template <typename T>
14994 inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 2) {
14995 static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
14996 typedef std::array<void*, data_t_count> data_t;
14997 data_t voiddata { {} };
14998 for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
14999 voiddata[i] = lua_touserdata(L, upvalue_index(index++));
15000 }
15001 return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
15002 }
15003
15004 template <typename T>
15005 inline std::pair<T, int> get_as_upvalues_using_function(lua_State* L, int function_index = -1) {
15006 static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
15007 typedef std::array<void*, data_t_count> data_t;
15008 function_index = lua_absindex(L, function_index);
15009 int index = 0;
15010 data_t voiddata { {} };
15011 for (std::size_t d = 0; d < sizeof(T); d += sizeof(void*)) {
15012 // first upvalue is nullptr to respect environment shenanigans
15013 // So +2 instead of +1
15014 const char* upvalue_name = lua_getupvalue(L, function_index, index + 2);
15015 if (upvalue_name == nullptr) {
15016 // We should freak out here...
15017 break;
15018 }
15019 voiddata[index] = lua_touserdata(L, -1);
15020 ++index;
15021 }
15022 lua_pop(L, index);
15023 return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
15024 }
15025
15026 template <typename Fx, typename... Args>
15027 static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, record&, Fx&& fx, Args&&... args) {
15028 return std::forward<Fx>(fx)(std::forward<Args>(args)...);
15029 }
15030
15031 template <typename Fx, typename Arg, typename... Args, std::size_t I, std::size_t... Is, typename... FxArgs>
15032 static decltype(auto) eval(
15033 types<Arg, Args...>, std::index_sequence<I, Is...>, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) {
15034 return eval(types<Args...>(),
15035 std::index_sequence<Is...>(),
15036 L,
15037 start,
15038 tracking,
15039 std::forward<Fx>(fx),
15040 std::forward<FxArgs>(fxargs)...,
15041 stack_detail::unchecked_get<Arg>(L, start + tracking.used, tracking));
15042 }
15043
15044 template <bool checkargs = detail::default_safe_function_calls, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs>
15045 inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
15046 static_assert(meta::all<meta::is_not_move_only<Args>...>::value,
15047 "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take "
15048 "a reference and std::move it manually if this was your intention.");
15049 if constexpr (checkargs) {
15050 argument_handler<types<R, Args...>> handler {};
15051 multi_check<Args...>(L, start, handler);
15052 }
15053 record tracking {};
15054 if constexpr (std::is_void_v<R>) {
15055 eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
15056 }
15057 else {
15058 return eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
15059 }
15060 }
15061 } // namespace stack_detail
15062
15063 template <typename T>
15064 int set_ref(lua_State* L, T&& arg, int tableindex = -2) {
15065 push(L, std::forward<T>(arg));
15066 return luaL_ref(L, tableindex);
15067 }
15068
15069 template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs>
15070 inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
15071 using args_indices = std::make_index_sequence<sizeof...(Args)>;
15072 if constexpr (std::is_void_v<R>) {
15073 stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
15074 }
15075 else {
15076 return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
15077 }
15078 }
15079
15080 template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs>
15081 inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
15082 if constexpr (std::is_void_v<R>) {
15083 call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
15084 }
15085 else {
15086 return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
15087 }
15088 }
15089
15090 template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs>
15091 inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
15092 using expected_count_t = meta::count_for_pack<lua_size, Args...>;
15093 if constexpr (std::is_void_v<R>) {
15094 call<check_args>(tr,
15095 ta,
15096 L,
15097 (std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value), static_cast<int>(0)),
15098 std::forward<Fx>(fx),
15099 std::forward<FxArgs>(args)...);
15100 }
15101 else {
15102 return call<check_args>(tr,
15103 ta,
15104 L,
15105 (std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value), static_cast<int>(0)),
15106 std::forward<Fx>(fx),
15107 std::forward<FxArgs>(args)...);
15108 }
15109 }
15110
15111 template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Ret0, typename... Ret, typename... Args,
15112 typename Fx, typename... FxArgs>
15113 inline int call_into_lua(types<Ret0, Ret...> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
15114 if constexpr (std::is_void_v<Ret0>) {
15115 call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
15116 if constexpr (clean_stack) {
15117 lua_settop(L, 0);
15118 }
15119 return 0;
15120 }
15121 else {
15122 (void)tr;
15123 decltype(auto) r
15124 = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
15125 using R = meta::unqualified_t<decltype(r)>;
15126 using is_stack = meta::any<is_stack_based<R>, std::is_same<R, absolute_index>, std::is_same<R, ref_index>, std::is_same<R, raw_index>>;
15127 if constexpr (clean_stack && !is_stack::value) {
15128 lua_settop(L, 0);
15129 }
15130 return push_reference(L, std::forward<decltype(r)>(r));
15131 }
15132 }
15133
15134 template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... FxArgs>
15135 inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
15136 using traits_type = lua_bind_traits<meta::unqualified_t<Fx>>;
15137 using args_list = typename traits_type::args_list;
15138 using returns_list = typename traits_type::returns_list;
15139 return call_into_lua<check_args, clean_stack>(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
15140 }
15141
15142 inline call_syntax get_call_syntax(lua_State* L, const string_view& key, int index) {
15143 if (lua_gettop(L) < 1) {
15144 return call_syntax::dot;
15145 }
15146 luaL_getmetatable(L, key.data());
15147 auto pn = pop_n(L, 1);
15148 if (lua_compare(L, -1, index, LUA_OPEQ) != 1) {
15149 return call_syntax::dot;
15150 }
15151 return call_syntax::colon;
15152 }
15153
15154 inline void script(
15155 lua_State* L, lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
15156 detail::typical_chunk_name_t basechunkname = {};
15157 const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
15158 if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
15159 lua_error(L);
15160 }
15161 }
15162
15163 inline void script(
15164 lua_State* L, const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
15165
15166 detail::typical_chunk_name_t basechunkname = {};
15167 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
15168 if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
15169 lua_error(L);
15170 }
15171 }
15172
15173 inline void script_file(lua_State* L, const std::string& filename, load_mode mode = load_mode::any) {
15174 if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
15175 lua_error(L);
15176 }
15177 }
15178
15179 inline void luajit_exception_handler(lua_State* L, int (*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) {
15180#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_)
15181 if (L == nullptr) {
15182 return;
15183 }
15184#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
15185 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15186#endif // make sure stack doesn't overflow
15187 lua_pushlightuserdata(L, (void*)handler);
15188 auto pn = pop_n(L, 1);
15189 luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
15190#else
15191 (void)L;
15192 (void)handler;
15193#endif
15194 }
15195
15196 inline void luajit_exception_off(lua_State* L) {
15197#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_)
15198 if (L == nullptr) {
15199 return;
15200 }
15201 luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF);
15202#else
15203 (void)L;
15204#endif
15205 }
15206 } // namespace stack
15207} // namespace sol
15208
15209// end of sol/stack.hpp
15210
15211// beginning of sol/object.hpp
15212
15213// beginning of sol/make_reference.hpp
15214
15215namespace sol {
15216
15217 template <typename R = reference, bool should_pop = !is_stack_based_v<R>, typename T>
15218 R make_reference(lua_State* L, T&& value) {
15219 int backpedal = stack::push(L, std::forward<T>(value));
15220 R r = stack::get<R>(L, -backpedal);
15221 if (should_pop) {
15222 lua_pop(L, backpedal);
15223 }
15224 return r;
15225 }
15226
15227 template <typename T, typename R = reference, bool should_pop = !is_stack_based_v<R>, typename... Args>
15228 R make_reference(lua_State* L, Args&&... args) {
15229 int backpedal = stack::push<T>(L, std::forward<Args>(args)...);
15230 R r = stack::get<R>(L, -backpedal);
15231 if (should_pop) {
15232 lua_pop(L, backpedal);
15233 }
15234 return r;
15235 }
15236
15237 template <typename R = reference, bool should_pop = !is_stack_based_v<R>, typename T>
15238 R make_reference_userdata(lua_State* L, T&& value) {
15239 int backpedal = stack::push_userdata(L, std::forward<T>(value));
15240 R r = stack::get<R>(L, -backpedal);
15241 if (should_pop) {
15242 lua_pop(L, backpedal);
15243 }
15244 return r;
15245 }
15246
15247 template <typename T, typename R = reference, bool should_pop = !is_stack_based_v<R>, typename... Args>
15248 R make_reference_userdata(lua_State* L, Args&&... args) {
15249 int backpedal = stack::push_userdata<T>(L, std::forward<Args>(args)...);
15250 R r = stack::get<R>(L, -backpedal);
15251 if (should_pop) {
15252 lua_pop(L, backpedal);
15253 }
15254 return r;
15255 }
15256
15257} // namespace sol
15258
15259// end of sol/make_reference.hpp
15260
15261// beginning of sol/object_base.hpp
15262
15263namespace sol {
15264
15265 template <typename ref_t>
15266 class basic_object_base : public ref_t {
15267 private:
15268 using base_t = ref_t;
15269
15270 template <typename T>
15271 decltype(auto) as_stack(std::true_type) const {
15272 return stack::get<T>(base_t::lua_state(), base_t::stack_index());
15273 }
15274
15275 template <typename T>
15276 decltype(auto) as_stack(std::false_type) const {
15277 base_t::push();
15278 return stack::pop<T>(base_t::lua_state());
15279 }
15280
15281 template <typename T>
15282 bool is_stack(std::true_type) const {
15283 return stack::check<T>(base_t::lua_state(), base_t::stack_index(), no_panic);
15284 }
15285
15286 template <typename T>
15287 bool is_stack(std::false_type) const {
15288 int r = base_t::registry_index();
15289 if (r == LUA_REFNIL)
15290 return meta::any_same<meta::unqualified_t<T>, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false;
15291 if (r == LUA_NOREF)
15292 return false;
15293 auto pp = stack::push_pop(*this);
15294 return stack::check<T>(base_t::lua_state(), -1, no_panic);
15295 }
15296
15297 public:
15298 basic_object_base() noexcept = default;
15299 basic_object_base(const basic_object_base&) = default;
15300 basic_object_base(basic_object_base&&) = default;
15301 basic_object_base& operator=(const basic_object_base&) = default;
15302 basic_object_base& operator=(basic_object_base&&) = default;
15303 template <typename T, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_object_base>>> = meta::enabler>
15304 basic_object_base(T&& arg, Args&&... args)
15305 : base_t(std::forward<T>(arg), std::forward<Args>(args)...) {
15306 }
15307
15308 template <typename T>
15309 decltype(auto) as() const {
15310 return as_stack<T>(is_stack_based<base_t>());
15311 }
15312
15313 template <typename T>
15314 bool is() const {
15315 return is_stack<T>(is_stack_based<base_t>());
15316 }
15317 };
15318} // namespace sol
15319
15320// end of sol/object_base.hpp
15321
15322namespace sol {
15323
15324 template <typename base_type>
15325 class basic_object : public basic_object_base<base_type> {
15326 private:
15327 typedef basic_object_base<base_type> base_t;
15328
15329 template <bool invert_and_pop = false>
15330 basic_object(std::integral_constant<bool, invert_and_pop>, lua_State* L, int index = -1) noexcept
15331 : base_t(L, index) {
15332 if (invert_and_pop) {
15333 lua_pop(L, -index);
15334 }
15335 }
15336
15337 protected:
15338 basic_object(detail::no_safety_tag, lua_nil_t n) : base_t(n) {
15339 }
15340 basic_object(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) {
15341 }
15342 basic_object(lua_State* L, detail::global_tag t) : base_t(L, t) {
15343 }
15344 basic_object(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) {
15345 }
15346 template <typename T,
15347 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_object>>, meta::neg<std::is_same<base_type, stack_reference>>,
15348 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
15349 basic_object(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward<T>(r)) {
15350 }
15351
15352 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
15353 basic_object(detail::no_safety_tag, lua_State* L, T&& r) noexcept : base_t(L, std::forward<T>(r)) {
15354 }
15355
15356 public:
15357 basic_object() noexcept = default;
15358 template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_object>>, meta::neg<std::is_same<base_type, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
15359 basic_object(T&& r)
15360 : base_t(std::forward<T>(r)) {
15361 }
15362 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
15363 basic_object(lua_State* L, T&& r)
15364 : base_t(L, std::forward<T>(r)) {
15365 }
15366 basic_object(lua_nil_t r)
15367 : base_t(r) {
15368 }
15369 basic_object(const basic_object&) = default;
15370 basic_object(basic_object&&) = default;
15371 basic_object(const stack_reference& r) noexcept
15372 : basic_object(r.lua_state(), r.stack_index()) {
15373 }
15374 basic_object(stack_reference&& r) noexcept
15375 : basic_object(r.lua_state(), r.stack_index()) {
15376 }
15377 template <typename Super>
15378 basic_object(const proxy_base<Super>& r) noexcept
15379 : basic_object(r.operator basic_object()) {
15380 }
15381 template <typename Super>
15382 basic_object(proxy_base<Super>&& r) noexcept
15383 : basic_object(r.operator basic_object()) {
15384 }
15385 basic_object(lua_State* L, lua_nil_t r) noexcept
15386 : base_t(L, r) {
15387 }
15388 basic_object(lua_State* L, int index = -1) noexcept
15389 : base_t(L, index) {
15390 }
15391 basic_object(lua_State* L, absolute_index index) noexcept
15392 : base_t(L, index) {
15393 }
15394 basic_object(lua_State* L, raw_index index) noexcept
15395 : base_t(L, index) {
15396 }
15397 basic_object(lua_State* L, ref_index index) noexcept
15398 : base_t(L, index) {
15399 }
15400 template <typename T, typename... Args>
15401 basic_object(lua_State* L, in_place_type_t<T>, Args&&... args) noexcept
15402 : basic_object(std::integral_constant<bool, !is_stack_based<base_t>::value>(), L, -stack::push<T>(L, std::forward<Args>(args)...)) {
15403 }
15404 template <typename T, typename... Args>
15405 basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept
15406 : basic_object(L, in_place_type<T>, std::forward<T>(arg), std::forward<Args>(args)...) {
15407 }
15408 basic_object& operator=(const basic_object&) = default;
15409 basic_object& operator=(basic_object&&) = default;
15410 basic_object& operator=(const base_type& b) {
15411 base_t::operator=(b);
15412 return *this;
15413 }
15414 basic_object& operator=(base_type&& b) {
15415 base_t::operator=(std::move(b));
15416 return *this;
15417 }
15418 template <typename Super>
15419 basic_object& operator=(const proxy_base<Super>& r) {
15420 this->operator=(r.operator basic_object());
15421 return *this;
15422 }
15423 template <typename Super>
15424 basic_object& operator=(proxy_base<Super>&& r) {
15425 this->operator=(r.operator basic_object());
15426 return *this;
15427 }
15428 };
15429
15430 template <typename T>
15431 object make_object(lua_State* L, T&& value) {
15432 return make_reference<object, true>(L, std::forward<T>(value));
15433 }
15434
15435 template <typename T, typename... Args>
15436 object make_object(lua_State* L, Args&&... args) {
15437 return make_reference<T, object, true>(L, std::forward<Args>(args)...);
15438 }
15439
15440 template <typename T>
15441 object make_object_userdata(lua_State* L, T&& value) {
15442 return make_reference_userdata<object, true>(L, std::forward<T>(value));
15443 }
15444
15445 template <typename T, typename... Args>
15446 object make_object_userdata(lua_State* L, Args&&... args) {
15447 return make_reference_userdata<T, object, true>(L, std::forward<Args>(args)...);
15448 }
15449} // namespace sol
15450
15451// end of sol/object.hpp
15452
15453// beginning of sol/function.hpp
15454
15455// beginning of sol/unsafe_function.hpp
15456
15457// beginning of sol/function_result.hpp
15458
15459// beginning of sol/protected_function_result.hpp
15460
15461// beginning of sol/proxy_base.hpp
15462
15463namespace sol {
15464 struct proxy_base_tag {};
15465
15466 namespace detail {
15467 template <typename T>
15468 using proxy_key_t = meta::conditional_t<meta::is_specialization_of_v<meta::unqualified_t<T>, std::tuple>, T,
15469 std::tuple<meta::conditional_t<std::is_array_v<meta::unqualified_t<T>>, std::remove_reference_t<T>&, meta::unqualified_t<T>>>>;
15470 }
15471
15472 template <typename Super>
15473 struct proxy_base : proxy_base_tag {
15474 operator std::string() const {
15475 const Super& super = *static_cast<const Super*>(static_cast<const void*>(this));
15476 return super.template get<std::string>();
15477 }
15478
15479 template <typename T, meta::enable<meta::neg<meta::is_string_constructible<T>>, is_proxy_primitive<meta::unqualified_t<T>>> = meta::enabler>
15480 operator T() const {
15481 const Super& super = *static_cast<const Super*>(static_cast<const void*>(this));
15482 return super.template get<T>();
15483 }
15484
15485 template <typename T, meta::enable<meta::neg<meta::is_string_constructible<T>>, meta::neg<is_proxy_primitive<meta::unqualified_t<T>>>> = meta::enabler>
15486 operator T&() const {
15487 const Super& super = *static_cast<const Super*>(static_cast<const void*>(this));
15488 return super.template get<T&>();
15489 }
15490
15491 lua_State* lua_state() const {
15492 const Super& super = *static_cast<const Super*>(static_cast<const void*>(this));
15493 return super.lua_state();
15494 }
15495 };
15496} // namespace sol
15497
15498// end of sol/proxy_base.hpp
15499
15500// beginning of sol/stack_iterator.hpp
15501
15502#include <limits>
15503#include <iterator>
15504
15505namespace sol {
15506 template <typename proxy_t, bool is_const>
15507 struct stack_iterator {
15508 typedef meta::conditional_t<is_const, const proxy_t, proxy_t> reference;
15509 typedef meta::conditional_t<is_const, const proxy_t*, proxy_t*> pointer;
15510 typedef proxy_t value_type;
15511 typedef std::ptrdiff_t difference_type;
15512 typedef std::random_access_iterator_tag iterator_category;
15513 lua_State* L;
15514 int index;
15515 int stacktop;
15516 proxy_t sp;
15517
15518 stack_iterator()
15519 : L(nullptr), index((std::numeric_limits<int>::max)()), stacktop((std::numeric_limits<int>::max)()), sp() {
15520 }
15521 stack_iterator(const stack_iterator<proxy_t, true>& r)
15522 : L(r.L), index(r.index), stacktop(r.stacktop), sp(r.sp) {
15523 }
15524 stack_iterator(lua_State* luastate, int idx, int topidx)
15525 : L(luastate), index(idx), stacktop(topidx), sp(luastate, idx) {
15526 }
15527
15528 reference operator*() {
15529 return proxy_t(L, index);
15530 }
15531
15532 reference operator*() const {
15533 return proxy_t(L, index);
15534 }
15535
15536 pointer operator->() {
15537 sp = proxy_t(L, index);
15538 return &sp;
15539 }
15540
15541 pointer operator->() const {
15542 const_cast<proxy_t&>(sp) = proxy_t(L, index);
15543 return &sp;
15544 }
15545
15546 stack_iterator& operator++() {
15547 ++index;
15548 return *this;
15549 }
15550
15551 stack_iterator operator++(int) {
15552 auto r = *this;
15553 this->operator++();
15554 return r;
15555 }
15556
15557 stack_iterator& operator--() {
15558 --index;
15559 return *this;
15560 }
15561
15562 stack_iterator operator--(int) {
15563 auto r = *this;
15564 this->operator--();
15565 return r;
15566 }
15567
15568 stack_iterator& operator+=(difference_type idx) {
15569 index += static_cast<int>(idx);
15570 return *this;
15571 }
15572
15573 stack_iterator& operator-=(difference_type idx) {
15574 index -= static_cast<int>(idx);
15575 return *this;
15576 }
15577
15578 difference_type operator-(const stack_iterator& r) const {
15579 return index - r.index;
15580 }
15581
15582 stack_iterator operator+(difference_type idx) const {
15583 stack_iterator r = *this;
15584 r += idx;
15585 return r;
15586 }
15587
15588 reference operator[](difference_type idx) const {
15589 return proxy_t(L, index + static_cast<int>(idx));
15590 }
15591
15592 bool operator==(const stack_iterator& r) const {
15593 if (stacktop == (std::numeric_limits<int>::max)()) {
15594 return r.index == r.stacktop;
15595 }
15596 else if (r.stacktop == (std::numeric_limits<int>::max)()) {
15597 return index == stacktop;
15598 }
15599 return index == r.index;
15600 }
15601
15602 bool operator!=(const stack_iterator& r) const {
15603 return !(this->operator==(r));
15604 }
15605
15606 bool operator<(const stack_iterator& r) const {
15607 return index < r.index;
15608 }
15609
15610 bool operator>(const stack_iterator& r) const {
15611 return index > r.index;
15612 }
15613
15614 bool operator<=(const stack_iterator& r) const {
15615 return index <= r.index;
15616 }
15617
15618 bool operator>=(const stack_iterator& r) const {
15619 return index >= r.index;
15620 }
15621 };
15622
15623 template <typename proxy_t, bool is_const>
15624 inline stack_iterator<proxy_t, is_const> operator+(typename stack_iterator<proxy_t, is_const>::difference_type n, const stack_iterator<proxy_t, is_const>& r) {
15625 return r + n;
15626 }
15627} // namespace sol
15628
15629// end of sol/stack_iterator.hpp
15630
15631// beginning of sol/stack_proxy.hpp
15632
15633// beginning of sol/stack_proxy_base.hpp
15634
15635namespace sol {
15636 struct stack_proxy_base : public proxy_base<stack_proxy_base> {
15637 private:
15638 lua_State* L;
15639 int index;
15640
15641 public:
15642 stack_proxy_base()
15643 : L(nullptr), index(0) {
15644 }
15645 stack_proxy_base(lua_State* L, int index)
15646 : L(L), index(index) {
15647 }
15648
15649 template <typename T>
15650 decltype(auto) get() const {
15651 return stack::get<T>(L, stack_index());
15652 }
15653
15654 template <typename T>
15655 bool is() const {
15656 return stack::check<T>(L, stack_index());
15657 }
15658
15659 template <typename T>
15660 decltype(auto) as() const {
15661 return get<T>();
15662 }
15663
15664 type get_type() const noexcept {
15665 return type_of(lua_state(), stack_index());
15666 }
15667
15668 int push() const {
15669 return push(L);
15670 }
15671
15672 int push(lua_State* Ls) const {
15673 lua_pushvalue(Ls, index);
15674 return 1;
15675 }
15676
15677 lua_State* lua_state() const {
15678 return L;
15679 }
15680 int stack_index() const {
15681 return index;
15682 }
15683 };
15684
15685 namespace stack {
15686 template <>
15687 struct unqualified_getter<stack_proxy_base> {
15688 static stack_proxy_base get(lua_State* L, int index = -1) {
15689 return stack_proxy_base(L, index);
15690 }
15691 };
15692
15693 template <>
15694 struct unqualified_pusher<stack_proxy_base> {
15695 static int push(lua_State*, const stack_proxy_base& ref) {
15696 return ref.push();
15697 }
15698 };
15699 } // namespace stack
15700
15701} // namespace sol
15702
15703// end of sol/stack_proxy_base.hpp
15704
15705namespace sol {
15706 struct stack_proxy : public stack_proxy_base {
15707 public:
15708 stack_proxy() : stack_proxy_base() {
15709 }
15710 stack_proxy(lua_State* L, int index) : stack_proxy_base(L, index) {
15711 }
15712
15713 template <typename... Ret, typename... Args>
15714 decltype(auto) call(Args&&... args);
15715
15716 template <typename... Args>
15717 decltype(auto) operator()(Args&&... args) {
15718 return call<>(std::forward<Args>(args)...);
15719 }
15720 };
15721
15722 namespace stack {
15723 template <>
15724 struct unqualified_getter<stack_proxy> {
15725 static stack_proxy get(lua_State* L, int index, record& tracking) {
15726 tracking.use(0);
15727 return stack_proxy(L, index);
15728 }
15729 };
15730
15731 template <>
15732 struct unqualified_pusher<stack_proxy> {
15733 static int push(lua_State*, const stack_proxy& ref) {
15734 return ref.push();
15735 }
15736 };
15737 } // namespace stack
15738} // namespace sol
15739
15740// end of sol/stack_proxy.hpp
15741
15742#include <cstdint>
15743
15744namespace sol {
15745 struct protected_function_result : public proxy_base<protected_function_result> {
15746 private:
15747 lua_State* L;
15748 int index;
15749 int returncount;
15750 int popcount;
15751 call_status err;
15752
15753 public:
15754 typedef stack_proxy reference_type;
15755 typedef stack_proxy value_type;
15756 typedef stack_proxy* pointer;
15757 typedef std::ptrdiff_t difference_type;
15758 typedef std::size_t size_type;
15759 typedef stack_iterator<stack_proxy, false> iterator;
15760 typedef stack_iterator<stack_proxy, true> const_iterator;
15761 typedef std::reverse_iterator<iterator> reverse_iterator;
15762 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
15763
15764 protected_function_result() noexcept = default;
15765 protected_function_result(lua_State* Ls, int idx = -1, int retnum = 0, int popped = 0, call_status pferr = call_status::ok) noexcept
15766 : L(Ls), index(idx), returncount(retnum), popcount(popped), err(pferr) {
15767 }
15768
15769 // We do not want anyone to copy these around willy-nilly
15770 // Will likely break people, but also will probably get rid of quiet bugs that have
15771 // been lurking. (E.g., Vanilla Lua will just quietly discard over-pops and under-pops:
15772 // LuaJIT and other Lua engines will implode and segfault at random later times.)
15773 protected_function_result(const protected_function_result&) = delete;
15774 protected_function_result& operator=(const protected_function_result&) = delete;
15775
15776 protected_function_result(protected_function_result&& o) noexcept
15777 : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) {
15778 // Must be manual, otherwise destructor will screw us
15779 // return count being 0 is enough to keep things clean
15780 // but we will be thorough
15781 o.abandon();
15782 }
15783 protected_function_result& operator=(protected_function_result&& o) noexcept {
15784 L = o.L;
15785 index = o.index;
15786 returncount = o.returncount;
15787 popcount = o.popcount;
15788 err = o.err;
15789 // Must be manual, otherwise destructor will screw us
15790 // return count being 0 is enough to keep things clean
15791 // but we will be thorough
15792 o.abandon();
15793 return *this;
15794 }
15795
15796 protected_function_result(const unsafe_function_result& o) = delete;
15797 protected_function_result& operator=(const unsafe_function_result& o) = delete;
15798 protected_function_result(unsafe_function_result&& o) noexcept;
15799 protected_function_result& operator=(unsafe_function_result&& o) noexcept;
15800
15801 call_status status() const noexcept {
15802 return err;
15803 }
15804
15805 bool valid() const noexcept {
15806 return status() == call_status::ok || status() == call_status::yielded;
15807 }
15808
15809 template <typename T>
15810 decltype(auto) get(int index_offset = 0) const {
15811 using UT = meta::unqualified_t<T>;
15812 int target = index + index_offset;
15813 if constexpr (meta::is_optional_v<UT>) {
15814 using ValueType = typename UT::value_type;
15815 if constexpr (std::is_same_v<ValueType, error>) {
15816 if (valid()) {
15817 return UT();
15818 }
15819 return UT(error(detail::direct_error, stack::get<std::string>(L, target)));
15820 }
15821 else {
15822 if (!valid()) {
15823 return UT();
15824 }
15825 return stack::get<UT>(L, target);
15826 }
15827 }
15828 else {
15829 if constexpr (std::is_same_v<T, error>) {
15830#if SOL_IS_ON(SOL_SAFE_PROXIES_I_)
15831 if (valid()) {
15832 type t = type_of(L, target);
15833 type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is an error)");
15834 }
15835#endif // Check Argument Safety
15836 return error(detail::direct_error, stack::get<std::string>(L, target));
15837 }
15838 else {
15839#if SOL_IS_ON(SOL_SAFE_PROXIES_I_)
15840 if (!valid()) {
15841 type t = type_of(L, target);
15842 type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is not an error)");
15843 }
15844#endif // Check Argument Safety
15845 return stack::get<T>(L, target);
15846 }
15847 }
15848 }
15849
15850 type get_type(int index_offset = 0) const noexcept {
15851 return type_of(L, index + static_cast<int>(index_offset));
15852 }
15853
15854 stack_proxy operator[](difference_type index_offset) const {
15855 return stack_proxy(L, index + static_cast<int>(index_offset));
15856 }
15857
15858 iterator begin() {
15859 return iterator(L, index, stack_index() + return_count());
15860 }
15861 iterator end() {
15862 return iterator(L, stack_index() + return_count(), stack_index() + return_count());
15863 }
15864 const_iterator begin() const {
15865 return const_iterator(L, index, stack_index() + return_count());
15866 }
15867 const_iterator end() const {
15868 return const_iterator(L, stack_index() + return_count(), stack_index() + return_count());
15869 }
15870 const_iterator cbegin() const {
15871 return begin();
15872 }
15873 const_iterator cend() const {
15874 return end();
15875 }
15876
15877 reverse_iterator rbegin() {
15878 return std::reverse_iterator<iterator>(begin());
15879 }
15880 reverse_iterator rend() {
15881 return std::reverse_iterator<iterator>(end());
15882 }
15883 const_reverse_iterator rbegin() const {
15884 return std::reverse_iterator<const_iterator>(begin());
15885 }
15886 const_reverse_iterator rend() const {
15887 return std::reverse_iterator<const_iterator>(end());
15888 }
15889 const_reverse_iterator crbegin() const {
15890 return std::reverse_iterator<const_iterator>(cbegin());
15891 }
15892 const_reverse_iterator crend() const {
15893 return std::reverse_iterator<const_iterator>(cend());
15894 }
15895
15896 lua_State* lua_state() const noexcept {
15897 return L;
15898 };
15899 int stack_index() const noexcept {
15900 return index;
15901 };
15902 int return_count() const noexcept {
15903 return returncount;
15904 };
15905 int pop_count() const noexcept {
15906 return popcount;
15907 };
15908 void abandon() noexcept {
15909 // L = nullptr;
15910 index = 0;
15911 returncount = 0;
15912 popcount = 0;
15913 err = call_status::runtime;
15914 }
15915 ~protected_function_result() {
15916 stack::remove(L, index, popcount);
15917 }
15918 };
15919
15920 namespace stack {
15921 template <>
15922 struct unqualified_pusher<protected_function_result> {
15923 static int push(lua_State* L, const protected_function_result& pfr) {
15924#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
15925 luaL_checkstack(L, static_cast<int>(pfr.pop_count()), detail::not_enough_stack_space_generic);
15926#endif // make sure stack doesn't overflow
15927 int p = 0;
15928 for (int i = 0; i < pfr.pop_count(); ++i) {
15929 lua_pushvalue(L, i + pfr.stack_index());
15930 ++p;
15931 }
15932 return p;
15933 }
15934 };
15935 } // namespace stack
15936} // namespace sol
15937
15938// end of sol/protected_function_result.hpp
15939
15940// beginning of sol/unsafe_function_result.hpp
15941
15942#include <cstdint>
15943
15944namespace sol {
15945 struct unsafe_function_result : public proxy_base<unsafe_function_result> {
15946 private:
15947 lua_State* L;
15948 int index;
15949 int returncount;
15950
15951 public:
15952 typedef stack_proxy reference_type;
15953 typedef stack_proxy value_type;
15954 typedef stack_proxy* pointer;
15955 typedef std::ptrdiff_t difference_type;
15956 typedef std::size_t size_type;
15957 typedef stack_iterator<stack_proxy, false> iterator;
15958 typedef stack_iterator<stack_proxy, true> const_iterator;
15959 typedef std::reverse_iterator<iterator> reverse_iterator;
15960 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
15961
15962 unsafe_function_result() noexcept = default;
15963 unsafe_function_result(lua_State* Ls, int idx = -1, int retnum = 0) noexcept : L(Ls), index(idx), returncount(retnum) {
15964 }
15965
15966 // We do not want anyone to copy these around willy-nilly
15967 // Will likely break people, but also will probably get rid of quiet bugs that have
15968 // been lurking. (E.g., Vanilla Lua will just quietly discard over-pops and under-pops:
15969 // LuaJIT and other Lua engines will implode and segfault at random later times.)
15970 unsafe_function_result(const unsafe_function_result&) = delete;
15971 unsafe_function_result& operator=(const unsafe_function_result&) = delete;
15972
15973 unsafe_function_result(unsafe_function_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount) {
15974 // Must be manual, otherwise destructor will screw us
15975 // return count being 0 is enough to keep things clean
15976 // but will be thorough
15977 o.abandon();
15978 }
15979 unsafe_function_result& operator=(unsafe_function_result&& o) noexcept {
15980 L = o.L;
15981 index = o.index;
15982 returncount = o.returncount;
15983 // Must be manual, otherwise destructor will screw us
15984 // return count being 0 is enough to keep things clean
15985 // but will be thorough
15986 o.abandon();
15987 return *this;
15988 }
15989
15990 unsafe_function_result(const protected_function_result& o) = delete;
15991 unsafe_function_result& operator=(const protected_function_result& o) = delete;
15992 unsafe_function_result(protected_function_result&& o) noexcept;
15993 unsafe_function_result& operator=(protected_function_result&& o) noexcept;
15994
15995 template <typename T>
15996 decltype(auto) get(difference_type index_offset = 0) const {
15997 return stack::get<T>(L, index + static_cast<int>(index_offset));
15998 }
15999
16000 type get_type(difference_type index_offset = 0) const noexcept {
16001 return type_of(L, index + static_cast<int>(index_offset));
16002 }
16003
16004 stack_proxy operator[](difference_type index_offset) const {
16005 return stack_proxy(L, index + static_cast<int>(index_offset));
16006 }
16007
16008 iterator begin() {
16009 return iterator(L, index, stack_index() + return_count());
16010 }
16011 iterator end() {
16012 return iterator(L, stack_index() + return_count(), stack_index() + return_count());
16013 }
16014 const_iterator begin() const {
16015 return const_iterator(L, index, stack_index() + return_count());
16016 }
16017 const_iterator end() const {
16018 return const_iterator(L, stack_index() + return_count(), stack_index() + return_count());
16019 }
16020 const_iterator cbegin() const {
16021 return begin();
16022 }
16023 const_iterator cend() const {
16024 return end();
16025 }
16026
16027 reverse_iterator rbegin() {
16028 return std::reverse_iterator<iterator>(begin());
16029 }
16030 reverse_iterator rend() {
16031 return std::reverse_iterator<iterator>(end());
16032 }
16033 const_reverse_iterator rbegin() const {
16034 return std::reverse_iterator<const_iterator>(begin());
16035 }
16036 const_reverse_iterator rend() const {
16037 return std::reverse_iterator<const_iterator>(end());
16038 }
16039 const_reverse_iterator crbegin() const {
16040 return std::reverse_iterator<const_iterator>(cbegin());
16041 }
16042 const_reverse_iterator crend() const {
16043 return std::reverse_iterator<const_iterator>(cend());
16044 }
16045
16046 call_status status() const noexcept {
16047 return call_status::ok;
16048 }
16049
16050 bool valid() const noexcept {
16051 return status() == call_status::ok || status() == call_status::yielded;
16052 }
16053
16054 lua_State* lua_state() const {
16055 return L;
16056 };
16057 int stack_index() const {
16058 return index;
16059 };
16060 int return_count() const {
16061 return returncount;
16062 };
16063 void abandon() noexcept {
16064 // L = nullptr;
16065 index = 0;
16066 returncount = 0;
16067 }
16068 ~unsafe_function_result() {
16069 lua_pop(L, returncount);
16070 }
16071 };
16072
16073 namespace stack {
16074 template <>
16075 struct unqualified_pusher<unsafe_function_result> {
16076 static int push(lua_State* L, const unsafe_function_result& fr) {
16077 int p = 0;
16078 for (int i = 0; i < fr.return_count(); ++i) {
16079 lua_pushvalue(L, i + fr.stack_index());
16080 ++p;
16081 }
16082 return p;
16083 }
16084 };
16085 } // namespace stack
16086} // namespace sol
16087
16088// end of sol/unsafe_function_result.hpp
16089
16090#include <cstdint>
16091
16092namespace sol {
16093
16094 namespace detail {
16095 template <>
16096 struct is_speshul<unsafe_function_result> : std::true_type {};
16097 template <>
16098 struct is_speshul<protected_function_result> : std::true_type {};
16099
16100 template <std::size_t I, typename... Args, typename T>
16101 stack_proxy get(types<Args...>, meta::index_value<0>, meta::index_value<I>, const T& fr) {
16102 return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I));
16103 }
16104
16105 template <std::size_t I, std::size_t N, typename Arg, typename... Args, typename T, meta::enable<meta::boolean<(N > 0)>> = meta::enabler>
16106 stack_proxy get(types<Arg, Args...>, meta::index_value<N>, meta::index_value<I>, const T& fr) {
16107 return get(types<Args...>(), meta::index_value<N - 1>(), meta::index_value<I + lua_size<Arg>::value>(), fr);
16108 }
16109 } // namespace detail
16110
16111 template <>
16112 struct tie_size<unsafe_function_result> : std::integral_constant<std::size_t, SIZE_MAX> {};
16113
16114 template <>
16115 struct tie_size<protected_function_result> : std::integral_constant<std::size_t, SIZE_MAX> {};
16116
16117 template <std::size_t I>
16118 stack_proxy get(const unsafe_function_result& fr) {
16119 return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I));
16120 }
16121
16122 template <std::size_t I, typename... Args>
16123 stack_proxy get(types<Args...> t, const unsafe_function_result& fr) {
16124 return detail::get(t, meta::index_value<I>(), meta::index_value<0>(), fr);
16125 }
16126
16127 template <std::size_t I>
16128 stack_proxy get(const protected_function_result& fr) {
16129 return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I));
16130 }
16131
16132 template <std::size_t I, typename... Args>
16133 stack_proxy get(types<Args...> t, const protected_function_result& fr) {
16134 return detail::get(t, meta::index_value<I>(), meta::index_value<0>(), fr);
16135 }
16136} // namespace sol
16137
16138// end of sol/function_result.hpp
16139
16140// beginning of sol/function_types.hpp
16141
16142// beginning of sol/function_types_core.hpp
16143
16144// beginning of sol/wrapper.hpp
16145
16146namespace sol {
16147
16148 namespace detail {
16149 template <typename T>
16150 using array_return_type = meta::conditional_t<std::is_array<T>::value, std::add_lvalue_reference_t<T>, T>;
16151 }
16152
16153 template <typename F, typename = void>
16154 struct wrapper {
16155 typedef lua_bind_traits<meta::unqualified_t<F>> traits_type;
16156 typedef typename traits_type::args_list args_list;
16157 typedef typename traits_type::args_list free_args_list;
16158 typedef typename traits_type::returns_list returns_list;
16159
16160 template <typename... Args>
16161 static decltype(auto) call(F& f, Args&&... args) {
16162 return f(std::forward<Args>(args)...);
16163 }
16164
16165 struct caller {
16166 template <typename... Args>
16167 decltype(auto) operator()(F& fx, Args&&... args) const {
16168 return call(fx, std::forward<Args>(args)...);
16169 }
16170 };
16171 };
16172
16173 template <typename F>
16174 struct wrapper<F, std::enable_if_t<std::is_function<std::remove_pointer_t<meta::unqualified_t<F>>>::value>> {
16175 typedef lua_bind_traits<std::remove_pointer_t<meta::unqualified_t<F>>> traits_type;
16176 typedef typename traits_type::args_list args_list;
16177 typedef typename traits_type::args_list free_args_list;
16178 typedef typename traits_type::returns_list returns_list;
16179
16180 template <F fx, typename... Args>
16181 static decltype(auto) invoke(Args&&... args) {
16182 return fx(std::forward<Args>(args)...);
16183 }
16184
16185 template <typename... Args>
16186 static decltype(auto) call(F& fx, Args&&... args) {
16187 return fx(std::forward<Args>(args)...);
16188 }
16189
16190 struct caller {
16191 template <typename... Args>
16192 decltype(auto) operator()(F& fx, Args&&... args) const {
16193 return call(fx, std::forward<Args>(args)...);
16194 }
16195 };
16196
16197 template <F fx>
16198 struct invoker {
16199 template <typename... Args>
16200 decltype(auto) operator()(Args&&... args) const {
16201 return invoke<fx>(std::forward<Args>(args)...);
16202 }
16203 };
16204 };
16205
16206 template <typename F>
16207 struct wrapper<F, std::enable_if_t<std::is_member_object_pointer<meta::unqualified_t<F>>::value>> {
16208 typedef lua_bind_traits<meta::unqualified_t<F>> traits_type;
16209 typedef typename traits_type::object_type object_type;
16210 typedef typename traits_type::return_type return_type;
16211 typedef typename traits_type::args_list args_list;
16212 typedef types<object_type&, return_type> free_args_list;
16213 typedef typename traits_type::returns_list returns_list;
16214
16215 template <F fx>
16216 static auto call(object_type& mem) -> detail::array_return_type<decltype(mem.*fx)> {
16217 return mem.*fx;
16218 }
16219
16220 template <F fx, typename Arg, typename... Args>
16221 static decltype(auto) invoke(object_type& mem, Arg&& arg, Args&&...) {
16222 return mem.*fx = std::forward<Arg>(arg);
16223 }
16224
16225 template <typename Fx>
16226 static auto call(Fx&& fx, object_type& mem) -> detail::array_return_type<decltype(mem.*fx)> {
16227 return mem.*fx;
16228 }
16229
16230 template <typename Fx, typename Arg, typename... Args>
16231 static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) {
16232 using actual_type = meta::unqualified_t<detail::array_return_type<decltype(mem.*fx)>>;
16233 if constexpr (std::is_array_v<actual_type>) {
16234 using std::cbegin;
16235 using std::cend;
16236 auto first = cbegin(arg);
16237 auto last = cend(arg);
16238 for (std::size_t i = 0; first != last; ++i, ++first) {
16239 (mem.*fx)[i] = *first;
16240 }
16241 }
16242 else {
16243 (mem.*fx) = std::forward<Arg>(arg);
16244 }
16245 }
16246
16247 struct caller {
16248 template <typename Fx, typename... Args>
16249 decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const {
16250 return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...);
16251 }
16252 };
16253
16254 template <F fx>
16255 struct invoker {
16256 template <typename... Args>
16257 decltype(auto) operator()(Args&&... args) const {
16258 return invoke<fx>(std::forward<Args>(args)...);
16259 }
16260 };
16261 };
16262
16263 template <typename F, typename R, typename O, typename... FArgs>
16264 struct member_function_wrapper {
16265 typedef O object_type;
16266 typedef lua_bind_traits<F> traits_type;
16267 typedef typename traits_type::args_list args_list;
16268 typedef types<object_type&, FArgs...> free_args_list;
16269 typedef meta::tuple_types<R> returns_list;
16270
16271 template <F fx, typename... Args>
16272 static R invoke(O& mem, Args&&... args) {
16273 return (mem.*fx)(std::forward<Args>(args)...);
16274 }
16275
16276 template <typename Fx, typename... Args>
16277 static R call(Fx&& fx, O& mem, Args&&... args) {
16278 return (mem.*fx)(std::forward<Args>(args)...);
16279 }
16280
16281 struct caller {
16282 template <typename Fx, typename... Args>
16283 decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const {
16284 return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...);
16285 }
16286 };
16287
16288 template <F fx>
16289 struct invoker {
16290 template <typename... Args>
16291 decltype(auto) operator()(O& mem, Args&&... args) const {
16292 return invoke<fx>(mem, std::forward<Args>(args)...);
16293 }
16294 };
16295 };
16296
16297 template <typename R, typename O, typename... Args>
16298 struct wrapper<R (O::*)(Args...)> : public member_function_wrapper<R (O::*)(Args...), R, O, Args...> {};
16299
16300 template <typename R, typename O, typename... Args>
16301 struct wrapper<R (O::*)(Args...) const> : public member_function_wrapper<R (O::*)(Args...) const, R, O, Args...> {};
16302
16303 template <typename R, typename O, typename... Args>
16304 struct wrapper<R (O::*)(Args...) const volatile> : public member_function_wrapper<R (O::*)(Args...) const volatile, R, O, Args...> {};
16305
16306 template <typename R, typename O, typename... Args>
16307 struct wrapper<R (O::*)(Args...)&> : public member_function_wrapper<R (O::*)(Args...)&, R, O, Args...> {};
16308
16309 template <typename R, typename O, typename... Args>
16310 struct wrapper<R (O::*)(Args...) const&> : public member_function_wrapper<R (O::*)(Args...) const&, R, O, Args...> {};
16311
16312 template <typename R, typename O, typename... Args>
16313 struct wrapper<R (O::*)(Args...) const volatile&> : public member_function_wrapper<R (O::*)(Args...) const volatile&, R, O, Args...> {};
16314
16315 template <typename R, typename O, typename... Args>
16316 struct wrapper<R (O::*)(Args..., ...)&> : public member_function_wrapper<R (O::*)(Args..., ...)&, R, O, Args...> {};
16317
16318 template <typename R, typename O, typename... Args>
16319 struct wrapper<R (O::*)(Args..., ...) const&> : public member_function_wrapper<R (O::*)(Args..., ...) const&, R, O, Args...> {};
16320
16321 template <typename R, typename O, typename... Args>
16322 struct wrapper<R (O::*)(Args..., ...) const volatile&> : public member_function_wrapper<R (O::*)(Args..., ...) const volatile&, R, O, Args...> {};
16323
16324 template <typename R, typename O, typename... Args>
16325 struct wrapper<R (O::*)(Args...) &&> : public member_function_wrapper<R (O::*)(Args...)&, R, O, Args...> {};
16326
16327 template <typename R, typename O, typename... Args>
16328 struct wrapper<R (O::*)(Args...) const&&> : public member_function_wrapper<R (O::*)(Args...) const&, R, O, Args...> {};
16329
16330 template <typename R, typename O, typename... Args>
16331 struct wrapper<R (O::*)(Args...) const volatile&&> : public member_function_wrapper<R (O::*)(Args...) const volatile&, R, O, Args...> {};
16332
16333 template <typename R, typename O, typename... Args>
16334 struct wrapper<R (O::*)(Args..., ...) &&> : public member_function_wrapper<R (O::*)(Args..., ...)&, R, O, Args...> {};
16335
16336 template <typename R, typename O, typename... Args>
16337 struct wrapper<R (O::*)(Args..., ...) const&&> : public member_function_wrapper<R (O::*)(Args..., ...) const&, R, O, Args...> {};
16338
16339 template <typename R, typename O, typename... Args>
16340 struct wrapper<R (O::*)(Args..., ...) const volatile&&> : public member_function_wrapper<R (O::*)(Args..., ...) const volatile&, R, O, Args...> {};
16341
16342#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
16343 // noexcept has become a part of a function's type
16344
16345 template <typename R, typename O, typename... Args>
16346 struct wrapper<R (O::*)(Args...) noexcept> : public member_function_wrapper<R (O::*)(Args...) noexcept, R, O, Args...> {};
16347
16348 template <typename R, typename O, typename... Args>
16349 struct wrapper<R (O::*)(Args...) const noexcept> : public member_function_wrapper<R (O::*)(Args...) const noexcept, R, O, Args...> {};
16350
16351 template <typename R, typename O, typename... Args>
16352 struct wrapper<R (O::*)(Args...) const volatile noexcept> : public member_function_wrapper<R (O::*)(Args...) const volatile noexcept, R, O, Args...> {};
16353
16354 template <typename R, typename O, typename... Args>
16355 struct wrapper<R (O::*)(Args...) & noexcept> : public member_function_wrapper<R (O::*)(Args...) & noexcept, R, O, Args...> {};
16356
16357 template <typename R, typename O, typename... Args>
16358 struct wrapper<R (O::*)(Args...) const& noexcept> : public member_function_wrapper<R (O::*)(Args...) const& noexcept, R, O, Args...> {};
16359
16360 template <typename R, typename O, typename... Args>
16361 struct wrapper<R (O::*)(Args...) const volatile& noexcept> : public member_function_wrapper<R (O::*)(Args...) const volatile& noexcept, R, O, Args...> {};
16362
16363 template <typename R, typename O, typename... Args>
16364 struct wrapper<R (O::*)(Args..., ...) & noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) & noexcept, R, O, Args...> {};
16365
16366 template <typename R, typename O, typename... Args>
16367 struct wrapper<R (O::*)(Args..., ...) const& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) const& noexcept, R, O, Args...> {};
16368
16369 template <typename R, typename O, typename... Args>
16370 struct wrapper<R (O::*)(Args..., ...) const volatile& noexcept>
16371 : public member_function_wrapper<R (O::*)(Args..., ...) const volatile& noexcept, R, O, Args...> {};
16372
16373 template <typename R, typename O, typename... Args>
16374 struct wrapper<R (O::*)(Args...) && noexcept> : public member_function_wrapper<R (O::*)(Args...) & noexcept, R, O, Args...> {};
16375
16376 template <typename R, typename O, typename... Args>
16377 struct wrapper<R (O::*)(Args...) const&& noexcept> : public member_function_wrapper<R (O::*)(Args...) const& noexcept, R, O, Args...> {};
16378
16379 template <typename R, typename O, typename... Args>
16380 struct wrapper<R (O::*)(Args...) const volatile&& noexcept> : public member_function_wrapper<R (O::*)(Args...) const volatile& noexcept, R, O, Args...> {};
16381
16382 template <typename R, typename O, typename... Args>
16383 struct wrapper<R (O::*)(Args..., ...) && noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) & noexcept, R, O, Args...> {};
16384
16385 template <typename R, typename O, typename... Args>
16386 struct wrapper<R (O::*)(Args..., ...) const&& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) const& noexcept, R, O, Args...> {};
16387
16388 template <typename R, typename O, typename... Args>
16389 struct wrapper<R (O::*)(Args..., ...) const volatile&& noexcept>
16390 : public member_function_wrapper<R (O::*)(Args..., ...) const volatile& noexcept, R, O, Args...> {};
16391
16392#endif // noexcept is part of a function's type
16393
16394} // namespace sol
16395
16396// end of sol/wrapper.hpp
16397
16398#include <memory>
16399
16400namespace sol {
16401namespace function_detail {
16402 template <typename Fx, int start = 1, bool is_yielding = false>
16403 int call(lua_State* L) {
16404 Fx& fx = stack::get<user<Fx>>(L, upvalue_index(start));
16405 int nr = fx(L);
16406 if (is_yielding) {
16407 return lua_yield(L, nr);
16408 }
16409 else {
16410 return nr;
16411 }
16412 }
16413}
16414} // namespace sol::function_detail
16415
16416// end of sol/function_types_core.hpp
16417
16418// beginning of sol/function_types_templated.hpp
16419
16420// beginning of sol/call.hpp
16421
16422// beginning of sol/property.hpp
16423
16424#include <type_traits>
16425#include <utility>
16426
16427namespace sol {
16428 namespace detail {
16429 struct no_prop {};
16430 }
16431
16432 template <typename R, typename W>
16433 struct property_wrapper : detail::ebco<R, 0>, detail::ebco<W, 1> {
16434 private:
16435 using read_base_t = detail::ebco<R, 0>;
16436 using write_base_t = detail::ebco<W, 1>;
16437
16438 public:
16439 template <typename Rx, typename Wx>
16440 property_wrapper(Rx&& r, Wx&& w)
16441 : read_base_t(std::forward<Rx>(r)), write_base_t(std::forward<Wx>(w)) {
16442 }
16443
16444 W& write() {
16445 return write_base_t::value();
16446 }
16447
16448 const W& write() const {
16449 return write_base_t::value();
16450 }
16451
16452 R& read() {
16453 return read_base_t::value();
16454 }
16455
16456 const R& read() const {
16457 return read_base_t::value();
16458 }
16459 };
16460
16461 template <typename F, typename G>
16462 inline decltype(auto) property(F&& f, G&& g) {
16463 typedef lua_bind_traits<meta::unqualified_t<F>> left_traits;
16464 typedef lua_bind_traits<meta::unqualified_t<G>> right_traits;
16465 if constexpr (left_traits::free_arity < right_traits::free_arity) {
16466 return property_wrapper<std::decay_t<F>, std::decay_t<G>>(std::forward<F>(f), std::forward<G>(g));
16467 }
16468 else {
16469 return property_wrapper<std::decay_t<G>, std::decay_t<F>>(std::forward<G>(g), std::forward<F>(f));
16470 }
16471 }
16472
16473 template <typename F>
16474 inline decltype(auto) property(F&& f) {
16475 typedef lua_bind_traits<meta::unqualified_t<F>> left_traits;
16476 if constexpr (left_traits::free_arity < 2) {
16477 return property_wrapper<std::decay_t<F>, detail::no_prop>(std::forward<F>(f), detail::no_prop());
16478 }
16479 else {
16480 return property_wrapper<detail::no_prop, std::decay_t<F>>(detail::no_prop(), std::forward<F>(f));
16481 }
16482 }
16483
16484 template <typename F>
16485 inline decltype(auto) readonly_property(F&& f) {
16486 return property_wrapper<std::decay_t<F>, detail::no_prop>(std::forward<F>(f), detail::no_prop());
16487 }
16488
16489 template <typename F>
16490 inline decltype(auto) writeonly_property(F&& f) {
16491 return property_wrapper<detail::no_prop, std::decay_t<F>>(detail::no_prop(), std::forward<F>(f));
16492 }
16493
16494 template <typename T>
16495 struct readonly_wrapper : detail::ebco<T> {
16496 private:
16497 using base_t = detail::ebco<T>;
16498
16499 public:
16500 using base_t::base_t;
16501
16502 operator T&() {
16503 return base_t::value();
16504 }
16505 operator const T&() const {
16506 return base_t::value();
16507 }
16508 };
16509
16510 // Allow someone to make a member variable readonly (const)
16511 template <typename R, typename T>
16512 inline auto readonly(R T::*v) {
16513 return readonly_wrapper<meta::unqualified_t<decltype(v)>>(v);
16514 }
16515
16516 template <typename T>
16517 struct var_wrapper : detail::ebco<T> {
16518 private:
16519 using base_t = detail::ebco<T>;
16520
16521 public:
16522 using base_t::base_t;
16523 };
16524
16525 template <typename V>
16526 inline auto var(V&& v) {
16527 typedef std::decay_t<V> T;
16528 return var_wrapper<T>(std::forward<V>(v));
16529 }
16530
16531 namespace meta {
16532 template <typename T>
16533 struct is_member_object : std::is_member_object_pointer<T> {};
16534
16535 template <typename T>
16536 struct is_member_object<readonly_wrapper<T>> : std::true_type {};
16537
16538 template <typename T>
16539 inline constexpr bool is_member_object_v = is_member_object<T>::value;
16540 } // namespace meta
16541
16542} // namespace sol
16543
16544// end of sol/property.hpp
16545
16546// beginning of sol/protect.hpp
16547
16548#include <utility>
16549
16550namespace sol {
16551
16552 template <typename T>
16553 struct protect_t {
16554 T value;
16555
16556 template <typename Arg, typename... Args, meta::disable<std::is_same<protect_t, meta::unqualified_t<Arg>>> = meta::enabler>
16557 protect_t(Arg&& arg, Args&&... args)
16558 : value(std::forward<Arg>(arg), std::forward<Args>(args)...) {
16559 }
16560
16561 protect_t(const protect_t&) = default;
16562 protect_t(protect_t&&) = default;
16563 protect_t& operator=(const protect_t&) = default;
16564 protect_t& operator=(protect_t&&) = default;
16565 };
16566
16567 template <typename T>
16568 auto protect(T&& value) {
16569 return protect_t<std::decay_t<T>>(std::forward<T>(value));
16570 }
16571
16572} // namespace sol
16573
16574// end of sol/protect.hpp
16575
16576namespace sol {
16577 namespace u_detail {
16578
16579 } // namespace u_detail
16580
16581 namespace policy_detail {
16582 template <int I, int... In>
16583 inline void handle_policy(static_stack_dependencies<I, In...>, lua_State* L, int&) {
16584 if constexpr (sizeof...(In) == 0) {
16585 (void)L;
16586 return;
16587 }
16588 else {
16589 absolute_index ai(L, I);
16590 if (type_of(L, ai) != type::userdata) {
16591 return;
16592 }
16593 lua_createtable(L, static_cast<int>(sizeof...(In)), 0);
16594 stack_reference deps(L, -1);
16595 auto per_dep = [&L, &deps](int i) {
16596#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
16597 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
16598#endif // make sure stack doesn't overflow
16599 lua_pushvalue(L, i);
16600 luaL_ref(L, deps.stack_index());
16601 };
16602 (void)per_dep;
16603 (void)detail::swallow{ int(), (per_dep(In), int())... };
16604 lua_setuservalue(L, ai);
16605 }
16606 }
16607
16608 template <int... In>
16609 inline void handle_policy(returns_self_with<In...>, lua_State* L, int& pushed) {
16610 pushed = stack::push(L, raw_index(1));
16611 handle_policy(static_stack_dependencies<-1, In...>(), L, pushed);
16612 }
16613
16614 inline void handle_policy(const stack_dependencies& sdeps, lua_State* L, int&) {
16615 absolute_index ai(L, sdeps.target);
16616 if (type_of(L, ai) != type::userdata) {
16617 return;
16618 }
16619 lua_createtable(L, static_cast<int>(sdeps.size()), 0);
16620 stack_reference deps(L, -1);
16621#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
16622 luaL_checkstack(L, static_cast<int>(sdeps.size()), detail::not_enough_stack_space_generic);
16623#endif // make sure stack doesn't overflow
16624 for (std::size_t i = 0; i < sdeps.size(); ++i) {
16625 lua_pushvalue(L, sdeps.stack_indices[i]);
16626 luaL_ref(L, deps.stack_index());
16627 }
16628 lua_setuservalue(L, ai);
16629 }
16630
16631 template <typename P, meta::disable<std::is_base_of<detail::policy_base_tag, meta::unqualified_t<P>>> = meta::enabler>
16632 inline void handle_policy(P&& p, lua_State* L, int& pushed) {
16633 pushed = std::forward<P>(p)(L, pushed);
16634 }
16635 } // namespace policy_detail
16636
16637 namespace function_detail {
16638 inline int no_construction_error(lua_State* L) {
16639 return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
16640 }
16641 } // namespace function_detail
16642
16643 namespace call_detail {
16644
16645 template <typename R, typename W>
16646 inline auto& pick(std::true_type, property_wrapper<R, W>& f) {
16647 return f.read();
16648 }
16649
16650 template <typename R, typename W>
16651 inline auto& pick(std::false_type, property_wrapper<R, W>& f) {
16652 return f.write();
16653 }
16654
16655 template <typename T, typename List>
16656 struct void_call : void_call<T, meta::function_args_t<List>> {};
16657
16658 template <typename T, typename... Args>
16659 struct void_call<T, types<Args...>> {
16660 static void call(Args...) {
16661 }
16662 };
16663
16664 template <typename T, bool checked, bool clean_stack>
16665 struct constructor_match {
16666 T* obj_;
16667
16668 constructor_match(T* o) : obj_(o) {
16669 }
16670
16671 template <typename Fx, std::size_t I, typename... R, typename... Args>
16672 int operator()(types<Fx>, meta::index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
16673 detail::default_construct func{};
16674 return stack::call_into_lua<checked, clean_stack>(r, a, L, start, func, obj_);
16675 }
16676 };
16677
16678 namespace overload_detail {
16679 template <std::size_t... M, typename Match, typename... Args>
16680 inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) {
16681 return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types");
16682 }
16683
16684 template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args>
16685 inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L,
16686 int fxarity, int start, Args&&... args) {
16687 typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
16688 typedef meta::tuple_types<typename traits::return_type> return_types;
16689 typedef typename traits::free_args_list args_list;
16690 // compile-time eliminate any functions that we know ahead of time are of improper arity
16691 if constexpr (!traits::runtime_variadics_t::value
16692 && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
16693 return overload_match_arity(types<Fxs...>(),
16694 std::index_sequence<In...>(),
16695 std::index_sequence<M...>(),
16696 std::forward<Match>(matchfx),
16697 L,
16698 fxarity,
16699 start,
16700 std::forward<Args>(args)...);
16701 }
16702 else {
16703 if constexpr (!traits::runtime_variadics_t::value) {
16704 if (traits::free_arity != fxarity) {
16705 return overload_match_arity(types<Fxs...>(),
16706 std::index_sequence<In...>(),
16707 std::index_sequence<traits::free_arity, M...>(),
16708 std::forward<Match>(matchfx),
16709 L,
16710 fxarity,
16711 start,
16712 std::forward<Args>(args)...);
16713 }
16714 }
16715 stack::record tracking{};
16716 if (!stack::stack_detail::check_types(args_list(), L, start, no_panic, tracking)) {
16717 return overload_match_arity(types<Fxs...>(),
16718 std::index_sequence<In...>(),
16719 std::index_sequence<M...>(),
16720 std::forward<Match>(matchfx),
16721 L,
16722 fxarity,
16723 start,
16724 std::forward<Args>(args)...);
16725 }
16726 return matchfx(types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
16727 }
16728 }
16729
16730 template <std::size_t... M, typename Match, typename... Args>
16731 inline int overload_match_arity_single(
16732 types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
16733 return overload_match_arity(types<>(),
16734 std::index_sequence<>(),
16735 std::index_sequence<M...>(),
16736 std::forward<Match>(matchfx),
16737 L,
16738 fxarity,
16739 start,
16740 std::forward<Args>(args)...);
16741 }
16742
16743 template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args>
16744 inline int overload_match_arity_single(
16745 types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
16746 typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
16747 typedef meta::tuple_types<typename traits::return_type> return_types;
16748 typedef typename traits::free_args_list args_list;
16749 // compile-time eliminate any functions that we know ahead of time are of improper arity
16750 if constexpr (!traits::runtime_variadics_t::value
16751 && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
16752 return overload_match_arity(types<>(),
16753 std::index_sequence<>(),
16754 std::index_sequence<M...>(),
16755 std::forward<Match>(matchfx),
16756 L,
16757 fxarity,
16758 start,
16759 std::forward<Args>(args)...);
16760 }
16761 if constexpr (!traits::runtime_variadics_t::value) {
16762 if (traits::free_arity != fxarity) {
16763 return overload_match_arity(types<>(),
16764 std::index_sequence<>(),
16765 std::index_sequence<traits::free_arity, M...>(),
16766 std::forward<Match>(matchfx),
16767 L,
16768 fxarity,
16769 start,
16770 std::forward<Args>(args)...);
16771 }
16772 }
16773 return matchfx(types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
16774 }
16775
16776 template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match,
16777 typename... Args>
16778 inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx,
16779 lua_State* L, int fxarity, int start, Args&&... args) {
16780 typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
16781 typedef meta::tuple_types<typename traits::return_type> return_types;
16782 typedef typename traits::free_args_list args_list;
16783 // compile-time eliminate any functions that we know ahead of time are of improper arity
16784 if constexpr (!traits::runtime_variadics_t::value
16785 && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
16786 return overload_match_arity(types<Fx1, Fxs...>(),
16787 std::index_sequence<I1, In...>(),
16788 std::index_sequence<M...>(),
16789 std::forward<Match>(matchfx),
16790 L,
16791 fxarity,
16792 start,
16793 std::forward<Args>(args)...);
16794 }
16795 else {
16796 if constexpr (!traits::runtime_variadics_t::value) {
16797 if (traits::free_arity != fxarity) {
16798 return overload_match_arity(types<Fx1, Fxs...>(),
16799 std::index_sequence<I1, In...>(),
16800 std::index_sequence<traits::free_arity, M...>(),
16801 std::forward<Match>(matchfx),
16802 L,
16803 fxarity,
16804 start,
16805 std::forward<Args>(args)...);
16806 }
16807 }
16808 stack::record tracking{};
16809 if (!stack::stack_detail::check_types(args_list(), L, start, no_panic, tracking)) {
16810 return overload_match_arity(types<Fx1, Fxs...>(),
16811 std::index_sequence<I1, In...>(),
16812 std::index_sequence<M...>(),
16813 std::forward<Match>(matchfx),
16814 L,
16815 fxarity,
16816 start,
16817 std::forward<Args>(args)...);
16818 }
16819 return matchfx(types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
16820 }
16821 }
16822 } // namespace overload_detail
16823
16824 template <typename... Functions, typename Match, typename... Args>
16825 inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
16826 return overload_detail::overload_match_arity_single(types<Functions...>(),
16827 std::make_index_sequence<sizeof...(Functions)>(),
16828 std::index_sequence<>(),
16829 std::forward<Match>(matchfx),
16830 L,
16831 fxarity,
16832 start,
16833 std::forward<Args>(args)...);
16834 }
16835
16836 template <typename... Functions, typename Match, typename... Args>
16837 inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) {
16838 int fxarity = lua_gettop(L) - (start - 1);
16839 return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
16840 }
16841
16842 template <typename T, typename... TypeLists, typename Match, typename... Args>
16843 inline int construct_match(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
16844 // use same overload resolution matching as all other parts of the framework
16845 return overload_match_arity<decltype(void_call<T, TypeLists>::call)...>(
16846 std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
16847 }
16848
16849 template <typename T, bool checked, bool clean_stack, typename... TypeLists>
16850 inline int construct_trampolined(lua_State* L) {
16851 static const auto& meta = usertype_traits<T>::metatable();
16852 int argcount = lua_gettop(L);
16853 call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot;
16854 argcount -= static_cast<int>(syntax);
16855
16856 T* obj = detail::usertype_allocate<T>(L);
16857 reference userdataref(L, -1);
16858 stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
16859 umf();
16860
16861 // put userdata at the first index
16862 lua_insert(L, 1);
16863 construct_match<T, TypeLists...>(constructor_match<T, checked, clean_stack>(obj), L, argcount, 1 + static_cast<int>(syntax));
16864
16865 userdataref.push();
16866 return 1;
16867 }
16868
16869 template <typename T, bool checked, bool clean_stack, typename... TypeLists>
16870 inline int construct(lua_State* L) {
16871 return detail::static_trampoline<&construct_trampolined<T, checked, clean_stack, TypeLists...>>(L);
16872 }
16873
16874 template <typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename = void>
16875 struct agnostic_lua_call_wrapper {
16876 template <typename Fx, typename... Args>
16877 static int call(lua_State* L, Fx&& f, Args&&... args) {
16878 using uFx = meta::unqualified_t<Fx>;
16879 static constexpr bool is_ref = is_lua_reference_v<uFx>;
16880 if constexpr (is_ref) {
16881 if constexpr (is_index) {
16882 return stack::push(L, std::forward<Fx>(f), std::forward<Args>(args)...);
16883 }
16884 else {
16885 std::forward<Fx>(f) = stack::unqualified_get<F>(L, boost + (is_variable ? 3 : 1));
16886 return 0;
16887 }
16888 }
16889 else {
16890 using wrap = wrapper<uFx>;
16891 using traits_type = typename wrap::traits_type;
16892 using fp_t = typename traits_type::function_pointer_type;
16893 constexpr bool is_function_pointer_convertible
16894 = std::is_class_v<uFx> && std::is_convertible_v<std::decay_t<Fx>, fp_t>;
16895 if constexpr (is_function_pointer_convertible) {
16896 fp_t fx = f;
16897 return agnostic_lua_call_wrapper<fp_t, is_index, is_variable, checked, boost, clean_stack>{}.call(
16898 L, fx, std::forward<Args>(args)...);
16899 }
16900 else {
16901 using returns_list = typename wrap::returns_list;
16902 using args_list = typename wrap::free_args_list;
16903 using caller = typename wrap::caller;
16904 return stack::call_into_lua<checked, clean_stack>(
16905 returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f), std::forward<Args>(args)...);
16906 }
16907 }
16908 }
16909 };
16910
16911 template <typename T, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
16912 struct agnostic_lua_call_wrapper<var_wrapper<T>, is_index, is_variable, checked, boost, clean_stack, C> {
16913 template <typename F>
16914 static int call(lua_State* L, F&& f) {
16915 if constexpr (is_index) {
16916 constexpr bool is_stack = is_stack_based_v<meta::unqualified_t<decltype(detail::unwrap(f.value()))>>;
16917 if constexpr (clean_stack && !is_stack) {
16918 lua_settop(L, 0);
16919 }
16920 return stack::push_reference(L, detail::unwrap(f.value()));
16921 }
16922 else {
16923 if constexpr (std::is_const_v<meta::unwrapped_t<T>>) {
16924 (void)f;
16925 return luaL_error(L, "sol: cannot write to a readonly (const) variable");
16926 }
16927 else {
16928 using R = meta::unwrapped_t<T>;
16929 if constexpr (std::is_assignable_v<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>) {
16930 detail::unwrap(f.value()) = stack::unqualified_get<meta::unwrapped_t<T>>(L, boost + (is_variable ? 3 : 1));
16931 if (clean_stack) {
16932 lua_settop(L, 0);
16933 }
16934 return 0;
16935 }
16936 else {
16937 return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
16938 }
16939 }
16940 }
16941 }
16942 };
16943
16944 template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
16945 struct agnostic_lua_call_wrapper<lua_CFunction_ref, is_index, is_variable, checked, boost, clean_stack, C> {
16946 static int call(lua_State* L, lua_CFunction_ref f) {
16947 return f(L);
16948 }
16949 };
16950
16951 template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
16952 struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, boost, clean_stack, C> {
16953 static int call(lua_State* L, lua_CFunction f) {
16954 return f(L);
16955 }
16956 };
16957
16958#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
16959 template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
16960 struct agnostic_lua_call_wrapper<detail::lua_CFunction_noexcept, is_index, is_variable, checked, boost, clean_stack, C> {
16961 static int call(lua_State* L, detail::lua_CFunction_noexcept f) {
16962 return f(L);
16963 }
16964 };
16965#endif // noexcept function types
16966
16967 template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
16968 struct agnostic_lua_call_wrapper<detail::no_prop, is_index, is_variable, checked, boost, clean_stack, C> {
16969 static int call(lua_State* L, const detail::no_prop&) {
16970 return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property");
16971 }
16972 };
16973
16974 template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
16975 struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, boost, clean_stack, C> {
16976 static int call(lua_State* L, const no_construction&) {
16977 return function_detail::no_construction_error(L);
16978 }
16979 };
16980
16981 template <typename... Args, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
16982 struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, boost, clean_stack, C> {
16983 static int call(lua_State*, const bases<Args...>&) {
16984 // Uh. How did you even call this, lul
16985 return 0;
16986 }
16987 };
16988
16989 template <typename T, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
16990 struct agnostic_lua_call_wrapper<std::reference_wrapper<T>, is_index, is_variable, checked, boost, clean_stack, C> {
16991 static int call(lua_State* L, std::reference_wrapper<T> f) {
16992 agnostic_lua_call_wrapper<T, is_index, is_variable, checked, boost, clean_stack> alcw{};
16993 return alcw.call(L, f.get());
16994 }
16995 };
16996
16997 template <typename T, typename F, bool is_index, bool is_variable, bool checked = detail::default_safe_function_calls, int boost = 0,
16998 bool clean_stack = true, typename = void>
16999 struct lua_call_wrapper {
17000 template <typename Fx, typename... Args>
17001 static int call(lua_State* L, Fx&& fx, Args&&... args) {
17002 if constexpr (std::is_member_function_pointer_v<F>) {
17003 using wrap = wrapper<F>;
17004 using object_type = typename wrap::object_type;
17005 if constexpr (sizeof...(Args) < 1) {
17006 using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
17007 static_assert(std::is_base_of_v<object_type, Ta>, "It seems like you might have accidentally bound a class type with a member function method that does not correspond to the class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one class \"T\" but then bind member methods from a complete unrelated class. Check things over!");
17008#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_)
17009 auto maybeo = stack::check_get<Ta*>(L, 1);
17010 if (!maybeo || maybeo.value() == nullptr) {
17011 return luaL_error(L,
17012 "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are "
17013 "preceeded by the "
17014 "actual object with '.' syntax)");
17015 }
17016 object_type* o = static_cast<object_type*>(maybeo.value());
17017 return call(L, std::forward<Fx>(fx), *o);
17018#else
17019 object_type& o = static_cast<object_type&>(*stack::unqualified_get<non_null<Ta*>>(L, 1));
17020 return call(L, std::forward<Fx>(fx), o);
17021#endif // Safety
17022 }
17023 else {
17024 using returns_list = typename wrap::returns_list;
17025 using args_list = typename wrap::args_list;
17026 using caller = typename wrap::caller;
17027 return stack::call_into_lua<checked, clean_stack>(
17028 returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), std::forward<Args>(args)...);
17029 }
17030 }
17031 else if constexpr (std::is_member_object_pointer_v<F>) {
17032 using wrap = wrapper<F>;
17033 using object_type = typename wrap::object_type;
17034 if constexpr (is_index) {
17035 if constexpr (sizeof...(Args) < 1) {
17036 using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
17037 static_assert(std::is_base_of_v<object_type, Ta>, "It seems like you might have accidentally bound a class type with a member function method that does not correspond to the class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one class \"T\" but then bind member methods from a complete unrelated class. Check things over!");
17038#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_)
17039 auto maybeo = stack::check_get<Ta*>(L, 1);
17040 if (!maybeo || maybeo.value() == nullptr) {
17041 if (is_variable) {
17042 return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)");
17043 }
17044 return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)");
17045 }
17046 object_type* o = static_cast<object_type*>(maybeo.value());
17047 return call(L, std::forward<Fx>(fx), *o);
17048#else
17049 object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
17050 return call(L, std::forward<Fx>(fx), o);
17051#endif // Safety
17052 }
17053 else {
17054 using returns_list = typename wrap::returns_list;
17055 using caller = typename wrap::caller;
17056 return stack::call_into_lua<checked, clean_stack>(returns_list(),
17057 types<>(),
17058 L,
17059 boost + (is_variable ? 3 : 2),
17060 caller(),
17061 std::forward<Fx>(fx),
17062 std::forward<Args>(args)...);
17063 }
17064 }
17065 else {
17066 using traits_type = lua_bind_traits<F>;
17067 using return_type = typename traits_type::return_type;
17068 constexpr bool ret_is_const = std::is_const_v<std::remove_reference_t<return_type>>;
17069 if constexpr (ret_is_const) {
17070 (void)fx;
17071 (void)detail::swallow{ 0, (static_cast<void>(args), 0)... };
17072 return luaL_error(L, "sol: cannot write to a readonly (const) variable");
17073 }
17074 else {
17075 using u_return_type = meta::unqualified_t<return_type>;
17076 constexpr bool is_assignable = std::is_copy_assignable_v<u_return_type> || std::is_array_v<u_return_type>;
17077 if constexpr (!is_assignable) {
17078 (void)fx;
17079 (void)detail::swallow{ 0, ((void)args, 0)... };
17080 return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
17081 }
17082 else {
17083 using args_list = typename wrap::args_list;
17084 using caller = typename wrap::caller;
17085 if constexpr (sizeof...(Args) > 0) {
17086 return stack::call_into_lua<checked, clean_stack>(types<void>(),
17087 args_list(),
17088 L,
17089 boost + (is_variable ? 3 : 2),
17090 caller(),
17091 std::forward<Fx>(fx),
17092 std::forward<Args>(args)...);
17093 }
17094 else {
17095 using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
17096#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_)
17097 auto maybeo = stack::check_get<Ta*>(L, 1);
17098 if (!maybeo || maybeo.value() == nullptr) {
17099 if (is_variable) {
17100 return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)");
17101 }
17102 return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)");
17103 }
17104 object_type* po = static_cast<object_type*>(maybeo.value());
17105 object_type& o = *po;
17106#else
17107 object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
17108#endif // Safety
17109
17110 return stack::call_into_lua<checked, clean_stack>(
17111 types<void>(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), o);
17112 }
17113 }
17114 }
17115 }
17116 }
17117 else {
17118 agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost, clean_stack> alcw{};
17119 return alcw.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
17120 }
17121 }
17122 };
17123
17124 template <typename T, typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17125 struct lua_call_wrapper<T, readonly_wrapper<F>, is_index, is_variable, checked, boost, clean_stack, C> {
17126 using traits_type = lua_bind_traits<F>;
17127 using wrap = wrapper<F>;
17128 using object_type = typename wrap::object_type;
17129
17130 static int call(lua_State* L, readonly_wrapper<F>&& rw) {
17131 if constexpr (!is_index) {
17132 (void)rw;
17133 return luaL_error(L, "sol: cannot write to a sol::readonly variable");
17134 }
17135 else {
17136 lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
17137 return lcw.call(L, std::move(rw.value()));
17138 }
17139 }
17140
17141 static int call(lua_State* L, readonly_wrapper<F>&& rw, object_type& o) {
17142 if constexpr (!is_index) {
17143 (void)o;
17144 return call(L, std::move(rw));
17145 }
17146 else {
17147 lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
17148 return lcw.call(L, rw.value(), o);
17149 }
17150 }
17151
17152 static int call(lua_State* L, const readonly_wrapper<F>& rw) {
17153 if constexpr (!is_index) {
17154 (void)rw;
17155 return luaL_error(L, "sol: cannot write to a sol::readonly variable");
17156 }
17157 else {
17158 lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
17159 return lcw.call(L, rw.value());
17160 }
17161 }
17162
17163 static int call(lua_State* L, const readonly_wrapper<F>& rw, object_type& o) {
17164 if constexpr (!is_index) {
17165 (void)o;
17166 return call(L, rw);
17167 }
17168 else {
17169 lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
17170 return lcw.call(L, rw.value(), o);
17171 }
17172 }
17173 };
17174
17175 template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17176 struct lua_call_wrapper<T, constructor_list<Args...>, is_index, is_variable, checked, boost, clean_stack, C> {
17177 typedef constructor_list<Args...> F;
17178
17179 static int call(lua_State* L, F&) {
17180 const auto& meta = usertype_traits<T>::metatable();
17181 int argcount = lua_gettop(L);
17182 call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot;
17183 argcount -= static_cast<int>(syntax);
17184
17185 T* obj = detail::usertype_allocate<T>(L);
17186 reference userdataref(L, -1);
17187 stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
17188 umf();
17189
17190 // put userdata at the first index
17191 lua_insert(L, 1);
17192 construct_match<T, Args...>(constructor_match<T, checked, clean_stack>(obj), L, argcount, boost + 1 + 1 + static_cast<int>(syntax));
17193
17194 userdataref.push();
17195 return 1;
17196 }
17197 };
17198
17199 template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17200 struct lua_call_wrapper<T, constructor_wrapper<Cxs...>, is_index, is_variable, checked, boost, clean_stack, C> {
17201 typedef constructor_wrapper<Cxs...> F;
17202
17203 struct onmatch {
17204 template <typename Fx, std::size_t I, typename... R, typename... Args>
17205 int operator()(types<Fx>, meta::index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
17206 const auto& meta = usertype_traits<T>::metatable();
17207 T* obj = detail::usertype_allocate<T>(L);
17208 reference userdataref(L, -1);
17209 stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
17210 umf();
17211
17212 auto& func = std::get<I>(f.functions);
17213 // put userdata at the first index
17214 lua_insert(L, 1);
17215 stack::call_into_lua<checked, clean_stack>(r, a, L, boost + 1 + start, func, detail::implicit_wrapper<T>(obj));
17216
17217 userdataref.push();
17218 return 1;
17219 }
17220 };
17221
17222 static int call(lua_State* L, F& f) {
17223 call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1);
17224 int syntaxval = static_cast<int>(syntax);
17225 int argcount = lua_gettop(L) - syntaxval;
17226 return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
17227 }
17228 };
17229
17230 template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17231 struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, clean_stack, C> {
17232
17233 template <typename F>
17234 static int call(lua_State* L, F&& f) {
17235 if constexpr (std::is_void_v<Fx>) {
17236 return detail::usertype_alloc_destruct<T>(L);
17237 }
17238 else {
17239 using uFx = meta::unqualified_t<Fx>;
17240 lua_call_wrapper<T, uFx, is_index, is_variable, checked, boost, clean_stack> lcw{};
17241 return lcw.call(L, std::forward<F>(f).fx);
17242 }
17243 }
17244 };
17245
17246 template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17247 struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, boost, clean_stack, C> {
17248 typedef overload_set<Fs...> F;
17249
17250 struct on_match {
17251 template <typename Fx, std::size_t I, typename... R, typename... Args>
17252 int operator()(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) {
17253 auto& f = std::get<I>(fx.functions);
17254 return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost>{}.call(L, f);
17255 }
17256 };
17257
17258 static int call(lua_State* L, F& fx) {
17259 return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx);
17260 }
17261 };
17262
17263 template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17264 struct lua_call_wrapper<T, factory_wrapper<Fs...>, is_index, is_variable, checked, boost, clean_stack, C> {
17265 typedef factory_wrapper<Fs...> F;
17266
17267 struct on_match {
17268 template <typename Fx, std::size_t I, typename... R, typename... Args>
17269 int operator()(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) {
17270 auto& f = std::get<I>(fx.functions);
17271 return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost, clean_stack>{}.call(L, f);
17272 }
17273 };
17274
17275 static int call(lua_State* L, F& fx) {
17276 return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx);
17277 }
17278 };
17279
17280 template <typename T, typename R, typename W, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17281 struct lua_call_wrapper<T, property_wrapper<R, W>, is_index, is_variable, checked, boost, clean_stack, C> {
17282 typedef meta::conditional_t<is_index, R, W> P;
17283 typedef meta::unqualified_t<P> U;
17284 typedef wrapper<U> wrap;
17285 typedef lua_bind_traits<U> traits_type;
17286 typedef meta::unqualified_t<typename traits_type::template arg_at<0>> object_type;
17287
17288 template <typename F, typename... Args>
17289 static int call(lua_State* L, F&& f, Args&&... args) {
17290 constexpr bool is_specialized = meta::any<std::is_same<U, detail::no_prop>,
17291 meta::is_specialization_of<U, var_wrapper>,
17292 meta::is_specialization_of<U, constructor_wrapper>,
17293 meta::is_specialization_of<U, constructor_list>,
17294 std::is_member_pointer<U>>::value;
17295 if constexpr (is_specialized) {
17296 if constexpr (is_index) {
17297 decltype(auto) p = f.read();
17298 lua_call_wrapper<T, meta::unqualified_t<decltype(p)>, is_index, is_variable, checked, boost, clean_stack> lcw{};
17299 return lcw.call(L, p, std::forward<Args>(args)...);
17300 }
17301 else {
17302 decltype(auto) p = f.write();
17303 lua_call_wrapper<T, meta::unqualified_t<decltype(p)>, is_index, is_variable, checked, boost, clean_stack> lcw{};
17304 return lcw.call(L, p, std::forward<Args>(args)...);
17305 }
17306 }
17307 else {
17308 constexpr bool non_class_object_type = meta::any<std::is_void<object_type>,
17309 meta::boolean<lua_type_of<meta::unwrap_unqualified_t<object_type>>::value != type::userdata>>::value;
17310 if constexpr (non_class_object_type) {
17311 // The type being void means we don't have any arguments, so it might be a free functions?
17312 using args_list = typename traits_type::free_args_list;
17313 using returns_list = typename wrap::returns_list;
17314 using caller = typename wrap::caller;
17315 if constexpr (is_index) {
17316 decltype(auto) pf = f.read();
17317 return stack::call_into_lua<checked, clean_stack>(
17318 returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf);
17319 }
17320 else {
17321 decltype(auto) pf = f.write();
17322 return stack::call_into_lua<checked, clean_stack>(
17323 returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf);
17324 }
17325 }
17326 else {
17327 using args_list = meta::pop_front_type_t<typename traits_type::free_args_list>;
17328 using Ta = T;
17329 using Oa = std::remove_pointer_t<object_type>;
17330#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_)
17331 auto maybeo = stack::check_get<Ta*>(L, 1);
17332 if (!maybeo || maybeo.value() == nullptr) {
17333 if (is_variable) {
17334 return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)");
17335 }
17336 return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)");
17337 }
17338 Oa* o = static_cast<Oa*>(maybeo.value());
17339#else
17340 Oa* o = static_cast<Oa*>(stack::get<non_null<Ta*>>(L, 1));
17341#endif // Safety
17342 using returns_list = typename wrap::returns_list;
17343 using caller = typename wrap::caller;
17344 if constexpr (is_index) {
17345 decltype(auto) pf = f.read();
17346 return stack::call_into_lua<checked, clean_stack>(
17347 returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper<Oa>(*o));
17348 }
17349 else {
17350 decltype(auto) pf = f.write();
17351 return stack::call_into_lua<checked, clean_stack>(
17352 returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper<Oa>(*o));
17353 }
17354 }
17355 }
17356 }
17357 };
17358
17359 template <typename T, typename V, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17360 struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, boost, clean_stack, C> {
17361 typedef protect_t<V> F;
17362
17363 template <typename... Args>
17364 static int call(lua_State* L, F& fx, Args&&... args) {
17365 return lua_call_wrapper<T, V, is_index, is_variable, true, boost, clean_stack>{}.call(L, fx.value, std::forward<Args>(args)...);
17366 }
17367 };
17368
17369 template <typename T, typename F, typename... Policies, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17370 struct lua_call_wrapper<T, policy_wrapper<F, Policies...>, is_index, is_variable, checked, boost, clean_stack, C> {
17371 typedef policy_wrapper<F, Policies...> P;
17372
17373 template <std::size_t... In>
17374 static int call(std::index_sequence<In...>, lua_State* L, P& fx) {
17375 int pushed = lua_call_wrapper<T, F, is_index, is_variable, checked, boost, false, C>{}.call(L, fx.value);
17376 (void)detail::swallow{ int(), (policy_detail::handle_policy(std::get<In>(fx.policies), L, pushed), int())... };
17377 return pushed;
17378 }
17379
17380 static int call(lua_State* L, P& fx) {
17381 typedef typename P::indices indices;
17382 return call(indices(), L, fx);
17383 }
17384 };
17385
17386 template <typename T, typename Y, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17387 struct lua_call_wrapper<T, yielding_t<Y>, is_index, is_variable, checked, boost, clean_stack, C> {
17388 template <typename F>
17389 static int call(lua_State* L, F&& f) {
17390 return lua_call_wrapper<T, meta::unqualified_t<Y>, is_index, is_variable, checked, boost, clean_stack>{}.call(L, f.func);
17391 }
17392 };
17393
17394 template <typename T, typename Sig, typename P, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
17395 struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, clean_stack, C> {
17396 static int call(lua_State* L, const function_arguments<Sig, P>& f) {
17397 lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> lcw{};
17398 return lcw.call(L, std::get<0>(f.arguments));
17399 }
17400
17401 static int call(lua_State* L, function_arguments<Sig, P>&& f) {
17402 lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> lcw{};
17403 return lcw.call(L, std::get<0>(std::move(f.arguments)));
17404 }
17405 };
17406
17407 template <typename T, bool is_index, bool is_variable, int boost = 0, bool checked = detail::default_safe_function_calls, bool clean_stack = true,
17408 typename Fx, typename... Args>
17409 inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) {
17410 using uFx = meta::unqualified_t<Fx>;
17411 if constexpr (meta::is_specialization_of_v<uFx, yielding_t>) {
17412 using real_fx = meta::unqualified_t<decltype(std::forward<Fx>(fx).func)>;
17413 lua_call_wrapper<T, real_fx, is_index, is_variable, checked, boost, clean_stack> lcw{};
17414 return lcw.call(L, std::forward<Fx>(fx).func, std::forward<Args>(args)...);
17415 }
17416 else {
17417 lua_call_wrapper<T, uFx, is_index, is_variable, checked, boost, clean_stack> lcw{};
17418 return lcw.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
17419 }
17420 }
17421
17422 template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls,
17423 bool clean_stack = true>
17424 inline int call_user(lua_State* L) {
17425 auto& fx = stack::unqualified_get<user<F>>(L, upvalue_index(start));
17426 using uFx = meta::unqualified_t<F>;
17427 int nr = call_wrapped<T, is_index, is_variable, 0, checked, clean_stack>(L, fx);
17428 if constexpr (meta::is_specialization_of_v<uFx, yielding_t>) {
17429 return lua_yield(L, nr);
17430 }
17431 else {
17432 return nr;
17433 }
17434 }
17435
17436 template <typename T, typename = void>
17437 struct is_var_bind : std::false_type {};
17438
17439 template <typename T>
17440 struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type {};
17441
17442 template <typename T>
17443 struct is_var_bind<T, std::enable_if_t<is_lua_reference_or_proxy<T>::value>> : std::true_type {};
17444
17445 template <>
17446 struct is_var_bind<detail::no_prop> : std::true_type {};
17447
17448 template <typename R, typename W>
17449 struct is_var_bind<property_wrapper<R, W>> : std::true_type {};
17450
17451 template <typename T>
17452 struct is_var_bind<var_wrapper<T>> : std::true_type {};
17453
17454 template <typename T>
17455 struct is_var_bind<readonly_wrapper<T>> : is_var_bind<meta::unqualified_t<T>> {};
17456
17457 template <typename F, typename... Policies>
17458 struct is_var_bind<policy_wrapper<F, Policies...>> : is_var_bind<meta::unqualified_t<F>> {};
17459 } // namespace call_detail
17460
17461 template <typename T>
17462 struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> {};
17463
17464 template <typename T>
17465 using is_var_wrapper = meta::is_specialization_of<T, var_wrapper>;
17466
17467 template <typename T>
17468 struct is_function_binding : meta::neg<is_variable_binding<T>> {};
17469
17470} // namespace sol
17471
17472// end of sol/call.hpp
17473
17474namespace sol {
17475 namespace function_detail {
17476 template <typename F, F fx>
17477 inline int call_wrapper_variable(std::false_type, lua_State* L) {
17478 typedef meta::bind_traits<meta::unqualified_t<F>> traits_type;
17479 typedef typename traits_type::args_list args_list;
17480 typedef meta::tuple_types<typename traits_type::return_type> return_type;
17481 return stack::call_into_lua(return_type(), args_list(), L, 1, fx);
17482 }
17483
17484 template <typename R, typename V, V, typename T>
17485 inline int call_set_assignable(std::false_type, T&&, lua_State* L) {
17486 return luaL_error(L, "cannot write to this type: copy assignment/constructor not available");
17487 }
17488
17489 template <typename R, typename V, V variable, typename T>
17490 inline int call_set_assignable(std::true_type, lua_State* L, T&& mem) {
17491 (mem.*variable) = stack::get<R>(L, 2);
17492 return 0;
17493 }
17494
17495 template <typename R, typename V, V, typename T>
17496 inline int call_set_variable(std::false_type, lua_State* L, T&&) {
17497 return luaL_error(L, "cannot write to a const variable");
17498 }
17499
17500 template <typename R, typename V, V variable, typename T>
17501 inline int call_set_variable(std::true_type, lua_State* L, T&& mem) {
17502 return call_set_assignable<R, V, variable>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, std::forward<T>(mem));
17503 }
17504
17505 template <typename V, V variable>
17506 inline int call_wrapper_variable(std::true_type, lua_State* L) {
17507 typedef meta::bind_traits<meta::unqualified_t<V>> traits_type;
17508 typedef typename traits_type::object_type T;
17509 typedef typename traits_type::return_type R;
17510 auto& mem = stack::get<T>(L, 1);
17511 switch (lua_gettop(L)) {
17512 case 1: {
17513 decltype(auto) r = (mem.*variable);
17514 stack::push_reference(L, std::forward<decltype(r)>(r));
17515 return 1;
17516 }
17517 case 2:
17518 return call_set_variable<R, V, variable>(meta::neg<std::is_const<R>>(), L, mem);
17519 default:
17520 return luaL_error(L, "incorrect number of arguments to member variable function call");
17521 }
17522 }
17523
17524 template <typename F, F fx>
17525 inline int call_wrapper_function(std::false_type, lua_State* L) {
17526 return call_wrapper_variable<F, fx>(std::is_member_object_pointer<F>(), L);
17527 }
17528
17529 template <typename F, F fx>
17530 inline int call_wrapper_function(std::true_type, lua_State* L) {
17531 return call_detail::call_wrapped<void, false, false>(L, fx);
17532 }
17533
17534 template <typename F, F fx>
17535 int call_wrapper_entry(lua_State* L) noexcept(meta::bind_traits<F>::is_noexcept) {
17536 return call_wrapper_function<F, fx>(std::is_member_function_pointer<meta::unqualified_t<F>>(), L);
17537 }
17538
17539 template <typename... Fxs>
17540 struct c_call_matcher {
17541 template <typename Fx, std::size_t I, typename R, typename... Args>
17542 int operator()(types<Fx>, meta::index_value<I>, types<R>, types<Args...>, lua_State* L, int, int) const {
17543 typedef meta::at_in_pack_t<I, Fxs...> target;
17544 return target::call(L);
17545 }
17546 };
17547
17548 template <typename F, F fx>
17549 inline int c_call_raw(std::true_type, lua_State* L) {
17550 return fx(L);
17551 }
17552
17553 template <typename F, F fx>
17554 inline int c_call_raw(std::false_type, lua_State* L) {
17555#ifdef __clang__
17556 return detail::trampoline(L, function_detail::call_wrapper_entry<F, fx>);
17557#else
17558 return detail::typed_static_trampoline<decltype(&function_detail::call_wrapper_entry<F, fx>), (&function_detail::call_wrapper_entry<F, fx>)>(L);
17559#endif // fuck you clang :c
17560 }
17561
17562 } // namespace function_detail
17563
17564 template <typename F, F fx>
17565 inline int c_call(lua_State* L) {
17566 typedef meta::unqualified_t<F> Fu;
17567 typedef std::integral_constant<bool,
17568 std::is_same<Fu, lua_CFunction>::value
17569#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
17570 || std::is_same<Fu, detail::lua_CFunction_noexcept>::value
17571#endif
17572 >
17573 is_raw;
17574 return function_detail::c_call_raw<F, fx>(is_raw(), L);
17575 }
17576
17577 template <typename F, F f>
17578 struct wrap {
17579 typedef F type;
17580
17581 static int call(lua_State* L) {
17582 return c_call<type, f>(L);
17583 }
17584 };
17585
17586 template <typename... Fxs>
17587 inline int c_call(lua_State* L) {
17588 if constexpr (sizeof...(Fxs) < 2) {
17589 using target = meta::at_in_pack_t<0, Fxs...>;
17590 return target::call(L);
17591 }
17592 else {
17593 return call_detail::overload_match_arity<typename Fxs::type...>(function_detail::c_call_matcher<Fxs...>(), L, lua_gettop(L), 1);
17594 }
17595 }
17596
17597} // namespace sol
17598
17599// end of sol/function_types_templated.hpp
17600
17601// beginning of sol/function_types_stateless.hpp
17602
17603namespace sol { namespace function_detail {
17604 template <typename Function, bool is_yielding>
17605 struct upvalue_free_function {
17606 using function_type = std::remove_pointer_t<std::decay_t<Function>>;
17607 using traits_type = meta::bind_traits<function_type>;
17608
17609 static int real_call(lua_State* L)
17610#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
17611 // MSVC is broken, what a surprise...
17612#else
17613 noexcept(traits_type::is_noexcept)
17614#endif
17615 {
17616 auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
17617 function_type* fx = udata.first;
17618 return call_detail::call_wrapped<void, true, false>(L, fx);
17619 }
17620
17621 static int call(lua_State* L) {
17622 int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
17623 if (is_yielding) {
17624 return lua_yield(L, nr);
17625 }
17626 else {
17627 return nr;
17628 }
17629 }
17630
17631 int operator()(lua_State* L) {
17632 return call(L);
17633 }
17634 };
17635
17636 template <typename T, typename Function, bool is_yielding>
17637 struct upvalue_member_function {
17638 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
17639 typedef lua_bind_traits<function_type> traits_type;
17640
17641 static int real_call(lua_State* L)
17642#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
17643 // MSVC is broken, what a surprise...
17644#else
17645 noexcept(traits_type::is_noexcept)
17646#endif
17647 {
17648 // Layout:
17649 // idx 1...n: verbatim data of member function pointer
17650 // idx n + 1: is the object's void pointer
17651 // We don't need to store the size, because the other side is templated
17652 // with the same member function pointer type
17653 function_type& memfx = stack::get<user<function_type>>(L, upvalue_index(2));
17654 auto& item = *static_cast<T*>(stack::get<void*>(L, upvalue_index(3)));
17655 return call_detail::call_wrapped<T, true, false, -1>(L, memfx, item);
17656 }
17657
17658 static int call(lua_State* L)
17659#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
17660 // MSVC is broken, what a surprise...
17661#else
17662 noexcept(traits_type::is_noexcept)
17663#endif
17664 {
17665 int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
17666 if (is_yielding) {
17667 return lua_yield(L, nr);
17668 }
17669 else {
17670 return nr;
17671 }
17672 }
17673
17674 int operator()(lua_State* L) {
17675 return call(L);
17676 }
17677 };
17678
17679 template <typename T, typename Function, bool is_yielding>
17680 struct upvalue_member_variable {
17681 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
17682 typedef lua_bind_traits<function_type> traits_type;
17683
17684 static int real_call(lua_State* L)
17685#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
17686 // MSVC is broken, what a surprise...
17687#else
17688 noexcept(traits_type::is_noexcept)
17689#endif
17690 {
17691 // Layout:
17692 // idx 1...n: verbatim data of member variable pointer
17693 // idx n + 1: is the object's void pointer
17694 // We don't need to store the size, because the other side is templated
17695 // with the same member function pointer type
17696 auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
17697 auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
17698 auto& mem = *objdata.first;
17699 function_type& var = memberdata.first;
17700 switch (lua_gettop(L)) {
17701 case 0:
17702 return call_detail::call_wrapped<T, true, false, -1>(L, var, mem);
17703 case 1:
17704 return call_detail::call_wrapped<T, false, false, -1>(L, var, mem);
17705 default:
17706 return luaL_error(L, "sol: incorrect number of arguments to member variable function");
17707 }
17708 }
17709
17710 static int call(lua_State* L)
17711#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
17712 // MSVC is broken, what a surprise...
17713#else
17714 noexcept(traits_type::is_noexcept)
17715#endif
17716 {
17717 int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
17718 if (is_yielding) {
17719 return lua_yield(L, nr);
17720 }
17721 else {
17722 return nr;
17723 }
17724 }
17725
17726 int operator()(lua_State* L) {
17727 return call(L);
17728 }
17729 };
17730
17731 template <typename T, typename Function, bool is_yielding>
17732 struct upvalue_member_variable<T, readonly_wrapper<Function>, is_yielding> {
17733 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
17734 typedef lua_bind_traits<function_type> traits_type;
17735
17736 static int real_call(lua_State* L)
17737#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
17738 // MSVC is broken, what a surprise...
17739#else
17740 noexcept(traits_type::is_noexcept)
17741#endif
17742 {
17743 // Layout:
17744 // idx 1...n: verbatim data of member variable pointer
17745 // idx n + 1: is the object's void pointer
17746 // We don't need to store the size, because the other side is templated
17747 // with the same member function pointer type
17748 auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
17749 auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
17750 auto& mem = *objdata.first;
17751 function_type& var = memberdata.first;
17752 switch (lua_gettop(L)) {
17753 case 0:
17754 return call_detail::call_wrapped<T, true, false, -1>(L, var, mem);
17755 default:
17756 return luaL_error(L, "sol: incorrect number of arguments to member variable function");
17757 }
17758 }
17759
17760 static int call(lua_State* L)
17761#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
17762 // MSVC is broken, what a surprise...
17763#else
17764 noexcept(traits_type::is_noexcept)
17765#endif
17766 {
17767 int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
17768 if (is_yielding) {
17769 return lua_yield(L, nr);
17770 }
17771 else {
17772 return nr;
17773 }
17774 }
17775
17776 int operator()(lua_State* L) {
17777 return call(L);
17778 }
17779 };
17780
17781 template <typename T, typename Function, bool is_yielding>
17782 struct upvalue_this_member_function {
17783 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
17784 typedef lua_bind_traits<function_type> traits_type;
17785
17786 static int real_call(lua_State* L)
17787#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
17788 // MSVC is broken, what a surprise...
17789#else
17790 noexcept(traits_type::is_noexcept)
17791#endif
17792 {
17793 // Layout:
17794 // idx 1...n: verbatim data of member variable pointer
17795 function_type& memfx = stack::get<user<function_type>>(L, upvalue_index(2));
17796 return call_detail::call_wrapped<T, false, false>(L, memfx);
17797 }
17798
17799 static int call(lua_State* L)
17800#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
17801 // MSVC is broken, what a surprise...
17802#else
17803 noexcept(traits_type::is_noexcept)
17804#endif
17805 {
17806 int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
17807 if (is_yielding) {
17808 return lua_yield(L, nr);
17809 }
17810 else {
17811 return nr;
17812 }
17813 }
17814
17815 int operator()(lua_State* L) {
17816 return call(L);
17817 }
17818 };
17819
17820 template <typename T, typename Function, bool is_yielding>
17821 struct upvalue_this_member_variable {
17822 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
17823
17824 static int real_call(lua_State* L) noexcept(false) {
17825 // Layout:
17826 // idx 1...n: verbatim data of member variable pointer
17827 auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
17828 function_type& var = memberdata.first;
17829 switch (lua_gettop(L)) {
17830 case 1:
17831 return call_detail::call_wrapped<T, true, false>(L, var);
17832 case 2:
17833 return call_detail::call_wrapped<T, false, false>(L, var);
17834 default:
17835 return luaL_error(L, "sol: incorrect number of arguments to member variable function");
17836 }
17837 }
17838
17839 static int call(lua_State* L) {
17840 int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
17841 if (is_yielding) {
17842 return lua_yield(L, nr);
17843 }
17844 else {
17845 return nr;
17846 }
17847 }
17848
17849 int operator()(lua_State* L) {
17850 return call(L);
17851 }
17852 };
17853
17854 template <typename T, typename Function, bool is_yielding>
17855 struct upvalue_this_member_variable<T, readonly_wrapper<Function>, is_yielding> {
17856 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
17857 typedef lua_bind_traits<function_type> traits_type;
17858
17859 static int real_call(lua_State* L) noexcept(false) {
17860 // Layout:
17861 // idx 1...n: verbatim data of member variable pointer
17862 auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
17863 function_type& var = memberdata.first;
17864 switch (lua_gettop(L)) {
17865 case 1:
17866 return call_detail::call_wrapped<T, true, false>(L, var);
17867 default:
17868 return luaL_error(L, "sol: incorrect number of arguments to member variable function");
17869 }
17870 }
17871
17872 static int call(lua_State* L) {
17873 int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
17874 if (is_yielding) {
17875 return lua_yield(L, nr);
17876 }
17877 else {
17878 return nr;
17879 }
17880 }
17881
17882 int operator()(lua_State* L) {
17883 return call(L);
17884 }
17885 };
17886}} // namespace sol::function_detail
17887
17888// end of sol/function_types_stateless.hpp
17889
17890// beginning of sol/function_types_stateful.hpp
17891
17892namespace sol {
17893namespace function_detail {
17894 template <typename Func, bool is_yielding, bool no_trampoline>
17895 struct functor_function {
17896 typedef std::decay_t<meta::unwrap_unqualified_t<Func>> function_type;
17897 function_type fx;
17898
17899 template <typename... Args>
17900 functor_function(function_type f, Args&&... args)
17901 : fx(std::move(f), std::forward<Args>(args)...) {
17902 }
17903
17904 int call(lua_State* L) {
17905 int nr = call_detail::call_wrapped<void, true, false>(L, fx);
17906 if (is_yielding) {
17907 return lua_yield(L, nr);
17908 }
17909 else {
17910 return nr;
17911 }
17912 }
17913
17914 int operator()(lua_State* L) {
17915 if (!no_trampoline) {
17916 auto f = [&](lua_State*) -> int { return this->call(L); };
17917 return detail::trampoline(L, f);
17918 }
17919 else {
17920 return call(L);
17921 }
17922 }
17923 };
17924
17925 template <typename T, typename Function, bool is_yielding>
17926 struct member_function {
17927 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
17928 typedef meta::function_return_t<function_type> return_type;
17929 typedef meta::function_args_t<function_type> args_lists;
17930 function_type invocation;
17931 T member;
17932
17933 template <typename... Args>
17934 member_function(function_type f, Args&&... args)
17935 : invocation(std::move(f)), member(std::forward<Args>(args)...) {
17936 }
17937
17938 int call(lua_State* L) {
17939 int nr = call_detail::call_wrapped<T, true, false, -1>(L, invocation, detail::unwrap(detail::deref(member)));
17940 if (is_yielding) {
17941 return lua_yield(L, nr);
17942 }
17943 else {
17944 return nr;
17945 }
17946 }
17947
17948 int operator()(lua_State* L) {
17949 auto f = [&](lua_State*) -> int { return this->call(L); };
17950 return detail::trampoline(L, f);
17951 }
17952 };
17953
17954 template <typename T, typename Function, bool is_yielding>
17955 struct member_variable {
17956 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
17957 typedef typename meta::bind_traits<function_type>::return_type return_type;
17958 typedef typename meta::bind_traits<function_type>::args_list args_lists;
17959 function_type var;
17960 T member;
17961 typedef std::add_lvalue_reference_t<meta::unwrapped_t<std::remove_reference_t<decltype(detail::deref(member))>>> M;
17962
17963 template <typename... Args>
17964 member_variable(function_type v, Args&&... args)
17965 : var(std::move(v)), member(std::forward<Args>(args)...) {
17966 }
17967
17968 int call(lua_State* L) {
17969 int nr;
17970 {
17971 M mem = detail::unwrap(detail::deref(member));
17972 switch (lua_gettop(L)) {
17973 case 0:
17974 nr = call_detail::call_wrapped<T, true, false, -1>(L, var, mem);
17975 break;
17976 case 1:
17977 nr = call_detail::call_wrapped<T, false, false, -1>(L, var, mem);
17978 break;
17979 default:
17980 nr = luaL_error(L, "sol: incorrect number of arguments to member variable function");
17981 break;
17982 }
17983 }
17984 if (is_yielding) {
17985 return lua_yield(L, nr);
17986 }
17987 else {
17988 return nr;
17989 }
17990 }
17991
17992 int operator()(lua_State* L) {
17993 auto f = [&](lua_State*) -> int { return this->call(L); };
17994 return detail::trampoline(L, f);
17995 }
17996 };
17997}
17998} // namespace sol::function_detail
17999
18000// end of sol/function_types_stateful.hpp
18001
18002// beginning of sol/function_types_overloaded.hpp
18003
18004namespace sol {
18005namespace function_detail {
18006 template <int start_skew, typename... Functions>
18007 struct overloaded_function {
18008 typedef std::tuple<Functions...> overload_list;
18009 typedef std::make_index_sequence<sizeof...(Functions)> indices;
18010 overload_list overloads;
18011
18012 overloaded_function(overload_list set)
18013 : overloads(std::move(set)) {
18014 }
18015
18016 overloaded_function(Functions... fxs)
18017 : overloads(fxs...) {
18018 }
18019
18020 template <typename Fx, std::size_t I, typename... R, typename... Args>
18021 static int call(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, overload_list& ol) {
18022 auto& func = std::get<I>(ol);
18023 int nr = call_detail::call_wrapped<void, true, false, start_skew>(L, func);
18024 return nr;
18025 }
18026
18027 int operator()(lua_State* L) {
18028 auto mfx = [](auto&&... args) { return call(std::forward<decltype(args)>(args)...); };
18029 return call_detail::overload_match<Functions...>(mfx, L, 1 + start_skew, overloads);
18030 }
18031 };
18032}
18033} // namespace sol::function_detail
18034
18035// end of sol/function_types_overloaded.hpp
18036
18037// beginning of sol/resolve.hpp
18038
18039namespace sol {
18040
18041#ifndef __clang__
18042 // constexpr is fine for not-clang
18043
18044 namespace detail {
18045 template <typename R, typename... Args, typename F, typename = std::invoke_result_t<meta::unqualified_t<F>, Args...>>
18046 inline constexpr auto resolve_i(types<R(Args...)>, F &&) -> R (meta::unqualified_t<F>::*)(Args...) {
18047 using Sig = R(Args...);
18048 typedef meta::unqualified_t<F> Fu;
18049 return static_cast<Sig Fu::*>(&Fu::operator());
18050 }
18051
18052 template <typename F, typename U = meta::unqualified_t<F>>
18053 inline constexpr auto resolve_f(std::true_type, F&& f)
18054 -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) {
18055 return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f));
18056 }
18057
18058 template <typename F>
18059 inline constexpr void resolve_f(std::false_type, F&&) {
18060 static_assert(
18061 meta::has_deducible_signature<F>::value, "Cannot use no-template-parameter call with an overloaded functor: specify the signature");
18062 }
18063
18064 template <typename F, typename U = meta::unqualified_t<F>>
18065 inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) {
18066 return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f));
18067 }
18068
18069 template <typename... Args, typename F, typename R = std::invoke_result_t<F&, Args...>>
18070 inline constexpr auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) {
18071 return resolve_i(types<R(Args...)>(), std::forward<F>(f));
18072 }
18073
18074 template <typename Sig, typename C>
18075 inline constexpr Sig C::*resolve_v(std::false_type, Sig C::*mem_func_ptr) {
18076 return mem_func_ptr;
18077 }
18078
18079 template <typename Sig, typename C>
18080 inline constexpr Sig C::*resolve_v(std::true_type, Sig C::*mem_variable_ptr) {
18081 return mem_variable_ptr;
18082 }
18083 } // namespace detail
18084
18085 template <typename... Args, typename R>
18086 inline constexpr auto resolve(R fun_ptr(Args...)) -> R (*)(Args...) {
18087 return fun_ptr;
18088 }
18089
18090 template <typename Sig>
18091 inline constexpr Sig* resolve(Sig* fun_ptr) {
18092 return fun_ptr;
18093 }
18094
18095 template <typename... Args, typename R, typename C>
18096 inline constexpr auto resolve(R (C::*mem_ptr)(Args...)) -> R (C::*)(Args...) {
18097 return mem_ptr;
18098 }
18099
18100 template <typename Sig, typename C>
18101 inline constexpr Sig C::*resolve(Sig C::*mem_ptr) {
18102 return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr);
18103 }
18104
18105 template <typename... Sig, typename F, meta::disable<std::is_function<meta::unqualified_t<F>>> = meta::enabler>
18106 inline constexpr auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) {
18107 return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
18108 }
18109#else
18110
18111 // Clang has distinct problems with constexpr arguments,
18112 // so don't use the constexpr versions inside of clang.
18113
18114 namespace detail {
18115 template <typename R, typename... Args, typename F, typename = std::invoke_result_t<meta::unqualified_t<F>, Args...>>
18116 inline auto resolve_i(types<R(Args...)>, F &&) -> R (meta::unqualified_t<F>::*)(Args...) {
18117 using Sig = R(Args...);
18118 typedef meta::unqualified_t<F> Fu;
18119 return static_cast<Sig Fu::*>(&Fu::operator());
18120 }
18121
18122 template <typename F, typename U = meta::unqualified_t<F>>
18123 inline auto resolve_f(std::true_type, F&& f)
18124 -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) {
18125 return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f));
18126 }
18127
18128 template <typename F>
18129 inline void resolve_f(std::false_type, F&&) {
18130 static_assert(
18131 meta::has_deducible_signature<F>::value, "Cannot use no-template-parameter call with an overloaded functor: specify the signature");
18132 }
18133
18134 template <typename F, typename U = meta::unqualified_t<F>>
18135 inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) {
18136 return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f));
18137 }
18138
18139 template <typename... Args, typename F, typename R = std::invoke_result_t<F&, Args...>>
18140 inline auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) {
18141 return resolve_i(types<R(Args...)>(), std::forward<F>(f));
18142 }
18143
18144 template <typename Sig, typename C>
18145 inline Sig C::*resolve_v(std::false_type, Sig C::*mem_func_ptr) {
18146 return mem_func_ptr;
18147 }
18148
18149 template <typename Sig, typename C>
18150 inline Sig C::*resolve_v(std::true_type, Sig C::*mem_variable_ptr) {
18151 return mem_variable_ptr;
18152 }
18153 } // namespace detail
18154
18155 template <typename... Args, typename R>
18156 inline auto resolve(R fun_ptr(Args...)) -> R (*)(Args...) {
18157 return fun_ptr;
18158 }
18159
18160 template <typename Sig>
18161 inline Sig* resolve(Sig* fun_ptr) {
18162 return fun_ptr;
18163 }
18164
18165 template <typename... Args, typename R, typename C>
18166 inline auto resolve(R (C::*mem_ptr)(Args...)) -> R (C::*)(Args...) {
18167 return mem_ptr;
18168 }
18169
18170 template <typename Sig, typename C>
18171 inline Sig C::*resolve(Sig C::*mem_ptr) {
18172 return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr);
18173 }
18174
18175 template <typename... Sig, typename F>
18176 inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) {
18177 return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
18178 }
18179
18180#endif
18181
18182} // namespace sol
18183
18184// end of sol/resolve.hpp
18185
18186namespace sol {
18187 namespace function_detail {
18188 template <typename T>
18189 struct class_indicator {
18190 using type = T;
18191 };
18192
18193 struct call_indicator { };
18194
18195 template <bool yielding>
18196 int lua_c_wrapper(lua_State* L) {
18197 lua_CFunction cf = lua_tocfunction(L, lua_upvalueindex(2));
18198 int nr = cf(L);
18199 if constexpr (yielding) {
18200 return lua_yield(L, nr);
18201 }
18202 else {
18203 return nr;
18204 }
18205 }
18206
18207 template <bool yielding>
18208 int lua_c_noexcept_wrapper(lua_State* L) noexcept {
18209 detail::lua_CFunction_noexcept cf = reinterpret_cast<detail::lua_CFunction_noexcept>(lua_tocfunction(L, lua_upvalueindex(2)));
18210 int nr = cf(L);
18211 if constexpr (yielding) {
18212 return lua_yield(L, nr);
18213 }
18214 else {
18215 return nr;
18216 }
18217 }
18218
18219 struct c_function_invocation { };
18220
18221 template <bool is_yielding, typename Fx, typename... Args>
18222 void select(lua_State* L, Fx&& fx, Args&&... args);
18223
18224 template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args>
18225 void select_set_fx(lua_State* L, Args&&... args) {
18226 lua_CFunction freefunc = no_trampoline ? detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>
18227 : function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>;
18228
18229 int upvalues = 0;
18230 upvalues += stack::push(L, nullptr);
18231 upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...);
18232 stack::push(L, c_closure(freefunc, upvalues));
18233 }
18234
18235 template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args>
18236 void select_convertible(types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
18237 using dFx = std::decay_t<meta::unwrap_unqualified_t<Fx>>;
18238 using fx_ptr_t = R (*)(A...);
18239 constexpr bool is_convertible = std::is_convertible_v<dFx, fx_ptr_t>;
18240 if constexpr (is_convertible) {
18241 fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
18242 select<is_yielding>(L, std::move(fxptr), std::forward<Args>(args)...);
18243 }
18244 else {
18245 using F = function_detail::functor_function<dFx, false, true>;
18246 select_set_fx<is_yielding, false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18247 }
18248 }
18249
18250 template <bool is_yielding, typename Fx, typename... Args>
18251 void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
18252 typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig;
18253 select_convertible<is_yielding>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18254 }
18255
18256 template <bool is_yielding, typename Fx, typename... Args>
18257 void select_member_variable(lua_State* L, Fx&& fx, Args&&... args) {
18258 using uFx = meta::unqualified_t<Fx>;
18259 if constexpr (sizeof...(Args) < 1) {
18260 using C = typename meta::bind_traits<uFx>::object_type;
18261 lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx, is_yielding>::call;
18262
18263 int upvalues = 0;
18264 upvalues += stack::push(L, nullptr);
18265 upvalues += stack::stack_detail::push_as_upvalues(L, fx);
18266 stack::push(L, c_closure(freefunc, upvalues));
18267 }
18268 else if constexpr (sizeof...(Args) < 2) {
18269 using Tu = typename meta::meta_detail::unqualified_non_alias<Args...>::type;
18270 constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
18271 if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
18272 lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<typename Tu::type, Fx, is_yielding>::call;
18273
18274 int upvalues = 0;
18275 upvalues += stack::push(L, nullptr);
18276 upvalues += stack::stack_detail::push_as_upvalues(L, fx);
18277 stack::push(L, c_closure(freefunc, upvalues));
18278 }
18279 else if constexpr (is_reference) {
18280 typedef std::decay_t<Fx> dFx;
18281 dFx memfxptr(std::forward<Fx>(fx));
18282 auto userptr = detail::ptr(std::forward<Args>(args)...);
18283 lua_CFunction freefunc
18284 = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call;
18285
18286 int upvalues = 0;
18287 upvalues += stack::push(L, nullptr);
18288 upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr);
18289 upvalues += stack::push(L, static_cast<void const*>(userptr));
18290 stack::push(L, c_closure(freefunc, upvalues));
18291 }
18292 else {
18293 using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
18294 using F = function_detail::member_variable<Tu, clean_fx, is_yielding>;
18295 select_set_fx<false, false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18296 }
18297 }
18298 else {
18299 using C = typename meta::bind_traits<uFx>::object_type;
18300 using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
18301 using F = function_detail::member_variable<C, clean_fx, is_yielding>;
18302 select_set_fx<false, false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18303 }
18304 }
18305
18306 template <bool is_yielding, typename Fx, typename T, typename... Args>
18307 void select_member_function_with(lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
18308 using dFx = std::decay_t<Fx>;
18309 using Tu = meta::unqualified_t<T>;
18310 if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
18311 (void)obj;
18312 using C = typename Tu::type;
18313 lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
18314
18315 int upvalues = 0;
18316 upvalues += stack::push(L, nullptr);
18317 upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18318 stack::push(L, c_closure(freefunc, upvalues));
18319 }
18320 else {
18321 constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
18322 if constexpr (is_reference) {
18323 auto userptr = detail::ptr(std::forward<T>(obj));
18324 lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, dFx, is_yielding>::call;
18325
18326 int upvalues = 0;
18327 upvalues += stack::push(L, nullptr);
18328 upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18329 upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
18330 stack::push(L, c_closure(freefunc, upvalues));
18331 }
18332 else {
18333 using F = function_detail::member_function<Tu, dFx, is_yielding>;
18334 select_set_fx<false, false, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
18335 }
18336 }
18337 }
18338
18339 template <bool is_yielding, typename Fx, typename... Args>
18340 void select_member_function(lua_State* L, Fx&& fx, Args&&... args) {
18341 using dFx = std::decay_t<Fx>;
18342 if constexpr (sizeof...(Args) < 1) {
18343 using C = typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type;
18344 lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx, is_yielding>::call;
18345
18346 int upvalues = 0;
18347 upvalues += stack::push(L, nullptr);
18348 upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx));
18349 stack::push(L, c_closure(freefunc, upvalues));
18350 }
18351 else {
18352 select_member_function_with<is_yielding>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18353 }
18354 }
18355
18356 template <bool is_yielding, typename Fx, typename... Args>
18357 void select(lua_State* L, Fx&& fx, Args&&... args) {
18358 using uFx = meta::unqualified_t<Fx>;
18359 if constexpr (is_lua_reference_v<uFx>) {
18360 // TODO: hoist into lambda in this case for yielding???
18361 stack::push(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18362 }
18363 else if constexpr (is_lua_c_function_v<uFx>) {
18364 int upvalues = 0;
18365 upvalues += stack::push(L, nullptr);
18366 upvalues += stack::push(L, std::forward<Fx>(fx));
18367#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
18368 if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) {
18369 detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<is_yielding>;
18370 lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), 2);
18371 }
18372 else {
18373 lua_CFunction cf = &lua_c_wrapper<is_yielding>;
18374 lua_pushcclosure(L, cf, 2);
18375 }
18376#else
18377 lua_CFunction cf = &function_detail::lua_c_wrapper<is_yielding>;
18378 lua_pushcclosure(L, cf, 2);
18379#endif
18380 }
18381 else if constexpr (std::is_function_v<std::remove_pointer_t<uFx>>) {
18382 std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
18383 lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx, is_yielding>::call;
18384
18385 int upvalues = 0;
18386 upvalues += stack::push(L, nullptr);
18387 upvalues += stack::stack_detail::push_as_upvalues(L, target);
18388 stack::push(L, c_closure(freefunc, upvalues));
18389 }
18390 else if constexpr (std::is_member_function_pointer_v<uFx>) {
18391 select_member_function<is_yielding>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18392 }
18393 else if constexpr (meta::is_member_object_v<uFx>) {
18394 select_member_variable<is_yielding>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18395 }
18396 else {
18397 select_convertible<is_yielding>(types<>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18398 }
18399 }
18400 } // namespace function_detail
18401
18402 namespace stack {
18403 template <typename... Sigs>
18404 struct unqualified_pusher<function_sig<Sigs...>> {
18405 template <bool is_yielding, typename Arg0, typename... Args>
18406 static int push(lua_State* L, Arg0&& arg0, Args&&... args) {
18407 if constexpr (meta::is_specialization_of_v<meta::unqualified_t<Arg0>, std::function>) {
18408 if constexpr (is_yielding) {
18409 return stack::push<meta::unqualified_t<Arg0>>(L, detail::yield_tag, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
18410 }
18411 else {
18412 return stack::push(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
18413 }
18414 }
18415 else {
18416 function_detail::select<is_yielding>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
18417 return 1;
18418 }
18419 }
18420
18421 template <typename Arg0, typename... Args>
18422 static int push(lua_State* L, Arg0&& arg0, Args&&... args) {
18423 if constexpr (std::is_same_v<meta::unqualified_t<Arg0>, detail::yield_tag_t>) {
18424 push<true>(L, std::forward<Args>(args)...);
18425 }
18426 else if constexpr (meta::is_specialization_of_v<meta::unqualified_t<Arg0>, yielding_t>) {
18427 push<true>(L, std::forward<Arg0>(arg0).func, std::forward<Args>(args)...);
18428 }
18429 else {
18430 push<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
18431 }
18432 return 1;
18433 }
18434 };
18435
18436 template <typename T>
18437 struct unqualified_pusher<yielding_t<T>> {
18438 template <typename... Args>
18439 static int push(lua_State* L, const yielding_t<T>& f, Args&&... args) {
18440 if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::function>) {
18441 return stack::push<T>(L, detail::yield_tag, f.func, std::forward<Args>(args)...);
18442 }
18443 else {
18444 function_detail::select<true>(L, f.func, std::forward<Args>(args)...);
18445 return 1;
18446 }
18447 }
18448
18449 template <typename... Args>
18450 static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) {
18451 if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::function>) {
18452 return stack::push<T>(L, detail::yield_tag, std::move(f.func), std::forward<Args>(args)...);
18453 }
18454 else {
18455 function_detail::select<true>(L, std::move(f.func), std::forward<Args>(args)...);
18456 return 1;
18457 }
18458 }
18459 };
18460
18461 template <typename T, typename... Args>
18462 struct unqualified_pusher<function_arguments<T, Args...>> {
18463 template <std::size_t... I, typename FP>
18464 static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
18465 return stack::push<T>(L, std::get<I>(std::forward<FP>(fp).arguments)...);
18466 }
18467
18468 static int push(lua_State* L, const function_arguments<T, Args...>& fp) {
18469 return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp);
18470 }
18471
18472 static int push(lua_State* L, function_arguments<T, Args...>&& fp) {
18473 return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp));
18474 }
18475 };
18476
18477 template <typename Signature>
18478 struct unqualified_pusher<std::function<Signature>> {
18479 static int push(lua_State* L, detail::yield_tag_t, const std::function<Signature>& fx) {
18480 if (fx) {
18481 function_detail::select<true>(L, fx);
18482 return 1;
18483 }
18484 return stack::push(L, lua_nil);
18485 }
18486
18487 static int push(lua_State* L, detail::yield_tag_t, std::function<Signature>&& fx) {
18488 if (fx) {
18489 function_detail::select<true>(L, std::move(fx));
18490 return 1;
18491 }
18492 return stack::push(L, lua_nil);
18493 }
18494
18495 static int push(lua_State* L, const std::function<Signature>& fx) {
18496 if (fx) {
18497 function_detail::select<false>(L, fx);
18498 return 1;
18499 }
18500 return stack::push(L, lua_nil);
18501 }
18502
18503 static int push(lua_State* L, std::function<Signature>&& fx) {
18504 if (fx) {
18505 function_detail::select<false>(L, std::move(fx));
18506 return 1;
18507 }
18508 return stack::push(L, lua_nil);
18509 }
18510 };
18511
18512 template <typename Signature>
18513 struct unqualified_pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
18514 template <typename... Args>
18515 static int push(lua_State* L, Args&&... args) {
18516 function_detail::select<false>(L, std::forward<Args>(args)...);
18517 return 1;
18518 }
18519 };
18520
18521 template <typename Signature>
18522 struct unqualified_pusher<Signature,
18523 std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>,
18524 meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
18525#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_)
18526 ,
18527 meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>,
18528 meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>>
18529#endif // noexcept function types
18530 >::value>> {
18531 template <typename F>
18532 static int push(lua_State* L, F&& f) {
18533 function_detail::select<false>(L, std::forward<F>(f));
18534 return 1;
18535 }
18536 };
18537
18538 template <typename... Functions>
18539 struct unqualified_pusher<overload_set<Functions...>> {
18540 static int push(lua_State* L, overload_set<Functions...>&& set) {
18541 using F = function_detail::overloaded_function<0, Functions...>;
18542 function_detail::select_set_fx<false, false, F>(L, std::move(set.functions));
18543 return 1;
18544 }
18545
18546 static int push(lua_State* L, const overload_set<Functions...>& set) {
18547 using F = function_detail::overloaded_function<0, Functions...>;
18548 function_detail::select_set_fx<false, false, F>(L, set.functions);
18549 return 1;
18550 }
18551 };
18552
18553 template <typename T>
18554 struct unqualified_pusher<protect_t<T>> {
18555 static int push(lua_State* L, protect_t<T>&& pw) {
18556 lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>;
18557 int upvalues = 0;
18558 upvalues += stack::push(L, nullptr);
18559 upvalues += stack::push<user<protect_t<T>>>(L, std::move(pw.value));
18560 return stack::push(L, c_closure(cf, upvalues));
18561 }
18562
18563 static int push(lua_State* L, const protect_t<T>& pw) {
18564 lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>;
18565 int upvalues = 0;
18566 upvalues += stack::push(L, nullptr);
18567 upvalues += stack::push<user<protect_t<T>>>(L, pw.value);
18568 return stack::push(L, c_closure(cf, upvalues));
18569 }
18570 };
18571
18572 template <typename F, typename G>
18573 struct unqualified_pusher<property_wrapper<F, G>> {
18574 static int push(lua_State* L, property_wrapper<F, G>&& pw) {
18575 if constexpr (std::is_void_v<F>) {
18576 return stack::push(L, std::move(pw.write()));
18577 }
18578 else if constexpr (std::is_void_v<G>) {
18579 return stack::push(L, std::move(pw.read()));
18580 }
18581 else {
18582 return stack::push(L, overload(std::move(pw.read()), std::move(pw.write())));
18583 }
18584 }
18585
18586 static int push(lua_State* L, const property_wrapper<F, G>& pw) {
18587 if constexpr (std::is_void_v<F>) {
18588 return stack::push(L, pw.write);
18589 }
18590 else if constexpr (std::is_void_v<G>) {
18591 return stack::push(L, pw.read);
18592 }
18593 else {
18594 return stack::push(L, overload(pw.read, pw.write));
18595 }
18596 }
18597 };
18598
18599 template <typename T>
18600 struct unqualified_pusher<var_wrapper<T>> {
18601 static int push(lua_State* L, var_wrapper<T>&& vw) {
18602 return stack::push(L, std::move(vw.value()));
18603 }
18604 static int push(lua_State* L, const var_wrapper<T>& vw) {
18605 return stack::push(L, vw.value());
18606 }
18607 };
18608
18609 template <typename... Functions>
18610 struct unqualified_pusher<factory_wrapper<Functions...>> {
18611 static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
18612 using F = function_detail::overloaded_function<0, Functions...>;
18613 function_detail::select_set_fx<false, false, F>(L, fw.functions);
18614 return 1;
18615 }
18616
18617 static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
18618 using F = function_detail::overloaded_function<0, Functions...>;
18619 function_detail::select_set_fx<false, false, F>(L, std::move(fw.functions));
18620 return 1;
18621 }
18622
18623 static int push(lua_State* L, const factory_wrapper<Functions...>& fw, function_detail::call_indicator) {
18624 using F = function_detail::overloaded_function<1, Functions...>;
18625 function_detail::select_set_fx<false, false, F>(L, fw.functions);
18626 return 1;
18627 }
18628
18629 static int push(lua_State* L, factory_wrapper<Functions...>&& fw, function_detail::call_indicator) {
18630 using F = function_detail::overloaded_function<1, Functions...>;
18631 function_detail::select_set_fx<false, false, F>(L, std::move(fw.functions));
18632 return 1;
18633 }
18634 };
18635
18636 template <>
18637 struct unqualified_pusher<no_construction> {
18638 static int push(lua_State* L, no_construction) {
18639 lua_CFunction cf = &function_detail::no_construction_error;
18640 return stack::push(L, cf);
18641 }
18642
18643 static int push(lua_State* L, no_construction c, function_detail::call_indicator) {
18644 return push(L, c);
18645 }
18646 };
18647
18648 template <typename T>
18649 struct unqualified_pusher<detail::tagged<T, no_construction>> {
18650 static int push(lua_State* L, detail::tagged<T, no_construction>) {
18651 lua_CFunction cf = &function_detail::no_construction_error;
18652 return stack::push(L, cf);
18653 }
18654
18655 static int push(lua_State* L, no_construction c, function_detail::call_indicator) {
18656 return push(L, c);
18657 }
18658 };
18659
18660 template <typename T, typename... Lists>
18661 struct unqualified_pusher<detail::tagged<T, constructor_list<Lists...>>> {
18662 static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) {
18663 lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls, true, Lists...>;
18664 return stack::push(L, cf);
18665 }
18666
18667 static int push(lua_State* L, constructor_list<Lists...>) {
18668 lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls, true, Lists...>;
18669 return stack::push(L, cf);
18670 }
18671 };
18672
18673 template <typename L0, typename... Lists>
18674 struct unqualified_pusher<constructor_list<L0, Lists...>> {
18675 typedef constructor_list<L0, Lists...> cl_t;
18676 static int push(lua_State* L, cl_t cl) {
18677 typedef typename meta::bind_traits<L0>::return_type T;
18678 return stack::push<detail::tagged<T, cl_t>>(L, cl);
18679 }
18680 };
18681
18682 template <typename T, typename... Fxs>
18683 struct unqualified_pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> {
18684 static int push(lua_State* L, detail::tagged<T, constructor_wrapper<Fxs...>>&& c) {
18685 return push(L, std::move(c.value()));
18686 }
18687
18688 static int push(lua_State* L, const detail::tagged<T, const constructor_wrapper<Fxs...>>& c) {
18689 return push(L, c.value());
18690 }
18691
18692 static int push(lua_State* L, constructor_wrapper<Fxs...>&& c) {
18693 lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>, 2>;
18694 int upvalues = 0;
18695 upvalues += stack::push(L, nullptr);
18696 upvalues += stack::push<user<constructor_wrapper<Fxs...>>>(L, std::move(c));
18697 return stack::push(L, c_closure(cf, upvalues));
18698 }
18699
18700 static int push(lua_State* L, const constructor_wrapper<Fxs...>& c) {
18701 lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>, 2>;
18702 int upvalues = 0;
18703 upvalues += stack::push(L, nullptr);
18704 upvalues += stack::push<user<constructor_wrapper<Fxs...>>>(L, c);
18705 return stack::push(L, c_closure(cf, upvalues));
18706 }
18707 };
18708
18709 template <typename F, typename... Fxs>
18710 struct unqualified_pusher<constructor_wrapper<F, Fxs...>> {
18711 static int push(lua_State* L, const constructor_wrapper<F, Fxs...>& c) {
18712 typedef typename meta::bind_traits<F>::template arg_at<0> arg0;
18713 typedef meta::unqualified_t<std::remove_pointer_t<arg0>> T;
18714 return stack::push<detail::tagged<T, constructor_wrapper<F, Fxs...>>>(L, c);
18715 }
18716
18717 static int push(lua_State* L, constructor_wrapper<F, Fxs...>&& c) {
18718 typedef typename meta::bind_traits<F>::template arg_at<0> arg0;
18719 typedef meta::unqualified_t<std::remove_pointer_t<arg0>> T;
18720 return stack::push<detail::tagged<T, constructor_wrapper<F, Fxs...>>>(L, std::move(c));
18721 }
18722 };
18723
18724 template <typename T>
18725 struct unqualified_pusher<detail::tagged<T, destructor_wrapper<void>>> {
18726 static int push(lua_State* L, destructor_wrapper<void>) {
18727 lua_CFunction cf = detail::usertype_alloc_destruct<T>;
18728 return stack::push(L, cf);
18729 }
18730 };
18731
18732 template <typename T, typename Fx>
18733 struct unqualified_pusher<detail::tagged<T, destructor_wrapper<Fx>>> {
18734 static int push(lua_State* L, destructor_wrapper<Fx>&& c) {
18735 lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>;
18736 int upvalues = 0;
18737 upvalues += stack::push(L, nullptr);
18738 upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c));
18739 return stack::push(L, c_closure(cf, upvalues));
18740 }
18741
18742 static int push(lua_State* L, const destructor_wrapper<Fx>& c) {
18743 lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>;
18744 int upvalues = 0;
18745 upvalues += stack::push(L, nullptr);
18746 upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c);
18747 return stack::push(L, c_closure(cf, upvalues));
18748 }
18749 };
18750
18751 template <typename Fx>
18752 struct unqualified_pusher<destructor_wrapper<Fx>> {
18753 static int push(lua_State* L, destructor_wrapper<Fx>&& c) {
18754 lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>;
18755 int upvalues = 0;
18756 upvalues += stack::push(L, nullptr);
18757 upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c));
18758 return stack::push(L, c_closure(cf, upvalues));
18759 }
18760
18761 static int push(lua_State* L, const destructor_wrapper<Fx>& c) {
18762 lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>;
18763 int upvalues = 0;
18764 upvalues += stack::push(L, nullptr);
18765 upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c);
18766 return stack::push(L, c_closure(cf, upvalues));
18767 }
18768 };
18769
18770 template <typename F, typename... Policies>
18771 struct unqualified_pusher<policy_wrapper<F, Policies...>> {
18772 using P = policy_wrapper<F, Policies...>;
18773
18774 static int push(lua_State* L, const P& p) {
18775 lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>;
18776 int upvalues = 0;
18777 upvalues += stack::push(L, nullptr);
18778 upvalues += stack::push<user<P>>(L, p);
18779 return stack::push(L, c_closure(cf, upvalues));
18780 }
18781
18782 static int push(lua_State* L, P&& p) {
18783 lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>;
18784 int upvalues = 0;
18785 upvalues += stack::push(L, nullptr);
18786 upvalues += stack::push<user<P>>(L, std::move(p));
18787 return stack::push(L, c_closure(cf, upvalues));
18788 }
18789 };
18790
18791 template <typename T, typename F, typename... Policies>
18792 struct unqualified_pusher<detail::tagged<T, policy_wrapper<F, Policies...>>> {
18793 using P = policy_wrapper<F, Policies...>;
18794 using Tagged = detail::tagged<T, P>;
18795
18796 static int push(lua_State* L, const Tagged& p) {
18797 lua_CFunction cf = call_detail::call_user<T, false, false, P, 2>;
18798 int upvalues = 0;
18799 upvalues += stack::push(L, nullptr);
18800 upvalues += stack::push<user<P>>(L, p.value());
18801 return stack::push(L, c_closure(cf, upvalues));
18802 }
18803
18804 static int push(lua_State* L, Tagged&& p) {
18805 lua_CFunction cf = call_detail::call_user<T, false, false, P, 2>;
18806 int upvalues = 0;
18807 upvalues += stack::push(L, nullptr);
18808 upvalues += stack::push<user<P>>(L, std::move(p.value()));
18809 return stack::push(L, c_closure(cf, upvalues));
18810 }
18811 };
18812
18813 template <typename T>
18814 struct unqualified_pusher<push_invoke_t<T>> {
18815 static int push(lua_State* L, push_invoke_t<T>&& pi) {
18816 if constexpr (std::is_invocable_v<std::add_rvalue_reference_t<T>, lua_State*>) {
18817 return stack::push(L, std::move(pi.value())(L));
18818 }
18819 else {
18820 return stack::push(L, std::move(pi.value())());
18821 }
18822 }
18823
18824 static int push(lua_State* L, const push_invoke_t<T>& pi) {
18825 if constexpr (std::is_invocable_v<const T, lua_State*>) {
18826 return stack::push(L, pi.value()(L));
18827 }
18828 else {
18829 return stack::push(L, pi.value()());
18830 }
18831 }
18832 };
18833
18834 namespace stack_detail {
18835 template <typename Function, typename Handler>
18836 bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept {
18837#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
18838 tracking.use(1);
18839 bool success = lua_iscfunction(L, index) == 1;
18840 if (success) {
18841 // there must be at LEAST 2 upvalues; otherwise, we didn't serialize it.
18842 const char* upvalue_name = lua_getupvalue(L, index, 2);
18843 lua_pop(L, 1);
18844 success = upvalue_name != nullptr;
18845 }
18846 if (!success) {
18847 // expected type, actual type
18848 handler(
18849 L, index, type::function, type_of(L, index), "type must be a Lua C Function gotten from a function pointer serialized by sol2");
18850 }
18851 return success;
18852#else
18853 return false;
18854#endif
18855 }
18856
18857 template <typename Function>
18858 Function* get_function_pointer(lua_State* L, int index, record& tracking) noexcept {
18859#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
18860 tracking.use(1);
18861 auto udata = stack::stack_detail::get_as_upvalues_using_function<Function*>(L, index);
18862 Function* fx = udata.first;
18863 return fx;
18864#else
18865 static_assert(meta::meta_detail::always_true<Function>::value,
18866#if SOL_IS_DEFAULT_OFF(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
18867 "You are attempting to retrieve a function pointer type. "
18868 "This is inherently unsafe in sol2. In order to do this, you must turn on the "
18869 "SOL_GET_FUNCTION_POINTER_UNSAFE configuration macro, as detailed in the documentation. "
18870 "Please be careful!"
18871#else
18872 "You are attempting to retrieve a function pointer type. "
18873 "You explicitly turned off the ability to do this by defining "
18874 "SOL_GET_FUNCTION_POINTER_UNSAFE or similar to be off. "
18875 "Please reconsider this!"
18876#endif
18877 );
18878 return nullptr;
18879#endif
18880 }
18881 } // namespace stack_detail
18882 } // namespace stack
18883} // namespace sol
18884
18885// end of sol/function_types.hpp
18886
18887// beginning of sol/dump_handler.hpp
18888
18889#include <cstdint>
18890#include <exception>
18891
18892namespace sol {
18893
18894 class dump_error : public error {
18895 private:
18896 int ec_;
18897
18898 public:
18899 dump_error(int error_code_) : error("dump returned non-zero error of " + std::to_string(error_code_)), ec_(error_code_) {
18900 }
18901
18902 int error_code() const {
18903 return ec_;
18904 }
18905 };
18906
18907 inline int dump_pass_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) {
18908 (void)L;
18909 (void)writer_function;
18910 (void)userdata;
18911 (void)strip;
18912 return result_code;
18913 }
18914
18915 inline int dump_panic_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) {
18916 (void)L;
18917 (void)writer_function;
18918 (void)userdata;
18919 (void)strip;
18920 return luaL_error(L, "a non-zero error code (%d) was returned by the lua_Writer for the dump function", result_code);
18921 }
18922
18923 inline int dump_throw_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) {
18924#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
18925 return dump_panic_on_error(L, result_code, writer_function, userdata, strip);
18926#else
18927 (void)L;
18928 (void)writer_function;
18929 (void)userdata;
18930 (void)strip;
18931 throw dump_error(result_code);
18932#endif // no exceptions stuff
18933 }
18934
18935} // namespace sol
18936
18937// end of sol/dump_handler.hpp
18938
18939#include <cstdint>
18940
18941namespace sol {
18942 template <typename ref_t, bool aligned = false>
18943 class basic_function : public basic_object<ref_t> {
18944 private:
18945 using base_t = basic_object<ref_t>;
18946
18947 void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const {
18948 lua_call(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount));
18949 }
18950
18951 template <std::size_t... I, typename... Ret>
18952 auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) const {
18953 luacall(n, lua_size<std::tuple<Ret...>>::value);
18954 return stack::pop<std::tuple<Ret...>>(lua_state());
18955 }
18956
18957 template <std::size_t I, typename Ret, meta::enable<meta::neg<std::is_void<Ret>>> = meta::enabler>
18958 Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) const {
18959 luacall(n, lua_size<Ret>::value);
18960 return stack::pop<Ret>(lua_state());
18961 }
18962
18963 template <std::size_t I>
18964 void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) const {
18965 luacall(n, 0);
18966 }
18967
18968 unsafe_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const {
18969 int stacksize = lua_gettop(lua_state());
18970 int firstreturn = (std::max)(1, stacksize - static_cast<int>(n));
18971 luacall(n, LUA_MULTRET);
18972 int poststacksize = lua_gettop(lua_state());
18973 int returncount = poststacksize - (firstreturn - 1);
18974 return unsafe_function_result(lua_state(), firstreturn, returncount);
18975 }
18976
18977 public:
18978 using base_t::lua_state;
18979
18980 basic_function() = default;
18981 template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_function>>, meta::neg<std::is_same<base_t, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
18982 basic_function(T&& r) noexcept
18983 : base_t(std::forward<T>(r)) {
18984#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
18985 if (!is_function<meta::unqualified_t<T>>::value) {
18986 auto pp = stack::push_pop(*this);
18987 constructor_handler handler{};
18988 stack::check<basic_function>(lua_state(), -1, handler);
18989 }
18990#endif // Safety
18991 }
18992 basic_function(const basic_function&) = default;
18993 basic_function& operator=(const basic_function&) = default;
18994 basic_function(basic_function&&) = default;
18995 basic_function& operator=(basic_function&&) = default;
18996 basic_function(const stack_reference& r)
18997 : basic_function(r.lua_state(), r.stack_index()) {
18998 }
18999 basic_function(stack_reference&& r)
19000 : basic_function(r.lua_state(), r.stack_index()) {
19001 }
19002 basic_function(lua_nil_t n)
19003 : base_t(n) {
19004 }
19005 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
19006 basic_function(lua_State* L, T&& r)
19007 : base_t(L, std::forward<T>(r)) {
19008#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
19009 auto pp = stack::push_pop(*this);
19010 constructor_handler handler{};
19011 stack::check<basic_function>(lua_state(), -1, handler);
19012#endif // Safety
19013 }
19014 basic_function(lua_State* L, int index = -1)
19015 : base_t(L, index) {
19016#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
19017 constructor_handler handler{};
19018 stack::check<basic_function>(L, index, handler);
19019#endif // Safety
19020 }
19021 basic_function(lua_State* L, ref_index index)
19022 : base_t(L, index) {
19023#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
19024 auto pp = stack::push_pop(*this);
19025 constructor_handler handler{};
19026 stack::check<basic_function>(lua_state(), -1, handler);
19027#endif // Safety
19028 }
19029
19030 template <typename Fx>
19031 int dump(lua_Writer writer, void* userdata, bool strip, Fx&& on_error) const {
19032 this->push();
19033 auto ppn = stack::push_popper_n<false>(this->lua_state(), 1);
19034 int r = lua_dump(this->lua_state(), writer, userdata, strip ? 1 : 0);
19035 if (r != 0) {
19036 return on_error(this->lua_state(), r, writer, userdata, strip);
19037 }
19038 return r;
19039 }
19040
19041 int dump(lua_Writer writer, void* userdata, bool strip = false) const {
19042 return dump(writer, userdata, strip, &dump_throw_on_error);
19043 }
19044
19045 template <typename Container = bytecode>
19046 Container dump() const {
19047 Container bc;
19048 (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, &dump_panic_on_error);
19049 return bc;
19050 }
19051
19052 template <typename Container = bytecode, typename Fx>
19053 Container dump(Fx&& on_error) const {
19054 Container bc;
19055 (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, std::forward<Fx>(on_error));
19056 return bc;
19057 }
19058
19059 template <typename... Args>
19060 unsafe_function_result operator()(Args&&... args) const {
19061 return call<>(std::forward<Args>(args)...);
19062 }
19063
19064 template <typename... Ret, typename... Args>
19065 decltype(auto) operator()(types<Ret...>, Args&&... args) const {
19066 return call<Ret...>(std::forward<Args>(args)...);
19067 }
19068
19069 template <typename... Ret, typename... Args>
19070 decltype(auto) call(Args&&... args) const {
19071 if (!aligned) {
19072 base_t::push();
19073 }
19074 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
19075 return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), static_cast<std::ptrdiff_t>(pushcount));
19076 }
19077 };
19078} // namespace sol
19079
19080// end of sol/unsafe_function.hpp
19081
19082// beginning of sol/protected_function.hpp
19083
19084// beginning of sol/protected_handler.hpp
19085
19086#include <cstdint>
19087
19088namespace sol {
19089 namespace detail {
19090 inline const char(&default_handler_name())[9]{
19091 static const char name[9] = "sol.\xF0\x9F\x94\xA9";
19092 return name;
19093 }
19094
19095 template <bool b, typename target_t = reference>
19096 struct protected_handler {
19097 typedef is_stack_based<target_t> is_stack;
19098 const target_t& target;
19099 int stackindex;
19100
19101 protected_handler(std::false_type, const target_t& target)
19102 : target(target), stackindex(0) {
19103 if (b) {
19104 stackindex = lua_gettop(target.lua_state()) + 1;
19105 target.push();
19106 }
19107 }
19108
19109 protected_handler(std::true_type, const target_t& target)
19110 : target(target), stackindex(0) {
19111 if (b) {
19112 stackindex = target.stack_index();
19113 }
19114 }
19115
19116 protected_handler(const target_t& target)
19117 : protected_handler(is_stack(), target) {
19118 }
19119
19120 bool valid() const noexcept {
19121 return b;
19122 }
19123
19124 ~protected_handler() {
19125 if constexpr (!is_stack::value) {
19126 if (stackindex != 0) {
19127 lua_remove(target.lua_state(), stackindex);
19128 }
19129 }
19130 }
19131 };
19132
19133 template <typename base_t, typename T>
19134 basic_function<base_t> force_cast(T& p) {
19135 return p;
19136 }
19137
19138 template <typename Reference, bool is_main_ref = false>
19139 static Reference get_default_handler(lua_State* L) {
19140 if (is_stack_based<Reference>::value || L == nullptr)
19141 return Reference(L, lua_nil);
19142 L = is_main_ref ? main_thread(L, L) : L;
19143 lua_getglobal(L, default_handler_name());
19144 auto pp = stack::pop_n(L, 1);
19145 return Reference(L, -1);
19146 }
19147
19148 template <typename T>
19149 static void set_default_handler(lua_State* L, const T& ref) {
19150 if (L == nullptr) {
19151 return;
19152 }
19153 if (!ref.valid()) {
19154#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
19155 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
19156#endif // make sure stack doesn't overflow
19157 lua_pushnil(L);
19158 lua_setglobal(L, default_handler_name());
19159 }
19160 else {
19161 ref.push(L);
19162 lua_setglobal(L, default_handler_name());
19163 }
19164 }
19165 } // namespace detail
19166} // namespace sol
19167
19168// end of sol/protected_handler.hpp
19169
19170#include <cstdint>
19171#include <algorithm>
19172
19173namespace sol {
19174
19175 namespace detail {
19176 template <bool b, typename handler_t>
19177 inline void handle_protected_exception(lua_State* L, optional<const std::exception&> maybe_ex, const char* error, detail::protected_handler<b, handler_t>& h) {
19178 h.stackindex = 0;
19179 if (b) {
19180 h.target.push();
19181 detail::call_exception_handler(L, maybe_ex, error);
19182 lua_call(L, 1, 1);
19183 }
19184 else {
19185 detail::call_exception_handler(L, maybe_ex, error);
19186 }
19187 }
19188 }
19189
19190 template <typename ref_t, bool aligned = false, typename handler_t = reference>
19191 class basic_protected_function : public basic_object<ref_t> {
19192 private:
19193 using base_t = basic_object<ref_t>;
19194
19195 public:
19196 using is_stack_handler = is_stack_based<handler_t>;
19197
19198 static handler_t get_default_handler(lua_State* L) {
19199 return detail::get_default_handler<handler_t, is_main_threaded<base_t>::value>(L);
19200 }
19201
19202 template <typename T>
19203 static void set_default_handler(const T& ref) {
19204 detail::set_default_handler(ref.lua_state(), ref);
19205 }
19206
19207 private:
19208 template <bool b>
19209 call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, detail::protected_handler<b, handler_t>& h) const {
19210 return static_cast<call_status>(lua_pcall(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex));
19211 }
19212
19213 template <std::size_t... I, bool b, typename... Ret>
19214 auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const {
19215 luacall(n, sizeof...(Ret), h);
19216 return stack::pop<std::tuple<Ret...>>(lua_state());
19217 }
19218
19219 template <std::size_t I, bool b, typename Ret>
19220 Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const {
19221 luacall(n, 1, h);
19222 return stack::pop<Ret>(lua_state());
19223 }
19224
19225 template <std::size_t I, bool b>
19226 void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const {
19227 luacall(n, 0, h);
19228 }
19229
19230 template <bool b>
19231 protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const {
19232 int stacksize = lua_gettop(lua_state());
19233 int poststacksize = stacksize;
19234 int firstreturn = 1;
19235 int returncount = 0;
19236 call_status code = call_status::ok;
19237#if !defined(SOL_NO_EXCEPTIONS) || !SOL_NO_EXCEPTIONS
19238#if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) || (defined(SOL_LUAJIT) && SOL_LUAJIT)
19239 try {
19240#endif // Safe Exception Propagation
19241#endif // No Exceptions
19242 firstreturn = (std::max)(1, static_cast<int>(stacksize - n - static_cast<int>(h.valid() && !is_stack_handler::value)));
19243 code = luacall(n, LUA_MULTRET, h);
19244 poststacksize = lua_gettop(lua_state()) - static_cast<int>(h.valid() && !is_stack_handler::value);
19245 returncount = poststacksize - (firstreturn - 1);
19246#ifndef SOL_NO_EXCEPTIONS
19247#if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) || (defined(SOL_LUAJIT) && SOL_LUAJIT)
19248 }
19249 // Handle C++ errors thrown from C++ functions bound inside of lua
19250 catch (const char* error) {
19251 detail::handle_protected_exception(lua_state(), optional<const std::exception&>(nullopt), error, h);
19252 firstreturn = lua_gettop(lua_state());
19253 return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
19254 }
19255 catch (const std::string& error) {
19256 detail::handle_protected_exception(lua_state(), optional<const std::exception&>(nullopt), error.c_str(), h);
19257 firstreturn = lua_gettop(lua_state());
19258 return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
19259 }
19260 catch (const std::exception& error) {
19261 detail::handle_protected_exception(lua_state(), optional<const std::exception&>(error), error.what(), h);
19262 firstreturn = lua_gettop(lua_state());
19263 return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
19264 }
19265#if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION)
19266 // LuaJIT cannot have the catchall when the safe propagation is on
19267 // but LuaJIT will swallow all C++ errors
19268 // if we don't at least catch std::exception ones
19269 catch (...) {
19270 detail::handle_protected_exception(lua_state(), optional<const std::exception&>(nullopt), detail::protected_function_error, h);
19271 firstreturn = lua_gettop(lua_state());
19272 return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
19273 }
19274#endif // LuaJIT
19275#else
19276 // do not handle exceptions: they can be propogated into C++ and keep all type information / rich information
19277#endif // Safe Exception Propagation
19278#endif // Exceptions vs. No Exceptions
19279 return protected_function_result(lua_state(), firstreturn, returncount, returncount, code);
19280 }
19281
19282 public:
19283 using base_t::lua_state;
19284
19285 handler_t error_handler;
19286
19287 basic_protected_function() = default;
19288 template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
19289 basic_protected_function(T&& r) noexcept
19290 : base_t(std::forward<T>(r)), error_handler(get_default_handler(r.lua_state())) {
19291#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
19292 if (!is_function<meta::unqualified_t<T>>::value) {
19293 auto pp = stack::push_pop(*this);
19294 constructor_handler handler{};
19295 stack::check<basic_protected_function>(lua_state(), -1, handler);
19296 }
19297#endif // Safety
19298 }
19299 basic_protected_function(const basic_protected_function&) = default;
19300 basic_protected_function& operator=(const basic_protected_function&) = default;
19301 basic_protected_function(basic_protected_function&&) = default;
19302 basic_protected_function& operator=(basic_protected_function&&) = default;
19303 basic_protected_function(const basic_function<base_t>& b)
19304 : basic_protected_function(b, get_default_handler(b.lua_state())) {
19305 }
19306 basic_protected_function(basic_function<base_t>&& b)
19307 : basic_protected_function(std::move(b), get_default_handler(b.lua_state())) {
19308 }
19309 basic_protected_function(const basic_function<base_t>& b, handler_t eh)
19310 : base_t(b), error_handler(std::move(eh)) {
19311 }
19312 basic_protected_function(basic_function<base_t>&& b, handler_t eh)
19313 : base_t(std::move(b)), error_handler(std::move(eh)) {
19314 }
19315 basic_protected_function(const stack_reference& r)
19316 : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {
19317 }
19318 basic_protected_function(stack_reference&& r)
19319 : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {
19320 }
19321 basic_protected_function(const stack_reference& r, handler_t eh)
19322 : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {
19323 }
19324 basic_protected_function(stack_reference&& r, handler_t eh)
19325 : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {
19326 }
19327
19328 template <typename Super>
19329 basic_protected_function(const proxy_base<Super>& p)
19330 : basic_protected_function(p, get_default_handler(p.lua_state())) {
19331 }
19332 template <typename Super>
19333 basic_protected_function(proxy_base<Super>&& p)
19334 : basic_protected_function(std::move(p), get_default_handler(p.lua_state())) {
19335 }
19336 template <typename Proxy, typename Handler, meta::enable<std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>, meta::neg<is_lua_index<meta::unqualified_t<Handler>>>> = meta::enabler>
19337 basic_protected_function(Proxy&& p, Handler&& eh)
19338 : basic_protected_function(detail::force_cast<base_t>(p), std::forward<Handler>(eh)) {
19339 }
19340
19341 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
19342 basic_protected_function(lua_State* L, T&& r)
19343 : basic_protected_function(L, std::forward<T>(r), get_default_handler(L)) {
19344 }
19345 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
19346 basic_protected_function(lua_State* L, T&& r, handler_t eh)
19347 : base_t(L, std::forward<T>(r)), error_handler(std::move(eh)) {
19348#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
19349 auto pp = stack::push_pop(*this);
19350 constructor_handler handler{};
19351 stack::check<basic_protected_function>(lua_state(), -1, handler);
19352#endif // Safety
19353 }
19354
19355 basic_protected_function(lua_nil_t n)
19356 : base_t(n), error_handler(n) {
19357 }
19358
19359 basic_protected_function(lua_State* L, int index = -1)
19360 : basic_protected_function(L, index, get_default_handler(L)) {
19361 }
19362 basic_protected_function(lua_State* L, int index, handler_t eh)
19363 : base_t(L, index), error_handler(std::move(eh)) {
19364#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
19365 constructor_handler handler{};
19366 stack::check<basic_protected_function>(L, index, handler);
19367#endif // Safety
19368 }
19369 basic_protected_function(lua_State* L, absolute_index index)
19370 : basic_protected_function(L, index, get_default_handler(L)) {
19371 }
19372 basic_protected_function(lua_State* L, absolute_index index, handler_t eh)
19373 : base_t(L, index), error_handler(std::move(eh)) {
19374#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
19375 constructor_handler handler{};
19376 stack::check<basic_protected_function>(L, index, handler);
19377#endif // Safety
19378 }
19379 basic_protected_function(lua_State* L, raw_index index)
19380 : basic_protected_function(L, index, get_default_handler(L)) {
19381 }
19382 basic_protected_function(lua_State* L, raw_index index, handler_t eh)
19383 : base_t(L, index), error_handler(std::move(eh)) {
19384#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
19385 constructor_handler handler{};
19386 stack::check<basic_protected_function>(L, index, handler);
19387#endif // Safety
19388 }
19389 basic_protected_function(lua_State* L, ref_index index)
19390 : basic_protected_function(L, index, get_default_handler(L)) {
19391 }
19392 basic_protected_function(lua_State* L, ref_index index, handler_t eh)
19393 : base_t(L, index), error_handler(std::move(eh)) {
19394#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
19395 auto pp = stack::push_pop(*this);
19396 constructor_handler handler{};
19397 stack::check<basic_protected_function>(lua_state(), -1, handler);
19398#endif // Safety
19399 }
19400
19401 template <typename Fx>
19402 int dump(lua_Writer writer, void* userdata, bool strip, Fx&& on_error) const {
19403 this->push();
19404 auto ppn = stack::push_popper_n<false>(this->lua_state(), 1);
19405 int r = lua_dump(this->lua_state(), writer, userdata, strip ? 1 : 0);
19406 if (r != 0) {
19407 return on_error(this->lua_state(), r, writer, userdata, strip);
19408 }
19409 return r;
19410 }
19411
19412 int dump(lua_Writer writer, void* userdata, bool strip = false) const {
19413 return dump(writer, userdata, strip, &dump_pass_on_error);
19414 }
19415
19416 template <typename Container = bytecode>
19417 Container dump() const {
19418 Container bc;
19419 (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, &dump_throw_on_error);
19420 return bc;
19421 }
19422
19423 template <typename Container = bytecode, typename Fx>
19424 Container dump(Fx&& on_error) const {
19425 Container bc;
19426 (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, std::forward<Fx>(on_error));
19427 return bc;
19428 }
19429
19430 template <typename... Args>
19431 protected_function_result operator()(Args&&... args) const {
19432 return call<>(std::forward<Args>(args)...);
19433 }
19434
19435 template <typename... Ret, typename... Args>
19436 decltype(auto) operator()(types<Ret...>, Args&&... args) const {
19437 return call<Ret...>(std::forward<Args>(args)...);
19438 }
19439
19440 template <typename... Ret, typename... Args>
19441 decltype(auto) call(Args&&... args) const {
19442 if constexpr (!aligned) {
19443 // we do not expect the function to already be on the stack: push it
19444 if (error_handler.valid()) {
19445 detail::protected_handler<true, handler_t> h(error_handler);
19446 base_t::push();
19447 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
19448 return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h);
19449 }
19450 else {
19451 detail::protected_handler<false, handler_t> h(error_handler);
19452 base_t::push();
19453 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
19454 return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h);
19455 }
19456 }
19457 else {
19458 // the function is already on the stack at the right location
19459 if (error_handler.valid()) {
19460 // the handler will be pushed onto the stack manually,
19461 // since it's not already on the stack this means we need to push our own
19462 // function on the stack too and swap things to be in-place
19463 if constexpr (!is_stack_handler::value) {
19464 // so, we need to remove the function at the top and then dump the handler out ourselves
19465 base_t::push();
19466 }
19467 detail::protected_handler<true, handler_t> h(error_handler);
19468 if constexpr (!is_stack_handler::value) {
19469 lua_replace(lua_state(), -3);
19470 h.stackindex = lua_absindex(lua_state(), -2);
19471 }
19472 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
19473 return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h);
19474 }
19475 else {
19476 detail::protected_handler<false, handler_t> h(error_handler);
19477 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
19478 return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h);
19479 }
19480 }
19481 }
19482 };
19483} // namespace sol
19484
19485// end of sol/protected_function.hpp
19486
19487#include <functional>
19488
19489namespace sol {
19490 template <typename... Ret, typename... Args>
19491 decltype(auto) stack_proxy::call(Args&&... args) {
19492 stack_function sf(this->lua_state(), this->stack_index());
19493 return sf.template call<Ret...>(std::forward<Args>(args)...);
19494 }
19495
19496 inline protected_function_result::protected_function_result(unsafe_function_result&& o) noexcept
19497 : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()), popcount(o.return_count()), err(o.status()) {
19498 // Must be manual, otherwise destructor will screw us
19499 // return count being 0 is enough to keep things clean
19500 // but we will be thorough
19501 o.abandon();
19502 }
19503
19504 inline protected_function_result& protected_function_result::operator=(unsafe_function_result&& o) noexcept {
19505 L = o.lua_state();
19506 index = o.stack_index();
19507 returncount = o.return_count();
19508 popcount = o.return_count();
19509 err = o.status();
19510 // Must be manual, otherwise destructor will screw us
19511 // return count being 0 is enough to keep things clean
19512 // but we will be thorough
19513 o.abandon();
19514 return *this;
19515 }
19516
19517 inline unsafe_function_result::unsafe_function_result(protected_function_result&& o) noexcept
19518 : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) {
19519 // Must be manual, otherwise destructor will screw us
19520 // return count being 0 is enough to keep things clean
19521 // but we will be thorough
19522 o.abandon();
19523 }
19524 inline unsafe_function_result& unsafe_function_result::operator=(protected_function_result&& o) noexcept {
19525 L = o.lua_state();
19526 index = o.stack_index();
19527 returncount = o.return_count();
19528 // Must be manual, otherwise destructor will screw us
19529 // return count being 0 is enough to keep things clean
19530 // but we will be thorough
19531 o.abandon();
19532 return *this;
19533 }
19534
19535 namespace detail {
19536 template <typename... R>
19537 struct std_shim {
19538 unsafe_function lua_func_;
19539
19540 std_shim(unsafe_function lua_func) : lua_func_(std::move(lua_func)) {
19541 }
19542
19543 template <typename... Args>
19544 meta::return_type_t<R...> operator()(Args&&... args) {
19545 return lua_func_.call<R...>(std::forward<Args>(args)...);
19546 }
19547 };
19548
19549 template <>
19550 struct std_shim<void> {
19551 unsafe_function lua_func_;
19552
19553 std_shim(unsafe_function lua_func) : lua_func_(std::move(lua_func)) {
19554 }
19555
19556 template <typename... Args>
19557 void operator()(Args&&... args) {
19558 lua_func_.call<void>(std::forward<Args>(args)...);
19559 }
19560 };
19561 } // namespace detail
19562
19563 namespace stack {
19564 template <typename Signature>
19565 struct unqualified_getter<std::function<Signature>> {
19566 typedef meta::bind_traits<Signature> fx_t;
19567 typedef typename fx_t::args_list args_lists;
19568 typedef meta::tuple_types<typename fx_t::return_type> return_types;
19569
19570 template <typename... R>
19571 static std::function<Signature> get_std_func(types<R...>, lua_State* L, int index) {
19572 detail::std_shim<R...> fx(unsafe_function(L, index));
19573 return fx;
19574 }
19575
19576 static std::function<Signature> get(lua_State* L, int index, record& tracking) {
19577 tracking.use(1);
19578 type t = type_of(L, index);
19579 if (t == type::none || t == type::lua_nil) {
19580 return nullptr;
19581 }
19582 return get_std_func(return_types(), L, index);
19583 }
19584 };
19585
19586 template <typename Allocator>
19587 struct unqualified_getter<basic_bytecode<Allocator>> {
19588 static basic_bytecode<Allocator> get(lua_State* L, int index, record& tracking) {
19589 tracking.use(1);
19590 stack_function sf(L, index);
19591 return sf.dump(&dump_panic_on_error);
19592 }
19593 };
19594 } // namespace stack
19595
19596} // namespace sol
19597
19598// end of sol/function.hpp
19599
19600// beginning of sol/usertype.hpp
19601
19602// beginning of sol/usertype_core.hpp
19603
19604// beginning of sol/deprecate.hpp
19605
19606#ifndef SOL_DEPRECATED
19607#ifdef _MSC_VER
19608#define SOL_DEPRECATED __declspec(deprecated)
19609#elif __GNUC__
19610#define SOL_DEPRECATED __attribute__((deprecated))
19611#else
19612#define SOL_DEPRECATED [[deprecated]]
19613#endif // compilers
19614#endif // SOL_DEPRECATED
19615
19616namespace sol {
19617namespace detail {
19618 template <typename T>
19619 struct SOL_DEPRECATED deprecate_type {
19620 using type = T;
19621 };
19622}
19623} // namespace sol::detail
19624
19625// end of sol/deprecate.hpp
19626
19627// beginning of sol/usertype_container_launch.hpp
19628
19629// beginning of sol/usertype_container.hpp
19630
19631namespace sol {
19632
19633 template <typename T>
19634 struct usertype_container;
19635
19636 namespace container_detail {
19637
19638 template <typename T>
19639 struct has_clear_test {
19640 private:
19641 template <typename C>
19642 static meta::sfinae_yes_t test(decltype(&C::clear));
19643 template <typename C>
19644 static meta::sfinae_no_t test(...);
19645
19646 public:
19647 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19648 };
19649
19650 template <typename T>
19651 struct has_empty_test {
19652 private:
19653 template <typename C>
19654 static meta::sfinae_yes_t test(decltype(&C::empty));
19655 template <typename C>
19656 static meta::sfinae_no_t test(...);
19657
19658 public:
19659 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19660 };
19661
19662 template <typename T>
19663 struct has_erase_after_test {
19664 private:
19665 template <typename C>
19666 static meta::sfinae_yes_t test(
19667 decltype(std::declval<C>().erase_after(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>()))*);
19668 template <typename C>
19669 static meta::sfinae_no_t test(...);
19670
19671 public:
19672 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19673 };
19674
19675 template <typename T, typename = void>
19676 struct has_find_test {
19677 private:
19678 template <typename C>
19679 static meta::sfinae_yes_t test(decltype(std::declval<C>().find(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
19680 template <typename C>
19681 static meta::sfinae_no_t test(...);
19682
19683 public:
19684 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19685 };
19686
19687 template <typename T>
19688 struct has_find_test<T, std::enable_if_t<meta::is_lookup<T>::value>> {
19689 private:
19690 template <typename C>
19691 static meta::sfinae_yes_t test(decltype(std::declval<C>().find(std::declval<std::add_rvalue_reference_t<typename C::key_type>>()))*);
19692 template <typename C>
19693 static meta::sfinae_no_t test(...);
19694
19695 public:
19696 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19697 };
19698
19699 template <typename T>
19700 struct has_erase_test {
19701 private:
19702 template <typename C>
19703 static meta::sfinae_yes_t test(decltype(std::declval<C>().erase(std::declval<typename C::iterator>()))*);
19704 template <typename C>
19705 static meta::sfinae_no_t test(...);
19706
19707 public:
19708 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19709 };
19710
19711 template <typename T>
19712 struct has_erase_key_test {
19713 private:
19714 template <typename C>
19715 static meta::sfinae_yes_t test(decltype(std::declval<C>().erase(std::declval<typename C::key_type>()))*);
19716 template <typename C>
19717 static meta::sfinae_no_t test(...);
19718
19719 public:
19720 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19721 };
19722
19723 template <typename T>
19724 struct has_traits_find_test {
19725 private:
19726 template <typename C>
19727 static meta::sfinae_yes_t test(decltype(&C::find));
19728 template <typename C>
19729 static meta::sfinae_no_t test(...);
19730
19731 public:
19732 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19733 };
19734
19735 template <typename T>
19736 struct has_traits_index_of_test {
19737 private:
19738 template <typename C>
19739 static meta::sfinae_yes_t test(decltype(&C::index_of));
19740 template <typename C>
19741 static meta::sfinae_no_t test(...);
19742
19743 public:
19744 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19745 };
19746
19747 template <typename T>
19748 struct has_traits_insert_test {
19749 private:
19750 template <typename C>
19751 static meta::sfinae_yes_t test(decltype(&C::insert));
19752 template <typename C>
19753 static meta::sfinae_no_t test(...);
19754
19755 public:
19756 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19757 };
19758
19759 template <typename T>
19760 struct has_traits_erase_test {
19761 private:
19762 template <typename C>
19763 static meta::sfinae_yes_t test(decltype(&C::erase));
19764 template <typename C>
19765 static meta::sfinae_no_t test(...);
19766
19767 public:
19768 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19769 };
19770
19771 template <typename T>
19772 struct has_traits_index_set_test {
19773 private:
19774 template <typename C>
19775 static meta::sfinae_yes_t test(decltype(&C::index_set));
19776 template <typename C>
19777 static meta::sfinae_no_t test(...);
19778
19779 public:
19780 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19781 };
19782
19783 template <typename T>
19784 struct has_traits_index_get_test {
19785 private:
19786 template <typename C>
19787 static meta::sfinae_yes_t test(decltype(&C::index_get));
19788 template <typename C>
19789 static meta::sfinae_no_t test(...);
19790
19791 public:
19792 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19793 };
19794
19795 template <typename T>
19796 struct has_traits_set_test {
19797 private:
19798 template <typename C>
19799 static meta::sfinae_yes_t test(decltype(&C::set));
19800 template <typename C>
19801 static meta::sfinae_no_t test(...);
19802
19803 public:
19804 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19805 };
19806
19807 template <typename T>
19808 struct has_traits_get_test {
19809 private:
19810 template <typename C>
19811 static meta::sfinae_yes_t test(decltype(&C::get));
19812 template <typename C>
19813 static meta::sfinae_no_t test(...);
19814
19815 public:
19816 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19817 };
19818
19819 template <typename T>
19820 struct has_traits_at_test {
19821 private:
19822 template <typename C>
19823 static meta::sfinae_yes_t test(decltype(&C::at));
19824 template <typename C>
19825 static meta::sfinae_no_t test(...);
19826
19827 public:
19828 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19829 };
19830
19831 template <typename T>
19832 struct has_traits_pairs_test {
19833 private:
19834 template <typename C>
19835 static meta::sfinae_yes_t test(decltype(&C::pairs));
19836 template <typename C>
19837 static meta::sfinae_no_t test(...);
19838
19839 public:
19840 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19841 };
19842
19843 template <typename T>
19844 struct has_traits_ipairs_test {
19845 private:
19846 template <typename C>
19847 static meta::sfinae_yes_t test(decltype(&C::ipairs));
19848 template <typename C>
19849 static meta::sfinae_no_t test(...);
19850
19851 public:
19852 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19853 };
19854
19855 template <typename T>
19856 struct has_traits_next_test {
19857 private:
19858 template <typename C>
19859 static meta::sfinae_yes_t test(decltype(&C::next));
19860 template <typename C>
19861 static meta::sfinae_no_t test(...);
19862
19863 public:
19864 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19865 };
19866
19867 template <typename T>
19868 struct has_traits_add_test {
19869 private:
19870 template <typename C>
19871 static meta::sfinae_yes_t test(decltype(&C::add));
19872 template <typename C>
19873 static meta::sfinae_no_t test(...);
19874
19875 public:
19876 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19877 };
19878
19879 template <typename T>
19880 struct has_traits_size_test {
19881 private:
19882 template <typename C>
19883 static meta::sfinae_yes_t test(decltype(&C::size));
19884 template <typename C>
19885 static meta::sfinae_no_t test(...);
19886
19887 public:
19888 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
19889 };
19890
19891 template <typename T>
19892 using has_clear = meta::boolean<has_clear_test<T>::value>;
19893
19894 template <typename T>
19895 using has_empty = meta::boolean<has_empty_test<T>::value>;
19896
19897 template <typename T>
19898 using has_find = meta::boolean<has_find_test<T>::value>;
19899
19900 template <typename T>
19901 using has_erase = meta::boolean<has_erase_test<T>::value>;
19902
19903 template <typename T>
19904 using has_erase_key = meta::boolean<has_erase_key_test<T>::value>;
19905
19906 template <typename T>
19907 using has_erase_after = meta::boolean<has_erase_after_test<T>::value>;
19908
19909 template <typename T>
19910 using has_traits_get = meta::boolean<has_traits_get_test<T>::value>;
19911
19912 template <typename T>
19913 using has_traits_at = meta::boolean<has_traits_at_test<T>::value>;
19914
19915 template <typename T>
19916 using has_traits_set = meta::boolean<has_traits_set_test<T>::value>;
19917
19918 template <typename T>
19919 using has_traits_index_get = meta::boolean<has_traits_index_get_test<T>::value>;
19920
19921 template <typename T>
19922 using has_traits_index_set = meta::boolean<has_traits_index_set_test<T>::value>;
19923
19924 template <typename T>
19925 using has_traits_pairs = meta::boolean<has_traits_pairs_test<T>::value>;
19926
19927 template <typename T>
19928 using has_traits_ipairs = meta::boolean<has_traits_ipairs_test<T>::value>;
19929
19930 template <typename T>
19931 using has_traits_next = meta::boolean<has_traits_next_test<T>::value>;
19932
19933 template <typename T>
19934 using has_traits_add = meta::boolean<has_traits_add_test<T>::value>;
19935
19936 template <typename T>
19937 using has_traits_size = meta::boolean<has_traits_size_test<T>::value>;
19938
19939 template <typename T>
19940 using has_traits_clear = has_clear<T>;
19941
19942 template <typename T>
19943 using has_traits_empty = has_empty<T>;
19944
19945 template <typename T>
19946 using has_traits_find = meta::boolean<has_traits_find_test<T>::value>;
19947
19948 template <typename T>
19949 using has_traits_index_of = meta::boolean<has_traits_index_of_test<T>::value>;
19950
19951 template <typename T>
19952 using has_traits_insert = meta::boolean<has_traits_insert_test<T>::value>;
19953
19954 template <typename T>
19955 using has_traits_erase = meta::boolean<has_traits_erase_test<T>::value>;
19956
19957 template <typename T>
19958 struct is_forced_container : is_container<T> {};
19959
19960 template <typename T>
19961 struct is_forced_container<as_container_t<T>> : std::true_type {};
19962
19963 template <typename T>
19964 struct container_decay {
19965 typedef T type;
19966 };
19967
19968 template <typename T>
19969 struct container_decay<as_container_t<T>> {
19970 typedef T type;
19971 };
19972
19973 template <typename T>
19974 using container_decay_t = typename container_decay<meta::unqualified_t<T>>::type;
19975
19976 template <typename T>
19977 decltype(auto) get_key(std::false_type, T&& t) {
19978 return std::forward<T>(t);
19979 }
19980
19981 template <typename T>
19982 decltype(auto) get_key(std::true_type, T&& t) {
19983 return t.first;
19984 }
19985
19986 template <typename T>
19987 decltype(auto) get_value(std::false_type, T&& t) {
19988 return std::forward<T>(t);
19989 }
19990
19991 template <typename T>
19992 decltype(auto) get_value(std::true_type, T&& t) {
19993 return t.second;
19994 }
19995
19996 template <typename X, typename = void>
19997 struct usertype_container_default {
19998 private:
19999 typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> T;
20000
20001 public:
20002 typedef lua_nil_t iterator;
20003 typedef lua_nil_t value_type;
20004
20005 static int at(lua_State* L) {
20006 return luaL_error(L, "sol: cannot call 'at(index)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20007 }
20008
20009 static int get(lua_State* L) {
20010 return luaL_error(L, "sol: cannot call 'get(key)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20011 }
20012
20013 static int index_get(lua_State* L) {
20014 return luaL_error(L, "sol: cannot call 'container[key]' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20015 }
20016
20017 static int set(lua_State* L) {
20018 return luaL_error(L, "sol: cannot call 'set(key, value)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20019 }
20020
20021 static int index_set(lua_State* L) {
20022 return luaL_error(
20023 L, "sol: cannot call 'container[key] = value' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20024 }
20025
20026 static int add(lua_State* L) {
20027 return luaL_error(L, "sol: cannot call 'add' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20028 }
20029
20030 static int insert(lua_State* L) {
20031 return luaL_error(L, "sol: cannot call 'insert' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20032 }
20033
20034 static int find(lua_State* L) {
20035 return luaL_error(L, "sol: cannot call 'find' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20036 }
20037
20038 static int index_of(lua_State* L) {
20039 return luaL_error(L, "sol: cannot call 'index_of' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20040 }
20041
20042 static int size(lua_State* L) {
20043 return luaL_error(L, "sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20044 }
20045
20046 static int clear(lua_State* L) {
20047 return luaL_error(L, "sol: cannot call 'clear' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20048 }
20049
20050 static int empty(lua_State* L) {
20051 return luaL_error(L, "sol: cannot call 'empty' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20052 }
20053
20054 static int erase(lua_State* L) {
20055 return luaL_error(L, "sol: cannot call 'erase' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20056 }
20057
20058 static int next(lua_State* L) {
20059 return luaL_error(L, "sol: cannot call 'next' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20060 }
20061
20062 static int pairs(lua_State* L) {
20063 return luaL_error(L, "sol: cannot call '__pairs/pairs' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20064 }
20065
20066 static int ipairs(lua_State* L) {
20067 return luaL_error(L, "sol: cannot call '__ipairs' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20068 }
20069
20070 static iterator begin(lua_State* L, T&) {
20071 luaL_error(L, "sol: cannot call 'being' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20072 return lua_nil;
20073 }
20074
20075 static iterator end(lua_State* L, T&) {
20076 luaL_error(L, "sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
20077 return lua_nil;
20078 }
20079 };
20080
20081 template <typename X>
20082 struct usertype_container_default<X,
20083 std::enable_if_t<meta::all<is_forced_container<meta::unqualified_t<X>>, meta::has_value_type<meta::unqualified_t<container_decay_t<X>>>,
20084 meta::has_iterator<meta::unqualified_t<container_decay_t<X>>>>::value>> {
20085 private:
20086 using T = std::remove_pointer_t<meta::unwrap_unqualified_t<container_decay_t<X>>>;
20087
20088 private:
20089 using deferred_uc = usertype_container<X>;
20090 using is_associative = meta::is_associative<T>;
20091 using is_lookup = meta::is_lookup<T>;
20092 using is_ordered = meta::is_ordered<T>;
20093 using is_matched_lookup = meta::is_matched_lookup<T>;
20094 using iterator = typename T::iterator;
20095 using value_type = typename T::value_type;
20096 typedef meta::conditional_t<is_matched_lookup::value, std::pair<value_type, value_type>,
20097 meta::conditional_t<is_associative::value || is_lookup::value, value_type, std::pair<std::ptrdiff_t, value_type>>>
20098 KV;
20099 typedef typename KV::first_type K;
20100 typedef typename KV::second_type V;
20101 typedef meta::conditional_t<is_matched_lookup::value, std::ptrdiff_t, K> next_K;
20102 typedef decltype(*std::declval<iterator&>()) iterator_return;
20103 typedef meta::conditional_t<is_associative::value || is_matched_lookup::value, std::add_lvalue_reference_t<V>,
20104 meta::conditional_t<is_lookup::value, V, iterator_return>>
20105 captured_type;
20106 typedef typename meta::iterator_tag<iterator>::type iterator_category;
20107 typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator;
20108 typedef meta::conditional_t<is_input_iterator::value, V, decltype(detail::deref_move_only(std::declval<captured_type>()))> push_type;
20109 typedef std::is_copy_assignable<V> is_copyable;
20110 typedef meta::neg<meta::any<std::is_const<V>, std::is_const<std::remove_reference_t<iterator_return>>, meta::neg<is_copyable>>> is_writable;
20111 typedef meta::unqualified_t<decltype(get_key(is_associative(), std::declval<std::add_lvalue_reference_t<value_type>>()))> key_type;
20112 typedef meta::all<std::is_integral<K>, meta::neg<meta::any<is_associative, is_lookup>>> is_linear_integral;
20113
20114 struct iter {
20115 T& source;
20116 iterator it;
20117 std::size_t i;
20118
20119 iter(T& source, iterator it) : source(source), it(std::move(it)), i(0) {
20120 }
20121
20122 ~iter() {
20123 }
20124 };
20125
20126 static auto& get_src(lua_State* L) {
20127#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_)
20128 auto p = stack::unqualified_check_get<T*>(L, 1);
20129 if (!p) {
20130 luaL_error(L,
20131 "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)",
20132 detail::demangle<T>().c_str());
20133 }
20134 if (p.value() == nullptr) {
20135 luaL_error(
20136 L, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle<T>().c_str());
20137 }
20138 return *p.value();
20139#else
20140 return stack::unqualified_get<T>(L, 1);
20141#endif // Safe getting with error
20142 }
20143
20144 static detail::error_result at_category(std::input_iterator_tag, lua_State* L, T& self, std::ptrdiff_t pos) {
20145 pos += deferred_uc::index_adjustment(L, self);
20146 if (pos < 0) {
20147 return stack::push(L, lua_nil);
20148 }
20149 auto it = deferred_uc::begin(L, self);
20150 auto e = deferred_uc::end(L, self);
20151 if (it == e) {
20152 return stack::push(L, lua_nil);
20153 }
20154 while (pos > 0) {
20155 --pos;
20156 ++it;
20157 if (it == e) {
20158 return stack::push(L, lua_nil);
20159 }
20160 }
20161 return get_associative(is_associative(), L, it);
20162 }
20163
20164 static detail::error_result at_category(std::random_access_iterator_tag, lua_State* L, T& self, std::ptrdiff_t pos) {
20165 std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self));
20166 pos += deferred_uc::index_adjustment(L, self);
20167 if (pos < 0 || pos >= len) {
20168 return stack::push(L, lua_nil);
20169 }
20170 auto it = std::next(deferred_uc::begin(L, self), pos);
20171 return get_associative(is_associative(), L, it);
20172 }
20173
20174 static detail::error_result at_start(lua_State* L, T& self, std::ptrdiff_t pos) {
20175 return at_category(iterator_category(), L, self, pos);
20176 }
20177
20178 template <typename Iter>
20179 static detail::error_result get_associative(std::true_type, lua_State* L, Iter& it) {
20180 decltype(auto) v = *it;
20181 return stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(v.second));
20182 }
20183
20184 template <typename Iter>
20185 static detail::error_result get_associative(std::false_type, lua_State* L, Iter& it) {
20186 return stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(*it));
20187 }
20188
20189 static detail::error_result get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) {
20190 key += deferred_uc::index_adjustment(L, self);
20191 if (key < 0) {
20192 return stack::push(L, lua_nil);
20193 }
20194 auto it = deferred_uc::begin(L, self);
20195 auto e = deferred_uc::end(L, self);
20196 if (it == e) {
20197 return stack::push(L, lua_nil);
20198 }
20199 while (key > 0) {
20200 --key;
20201 ++it;
20202 if (it == e) {
20203 return stack::push(L, lua_nil);
20204 }
20205 }
20206 return get_associative(is_associative(), L, it);
20207 }
20208
20209 static detail::error_result get_category(std::random_access_iterator_tag, lua_State* L, T& self, K& key) {
20210 std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self));
20211 key += deferred_uc::index_adjustment(L, self);
20212 if (key < 0 || key >= len) {
20213 return stack::push(L, lua_nil);
20214 }
20215 auto it = std::next(deferred_uc::begin(L, self), key);
20216 return get_associative(is_associative(), L, it);
20217 }
20218
20219 static detail::error_result get_it(std::true_type, lua_State* L, T& self, K& key) {
20220 return get_category(iterator_category(), L, self, key);
20221 }
20222
20223 static detail::error_result get_comparative(std::true_type, lua_State* L, T& self, K& key) {
20224 auto fx = [&](const value_type& r) -> bool { return key == get_key(is_associative(), r); };
20225 auto e = deferred_uc::end(L, self);
20226 auto it = std::find_if(deferred_uc::begin(L, self), e, std::ref(fx));
20227 if (it == e) {
20228 return stack::push(L, lua_nil);
20229 }
20230 return get_associative(is_associative(), L, it);
20231 }
20232
20233 static detail::error_result get_comparative(std::false_type, lua_State*, T&, K&) {
20234 return detail::error_result("cannot get this key on '%s': no suitable way to increment iterator and compare to key value '%s'",
20235 detail::demangle<T>().data(),
20236 detail::demangle<K>().data());
20237 }
20238
20239 static detail::error_result get_it(std::false_type, lua_State* L, T& self, K& key) {
20240 return get_comparative(meta::supports_op_equal<K, key_type>(), L, self, key);
20241 }
20242
20243 static detail::error_result set_associative(std::true_type, iterator& it, stack_object value) {
20244 decltype(auto) v = *it;
20245 v.second = value.as<V>();
20246 return {};
20247 }
20248
20249 static detail::error_result set_associative(std::false_type, iterator& it, stack_object value) {
20250 decltype(auto) v = *it;
20251 v = value.as<V>();
20252 return {};
20253 }
20254
20255 static detail::error_result set_writable(std::true_type, lua_State*, T&, iterator& it, stack_object value) {
20256 return set_associative(is_associative(), it, std::move(value));
20257 }
20258
20259 static detail::error_result set_writable(std::false_type, lua_State*, T&, iterator&, stack_object) {
20260 return detail::error_result(
20261 "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle<T>().data());
20262 }
20263
20264 static detail::error_result set_category(std::input_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) {
20265 decltype(auto) key = okey.as<K>();
20266 key += deferred_uc::index_adjustment(L, self);
20267 auto e = deferred_uc::end(L, self);
20268 auto it = deferred_uc::begin(L, self);
20269 auto backit = it;
20270 for (; key > 0 && it != e; --key, ++it) {
20271 backit = it;
20272 }
20273 if (it == e) {
20274 if (key == 0) {
20275 return add_copyable(is_copyable(), L, self, std::move(value), meta::has_insert_after<T>::value ? backit : it);
20276 }
20277 return detail::error_result("out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
20278 }
20279 return set_writable(is_writable(), L, self, it, std::move(value));
20280 }
20281
20282 static detail::error_result set_category(std::random_access_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) {
20283 decltype(auto) key = okey.as<K>();
20284 key += deferred_uc::index_adjustment(L, self);
20285 if (key < 0) {
20286 return detail::error_result("sol: out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str());
20287 }
20288 std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self));
20289 if (key == len) {
20290 return add_copyable(is_copyable(), L, self, std::move(value));
20291 }
20292 else if (key >= len) {
20293 return detail::error_result("sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
20294 }
20295 auto it = std::next(deferred_uc::begin(L, self), key);
20296 return set_writable(is_writable(), L, self, it, std::move(value));
20297 }
20298
20299 static detail::error_result set_comparative(std::true_type, lua_State* L, T& self, stack_object okey, stack_object value) {
20300 decltype(auto) key = okey.as<K>();
20301 if (!is_writable::value) {
20302 return detail::error_result(
20303 "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle<T>().data());
20304 }
20305 auto fx = [&](const value_type& r) -> bool { return key == get_key(is_associative(), r); };
20306 auto e = deferred_uc::end(L, self);
20307 auto it = std::find_if(deferred_uc::begin(L, self), e, std::ref(fx));
20308 if (it == e) {
20309 return {};
20310 }
20311 return set_writable(is_writable(), L, self, it, std::move(value));
20312 }
20313
20314 static detail::error_result set_comparative(std::false_type, lua_State*, T&, stack_object, stack_object) {
20315 return detail::error_result("cannot set this value on '%s': no suitable way to increment iterator or compare to '%s' key",
20316 detail::demangle<T>().data(),
20317 detail::demangle<K>().data());
20318 }
20319
20320 template <typename Iter>
20321 static detail::error_result set_associative_insert(std::true_type, lua_State*, T& self, Iter& it, K& key, stack_object value) {
20322 if constexpr (meta::has_insert<T>::value) {
20323 self.insert(it, value_type(key, value.as<V>()));
20324 return {};
20325 }
20326 else {
20327 (void)self;
20328 (void)it;
20329 (void)key;
20330 return detail::error_result(
20331 "cannot call 'set' on '%s': there is no 'insert' function on this associative type", detail::demangle<T>().c_str());
20332 }
20333 }
20334
20335 template <typename Iter>
20336 static detail::error_result set_associative_insert(std::false_type, lua_State*, T& self, Iter& it, K& key, stack_object) {
20337 if constexpr (meta::has_insert<T>::value) {
20338 self.insert(it, key);
20339 return {};
20340 }
20341 else {
20342 (void)self;
20343 (void)it;
20344 (void)key;
20345 return detail::error_result(
20346 "cannot call 'set' on '%s': there is no 'insert' function on this non-associative type", detail::demangle<T>().c_str());
20347 }
20348 }
20349
20350 static detail::error_result set_associative_find(std::true_type, lua_State* L, T& self, stack_object okey, stack_object value) {
20351 decltype(auto) key = okey.as<K>();
20352 auto it = self.find(key);
20353 if (it == deferred_uc::end(L, self)) {
20354 return set_associative_insert(is_associative(), L, self, it, key, std::move(value));
20355 }
20356 return set_writable(is_writable(), L, self, it, std::move(value));
20357 }
20358
20359 static detail::error_result set_associative_find(std::false_type, lua_State* L, T& self, stack_object key, stack_object value) {
20360 return set_comparative(meta::supports_op_equal<K, key_type>(), L, self, std::move(key), std::move(value));
20361 }
20362
20363 static detail::error_result set_it(std::true_type, lua_State* L, T& self, stack_object key, stack_object value) {
20364 return set_category(iterator_category(), L, self, std::move(key), std::move(value));
20365 }
20366
20367 static detail::error_result set_it(std::false_type, lua_State* L, T& self, stack_object key, stack_object value) {
20368 return set_associative_find(meta::all<has_find<T>, meta::any<is_associative, is_lookup>>(), L, self, std::move(key), std::move(value));
20369 }
20370
20371 template <bool idx_of = false>
20372 static detail::error_result find_has_associative_lookup(std::true_type, lua_State* L, T& self) {
20373 if constexpr (!is_ordered::value && idx_of) {
20374 (void)L;
20375 (void)self;
20376 return detail::error_result("cannot perform an 'index_of': '%s's is not an ordered container", detail::demangle<T>().data());
20377 }
20378 else {
20379 decltype(auto) key = stack::unqualified_get<K>(L, 2);
20380 auto it = self.find(key);
20381 if (it == deferred_uc::end(L, self)) {
20382 return stack::push(L, lua_nil);
20383 }
20384 if constexpr (idx_of) {
20385 auto dist = std::distance(deferred_uc::begin(L, self), it);
20386 dist -= deferred_uc::index_adjustment(L, self);
20387 return stack::push(L, dist);
20388 }
20389 else {
20390 return get_associative(is_associative(), L, it);
20391 }
20392 }
20393 }
20394
20395 template <bool idx_of = false>
20396 static detail::error_result find_has_associative_lookup(std::false_type, lua_State* L, T& self) {
20397 if constexpr (!is_ordered::value && idx_of) {
20398 (void)L;
20399 (void)self;
20400 return detail::error_result("cannot perform an 'index_of': '%s's is not an ordered container", detail::demangle<T>().data());
20401 }
20402 else {
20403 decltype(auto) value = stack::unqualified_get<V>(L, 2);
20404 auto it = self.find(value);
20405 if (it == deferred_uc::end(L, self)) {
20406 return stack::push(L, lua_nil);
20407 }
20408 if constexpr (idx_of) {
20409 auto dist = std::distance(deferred_uc::begin(L, self), it);
20410 dist -= deferred_uc::index_adjustment(L, self);
20411 return stack::push(L, dist);
20412 }
20413 else {
20414 return get_associative(is_associative(), L, it);
20415 }
20416 }
20417 }
20418
20419 template <bool idx_of = false>
20420 static detail::error_result find_has(std::true_type, lua_State* L, T& self) {
20421 return find_has_associative_lookup<idx_of>(meta::any<is_lookup, is_associative>(), L, self);
20422 }
20423
20424 template <typename Iter>
20425 static detail::error_result find_associative_lookup(std::true_type, lua_State* L, T&, Iter& it, std::size_t) {
20426 return get_associative(is_associative(), L, it);
20427 }
20428
20429 template <typename Iter>
20430 static detail::error_result find_associative_lookup(std::false_type, lua_State* L, T& self, Iter&, std::size_t idx) {
20431 idx -= deferred_uc::index_adjustment(L, self);
20432 return stack::push(L, idx);
20433 }
20434
20435 template <bool = false>
20436 static detail::error_result find_comparative(std::false_type, lua_State*, T&) {
20437 return detail::error_result("cannot call 'find' on '%s': there is no 'find' function and the value_type is not equality comparable",
20438 detail::demangle<T>().c_str());
20439 }
20440
20441 template <bool idx_of = false>
20442 static detail::error_result find_comparative(std::true_type, lua_State* L, T& self) {
20443 decltype(auto) value = stack::unqualified_get<V>(L, 2);
20444 auto it = deferred_uc::begin(L, self);
20445 auto e = deferred_uc::end(L, self);
20446 std::size_t idx = 0;
20447 for (;; ++it, ++idx) {
20448 if (it == e) {
20449 return stack::push(L, lua_nil);
20450 }
20451 if (value == get_value(is_associative(), *it)) {
20452 break;
20453 }
20454 }
20455 return find_associative_lookup(meta::all<meta::boolean<!idx_of>, meta::any<is_lookup, is_associative>>(), L, self, it, idx);
20456 }
20457
20458 template <bool idx_of = false>
20459 static detail::error_result find_has(std::false_type, lua_State* L, T& self) {
20460 return find_comparative<idx_of>(meta::supports_op_equal<V>(), L, self);
20461 }
20462
20463 template <typename Iter>
20464 static detail::error_result add_insert_after(std::false_type, lua_State* L, T& self, stack_object value, Iter&) {
20465 return add_insert_after(std::false_type(), L, self, value);
20466 }
20467
20468 static detail::error_result add_insert_after(std::false_type, lua_State*, T&, stack_object) {
20469 return detail::error_result("cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", detail::demangle<T>().data());
20470 }
20471
20472 template <typename Iter>
20473 static detail::error_result add_insert_after(std::true_type, lua_State*, T& self, stack_object value, Iter& pos) {
20474 self.insert_after(pos, value.as<V>());
20475 return {};
20476 }
20477
20478 static detail::error_result add_insert_after(std::true_type, lua_State* L, T& self, stack_object value) {
20479 auto backit = self.before_begin();
20480 {
20481 auto e = deferred_uc::end(L, self);
20482 for (auto it = deferred_uc::begin(L, self); it != e; ++backit, ++it) {
20483 }
20484 }
20485 return add_insert_after(std::true_type(), L, self, value, backit);
20486 }
20487
20488 template <typename Iter>
20489 static detail::error_result add_insert(std::true_type, lua_State*, T& self, stack_object value, Iter& pos) {
20490 self.insert(pos, value.as<V>());
20491 return {};
20492 }
20493
20494 static detail::error_result add_insert(std::true_type, lua_State* L, T& self, stack_object value) {
20495 auto pos = deferred_uc::end(L, self);
20496 return add_insert(std::true_type(), L, self, value, pos);
20497 }
20498
20499 template <typename Iter>
20500 static detail::error_result add_insert(std::false_type, lua_State* L, T& self, stack_object value, Iter& pos) {
20501 return add_insert_after(meta::has_insert_after<T>(), L, self, std::move(value), pos);
20502 }
20503
20504 static detail::error_result add_insert(std::false_type, lua_State* L, T& self, stack_object value) {
20505 return add_insert_after(meta::has_insert_after<T>(), L, self, std::move(value));
20506 }
20507
20508 template <typename Iter>
20509 static detail::error_result add_push_back(std::true_type, lua_State*, T& self, stack_object value, Iter&) {
20510 self.push_back(value.as<V>());
20511 return {};
20512 }
20513
20514 static detail::error_result add_push_back(std::true_type, lua_State*, T& self, stack_object value) {
20515 self.push_back(value.as<V>());
20516 return {};
20517 }
20518
20519 template <typename Iter>
20520 static detail::error_result add_push_back(std::false_type, lua_State* L, T& self, stack_object value, Iter& pos) {
20521 return add_insert(meta::has_insert<T>(), L, self, value, pos);
20522 }
20523
20524 static detail::error_result add_push_back(std::false_type, lua_State* L, T& self, stack_object value) {
20525 return add_insert(meta::has_insert<T>(), L, self, value);
20526 }
20527
20528 template <typename Iter>
20529 static detail::error_result add_associative(std::true_type, lua_State* L, T& self, stack_object key, Iter& pos) {
20530 if constexpr (meta::has_insert<T>::value) {
20531 self.insert(pos, value_type(key.as<K>(), stack::unqualified_get<V>(L, 3)));
20532 return {};
20533 }
20534 else {
20535 (void)L;
20536 (void)self;
20537 (void)key;
20538 (void)pos;
20539 return detail::error_result(
20540 "cannot call 'insert' on '%s': there is no 'insert' function on this associative type", detail::demangle<T>().c_str());
20541 }
20542 }
20543
20544 static detail::error_result add_associative(std::true_type, lua_State* L, T& self, stack_object key) {
20545 auto pos = deferred_uc::end(L, self);
20546 return add_associative(std::true_type(), L, self, std::move(key), pos);
20547 }
20548
20549 template <typename Iter>
20550 static detail::error_result add_associative(std::false_type, lua_State* L, T& self, stack_object value, Iter& pos) {
20551 return add_push_back(meta::has_push_back<T>(), L, self, value, pos);
20552 }
20553
20554 static detail::error_result add_associative(std::false_type, lua_State* L, T& self, stack_object value) {
20555 return add_push_back(meta::has_push_back<T>(), L, self, value);
20556 }
20557
20558 template <typename Iter>
20559 static detail::error_result add_copyable(std::true_type, lua_State* L, T& self, stack_object value, Iter& pos) {
20560 return add_associative(is_associative(), L, self, std::move(value), pos);
20561 }
20562
20563 static detail::error_result add_copyable(std::true_type, lua_State* L, T& self, stack_object value) {
20564 return add_associative(is_associative(), L, self, value);
20565 }
20566
20567 template <typename Iter>
20568 static detail::error_result add_copyable(std::false_type, lua_State* L, T& self, stack_object value, Iter&) {
20569 return add_copyable(std::false_type(), L, self, std::move(value));
20570 }
20571
20572 static detail::error_result add_copyable(std::false_type, lua_State*, T&, stack_object) {
20573 return detail::error_result("cannot call 'add' on '%s': value_type is non-copyable", detail::demangle<T>().data());
20574 }
20575
20576 static detail::error_result insert_lookup(std::true_type, lua_State* L, T& self, stack_object, stack_object value) {
20577 // TODO: should we warn or error about someone calling insert on an ordered / lookup container with no associativity?
20578 return add_copyable(std::true_type(), L, self, std::move(value));
20579 }
20580
20581 static detail::error_result insert_lookup(std::false_type, lua_State* L, T& self, stack_object where, stack_object value) {
20582 auto it = deferred_uc::begin(L, self);
20583 auto key = where.as<K>();
20584 key += deferred_uc::index_adjustment(L, self);
20585 std::advance(it, key);
20586 self.insert(it, value.as<V>());
20587 return {};
20588 }
20589
20590 static detail::error_result insert_after_has(std::true_type, lua_State* L, T& self, stack_object where, stack_object value) {
20591 auto key = where.as<K>();
20592 auto backit = self.before_begin();
20593 {
20594 key += deferred_uc::index_adjustment(L, self);
20595 auto e = deferred_uc::end(L, self);
20596 for (auto it = deferred_uc::begin(L, self); key > 0; ++backit, ++it, --key) {
20597 if (backit == e) {
20598 return detail::error_result("sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
20599 }
20600 }
20601 }
20602 self.insert_after(backit, value.as<V>());
20603 return {};
20604 }
20605
20606 static detail::error_result insert_after_has(std::false_type, lua_State*, T&, stack_object, stack_object) {
20607 return detail::error_result(
20608 "cannot call 'insert' on '%s': no suitable or similar functionality detected on this container", detail::demangle<T>().data());
20609 }
20610
20611 static detail::error_result insert_has(std::true_type, lua_State* L, T& self, stack_object key, stack_object value) {
20612 return insert_lookup(meta::any<is_associative, is_lookup>(), L, self, std::move(key), std::move(value));
20613 }
20614
20615 static detail::error_result insert_has(std::false_type, lua_State* L, T& self, stack_object where, stack_object value) {
20616 return insert_after_has(meta::has_insert_after<T>(), L, self, where, value);
20617 }
20618
20619 static detail::error_result insert_copyable(std::true_type, lua_State* L, T& self, stack_object key, stack_object value) {
20620 return insert_has(meta::has_insert<T>(), L, self, std::move(key), std::move(value));
20621 }
20622
20623 static detail::error_result insert_copyable(std::false_type, lua_State*, T&, stack_object, stack_object) {
20624 return detail::error_result("cannot call 'insert' on '%s': value_type is non-copyable", detail::demangle<T>().data());
20625 }
20626
20627 static detail::error_result erase_integral(std::true_type, lua_State* L, T& self, K& key) {
20628 auto it = deferred_uc::begin(L, self);
20629 key += deferred_uc::index_adjustment(L, self);
20630 std::advance(it, key);
20631 self.erase(it);
20632
20633 return {};
20634 }
20635
20636 static detail::error_result erase_integral(std::false_type, lua_State* L, T& self, const K& key) {
20637 auto fx = [&](const value_type& r) -> bool { return key == r; };
20638 auto e = deferred_uc::end(L, self);
20639 auto it = std::find_if(deferred_uc::begin(L, self), e, std::ref(fx));
20640 if (it == e) {
20641 return {};
20642 }
20643 self.erase(it);
20644
20645 return {};
20646 }
20647
20648 static detail::error_result erase_associative_lookup(std::true_type, lua_State*, T& self, const K& key) {
20649 self.erase(key);
20650 return {};
20651 }
20652
20653 static detail::error_result erase_associative_lookup(std::false_type, lua_State* L, T& self, K& key) {
20654 return erase_integral(std::is_integral<K>(), L, self, key);
20655 }
20656
20657 static detail::error_result erase_after_has(std::true_type, lua_State* L, T& self, K& key) {
20658 auto backit = self.before_begin();
20659 {
20660 key += deferred_uc::index_adjustment(L, self);
20661 auto e = deferred_uc::end(L, self);
20662 for (auto it = deferred_uc::begin(L, self); key > 0; ++backit, ++it, --key) {
20663 if (backit == e) {
20664 return detail::error_result("sol: out of bounds for erase on '%s'", detail::demangle<T>().c_str());
20665 }
20666 }
20667 }
20668 self.erase_after(backit);
20669 return {};
20670 }
20671
20672 static detail::error_result erase_after_has(std::false_type, lua_State*, T&, const K&) {
20673 return detail::error_result("sol: cannot call erase on '%s'", detail::demangle<T>().c_str());
20674 }
20675
20676 static detail::error_result erase_key_has(std::true_type, lua_State* L, T& self, K& key) {
20677 return erase_associative_lookup(meta::any<is_associative, is_lookup>(), L, self, key);
20678 }
20679
20680 static detail::error_result erase_key_has(std::false_type, lua_State* L, T& self, K& key) {
20681 return erase_after_has(has_erase_after<T>(), L, self, key);
20682 }
20683
20684 static detail::error_result erase_has(std::true_type, lua_State* L, T& self, K& key) {
20685 return erase_associative_lookup(meta::any<is_associative, is_lookup>(), L, self, key);
20686 }
20687
20688 static detail::error_result erase_has(std::false_type, lua_State* L, T& self, K& key) {
20689 return erase_key_has(has_erase_key<T>(), L, self, key);
20690 }
20691
20692 static auto size_has(std::false_type, lua_State* L, T& self) {
20693 return std::distance(deferred_uc::begin(L, self), deferred_uc::end(L, self));
20694 }
20695
20696 static auto size_has(std::true_type, lua_State*, T& self) {
20697 return self.size();
20698 }
20699
20700 static void clear_has(std::true_type, lua_State*, T& self) {
20701 self.clear();
20702 }
20703
20704 static void clear_has(std::false_type, lua_State* L, T&) {
20705 luaL_error(L, "sol: cannot call clear on '%s'", detail::demangle<T>().c_str());
20706 }
20707
20708 static bool empty_has(std::true_type, lua_State*, T& self) {
20709 return self.empty();
20710 }
20711
20712 static bool empty_has(std::false_type, lua_State* L, T& self) {
20713 return deferred_uc::begin(L, self) == deferred_uc::end(L, self);
20714 }
20715
20716 static detail::error_result get_associative_find(std::true_type, lua_State* L, T& self, K& key) {
20717 auto it = self.find(key);
20718 if (it == deferred_uc::end(L, self)) {
20719 stack::push(L, lua_nil);
20720 return {};
20721 }
20722 return get_associative(std::true_type(), L, it);
20723 }
20724
20725 static detail::error_result get_associative_find(std::false_type, lua_State* L, T& self, K& key) {
20726 return get_it(is_linear_integral(), L, self, key);
20727 }
20728
20729 static detail::error_result get_start(lua_State* L, T& self, K& key) {
20730 return get_associative_find(std::integral_constant < bool, is_associative::value&& has_find<T>::value > (), L, self, key);
20731 }
20732
20733 static detail::error_result set_start(lua_State* L, T& self, stack_object key, stack_object value) {
20734 return set_it(is_linear_integral(), L, self, std::move(key), std::move(value));
20735 }
20736
20737 static std::size_t size_start(lua_State* L, T& self) {
20738 return size_has(meta::has_size<T>(), L, self);
20739 }
20740
20741 static void clear_start(lua_State* L, T& self) {
20742 clear_has(has_clear<T>(), L, self);
20743 }
20744
20745 static bool empty_start(lua_State* L, T& self) {
20746 return empty_has(has_empty<T>(), L, self);
20747 }
20748
20749 static detail::error_result erase_start(lua_State* L, T& self, K& key) {
20750 return erase_has(has_erase<T>(), L, self, key);
20751 }
20752
20753 template <bool ip>
20754 static int next_associative(std::true_type, lua_State* L) {
20755 iter& i = stack::unqualified_get<user<iter>>(L, 1);
20756 auto& source = i.source;
20757 auto& it = i.it;
20758 if (it == deferred_uc::end(L, source)) {
20759 return stack::push(L, lua_nil);
20760 }
20761 int p;
20762 if constexpr (ip) {
20763 ++i.i;
20764 p = stack::push_reference(L, i.i);
20765 }
20766 else {
20767 p = stack::push_reference(L, it->first);
20768 }
20769 p += stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(it->second));
20770 std::advance(it, 1);
20771 return p;
20772 }
20773
20774 template <bool>
20775 static int next_associative(std::false_type, lua_State* L) {
20776 iter& i = stack::unqualified_get<user<iter>>(L, 1);
20777 auto& source = i.source;
20778 auto& it = i.it;
20779 next_K k = stack::unqualified_get<next_K>(L, 2);
20780 if (it == deferred_uc::end(L, source)) {
20781 return stack::push(L, lua_nil);
20782 }
20783 int p;
20784 if constexpr (std::is_integral_v<next_K>) {
20785 p = stack::push_reference(L, k + 1);
20786 }
20787 else {
20788 p = stack::stack_detail::push_reference(L, k + 1);
20789 }
20790 p += stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(*it));
20791 std::advance(it, 1);
20792 return p;
20793 }
20794
20795 template <bool ip>
20796 static int next_iter(lua_State* L) {
20797 typedef meta::any<is_associative, meta::all<is_lookup, meta::neg<is_matched_lookup>>> is_assoc;
20798 return next_associative<ip>(is_assoc(), L);
20799 }
20800
20801 template <bool ip>
20802 static int pairs_associative(std::true_type, lua_State* L) {
20803 auto& src = get_src(L);
20804 stack::push(L, next_iter<ip>);
20805 stack::push<user<iter>>(L, src, deferred_uc::begin(L, src));
20806 stack::push(L, lua_nil);
20807 return 3;
20808 }
20809
20810 template <bool ip>
20811 static int pairs_associative(std::false_type, lua_State* L) {
20812 auto& src = get_src(L);
20813 stack::push(L, next_iter<ip>);
20814 stack::push<user<iter>>(L, src, deferred_uc::begin(L, src));
20815 stack::push(L, 0);
20816 return 3;
20817 }
20818
20819 public:
20820 static int at(lua_State* L) {
20821 auto& self = get_src(L);
20822 detail::error_result er;
20823 {
20824 std::ptrdiff_t pos = stack::unqualified_get<std::ptrdiff_t>(L, 2);
20825 er = at_start(L, self, pos);
20826 }
20827 return handle_errors(L, er);
20828 }
20829
20830 static int get(lua_State* L) {
20831 auto& self = get_src(L);
20832 detail::error_result er;
20833 {
20834 decltype(auto) key = stack::unqualified_get<K>(L);
20835 er = get_start(L, self, key);
20836 }
20837 return handle_errors(L, er);
20838 }
20839
20840 static int index_get(lua_State* L) {
20841 return get(L);
20842 }
20843
20844 static int set(lua_State* L) {
20845 stack_object value = stack_object(L, raw_index(3));
20846 if constexpr (is_linear_integral::value) {
20847 // for non-associative containers,
20848 // erasure only happens if it is the
20849 // last index in the container
20850 auto key = stack::get<K>(L, 2);
20851 auto self_size = deferred_uc::size(L);
20852 if (key == static_cast<K>(self_size)) {
20853 if (type_of(L, 3) == type::lua_nil) {
20854 return erase(L);
20855 }
20856 }
20857 }
20858 else {
20859 if (type_of(L, 3) == type::lua_nil) {
20860 return erase(L);
20861 }
20862 }
20863 auto& self = get_src(L);
20864 detail::error_result er = set_start(L, self, stack_object(L, raw_index(2)), std::move(value));
20865 return handle_errors(L, er);
20866 }
20867
20868 static int index_set(lua_State* L) {
20869 return set(L);
20870 }
20871
20872 static int add(lua_State* L) {
20873 auto& self = get_src(L);
20874 detail::error_result er = add_copyable(is_copyable(), L, self, stack_object(L, raw_index(2)));
20875 return handle_errors(L, er);
20876 }
20877
20878 static int insert(lua_State* L) {
20879 auto& self = get_src(L);
20880 detail::error_result er = insert_copyable(is_copyable(), L, self, stack_object(L, raw_index(2)), stack_object(L, raw_index(3)));
20881 return handle_errors(L, er);
20882 }
20883
20884 static int find(lua_State* L) {
20885 auto& self = get_src(L);
20886 detail::error_result er = find_has(has_find<T>(), L, self);
20887 return handle_errors(L, er);
20888 }
20889
20890 static int index_of(lua_State* L) {
20891 auto& self = get_src(L);
20892 detail::error_result er = find_has<true>(has_find<T>(), L, self);
20893 return handle_errors(L, er);
20894 }
20895
20896 static iterator begin(lua_State*, T& self) {
20897 if constexpr (meta::has_begin_end_v<T>) {
20898 return self.begin();
20899 }
20900 else {
20901 using std::begin;
20902 return begin(self);
20903 }
20904 }
20905
20906 static iterator end(lua_State*, T& self) {
20907 if constexpr (meta::has_begin_end_v<T>) {
20908 return self.end();
20909 }
20910 else {
20911 using std::end;
20912 return end(self);
20913 }
20914 }
20915
20916 static int size(lua_State* L) {
20917 auto& self = get_src(L);
20918 std::size_t r = size_start(L, self);
20919 return stack::push(L, r);
20920 }
20921
20922 static int clear(lua_State* L) {
20923 auto& self = get_src(L);
20924 clear_start(L, self);
20925 return 0;
20926 }
20927
20928 static int erase(lua_State* L) {
20929 auto& self = get_src(L);
20930 detail::error_result er;
20931 {
20932 decltype(auto) key = stack::unqualified_get<K>(L, 2);
20933 er = erase_start(L, self, key);
20934 }
20935 return handle_errors(L, er);
20936 }
20937
20938 static int empty(lua_State* L) {
20939 auto& self = get_src(L);
20940 return stack::push(L, empty_start(L, self));
20941 }
20942
20943 static std::ptrdiff_t index_adjustment(lua_State*, T&) {
20944 return static_cast<std::ptrdiff_t>((SOL_CONTAINER_START_INDEX_I_) == 0 ? 0 : -(SOL_CONTAINER_START_INDEX_I_));
20945 }
20946
20947 static int pairs(lua_State* L) {
20948 typedef meta::any<is_associative, meta::all<is_lookup, meta::neg<is_matched_lookup>>> is_assoc;
20949 return pairs_associative<false>(is_assoc(), L);
20950 }
20951
20952 static int ipairs(lua_State* L) {
20953 typedef meta::any<is_associative, meta::all<is_lookup, meta::neg<is_matched_lookup>>> is_assoc;
20954 return pairs_associative<true>(is_assoc(), L);
20955 }
20956
20957 static int next(lua_State* L) {
20958 return stack::push(L, next_iter<false>);
20959 }
20960 };
20961
20962 template <typename X>
20963 struct usertype_container_default<X, std::enable_if_t<std::is_array<std::remove_pointer_t<meta::unwrap_unqualified_t<X>>>::value>> {
20964 private:
20965 typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> T;
20966 typedef usertype_container<X> deferred_uc;
20967
20968 public:
20969 typedef std::remove_extent_t<T> value_type;
20970 typedef value_type* iterator;
20971
20972 private:
20973 struct iter {
20974 T& source;
20975 iterator it;
20976
20977 iter(T& source, iterator it) : source(source), it(std::move(it)) {
20978 }
20979 };
20980
20981 static auto& get_src(lua_State* L) {
20982 auto p = stack::unqualified_check_get<T*>(L, 1);
20983#if SOL_IS_ON(SOL_SAFE_USERTYPE_I_)
20984 if (!p) {
20985 luaL_error(L,
20986 "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)",
20987 detail::demangle<T>().c_str());
20988 }
20989 if (p.value() == nullptr) {
20990 luaL_error(
20991 L, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle<T>().c_str());
20992 }
20993#endif // Safe getting with error
20994 return *p.value();
20995 }
20996
20997 static int find(std::true_type, lua_State* L) {
20998 T& self = get_src(L);
20999 decltype(auto) value = stack::unqualified_get<value_type>(L, 2);
21000 std::size_t N = std::extent<T>::value;
21001 for (std::size_t idx = 0; idx < N; ++idx) {
21002 using v_t = std::add_const_t<decltype(self[idx])>;
21003 v_t v = self[idx];
21004 if (v == value) {
21005 idx -= deferred_uc::index_adjustment(L, self);
21006 return stack::push(L, idx);
21007 }
21008 }
21009 return stack::push(L, lua_nil);
21010 }
21011
21012 static int find(std::false_type, lua_State* L) {
21013 return luaL_error(L, "sol: cannot call 'find' on '%s': no supported comparison operator for the value type", detail::demangle<T>().c_str());
21014 }
21015
21016 static int next_iter(lua_State* L) {
21017 iter& i = stack::unqualified_get<user<iter>>(L, 1);
21018 auto& source = i.source;
21019 auto& it = i.it;
21020 std::size_t k = stack::unqualified_get<std::size_t>(L, 2);
21021 if (it == deferred_uc::end(L, source)) {
21022 return 0;
21023 }
21024 int p;
21025 p = stack::push(L, k + 1);
21026 p += stack::push_reference(L, detail::deref_move_only(*it));
21027 std::advance(it, 1);
21028 return p;
21029 }
21030
21031 public:
21032 static int clear(lua_State* L) {
21033 return luaL_error(L, "sol: cannot call 'clear' on type '%s': cannot remove all items from a fixed array", detail::demangle<T>().c_str());
21034 }
21035
21036 static int erase(lua_State* L) {
21037 return luaL_error(L, "sol: cannot call 'erase' on type '%s': cannot remove an item from fixed arrays", detail::demangle<T>().c_str());
21038 }
21039
21040 static int add(lua_State* L) {
21041 return luaL_error(L, "sol: cannot call 'add' on type '%s': cannot add to fixed arrays", detail::demangle<T>().c_str());
21042 }
21043
21044 static int insert(lua_State* L) {
21045 return luaL_error(L, "sol: cannot call 'insert' on type '%s': cannot insert new entries into fixed arrays", detail::demangle<T>().c_str());
21046 }
21047
21048 static int at(lua_State* L) {
21049 return get(L);
21050 }
21051
21052 static int get(lua_State* L) {
21053 T& self = get_src(L);
21054 std::ptrdiff_t idx = stack::unqualified_get<std::ptrdiff_t>(L, 2);
21055 idx += deferred_uc::index_adjustment(L, self);
21056 if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value) || idx < 0) {
21057 return stack::push(L, lua_nil);
21058 }
21059 return stack::push_reference(L, detail::deref_move_only(self[idx]));
21060 }
21061
21062 static int index_get(lua_State* L) {
21063 return get(L);
21064 }
21065
21066 static int set(lua_State* L) {
21067 T& self = get_src(L);
21068 std::ptrdiff_t idx = stack::unqualified_get<std::ptrdiff_t>(L, 2);
21069 idx += deferred_uc::index_adjustment(L, self);
21070 if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value)) {
21071 return luaL_error(L, "sol: index out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
21072 }
21073 if (idx < 0) {
21074 return luaL_error(L, "sol: index out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str());
21075 }
21076 self[idx] = stack::unqualified_get<value_type>(L, 3);
21077 return 0;
21078 }
21079
21080 static int index_set(lua_State* L) {
21081 return set(L);
21082 }
21083
21084 static int index_of(lua_State* L) {
21085 return find(L);
21086 }
21087
21088 static int find(lua_State* L) {
21089 return find(meta::supports_op_equal<value_type, value_type>(), L);
21090 }
21091
21092 static int size(lua_State* L) {
21093 return stack::push(L, std::extent<T>::value);
21094 }
21095
21096 static int empty(lua_State* L) {
21097 return stack::push(L, std::extent<T>::value > 0);
21098 }
21099
21100 static int pairs(lua_State* L) {
21101 auto& src = get_src(L);
21102 stack::push(L, next_iter);
21103 stack::push<user<iter>>(L, src, deferred_uc::begin(L, src));
21104 stack::push(L, 0);
21105 return 3;
21106 }
21107
21108 static int ipairs(lua_State* L) {
21109 return pairs(L);
21110 }
21111
21112 static int next(lua_State* L) {
21113 return stack::push(L, next_iter);
21114 }
21115
21116 static std::ptrdiff_t index_adjustment(lua_State*, T&) {
21117 return (SOL_CONTAINER_START_INDEX_I_) == 0 ? 0 : -(SOL_CONTAINER_START_INDEX_I_);
21118 }
21119
21120 static iterator begin(lua_State*, T& self) {
21121 return std::addressof(self[0]);
21122 }
21123
21124 static iterator end(lua_State*, T& self) {
21125 return std::addressof(self[0]) + std::extent<T>::value;
21126 }
21127 };
21128
21129 template <typename X>
21130 struct usertype_container_default<usertype_container<X>> : usertype_container_default<X> {};
21131 } // namespace container_detail
21132
21133 template <typename T>
21134 struct usertype_container : container_detail::usertype_container_default<T> {};
21135
21136} // namespace sol
21137
21138// end of sol/usertype_container.hpp
21139
21140#include <unordered_map>
21141
21142namespace sol {
21143
21144 namespace container_detail {
21145 template <typename X>
21146 struct u_c_launch {
21147 using T = std::remove_pointer_t<meta::unqualified_t<X>>;
21148 using uc = usertype_container<T>;
21149 using default_uc = usertype_container_default<T>;
21150
21151 static inline int real_index_get_traits(std::true_type, lua_State* L) {
21152 return uc::index_get(L);
21153 }
21154
21155 static inline int real_index_get_traits(std::false_type, lua_State* L) {
21156 return default_uc::index_get(L);
21157 }
21158
21159 static inline int real_index_call(lua_State* L) {
21160 static const std::unordered_map<string_view, lua_CFunction> calls {
21161 { "at", &real_at_call },
21162 { "get", &real_get_call },
21163 { "set", &real_set_call },
21164 { "size", &real_length_call },
21165 { "add", &real_add_call },
21166 { "empty", &real_empty_call },
21167 { "insert", &real_insert_call },
21168 { "clear", &real_clear_call },
21169 { "find", &real_find_call },
21170 { "index_of", &real_index_of_call },
21171 { "erase", &real_erase_call },
21172 { "pairs", &pairs_call },
21173 { "next", &next_call },
21174 };
21175 auto maybenameview = stack::unqualified_check_get<string_view>(L, 2);
21176 if (maybenameview) {
21177 const string_view& name = *maybenameview;
21178 auto it = calls.find(name);
21179 if (it != calls.cend()) {
21180 return stack::push(L, it->second);
21181 }
21182 }
21183 return real_index_get_traits(container_detail::has_traits_index_get<uc>(), L);
21184 }
21185
21186 static inline int real_at_traits(std::true_type, lua_State* L) {
21187 return uc::at(L);
21188 }
21189
21190 static inline int real_at_traits(std::false_type, lua_State* L) {
21191 return default_uc::at(L);
21192 }
21193
21194 static inline int real_at_call(lua_State* L) {
21195 return real_at_traits(container_detail::has_traits_at<uc>(), L);
21196 }
21197
21198 static inline int real_get_traits(std::true_type, lua_State* L) {
21199 return uc::get(L);
21200 }
21201
21202 static inline int real_get_traits(std::false_type, lua_State* L) {
21203 return default_uc::get(L);
21204 }
21205
21206 static inline int real_get_call(lua_State* L) {
21207 return real_get_traits(container_detail::has_traits_get<uc>(), L);
21208 }
21209
21210 static inline int real_set_traits(std::true_type, lua_State* L) {
21211 return uc::set(L);
21212 }
21213
21214 static inline int real_set_traits(std::false_type, lua_State* L) {
21215 return default_uc::set(L);
21216 }
21217
21218 static inline int real_set_call(lua_State* L) {
21219 return real_set_traits(container_detail::has_traits_set<uc>(), L);
21220 }
21221
21222 static inline int real_index_set_traits(std::true_type, lua_State* L) {
21223 return uc::index_set(L);
21224 }
21225
21226 static inline int real_index_set_traits(std::false_type, lua_State* L) {
21227 return default_uc::index_set(L);
21228 }
21229
21230 static inline int real_new_index_call(lua_State* L) {
21231 return real_index_set_traits(container_detail::has_traits_index_set<uc>(), L);
21232 }
21233
21234 static inline int real_pairs_traits(std::true_type, lua_State* L) {
21235 return uc::pairs(L);
21236 }
21237
21238 static inline int real_pairs_traits(std::false_type, lua_State* L) {
21239 return default_uc::pairs(L);
21240 }
21241
21242 static inline int real_pairs_call(lua_State* L) {
21243 return real_pairs_traits(container_detail::has_traits_pairs<uc>(), L);
21244 }
21245
21246 static inline int real_ipairs_traits(std::true_type, lua_State* L) {
21247 return uc::ipairs(L);
21248 }
21249
21250 static inline int real_ipairs_traits(std::false_type, lua_State* L) {
21251 return default_uc::ipairs(L);
21252 }
21253
21254 static inline int real_ipairs_call(lua_State* L) {
21255 return real_ipairs_traits(container_detail::has_traits_ipairs<uc>(), L);
21256 }
21257
21258 static inline int real_next_traits(std::true_type, lua_State* L) {
21259 return uc::next(L);
21260 }
21261
21262 static inline int real_next_traits(std::false_type, lua_State* L) {
21263 return default_uc::next(L);
21264 }
21265
21266 static inline int real_next_call(lua_State* L) {
21267 return real_next_traits(container_detail::has_traits_next<uc>(), L);
21268 }
21269
21270 static inline int real_size_traits(std::true_type, lua_State* L) {
21271 return uc::size(L);
21272 }
21273
21274 static inline int real_size_traits(std::false_type, lua_State* L) {
21275 return default_uc::size(L);
21276 }
21277
21278 static inline int real_length_call(lua_State* L) {
21279 return real_size_traits(container_detail::has_traits_size<uc>(), L);
21280 }
21281
21282 static inline int real_add_traits(std::true_type, lua_State* L) {
21283 return uc::add(L);
21284 }
21285
21286 static inline int real_add_traits(std::false_type, lua_State* L) {
21287 return default_uc::add(L);
21288 }
21289
21290 static inline int real_add_call(lua_State* L) {
21291 return real_add_traits(container_detail::has_traits_add<uc>(), L);
21292 }
21293
21294 static inline int real_insert_traits(std::true_type, lua_State* L) {
21295 return uc::insert(L);
21296 }
21297
21298 static inline int real_insert_traits(std::false_type, lua_State* L) {
21299 return default_uc::insert(L);
21300 }
21301
21302 static inline int real_insert_call(lua_State* L) {
21303 return real_insert_traits(container_detail::has_traits_insert<uc>(), L);
21304 }
21305
21306 static inline int real_clear_traits(std::true_type, lua_State* L) {
21307 return uc::clear(L);
21308 }
21309
21310 static inline int real_clear_traits(std::false_type, lua_State* L) {
21311 return default_uc::clear(L);
21312 }
21313
21314 static inline int real_clear_call(lua_State* L) {
21315 return real_clear_traits(container_detail::has_traits_clear<uc>(), L);
21316 }
21317
21318 static inline int real_empty_traits(std::true_type, lua_State* L) {
21319 return uc::empty(L);
21320 }
21321
21322 static inline int real_empty_traits(std::false_type, lua_State* L) {
21323 return default_uc::empty(L);
21324 }
21325
21326 static inline int real_empty_call(lua_State* L) {
21327 return real_empty_traits(container_detail::has_traits_empty<uc>(), L);
21328 }
21329
21330 static inline int real_erase_traits(std::true_type, lua_State* L) {
21331 return uc::erase(L);
21332 }
21333
21334 static inline int real_erase_traits(std::false_type, lua_State* L) {
21335 return default_uc::erase(L);
21336 }
21337
21338 static inline int real_erase_call(lua_State* L) {
21339 return real_erase_traits(container_detail::has_traits_erase<uc>(), L);
21340 }
21341
21342 static inline int real_find_traits(std::true_type, lua_State* L) {
21343 return uc::find(L);
21344 }
21345
21346 static inline int real_find_traits(std::false_type, lua_State* L) {
21347 return default_uc::find(L);
21348 }
21349
21350 static inline int real_find_call(lua_State* L) {
21351 return real_find_traits(container_detail::has_traits_find<uc>(), L);
21352 }
21353
21354 static inline int real_index_of_call(lua_State* L) {
21355 if constexpr (container_detail::has_traits_index_of<uc>()) {
21356 return uc::index_of(L);
21357 }
21358 else {
21359 return default_uc::index_of(L);
21360 }
21361 }
21362
21363 static inline int add_call(lua_State* L) {
21364 return detail::typed_static_trampoline<decltype(&real_add_call), (&real_add_call)>(L);
21365 }
21366
21367 static inline int erase_call(lua_State* L) {
21368 return detail::typed_static_trampoline<decltype(&real_erase_call), (&real_erase_call)>(L);
21369 }
21370
21371 static inline int insert_call(lua_State* L) {
21372 return detail::typed_static_trampoline<decltype(&real_insert_call), (&real_insert_call)>(L);
21373 }
21374
21375 static inline int clear_call(lua_State* L) {
21376 return detail::typed_static_trampoline<decltype(&real_clear_call), (&real_clear_call)>(L);
21377 }
21378
21379 static inline int empty_call(lua_State* L) {
21380 return detail::typed_static_trampoline<decltype(&real_empty_call), (&real_empty_call)>(L);
21381 }
21382
21383 static inline int find_call(lua_State* L) {
21384 return detail::typed_static_trampoline<decltype(&real_find_call), (&real_find_call)>(L);
21385 }
21386
21387 static inline int index_of_call(lua_State* L) {
21388 return detail::typed_static_trampoline<decltype(&real_index_of_call), (&real_index_of_call)>(L);
21389 }
21390
21391 static inline int length_call(lua_State* L) {
21392 return detail::typed_static_trampoline<decltype(&real_length_call), (&real_length_call)>(L);
21393 }
21394
21395 static inline int pairs_call(lua_State* L) {
21396 return detail::typed_static_trampoline<decltype(&real_pairs_call), (&real_pairs_call)>(L);
21397 }
21398
21399 static inline int ipairs_call(lua_State* L) {
21400 return detail::typed_static_trampoline<decltype(&real_ipairs_call), (&real_ipairs_call)>(L);
21401 }
21402
21403 static inline int next_call(lua_State* L) {
21404 return detail::typed_static_trampoline<decltype(&real_next_call), (&real_next_call)>(L);
21405 }
21406
21407 static inline int at_call(lua_State* L) {
21408 return detail::typed_static_trampoline<decltype(&real_at_call), (&real_at_call)>(L);
21409 }
21410
21411 static inline int get_call(lua_State* L) {
21412 return detail::typed_static_trampoline<decltype(&real_get_call), (&real_get_call)>(L);
21413 }
21414
21415 static inline int set_call(lua_State* L) {
21416 return detail::typed_static_trampoline<decltype(&real_set_call), (&real_set_call)>(L);
21417 }
21418
21419 static inline int index_call(lua_State* L) {
21420 return detail::typed_static_trampoline<decltype(&real_index_call), (&real_index_call)>(L);
21421 }
21422
21423 static inline int new_index_call(lua_State* L) {
21424 return detail::typed_static_trampoline<decltype(&real_new_index_call), (&real_new_index_call)>(L);
21425 }
21426 };
21427 } // namespace container_detail
21428
21429 namespace stack {
21430 namespace stack_detail {
21431 template <typename T, bool is_shim = false>
21432 struct metatable_setup {
21433 lua_State* L;
21434
21435 metatable_setup(lua_State* L) : L(L) {
21436 }
21437
21438 void operator()() {
21439 using meta_usertype_container
21440 = container_detail::u_c_launch<meta::conditional_t<is_shim, as_container_t<std::remove_pointer_t<T>>, std::remove_pointer_t<T>>>;
21441 static const char* metakey
21442 = is_shim ? &usertype_traits<as_container_t<std::remove_pointer_t<T>>>::metatable()[0] : &usertype_traits<T>::metatable()[0];
21443 static const std::array<luaL_Reg, 20> reg = { {
21444 // clang-format off
21445 { "__pairs", &meta_usertype_container::pairs_call },
21446 { "__ipairs", &meta_usertype_container::ipairs_call },
21447 { "__len", &meta_usertype_container::length_call },
21448 { "__index", &meta_usertype_container::index_call },
21449 { "__newindex", &meta_usertype_container::new_index_call },
21450 { "pairs", &meta_usertype_container::pairs_call },
21451 { "next", &meta_usertype_container::next_call },
21452 { "at", &meta_usertype_container::at_call },
21453 { "get", &meta_usertype_container::get_call },
21454 { "set", &meta_usertype_container::set_call },
21455 { "size", &meta_usertype_container::length_call },
21456 { "empty", &meta_usertype_container::empty_call },
21457 { "clear", &meta_usertype_container::clear_call },
21458 { "insert", &meta_usertype_container::insert_call },
21459 { "add", &meta_usertype_container::add_call },
21460 { "find", &meta_usertype_container::find_call },
21461 { "index_of", &meta_usertype_container::index_of_call },
21462 { "erase", &meta_usertype_container::erase_call },
21463 std::is_pointer<T>::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destruct<T> },
21464 { nullptr, nullptr }
21465 // clang-format on
21466 } };
21467
21468 if (luaL_newmetatable(L, metakey) == 1) {
21469 luaL_setfuncs(L, reg.data(), 0);
21470 }
21471 lua_setmetatable(L, -2);
21472 }
21473 };
21474 } // namespace stack_detail
21475
21476 template <typename T>
21477 struct unqualified_pusher<as_container_t<T>> {
21478 using C = meta::unqualified_t<T>;
21479
21480 static int push_lvalue(std::true_type, lua_State* L, const C& cont) {
21481 stack_detail::metatable_setup<C*, true> fx(L);
21482 return stack::push<detail::as_pointer_tag<const C>>(L, detail::with_function_tag(), fx, detail::ptr(cont));
21483 }
21484
21485 static int push_lvalue(std::false_type, lua_State* L, const C& cont) {
21486 stack_detail::metatable_setup<C, true> fx(L);
21487 return stack::push<detail::as_value_tag<C>>(L, detail::with_function_tag(), fx, cont);
21488 }
21489
21490 static int push_rvalue(std::true_type, lua_State* L, C&& cont) {
21491 stack_detail::metatable_setup<C, true> fx(L);
21492 return stack::push<detail::as_value_tag<C>>(L, detail::with_function_tag(), fx, std::move(cont));
21493 }
21494
21495 static int push_rvalue(std::false_type, lua_State* L, const C& cont) {
21496 return push_lvalue(std::is_lvalue_reference<T>(), L, cont);
21497 }
21498
21499 static int push(lua_State* L, const as_container_t<T>& as_cont) {
21500 return push_lvalue(std::is_lvalue_reference<T>(), L, as_cont.value());
21501 }
21502
21503 static int push(lua_State* L, as_container_t<T>&& as_cont) {
21504 return push_rvalue(meta::all<std::is_rvalue_reference<T>, meta::neg<std::is_lvalue_reference<T>>>(), L, std::forward<T>(as_cont.value()));
21505 }
21506 };
21507
21508 template <typename T>
21509 struct unqualified_pusher<as_container_t<T*>> {
21510 using C = std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>>;
21511
21512 static int push(lua_State* L, T* cont) {
21513 stack_detail::metatable_setup<C> fx(L);
21514 return stack::push<detail::as_pointer_tag<T>>(L, detail::with_function_tag(), fx, cont);
21515 }
21516 };
21517
21518 template <typename T>
21519 struct unqualified_pusher<T, std::enable_if_t<is_container_v<T>>> {
21520 using C = T;
21521
21522 template <typename... Args>
21523 static int push(lua_State* L, Args&&... args) {
21524 stack_detail::metatable_setup<C> fx(L);
21525 return stack::push<detail::as_value_tag<T>>(L, detail::with_function_tag(), fx, std::forward<Args>(args)...);
21526 }
21527 };
21528
21529 template <typename T>
21530 struct unqualified_pusher<T*, std::enable_if_t<is_container_v<T>>> {
21531 using C = std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>>;
21532
21533 static int push(lua_State* L, T* cont) {
21534 stack_detail::metatable_setup<C> fx(L);
21535 return stack::push<detail::as_pointer_tag<T>>(L, detail::with_function_tag(), fx, cont);
21536 }
21537 };
21538 } // namespace stack
21539
21540} // namespace sol
21541
21542// end of sol/usertype_container_launch.hpp
21543
21544#include <sstream>
21545#include <type_traits>
21546
21547namespace sol {
21548 namespace u_detail {
21549 constexpr const lua_Integer toplevel_magic = static_cast<lua_Integer>(0xCCC2CCC1);
21550
21551 constexpr const int environment_index = 1;
21552 constexpr const int usertype_storage_index = 2;
21553 constexpr const int usertype_storage_base_index = 3;
21554 constexpr const int exact_function_index = 4;
21555 constexpr const int magic_index = 5;
21556
21557 constexpr const int simple_usertype_storage_index = 2;
21558 constexpr const int index_function_index = 3;
21559 constexpr const int new_index_function_index = 4;
21560
21561 constexpr const int base_walking_failed_index = -32467;
21562 constexpr const int lookup_failed_index = -42469;
21563
21564 enum class submetatable_type {
21565 // must be sequential
21566 value,
21567 reference,
21568 unique,
21569 const_reference,
21570 const_value,
21571 // must be LAST!
21572 named
21573 };
21574
21575 inline auto make_string_view(string_view s) {
21576 return s;
21577 }
21578
21579 inline auto make_string_view(call_construction) {
21580 return string_view(to_string(meta_function::call_function));
21581 }
21582
21583 inline auto make_string_view(meta_function mf) {
21584 return string_view(to_string(mf));
21585 }
21586
21587 inline auto make_string_view(base_classes_tag) {
21588 return string_view(detail::base_class_cast_key());
21589 }
21590
21591 template <typename Arg>
21592 inline std::string make_string(Arg&& arg) {
21593 string_view s = make_string_view(arg);
21594 return std::string(s.data(), s.size());
21595 }
21596
21597 inline int is_indexer(string_view s) {
21598 if (s == to_string(meta_function::index)) {
21599 return 1;
21600 }
21601 else if (s == to_string(meta_function::new_index)) {
21602 return 2;
21603 }
21604 return 0;
21605 }
21606
21607 inline int is_indexer(meta_function mf) {
21608 if (mf == meta_function::index) {
21609 return 1;
21610 }
21611 else if (mf == meta_function::new_index) {
21612 return 2;
21613 }
21614 return 0;
21615 }
21616
21617 inline int is_indexer(call_construction) {
21618 return 0;
21619 }
21620 } // namespace u_detail
21621
21622 namespace detail {
21623
21624 template <typename T, typename IFx, typename Fx>
21625 inline void insert_default_registrations(IFx&& ifx, Fx&& fx) {
21626 (void)ifx;
21627 (void)fx;
21628 if constexpr (is_automagical<T>::value) {
21629 if (fx(meta_function::less_than)) {
21630 if constexpr (meta::supports_op_less<T>::value) {
21631 lua_CFunction f = &comparsion_operator_wrap<T, std::less<>>;
21632 ifx(meta_function::less_than, f);
21633 }
21634 }
21635 if (fx(meta_function::less_than_or_equal_to)) {
21636 if constexpr (meta::supports_op_less_equal<T>::value) {
21637 lua_CFunction f = &comparsion_operator_wrap<T, std::less_equal<>>;
21638 ifx(meta_function::less_than_or_equal_to, f);
21639 }
21640 }
21641 if (fx(meta_function::equal_to)) {
21642 if constexpr (meta::supports_op_equal<T>::value) {
21643 lua_CFunction f = &comparsion_operator_wrap<T, std::equal_to<>>;
21644 ifx(meta_function::equal_to, f);
21645 }
21646 else {
21647 lua_CFunction f = &comparsion_operator_wrap<T, no_comp>;
21648 ifx(meta_function::equal_to, f);
21649 }
21650 }
21651 if (fx(meta_function::pairs)) {
21652 ifx(meta_function::pairs, &container_detail::u_c_launch<as_container_t<T>>::pairs_call);
21653 }
21654 if (fx(meta_function::length)) {
21655 if constexpr (meta::has_size<const T>::value || meta::has_size<T>::value) {
21656 auto f = &default_size<T>;
21657 ifx(meta_function::length, f);
21658 }
21659 }
21660 if (fx(meta_function::to_string)) {
21661 if constexpr (is_to_stringable<T>::value) {
21662 auto f = &detail::static_trampoline<&default_to_string<T>>;
21663 ifx(meta_function::to_string, f);
21664 }
21665 }
21666 if (fx(meta_function::call_function)) {
21667 if constexpr (meta::has_deducible_signature<T>::value) {
21668 auto f = &c_call<decltype(&T::operator()), &T::operator()>;
21669 ifx(meta_function::call_function, f);
21670 }
21671 }
21672 }
21673 }
21674 } // namespace detail
21675
21676 namespace stack { namespace stack_detail {
21677 template <typename X>
21678 void set_undefined_methods_on(stack_reference t) {
21679 using T = std::remove_pointer_t<X>;
21680
21681 lua_State* L = t.lua_state();
21682
21683 t.push();
21684
21685 detail::lua_reg_table l{};
21686 int index = 0;
21687 detail::indexed_insert insert_fx(l, index);
21688 detail::insert_default_registrations<T>(insert_fx, detail::property_always_true);
21689 if constexpr (!std::is_pointer_v<X>) {
21690 l[index] = luaL_Reg{ to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<T>() };
21691 }
21692 luaL_setfuncs(L, l, 0);
21693
21694 // __type table
21695 lua_createtable(L, 0, 2);
21696 const std::string& name = detail::demangle<T>();
21697 lua_pushlstring(L, name.c_str(), name.size());
21698 lua_setfield(L, -2, "name");
21699 lua_CFunction is_func = &detail::is_check<T>;
21700 lua_pushcclosure(L, is_func, 0);
21701 lua_setfield(L, -2, "is");
21702 lua_setfield(L, t.stack_index(), to_string(meta_function::type).c_str());
21703
21704 t.pop();
21705 }
21706 }} // namespace stack::stack_detail
21707} // namespace sol
21708
21709// end of sol/usertype_core.hpp
21710
21711// beginning of sol/usertype_storage.hpp
21712
21713#include <bitset>
21714#include <unordered_map>
21715
21716namespace sol { namespace u_detail {
21717
21718 struct usertype_storage_base;
21719 template <typename T>
21720 struct usertype_storage;
21721
21722 optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L, int index);
21723 usertype_storage_base& get_usertype_storage_base(lua_State* L, const char* gcmetakey);
21724 template <typename T>
21725 optional<usertype_storage<T>&> maybe_get_usertype_storage(lua_State* L);
21726 template <typename T>
21727 usertype_storage<T>& get_usertype_storage(lua_State* L);
21728
21729 using index_call_function = int(lua_State*, void*);
21730 using change_indexing_mem_func
21731 = void (usertype_storage_base::*)(lua_State*, submetatable_type, void*, stack_reference&, lua_CFunction, lua_CFunction, lua_CFunction, lua_CFunction);
21732
21733 struct index_call_storage {
21734 index_call_function* index;
21735 index_call_function* new_index;
21736 void* binding_data;
21737 };
21738
21739 struct new_index_call_storage : index_call_storage {
21740 void* new_binding_data;
21741 };
21742
21743 struct binding_base {
21744 virtual void* data() = 0;
21745 virtual ~binding_base() {
21746 }
21747 };
21748
21749 template <typename K, typename Fq, typename T = void>
21750 struct binding : binding_base {
21751 using uF = meta::unqualified_t<Fq>;
21752 using F = meta::conditional_t<meta::is_c_str_of_v<uF, char>
21753#ifdef __cpp_char8_t
21754 || meta::is_c_str_of_v<uF, char8_t>
21755#endif
21756 || meta::is_c_str_of_v<uF, char16_t> || meta::is_c_str_of_v<uF, char32_t> || meta::is_c_str_of_v<uF, wchar_t>,
21757 std::add_pointer_t<std::add_const_t<std::remove_all_extents_t<Fq>>>, std::decay_t<Fq>>;
21758 F data_;
21759
21760 template <typename... Args>
21761 binding(Args&&... args) : data_(std::forward<Args>(args)...) {
21762 }
21763
21764 virtual void* data() override {
21765 return static_cast<void*>(std::addressof(data_));
21766 }
21767
21768 template <bool is_index = true, bool is_variable = false>
21769 static inline int call_with_(lua_State* L, void* target) {
21770 constexpr int boost = !detail::is_non_factory_constructor<F>::value && std::is_same<K, call_construction>::value ? 1 : 0;
21771 auto& f = *static_cast<F*>(target);
21772 return call_detail::call_wrapped<T, is_index, is_variable, boost>(L, f);
21773 }
21774
21775 template <bool is_index = true, bool is_variable = false>
21776 static inline int call_(lua_State* L) {
21777 void* f = stack::get<void*>(L, upvalue_index(usertype_storage_index));
21778 return call_with_<is_index, is_variable>(L, f);
21779 }
21780
21781 template <bool is_index = true, bool is_variable = false>
21782 static inline int call(lua_State* L) {
21783 int r = detail::typed_static_trampoline<decltype(&call_<is_index, is_variable>), (&call_<is_index, is_variable>)>(L);
21784 if constexpr (meta::is_specialization_of_v<uF, yielding_t>) {
21785 return lua_yield(L, r);
21786 }
21787 else {
21788 return r;
21789 }
21790 }
21791
21792 template <bool is_index = true, bool is_variable = false>
21793 static inline int index_call_with_(lua_State* L, void* target) {
21794 if constexpr (!is_variable) {
21795 if constexpr (is_lua_c_function_v<std::decay_t<F>>) {
21796 auto& f = *static_cast<std::decay_t<F>*>(target);
21797 return stack::push(L, f);
21798 }
21799 else {
21800 // set up upvalues
21801 // for a chained call
21802 int upvalues = 0;
21803 upvalues += stack::push(L, nullptr);
21804 upvalues += stack::push(L, target);
21805 auto cfunc = &call<is_index, is_variable>;
21806 return stack::push(L, c_closure(cfunc, upvalues));
21807 }
21808 }
21809 else {
21810 constexpr int boost = !detail::is_non_factory_constructor<F>::value && std::is_same<K, call_construction>::value ? 1 : 0;
21811 auto& f = *static_cast<F*>(target);
21812 return call_detail::call_wrapped<T, is_index, is_variable, boost>(L, f);
21813 }
21814 }
21815
21816 template <bool is_index = true, bool is_variable = false>
21817 static inline int index_call_(lua_State* L) {
21818 void* f = stack::get<void*>(L, upvalue_index(usertype_storage_index));
21819 return index_call_with_<is_index, is_variable>(L, f);
21820 }
21821
21822 template <bool is_index = true, bool is_variable = false>
21823 static inline int index_call(lua_State* L) {
21824 int r = detail::typed_static_trampoline<decltype(&index_call_<is_index, is_variable>), (&index_call_<is_index, is_variable>)>(L);
21825 if constexpr (meta::is_specialization_of_v<uF, yielding_t>) {
21826 return lua_yield(L, r);
21827 }
21828 else {
21829 return r;
21830 }
21831 }
21832 };
21833
21834 inline int index_fail(lua_State* L) {
21835 if (lua_getmetatable(L, 1) == 1) {
21836 int metatarget = lua_gettop(L);
21837 stack::get_field<false, true>(L, stack_reference(L, raw_index(2)), metatarget);
21838 return 1;
21839 }
21840 // With runtime extensibility, we can't
21841 // hard-error things. They have to
21842 // return nil, like regular table types
21843 return stack::push(L, lua_nil);
21844 }
21845
21846 inline int index_target_fail(lua_State* L, void*) {
21847 return index_fail(L);
21848 }
21849
21850 inline int new_index_fail(lua_State* L) {
21851 return luaL_error(L, "sol: cannot set (new_index) into this object: no defined new_index operation on usertype");
21852 }
21853
21854 inline int new_index_target_fail(lua_State* L, void*) {
21855 return new_index_fail(L);
21856 }
21857
21858 struct string_for_each_metatable_func {
21859 bool is_destruction = false;
21860 bool is_index = false;
21861 bool is_new_index = false;
21862 bool is_static_index = false;
21863 bool is_static_new_index = false;
21864 bool poison_indexing = false;
21865 bool is_unqualified_lua_CFunction = false;
21866 bool is_unqualified_lua_reference = false;
21867 std::string* p_key = nullptr;
21868 reference* p_binding_ref = nullptr;
21869 lua_CFunction call_func = nullptr;
21870 index_call_storage* p_ics = nullptr;
21871 usertype_storage_base* p_usb = nullptr;
21872 void* p_derived_usb = nullptr;
21873 lua_CFunction idx_call = nullptr, new_idx_call = nullptr, meta_idx_call = nullptr, meta_new_idx_call = nullptr;
21874 change_indexing_mem_func change_indexing;
21875
21876 void operator()(lua_State* L, submetatable_type smt, reference& fast_index_table) {
21877 std::string& key = *p_key;
21878 usertype_storage_base& usb = *p_usb;
21879 index_call_storage& ics = *p_ics;
21880
21881 if (smt == submetatable_type::named) {
21882 // do not override __call or
21883 // other specific meta functions on named metatable:
21884 // we need that for call construction
21885 // and other amenities
21886 return;
21887 }
21888 int fast_index_table_push = fast_index_table.push();
21889 stack_reference t(L, -fast_index_table_push);
21890 if (poison_indexing) {
21891 (usb.*change_indexing)(L, smt, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call);
21892 }
21893 if (is_destruction
21894 && (smt == submetatable_type::reference || smt == submetatable_type::const_reference || smt == submetatable_type::named
21895 || smt == submetatable_type::unique)) {
21896 // gc does not apply to us here
21897 // for reference types (raw T*, std::ref)
21898 // for the named metatable itself,
21899 // or for unique_usertypes, which do their own custom destruction
21900 t.pop();
21901 return;
21902 }
21903 if (is_index || is_new_index || is_static_index || is_static_new_index) {
21904 // do not serialize the new_index and index functions here directly
21905 // we control those...
21906 t.pop();
21907 return;
21908 }
21909 if (is_unqualified_lua_CFunction) {
21910 stack::set_field<false, true>(L, key, call_func, t.stack_index());
21911 }
21912 else if (is_unqualified_lua_reference) {
21913 reference& binding_ref = *p_binding_ref;
21914 stack::set_field<false, true>(L, key, binding_ref, t.stack_index());
21915 }
21916 else {
21917 stack::set_field<false, true>(L, key, make_closure(call_func, nullptr, ics.binding_data), t.stack_index());
21918 }
21919 t.pop();
21920 }
21921 };
21922
21923 struct lua_reference_func {
21924 reference key;
21925 reference value;
21926
21927 void operator()(lua_State* L, submetatable_type smt, reference& fast_index_table) {
21928 if (smt == submetatable_type::named) {
21929 return;
21930 }
21931 int fast_index_table_push = fast_index_table.push();
21932 stack_reference t(L, -fast_index_table_push);
21933 stack::set_field<false, true>(L, key, value, t.stack_index());
21934 t.pop();
21935 }
21936 };
21937
21938 struct update_bases_func {
21939 detail::inheritance_check_function base_class_check_func;
21940 detail::inheritance_cast_function base_class_cast_func;
21941 lua_CFunction idx_call, new_idx_call, meta_idx_call, meta_new_idx_call;
21942 usertype_storage_base* p_usb;
21943 void* p_derived_usb;
21944 change_indexing_mem_func change_indexing;
21945
21946 void operator()(lua_State* L, submetatable_type smt, reference& fast_index_table) {
21947 int fast_index_table_push = fast_index_table.push();
21948 stack_reference t(L, -fast_index_table_push);
21949 stack::set_field(L, detail::base_class_check_key(), reinterpret_cast<void*>(base_class_check_func), t.stack_index());
21950 stack::set_field(L, detail::base_class_cast_key(), reinterpret_cast<void*>(base_class_cast_func), t.stack_index());
21951 // change indexing, forcefully
21952 (p_usb->*change_indexing)(L, smt, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call);
21953 t.pop();
21954 }
21955 };
21956
21957 struct binding_data_equals {
21958 void* binding_data;
21959
21960 binding_data_equals(void* b) : binding_data(b) {
21961 }
21962
21963 bool operator()(const std::unique_ptr<binding_base>& ptr) const {
21964 return binding_data == ptr->data();
21965 }
21966 };
21967
21968 struct usertype_storage_base {
21969 public:
21970 std::vector<std::unique_ptr<binding_base>> storage;
21971 std::vector<std::unique_ptr<char[]>> string_keys_storage;
21972 std::unordered_map<string_view, index_call_storage> string_keys;
21973 std::unordered_map<reference, reference, reference_hash, reference_equals> auxiliary_keys;
21974 reference value_index_table;
21975 reference reference_index_table;
21976 reference unique_index_table;
21977 reference const_reference_index_table;
21978 reference const_value_index_table;
21979 reference named_index_table;
21980 reference type_table;
21981 reference gc_names_table;
21982 reference named_metatable;
21983 new_index_call_storage base_index;
21984 new_index_call_storage static_base_index;
21985 bool is_using_index;
21986 bool is_using_new_index;
21987 std::bitset<64> properties;
21988
21989 usertype_storage_base(lua_State* L)
21990 : storage()
21991 , string_keys()
21992 , auxiliary_keys()
21993 , value_index_table()
21994 , reference_index_table()
21995 , unique_index_table()
21996 , const_reference_index_table()
21997 , type_table(make_reference(L, create))
21998 , gc_names_table(make_reference(L, create))
21999 , named_metatable(make_reference(L, create))
22000 , base_index()
22001 , static_base_index()
22002 , is_using_index(false)
22003 , is_using_new_index(false)
22004 , properties() {
22005 base_index.binding_data = nullptr;
22006 base_index.index = index_target_fail;
22007 base_index.new_index = new_index_target_fail;
22008 base_index.new_binding_data = nullptr;
22009 static_base_index.binding_data = nullptr;
22010 static_base_index.index = index_target_fail;
22011 static_base_index.new_binding_data = this;
22012 static_base_index.new_index = new_index_target_set;
22013 }
22014
22015 template <typename Fx>
22016 void for_each_table(lua_State* L, Fx&& fx) {
22017 for (int i = 0; i < 6; ++i) {
22018 submetatable_type smt = static_cast<submetatable_type>(i);
22019 reference* p_fast_index_table = nullptr;
22020 switch (smt) {
22021 case submetatable_type::const_value:
22022 p_fast_index_table = &this->const_value_index_table;
22023 break;
22024 case submetatable_type::reference:
22025 p_fast_index_table = &this->reference_index_table;
22026 break;
22027 case submetatable_type::unique:
22028 p_fast_index_table = &this->unique_index_table;
22029 break;
22030 case submetatable_type::const_reference:
22031 p_fast_index_table = &this->const_reference_index_table;
22032 break;
22033 case submetatable_type::named:
22034 p_fast_index_table = &this->named_index_table;
22035 break;
22036 case submetatable_type::value:
22037 default:
22038 p_fast_index_table = &this->value_index_table;
22039 break;
22040 }
22041 fx(L, smt, *p_fast_index_table);
22042 }
22043 }
22044
22045 void add_entry(string_view sv, index_call_storage ics) {
22046 string_keys_storage.emplace_back(new char[sv.size()]);
22047 std::unique_ptr<char[]>& sv_storage = string_keys_storage.back();
22048 std::memcpy(sv_storage.get(), sv.data(), sv.size());
22049 string_view stored_sv(sv_storage.get(), sv.size());
22050 string_keys.insert_or_assign(std::move(stored_sv), std::move(ics));
22051 }
22052
22053 template <typename T, typename... Bases>
22054 void update_bases(lua_State* L, bases<Bases...>) {
22055 static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function),
22056 "The size of this data pointer is too small to fit the inheritance checking function: Please file "
22057 "a bug report.");
22058 static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function),
22059 "The size of this data pointer is too small to fit the inheritance checking function: Please file "
22060 "a bug report.");
22061 static_assert(!meta::any_same<T, Bases...>::value, "base classes cannot list the original class as part of the bases");
22062 if constexpr (sizeof...(Bases) < 1) {
22063 return;
22064 }
22065
22066 (void)detail::swallow { 0, ((weak_derive<Bases>::value = true), 0)... };
22067
22068 void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this));
22069
22070 update_bases_func for_each_fx;
22071 for_each_fx.base_class_check_func = &detail::inheritance<T>::template type_check_with<Bases...>;
22072 for_each_fx.base_class_cast_func = &detail::inheritance<T>::template type_cast_with<Bases...>;
22073 for_each_fx.idx_call = &usertype_storage<T>::template index_call_with_bases<false, Bases...>;
22074 for_each_fx.new_idx_call = &usertype_storage<T>::template index_call_with_bases<true, Bases...>;
22075 for_each_fx.meta_idx_call = &usertype_storage<T>::template meta_index_call_with_bases<false, Bases...>;
22076 for_each_fx.meta_new_idx_call = &usertype_storage<T>::template meta_index_call_with_bases<true, Bases...>;
22077 for_each_fx.p_usb = this;
22078 for_each_fx.p_derived_usb = derived_this;
22079 for_each_fx.change_indexing = &usertype_storage_base::change_indexing;
22080 for_each_fx.p_derived_usb = derived_this;
22081 this->for_each_table(L, for_each_fx);
22082 }
22083
22084 void clear() {
22085 if (value_index_table.valid()) {
22086 stack::clear(value_index_table);
22087 }
22088 if (reference_index_table.valid()) {
22089 stack::clear(reference_index_table);
22090 }
22091 if (unique_index_table.valid()) {
22092 stack::clear(unique_index_table);
22093 }
22094 if (const_reference_index_table.valid()) {
22095 stack::clear(const_reference_index_table);
22096 }
22097 if (const_value_index_table.valid()) {
22098 stack::clear(const_value_index_table);
22099 }
22100 if (named_index_table.valid()) {
22101 stack::clear(named_index_table);
22102 }
22103 if (type_table.valid()) {
22104 stack::clear(type_table);
22105 }
22106 if (gc_names_table.valid()) {
22107 stack::clear(gc_names_table);
22108 }
22109 if (named_metatable.valid()) {
22110 lua_State* L = named_metatable.lua_state();
22111 auto pp = stack::push_pop(named_metatable);
22112 int named_metatable_index = pp.index_of(named_metatable);
22113 if (lua_getmetatable(L, named_metatable_index) == 1) {
22114 stack::clear(L, absolute_index(L, -1));
22115 }
22116 stack::clear(named_metatable);
22117 }
22118
22119 value_index_table = lua_nil;
22120 reference_index_table = lua_nil;
22121 unique_index_table = lua_nil;
22122 const_reference_index_table = lua_nil;
22123 const_value_index_table = lua_nil;
22124 named_index_table = lua_nil;
22125 type_table = lua_nil;
22126 gc_names_table = lua_nil;
22127 named_metatable = lua_nil;
22128
22129 storage.clear();
22130 string_keys.clear();
22131 auxiliary_keys.clear();
22132 }
22133
22134 template <bool is_new_index, typename Base>
22135 static void base_walk_index(lua_State* L, usertype_storage_base& self, bool& keep_going, int& base_result) {
22136 using bases = typename base<Base>::type;
22137 if (!keep_going) {
22138 return;
22139 }
22140 (void)L;
22141 (void)self;
22142#if SOL_IS_ON(SOL_USE_UNSAFE_BASE_LOOKUP_I_)
22143 usertype_storage_base& base_storage = get_usertype_storage<Base>(L);
22144 base_result = self_index_call<is_new_index, true>(bases(), L, base_storage);
22145#else
22146 optional<usertype_storage<Base>&> maybe_base_storage = maybe_get_usertype_storage<Base>(L);
22147 if (static_cast<bool>(maybe_base_storage)) {
22148 base_result = self_index_call<is_new_index, true>(bases(), L, *maybe_base_storage);
22149 keep_going = base_result == base_walking_failed_index;
22150 }
22151#endif // Fast versus slow, safe base lookup
22152 }
22153
22154 template <bool is_new_index = false, bool base_walking = false, bool from_named_metatable = false, typename... Bases>
22155 static inline int self_index_call(types<Bases...>, lua_State* L, usertype_storage_base& self) {
22156 type k_type = stack::get<type>(L, 2);
22157 if (k_type == type::string) {
22158 index_call_storage* target = nullptr;
22159 {
22160 string_view k = stack::get<string_view>(L, 2);
22161 auto it = self.string_keys.find(k);
22162 if (it != self.string_keys.cend()) {
22163 target = &it->second;
22164 }
22165 }
22166 if (target != nullptr) {
22167 // let the target decide what to do
22168 if constexpr (is_new_index) {
22169 return (target->new_index)(L, target->binding_data);
22170 }
22171 else {
22172 return (target->index)(L, target->binding_data);
22173 }
22174 }
22175 }
22176 else if (k_type != type::lua_nil && k_type != type::none) {
22177 reference* target = nullptr;
22178 {
22179 stack_reference k = stack::get<stack_reference>(L, 2);
22180 auto it = self.auxiliary_keys.find(k);
22181 if (it != self.auxiliary_keys.cend()) {
22182 target = &it->second;
22183 }
22184 }
22185 if (target != nullptr) {
22186 if constexpr (is_new_index) {
22187 // set value and return
22188 *target = reference(L, 3);
22189 return 0;
22190 }
22191 else {
22192 // push target to return
22193 // what we found
22194 return stack::push(L, *target);
22195 }
22196 }
22197 }
22198
22199 // retrieve bases and walk through them.
22200 bool keep_going = true;
22201 int base_result;
22202 (void)keep_going;
22203 (void)base_result;
22204 (void)detail::swallow { 1, (base_walk_index<is_new_index, Bases>(L, self, keep_going, base_result), 1)... };
22205 if constexpr (sizeof...(Bases) > 0) {
22206 if (!keep_going) {
22207 return base_result;
22208 }
22209 }
22210 if constexpr (base_walking) {
22211 // if we're JUST base-walking then don't index-fail, just
22212 // return the false bits
22213 return base_walking_failed_index;
22214 }
22215 else if constexpr (from_named_metatable) {
22216 if constexpr (is_new_index) {
22217 return self.static_base_index.new_index(L, self.static_base_index.new_binding_data);
22218 }
22219 else {
22220 return self.static_base_index.index(L, self.static_base_index.binding_data);
22221 }
22222 }
22223 else {
22224 if constexpr (is_new_index) {
22225 return self.base_index.new_index(L, self.base_index.new_binding_data);
22226 }
22227 else {
22228 return self.base_index.index(L, self.base_index.binding_data);
22229 }
22230 }
22231 }
22232
22233 void change_indexing(lua_State* L, submetatable_type submetatable, void* derived_this, stack_reference& t, lua_CFunction index,
22234 lua_CFunction new_index, lua_CFunction meta_index, lua_CFunction meta_new_index) {
22235 usertype_storage_base& this_base = *this;
22236 void* base_this = static_cast<void*>(&this_base);
22237
22238 this->is_using_index |= true;
22239 this->is_using_new_index |= true;
22240 if (submetatable == submetatable_type::named) {
22241 stack::set_field(L, metatable_key, named_index_table, t.stack_index());
22242 stack_reference stack_metametatable(L, -named_metatable.push());
22243 stack::set_field<false, true>(L,
22244 meta_function::index,
22245 make_closure(meta_index, nullptr, derived_this, base_this, nullptr, toplevel_magic),
22246 stack_metametatable.stack_index());
22247 stack::set_field<false, true>(L,
22248 meta_function::new_index,
22249 make_closure(meta_new_index, nullptr, derived_this, base_this, nullptr, toplevel_magic),
22250 stack_metametatable.stack_index());
22251 stack_metametatable.pop();
22252 }
22253 else {
22254 stack::set_field<false, true>(
22255 L, meta_function::index, make_closure(index, nullptr, derived_this, base_this, nullptr, toplevel_magic), t.stack_index());
22256 stack::set_field<false, true>(
22257 L, meta_function::new_index, make_closure(new_index, nullptr, derived_this, base_this, nullptr, toplevel_magic), t.stack_index());
22258 }
22259 }
22260
22261 template <typename T = void, typename Key, typename Value>
22262 void set(lua_State* L, Key&& key, Value&& value);
22263
22264 static int new_index_target_set(lua_State* L, void* target) {
22265 usertype_storage_base& self = *static_cast<usertype_storage_base*>(target);
22266 self.set(L, reference(L, raw_index(2)), reference(L, raw_index(3)));
22267 return 0;
22268 }
22269 };
22270
22271 template <typename T>
22272 struct usertype_storage : usertype_storage_base {
22273
22274 using usertype_storage_base::usertype_storage_base;
22275
22276 template <bool is_new_index, bool from_named_metatable>
22277 static inline int index_call_(lua_State* L) {
22278 using bases = typename base<T>::type;
22279 usertype_storage_base& self = stack::get<light<usertype_storage_base>>(L, upvalue_index(usertype_storage_index));
22280 return self_index_call<is_new_index, false, from_named_metatable>(bases(), L, self);
22281 }
22282
22283 template <bool is_new_index, bool from_named_metatable, typename... Bases>
22284 static inline int index_call_with_bases_(lua_State* L) {
22285 using bases = types<Bases...>;
22286 usertype_storage_base& self = stack::get<light<usertype_storage_base>>(L, upvalue_index(usertype_storage_index));
22287 return self_index_call<is_new_index, false, from_named_metatable>(bases(), L, self);
22288 }
22289
22290 template <bool is_new_index>
22291 static inline int index_call(lua_State* L) {
22292 return detail::static_trampoline<&index_call_<is_new_index, false>>(L);
22293 }
22294
22295 template <bool is_new_index, typename... Bases>
22296 static inline int index_call_with_bases(lua_State* L) {
22297 return detail::static_trampoline<&index_call_with_bases_<is_new_index, false, Bases...>>(L);
22298 }
22299
22300 template <bool is_new_index>
22301 static inline int meta_index_call(lua_State* L) {
22302 return detail::static_trampoline<&index_call_<is_new_index, true>>(L);
22303 }
22304
22305 template <bool is_new_index, typename... Bases>
22306 static inline int meta_index_call_with_bases(lua_State* L) {
22307 return detail::static_trampoline<&index_call_with_bases_<is_new_index, true, Bases...>>(L);
22308 }
22309
22310 template <typename Key, typename Value>
22311 inline void set(lua_State* L, Key&& key, Value&& value);
22312 };
22313
22314 template <typename T>
22315 inline int destruct_usertype_storage(lua_State* L) {
22316 return detail::user_alloc_destruct<usertype_storage<T>>(L);
22317 }
22318
22319 template <typename T, typename Key, typename Value>
22320 void usertype_storage_base::set(lua_State* L, Key&& key, Value&& value) {
22321 using ValueU = meta::unwrap_unqualified_t<Value>;
22322 using KeyU = meta::unwrap_unqualified_t<Key>;
22323 using Binding = binding<KeyU, ValueU, T>;
22324 using is_var_bind = is_variable_binding<ValueU>;
22325 if constexpr (std::is_same_v<KeyU, call_construction>) {
22326 (void)key;
22327 std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
22328 Binding& b = *p_binding;
22329 this->storage.push_back(std::move(p_binding));
22330
22331 this->named_index_table.push();
22332 absolute_index metametatable_index(L, -1);
22333 stack::push(L, nullptr);
22334 stack::push(L, b.data());
22335 lua_CFunction target_func = &b.template call<false, false>;
22336 lua_pushcclosure(L, target_func, 2);
22337 lua_setfield(L, metametatable_index, to_string(meta_function::call).c_str());
22338 this->named_index_table.pop();
22339 }
22340 else if constexpr (std::is_same_v<KeyU, base_classes_tag>) {
22341 (void)key;
22342 this->update_bases<T>(L, std::forward<Value>(value));
22343 }
22344 else if constexpr ((meta::is_string_like_or_constructible<KeyU>::value || std::is_same_v<KeyU, meta_function>)) {
22345 std::string s = u_detail::make_string(std::forward<Key>(key));
22346 auto storage_it = this->storage.end();
22347 auto string_it = this->string_keys.find(s);
22348 if (string_it != this->string_keys.cend()) {
22349 const auto& binding_data = string_it->second.binding_data;
22350 storage_it = std::find_if(this->storage.begin(), this->storage.end(), binding_data_equals(binding_data));
22351 this->string_keys.erase(string_it);
22352 }
22353
22354 std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
22355 Binding& b = *p_binding;
22356 if (storage_it != this->storage.cend()) {
22357 *storage_it = std::move(p_binding);
22358 }
22359 else {
22360 this->storage.push_back(std::move(p_binding));
22361 }
22362
22363 bool is_index = (s == to_string(meta_function::index));
22364 bool is_new_index = (s == to_string(meta_function::new_index));
22365 bool is_static_index = (s == to_string(meta_function::static_index));
22366 bool is_static_new_index = (s == to_string(meta_function::static_new_index));
22367 bool is_destruction = s == to_string(meta_function::garbage_collect);
22368 bool poison_indexing = (!is_using_index || !is_using_new_index) && (is_var_bind::value || is_index || is_new_index);
22369 void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this));
22370 index_call_storage ics;
22371 ics.binding_data = b.data();
22372 ics.index = is_index || is_static_index ? &Binding::template call_with_<true, is_var_bind::value>
22373 : &Binding::template index_call_with_<true, is_var_bind::value>;
22374 ics.new_index = is_new_index || is_static_new_index ? &Binding::template call_with_<false, is_var_bind::value>
22375 : &Binding::template index_call_with_<false, is_var_bind::value>;
22376
22377 string_for_each_metatable_func for_each_fx;
22378 for_each_fx.is_destruction = is_destruction;
22379 for_each_fx.is_index = is_index;
22380 for_each_fx.is_new_index = is_new_index;
22381 for_each_fx.is_static_index = is_static_index;
22382 for_each_fx.is_static_new_index = is_static_new_index;
22383 for_each_fx.poison_indexing = poison_indexing;
22384 for_each_fx.p_key = &s;
22385 for_each_fx.p_ics = &ics;
22386 if constexpr (is_lua_c_function_v<ValueU>) {
22387 for_each_fx.is_unqualified_lua_CFunction = true;
22388 for_each_fx.call_func = *static_cast<lua_CFunction*>(ics.binding_data);
22389 }
22390 else if constexpr (is_lua_reference_or_proxy_v<ValueU>) {
22391 for_each_fx.is_unqualified_lua_reference = true;
22392 for_each_fx.p_binding_ref = static_cast<reference*>(ics.binding_data);
22393 }
22394 else {
22395 for_each_fx.call_func = &b.template call<false, is_var_bind::value>;
22396 }
22397 for_each_fx.p_usb = this;
22398 for_each_fx.p_derived_usb = derived_this;
22399 for_each_fx.idx_call = &usertype_storage<T>::template index_call<false>;
22400 for_each_fx.new_idx_call = &usertype_storage<T>::template index_call<true>;
22401 for_each_fx.meta_idx_call = &usertype_storage<T>::template meta_index_call<false>;
22402 for_each_fx.meta_new_idx_call = &usertype_storage<T>::template meta_index_call<true>;
22403 for_each_fx.change_indexing = &usertype_storage_base::change_indexing;
22404 // set base index and base new_index
22405 // functions here
22406 if (is_index) {
22407 this->base_index.index = ics.index;
22408 this->base_index.binding_data = ics.binding_data;
22409 }
22410 if (is_new_index) {
22411 this->base_index.new_index = ics.new_index;
22412 this->base_index.new_binding_data = ics.binding_data;
22413 }
22414 if (is_static_index) {
22415 this->static_base_index.index = ics.index;
22416 this->static_base_index.binding_data = ics.binding_data;
22417 }
22418 if (is_static_new_index) {
22419 this->static_base_index.new_index = ics.new_index;
22420 this->static_base_index.new_binding_data = ics.binding_data;
22421 }
22422 this->for_each_table(L, for_each_fx);
22423 this->add_entry(s, std::move(ics));
22424 }
22425 else {
22426 // the reference-based implementation might compare poorly and hash
22427 // poorly in some cases...
22428 if constexpr (is_lua_reference_v<KeyU> && is_lua_reference_v<ValueU>) {
22429 if (key.get_type() == type::string) {
22430 stack::push(L, key);
22431 std::string string_key = stack::pop<std::string>(L);
22432 this->set<T>(L, string_key, std::forward<Value>(value));
22433 }
22434 else {
22435 lua_reference_func ref_additions_fx { key, value };
22436
22437 this->for_each_table(L, ref_additions_fx);
22438 this->auxiliary_keys.insert_or_assign(std::forward<Key>(key), std::forward<Value>(value));
22439 }
22440 }
22441 else {
22442 reference ref_key = make_reference(L, std::forward<Key>(key));
22443 reference ref_value = make_reference(L, std::forward<Value>(value));
22444 lua_reference_func ref_additions_fx { key, value };
22445
22446 this->for_each_table(L, ref_additions_fx);
22447 this->auxiliary_keys.insert_or_assign(std::move(ref_key), std::move(ref_value));
22448 }
22449 }
22450 }
22451
22452 template <typename T>
22453 template <typename Key, typename Value>
22454 void usertype_storage<T>::set(lua_State* L, Key&& key, Value&& value) {
22455 static_cast<usertype_storage_base&>(*this).set<T>(L, std::forward<Key>(key), std::forward<Value>(value));
22456 }
22457
22458 template <typename T>
22459 inline usertype_storage<T>& create_usertype_storage(lua_State* L) {
22460 const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
22461
22462 // Make sure userdata's memory is properly in lua first,
22463 // otherwise all the light userdata we make later will become invalid
22464 int usertype_storage_push_count = stack::push<user<usertype_storage<T>>>(L, no_metatable, L);
22465 stack_reference usertype_storage_ref(L, -usertype_storage_push_count);
22466
22467 // create and push onto the stack a table to use as metatable for this GC
22468 // we create a metatable to attach to the regular gc_table
22469 // so that the destructor is called for the usertype storage
22470 int usertype_storage_metatabe_count = stack::push(L, new_table(0, 1));
22471 stack_reference usertype_storage_metatable(L, -usertype_storage_metatabe_count);
22472 // set the destruction routine on the metatable
22473 stack::set_field(L, meta_function::garbage_collect, &destruct_usertype_storage<T>, usertype_storage_metatable.stack_index());
22474 // set the metatable on the usertype storage userdata
22475 stack::set_field(L, metatable_key, usertype_storage_metatable, usertype_storage_ref.stack_index());
22476 usertype_storage_metatable.pop();
22477
22478 // set the usertype storage and its metatable
22479 // into the global table...
22480 stack::set_field<true>(L, gcmetakey, usertype_storage_ref);
22481 usertype_storage_ref.pop();
22482
22483 // then retrieve the lua-stored version so we have a well-pinned
22484 // reference that does not die
22485 stack::get_field<true>(L, gcmetakey);
22486 usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L);
22487 return target_umt;
22488 }
22489
22490 inline optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L, int index) {
22491 stack::record tracking;
22492 if (!stack::check<user<usertype_storage_base>>(L, index)) {
22493 return nullopt;
22494 }
22495 usertype_storage_base& target_umt = stack::stack_detail::unchecked_unqualified_get<user<usertype_storage_base>>(L, -1, tracking);
22496 return target_umt;
22497 }
22498
22499 inline optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L, const char* gcmetakey) {
22500 stack::get_field<true>(L, gcmetakey);
22501 auto maybe_storage = maybe_get_usertype_storage_base(L, lua_gettop(L));
22502 lua_pop(L, 1);
22503 return maybe_storage;
22504 }
22505
22506 inline usertype_storage_base& get_usertype_storage_base(lua_State* L, const char* gcmetakey) {
22507 stack::get_field<true>(L, gcmetakey);
22508 stack::record tracking;
22509 usertype_storage_base& target_umt = stack::stack_detail::unchecked_unqualified_get<user<usertype_storage_base>>(L, -1, tracking);
22510 lua_pop(L, 1);
22511 return target_umt;
22512 }
22513
22514 template <typename T>
22515 inline optional<usertype_storage<T>&> maybe_get_usertype_storage(lua_State* L) {
22516 const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
22517 stack::get_field<true>(L, gcmetakey);
22518 int target = lua_gettop(L);
22519 if (!stack::check<user<usertype_storage<T>>>(L, target)) {
22520 return nullopt;
22521 }
22522 usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L);
22523 return target_umt;
22524 }
22525
22526 template <typename T>
22527 inline usertype_storage<T>& get_usertype_storage(lua_State* L) {
22528 const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
22529 stack::get_field<true>(L, gcmetakey);
22530 usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L);
22531 return target_umt;
22532 }
22533
22534 template <typename T>
22535 inline void delete_usertype_storage(lua_State* L) {
22536 using u_traits = usertype_traits<T>;
22537#if 0
22538 using u_const_traits = usertype_traits<const T>;
22539 using u_unique_traits = usertype_traits<detail::unique_usertype<T>>;
22540 using u_ref_traits = usertype_traits<T*>;
22541 using u_const_ref_traits = usertype_traits<T const*>;
22542#endif
22543 using uts = usertype_storage<T>;
22544
22545 const char* gcmetakey = &u_traits::gc_table()[0];
22546 stack::get_field<true>(L, gcmetakey);
22547 if (!stack::check<user<uts>>(L)) {
22548 lua_pop(L, 1);
22549 return;
22550 }
22551 usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L);
22552 target_umt.clear();
22553
22554 // get the registry
22555#if 0
22556 stack_reference registry(L, raw_index(LUA_REGISTRYINDEX));
22557 registry.push();
22558 // eliminate all named entries for this usertype
22559 // in the registry (luaL_newmetatable does
22560 // [name] = new table
22561 // in registry upon creation
22562 stack::set_field(L, &u_traits::metatable()[0], lua_nil, registry.stack_index());
22563 stack::set_field(L, &u_const_traits::metatable()[0], lua_nil, registry.stack_index());
22564 stack::set_field(L, &u_const_ref_traits::metatable()[0], lua_nil, registry.stack_index());
22565 stack::set_field(L, &u_ref_traits::metatable()[0], lua_nil, registry.stack_index());
22566 stack::set_field(L, &u_unique_traits::metatable()[0], lua_nil, registry.stack_index());
22567 registry.pop();
22568#endif // Registry Cleanout
22569
22570 stack::set_field<true>(L, gcmetakey, lua_nil);
22571 }
22572
22573 template <typename T>
22574 inline int register_usertype(lua_State* L, automagic_enrollments enrollments = {}) {
22575 using u_traits = usertype_traits<T>;
22576 using u_const_traits = usertype_traits<const T>;
22577 using u_unique_traits = usertype_traits<detail::unique_usertype<T>>;
22578 using u_ref_traits = usertype_traits<T*>;
22579 using u_const_ref_traits = usertype_traits<T const*>;
22580 using uts = usertype_storage<T>;
22581
22582 // always have __new_index point to usertype_storage method
22583 // have __index always point to regular fast-lookup
22584 // meta_method table
22585 // if __new_index is invoked, runtime-swap
22586 // to slow __index if necessary
22587 // (no speed penalty because function calls
22588 // are all read-only -- only depend on __index
22589 // to retrieve function and then call happens VIA Lua)
22590
22591 // __type entry:
22592 // table contains key -> value lookup,
22593 // where key is entry in metatable
22594 // and value is type information as a string as
22595 // best as we can give it
22596
22597 // name entry:
22598 // string that contains raw class name,
22599 // as defined from C++
22600
22601 // is entry:
22602 // checks if argument supplied is of type T
22603
22604 // __storage entry:
22605 // a light userdata pointing to the storage
22606 // mostly to enable this new abstraction
22607 // to not require the type name `T`
22608 // to get at the C++ usertype storage within
22609
22610 // we then let typical definitions potentially override these intrinsics
22611 // it's the user's fault if they override things or screw them up:
22612 // these names have been reserved and documented since sol3
22613
22614 // STEP 0: tell the old usertype (if it exists)
22615 // to fuck off
22616 delete_usertype_storage<T>(L);
22617
22618 // STEP 1: Create backing store for usertype storage
22619 // Pretty much the most important step.
22620 // STEP 2: Create Lua tables used for fast method indexing.
22621 // This is done inside of the storage table's constructor
22622 usertype_storage<T>& storage = create_usertype_storage<T>(L);
22623 usertype_storage_base& base_storage = storage;
22624 void* light_storage = static_cast<void*>(&storage);
22625 void* light_base_storage = static_cast<void*>(&base_storage);
22626
22627 // STEP 3: set up GC escape hatch table entirely
22628 storage.gc_names_table.push();
22629 stack_reference gnt(L, -1);
22630 stack::set_field(L, submetatable_type::named, &u_traits::gc_table()[0], gnt.stack_index());
22631 stack::set_field(L, submetatable_type::const_value, &u_const_traits::metatable()[0], gnt.stack_index());
22632 stack::set_field(L, submetatable_type::const_reference, &u_const_ref_traits::metatable()[0], gnt.stack_index());
22633 stack::set_field(L, submetatable_type::reference, &u_ref_traits::metatable()[0], gnt.stack_index());
22634 stack::set_field(L, submetatable_type::unique, &u_unique_traits::metatable()[0], gnt.stack_index());
22635 stack::set_field(L, submetatable_type::value, &u_traits::metatable()[0], gnt.stack_index());
22636 gnt.pop();
22637
22638 // STEP 4: add some useful information to the type table
22639 stack_reference stacked_type_table(L, -storage.type_table.push());
22640 stack::set_field(L, "name", detail::demangle<T>(), stacked_type_table.stack_index());
22641 stack::set_field(L, "is", &detail::is_check<T>, stacked_type_table.stack_index());
22642 stacked_type_table.pop();
22643
22644 // STEP 5: create and hook up metatable,
22645 // add intrinsics
22646 // this one is the actual meta-handling table,
22647 // the next one will be the one for
22648 int for_each_backing_metatable_calls = 0;
22649 auto for_each_backing_metatable = [&](lua_State* L, submetatable_type smt, reference& fast_index_table) {
22650 // Pointer types, AKA "references" from C++
22651 const char* metakey = nullptr;
22652 switch (smt) {
22653 case submetatable_type::const_value:
22654 metakey = &u_const_traits::metatable()[0];
22655 break;
22656 case submetatable_type::reference:
22657 metakey = &u_ref_traits::metatable()[0];
22658 break;
22659 case submetatable_type::unique:
22660 metakey = &u_unique_traits::metatable()[0];
22661 break;
22662 case submetatable_type::const_reference:
22663 metakey = &u_const_ref_traits::metatable()[0];
22664 break;
22665 case submetatable_type::named:
22666 metakey = &u_traits::user_metatable()[0];
22667 break;
22668 case submetatable_type::value:
22669 default:
22670 metakey = &u_traits::metatable()[0];
22671 break;
22672 }
22673
22674 luaL_newmetatable(L, metakey);
22675 if (smt == submetatable_type::named) {
22676 // the named table itself
22677 // gets the associated name value
22678 storage.named_metatable = reference(L, -1);
22679 lua_pop(L, 1);
22680 // but the thing we perform the methods on
22681 // is still the metatable of the named
22682 // table
22683 lua_createtable(L, 0, 6);
22684 }
22685 stack_reference t(L, -1);
22686 fast_index_table = reference(t);
22687 stack::set_field<false, true>(L, meta_function::type, storage.type_table, t.stack_index());
22688 if constexpr (std::is_destructible_v<T>) {
22689 // destructible: serialize default
22690 // destructor here
22691 switch (smt) {
22692 case submetatable_type::const_reference:
22693 case submetatable_type::reference:
22694 case submetatable_type::named:
22695 break;
22696 case submetatable_type::unique:
22697 stack::set_field<false, true>(L, meta_function::garbage_collect, &detail::unique_destruct<T>, t.stack_index());
22698 break;
22699 case submetatable_type::value:
22700 case submetatable_type::const_value:
22701 default:
22702 stack::set_field<false, true>(L, meta_function::garbage_collect, detail::make_destructor<T>(), t.stack_index());
22703 break;
22704 }
22705 }
22706 else {
22707 // not destructible: serialize a
22708 // "hey you messed up"
22709 // destructor
22710 switch (smt) {
22711 case submetatable_type::const_reference:
22712 case submetatable_type::reference:
22713 case submetatable_type::named:
22714 break;
22715 case submetatable_type::unique:
22716 stack::set_field<false, true>(L, meta_function::garbage_collect, &detail::cannot_destruct<T>, t.stack_index());
22717 break;
22718 case submetatable_type::value:
22719 case submetatable_type::const_value:
22720 default:
22721 stack::set_field<false, true>(L, meta_function::garbage_collect, &detail::cannot_destruct<T>, t.stack_index());
22722 break;
22723 }
22724 }
22725
22726 static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function),
22727 "The size of this data pointer is too small to fit the inheritance checking function: file a bug "
22728 "report.");
22729 static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function),
22730 "The size of this data pointer is too small to fit the inheritance checking function: file a bug "
22731 "report.");
22732 stack::set_field<false, true>(L, detail::base_class_check_key(), reinterpret_cast<void*>(&detail::inheritance<T>::type_check), t.stack_index());
22733 stack::set_field<false, true>(L, detail::base_class_cast_key(), reinterpret_cast<void*>(&detail::inheritance<T>::type_cast), t.stack_index());
22734
22735 auto prop_fx = detail::properties_enrollment_allowed(for_each_backing_metatable_calls, storage.properties, enrollments);
22736 auto insert_fx = [&L, &t, &storage](meta_function mf, lua_CFunction reg) {
22737 stack::set_field<false, true>(L, mf, reg, t.stack_index());
22738 storage.properties[static_cast<int>(mf)] = true;
22739 };
22740 detail::insert_default_registrations<T>(insert_fx, prop_fx);
22741
22742 // There are no variables, so serialize the fast function stuff
22743 // be sure to reset the index stuff to the non-fast version
22744 // if the user ever adds something later!
22745 if (smt == submetatable_type::named) {
22746 // add escape hatch storage pointer and gc names
22747 stack::set_field<false, true>(L, meta_function::storage, light_base_storage, t.stack_index());
22748 stack::set_field<false, true>(L, meta_function::gc_names, storage.gc_names_table, t.stack_index());
22749
22750 // fancy new_indexing when using the named table
22751 {
22752 absolute_index named_metatable_index(L, -storage.named_metatable.push());
22753 stack::set_field<false, true>(L, metatable_key, t, named_metatable_index);
22754 storage.named_metatable.pop();
22755 }
22756 stack_reference stack_metametatable(L, -storage.named_index_table.push());
22757 stack::set_field<false, true>(L,
22758 meta_function::index,
22759 make_closure(uts::template meta_index_call<false>, nullptr, light_storage, light_base_storage, nullptr, toplevel_magic),
22760 stack_metametatable.stack_index());
22761 stack::set_field<false, true>(L,
22762 meta_function::new_index,
22763 make_closure(uts::template meta_index_call<true>, nullptr, light_storage, light_base_storage, nullptr, toplevel_magic),
22764 stack_metametatable.stack_index());
22765 stack_metametatable.pop();
22766 }
22767 else {
22768 // otherwise just plain for index,
22769 // and elaborated for new_index
22770 stack::set_field<false, true>(L, meta_function::index, t, t.stack_index());
22771 stack::set_field<false, true>(L,
22772 meta_function::new_index,
22773 make_closure(uts::template index_call<true>, nullptr, light_storage, light_base_storage, nullptr, toplevel_magic),
22774 t.stack_index());
22775 storage.is_using_new_index = true;
22776 }
22777
22778 ++for_each_backing_metatable_calls;
22779 fast_index_table = reference(L, t);
22780 t.pop();
22781 };
22782
22783 storage.for_each_table(L, for_each_backing_metatable);
22784
22785 // can only use set AFTER we initialize all the metatables
22786 if constexpr (std::is_default_constructible_v<T>) {
22787 if (enrollments.default_constructor) {
22788 storage.set(L, meta_function::construct, constructors<T()>());
22789 }
22790 }
22791
22792 // return the named metatable we want names linked into
22793 storage.named_metatable.push();
22794 return 1;
22795 }
22796}} // namespace sol::u_detail
22797
22798// end of sol/usertype_storage.hpp
22799
22800// beginning of sol/usertype_proxy.hpp
22801
22802namespace sol {
22803 template <typename Table, typename Key>
22804 struct usertype_proxy : public proxy_base<usertype_proxy<Table, Key>> {
22805 private:
22806 using key_type = detail::proxy_key_t<Key>;
22807
22808 template <typename T, std::size_t... I>
22809 decltype(auto) tuple_get(std::index_sequence<I...>) const & {
22810 return tbl.template traverse_get<T>(std::get<I>(key)...);
22811 }
22812
22813 template <typename T, std::size_t... I>
22814 decltype(auto) tuple_get(std::index_sequence<I...>) && {
22815 return tbl.template traverse_get<T>(std::get<I>(std::move(key))...);
22816 }
22817
22818 template <std::size_t... I, typename T>
22819 void tuple_set(std::index_sequence<I...>, T&& value) & {
22820 if constexpr (sizeof...(I) > 1) {
22821 tbl.traverse_set(std::get<I>(key)..., std::forward<T>(value));
22822 }
22823 else {
22824 tbl.set(std::get<I>(key)..., std::forward<T>(value));
22825 }
22826 }
22827
22828 template <std::size_t... I, typename T>
22829 void tuple_set(std::index_sequence<I...>, T&& value) && {
22830 if constexpr (sizeof...(I) > 1) {
22831 tbl.traverse_set(std::get<I>(std::move(key))..., std::forward<T>(value));
22832 }
22833 else {
22834 tbl.set(std::get<I>(std::move(key))..., std::forward<T>(value));
22835 }
22836 }
22837
22838 public:
22839 Table tbl;
22840 key_type key;
22841
22842 template <typename T>
22843 usertype_proxy(Table table, T&& k)
22844 : tbl(table), key(std::forward<T>(k)) {
22845 }
22846
22847 template <typename T>
22848 usertype_proxy& set(T&& item) & {
22849 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
22850 tuple_set(idx_seq(), std::forward<T>(item));
22851 return *this;
22852 }
22853
22854 template <typename T>
22855 usertype_proxy&& set(T&& item) && {
22856 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
22857 std::move(*this).tuple_set(idx_seq(), std::forward<T>(item));
22858 return std::move(*this);
22859 }
22860
22861 template <typename T>
22862 usertype_proxy& operator=(T&& other) & {
22863 return set(std::forward<T>(other));
22864 }
22865
22866 template <typename T>
22867 usertype_proxy&& operator=(T&& other) && {
22868 return std::move(*this).set(std::forward<T>(other));
22869 }
22870
22871 template <typename T>
22872 usertype_proxy& operator=(std::initializer_list<T> other) & {
22873 return set(std::move(other));
22874 }
22875
22876 template <typename T>
22877 usertype_proxy&& operator=(std::initializer_list<T> other) && {
22878 return std::move(*this).set(std::move(other));
22879 }
22880
22881 template <typename T>
22882 decltype(auto) get() const& {
22883 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
22884 return tuple_get<T>(idx_seq());
22885 }
22886
22887 template <typename T>
22888 decltype(auto) get() && {
22889 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
22890 return std::move(*this).template tuple_get<T>(idx_seq());
22891 }
22892
22893 template <typename K>
22894 decltype(auto) operator[](K&& k) const& {
22895 auto keys = meta::tuplefy(key, std::forward<K>(k));
22896 return usertype_proxy<Table, decltype(keys)>(tbl, std::move(keys));
22897 }
22898
22899 template <typename K>
22900 decltype(auto) operator[](K&& k) & {
22901 auto keys = meta::tuplefy(key, std::forward<K>(k));
22902 return usertype_proxy<Table, decltype(keys)>(tbl, std::move(keys));
22903 }
22904
22905 template <typename K>
22906 decltype(auto) operator[](K&& k) && {
22907 auto keys = meta::tuplefy(std::move(key), std::forward<K>(k));
22908 return usertype_proxy<Table, decltype(keys)>(tbl, std::move(keys));
22909 }
22910
22911 template <typename... Ret, typename... Args>
22912 decltype(auto) call(Args&&... args) {
22913#if !defined(__clang__) && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191200000
22914 // MSVC is ass sometimes
22915 return get<function>().call<Ret...>(std::forward<Args>(args)...);
22916#else
22917 return get<function>().template call<Ret...>(std::forward<Args>(args)...);
22918#endif
22919 }
22920
22921 template <typename... Args>
22922 decltype(auto) operator()(Args&&... args) {
22923 return call<>(std::forward<Args>(args)...);
22924 }
22925
22926 bool valid() const {
22927 auto pp = stack::push_pop(tbl);
22928 auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state()));
22929 lua_pop(lua_state(), p.levels);
22930 return p;
22931 }
22932
22933 int push() const noexcept {
22934 return push(this->lua_state());
22935 }
22936
22937 int push(lua_State* L) const noexcept {
22938 return get<reference>().push(L);
22939 }
22940
22941 type get_type() const {
22942 type t = type::none;
22943 auto pp = stack::push_pop(tbl);
22944 auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state()));
22945 if (p) {
22946 t = type_of(lua_state(), -1);
22947 }
22948 lua_pop(lua_state(), p.levels);
22949 return t;
22950 }
22951
22952 lua_State* lua_state() const {
22953 return tbl.lua_state();
22954 }
22955 };
22956} // namespace sol
22957
22958// end of sol/usertype_proxy.hpp
22959
22960// beginning of sol/metatable.hpp
22961
22962// beginning of sol/table_core.hpp
22963
22964// beginning of sol/table_proxy.hpp
22965
22966namespace sol {
22967
22968 template <typename Table, typename Key>
22969 struct table_proxy : public proxy_base<table_proxy<Table, Key>> {
22970 private:
22971 using key_type = detail::proxy_key_t<Key>;
22972
22973 template <typename T, std::size_t... I>
22974 decltype(auto) tuple_get(std::index_sequence<I...>) const& {
22975 return tbl.template traverse_get<T>(std::get<I>(key)...);
22976 }
22977
22978 template <typename T, std::size_t... I>
22979 decltype(auto) tuple_get(std::index_sequence<I...>) && {
22980 return tbl.template traverse_get<T>(std::get<I>(std::move(key))...);
22981 }
22982
22983 template <std::size_t... I, typename T>
22984 void tuple_set(std::index_sequence<I...>, T&& value) & {
22985 tbl.traverse_set(std::get<I>(key)..., std::forward<T>(value));
22986 }
22987
22988 template <std::size_t... I, typename T>
22989 void tuple_set(std::index_sequence<I...>, T&& value) && {
22990 tbl.traverse_set(std::get<I>(std::move(key))..., std::forward<T>(value));
22991 }
22992
22993 auto setup_table(std::true_type) {
22994 auto p = stack::probe_get_field<std::is_same_v<meta::unqualified_t<Table>, global_table>>(lua_state(), key, tbl.stack_index());
22995 lua_pop(lua_state(), p.levels);
22996 return p;
22997 }
22998
22999 bool is_valid(std::false_type) {
23000 auto pp = stack::push_pop(tbl);
23001 auto p = stack::probe_get_field<std::is_same_v<meta::unqualified_t<Table>, global_table>>(lua_state(), key, lua_gettop(lua_state()));
23002 lua_pop(lua_state(), p.levels);
23003 return p;
23004 }
23005
23006 public:
23007 Table tbl;
23008 key_type key;
23009
23010 template <typename T>
23011 table_proxy(Table table, T&& k) : tbl(table), key(std::forward<T>(k)) {
23012 }
23013
23014 template <typename T>
23015 table_proxy& set(T&& item) & {
23016 tuple_set(std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>(), std::forward<T>(item));
23017 return *this;
23018 }
23019
23020 template <typename T>
23021 table_proxy&& set(T&& item) && {
23022 tuple_set(std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>(), std::forward<T>(item));
23023 return std::move(*this);
23024 }
23025
23026 template <typename... Args>
23027 table_proxy& set_function(Args&&... args) & {
23028 tbl.set_function(key, std::forward<Args>(args)...);
23029 return *this;
23030 }
23031
23032 template <typename... Args>
23033 table_proxy&& set_function(Args&&... args) && {
23034 tbl.set_function(std::move(key), std::forward<Args>(args)...);
23035 return std::move(*this);
23036 }
23037
23038 template <typename T>
23039 table_proxy& operator=(T&& other) & {
23040 using Tu = meta::unwrap_unqualified_t<T>;
23041 if constexpr (!is_lua_reference_or_proxy_v<Tu> && meta::is_callable_v<Tu>) {
23042 return set_function(std::forward<T>(other));
23043 }
23044 else {
23045 return set(std::forward<T>(other));
23046 }
23047 }
23048
23049 template <typename T>
23050 table_proxy&& operator=(T&& other) && {
23051 using Tu = meta::unwrap_unqualified_t<T>;
23052 if constexpr (!is_lua_reference_or_proxy_v<Tu> && meta::is_callable_v<Tu>) {
23053 return std::move(*this).set_function(std::forward<T>(other));
23054 }
23055 else {
23056 return std::move(*this).set(std::forward<T>(other));
23057 }
23058 }
23059
23060 template <typename T>
23061 table_proxy& operator=(std::initializer_list<T> other) & {
23062 return set(std::move(other));
23063 }
23064
23065 template <typename T>
23066 table_proxy&& operator=(std::initializer_list<T> other) && {
23067 return std::move(*this).set(std::move(other));
23068 }
23069
23070 template <typename T>
23071 decltype(auto) get() const& {
23072 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
23073 return tuple_get<T>(idx_seq());
23074 }
23075
23076 template <typename T>
23077 decltype(auto) get() && {
23078 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
23079 return std::move(*this).template tuple_get<T>(idx_seq());
23080 }
23081
23082 template <typename T>
23083 decltype(auto) get_or(T&& otherwise) const {
23084 typedef decltype(get<T>()) U;
23085 optional<U> option = get<optional<U>>();
23086 if (option) {
23087 return static_cast<U>(option.value());
23088 }
23089 return static_cast<U>(std::forward<T>(otherwise));
23090 }
23091
23092 template <typename T, typename D>
23093 decltype(auto) get_or(D&& otherwise) const {
23094 optional<T> option = get<optional<T>>();
23095 if (option) {
23096 return static_cast<T>(option.value());
23097 }
23098 return static_cast<T>(std::forward<D>(otherwise));
23099 }
23100
23101 template <typename T>
23102 decltype(auto) get_or_create() {
23103 return get_or_create<T>(new_table());
23104 }
23105
23106 template <typename T, typename Otherwise>
23107 decltype(auto) get_or_create(Otherwise&& other) {
23108 if (!this->valid()) {
23109 this->set(std::forward<Otherwise>(other));
23110 }
23111 return get<T>();
23112 }
23113
23114 template <typename K>
23115 decltype(auto) operator[](K&& k) const& {
23116 auto keys = meta::tuplefy(key, std::forward<K>(k));
23117 return table_proxy<Table, decltype(keys)>(tbl, std::move(keys));
23118 }
23119
23120 template <typename K>
23121 decltype(auto) operator[](K&& k) & {
23122 auto keys = meta::tuplefy(key, std::forward<K>(k));
23123 return table_proxy<Table, decltype(keys)>(tbl, std::move(keys));
23124 }
23125
23126 template <typename K>
23127 decltype(auto) operator[](K&& k) && {
23128 auto keys = meta::tuplefy(std::move(key), std::forward<K>(k));
23129 return table_proxy<Table, decltype(keys)>(tbl, std::move(keys));
23130 }
23131
23132 template <typename... Ret, typename... Args>
23133 decltype(auto) call(Args&&... args) {
23134 lua_State* L = this->lua_state();
23135 push(L);
23136 int idx = lua_gettop(L);
23137 stack_aligned_function func(L, idx);
23138 return func.call<Ret...>(std::forward<Args>(args)...);
23139 }
23140
23141 template <typename... Args>
23142 decltype(auto) operator()(Args&&... args) {
23143 return call<>(std::forward<Args>(args)...);
23144 }
23145
23146 bool valid() const {
23147 auto pp = stack::push_pop(tbl);
23148 auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state()));
23149 lua_pop(lua_state(), p.levels);
23150 return p;
23151 }
23152
23153 int push() const noexcept {
23154 return push(this->lua_state());
23155 }
23156
23157 int push(lua_State* L) const noexcept {
23158 if constexpr (std::is_same_v<meta::unqualified_t<Table>, global_table> || is_stack_table_v<meta::unqualified_t<Table>>) {
23159 auto pp = stack::push_pop<true>(tbl);
23160 int tableindex = pp.index_of(tbl);
23161 int top_index = lua_gettop(L);
23162 stack::get_field<true>(lua_state(), key, tableindex);
23163 lua_replace(L, top_index + 1);
23164 lua_settop(L, top_index + 1);
23165 }
23166 else {
23167 auto pp = stack::push_pop<false>(tbl);
23168 int tableindex = pp.index_of(tbl);
23169 int aftertableindex = lua_gettop(L);
23170 stack::get_field<false>(lua_state(), key, tableindex);
23171 lua_replace(L, tableindex);
23172 lua_settop(L, aftertableindex + 1);
23173 }
23174 return 1;
23175 }
23176
23177 type get_type() const {
23178 type t = type::none;
23179 auto pp = stack::push_pop(tbl);
23180 auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state()));
23181 if (p) {
23182 t = type_of(lua_state(), -1);
23183 }
23184 lua_pop(lua_state(), p.levels);
23185 return t;
23186 }
23187
23188 lua_State* lua_state() const {
23189 return tbl.lua_state();
23190 }
23191
23192 table_proxy& force() {
23193 if (!this->valid()) {
23194 this->set(new_table());
23195 }
23196 return *this;
23197 }
23198 };
23199
23200 template <typename Table, typename Key, typename T>
23201 inline bool operator==(T&& left, const table_proxy<Table, Key>& right) {
23202 using G = decltype(stack::get<T>(nullptr, 0));
23203 return right.template get<optional<G>>() == left;
23204 }
23205
23206 template <typename Table, typename Key, typename T>
23207 inline bool operator==(const table_proxy<Table, Key>& right, T&& left) {
23208 using G = decltype(stack::get<T>(nullptr, 0));
23209 return right.template get<optional<G>>() == left;
23210 }
23211
23212 template <typename Table, typename Key, typename T>
23213 inline bool operator!=(T&& left, const table_proxy<Table, Key>& right) {
23214 using G = decltype(stack::get<T>(nullptr, 0));
23215 return right.template get<optional<G>>() != left;
23216 }
23217
23218 template <typename Table, typename Key, typename T>
23219 inline bool operator!=(const table_proxy<Table, Key>& right, T&& left) {
23220 using G = decltype(stack::get<T>(nullptr, 0));
23221 return right.template get<optional<G>>() != left;
23222 }
23223
23224 template <typename Table, typename Key>
23225 inline bool operator==(lua_nil_t, const table_proxy<Table, Key>& right) {
23226 return !right.valid();
23227 }
23228
23229 template <typename Table, typename Key>
23230 inline bool operator==(const table_proxy<Table, Key>& right, lua_nil_t) {
23231 return !right.valid();
23232 }
23233
23234 template <typename Table, typename Key>
23235 inline bool operator!=(lua_nil_t, const table_proxy<Table, Key>& right) {
23236 return right.valid();
23237 }
23238
23239 template <typename Table, typename Key>
23240 inline bool operator!=(const table_proxy<Table, Key>& right, lua_nil_t) {
23241 return right.valid();
23242 }
23243
23244 template <bool b>
23245 template <typename Super>
23246 basic_reference<b>& basic_reference<b>::operator=(proxy_base<Super>&& r) {
23247 basic_reference<b> v = r;
23248 this->operator=(std::move(v));
23249 return *this;
23250 }
23251
23252 template <bool b>
23253 template <typename Super>
23254 basic_reference<b>& basic_reference<b>::operator=(const proxy_base<Super>& r) {
23255 basic_reference<b> v = r;
23256 this->operator=(std::move(v));
23257 return *this;
23258 }
23259
23260 namespace stack {
23261 template <typename Table, typename Key>
23262 struct unqualified_pusher<table_proxy<Table, Key>> {
23263 static int push(lua_State* L, const table_proxy<Table, Key>& p) {
23264 return p.push(L);
23265 }
23266 };
23267 } // namespace stack
23268} // namespace sol
23269
23270// end of sol/table_proxy.hpp
23271
23272// beginning of sol/table_iterator.hpp
23273
23274#include <iterator>
23275
23276namespace sol {
23277
23278 template <typename reference_type>
23279 class basic_table_iterator {
23280 public:
23281 typedef object key_type;
23282 typedef object mapped_type;
23283 typedef std::pair<object, object> value_type;
23284 typedef std::input_iterator_tag iterator_category;
23285 typedef std::ptrdiff_t difference_type;
23286 typedef value_type* pointer;
23287 typedef value_type& reference;
23288 typedef const value_type& const_reference;
23289
23290 private:
23291 std::pair<object, object> kvp;
23292 reference_type ref;
23293 int tableidx = 0;
23294 int keyidx = 0;
23295 std::ptrdiff_t idx = 0;
23296
23297 public:
23298 basic_table_iterator() : keyidx(-1), idx(-1) {
23299 }
23300
23301 basic_table_iterator(reference_type x) : ref(std::move(x)) {
23302 ref.push();
23303 tableidx = lua_gettop(ref.lua_state());
23304 stack::push(ref.lua_state(), lua_nil);
23305 this->operator++();
23306 if (idx == -1) {
23307 return;
23308 }
23309 --idx;
23310 }
23311
23312 basic_table_iterator& operator++() {
23313 if (idx == -1)
23314 return *this;
23315
23316 if (lua_next(ref.lua_state(), tableidx) == 0) {
23317 idx = -1;
23318 keyidx = -1;
23319 return *this;
23320 }
23321 ++idx;
23322 kvp.first = object(ref.lua_state(), -2);
23323 kvp.second = object(ref.lua_state(), -1);
23324 lua_pop(ref.lua_state(), 1);
23325 // leave key on the stack
23326 keyidx = lua_gettop(ref.lua_state());
23327 return *this;
23328 }
23329
23330 basic_table_iterator operator++(int) {
23331 auto saved = *this;
23332 this->operator++();
23333 return saved;
23334 }
23335
23336 reference operator*() {
23337 return kvp;
23338 }
23339
23340 const_reference operator*() const {
23341 return kvp;
23342 }
23343
23344 bool operator==(const basic_table_iterator& right) const {
23345 return idx == right.idx;
23346 }
23347
23348 bool operator!=(const basic_table_iterator& right) const {
23349 return idx != right.idx;
23350 }
23351
23352 ~basic_table_iterator() {
23353 if (keyidx != -1) {
23354 stack::remove(ref.lua_state(), keyidx, 1);
23355 }
23356 if (ref.lua_state() != nullptr && ref.valid()) {
23357 stack::remove(ref.lua_state(), tableidx, 1);
23358 }
23359 }
23360 };
23361
23362} // namespace sol
23363
23364// end of sol/table_iterator.hpp
23365
23366namespace sol {
23367 namespace detail {
23368 template <std::size_t n>
23369 struct clean {
23370 lua_State* L;
23371 clean(lua_State* luastate) : L(luastate) {
23372 }
23373 ~clean() {
23374 lua_pop(L, static_cast<int>(n));
23375 }
23376 };
23377
23378 struct ref_clean {
23379 lua_State* L;
23380 int& n;
23381 ref_clean(lua_State* luastate, int& n) : L(luastate), n(n) {
23382 }
23383 ~ref_clean() {
23384 lua_pop(L, static_cast<int>(n));
23385 }
23386 };
23387
23388 inline int fail_on_newindex(lua_State* L) {
23389 return luaL_error(L, "sol: cannot modify the elements of an enumeration table");
23390 }
23391
23392 } // namespace detail
23393
23394 template <bool top_level, typename ref_t>
23395 class basic_table_core : public basic_object<ref_t> {
23396 private:
23397 using base_t = basic_object<ref_t>;
23398
23399 friend class state;
23400 friend class state_view;
23401 template <typename, typename>
23402 friend class basic_usertype;
23403 template <typename>
23404 friend class basic_metatable;
23405
23406 template <bool raw, typename... Ret, typename... Keys>
23407 decltype(auto) tuple_get(int table_index, Keys&&... keys) const {
23408 if constexpr (sizeof...(Ret) < 2) {
23409 return traverse_get_single_maybe_tuple<raw, Ret...>(table_index, std::forward<Keys>(keys)...);
23410 }
23411 else {
23412 using multi_ret = decltype(stack::pop<std::tuple<Ret...>>(nullptr));
23413 return multi_ret(traverse_get_single_maybe_tuple<raw, Ret>(table_index, std::forward<Keys>(keys))...);
23414 }
23415 }
23416
23417 template <bool raw, typename Ret, size_t... I, typename Key>
23418 decltype(auto) traverse_get_single_tuple(int table_index, std::index_sequence<I...>, Key&& key) const {
23419 return traverse_get_single<raw, Ret>(table_index, std::get<I>(std::forward<Key>(key))...);
23420 }
23421
23422 template <bool raw, typename Ret, typename Key>
23423 decltype(auto) traverse_get_single_maybe_tuple(int table_index, Key&& key) const {
23424 if constexpr (meta::is_tuple_v<meta::unqualified_t<Key>>) {
23425 return traverse_get_single_tuple<raw, Ret>(
23426 table_index, std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<Key>>>(), std::forward<Key>(key));
23427 }
23428 else {
23429 return traverse_get_single<raw, Ret>(table_index, std::forward<Key>(key));
23430 }
23431 }
23432
23433 template <bool raw, typename Ret, typename... Keys>
23434 decltype(auto) traverse_get_single(int table_index, Keys&&... keys) const {
23435 constexpr static bool global = top_level && (meta::count_for_to_pack_v<1, meta::is_c_str, meta::unqualified_t<Keys>...> > 0);
23436 if constexpr (meta::is_optional_v<meta::unqualified_t<Ret>>) {
23437 int popcount = 0;
23438 detail::ref_clean c(base_t::lua_state(), popcount);
23439 return traverse_get_deep_optional<global, raw, detail::insert_mode::none, Ret>(popcount, table_index, std::forward<Keys>(keys)...);
23440 }
23441 else {
23442 detail::clean<sizeof...(Keys) - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>> c(base_t::lua_state());
23443 return traverse_get_deep<global, raw, detail::insert_mode::none, Ret>(table_index, std::forward<Keys>(keys)...);
23444 }
23445 }
23446
23447 template <bool raw, typename Pairs, std::size_t... I>
23448 void tuple_set(std::index_sequence<I...>, Pairs&& pairs) {
23449 constexpr static bool global = top_level
23450 && (meta::count_even_for_pack_v<meta::is_c_str, meta::unqualified_t<decltype(std::get<I * 2>(std::forward<Pairs>(pairs)))>...> > 0);
23451 auto pp = stack::push_pop<global>(*this);
23452 int table_index = pp.index_of(*this);
23453 lua_State* L = base_t::lua_state();
23454 (void)table_index;
23455 (void)L;
23456 void(detail::swallow { (stack::set_field<(top_level), raw>(
23457 L, std::get<I * 2>(std::forward<Pairs>(pairs)), std::get<I * 2 + 1>(std::forward<Pairs>(pairs)), table_index),
23458 0)... });
23459 }
23460
23461 template <bool global, bool raw, detail::insert_mode mode, typename T, typename Key, typename... Keys>
23462 decltype(auto) traverse_get_deep(int table_index, Key&& key, Keys&&... keys) const {
23463 if constexpr (std::is_same_v<meta::unqualified_t<Key>, create_if_nil_t>) {
23464 (void)key;
23465 return traverse_get_deep<false, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::create_if_nil), T>(
23466 table_index, std::forward<Keys>(keys)...);
23467 }
23468 else {
23469 lua_State* L = base_t::lua_state();
23470 stack::get_field<global, raw>(L, std::forward<Key>(key), table_index);
23471 if constexpr (sizeof...(Keys) > 0) {
23472 if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
23473 type t = type_of(L, -1);
23474 if (t == type::lua_nil || t == type::none) {
23475 lua_pop(L, 1);
23476 stack::push(L, new_table(0, 0));
23477 }
23478 }
23479 return traverse_get_deep<false, raw, mode, T>(lua_gettop(L), std::forward<Keys>(keys)...);
23480 }
23481 else {
23482 if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
23483 type t = type_of(L, -1);
23484 if ((t == type::lua_nil || t == type::none) && (is_table_like_v<T>)) {
23485 lua_pop(L, 1);
23486 stack::push(L, new_table(0, 0));
23487 }
23488 }
23489 return stack::get<T>(L);
23490 }
23491 }
23492 }
23493
23494 template <bool global, bool raw, detail::insert_mode mode, typename T, typename Key, typename... Keys>
23495 decltype(auto) traverse_get_deep_optional(int& popcount, int table_index, Key&& key, Keys&&... keys) const {
23496 if constexpr (std::is_same_v<meta::unqualified_t<Key>, create_if_nil_t>) {
23497 constexpr detail::insert_mode new_mode = static_cast<detail::insert_mode>(mode | detail::insert_mode::create_if_nil);
23498 (void)key;
23499 return traverse_get_deep_optional<global, raw, new_mode, T>(popcount, table_index, std::forward<Keys>(keys)...);
23500 }
23501 else if constexpr (std::is_same_v<meta::unqualified_t<Key>, update_if_empty_t>) {
23502 constexpr detail::insert_mode new_mode = static_cast<detail::insert_mode>(mode | detail::insert_mode::update_if_empty);
23503 (void)key;
23504 return traverse_get_deep_optional<global, raw, new_mode, T>(popcount, table_index, std::forward<Keys>(keys)...);
23505 }
23506 else if constexpr (std::is_same_v<meta::unqualified_t<Key>, override_value_t>) {
23507 constexpr detail::insert_mode new_mode = static_cast<detail::insert_mode>(mode | detail::insert_mode::override_value);
23508 (void)key;
23509 return traverse_get_deep_optional<global, raw, new_mode, T>(popcount, table_index, std::forward<Keys>(keys)...);
23510 }
23511 else {
23512 if constexpr (sizeof...(Keys) > 0) {
23513 lua_State* L = base_t::lua_state();
23514 auto p = stack::probe_get_field<global, raw>(L, std::forward<Key>(key), table_index);
23515 popcount += p.levels;
23516 if (!p.success) {
23517 if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
23518 lua_pop(L, 1);
23519 constexpr bool is_seq = meta::count_for_to_pack_v<1, std::is_integral, Keys...> > 0;
23520 stack::push(L, new_table(static_cast<int>(is_seq), static_cast<int>(!is_seq)));
23521 stack::set_field<global, raw>(L, std::forward<Key>(key), stack_reference(L, -1), table_index);
23522 }
23523 else {
23524 return T(nullopt);
23525 }
23526 }
23527 return traverse_get_deep_optional<false, raw, mode, T>(popcount, lua_gettop(L), std::forward<Keys>(keys)...);
23528 }
23529 else {
23530 using R = decltype(stack::get<T>(nullptr));
23531 using value_type = typename meta::unqualified_t<R>::value_type;
23532 lua_State* L = base_t::lua_state();
23533 auto p = stack::probe_get_field<global, raw, value_type>(L, key, table_index);
23534 popcount += p.levels;
23535 if (!p.success) {
23536 if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
23537 lua_pop(L, 1);
23538 stack::push(L, new_table(0, 0));
23539 stack::set_field<global, raw>(L, std::forward<Key>(key), stack_reference(L, -1), table_index);
23540 if (stack::check<value_type>(L, lua_gettop(L), no_panic)) {
23541 return stack::get<T>(L);
23542 }
23543 }
23544 return R(nullopt);
23545 }
23546 return stack::get<T>(L);
23547 }
23548 }
23549 }
23550
23551 template <bool global, bool raw, detail::insert_mode mode, typename Key, typename... Keys>
23552 void traverse_set_deep(int table_index, Key&& key, Keys&&... keys) const {
23553 using KeyU = meta::unqualified_t<Key>;
23554 if constexpr (std::is_same_v<KeyU, update_if_empty_t>) {
23555 (void)key;
23556 traverse_set_deep<global, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::update_if_empty)>(
23557 table_index, std::forward<Keys>(keys)...);
23558 }
23559 else if constexpr (std::is_same_v<KeyU, create_if_nil_t>) {
23560 (void)key;
23561 traverse_set_deep<global, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::create_if_nil)>(
23562 table_index, std::forward<Keys>(keys)...);
23563 }
23564 else if constexpr (std::is_same_v<KeyU, override_value_t>) {
23565 (void)key;
23566 traverse_set_deep<global, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::override_value)>(
23567 table_index, std::forward<Keys>(keys)...);
23568 }
23569 else {
23570 lua_State* L = base_t::lua_state();
23571 if constexpr (sizeof...(Keys) == 1) {
23572 if constexpr ((mode & detail::insert_mode::update_if_empty) == detail::insert_mode::update_if_empty) {
23573 auto p = stack::probe_get_field<global, raw>(L, key, table_index);
23574 lua_pop(L, p.levels);
23575 if (!p.success) {
23576 stack::set_field<global, raw>(L, std::forward<Key>(key), std::forward<Keys>(keys)..., table_index);
23577 }
23578 }
23579 else {
23580 stack::set_field<global, raw>(L, std::forward<Key>(key), std::forward<Keys>(keys)..., table_index);
23581 }
23582 }
23583 else {
23584 if constexpr (mode != detail::insert_mode::none) {
23585 stack::get_field<global, raw>(L, key, table_index);
23586 type vt = type_of(L, -1);
23587 if constexpr ((mode & detail::insert_mode::update_if_empty) == detail::insert_mode::update_if_empty
23588 || (mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
23589 if (vt == type::lua_nil || vt == type::none) {
23590 constexpr bool is_seq = meta::count_for_to_pack_v<1, std::is_integral, Keys...> > 0;
23591 lua_pop(L, 1);
23592 stack::push(L, new_table(static_cast<int>(is_seq), static_cast<int>(!is_seq)));
23593 stack::set_field<global, raw>(L, std::forward<Key>(key), stack_reference(L, -1), table_index);
23594 }
23595 }
23596 else {
23597 if (vt != type::table) {
23598 constexpr bool is_seq = meta::count_for_to_pack_v<1, std::is_integral, Keys...> > 0;
23599 lua_pop(L, 1);
23600 stack::push(L, new_table(static_cast<int>(is_seq), static_cast<int>(!is_seq)));
23601 stack::set_field<global, raw>(L, std::forward<Key>(key), stack_reference(L, -1), table_index);
23602 }
23603 }
23604 }
23605 else {
23606 stack::get_field<global, raw>(L, std::forward<Key>(key), table_index);
23607 }
23608 traverse_set_deep<false, raw, mode>(lua_gettop(L), std::forward<Keys>(keys)...);
23609 }
23610 }
23611 }
23612
23613 basic_table_core(lua_State* L, detail::global_tag t) noexcept : base_t(L, t) {
23614 }
23615
23616 protected:
23617 basic_table_core(detail::no_safety_tag, lua_nil_t n) : base_t(n) {
23618 }
23619 basic_table_core(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) {
23620 }
23621 basic_table_core(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) {
23622 }
23623 template <typename T,
23624 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<ref_t, stack_reference>>,
23625 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
23626 basic_table_core(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward<T>(r)) {
23627 }
23628 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
23629 basic_table_core(detail::no_safety_tag, lua_State* L, T&& r) noexcept : base_t(L, std::forward<T>(r)) {
23630 }
23631
23632 public:
23633 using iterator = basic_table_iterator<ref_t>;
23634 using const_iterator = iterator;
23635
23636 using base_t::lua_state;
23637
23638 basic_table_core() noexcept = default;
23639 basic_table_core(const basic_table_core&) = default;
23640 basic_table_core(basic_table_core&&) = default;
23641 basic_table_core& operator=(const basic_table_core&) = default;
23642 basic_table_core& operator=(basic_table_core&&) = default;
23643 basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) {
23644 }
23645 basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) {
23646 }
23647 template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
23648 basic_table_core(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
23649#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
23650 auto pp = stack::push_pop(*this);
23651 int table_index = pp.index_of(*this);
23652 constructor_handler handler {};
23653 stack::check<basic_table_core>(lua_state(), table_index, handler);
23654#endif // Safety
23655 }
23656 basic_table_core(lua_State* L, const new_table& nt) : base_t(L, -stack::push(L, nt)) {
23657 if (!is_stack_based<meta::unqualified_t<ref_t>>::value) {
23658 lua_pop(L, 1);
23659 }
23660 }
23661 basic_table_core(lua_State* L, int index = -1) : basic_table_core(detail::no_safety, L, index) {
23662#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
23663 constructor_handler handler {};
23664 stack::check<basic_table_core>(L, index, handler);
23665#endif // Safety
23666 }
23667 basic_table_core(lua_State* L, ref_index index) : basic_table_core(detail::no_safety, L, index) {
23668#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
23669 auto pp = stack::push_pop(*this);
23670 int table_index = pp.index_of(*this);
23671 constructor_handler handler {};
23672 stack::check<basic_table_core>(lua_state(), table_index, handler);
23673#endif // Safety
23674 }
23675 template <typename T,
23676 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<ref_t, stack_reference>>,
23677 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
23678 basic_table_core(T&& r) noexcept : basic_table_core(detail::no_safety, std::forward<T>(r)) {
23679#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
23680 if (!is_table<meta::unqualified_t<T>>::value) {
23681 auto pp = stack::push_pop(*this);
23682 int table_index = pp.index_of(*this);
23683 constructor_handler handler {};
23684 stack::check<basic_table_core>(lua_state(), table_index, handler);
23685 }
23686#endif // Safety
23687 }
23688 basic_table_core(lua_nil_t r) noexcept : basic_table_core(detail::no_safety, r) {
23689 }
23690
23691 iterator begin() const {
23692 if (this->get_type() == type::table) {
23693 return iterator(*this);
23694 }
23695 return iterator();
23696 }
23697
23698 iterator end() const {
23699 return iterator();
23700 }
23701
23702 const_iterator cbegin() const {
23703 return begin();
23704 }
23705
23706 const_iterator cend() const {
23707 return end();
23708 }
23709
23710 void clear() {
23711 auto pp = stack::push_pop<false>(*this);
23712 int table_index = pp.index_of(*this);
23713 stack::clear(lua_state(), table_index);
23714 }
23715
23716 template <typename... Ret, typename... Keys>
23717 decltype(auto) get(Keys&&... keys) const {
23718 static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match");
23719 constexpr static bool global = meta::all<meta::boolean<top_level>, meta::is_c_str<meta::unqualified_t<Keys>>...>::value;
23720 auto pp = stack::push_pop<global>(*this);
23721 int table_index = pp.index_of(*this);
23722 return tuple_get<false, Ret...>(table_index, std::forward<Keys>(keys)...);
23723 }
23724
23725 template <typename T, typename Key>
23726 decltype(auto) get_or(Key&& key, T&& otherwise) const {
23727 typedef decltype(get<T>("")) U;
23728 optional<U> option = get<optional<U>>(std::forward<Key>(key));
23729 if (option) {
23730 return static_cast<U>(option.value());
23731 }
23732 return static_cast<U>(std::forward<T>(otherwise));
23733 }
23734
23735 template <typename T, typename Key, typename D>
23736 decltype(auto) get_or(Key&& key, D&& otherwise) const {
23737 optional<T> option = get<optional<T>>(std::forward<Key>(key));
23738 if (option) {
23739 return static_cast<T>(option.value());
23740 }
23741 return static_cast<T>(std::forward<D>(otherwise));
23742 }
23743
23744 template <typename T, typename... Keys>
23745 decltype(auto) traverse_get(Keys&&... keys) const {
23746 static_assert(sizeof...(Keys) > 0, "must pass at least 1 key to get");
23747 constexpr static bool global = top_level && (meta::count_for_to_pack_v<1, meta::is_c_str, meta::unqualified_t<Keys>...> > 0);
23748 auto pp = stack::push_pop<global>(*this);
23749 int table_index = pp.index_of(*this);
23750 return traverse_get_single<false, T>(table_index, std::forward<Keys>(keys)...);
23751 }
23752
23753 template <typename... Keys>
23754 basic_table_core& traverse_set(Keys&&... keys) {
23755 static_assert(sizeof...(Keys) > 1, "must pass at least 1 key and 1 value to set");
23756 constexpr static bool global
23757 = top_level && (meta::count_when_for_to_pack_v<detail::is_not_insert_mode, 1, meta::is_c_str, meta::unqualified_t<Keys>...> > 0);
23758 auto pp = stack::push_pop<global>(*this);
23759 int table_index = pp.index_of(*this);
23760 lua_State* L = base_t::lua_state();
23761 auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2 - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>));
23762 traverse_set_deep<top_level, false, detail::insert_mode::none>(table_index, std::forward<Keys>(keys)...);
23763 return *this;
23764 }
23765
23766 template <typename... Args>
23767 basic_table_core& set(Args&&... args) {
23768 if constexpr (sizeof...(Args) == 2) {
23769 traverse_set(std::forward<Args>(args)...);
23770 }
23771 else {
23772 tuple_set<false>(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
23773 }
23774 return *this;
23775 }
23776
23777 template <typename... Ret, typename... Keys>
23778 decltype(auto) raw_get(Keys&&... keys) const {
23779 static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match");
23780 constexpr static bool global = top_level && (meta::count_for_to_pack_v<1, meta::is_c_str, meta::unqualified_t<Keys>...> > 0);
23781 auto pp = stack::push_pop<global>(*this);
23782 int table_index = pp.index_of(*this);
23783 return tuple_get<true, Ret...>(table_index, std::forward<Keys>(keys)...);
23784 }
23785
23786 template <typename T, typename Key>
23787 decltype(auto) raw_get_or(Key&& key, T&& otherwise) const {
23788 typedef decltype(raw_get<T>("")) U;
23789 optional<U> option = raw_get<optional<U>>(std::forward<Key>(key));
23790 if (option) {
23791 return static_cast<U>(option.value());
23792 }
23793 return static_cast<U>(std::forward<T>(otherwise));
23794 }
23795
23796 template <typename T, typename Key, typename D>
23797 decltype(auto) raw_get_or(Key&& key, D&& otherwise) const {
23798 optional<T> option = raw_get<optional<T>>(std::forward<Key>(key));
23799 if (option) {
23800 return static_cast<T>(option.value());
23801 }
23802 return static_cast<T>(std::forward<D>(otherwise));
23803 }
23804
23805 template <typename T, typename... Keys>
23806 decltype(auto) traverse_raw_get(Keys&&... keys) const {
23807 constexpr static bool global = top_level && (meta::count_for_to_pack_v<1, meta::is_c_str, meta::unqualified_t<Keys>...> > 0);
23808 auto pp = stack::push_pop<global>(*this);
23809 int table_index = pp.index_of(*this);
23810 return traverse_get_single<true, T>(table_index, std::forward<Keys>(keys)...);
23811 }
23812
23813 template <typename... Keys>
23814 basic_table_core& traverse_raw_set(Keys&&... keys) {
23815 constexpr static bool global = top_level && (meta::count_for_to_pack_v<1, meta::is_c_str, meta::unqualified_t<Keys>...> > 0);
23816 auto pp = stack::push_pop<global>(*this);
23817 lua_State* L = base_t::lua_state();
23818 auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2 - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>));
23819 traverse_set_deep<top_level, true, false>(std::forward<Keys>(keys)...);
23820 return *this;
23821 }
23822
23823 template <typename... Args>
23824 basic_table_core& raw_set(Args&&... args) {
23825 tuple_set<true>(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
23826 return *this;
23827 }
23828
23829 template <typename Class, typename Key>
23830 usertype<Class> new_usertype(Key&& key);
23831
23832 template <typename Class, typename Key>
23833 usertype<Class> new_usertype(Key&& key, automagic_enrollments enrollment);
23834
23835 template <typename Class, typename Key, typename Arg, typename... Args,
23836 typename = std::enable_if_t<!std::is_same_v<meta::unqualified_t<Arg>, automagic_enrollments>>>
23837 usertype<Class> new_usertype(Key&& key, Arg&& arg, Args&&... args);
23838
23839 template <bool read_only = true, typename... Args>
23840 table new_enum(const string_view& name, Args&&... args) {
23841 table target = create_with(std::forward<Args>(args)...);
23842 if (read_only) {
23843 table x = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target);
23844 table shim = create_named(name, metatable_key, x);
23845 return shim;
23846 }
23847 else {
23848 set(name, target);
23849 return target;
23850 }
23851 }
23852
23853 template <typename T, bool read_only = true>
23854 table new_enum(const string_view& name, std::initializer_list<std::pair<string_view, T>> items) {
23855 table target = create(static_cast<int>(items.size()), static_cast<int>(0));
23856 for (const auto& kvp : items) {
23857 target.set(kvp.first, kvp.second);
23858 }
23859 if constexpr (read_only) {
23860 table x = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target);
23861 table shim = create_named(name, metatable_key, x);
23862 return shim;
23863 }
23864 else {
23865 set(name, target);
23866 return target;
23867 }
23868 }
23869
23870 template <typename Key = object, typename Value = object, typename Fx>
23871 void for_each(Fx&& fx) const {
23872 lua_State* L = base_t::lua_state();
23873 if constexpr (std::is_invocable_v<Fx, Key, Value>) {
23874 auto pp = stack::push_pop(*this);
23875 int table_index = pp.index_of(*this);
23876 stack::push(L, lua_nil);
23877 while (lua_next(L, table_index)) {
23878 Key key(L, -2);
23879 Value value(L, -1);
23880 auto pn = stack::pop_n(L, 1);
23881 fx(key, value);
23882 }
23883 }
23884 else {
23885 auto pp = stack::push_pop(*this);
23886 int table_index = pp.index_of(*this);
23887 stack::push(L, lua_nil);
23888 while (lua_next(L, table_index)) {
23889 Key key(L, -2);
23890 Value value(L, -1);
23891 auto pn = stack::pop_n(L, 1);
23892 std::pair<Key&, Value&> keyvalue(key, value);
23893 fx(keyvalue);
23894 }
23895 }
23896 }
23897
23898 size_t size() const {
23899 auto pp = stack::push_pop(*this);
23900 int table_index = pp.index_of(*this);
23901 lua_State* L = base_t::lua_state();
23902 lua_len(L, table_index);
23903 return stack::pop<size_t>(L);
23904 }
23905
23906 bool empty() const {
23907 return cbegin() == cend();
23908 }
23909
23910 template <typename T>
23911 auto operator[](T&& key) & {
23912 return table_proxy<basic_table_core&, detail::proxy_key_t<T>>(*this, std::forward<T>(key));
23913 }
23914
23915 template <typename T>
23916 auto operator[](T&& key) const& {
23917 return table_proxy<const basic_table_core&, detail::proxy_key_t<T>>(*this, std::forward<T>(key));
23918 }
23919
23920 template <typename T>
23921 auto operator[](T&& key) && {
23922 return table_proxy<basic_table_core, detail::proxy_key_t<T>>(std::move(*this), std::forward<T>(key));
23923 }
23924
23925 template <typename Sig, typename Key, typename... Args>
23926 basic_table_core& set_function(Key&& key, Args&&... args) {
23927 set_fx(types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...);
23928 return *this;
23929 }
23930
23931 template <typename Key, typename... Args>
23932 basic_table_core& set_function(Key&& key, Args&&... args) {
23933 set_fx(types<>(), std::forward<Key>(key), std::forward<Args>(args)...);
23934 return *this;
23935 }
23936
23937 template <typename... Args>
23938 basic_table_core& add(Args&&... args) {
23939 auto pp = stack::push_pop(*this);
23940 int table_index = pp.index_of(*this);
23941 lua_State* L = base_t::lua_state();
23942 (void)detail::swallow { 0, (stack::set_ref(L, std::forward<Args>(args), table_index), 0)... };
23943 return *this;
23944 }
23945
23946 private:
23947 template <typename R, typename... Args, typename Fx, typename Key, typename = std::invoke_result_t<Fx, Args...>>
23948 void set_fx(types<R(Args...)>, Key&& key, Fx&& fx) {
23949 set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx));
23950 }
23951
23952 template <typename Fx, typename Key, meta::enable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler>
23953 void set_fx(types<>, Key&& key, Fx&& fx) {
23954 set(std::forward<Key>(key), std::forward<Fx>(fx));
23955 }
23956
23957 template <typename Fx, typename Key, typename... Args,
23958 meta::disable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler>
23959 void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) {
23960 set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...));
23961 }
23962
23963 template <typename... Sig, typename... Args, typename Key>
23964 void set_resolved_function(Key&& key, Args&&... args) {
23965 set(std::forward<Key>(key), as_function_reference<function_sig<Sig...>>(std::forward<Args>(args)...));
23966 }
23967
23968 public:
23969 static inline table create(lua_State* L, int narr = 0, int nrec = 0) {
23970 lua_createtable(L, narr, nrec);
23971 table result(L);
23972 lua_pop(L, 1);
23973 return result;
23974 }
23975
23976 template <typename Key, typename Value, typename... Args>
23977 static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
23978 lua_createtable(L, narr, nrec);
23979 table result(L);
23980 result.set(std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
23981 lua_pop(L, 1);
23982 return result;
23983 }
23984
23985 template <typename... Args>
23986 static inline table create_with(lua_State* L, Args&&... args) {
23987 static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list.");
23988 constexpr int narr = static_cast<int>(meta::count_odd_for_pack_v<std::is_integral, Args...>);
23989 return create(L, narr, static_cast<int>((sizeof...(Args) / 2) - narr), std::forward<Args>(args)...);
23990 }
23991
23992 table create(int narr = 0, int nrec = 0) {
23993 return create(base_t::lua_state(), narr, nrec);
23994 }
23995
23996 template <typename Key, typename Value, typename... Args>
23997 table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
23998 return create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
23999 }
24000
24001 template <typename Name>
24002 table create(Name&& name, int narr = 0, int nrec = 0) {
24003 table x = create(base_t::lua_state(), narr, nrec);
24004 this->set(std::forward<Name>(name), x);
24005 return x;
24006 }
24007
24008 template <typename Name, typename Key, typename Value, typename... Args>
24009 table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
24010 table x = create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
24011 this->set(std::forward<Name>(name), x);
24012 return x;
24013 }
24014
24015 template <typename... Args>
24016 table create_with(Args&&... args) {
24017 return create_with(base_t::lua_state(), std::forward<Args>(args)...);
24018 }
24019
24020 template <typename Name, typename... Args>
24021 table create_named(Name&& name, Args&&... args) {
24022 static const int narr = static_cast<int>(meta::count_even_for_pack_v<std::is_integral, Args...>);
24023 return create(std::forward<Name>(name), narr, (sizeof...(Args) / 2) - narr, std::forward<Args>(args)...);
24024 }
24025 };
24026} // namespace sol
24027
24028// end of sol/table_core.hpp
24029
24030namespace sol {
24031
24032 template <typename base_type>
24033 class basic_metatable : public basic_table<base_type> {
24034 typedef basic_table<base_type> base_t;
24035 friend class state;
24036 friend class state_view;
24037
24038 protected:
24039 basic_metatable(detail::no_safety_tag, lua_nil_t n) : base_t(n) {
24040 }
24041 basic_metatable(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) {
24042 }
24043 basic_metatable(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) {
24044 }
24045 template <typename T,
24046 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_metatable>>, meta::neg<std::is_same<base_type, stack_reference>>,
24047 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
24048 basic_metatable(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward<T>(r)) {
24049 }
24050 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
24051 basic_metatable(detail::no_safety_tag, lua_State* L, T&& r) noexcept : base_t(L, std::forward<T>(r)) {
24052 }
24053
24054 public:
24055 using base_t::lua_state;
24056
24057 basic_metatable() noexcept = default;
24058 basic_metatable(const basic_metatable&) = default;
24059 basic_metatable(basic_metatable&&) = default;
24060 basic_metatable& operator=(const basic_metatable&) = default;
24061 basic_metatable& operator=(basic_metatable&&) = default;
24062 basic_metatable(const stack_reference& r) : basic_metatable(r.lua_state(), r.stack_index()) {
24063 }
24064 basic_metatable(stack_reference&& r) : basic_metatable(r.lua_state(), r.stack_index()) {
24065 }
24066 template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
24067 basic_metatable(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
24068#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24069 auto pp = stack::push_pop(*this);
24070 constructor_handler handler{};
24071 stack::check<basic_metatable>(lua_state(), -1, handler);
24072#endif // Safety
24073 }
24074 basic_metatable(lua_State* L, int index = -1) : basic_metatable(detail::no_safety, L, index) {
24075#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24076 constructor_handler handler{};
24077 stack::check<basic_metatable>(L, index, handler);
24078#endif // Safety
24079 }
24080 basic_metatable(lua_State* L, ref_index index) : basic_metatable(detail::no_safety, L, index) {
24081#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24082 auto pp = stack::push_pop(*this);
24083 constructor_handler handler{};
24084 stack::check<basic_metatable>(lua_state(), -1, handler);
24085#endif // Safety
24086 }
24087 template <typename T,
24088 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_metatable>>, meta::neg<std::is_same<base_type, stack_reference>>,
24089 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
24090 basic_metatable(T&& r) noexcept : basic_metatable(detail::no_safety, std::forward<T>(r)) {
24091#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24092 if (!is_table<meta::unqualified_t<T>>::value) {
24093 auto pp = stack::push_pop(*this);
24094 constructor_handler handler{};
24095 stack::check<basic_metatable>(base_t::lua_state(), -1, handler);
24096 }
24097#endif // Safety
24098 }
24099 basic_metatable(lua_nil_t r) noexcept : basic_metatable(detail::no_safety, r) {
24100 }
24101
24102 template <typename Key, typename Value>
24103 void set(Key&& key, Value&& value);
24104
24105 void unregister() {
24106 using ustorage_base = u_detail::usertype_storage_base;
24107
24108 lua_State* L = this->lua_state();
24109
24110 auto pp = stack::push_pop(*this);
24111 int top = lua_gettop(L);
24112
24113 stack_reference mt(L, -1);
24114 stack::get_field(L, meta_function::gc_names, mt.stack_index());
24115 if (type_of(L, -1) != type::table) {
24116 return;
24117 }
24118 stack_reference gc_names_table(L, -1);
24119 stack::get_field(L, meta_function::storage, mt.stack_index());
24120 if (type_of(L, -1) != type::lightuserdata) {
24121 return;
24122 }
24123 ustorage_base& base_storage = *static_cast<ustorage_base*>(stack::get<void*>(L, -1));
24124 std::array<string_view, 6> registry_traits;
24125 for (std::size_t i = 0; i < registry_traits.size(); ++i) {
24126 u_detail::submetatable_type smt = static_cast<u_detail::submetatable_type>(i);
24127 stack::get_field<false, true>(L, smt, gc_names_table.stack_index());
24128 registry_traits[i] = stack::get<string_view>(L, -1);
24129 }
24130
24131 // get the registry
24132 stack_reference registry(L, raw_index(LUA_REGISTRYINDEX));
24133 registry.push();
24134 // eliminate all named entries for this usertype
24135 // in the registry (luaL_newmetatable does
24136 // [name] = new table
24137 // in registry upon creation)
24138 for (std::size_t i = 0; i < registry_traits.size(); ++i) {
24139 u_detail::submetatable_type smt = static_cast<u_detail::submetatable_type>(i);
24140 const string_view& gcmetakey = registry_traits[i];
24141 if (smt == u_detail::submetatable_type::named) {
24142 // use .data() to make it treat it like a c string,
24143 // which it is...
24144 stack::set_field<true>(L, gcmetakey.data(), lua_nil);
24145 }
24146 else {
24147 // do not change the values in the registry: they need to be present
24148 // no matter what, for safety's sake
24149 //stack::set_field(L, gcmetakey, lua_nil, registry.stack_index());
24150 }
24151 }
24152
24153 // destroy all storage and tables
24154 base_storage.clear();
24155
24156 // 6 strings from gc_names table,
24157 // + 1 registry,
24158 // + 1 gc_names table
24159 // + 1 light userdata of storage
24160 // + 1 registry
24161 // 10 total, 4 left since popping off 6 gc_names tables
24162 lua_settop(L, top);
24163 }
24164 };
24165
24166} // namespace sol
24167
24168// end of sol/metatable.hpp
24169
24170namespace sol {
24171
24172 template <typename T, typename base_type>
24173 class basic_usertype : private basic_metatable<base_type> {
24174 private:
24175 using base_t = basic_metatable<base_type>;
24176 using table_base_t = basic_table<base_type>;
24177
24178 template <typename>
24179 friend class basic_metatable;
24180
24181 template <bool, typename>
24182 friend class basic_table_core;
24183
24184 template <std::size_t... I, typename... Args>
24185 void tuple_set(std::index_sequence<I...>, std::tuple<Args...>&& args) {
24186 (void)args;
24187 (void)detail::swallow{ 0,
24188 (this->set(std::get<I * 2>(std::move(args)), std::get<I * 2 + 1>(std::move(args))), 0)... };
24189 }
24190
24191 public:
24192 using base_t::base_t;
24193
24194 using base_t::pop;
24195 using base_t::push;
24196 using base_t::lua_state;
24197 using base_t::get;
24198 using base_t::set_function;
24199 using base_t::traverse_set;
24200 using base_t::traverse_get;
24201 using base_t::unregister;
24202
24203 template <typename Key, typename Value>
24204 void set(Key&& key, Value&& value) {
24205 optional<u_detail::usertype_storage<T>&> maybe_uts = u_detail::maybe_get_usertype_storage<T>(this->lua_state());
24206 if (maybe_uts) {
24207 u_detail::usertype_storage<T>& uts = *maybe_uts;
24208 uts.set(this->lua_state(), std::forward<Key>(key), std::forward<Value>(value));
24209 }
24210 else {
24211 using ValueU = meta::unqualified_t<Value>;
24212 // cannot get metatable: try regular table set?
24213 if constexpr (detail::is_non_factory_constructor_v<ValueU> || detail::is_policy_v<ValueU>) {
24214 // tag constructors so we don't get destroyed by lack of info
24215 table_base_t::set(std::forward<Key>(key), detail::tagged<T, Value>(std::forward<Value>(value)));
24216 }
24217 else {
24218 table_base_t::set(std::forward<Key>(key), std::forward<Value>(value));
24219 }
24220 }
24221 }
24222
24223 template <typename Key>
24224 usertype_proxy<basic_usertype&, std::decay_t<Key>> operator[](Key&& key) {
24225 return usertype_proxy<basic_usertype&, std::decay_t<Key>>(*this, std::forward<Key>(key));
24226 }
24227
24228 template <typename Key>
24229 usertype_proxy<const basic_usertype&, std::decay_t<Key>> operator[](Key&& key) const {
24230 return usertype_proxy<const basic_usertype&, std::decay_t<Key>>(*this, std::forward<Key>(key));
24231 }
24232 };
24233
24234} // namespace sol
24235
24236// end of sol/usertype.hpp
24237
24238// beginning of sol/table.hpp
24239
24240// beginning of sol/lua_table.hpp
24241
24242namespace sol {
24243
24244 template <typename ref_t>
24245 struct basic_lua_table : basic_table_core<false, ref_t> {
24246 private:
24247 using base_t = basic_table_core<false, ref_t>;
24248
24249 friend class state;
24250 friend class state_view;
24251
24252 public:
24253 using base_t::lua_state;
24254
24255 basic_lua_table() noexcept = default;
24256 basic_lua_table(const basic_lua_table&) = default;
24257 basic_lua_table(basic_lua_table&&) = default;
24258 basic_lua_table& operator=(const basic_lua_table&) = default;
24259 basic_lua_table& operator=(basic_lua_table&&) = default;
24260 basic_lua_table(const stack_reference& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
24261 }
24262 basic_lua_table(stack_reference&& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
24263 }
24264 template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
24265 basic_lua_table(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
24266#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24267 auto pp = stack::push_pop(*this);
24268 constructor_handler handler{};
24269 stack::check<basic_lua_table>(lua_state(), -1, handler);
24270#endif // Safety
24271 }
24272 basic_lua_table(lua_State* L, const new_table& nt) : base_t(L, nt) {
24273 if (!is_stack_based<meta::unqualified_t<ref_t>>::value) {
24274 lua_pop(L, 1);
24275 }
24276 }
24277 basic_lua_table(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) {
24278#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24279 constructor_handler handler{};
24280 stack::check<basic_lua_table>(L, index, handler);
24281#endif // Safety
24282 }
24283 basic_lua_table(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) {
24284#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24285 auto pp = stack::push_pop(*this);
24286 constructor_handler handler{};
24287 stack::check<basic_lua_table>(lua_state(), -1, handler);
24288#endif // Safety
24289 }
24290 template <typename T,
24291 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_lua_table>>, meta::neg<std::is_same<ref_t, stack_reference>>,
24292 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
24293 basic_lua_table(T&& r) noexcept : basic_lua_table(detail::no_safety, std::forward<T>(r)) {
24294#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24295 if (!is_table<meta::unqualified_t<T>>::value) {
24296 auto pp = stack::push_pop(*this);
24297 constructor_handler handler{};
24298 stack::check<basic_lua_table>(lua_state(), -1, handler);
24299 }
24300#endif // Safety
24301 }
24302 basic_lua_table(lua_nil_t r) noexcept : basic_lua_table(detail::no_safety, r) {
24303 }
24304 };
24305
24306}
24307
24308// end of sol/lua_table.hpp
24309
24310namespace sol {
24311 typedef table_core<false> table;
24312
24313 template <bool is_global, typename base_type>
24314 template <typename Class, typename Key>
24315 usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key) {
24316 automagic_enrollments enrollments;
24317 return this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
24318 }
24319
24320 template <bool is_global, typename base_type>
24321 template <typename Class, typename Key>
24322 usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, automagic_enrollments enrollments) {
24323 int mt_index = u_detail::register_usertype<Class>(this->lua_state(), std::move(enrollments));
24324 usertype<Class> mt(this->lua_state(), -mt_index);
24325 lua_pop(this->lua_state(), 1);
24326 set(std::forward<Key>(key), mt);
24327 return mt;
24328 }
24329
24330 template <bool is_global, typename base_type>
24331 template <typename Class, typename Key, typename Arg, typename... Args, typename>
24332 usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, Arg&& arg, Args&&... args) {
24333 automagic_enrollments enrollments;
24334 enrollments.default_constructor = !detail::any_is_constructor_v<Arg, Args...>;
24335 enrollments.destructor = !detail::any_is_destructor_v<Arg, Args...>;
24336 usertype<Class> ut = this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
24337 static_assert(sizeof...(Args) % 2 == static_cast<std::size_t>(!detail::any_is_constructor_v<Arg>),
24338 "you must pass an even number of arguments to new_usertype after first passing a constructor");
24339 if constexpr (detail::any_is_constructor_v<Arg>) {
24340 ut.set(meta_function::construct, std::forward<Arg>(arg));
24341 ut.tuple_set(std::make_index_sequence<(sizeof...(Args)) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
24342 }
24343 else {
24344 ut.tuple_set(std::make_index_sequence<(sizeof...(Args) + 1) / 2>(), std::forward_as_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...));
24345 }
24346 return ut;
24347 }
24348
24349 template <typename base_type>
24350 template <typename Key, typename Value>
24351 void basic_metatable<base_type>::set(Key&& key, Value&& value) {
24352 this->push();
24353 lua_State* L = this->lua_state();
24354 int target = lua_gettop(L);
24355 optional<u_detail::usertype_storage_base&> maybe_uts = u_detail::maybe_get_usertype_storage_base(L, target);
24356 lua_pop(L, 1);
24357 if (maybe_uts) {
24358 u_detail::usertype_storage_base& uts = *maybe_uts;
24359 uts.set(L, std::forward<Key>(key), std::forward<Value>(value));
24360 }
24361 else {
24362 base_t::set(std::forward<Key>(key), std::forward<Value>(value));
24363 }
24364 }
24365
24366 namespace stack {
24367 template <>
24368 struct unqualified_getter<metatable_key_t> {
24369 static table get(lua_State* L, int index = -1) {
24370 if (lua_getmetatable(L, index) == 0) {
24371 return table(L, ref_index(LUA_REFNIL));
24372 }
24373 return table(L, -1);
24374 }
24375 };
24376 } // namespace stack
24377} // namespace sol
24378
24379// end of sol/table.hpp
24380
24381// beginning of sol/state.hpp
24382
24383// beginning of sol/state_view.hpp
24384
24385// beginning of sol/environment.hpp
24386
24387namespace sol {
24388
24389 template <typename base_type>
24390 struct basic_environment : basic_table<base_type> {
24391 private:
24392 typedef basic_table<base_type> base_t;
24393
24394 public:
24395 using base_t::lua_state;
24396
24397 basic_environment() noexcept = default;
24398 basic_environment(const basic_environment&) = default;
24399 basic_environment(basic_environment&&) = default;
24400 basic_environment& operator=(const basic_environment&) = default;
24401 basic_environment& operator=(basic_environment&&) = default;
24402 basic_environment(const stack_reference& r) : basic_environment(r.lua_state(), r.stack_index()) {
24403 }
24404 basic_environment(stack_reference&& r) : basic_environment(r.lua_state(), r.stack_index()) {
24405 }
24406
24407 basic_environment(lua_State* L, new_table nt) : base_t(L, std::move(nt)) {
24408 }
24409 template <bool b>
24410 basic_environment(lua_State* L, new_table t, const basic_reference<b>& fallback) : basic_environment(L, std::move(t)) {
24411 stack_table mt(L, new_table(0, 1));
24412 mt.set(meta_function::index, fallback);
24413 this->set(metatable_key, mt);
24414 mt.pop();
24415 }
24416
24417 basic_environment(env_key_t, const stack_reference& extraction_target)
24418 : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) {
24419#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24420 constructor_handler handler {};
24421 stack::check<env_key_t>(this->lua_state(), -1, handler);
24422#endif // Safety
24423 lua_pop(this->lua_state(), 2);
24424 }
24425 template <bool b>
24426 basic_environment(env_key_t, const basic_reference<b>& extraction_target)
24427 : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) {
24428#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24429 constructor_handler handler {};
24430 stack::check<env_key_t>(this->lua_state(), -1, handler);
24431#endif // Safety
24432 lua_pop(this->lua_state(), 2);
24433 }
24434 basic_environment(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) {
24435#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24436 constructor_handler handler {};
24437 stack::check<basic_environment>(L, index, handler);
24438#endif // Safety
24439 }
24440 basic_environment(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) {
24441#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24442 auto pp = stack::push_pop(*this);
24443 constructor_handler handler {};
24444 stack::check<basic_environment>(L, -1, handler);
24445#endif // Safety
24446 }
24447 template <typename T,
24448 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>,
24449 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
24450 basic_environment(T&& r) noexcept : base_t(detail::no_safety, std::forward<T>(r)) {
24451#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24452 if (!is_environment<meta::unqualified_t<T>>::value) {
24453 auto pp = stack::push_pop(*this);
24454 constructor_handler handler {};
24455 stack::check<basic_environment>(lua_state(), -1, handler);
24456 }
24457#endif // Safety
24458 }
24459 basic_environment(lua_nil_t r) noexcept : base_t(detail::no_safety, r) {
24460 }
24461
24462 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
24463 basic_environment(lua_State* L, T&& r) noexcept : base_t(detail::no_safety, L, std::forward<T>(r)) {
24464#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
24465 if (!is_environment<meta::unqualified_t<T>>::value) {
24466 auto pp = stack::push_pop(*this);
24467 constructor_handler handler {};
24468 stack::check<basic_environment>(lua_state(), -1, handler);
24469 }
24470#endif // Safety
24471 }
24472
24473 template <typename T>
24474 void set_on(const T& target) const {
24475 lua_State* L = target.lua_state();
24476 auto pp = stack::push_pop(target);
24477#if SOL_LUA_VESION_I_ < 502
24478 // Use lua_setfenv
24479 this->push();
24480 lua_setfenv(L, -2);
24481#else
24482 // Use upvalues as explained in Lua 5.2 and beyond's manual
24483 this->push();
24484 const char* name = lua_setupvalue(L, -2, 1);
24485 if (name == nullptr) {
24486 this->pop();
24487 }
24488#endif
24489 }
24490 };
24491
24492 template <typename T, typename E>
24493 void set_environment(const basic_environment<E>& env, const T& target) {
24494 env.set_on(target);
24495 }
24496
24497 template <typename E = reference, typename T>
24498 basic_environment<E> get_environment(const T& target) {
24499 lua_State* L = target.lua_state();
24500 auto pp = stack::pop_n(L, stack::push_environment_of(target));
24501 return basic_environment<E>(L, -1);
24502 }
24503
24504 struct this_environment {
24505 optional<environment> env;
24506
24507 this_environment() : env(nullopt) {
24508 }
24509 this_environment(environment e) : env(std::move(e)) {
24510 }
24511 this_environment(const this_environment&) = default;
24512 this_environment(this_environment&&) = default;
24513 this_environment& operator=(const this_environment&) = default;
24514 this_environment& operator=(this_environment&&) = default;
24515
24516 explicit operator bool() const {
24517 return static_cast<bool>(env);
24518 }
24519
24520 operator optional<environment> &() {
24521 return env;
24522 }
24523
24524 operator const optional<environment> &() const {
24525 return env;
24526 }
24527
24528 operator environment&() {
24529 return env.value();
24530 }
24531
24532 operator const environment&() const {
24533 return env.value();
24534 }
24535 };
24536
24537 namespace stack {
24538 template <>
24539 struct unqualified_getter<env_key_t> {
24540 static environment get(lua_State* L, int index, record& tracking) {
24541 tracking.use(1);
24542 return get_environment(stack_reference(L, raw_index(index)));
24543 }
24544 };
24545
24546 template <>
24547 struct unqualified_getter<this_environment> {
24548 static this_environment get(lua_State* L, int, record& tracking) {
24549 tracking.use(0);
24550 lua_Debug info;
24551 // Level 0 means current function (this C function, which may or may not be useful for us?)
24552 // Level 1 means next call frame up the stack. (Can be nothing if function called directly from C++ with lua_p/call)
24553 int pre_stack_size = lua_gettop(L);
24554 if (lua_getstack(L, 1, &info) != 1) {
24555 if (lua_getstack(L, 0, &info) != 1) {
24556 lua_settop(L, pre_stack_size);
24557 return this_environment();
24558 }
24559 }
24560 if (lua_getinfo(L, "f", &info) == 0) {
24561 lua_settop(L, pre_stack_size);
24562 return this_environment();
24563 }
24564
24565 stack_reference f(L, -1);
24566 environment env(env_key, f);
24567 if (!env.valid()) {
24568 lua_settop(L, pre_stack_size);
24569 return this_environment();
24570 }
24571 return this_environment(std::move(env));
24572 }
24573 };
24574 } // namespace stack
24575} // namespace sol
24576
24577// end of sol/environment.hpp
24578
24579// beginning of sol/load_result.hpp
24580
24581#include <cstdint>
24582
24583namespace sol {
24584 struct load_result : public proxy_base<load_result> {
24585 private:
24586 lua_State* L;
24587 int index;
24588 int returncount;
24589 int popcount;
24590 load_status err;
24591
24592 public:
24593 load_result() noexcept = default;
24594 load_result(lua_State* Ls, int stackindex = -1, int retnum = 0, int popnum = 0, load_status lerr = load_status::ok) noexcept
24595 : L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) {
24596 }
24597
24598 // We do not want anyone to copy these around willy-nilly
24599 // Will likely break people, but also will probably get rid of quiet bugs that have
24600 // been lurking. (E.g., Vanilla Lua will just quietly discard over-pops and under-pops:
24601 // LuaJIT and other Lua engines will implode and segfault at random later times.)
24602 load_result(const load_result&) = delete;
24603 load_result& operator=(const load_result&) = delete;
24604
24605 load_result(load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) {
24606 // Must be manual, otherwise destructor will screw us
24607 // return count being 0 is enough to keep things clean
24608 // but we will be thorough
24609 o.L = nullptr;
24610 o.index = 0;
24611 o.returncount = 0;
24612 o.popcount = 0;
24613 o.err = load_status::syntax;
24614 }
24615 load_result& operator=(load_result&& o) noexcept {
24616 L = o.L;
24617 index = o.index;
24618 returncount = o.returncount;
24619 popcount = o.popcount;
24620 err = o.err;
24621 // Must be manual, otherwise destructor will screw us
24622 // return count being 0 is enough to keep things clean
24623 // but we will be thorough
24624 o.L = nullptr;
24625 o.index = 0;
24626 o.returncount = 0;
24627 o.popcount = 0;
24628 o.err = load_status::syntax;
24629 return *this;
24630 }
24631
24632 load_status status() const noexcept {
24633 return err;
24634 }
24635
24636 bool valid() const noexcept {
24637 return status() == load_status::ok;
24638 }
24639
24640 template <typename T>
24641 T get() const {
24642 using UT = meta::unqualified_t<T>;
24643 if constexpr (meta::is_optional_v<UT>) {
24644 using ValueType = typename UT::value_type;
24645 if constexpr (std::is_same_v<ValueType, error>) {
24646 if (valid()) {
24647 return UT(nullopt);
24648 }
24649 return error(detail::direct_error, stack::get<std::string>(L, index));
24650 }
24651 else {
24652 if (!valid()) {
24653 return UT(nullopt);
24654 }
24655 return stack::get<UT>(L, index);
24656 }
24657 }
24658 else {
24659 if constexpr (std::is_same_v<T, error>) {
24660#if SOL_IS_ON(SOL_SAFE_PROXIES_I_)
24661 if (valid()) {
24662 type_panic_c_str(L, index, type_of(L, index), type::none, "expecting an error type (a string, from Lua)");
24663 }
24664#endif // Check proxy type's safety
24665 return error(detail::direct_error, stack::get<std::string>(L, index));
24666 }
24667 else {
24668#if SOL_IS_ON(SOL_SAFE_PROXIES_I_)
24669 if (!valid()) {
24670 type_panic_c_str(L, index, type_of(L, index), type::none);
24671 }
24672#endif // Check proxy type's safety
24673 return stack::get<T>(L, index);
24674 }
24675 }
24676 }
24677
24678 template <typename... Ret, typename... Args>
24679 decltype(auto) call(Args&&... args) {
24680#if !defined(__clang__) && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191200000
24681 // MSVC is ass sometimes
24682 return get<protected_function>().call<Ret...>(std::forward<Args>(args)...);
24683#else
24684 return get<protected_function>().template call<Ret...>(std::forward<Args>(args)...);
24685#endif
24686 }
24687
24688 template <typename... Args>
24689 decltype(auto) operator()(Args&&... args) {
24690 return call<>(std::forward<Args>(args)...);
24691 }
24692
24693 lua_State* lua_state() const noexcept {
24694 return L;
24695 };
24696 int stack_index() const noexcept {
24697 return index;
24698 };
24699
24700 ~load_result() {
24701 stack::remove(L, index, popcount);
24702 }
24703 };
24704} // namespace sol
24705
24706// end of sol/load_result.hpp
24707
24708// beginning of sol/state_handling.hpp
24709
24710// beginning of sol/lua_value.hpp
24711
24712namespace sol {
24713 struct lua_value {
24714 public:
24715 struct arr : detail::ebco<std::initializer_list<lua_value>> {
24716 private:
24717 using base_t = detail::ebco<std::initializer_list<lua_value>>;
24718
24719 public:
24720 using base_t::base_t;
24721 };
24722
24723 private:
24724 template <typename T>
24725 using is_reference_or_lua_value_init_list
24726 = meta::any<meta::is_specialization_of<T, std::initializer_list>, std::is_same<T, reference>, std::is_same<T, arr>>;
24727
24728 template <typename T>
24729 using is_lua_value_single_constructible = meta::any<std::is_same<T, lua_value>, is_reference_or_lua_value_init_list<T>>;
24730
24731 static lua_State*& thread_local_lua_state() {
24732#if SOL_IS_ON(SOL_USE_THREAD_LOCAL_I_)
24733 static thread_local lua_State* L = nullptr;
24734#else
24735 static lua_State* L = nullptr;
24736#endif
24737 return L;
24738 }
24739
24740 reference ref_value;
24741
24742 public:
24743 static void set_lua_state(lua_State* L) {
24744 thread_local_lua_state() = L;
24745 }
24746
24747 template <typename T, meta::disable<is_reference_or_lua_value_init_list<meta::unqualified_t<T>>> = meta::enabler>
24748 lua_value(lua_State* L_, T&& value) : lua_value(((set_lua_state(L_)), std::forward<T>(value))) {
24749 }
24750
24751 template <typename T, meta::disable<is_lua_value_single_constructible<meta::unqualified_t<T>>> = meta::enabler>
24752 lua_value(T&& value) : ref_value(make_reference(thread_local_lua_state(), std::forward<T>(value))) {
24753 }
24754
24755 lua_value(lua_State* L_, std::initializer_list<std::pair<lua_value, lua_value>> il)
24756 : lua_value([&L_, &il]() {
24757 set_lua_state(L_);
24758 return std::move(il);
24759 }()) {
24760 }
24761
24762 lua_value(std::initializer_list<std::pair<lua_value, lua_value>> il) : ref_value(make_reference(thread_local_lua_state(), std::move(il))) {
24763 }
24764
24765 lua_value(lua_State* L_, arr il)
24766 : lua_value([&L_, &il]() {
24767 set_lua_state(L_);
24768 return std::move(il);
24769 }()) {
24770 }
24771
24772 lua_value(arr il) : ref_value(make_reference(thread_local_lua_state(), std::move(il.value()))) {
24773 }
24774
24775 lua_value(lua_State* L_, reference r)
24776 : lua_value([&L_, &r]() {
24777 set_lua_state(L_);
24778 return std::move(r);
24779 }()) {
24780 }
24781
24782 lua_value(reference r) : ref_value(std::move(r)) {
24783 }
24784
24785 lua_value(const lua_value&) noexcept = default;
24786 lua_value(lua_value&&) = default;
24787 lua_value& operator=(const lua_value&) = default;
24788 lua_value& operator=(lua_value&&) = default;
24789
24790 const reference& value() const& {
24791 return ref_value;
24792 }
24793
24794 reference& value() & {
24795 return ref_value;
24796 }
24797
24798 reference&& value() && {
24799 return std::move(ref_value);
24800 }
24801
24802 template <typename T>
24803 decltype(auto) as() const {
24804 ref_value.push();
24805 return stack::pop<T>(ref_value.lua_state());
24806 }
24807
24808 template <typename T>
24809 bool is() const {
24810 int r = ref_value.registry_index();
24811 if (r == LUA_REFNIL)
24812 return meta::any_same<meta::unqualified_t<T>, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false;
24813 if (r == LUA_NOREF)
24814 return false;
24815 auto pp = stack::push_pop(ref_value);
24816 return stack::check<T>(ref_value.lua_state(), -1, no_panic);
24817 }
24818 };
24819
24820 using array_value = typename lua_value::arr;
24821
24822 namespace stack {
24823 template <>
24824 struct unqualified_pusher<lua_value> {
24825 static int push(lua_State* L, const lua_value& lv) {
24826 return stack::push(L, lv.value());
24827 }
24828
24829 static int push(lua_State* L, lua_value&& lv) {
24830 return stack::push(L, std::move(lv).value());
24831 }
24832 };
24833
24834 template <>
24835 struct unqualified_getter<lua_value> {
24836 static lua_value get(lua_State* L, int index, record& tracking) {
24837 return lua_value(L, stack::get<reference>(L, index, tracking));
24838 }
24839 };
24840 } // namespace stack
24841} // namespace sol
24842
24843// end of sol/lua_value.hpp
24844
24845#if SOL_IS_ON(SOL_PRINT_ERRORS_I_)
24846#include <iostream>
24847#endif
24848
24849namespace sol {
24850 inline void register_main_thread(lua_State* L) {
24851#if SOL_LUA_VESION_I_ < 502
24852 if (L == nullptr) {
24853 lua_pushnil(L);
24854 lua_setglobal(L, detail::default_main_thread_name());
24855 return;
24856 }
24857 lua_pushthread(L);
24858 lua_setglobal(L, detail::default_main_thread_name());
24859#else
24860 (void)L;
24861#endif
24862 }
24863
24864 inline int default_at_panic(lua_State* L) {
24865#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
24866 (void)L;
24867 return -1;
24868#else
24869 size_t messagesize;
24870 const char* message = lua_tolstring(L, -1, &messagesize);
24871 if (message) {
24872 std::string err(message, messagesize);
24873 lua_settop(L, 0);
24874#if SOL_IS_ON(SOL_PRINT_ERRORS_I_)
24875 std::cerr << "[sol3] An error occurred and panic has been invoked: ";
24876 std::cerr << err;
24877 std::cerr << std::endl;
24878#endif
24879 throw error(err);
24880 }
24881 lua_settop(L, 0);
24882 throw error(std::string("An unexpected error occurred and panic has been invoked"));
24883#endif // Printing Errors
24884 }
24885
24886 inline int default_traceback_error_handler(lua_State* L) {
24887 std::string msg = "An unknown error has triggered the default error handler";
24888 optional<string_view> maybetopmsg = stack::unqualified_check_get<string_view>(L, 1, no_panic);
24889 if (maybetopmsg) {
24890 const string_view& topmsg = maybetopmsg.value();
24891 msg.assign(topmsg.data(), topmsg.size());
24892 }
24893 luaL_traceback(L, L, msg.c_str(), 1);
24894 optional<string_view> maybetraceback = stack::unqualified_check_get<string_view>(L, -1, no_panic);
24895 if (maybetraceback) {
24896 const string_view& traceback = maybetraceback.value();
24897 msg.assign(traceback.data(), traceback.size());
24898 }
24899#if SOL_IS_ON(SOL_PRINT_ERRORS_I_)
24900 // std::cerr << "[sol3] An error occurred and was caught in traceback: ";
24901 // std::cerr << msg;
24902 // std::cerr << std::endl;
24903#endif // Printing
24904 return stack::push(L, msg);
24905 }
24906
24907 inline void set_default_state(lua_State* L, lua_CFunction panic_function = &default_at_panic,
24908 lua_CFunction traceback_function = c_call<decltype(&default_traceback_error_handler), &default_traceback_error_handler>,
24909 exception_handler_function exf = detail::default_exception_handler) {
24910 lua_atpanic(L, panic_function);
24911 protected_function::set_default_handler(object(L, in_place, traceback_function));
24912 set_default_exception_handler(L, exf);
24913 register_main_thread(L);
24914 stack::luajit_exception_handler(L);
24915 lua_value::set_lua_state(L);
24916 }
24917
24918 inline std::size_t total_memory_used(lua_State* L) {
24919 std::size_t kb = lua_gc(L, LUA_GCCOUNT, 0);
24920 kb *= 1024;
24921 kb += lua_gc(L, LUA_GCCOUNTB, 0);
24922 return kb;
24923 }
24924
24925 inline protected_function_result script_pass_on_error(lua_State*, protected_function_result result) {
24926 return result;
24927 }
24928
24929 inline protected_function_result script_throw_on_error(lua_State* L, protected_function_result result) {
24930 type t = type_of(L, result.stack_index());
24931 std::string err = "sol: ";
24932 err += to_string(result.status());
24933 err += " error";
24934#if SOL_IS_ON(SOL_EXCEPTIONS_I_)
24935 std::exception_ptr eptr = std::current_exception();
24936 if (eptr) {
24937 err += " with a ";
24938 try {
24939 std::rethrow_exception(eptr);
24940 }
24941 catch (const std::exception& ex) {
24942 err += "std::exception -- ";
24943 err.append(ex.what());
24944 }
24945 catch (const std::string& message) {
24946 err += "thrown message -- ";
24947 err.append(message);
24948 }
24949 catch (const char* message) {
24950 err += "thrown message -- ";
24951 err.append(message);
24952 }
24953 catch (...) {
24954 err.append("thrown but unknown type, cannot serialize into error message");
24955 }
24956 }
24957#endif // serialize exception information if possible
24958 if (t == type::string) {
24959 err += ": ";
24960 string_view serr = stack::unqualified_get<string_view>(L, result.stack_index());
24961 err.append(serr.data(), serr.size());
24962 }
24963#if SOL_IS_ON(SOL_PRINT_ERRORS_I_)
24964 std::cerr << "[sol3] An error occurred and has been passed to an error handler: ";
24965 std::cerr << err;
24966 std::cerr << std::endl;
24967#endif
24968 // replacing information of stack error into pfr
24969 int target = result.stack_index();
24970 if (result.pop_count() > 0) {
24971 stack::remove(L, target, result.pop_count());
24972 }
24973 stack::push(L, err);
24974 int top = lua_gettop(L);
24975 int towards = top - target;
24976 if (towards != 0) {
24977 lua_rotate(L, top, towards);
24978 }
24979#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
24980 return result;
24981#else
24982 // just throw our error
24983 throw error(detail::direct_error, err);
24984#endif // If exceptions are allowed
24985 }
24986
24987 inline protected_function_result script_default_on_error(lua_State* L, protected_function_result pfr) {
24988#if SOL_IS_ON(SOL_DEFAULT_PASS_ON_ERROR_I_)
24989 return script_pass_on_error(L, std::move(pfr));
24990#else
24991 return script_throw_on_error(L, std::move(pfr));
24992#endif
24993 }
24994
24995 namespace stack {
24996 inline error get_traceback_or_errors(lua_State* L) {
24997 int p = default_traceback_error_handler(L);
24998 sol::error err = stack::get<sol::error>(L, -p);
24999 lua_pop(L, p);
25000 return err;
25001 }
25002 } // namespace stack
25003} // namespace sol
25004
25005// end of sol/state_handling.hpp
25006
25007#include <memory>
25008#include <cstddef>
25009
25010namespace sol {
25011
25012 class state_view {
25013 private:
25014 lua_State* L;
25015 table reg;
25016 global_table global;
25017
25018 optional<object> is_loaded_package(const std::string& key) {
25019 auto loaded = reg.traverse_get<optional<object>>("_LOADED", key);
25020 bool is53mod = loaded && !(loaded->is<bool>() && !loaded->as<bool>());
25021 if (is53mod)
25022 return loaded;
25023#if SOL_LUA_VESION_I_ <= 501
25024 auto loaded51 = global.traverse_get<optional<object>>("package", "loaded", key);
25025 bool is51mod = loaded51 && !(loaded51->is<bool>() && !loaded51->as<bool>());
25026 if (is51mod)
25027 return loaded51;
25028#endif
25029 return nullopt;
25030 }
25031
25032 template <typename T>
25033 void ensure_package(const std::string& key, T&& sr) {
25034#if SOL_LUA_VESION_I_ <= 501
25035 auto pkg = global["package"];
25036 if (!pkg.valid()) {
25037 pkg = create_table_with("loaded", create_table_with(key, sr));
25038 }
25039 else {
25040 auto ld = pkg["loaded"];
25041 if (!ld.valid()) {
25042 ld = create_table_with(key, sr);
25043 }
25044 else {
25045 ld[key] = sr;
25046 }
25047 }
25048#endif
25049 auto loaded = reg["_LOADED"];
25050 if (!loaded.valid()) {
25051 loaded = create_table_with(key, sr);
25052 }
25053 else {
25054 loaded[key] = sr;
25055 }
25056 }
25057
25058 template <typename Fx>
25059 object require_core(const std::string& key, Fx&& action, bool create_global = true) {
25060 optional<object> loaded = is_loaded_package(key);
25061 if (loaded && loaded->valid())
25062 return std::move(*loaded);
25063 action();
25064 stack_reference sr(L, -1);
25065 if (create_global)
25066 set(key, sr);
25067 ensure_package(key, sr);
25068 return stack::pop<object>(L);
25069 }
25070
25071 public:
25072 using iterator = typename global_table::iterator;
25073 using const_iterator = typename global_table::const_iterator;
25074
25075 state_view(lua_State* Ls) : L(Ls), reg(Ls, LUA_REGISTRYINDEX), global(Ls, detail::global_) {
25076 }
25077
25078 state_view(this_state Ls) : state_view(Ls.L) {
25079 }
25080
25081 lua_State* lua_state() const {
25082 return L;
25083 }
25084
25085 template <typename... Args>
25086 void open_libraries(Args&&... args) {
25087 static_assert(meta::all_same<lib, meta::unqualified_t<Args>...>::value, "all types must be libraries");
25088 if constexpr (sizeof...(args) == 0) {
25089 luaL_openlibs(L);
25090 return;
25091 }
25092 else {
25093 lib libraries[1 + sizeof...(args)] = { lib::count, std::forward<Args>(args)... };
25094
25095 for (auto&& library : libraries) {
25096 switch (library) {
25097#if SOL_LUA_VESION_I_ <= 501 && defined(SOL_LUAJIT)
25098 case lib::coroutine:
25099#endif // luajit opens coroutine base stuff
25100 case lib::base:
25101 luaL_requiref(L, "base", luaopen_base, 1);
25102 lua_pop(L, 1);
25103 break;
25104 case lib::package:
25105 luaL_requiref(L, "package", luaopen_package, 1);
25106 lua_pop(L, 1);
25107 break;
25108#if !defined(SOL_LUAJIT)
25109 case lib::coroutine:
25110#if SOL_LUA_VESION_I_ > 501
25111 luaL_requiref(L, "coroutine", luaopen_coroutine, 1);
25112 lua_pop(L, 1);
25113#endif // Lua 5.2+ only
25114 break;
25115#endif // Not LuaJIT - comes builtin
25116 case lib::string:
25117 luaL_requiref(L, "string", luaopen_string, 1);
25118 lua_pop(L, 1);
25119 break;
25120 case lib::table:
25121 luaL_requiref(L, "table", luaopen_table, 1);
25122 lua_pop(L, 1);
25123 break;
25124 case lib::math:
25125 luaL_requiref(L, "math", luaopen_math, 1);
25126 lua_pop(L, 1);
25127 break;
25128 case lib::bit32:
25129#ifdef SOL_LUAJIT
25130 luaL_requiref(L, "bit32", luaopen_bit, 1);
25131 lua_pop(L, 1);
25132#elif (SOL_LUA_VESION_I_ == 502) || defined(LUA_COMPAT_BITLIB) || defined(LUA_COMPAT_5_2)
25133 luaL_requiref(L, "bit32", luaopen_bit32, 1);
25134 lua_pop(L, 1);
25135#else
25136#endif // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags)
25137 break;
25138 case lib::io:
25139 luaL_requiref(L, "io", luaopen_io, 1);
25140 lua_pop(L, 1);
25141 break;
25142 case lib::os:
25143 luaL_requiref(L, "os", luaopen_os, 1);
25144 lua_pop(L, 1);
25145 break;
25146 case lib::debug:
25147 luaL_requiref(L, "debug", luaopen_debug, 1);
25148 lua_pop(L, 1);
25149 break;
25150 case lib::utf8:
25151#if SOL_LUA_VESION_I_ > 502 && !defined(SOL_LUAJIT)
25152 luaL_requiref(L, "utf8", luaopen_utf8, 1);
25153 lua_pop(L, 1);
25154#endif // Lua 5.3+ only
25155 break;
25156 case lib::ffi:
25157#ifdef SOL_LUAJIT
25158 luaL_requiref(L, "ffi", luaopen_ffi, 1);
25159 lua_pop(L, 1);
25160#endif // LuaJIT only
25161 break;
25162 case lib::jit:
25163#ifdef SOL_LUAJIT
25164 luaL_requiref(L, "jit", luaopen_jit, 0);
25165 lua_pop(L, 1);
25166#endif // LuaJIT Only
25167 break;
25168 case lib::count:
25169 default:
25170 break;
25171 }
25172 }
25173 }
25174 }
25175
25176 object require(const std::string& key, lua_CFunction open_function, bool create_global = true) {
25177 luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0);
25178 return stack::pop<object>(L);
25179 }
25180
25181 object require_script(const std::string& key, const string_view& code, bool create_global = true,
25182 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25183 auto action = [this, &code, &chunkname, &mode]() { stack::script(L, code, chunkname, mode); };
25184 return require_core(key, action, create_global);
25185 }
25186
25187 object require_file(const std::string& key, const std::string& filename, bool create_global = true, load_mode mode = load_mode::any) {
25188 auto action = [this, &filename, &mode]() { stack::script_file(L, filename, mode); };
25189 return require_core(key, action, create_global);
25190 }
25191
25192 void clear_package_loaders() {
25193 optional<table> maybe_package = this->global["package"];
25194 if (!maybe_package) {
25195 // package lib wasn't opened
25196 // open package lib
25197 return;
25198 }
25199 table& package = *maybe_package;
25200 // yay for version differences...
25201 // one day Lua 5.1 will die a peaceful death
25202 // and its old bones will find blissful rest
25203 auto loaders_proxy = package
25204#if SOL_LUA_VESION_I_ < 502
25205 ["loaders"]
25206#else
25207 ["searchers"]
25208#endif
25209 ;
25210 if (!loaders_proxy.valid()) {
25211 // nothing to clear
25212 return;
25213 }
25214 // we need to create the table for loaders
25215 // table does not exist, so create and move forward
25216 loaders_proxy = new_table(1, 0);
25217 }
25218
25219 template <typename Fx>
25220 void add_package_loader(Fx&& fx, bool clear_all_package_loaders = false) {
25221 optional<table> maybe_package = this->global["package"];
25222 if (!maybe_package) {
25223 // package lib wasn't opened
25224 // open package lib
25225 return;
25226 }
25227 table& package = *maybe_package;
25228 // yay for version differences...
25229 // one day Lua 5.1 will die a peaceful death
25230 // and its old bones will find blissful rest
25231 auto loaders_proxy = package
25232#if SOL_LUA_VESION_I_ < 502
25233 ["loaders"]
25234#else
25235 ["searchers"]
25236#endif
25237 ;
25238 bool make_new_table = clear_all_package_loaders || !loaders_proxy.valid();
25239 if (make_new_table) {
25240 // we need to create the table for loaders
25241 // table does not exist, so create and move forward
25242 loaders_proxy = new_table(1, 0);
25243 }
25244 optional<table> maybe_loaders = loaders_proxy;
25245 if (!maybe_loaders) {
25246 // loaders/searches
25247 // thing exists in package, but it
25248 // ain't a table or a table-alike...!
25249 return;
25250 }
25251 table loaders = loaders_proxy;
25252 loaders.add(std::forward<Fx>(fx));
25253 }
25254
25255 template <typename E>
25256 protected_function_result do_reader(lua_Reader reader, void* data, const basic_environment<E>& env,
25257 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25258 detail::typical_chunk_name_t basechunkname = {};
25259 const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
25260 load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
25261 if (x != load_status::ok) {
25262 return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
25263 }
25264 stack_aligned_protected_function pf(L, -1);
25265 set_environment(env, pf);
25266 return pf();
25267 }
25268
25269 protected_function_result do_reader(
25270 lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25271 detail::typical_chunk_name_t basechunkname = {};
25272 const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
25273 load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
25274 if (x != load_status::ok) {
25275 return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
25276 }
25277 stack_aligned_protected_function pf(L, -1);
25278 return pf();
25279 }
25280
25281 template <typename E>
25282 protected_function_result do_string(const string_view& code, const basic_environment<E>& env,
25283 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25284 detail::typical_chunk_name_t basechunkname = {};
25285 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
25286 load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
25287 if (x != load_status::ok) {
25288 return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
25289 }
25290 stack_aligned_protected_function pf(L, -1);
25291 set_environment(env, pf);
25292 return pf();
25293 }
25294
25295 protected_function_result do_string(
25296 const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25297 detail::typical_chunk_name_t basechunkname = {};
25298 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
25299 load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
25300 if (x != load_status::ok) {
25301 return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
25302 }
25303 stack_aligned_protected_function pf(L, -1);
25304 return pf();
25305 }
25306
25307 template <typename E>
25308 protected_function_result do_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
25309 load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
25310 if (x != load_status::ok) {
25311 return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
25312 }
25313 stack_aligned_protected_function pf(L, -1);
25314 set_environment(env, pf);
25315 return pf();
25316 }
25317
25318 protected_function_result do_file(const std::string& filename, load_mode mode = load_mode::any) {
25319 load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
25320 if (x != load_status::ok) {
25321 return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
25322 }
25323 stack_aligned_protected_function pf(L, -1);
25324 return pf();
25325 }
25326
25327 template <typename Fx,
25328 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
25329 meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
25330 protected_function_result safe_script(
25331 lua_Reader reader, void* data, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25332 protected_function_result pfr = do_reader(reader, data, chunkname, mode);
25333 if (!pfr.valid()) {
25334 return on_error(L, std::move(pfr));
25335 }
25336 return pfr;
25337 }
25338
25339 protected_function_result safe_script(
25340 lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25341 return safe_script(reader, data, script_default_on_error, chunkname, mode);
25342 }
25343
25344 template <typename Fx,
25345 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
25346 meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
25347 protected_function_result safe_script(
25348 const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25349 protected_function_result pfr = do_string(code, chunkname, mode);
25350 if (!pfr.valid()) {
25351 return on_error(L, std::move(pfr));
25352 }
25353 return pfr;
25354 }
25355
25356 template <typename Fx, typename E>
25357 protected_function_result safe_script(const string_view& code, const basic_environment<E>& env, Fx&& on_error,
25358 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25359 protected_function_result pfr = do_string(code, env, chunkname, mode);
25360 if (!pfr.valid()) {
25361 return on_error(L, std::move(pfr));
25362 }
25363 return pfr;
25364 }
25365
25366 template <typename E>
25367 protected_function_result safe_script(const string_view& code, const basic_environment<E>& env,
25368 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25369 return safe_script(code, env, script_default_on_error, chunkname, mode);
25370 }
25371
25372 protected_function_result safe_script(
25373 const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25374 return safe_script(code, script_default_on_error, chunkname, mode);
25375 }
25376
25377 template <typename Fx,
25378 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
25379 meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
25380 protected_function_result safe_script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) {
25381 protected_function_result pfr = do_file(filename, mode);
25382 if (!pfr.valid()) {
25383 return on_error(L, std::move(pfr));
25384 }
25385 return pfr;
25386 }
25387
25388 template <typename Fx, typename E>
25389 protected_function_result safe_script_file(
25390 const std::string& filename, const basic_environment<E>& env, Fx&& on_error, load_mode mode = load_mode::any) {
25391 protected_function_result pfr = do_file(filename, env, mode);
25392 if (!pfr.valid()) {
25393 return on_error(L, std::move(pfr));
25394 }
25395 return pfr;
25396 }
25397
25398 template <typename E>
25399 protected_function_result safe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
25400 return safe_script_file(filename, env, script_default_on_error, mode);
25401 }
25402
25403 protected_function_result safe_script_file(const std::string& filename, load_mode mode = load_mode::any) {
25404 return safe_script_file(filename, script_default_on_error, mode);
25405 }
25406
25407 template <typename E>
25408 unsafe_function_result unsafe_script(lua_Reader reader, void* data, const basic_environment<E>& env,
25409 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25410 detail::typical_chunk_name_t basechunkname = {};
25411 const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
25412 int index = lua_gettop(L);
25413 if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())) {
25414 lua_error(L);
25415 }
25416 set_environment(env, stack_reference(L, raw_index(index + 1)));
25417 if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
25418 lua_error(L);
25419 }
25420 int postindex = lua_gettop(L);
25421 int returns = postindex - index;
25422 return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
25423 }
25424
25425 unsafe_function_result unsafe_script(
25426 lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25427 int index = lua_gettop(L);
25428 stack::script(L, reader, data, chunkname, mode);
25429 int postindex = lua_gettop(L);
25430 int returns = postindex - index;
25431 return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
25432 }
25433
25434 template <typename E>
25435 unsafe_function_result unsafe_script(const string_view& code, const basic_environment<E>& env,
25436 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25437 detail::typical_chunk_name_t basechunkname = {};
25438 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
25439 int index = lua_gettop(L);
25440 if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())) {
25441 lua_error(L);
25442 }
25443 set_environment(env, stack_reference(L, raw_index(index + 1)));
25444 if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
25445 lua_error(L);
25446 }
25447 int postindex = lua_gettop(L);
25448 int returns = postindex - index;
25449 return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
25450 }
25451
25452 unsafe_function_result unsafe_script(
25453 const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25454 int index = lua_gettop(L);
25455 stack::script(L, code, chunkname, mode);
25456 int postindex = lua_gettop(L);
25457 int returns = postindex - index;
25458 return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
25459 }
25460
25461 template <typename E>
25462 unsafe_function_result unsafe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
25463 int index = lua_gettop(L);
25464 if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) {
25465 lua_error(L);
25466 }
25467 set_environment(env, stack_reference(L, raw_index(index + 1)));
25468 if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
25469 lua_error(L);
25470 }
25471 int postindex = lua_gettop(L);
25472 int returns = postindex - index;
25473 return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
25474 }
25475
25476 unsafe_function_result unsafe_script_file(const std::string& filename, load_mode mode = load_mode::any) {
25477 int index = lua_gettop(L);
25478 stack::script_file(L, filename, mode);
25479 int postindex = lua_gettop(L);
25480 int returns = postindex - index;
25481 return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
25482 }
25483
25484 template <typename Fx,
25485 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
25486 meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
25487 protected_function_result script(
25488 const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25489 return safe_script(code, std::forward<Fx>(on_error), chunkname, mode);
25490 }
25491
25492 template <typename Fx,
25493 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
25494 meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
25495 protected_function_result script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) {
25496 return safe_script_file(filename, std::forward<Fx>(on_error), mode);
25497 }
25498
25499 template <typename Fx, typename E>
25500 protected_function_result script(const string_view& code, const basic_environment<E>& env, Fx&& on_error,
25501 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25502 return safe_script(code, env, std::forward<Fx>(on_error), chunkname, mode);
25503 }
25504
25505 template <typename Fx, typename E>
25506 protected_function_result script_file(const std::string& filename, const basic_environment<E>& env, Fx&& on_error, load_mode mode = load_mode::any) {
25507 return safe_script_file(filename, env, std::forward<Fx>(on_error), mode);
25508 }
25509
25510 protected_function_result script(
25511 const string_view& code, const environment& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25512 return safe_script(code, env, script_default_on_error, chunkname, mode);
25513 }
25514
25515 protected_function_result script_file(const std::string& filename, const environment& env, load_mode mode = load_mode::any) {
25516 return safe_script_file(filename, env, script_default_on_error, mode);
25517 }
25518
25519#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS_I_)
25520 protected_function_result script(
25521 lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25522 return safe_script(reader, data, chunkname, mode);
25523 }
25524
25525 protected_function_result script(
25526 const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25527 return safe_script(code, chunkname, mode);
25528 }
25529
25530 protected_function_result script_file(const std::string& filename, load_mode mode = load_mode::any) {
25531 return safe_script_file(filename, mode);
25532 }
25533#else
25534 unsafe_function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25535 return unsafe_script(code, chunkname, mode);
25536 }
25537
25538 unsafe_function_result script_file(const std::string& filename, load_mode mode = load_mode::any) {
25539 return unsafe_script_file(filename, mode);
25540 }
25541#endif
25542 load_result load(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25543 detail::typical_chunk_name_t basechunkname = {};
25544 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
25545 load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
25546 return load_result(L, absolute_index(L, -1), 1, 1, x);
25547 }
25548
25549 load_result load_buffer(const char* buff, size_t size, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25550 return load(string_view(buff, size), chunkname, mode);
25551 }
25552
25553 load_result load_buffer(
25554 const std::byte* buff, size_t size, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25555 return load(string_view(reinterpret_cast<const char*>(buff), size), chunkname, mode);
25556 }
25557
25558 load_result load_file(const std::string& filename, load_mode mode = load_mode::any) {
25559 load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
25560 return load_result(L, absolute_index(L, -1), 1, 1, x);
25561 }
25562
25563 load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
25564 detail::typical_chunk_name_t basechunkname = {};
25565 const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
25566 load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
25567 return load_result(L, absolute_index(L, -1), 1, 1, x);
25568 }
25569
25570 iterator begin() const {
25571 return global.begin();
25572 }
25573
25574 iterator end() const {
25575 return global.end();
25576 }
25577
25578 const_iterator cbegin() const {
25579 return global.cbegin();
25580 }
25581
25582 const_iterator cend() const {
25583 return global.cend();
25584 }
25585
25586 global_table globals() const {
25587 // if we return a reference
25588 // we'll be screwed a bit
25589 return global;
25590 }
25591
25592 global_table& globals() {
25593 return global;
25594 }
25595
25596 table registry() const {
25597 return reg;
25598 }
25599
25600 std::size_t memory_used() const {
25601 return total_memory_used(lua_state());
25602 }
25603
25604 int stack_top() const {
25605 return stack::top(L);
25606 }
25607
25608 int stack_clear() {
25609 int s = stack_top();
25610 lua_pop(L, s);
25611 return s;
25612 }
25613
25614 bool supports_gc_mode(gc_mode mode) const noexcept {
25615#if SOL_LUA_VESION_I_ >= 504
25616 // supports all modes
25617 (void)mode;
25618 return true;
25619#endif
25620 return mode == gc_mode::default_value;
25621 }
25622
25623 bool is_gc_on() const {
25624#if SOL_LUA_VESION_I_ >= 502
25625 return lua_gc(lua_state(), LUA_GCISRUNNING, 0) == 1;
25626#else
25627 // You cannot turn it off in Lua 5.1
25628 return true;
25629#endif
25630 }
25631
25632 void collect_garbage() {
25633 lua_gc(lua_state(), LUA_GCCOLLECT, 0);
25634 }
25635
25636 void collect_gc() {
25637 collect_garbage();
25638 }
25639
25640 bool step_gc(int step_size_kilobytes) {
25641 // THOUGHT: std::chrono-alikes to map "kilobyte size" here...?
25642 // Make it harder to give MB or KB to a B parameter...?
25643 // Probably overkill for now.
25644#if SOL_LUA_VESION_I_ >= 504
25645 // The manual implies that this function is almost always successful...
25646 // is it?? It could depend on the GC mode...
25647 return lua_gc(lua_state(), LUA_GCSTEP, step_size_kilobytes) != 0;
25648#else
25649 return lua_gc(lua_state(), LUA_GCSTEP, step_size_kilobytes) == 1;
25650#endif
25651 }
25652
25653 void restart_gc() {
25654 lua_gc(lua_state(), LUA_GCRESTART, 0);
25655 }
25656
25657 void stop_gc() {
25658 lua_gc(lua_state(), LUA_GCSTOP, 0);
25659 }
25660
25661 // Returns the old GC mode. Check support using the supports_gc_mode function.
25662 gc_mode change_gc_mode_incremental(int pause, int step_multiplier, int step_byte_size) {
25663 // "What the fuck does any of this mean??"
25664 // http://www.lua.org/manual/5.4/manual.html#2.5.1
25665
25666 // THOUGHT: std::chrono-alikes to map "byte size" here...?
25667 // Make it harder to give MB or KB to a B parameter...?
25668 // Probably overkill for now.
25669#if SOL_LUA_VESION_I_ >= 504
25670 int old_mode = lua_gc(lua_state(), LUA_GCINC, pause, step_multiplier, step_byte_size);
25671 if (old_mode == LUA_GCGEN) {
25672 return gc_mode::generational;
25673 }
25674 else if (old_mode == LUA_GCINC) {
25675 return gc_mode::incremental;
25676 }
25677#else
25678 lua_gc(lua_state(), LUA_GCSETPAUSE, pause);
25679 lua_gc(lua_state(), LUA_GCSETSTEPMUL, step_multiplier);
25680 (void)step_byte_size; // means nothing in older versions
25681#endif
25682 return gc_mode::default_value;
25683 }
25684
25685 // Returns the old GC mode. Check support using the supports_gc_mode function.
25686 gc_mode change_gc_mode_generational(int minor_multiplier, int major_multiplier) {
25687#if SOL_LUA_VESION_I_ >= 504
25688 // "What does this shit mean?"
25689 // http://www.lua.org/manual/5.4/manual.html#2.5.2
25690 int old_mode = lua_gc(lua_state(), LUA_GCGEN, minor_multiplier, major_multiplier);
25691 if (old_mode == LUA_GCGEN) {
25692 return gc_mode::generational;
25693 }
25694 else if (old_mode == LUA_GCINC) {
25695 return gc_mode::incremental;
25696 }
25697#endif
25698 return gc_mode::default_value;
25699 }
25700
25701 operator lua_State*() const {
25702 return lua_state();
25703 }
25704
25705 void set_panic(lua_CFunction panic) {
25706 lua_atpanic(lua_state(), panic);
25707 }
25708
25709 void set_exception_handler(exception_handler_function handler) {
25710 set_default_exception_handler(lua_state(), handler);
25711 }
25712
25713 template <typename... Args, typename... Keys>
25714 decltype(auto) get(Keys&&... keys) const {
25715 return global.get<Args...>(std::forward<Keys>(keys)...);
25716 }
25717
25718 template <typename T, typename Key>
25719 decltype(auto) get_or(Key&& key, T&& otherwise) const {
25720 return global.get_or(std::forward<Key>(key), std::forward<T>(otherwise));
25721 }
25722
25723 template <typename T, typename Key, typename D>
25724 decltype(auto) get_or(Key&& key, D&& otherwise) const {
25725 return global.get_or<T>(std::forward<Key>(key), std::forward<D>(otherwise));
25726 }
25727
25728 template <typename... Args>
25729 state_view& set(Args&&... args) {
25730 global.set(std::forward<Args>(args)...);
25731 return *this;
25732 }
25733
25734 template <typename T, typename... Keys>
25735 decltype(auto) traverse_get(Keys&&... keys) const {
25736 return global.traverse_get<T>(std::forward<Keys>(keys)...);
25737 }
25738
25739 template <typename... Args>
25740 state_view& traverse_set(Args&&... args) {
25741 global.traverse_set(std::forward<Args>(args)...);
25742 return *this;
25743 }
25744
25745 template <typename Class, typename... Args>
25746 usertype<Class> new_usertype(const std::string& name, Args&&... args) {
25747 return global.new_usertype<Class>(name, std::forward<Args>(args)...);
25748 }
25749
25750 template <bool read_only = true, typename... Args>
25751 state_view& new_enum(const string_view& name, Args&&... args) {
25752 global.new_enum<read_only>(name, std::forward<Args>(args)...);
25753 return *this;
25754 }
25755
25756 template <typename T, bool read_only = true>
25757 state_view& new_enum(const string_view& name, std::initializer_list<std::pair<string_view, T>> items) {
25758 global.new_enum<T, read_only>(name, std::move(items));
25759 return *this;
25760 }
25761
25762 template <typename Fx>
25763 void for_each(Fx&& fx) {
25764 global.for_each(std::forward<Fx>(fx));
25765 }
25766
25767 template <typename T>
25768 table_proxy<global_table&, detail::proxy_key_t<T>> operator[](T&& key) {
25769 return global[std::forward<T>(key)];
25770 }
25771
25772 template <typename T>
25773 table_proxy<const global_table&, detail::proxy_key_t<T>> operator[](T&& key) const {
25774 return global[std::forward<T>(key)];
25775 }
25776
25777 template <typename Sig, typename... Args, typename Key>
25778 state_view& set_function(Key&& key, Args&&... args) {
25779 global.set_function<Sig>(std::forward<Key>(key), std::forward<Args>(args)...);
25780 return *this;
25781 }
25782
25783 template <typename... Args, typename Key>
25784 state_view& set_function(Key&& key, Args&&... args) {
25785 global.set_function(std::forward<Key>(key), std::forward<Args>(args)...);
25786 return *this;
25787 }
25788
25789 template <typename Name>
25790 table create_table(Name&& name, int narr = 0, int nrec = 0) {
25791 return global.create(std::forward<Name>(name), narr, nrec);
25792 }
25793
25794 template <typename Name, typename Key, typename Value, typename... Args>
25795 table create_table(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
25796 return global.create(std::forward<Name>(name), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
25797 }
25798
25799 template <typename Name, typename... Args>
25800 table create_named_table(Name&& name, Args&&... args) {
25801 table x = global.create_with(std::forward<Args>(args)...);
25802 global.set(std::forward<Name>(name), x);
25803 return x;
25804 }
25805
25806 table create_table(int narr = 0, int nrec = 0) {
25807 return create_table(lua_state(), narr, nrec);
25808 }
25809
25810 template <typename Key, typename Value, typename... Args>
25811 table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
25812 return create_table(lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
25813 }
25814
25815 template <typename... Args>
25816 table create_table_with(Args&&... args) {
25817 return create_table_with(lua_state(), std::forward<Args>(args)...);
25818 }
25819
25820 static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) {
25821 return global_table::create(L, narr, nrec);
25822 }
25823
25824 template <typename Key, typename Value, typename... Args>
25825 static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
25826 return global_table::create(L, narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
25827 }
25828
25829 template <typename... Args>
25830 static inline table create_table_with(lua_State* L, Args&&... args) {
25831 return global_table::create_with(L, std::forward<Args>(args)...);
25832 }
25833 };
25834} // namespace sol
25835
25836// end of sol/state_view.hpp
25837
25838// beginning of sol/thread.hpp
25839
25840namespace sol {
25841 struct lua_thread_state {
25842 lua_State* L;
25843
25844 lua_thread_state(lua_State* Ls)
25845 : L(Ls) {
25846 }
25847
25848 lua_State* lua_state() const noexcept {
25849 return L;
25850 }
25851 operator lua_State*() const noexcept {
25852 return lua_state();
25853 }
25854 lua_State* operator->() const noexcept {
25855 return lua_state();
25856 }
25857 };
25858
25859 namespace stack {
25860 template <>
25861 struct unqualified_pusher<lua_thread_state> {
25862 int push(lua_State*, lua_thread_state lts) {
25863 lua_pushthread(lts.L);
25864 return 1;
25865 }
25866 };
25867
25868 template <>
25869 struct unqualified_getter<lua_thread_state> {
25870 lua_thread_state get(lua_State* L, int index, record& tracking) {
25871 tracking.use(1);
25872 lua_thread_state lts( lua_tothread(L, index) );
25873 return lts;
25874 }
25875 };
25876
25877 template <>
25878 struct unqualified_check_getter<lua_thread_state> {
25879 template <typename Handler>
25880 optional<lua_thread_state> get(lua_State* L, int index, Handler&& handler, record& tracking) {
25881 lua_thread_state lts( lua_tothread(L, index) );
25882 if (lts.lua_state() == nullptr) {
25883 handler(L, index, type::thread, type_of(L, index), "value is not a valid thread type");
25884 return nullopt;
25885 }
25886 tracking.use(1);
25887 return lts;
25888 }
25889 };
25890 } // namespace stack
25891
25892 template <typename ref_t>
25893 class basic_thread : public basic_object<ref_t> {
25894 private:
25895 using base_t = basic_object<ref_t>;
25896
25897 public:
25898 using base_t::lua_state;
25899
25900 basic_thread() noexcept = default;
25901 basic_thread(const basic_thread&) = default;
25902 basic_thread(basic_thread&&) = default;
25903 template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_thread>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
25904 basic_thread(T&& r)
25905 : base_t(std::forward<T>(r)) {
25906#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
25907 auto pp = stack::push_pop(*this);
25908 constructor_handler handler{};
25909 stack::check<basic_thread>(lua_state(), -1, handler);
25910#endif // Safety
25911 }
25912 basic_thread(const stack_reference& r)
25913 : basic_thread(r.lua_state(), r.stack_index()){};
25914 basic_thread(stack_reference&& r)
25915 : basic_thread(r.lua_state(), r.stack_index()){};
25916 basic_thread& operator=(const basic_thread&) = default;
25917 basic_thread& operator=(basic_thread&&) = default;
25918 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
25919 basic_thread(lua_State* L, T&& r)
25920 : base_t(L, std::forward<T>(r)) {
25921#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
25922 auto pp = stack::push_pop(*this);
25923 constructor_handler handler{};
25924 stack::check<basic_thread>(lua_state(), -1, handler);
25925#endif // Safety
25926 }
25927 basic_thread(lua_State* L, int index = -1)
25928 : base_t(L, index) {
25929#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
25930 constructor_handler handler{};
25931 stack::check<basic_thread>(L, index, handler);
25932#endif // Safety
25933 }
25934 basic_thread(lua_State* L, ref_index index)
25935 : base_t(L, index) {
25936#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
25937 auto pp = stack::push_pop(*this);
25938 constructor_handler handler{};
25939 stack::check<basic_thread>(lua_state(), -1, handler);
25940#endif // Safety
25941 }
25942 basic_thread(lua_State* L, lua_State* actualthread)
25943 : basic_thread(L, lua_thread_state{ actualthread }) {
25944 }
25945 basic_thread(lua_State* L, this_state actualthread)
25946 : basic_thread(L, lua_thread_state{ actualthread.L }) {
25947 }
25948 basic_thread(lua_State* L, lua_thread_state actualthread)
25949 : base_t(L, -stack::push(L, actualthread)) {
25950#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
25951 constructor_handler handler{};
25952 stack::check<basic_thread>(lua_state(), -1, handler);
25953#endif // Safety
25954 if (!is_stack_based<base_t>::value) {
25955 lua_pop(lua_state(), 1);
25956 }
25957 }
25958
25959 state_view state() const {
25960 return state_view(this->thread_state());
25961 }
25962
25963 bool is_main_thread() const {
25964 return stack::is_main_thread(this->thread_state());
25965 }
25966
25967 lua_State* thread_state() const {
25968 auto pp = stack::push_pop(*this);
25969 lua_State* lthread = lua_tothread(lua_state(), -1);
25970 return lthread;
25971 }
25972
25973 thread_status status() const {
25974 lua_State* lthread = thread_state();
25975 auto lstat = static_cast<thread_status>(lua_status(lthread));
25976 if (lstat == thread_status::ok) {
25977 lua_Debug ar;
25978 if (lua_getstack(lthread, 0, &ar) > 0)
25979 return thread_status::ok;
25980 else if (lua_gettop(lthread) == 0)
25981 return thread_status::dead;
25982 else
25983 return thread_status::yielded;
25984 }
25985 return lstat;
25986 }
25987
25988 basic_thread create() {
25989 return create(lua_state());
25990 }
25991
25992 static basic_thread create(lua_State* L) {
25993 lua_newthread(L);
25994 basic_thread result(L);
25995 if (!is_stack_based<base_t>::value) {
25996 lua_pop(L, 1);
25997 }
25998 return result;
25999 }
26000 };
26001
26002 typedef basic_thread<reference> thread;
26003 typedef basic_thread<stack_reference> stack_thread;
26004} // namespace sol
26005
26006// end of sol/thread.hpp
26007
26008namespace sol {
26009
26010 class state : private std::unique_ptr<lua_State, detail::state_deleter>, public state_view {
26011 private:
26012 typedef std::unique_ptr<lua_State, detail::state_deleter> unique_base;
26013
26014 public:
26015 state(lua_CFunction panic = default_at_panic)
26016 : unique_base(luaL_newstate()), state_view(unique_base::get()) {
26017 set_default_state(unique_base::get(), panic);
26018 }
26019
26020 state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr)
26021 : unique_base(lua_newstate(alfunc, alpointer)), state_view(unique_base::get()) {
26022 set_default_state(unique_base::get(), panic);
26023 }
26024
26025 state(const state&) = delete;
26026 state(state&&) = default;
26027 state& operator=(const state&) = delete;
26028 state& operator=(state&& that) {
26029 state_view::operator=(std::move(that));
26030 unique_base::operator=(std::move(that));
26031 return *this;
26032 }
26033
26034 using state_view::get;
26035
26036 ~state() {
26037 }
26038 };
26039} // namespace sol
26040
26041// end of sol/state.hpp
26042
26043// beginning of sol/coroutine.hpp
26044
26045namespace sol {
26046 template <typename ref_t>
26047 class basic_coroutine : public basic_object<ref_t> {
26048 private:
26049 using base_t = basic_object<ref_t>;
26050
26051 public:
26052 typedef reference handler_t;
26053 handler_t error_handler;
26054
26055 private:
26056 call_status stats = call_status::yielded;
26057
26058 void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) {
26059#if SOL_LUA_VESION_I_ >= 504
26060 int nresults;
26061 stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount), &nresults));
26062#else
26063 stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount)));
26064#endif
26065 }
26066
26067 template <std::size_t... I, typename... Ret>
26068 auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) {
26069 luacall(n, sizeof...(Ret));
26070 return stack::pop<std::tuple<Ret...>>(lua_state());
26071 }
26072
26073 template <std::size_t I, typename Ret>
26074 Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) {
26075 luacall(n, 1);
26076 return stack::pop<Ret>(lua_state());
26077 }
26078
26079 template <std::size_t I>
26080 void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) {
26081 luacall(n, 0);
26082 }
26083
26084 protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) {
26085 int firstreturn = 1;
26086 luacall(n, LUA_MULTRET);
26087 int poststacksize = lua_gettop(this->lua_state());
26088 int returncount = poststacksize - (firstreturn - 1);
26089 if (error()) {
26090 if (error_handler.valid()) {
26091 string_view err = stack::get<string_view>(this->lua_state(), poststacksize);
26092 error_handler.push();
26093 stack::push(this->lua_state(), err);
26094 lua_call(lua_state(), 1, 1);
26095 }
26096 return protected_function_result(this->lua_state(), lua_absindex(this->lua_state(), -1), 1, returncount, status());
26097 }
26098 return protected_function_result(this->lua_state(), firstreturn, returncount, returncount, status());
26099 }
26100
26101 public:
26102 using base_t::lua_state;
26103
26104 basic_coroutine() = default;
26105 template <typename T,
26106 meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_coroutine>>,
26107 meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>,
26108 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26109 basic_coroutine(T&& r) noexcept
26110 : base_t(std::forward<T>(r)), error_handler(detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
26111#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26112 if (!is_function<meta::unqualified_t<T>>::value) {
26113 auto pp = stack::push_pop(*this);
26114 constructor_handler handler {};
26115 stack::check<basic_coroutine>(lua_state(), -1, handler);
26116 }
26117#endif // Safety
26118 }
26119 basic_coroutine(const basic_coroutine&) = default;
26120 basic_coroutine& operator=(const basic_coroutine&) = default;
26121 basic_coroutine(basic_coroutine&&) = default;
26122 basic_coroutine& operator=(basic_coroutine&&) = default;
26123 basic_coroutine(const basic_function<base_t>& b)
26124 : basic_coroutine(b, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(b.lua_state())) {
26125 }
26126 basic_coroutine(basic_function<base_t>&& b)
26127 : basic_coroutine(std::move(b), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(b.lua_state())) {
26128 }
26129 basic_coroutine(const basic_function<base_t>& b, handler_t eh) : base_t(b), error_handler(std::move(eh)) {
26130 }
26131 basic_coroutine(basic_function<base_t>&& b, handler_t eh) : base_t(std::move(b)), error_handler(std::move(eh)) {
26132 }
26133 basic_coroutine(const stack_reference& r)
26134 : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
26135 }
26136 basic_coroutine(stack_reference&& r)
26137 : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
26138 }
26139 basic_coroutine(const stack_reference& r, handler_t eh) : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) {
26140 }
26141 basic_coroutine(stack_reference&& r, handler_t eh) : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) {
26142 }
26143
26144 template <typename Super>
26145 basic_coroutine(const proxy_base<Super>& p)
26146 : basic_coroutine(p, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) {
26147 }
26148 template <typename Super>
26149 basic_coroutine(proxy_base<Super>&& p)
26150 : basic_coroutine(std::move(p), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) {
26151 }
26152 template <typename Proxy, typename Handler,
26153 meta::enable<std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>, meta::neg<is_lua_index<meta::unqualified_t<Handler>>>> = meta::enabler>
26154 basic_coroutine(Proxy&& p, Handler&& eh) : basic_coroutine(detail::force_cast<base_t>(p), std::forward<Handler>(eh)) {
26155 }
26156
26157 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26158 basic_coroutine(lua_State* L, T&& r)
26159 : basic_coroutine(L, std::forward<T>(r), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
26160 }
26161 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26162 basic_coroutine(lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward<T>(r)), error_handler(std::move(eh)) {
26163#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26164 auto pp = stack::push_pop(*this);
26165 constructor_handler handler {};
26166 stack::check<basic_coroutine>(lua_state(), -1, handler);
26167#endif // Safety
26168 }
26169
26170 basic_coroutine(lua_nil_t n) : base_t(n), error_handler(n) {
26171 }
26172
26173 basic_coroutine(lua_State* L, int index = -1)
26174 : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
26175 }
26176 basic_coroutine(lua_State* L, int index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) {
26177#ifdef SOL_SAFE_REFERENCES
26178 constructor_handler handler {};
26179 stack::check<basic_coroutine>(L, index, handler);
26180#endif // Safety
26181 }
26182 basic_coroutine(lua_State* L, absolute_index index)
26183 : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
26184 }
26185 basic_coroutine(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) {
26186#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26187 constructor_handler handler {};
26188 stack::check<basic_coroutine>(L, index, handler);
26189#endif // Safety
26190 }
26191 basic_coroutine(lua_State* L, raw_index index)
26192 : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
26193 }
26194 basic_coroutine(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) {
26195#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26196 constructor_handler handler {};
26197 stack::check<basic_coroutine>(L, index, handler);
26198#endif // Safety
26199 }
26200 basic_coroutine(lua_State* L, ref_index index)
26201 : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
26202 }
26203 basic_coroutine(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) {
26204#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26205 auto pp = stack::push_pop(*this);
26206 constructor_handler handler {};
26207 stack::check<basic_coroutine>(lua_state(), -1, handler);
26208#endif // Safety
26209 }
26210
26211 call_status status() const noexcept {
26212 return stats;
26213 }
26214
26215 bool error() const noexcept {
26216 call_status cs = status();
26217 return cs != call_status::ok && cs != call_status::yielded;
26218 }
26219
26220 bool runnable() const noexcept {
26221 return base_t::valid() && (status() == call_status::yielded);
26222 }
26223
26224 explicit operator bool() const noexcept {
26225 return runnable();
26226 }
26227
26228 template <typename... Args>
26229 protected_function_result operator()(Args&&... args) {
26230 return call<>(std::forward<Args>(args)...);
26231 }
26232
26233 template <typename... Ret, typename... Args>
26234 decltype(auto) operator()(types<Ret...>, Args&&... args) {
26235 return call<Ret...>(std::forward<Args>(args)...);
26236 }
26237
26238 template <typename... Ret, typename... Args>
26239 decltype(auto) call(Args&&... args) {
26240 // some users screw up coroutine.create
26241 // and try to use it with sol::coroutine without ever calling the first resume in Lua
26242 // this makes the stack incompatible with other kinds of stacks: protect against this
26243 // make sure coroutines don't screw us over
26244 base_t::push();
26245 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
26246 return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount);
26247 }
26248 };
26249} // namespace sol
26250
26251// end of sol/coroutine.hpp
26252
26253// beginning of sol/userdata.hpp
26254
26255namespace sol {
26256 template <typename base_type>
26257 class basic_userdata : public basic_table<base_type> {
26258 private:
26259 using base_t = basic_table<base_type>;
26260
26261 public:
26262 using base_t::lua_state;
26263
26264 basic_userdata() noexcept = default;
26265 template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_userdata>>, meta::neg<std::is_same<base_t, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26266 basic_userdata(T&& r) noexcept
26267 : base_t(std::forward<T>(r)) {
26268#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26269 if (!is_userdata<meta::unqualified_t<T>>::value) {
26270 auto pp = stack::push_pop(*this);
26271 type_assert(lua_state(), -1, type::userdata);
26272 }
26273#endif // Safety
26274 }
26275 basic_userdata(const basic_userdata&) = default;
26276 basic_userdata(basic_userdata&&) = default;
26277 basic_userdata& operator=(const basic_userdata&) = default;
26278 basic_userdata& operator=(basic_userdata&&) = default;
26279 basic_userdata(const stack_reference& r)
26280 : basic_userdata(r.lua_state(), r.stack_index()) {
26281 }
26282 basic_userdata(stack_reference&& r)
26283 : basic_userdata(r.lua_state(), r.stack_index()) {
26284 }
26285 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26286 basic_userdata(lua_State* L, T&& r)
26287 : base_t(L, std::forward<T>(r)) {
26288#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26289 auto pp = stack::push_pop(*this);
26290 constructor_handler handler{};
26291 stack::check<basic_userdata>(L, -1, handler);
26292#endif // Safety
26293 }
26294 basic_userdata(lua_State* L, int index = -1)
26295 : base_t(detail::no_safety, L, index) {
26296#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26297 constructor_handler handler{};
26298 stack::check<basic_userdata>(L, index, handler);
26299#endif // Safety
26300 }
26301 basic_userdata(lua_State* L, ref_index index)
26302 : base_t(detail::no_safety, L, index) {
26303#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26304 auto pp = stack::push_pop(*this);
26305 constructor_handler handler{};
26306 stack::check<basic_userdata>(L, -1, handler);
26307#endif // Safety
26308 }
26309 };
26310
26311 template <typename base_type>
26312 class basic_lightuserdata : public basic_object_base<base_type> {
26313 typedef basic_object_base<base_type> base_t;
26314
26315 public:
26316 using base_t::lua_state;
26317
26318 basic_lightuserdata() noexcept = default;
26319 template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_lightuserdata>>, meta::neg<std::is_same<base_t, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26320 basic_lightuserdata(T&& r) noexcept
26321 : base_t(std::forward<T>(r)) {
26322#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26323 if (!is_lightuserdata<meta::unqualified_t<T>>::value) {
26324 auto pp = stack::push_pop(*this);
26325 type_assert(lua_state(), -1, type::lightuserdata);
26326 }
26327#endif // Safety
26328 }
26329 basic_lightuserdata(const basic_lightuserdata&) = default;
26330 basic_lightuserdata(basic_lightuserdata&&) = default;
26331 basic_lightuserdata& operator=(const basic_lightuserdata&) = default;
26332 basic_lightuserdata& operator=(basic_lightuserdata&&) = default;
26333 basic_lightuserdata(const stack_reference& r)
26334 : basic_lightuserdata(r.lua_state(), r.stack_index()) {
26335 }
26336 basic_lightuserdata(stack_reference&& r)
26337 : basic_lightuserdata(r.lua_state(), r.stack_index()) {
26338 }
26339 template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26340 basic_lightuserdata(lua_State* L, T&& r)
26341 : basic_lightuserdata(L, std::forward<T>(r)) {
26342#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26343 auto pp = stack::push_pop(*this);
26344 constructor_handler handler{};
26345 stack::check<basic_lightuserdata>(lua_state(), -1, handler);
26346#endif // Safety
26347 }
26348 basic_lightuserdata(lua_State* L, int index = -1)
26349 : base_t(L, index) {
26350#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26351 constructor_handler handler{};
26352 stack::check<basic_lightuserdata>(L, index, handler);
26353#endif // Safety
26354 }
26355 basic_lightuserdata(lua_State* L, ref_index index)
26356 : base_t(L, index) {
26357#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
26358 auto pp = stack::push_pop(*this);
26359 constructor_handler handler{};
26360 stack::check<basic_lightuserdata>(lua_state(), index, handler);
26361#endif // Safety
26362 }
26363 };
26364
26365} // namespace sol
26366
26367// end of sol/userdata.hpp
26368
26369// beginning of sol/as_args.hpp
26370
26371namespace sol {
26372 template <typename T>
26373 struct as_args_t {
26374 T src;
26375 };
26376
26377 template <typename Source>
26378 auto as_args(Source&& source) {
26379 return as_args_t<Source> { std::forward<Source>(source) };
26380 }
26381
26382 namespace stack {
26383 template <typename T>
26384 struct unqualified_pusher<as_args_t<T>> {
26385 int push(lua_State* L, const as_args_t<T>& e) {
26386 int p = 0;
26387 for (const auto& i : e.src) {
26388 p += stack::push(L, i);
26389 }
26390 return p;
26391 }
26392 };
26393 } // namespace stack
26394} // namespace sol
26395
26396// end of sol/as_args.hpp
26397
26398// beginning of sol/variadic_args.hpp
26399
26400#include <limits>
26401#include <iterator>
26402
26403namespace sol {
26404 struct variadic_args {
26405 private:
26406 lua_State* L;
26407 int index;
26408 int stacktop;
26409
26410 public:
26411 typedef stack_proxy reference_type;
26412 typedef stack_proxy value_type;
26413 typedef stack_proxy* pointer;
26414 typedef std::ptrdiff_t difference_type;
26415 typedef std::size_t size_type;
26416 typedef stack_iterator<stack_proxy, false> iterator;
26417 typedef stack_iterator<stack_proxy, true> const_iterator;
26418 typedef std::reverse_iterator<iterator> reverse_iterator;
26419 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
26420
26421 variadic_args() = default;
26422 variadic_args(lua_State* luastate, int stackindex = -1)
26423 : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lua_gettop(luastate)) {
26424 }
26425 variadic_args(lua_State* luastate, int stackindex, int lastindex)
26426 : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lastindex) {
26427 }
26428 variadic_args(const variadic_args&) = default;
26429 variadic_args& operator=(const variadic_args&) = default;
26430 variadic_args(variadic_args&& o)
26431 : L(o.L), index(o.index), stacktop(o.stacktop) {
26432 // Must be manual, otherwise destructor will screw us
26433 // return count being 0 is enough to keep things clean
26434 // but will be thorough
26435 o.L = nullptr;
26436 o.index = 0;
26437 o.stacktop = 0;
26438 }
26439 variadic_args& operator=(variadic_args&& o) {
26440 L = o.L;
26441 index = o.index;
26442 stacktop = o.stacktop;
26443 // Must be manual, otherwise destructor will screw us
26444 // return count being 0 is enough to keep things clean
26445 // but will be thorough
26446 o.L = nullptr;
26447 o.index = 0;
26448 o.stacktop = 0;
26449 return *this;
26450 }
26451
26452 iterator begin() {
26453 return iterator(L, index, stacktop + 1);
26454 }
26455 iterator end() {
26456 return iterator(L, stacktop + 1, stacktop + 1);
26457 }
26458 const_iterator begin() const {
26459 return const_iterator(L, index, stacktop + 1);
26460 }
26461 const_iterator end() const {
26462 return const_iterator(L, stacktop + 1, stacktop + 1);
26463 }
26464 const_iterator cbegin() const {
26465 return begin();
26466 }
26467 const_iterator cend() const {
26468 return end();
26469 }
26470
26471 reverse_iterator rbegin() {
26472 return std::reverse_iterator<iterator>(begin());
26473 }
26474 reverse_iterator rend() {
26475 return std::reverse_iterator<iterator>(end());
26476 }
26477 const_reverse_iterator rbegin() const {
26478 return std::reverse_iterator<const_iterator>(begin());
26479 }
26480 const_reverse_iterator rend() const {
26481 return std::reverse_iterator<const_iterator>(end());
26482 }
26483 const_reverse_iterator crbegin() const {
26484 return std::reverse_iterator<const_iterator>(cbegin());
26485 }
26486 const_reverse_iterator crend() const {
26487 return std::reverse_iterator<const_iterator>(cend());
26488 }
26489
26490 int push() const {
26491 return push(L);
26492 }
26493
26494 int push(lua_State* target) const {
26495 int pushcount = 0;
26496 for (int i = index; i <= stacktop; ++i) {
26497 lua_pushvalue(L, i);
26498 pushcount += 1;
26499 }
26500 if (target != L) {
26501 lua_xmove(L, target, pushcount);
26502 }
26503 return pushcount;
26504 }
26505
26506 template <typename T>
26507 decltype(auto) get(difference_type index_offset = 0) const {
26508 return stack::get<T>(L, index + static_cast<int>(index_offset));
26509 }
26510
26511 type get_type(difference_type index_offset = 0) const noexcept {
26512 return type_of(L, index + static_cast<int>(index_offset));
26513 }
26514
26515 stack_proxy operator[](difference_type index_offset) const {
26516 return stack_proxy(L, index + static_cast<int>(index_offset));
26517 }
26518
26519 lua_State* lua_state() const {
26520 return L;
26521 };
26522 int stack_index() const {
26523 return index;
26524 };
26525 int leftover_count() const {
26526 return stacktop - (index - 1);
26527 }
26528 std::size_t size() const {
26529 return static_cast<std::size_t>(leftover_count());
26530 }
26531 int top() const {
26532 return stacktop;
26533 }
26534 };
26535
26536 namespace stack {
26537 template <>
26538 struct unqualified_getter<variadic_args> {
26539 static variadic_args get(lua_State* L, int index, record& tracking) {
26540 tracking.last = 0;
26541 return variadic_args(L, index);
26542 }
26543 };
26544
26545 template <>
26546 struct unqualified_pusher<variadic_args> {
26547 static int push(lua_State* L, const variadic_args& ref) {
26548 return ref.push(L);
26549 }
26550 };
26551 } // namespace stack
26552} // namespace sol
26553
26554// end of sol/variadic_args.hpp
26555
26556// beginning of sol/variadic_results.hpp
26557
26558// beginning of sol/as_returns.hpp
26559
26560namespace sol {
26561 template <typename T>
26562 struct as_returns_t {
26563 T src;
26564 };
26565
26566 template <typename Source>
26567 auto as_returns(Source&& source) {
26568 return as_returns_t<std::decay_t<Source>>{ std::forward<Source>(source) };
26569 }
26570
26571 namespace stack {
26572 template <typename T>
26573 struct unqualified_pusher<as_returns_t<T>> {
26574 int push(lua_State* L, const as_returns_t<T>& e) {
26575 auto& src = detail::unwrap(e.src);
26576 int p = 0;
26577 for (const auto& i : src) {
26578 p += stack::push(L, i);
26579 }
26580 return p;
26581 }
26582 };
26583 } // namespace stack
26584} // namespace sol
26585
26586// end of sol/as_returns.hpp
26587
26588#include <vector>
26589
26590namespace sol {
26591
26592 template <typename Al = typename std::allocator<object>>
26593 struct basic_variadic_results : public std::vector<object, Al> {
26594 private:
26595 using base_t = std::vector<object, Al>;
26596
26597 public:
26598 basic_variadic_results() : base_t() {
26599 }
26600
26601 basic_variadic_results(unsafe_function_result fr) : base_t() {
26602 this->reserve(fr.return_count());
26603 this->insert(this->cend(), fr.begin(), fr.end());
26604 }
26605
26606 basic_variadic_results(protected_function_result fr) : base_t() {
26607 this->reserve(fr.return_count());
26608 this->insert(this->cend(), fr.begin(), fr.end());
26609 }
26610
26611 template <typename Arg0, typename... Args,
26612 meta::disable_any<std::is_same<meta::unqualified_t<Arg0>, basic_variadic_results>, std::is_same<meta::unqualified_t<Arg0>, function_result>,
26613 std::is_same<meta::unqualified_t<Arg0>, protected_function_result>> = meta::enabler>
26614 basic_variadic_results(Arg0&& arg0, Args&&... args) : base_t(std::forward<Arg0>(arg0), std::forward<Args>(args)...) {
26615 }
26616
26617 basic_variadic_results(const basic_variadic_results&) = default;
26618 basic_variadic_results(basic_variadic_results&&) = default;
26619 };
26620
26621 struct variadic_results : public basic_variadic_results<> {
26622 private:
26623 using base_t = basic_variadic_results<>;
26624
26625 public:
26626 using base_t::base_t;
26627 };
26628
26629 template <typename Al>
26630 struct is_container<basic_variadic_results<Al>> : std::false_type { };
26631
26632 template <>
26633 struct is_container<variadic_results> : std::false_type { };
26634
26635 namespace stack {
26636 template <typename Al>
26637 struct unqualified_pusher<basic_variadic_results<Al>> {
26638 int push(lua_State* L, const basic_variadic_results<Al>& e) {
26639 int p = 0;
26640 for (const auto& i : e) {
26641 p += stack::push(L, i);
26642 }
26643 return p;
26644 }
26645 };
26646
26647 template <>
26648 struct unqualified_pusher<variadic_results> {
26649 int push(lua_State* L, const variadic_results& r) {
26650 using base_t = basic_variadic_results<>;
26651 return stack::push(L, static_cast<const base_t&>(r));
26652 }
26653 };
26654 } // namespace stack
26655
26656} // namespace sol
26657
26658// end of sol/variadic_results.hpp
26659
26660#if SOL_IS_ON(SOL_COMPILER_GCC_I_)
26661#pragma GCC diagnostic pop
26662#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_)
26663#pragma warning(pop)
26664#endif // g++
26665
26666#if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE_I_)
26667#undef check
26668#pragma pop_macro("check")
26669#endif // Unreal Engine 4 Bullshit
26670
26671#endif // SOL_HPP
26672// end of sol/sol.hpp
26673
26674#endif // SOL_SINGLE_INCLUDE_HPP