diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-05-10 19:27:59 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-05-17 15:39:39 -0400 |
commit | 4bbfeae42a1245b1b84e8847787d7643e6a6f2cf (patch) | |
tree | 8dd65d9ab0cfffd0e79f670c94b035c5eebfa934 /vendor/sol.hpp | |
parent | 67b24a8ddd89371cfb944c5b441c852f0edc23b1 (diff) | |
download | therapy-4bbfeae42a1245b1b84e8847787d7643e6a6f2cf.tar.gz therapy-4bbfeae42a1245b1b84e8847787d7643e6a6f2cf.tar.bz2 therapy-4bbfeae42a1245b1b84e8847787d7643e6a6f2cf.zip |
Started integrating Lua as a scripting engine
Currently moving platforms are able to have their movement controlled by a script rather than by XML, which is probably a better implementation and scales better to other things. The scripts, instead of using the components as state, use the stack as state. In this way, they pretend to be multithreaded. For instance, the moving platform calls moveRight and then moveLeft. Both of those functions internally make calls that say to wait until the next tick. When the AutomatingSystem ticks, it continues execution of all scripts (sequentially, of course) until they ask for the next tick again. This is implemented using coroutines.
Diffstat (limited to 'vendor/sol.hpp')
-rw-r--r-- | vendor/sol.hpp | 21575 |
1 files changed, 21575 insertions, 0 deletions
diff --git a/vendor/sol.hpp b/vendor/sol.hpp new file mode 100644 index 0000000..d033cba --- /dev/null +++ b/vendor/sol.hpp | |||
@@ -0,0 +1,21575 @@ | |||
1 | // The MIT License (MIT) | ||
2 | |||
3 | // Copyright (c) 2013-2018 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 2018-04-18 00:12:41.772355 UTC | ||
24 | // This header was generated with sol v2.20.0 (revision 8b77411) | ||
25 | // https://github.com/ThePhD/sol2 | ||
26 | |||
27 | #ifndef SOL_SINGLE_INCLUDE_HPP | ||
28 | #define SOL_SINGLE_INCLUDE_HPP | ||
29 | |||
30 | // beginning of sol.hpp | ||
31 | |||
32 | #ifndef SOL_HPP | ||
33 | #define SOL_HPP | ||
34 | |||
35 | #if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) | ||
36 | #define SOL_INSIDE_UNREAL 1 | ||
37 | #endif // Unreal Engine 4 bullshit | ||
38 | |||
39 | #if defined(SOL_INSIDE_UNREAL) && SOL_INSIDE_UNREAL | ||
40 | #ifdef check | ||
41 | #define SOL_INSIDE_UNREAL_REMOVED_CHECK | ||
42 | #undef check | ||
43 | #endif | ||
44 | #endif // Unreal Engine 4 Bullshit | ||
45 | |||
46 | #if defined(__GNUC__) | ||
47 | #pragma GCC diagnostic push | ||
48 | #pragma GCC diagnostic ignored "-Wshadow" | ||
49 | #pragma GCC diagnostic ignored "-Wconversion" | ||
50 | #if __GNUC__ > 6 | ||
51 | #pragma GCC diagnostic ignored "-Wnoexcept-type" | ||
52 | #endif | ||
53 | #elif defined(__clang__) | ||
54 | #elif defined _MSC_VER | ||
55 | #pragma warning( push ) | ||
56 | #pragma warning( disable : 4324 ) // structure was padded due to alignment specifier | ||
57 | #pragma warning( disable : 4503 ) // decorated name horse shit | ||
58 | #pragma warning( disable : 4702 ) // unreachable code | ||
59 | #pragma warning( disable: 4127 ) // 'conditional expression is constant' yeah that's the point your old compilers don't have `if constexpr` you jerk | ||
60 | #pragma warning( disable: 4505 ) // some other nonsense warning | ||
61 | #endif // clang++ vs. g++ vs. VC++ | ||
62 | |||
63 | // beginning of sol/forward.hpp | ||
64 | |||
65 | // beginning of sol/feature_test.hpp | ||
66 | |||
67 | #if (defined(__cplusplus) && __cplusplus == 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && ((defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201402L)))) | ||
68 | #ifndef SOL_CXX17_FEATURES | ||
69 | #define SOL_CXX17_FEATURES 1 | ||
70 | #endif // C++17 features macro | ||
71 | #endif // C++17 features check | ||
72 | |||
73 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
74 | #if defined(__cpp_noexcept_function_type) || ((defined(_MSC_VER) && _MSC_VER > 1911) && (defined(_MSVC_LANG) && ((_MSVC_LANG >= 201403L)))) | ||
75 | #ifndef SOL_NOEXCEPT_FUNCTION_TYPE | ||
76 | #define SOL_NOEXCEPT_FUNCTION_TYPE 1 | ||
77 | #endif // noexcept is part of a function's type | ||
78 | #endif // compiler-specific checks | ||
79 | #if defined(__clang__) && defined(__APPLE__) | ||
80 | #if defined(__has_include) | ||
81 | #if __has_include(<variant>) | ||
82 | #define SOL_STD_VARIANT 1 | ||
83 | #endif // has include nonsense | ||
84 | #endif // __has_include | ||
85 | #else | ||
86 | #define SOL_STD_VARIANT 1 | ||
87 | #endif // Clang screws up variant | ||
88 | #endif // C++17 only | ||
89 | |||
90 | // beginning of sol/config.hpp | ||
91 | |||
92 | #ifdef _MSC_VER | ||
93 | #if defined(_DEBUG) && !defined(NDEBUG) | ||
94 | |||
95 | #ifndef SOL_IN_DEBUG_DETECTED | ||
96 | #define SOL_IN_DEBUG_DETECTED 1 | ||
97 | #endif | ||
98 | |||
99 | #endif // VC++ Debug macros | ||
100 | |||
101 | #ifndef _CPPUNWIND | ||
102 | #ifndef SOL_NO_EXCEPTIONS | ||
103 | #define SOL_NO_EXCEPTIONS 1 | ||
104 | #endif | ||
105 | #endif // Automatic Exceptions | ||
106 | |||
107 | #ifndef _CPPRTTI | ||
108 | #ifndef SOL_NO_RTTI | ||
109 | #define SOL_NO_RTTI 1 | ||
110 | #endif | ||
111 | #endif // Automatic RTTI | ||
112 | #elif defined(__GNUC__) || defined(__clang__) | ||
113 | |||
114 | #if !defined(NDEBUG) && !defined(__OPTIMIZE__) | ||
115 | |||
116 | #ifndef SOL_IN_DEBUG_DETECTED | ||
117 | #define SOL_IN_DEBUG_DETECTED 1 | ||
118 | #endif | ||
119 | |||
120 | #endif // Not Debug && g++ optimizer flag | ||
121 | |||
122 | #ifndef __EXCEPTIONS | ||
123 | #ifndef SOL_NO_EXCEPTIONS | ||
124 | #define SOL_NO_EXCEPTIONS 1 | ||
125 | #endif | ||
126 | #endif // No Exceptions | ||
127 | |||
128 | #ifndef __GXX_RTTI | ||
129 | #ifndef SOL_NO_RTII | ||
130 | #define SOL_NO_RTTI 1 | ||
131 | #endif | ||
132 | #endif // No RTTI | ||
133 | |||
134 | #endif // vc++ || clang++/g++ | ||
135 | |||
136 | #if defined(SOL_CHECK_ARGUMENTS) && SOL_CHECK_ARGUMENTS | ||
137 | |||
138 | // Checks low-level getter function | ||
139 | // (and thusly, affects nearly entire framework) | ||
140 | #if !defined(SOL_SAFE_GETTER) | ||
141 | #define SOL_SAFE_GETTER 1 | ||
142 | #endif | ||
143 | |||
144 | // Checks access on usertype functions | ||
145 | // local my_obj = my_type.new() | ||
146 | // my_obj.my_member_function() | ||
147 | // -- bad syntax and crash | ||
148 | #if !defined(SOL_SAFE_USERTYPE) | ||
149 | #define SOL_SAFE_USERTYPE 1 | ||
150 | #endif | ||
151 | |||
152 | // Checks sol::reference derived boundaries | ||
153 | // sol::function ref(L, 1); | ||
154 | // sol::userdata sref(L, 2); | ||
155 | #if !defined(SOL_SAFE_REFERENCES) | ||
156 | #define SOL_SAFE_REFERENCES 1 | ||
157 | #endif | ||
158 | |||
159 | // Changes all typedefs of sol::function to point to the | ||
160 | // protected_function version, instead of unsafe_function | ||
161 | #if !defined(SOL_SAFE_FUNCTION) | ||
162 | #define SOL_SAFE_FUNCTION 1 | ||
163 | #endif | ||
164 | |||
165 | // Checks function parameters and | ||
166 | // returns upon call into/from Lua | ||
167 | // local a = 1 | ||
168 | // local b = "woof" | ||
169 | // my_c_function(a, b) | ||
170 | #if !defined(SOL_SAFE_FUNCTION_CALLS) | ||
171 | #define SOL_SAFE_FUNCTION_CALLS 1 | ||
172 | #endif | ||
173 | |||
174 | // Checks conversions | ||
175 | // int v = lua["bark"]; | ||
176 | // int v2 = my_sol_function(); | ||
177 | #if !defined(SOL_SAFE_PROXIES) | ||
178 | #define SOL_SAFE_PROXIES 1 | ||
179 | #endif | ||
180 | |||
181 | // Check overflowing number conversions | ||
182 | // for things like 64 bit integers that don't fit in a typical lua_Number | ||
183 | // for Lua 5.1 and 5.2 | ||
184 | #if !defined(SOL_SAFE_NUMERICS) | ||
185 | #define SOL_SAFE_NUMERICS 1 | ||
186 | #endif | ||
187 | |||
188 | // Turn off Number Precision Checks | ||
189 | // if this is defined, we do not do range | ||
190 | // checks on integers / unsigned integers that might | ||
191 | // be bigger than what Lua can represent | ||
192 | #if !defined(SOL_NO_CHECK_NUMBER_PRECISION) | ||
193 | // off by default | ||
194 | #define SOL_NO_CHECK_NUMBER_PRECISION 0 | ||
195 | #endif | ||
196 | |||
197 | #endif // Turn on Safety for all if top-level macro is defined | ||
198 | |||
199 | #if defined(SOL_IN_DEBUG_DETECTED) && SOL_IN_DEBUG_DETECTED | ||
200 | |||
201 | #if !defined(SOL_SAFE_REFERENCES) | ||
202 | // Ensure that references are forcefully type-checked upon construction | ||
203 | #define SOL_SAFE_REFERENCES 1 | ||
204 | #endif | ||
205 | |||
206 | // Safe usertypes checks for errors such as | ||
207 | // obj = my_type.new() | ||
208 | // obj.f() -- note the '.' instead of ':' | ||
209 | // usertypes should be safe no matter what | ||
210 | #if !defined(SOL_SAFE_USERTYPE) | ||
211 | #define SOL_SAFE_USERTYPE 1 | ||
212 | #endif | ||
213 | |||
214 | #if !defined(SOL_SAFE_FUNCTION_CALLS) | ||
215 | // Function calls from Lua should be automatically safe in debug mode | ||
216 | #define SOL_SAFE_FUNCTION_CALLS 1 | ||
217 | #endif | ||
218 | |||
219 | // Print any exceptions / errors that occur | ||
220 | // in debug mode to the default error stream / console | ||
221 | #if !defined(SOL_PRINT_ERRORS) | ||
222 | #define SOL_PRINT_ERRORS 1 | ||
223 | #endif | ||
224 | |||
225 | #endif // DEBUG: Turn on all debug safety features for VC++ / g++ / clang++ and similar | ||
226 | |||
227 | #if !defined(SOL_PRINT_ERRORS) | ||
228 | #define SOL_PRINT_ERRORS 0 | ||
229 | #endif | ||
230 | |||
231 | #if !defined(SOL_DEFAULT_PASS_ON_ERROR) | ||
232 | #define SOL_DEFAULT_PASS_ON_ERROR 0 | ||
233 | #endif | ||
234 | |||
235 | #if !defined(SOL_ENABLE_INTEROP) | ||
236 | #define SOL_ENABLE_INTEROP 0 | ||
237 | #endif | ||
238 | |||
239 | #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) | ||
240 | #if !defined(SOL_NO_NIL) | ||
241 | #define SOL_NO_NIL 1 | ||
242 | #endif | ||
243 | #endif // avoiding nil defines / keywords | ||
244 | |||
245 | #if defined(SOL_USE_BOOST) && SOL_USE_BOOST | ||
246 | #ifndef SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
247 | #define SOL_UNORDERED_MAP_COMPATIBLE_HASH 1 | ||
248 | #endif // SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
249 | #endif | ||
250 | |||
251 | #ifndef SOL_STACK_STRING_OPTIMIZATION_SIZE | ||
252 | #define SOL_STACK_STRING_OPTIMIZATION_SIZE 1024 | ||
253 | #endif // Optimized conversion routines using a KB or so off the stack | ||
254 | |||
255 | // end of sol/config.hpp | ||
256 | |||
257 | // end of sol/feature_test.hpp | ||
258 | |||
259 | namespace sol { | ||
260 | |||
261 | template <bool b> | ||
262 | class basic_reference; | ||
263 | using reference = basic_reference<false>; | ||
264 | using main_reference = basic_reference<true>; | ||
265 | class stack_reference; | ||
266 | |||
267 | struct proxy_base_tag; | ||
268 | template <typename Super> | ||
269 | struct proxy_base; | ||
270 | template <typename Table, typename Key> | ||
271 | struct proxy; | ||
272 | |||
273 | template <typename T> | ||
274 | class usertype; | ||
275 | template <typename T> | ||
276 | class simple_usertype; | ||
277 | template <bool, typename T> | ||
278 | class basic_table_core; | ||
279 | template <bool b> | ||
280 | using table_core = basic_table_core<b, reference>; | ||
281 | template <bool b> | ||
282 | using main_table_core = basic_table_core<b, main_reference>; | ||
283 | template <bool b> | ||
284 | using stack_table_core = basic_table_core<b, stack_reference>; | ||
285 | template <typename T> | ||
286 | using basic_table = basic_table_core<false, T>; | ||
287 | typedef table_core<false> table; | ||
288 | typedef table_core<true> global_table; | ||
289 | typedef main_table_core<false> main_table; | ||
290 | typedef main_table_core<true> main_global_table; | ||
291 | typedef stack_table_core<false> stack_table; | ||
292 | typedef stack_table_core<true> stack_global_table; | ||
293 | template <typename base_t> | ||
294 | struct basic_environment; | ||
295 | using environment = basic_environment<reference>; | ||
296 | using main_environment = basic_environment<main_reference>; | ||
297 | using stack_environment = basic_environment<stack_reference>; | ||
298 | template <typename T, bool> | ||
299 | class basic_function; | ||
300 | template <typename T, bool, typename H> | ||
301 | class basic_protected_function; | ||
302 | using unsafe_function = basic_function<reference, false>; | ||
303 | using safe_function = basic_protected_function<reference, false, reference>; | ||
304 | using main_unsafe_function = basic_function<main_reference, false>; | ||
305 | using main_safe_function = basic_protected_function<main_reference, false, reference>; | ||
306 | using stack_unsafe_function = basic_function<stack_reference, false>; | ||
307 | using stack_safe_function = basic_protected_function<stack_reference, false, reference>; | ||
308 | using stack_aligned_unsafe_function = basic_function<stack_reference, true>; | ||
309 | using stack_aligned_safe_function = basic_protected_function<stack_reference, true, reference>; | ||
310 | using protected_function = safe_function; | ||
311 | using main_protected_function = main_safe_function; | ||
312 | using stack_protected_function = stack_safe_function; | ||
313 | using stack_aligned_protected_function = stack_aligned_safe_function; | ||
314 | #if defined(SOL_SAFE_FUNCTION) && SOL_SAFE_FUNCTION | ||
315 | using function = protected_function; | ||
316 | using main_function = main_protected_function; | ||
317 | using stack_function = stack_protected_function; | ||
318 | #else | ||
319 | using function = unsafe_function; | ||
320 | using main_function = main_unsafe_function; | ||
321 | using stack_function = stack_unsafe_function; | ||
322 | #endif | ||
323 | using stack_aligned_function = stack_aligned_unsafe_function; | ||
324 | using stack_aligned_stack_handler_function = basic_protected_function<stack_reference, true, stack_reference>; | ||
325 | |||
326 | struct unsafe_function_result; | ||
327 | struct protected_function_result; | ||
328 | using safe_function_result = protected_function_result; | ||
329 | #if defined(SOL_SAFE_FUNCTION) && SOL_SAFE_FUNCTION | ||
330 | using function_result = safe_function_result; | ||
331 | #else | ||
332 | using function_result = unsafe_function_result; | ||
333 | #endif | ||
334 | |||
335 | template <typename base_t> | ||
336 | class basic_object; | ||
337 | template <typename base_t> | ||
338 | class basic_userdata; | ||
339 | template <typename base_t> | ||
340 | class basic_lightuserdata; | ||
341 | template <typename base_t> | ||
342 | class basic_coroutine; | ||
343 | template <typename base_t> | ||
344 | class basic_thread; | ||
345 | |||
346 | using object = basic_object<reference>; | ||
347 | using userdata = basic_userdata<reference>; | ||
348 | using lightuserdata = basic_lightuserdata<reference>; | ||
349 | using thread = basic_thread<reference>; | ||
350 | using coroutine = basic_coroutine<reference>; | ||
351 | using main_object = basic_object<main_reference>; | ||
352 | using main_userdata = basic_userdata<main_reference>; | ||
353 | using main_lightuserdata = basic_lightuserdata<main_reference>; | ||
354 | using main_coroutine = basic_coroutine<main_reference>; | ||
355 | using stack_object = basic_object<stack_reference>; | ||
356 | using stack_userdata = basic_userdata<stack_reference>; | ||
357 | using stack_lightuserdata = basic_lightuserdata<stack_reference>; | ||
358 | using stack_thread = basic_thread<stack_reference>; | ||
359 | using stack_coroutine = basic_coroutine<stack_reference>; | ||
360 | |||
361 | struct stack_proxy_base; | ||
362 | struct stack_proxy; | ||
363 | struct variadic_args; | ||
364 | struct variadic_results; | ||
365 | struct stack_count; | ||
366 | struct this_state; | ||
367 | struct this_main_state; | ||
368 | struct this_environment; | ||
369 | |||
370 | template <typename T> | ||
371 | struct as_table_t; | ||
372 | template <typename T> | ||
373 | struct as_container_t; | ||
374 | template <typename T> | ||
375 | struct nested; | ||
376 | template <typename T> | ||
377 | struct light; | ||
378 | template <typename T> | ||
379 | struct user; | ||
380 | template <typename T> | ||
381 | struct as_args_t; | ||
382 | template <typename T> | ||
383 | struct protect_t; | ||
384 | template <typename F, typename... Filters> | ||
385 | struct filter_wrapper; | ||
386 | } // namespace sol | ||
387 | |||
388 | // end of sol/forward.hpp | ||
389 | |||
390 | // beginning of sol/state.hpp | ||
391 | |||
392 | // beginning of sol/state_view.hpp | ||
393 | |||
394 | // beginning of sol/error.hpp | ||
395 | |||
396 | #include <stdexcept> | ||
397 | #include <string> | ||
398 | |||
399 | namespace sol { | ||
400 | namespace detail { | ||
401 | struct direct_error_tag {}; | ||
402 | const auto direct_error = direct_error_tag{}; | ||
403 | } // namespace detail | ||
404 | |||
405 | class error : public std::runtime_error { | ||
406 | private: | ||
407 | // Because VC++ is upsetting, most of the time! | ||
408 | std::string w; | ||
409 | |||
410 | public: | ||
411 | error(const std::string& str) | ||
412 | : error(detail::direct_error, "lua: error: " + str) { | ||
413 | } | ||
414 | error(std::string&& str) | ||
415 | : error(detail::direct_error, "lua: error: " + std::move(str)) { | ||
416 | } | ||
417 | error(detail::direct_error_tag, const std::string& str) | ||
418 | : std::runtime_error(""), w(str) { | ||
419 | } | ||
420 | error(detail::direct_error_tag, std::string&& str) | ||
421 | : std::runtime_error(""), w(std::move(str)) { | ||
422 | } | ||
423 | |||
424 | error(const error& e) = default; | ||
425 | error(error&& e) = default; | ||
426 | error& operator=(const error& e) = default; | ||
427 | error& operator=(error&& e) = default; | ||
428 | |||
429 | virtual const char* what() const noexcept override { | ||
430 | return w.c_str(); | ||
431 | } | ||
432 | }; | ||
433 | |||
434 | } // namespace sol | ||
435 | |||
436 | // end of sol/error.hpp | ||
437 | |||
438 | // beginning of sol/table.hpp | ||
439 | |||
440 | // beginning of sol/table_core.hpp | ||
441 | |||
442 | // beginning of sol/proxy.hpp | ||
443 | |||
444 | // beginning of sol/traits.hpp | ||
445 | |||
446 | // beginning of sol/tuple.hpp | ||
447 | |||
448 | #include <tuple> | ||
449 | #include <cstddef> | ||
450 | |||
451 | namespace sol { | ||
452 | namespace detail { | ||
453 | using swallow = std::initializer_list<int>; | ||
454 | } // namespace detail | ||
455 | |||
456 | template <typename... Args> | ||
457 | struct types { | ||
458 | typedef std::make_index_sequence<sizeof...(Args)> indices; | ||
459 | static constexpr std::size_t size() { | ||
460 | return sizeof...(Args); | ||
461 | } | ||
462 | }; | ||
463 | namespace meta { | ||
464 | namespace detail { | ||
465 | template <typename... Args> | ||
466 | struct tuple_types_ { typedef types<Args...> type; }; | ||
467 | |||
468 | template <typename... Args> | ||
469 | struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; }; | ||
470 | } // namespace detail | ||
471 | |||
472 | template <typename T> | ||
473 | using unqualified = std::remove_cv<std::remove_reference_t<T>>; | ||
474 | |||
475 | template <typename T> | ||
476 | using unqualified_t = typename unqualified<T>::type; | ||
477 | |||
478 | template <typename... Args> | ||
479 | using tuple_types = typename detail::tuple_types_<Args...>::type; | ||
480 | |||
481 | template <typename Arg> | ||
482 | struct pop_front_type; | ||
483 | |||
484 | template <typename Arg> | ||
485 | using pop_front_type_t = typename pop_front_type<Arg>::type; | ||
486 | |||
487 | template <typename... Args> | ||
488 | struct pop_front_type<types<Args...>> { | ||
489 | typedef void front_type; | ||
490 | typedef types<Args...> type; | ||
491 | }; | ||
492 | |||
493 | template <typename Arg, typename... Args> | ||
494 | struct pop_front_type<types<Arg, Args...>> { | ||
495 | typedef Arg front_type; | ||
496 | typedef types<Args...> type; | ||
497 | }; | ||
498 | |||
499 | template <std::size_t N, typename Tuple> | ||
500 | using tuple_element = std::tuple_element<N, std::remove_reference_t<Tuple>>; | ||
501 | |||
502 | template <std::size_t N, typename Tuple> | ||
503 | using tuple_element_t = std::tuple_element_t<N, std::remove_reference_t<Tuple>>; | ||
504 | |||
505 | template <std::size_t N, typename Tuple> | ||
506 | using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>; | ||
507 | |||
508 | template <std::size_t N, typename Tuple> | ||
509 | using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>; | ||
510 | |||
511 | } // namespace meta | ||
512 | } // namespace sol | ||
513 | |||
514 | // end of sol/tuple.hpp | ||
515 | |||
516 | // beginning of sol/bind_traits.hpp | ||
517 | |||
518 | namespace sol { | ||
519 | namespace meta { | ||
520 | namespace meta_detail { | ||
521 | |||
522 | template <class F> | ||
523 | struct check_deducible_signature { | ||
524 | struct nat {}; | ||
525 | template <class G> | ||
526 | static auto test(int) -> decltype(&G::operator(), void()); | ||
527 | template <class> | ||
528 | static auto test(...) -> nat; | ||
529 | |||
530 | using type = std::is_void<decltype(test<F>(0))>; | ||
531 | }; | ||
532 | } // namespace meta_detail | ||
533 | |||
534 | template <class F> | ||
535 | struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type {}; | ||
536 | |||
537 | namespace meta_detail { | ||
538 | |||
539 | template <std::size_t I, typename T> | ||
540 | struct void_tuple_element : meta::tuple_element<I, T> {}; | ||
541 | |||
542 | template <std::size_t I> | ||
543 | struct void_tuple_element<I, std::tuple<>> { typedef void type; }; | ||
544 | |||
545 | template <std::size_t I, typename T> | ||
546 | using void_tuple_element_t = typename void_tuple_element<I, T>::type; | ||
547 | |||
548 | template <bool it_is_noexcept, bool has_c_variadic, typename T, typename R, typename... Args> | ||
549 | struct basic_traits { | ||
550 | private: | ||
551 | typedef std::conditional_t<std::is_void<T>::value, int, T>& first_type; | ||
552 | |||
553 | public: | ||
554 | static const bool is_noexcept = it_is_noexcept; | ||
555 | static const bool is_member_function = std::is_void<T>::value; | ||
556 | static const bool has_c_var_arg = has_c_variadic; | ||
557 | static const std::size_t arity = sizeof...(Args); | ||
558 | static const std::size_t free_arity = sizeof...(Args) + static_cast<std::size_t>(!std::is_void<T>::value); | ||
559 | typedef types<Args...> args_list; | ||
560 | typedef std::tuple<Args...> args_tuple; | ||
561 | typedef T object_type; | ||
562 | typedef R return_type; | ||
563 | typedef tuple_types<R> returns_list; | ||
564 | typedef R(function_type)(Args...); | ||
565 | typedef std::conditional_t<std::is_void<T>::value, args_list, types<first_type, Args...>> free_args_list; | ||
566 | typedef std::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type; | ||
567 | typedef std::conditional_t<std::is_void<T>::value, R (*)(Args...), R (*)(first_type, Args...)> free_function_pointer_type; | ||
568 | typedef std::remove_pointer_t<free_function_pointer_type> signature_type; | ||
569 | template <std::size_t i> | ||
570 | using arg_at = void_tuple_element_t<i, args_tuple>; | ||
571 | }; | ||
572 | |||
573 | template <typename Signature, bool b = has_deducible_signature<Signature>::value> | ||
574 | struct fx_traits : basic_traits<false, false, void, void> {}; | ||
575 | |||
576 | // Free Functions | ||
577 | template <typename R, typename... Args> | ||
578 | struct fx_traits<R(Args...), false> : basic_traits<false, false, void, R, Args...> { | ||
579 | typedef R (*function_pointer_type)(Args...); | ||
580 | }; | ||
581 | |||
582 | template <typename R, typename... Args> | ||
583 | struct fx_traits<R (*)(Args...), false> : basic_traits<false, false, void, R, Args...> { | ||
584 | typedef R (*function_pointer_type)(Args...); | ||
585 | }; | ||
586 | |||
587 | template <typename R, typename... Args> | ||
588 | struct fx_traits<R(Args..., ...), false> : basic_traits<false, true, void, R, Args...> { | ||
589 | typedef R (*function_pointer_type)(Args..., ...); | ||
590 | }; | ||
591 | |||
592 | template <typename R, typename... Args> | ||
593 | struct fx_traits<R (*)(Args..., ...), false> : basic_traits<false, true, void, R, Args...> { | ||
594 | typedef R (*function_pointer_type)(Args..., ...); | ||
595 | }; | ||
596 | |||
597 | // Member Functions | ||
598 | /* C-Style Variadics */ | ||
599 | template <typename T, typename R, typename... Args> | ||
600 | struct fx_traits<R (T::*)(Args...), false> : basic_traits<false, false, T, R, Args...> { | ||
601 | typedef R (T::*function_pointer_type)(Args...); | ||
602 | }; | ||
603 | |||
604 | template <typename T, typename R, typename... Args> | ||
605 | struct fx_traits<R (T::*)(Args..., ...), false> : basic_traits<false, true, T, R, Args...> { | ||
606 | typedef R (T::*function_pointer_type)(Args..., ...); | ||
607 | }; | ||
608 | |||
609 | /* Const Volatile */ | ||
610 | template <typename T, typename R, typename... Args> | ||
611 | struct fx_traits<R (T::*)(Args...) const, false> : basic_traits<false, false, T, R, Args...> { | ||
612 | typedef R (T::*function_pointer_type)(Args...) const; | ||
613 | }; | ||
614 | |||
615 | template <typename T, typename R, typename... Args> | ||
616 | struct fx_traits<R (T::*)(Args..., ...) const, false> : basic_traits<false, true, T, R, Args...> { | ||
617 | typedef R (T::*function_pointer_type)(Args..., ...) const; | ||
618 | }; | ||
619 | |||
620 | template <typename T, typename R, typename... Args> | ||
621 | struct fx_traits<R (T::*)(Args...) const volatile, false> : basic_traits<false, false, T, R, Args...> { | ||
622 | typedef R (T::*function_pointer_type)(Args...) const volatile; | ||
623 | }; | ||
624 | |||
625 | template <typename T, typename R, typename... Args> | ||
626 | struct fx_traits<R (T::*)(Args..., ...) const volatile, false> : basic_traits<false, true, T, R, Args...> { | ||
627 | typedef R (T::*function_pointer_type)(Args..., ...) const volatile; | ||
628 | }; | ||
629 | |||
630 | /* Member Function Qualifiers */ | ||
631 | template <typename T, typename R, typename... Args> | ||
632 | struct fx_traits<R (T::*)(Args...)&, false> : basic_traits<false, false, T, R, Args...> { | ||
633 | typedef R (T::*function_pointer_type)(Args...) &; | ||
634 | }; | ||
635 | |||
636 | template <typename T, typename R, typename... Args> | ||
637 | struct fx_traits<R (T::*)(Args..., ...)&, false> : basic_traits<false, true, T, R, Args...> { | ||
638 | typedef R (T::*function_pointer_type)(Args..., ...) &; | ||
639 | }; | ||
640 | |||
641 | template <typename T, typename R, typename... Args> | ||
642 | struct fx_traits<R (T::*)(Args...) const&, false> : basic_traits<false, false, T, R, Args...> { | ||
643 | typedef R (T::*function_pointer_type)(Args...) const&; | ||
644 | }; | ||
645 | |||
646 | template <typename T, typename R, typename... Args> | ||
647 | struct fx_traits<R (T::*)(Args..., ...) const&, false> : basic_traits<false, true, T, R, Args...> { | ||
648 | typedef R (T::*function_pointer_type)(Args..., ...) const&; | ||
649 | }; | ||
650 | |||
651 | template <typename T, typename R, typename... Args> | ||
652 | struct fx_traits<R (T::*)(Args...) const volatile&, false> : basic_traits<false, false, T, R, Args...> { | ||
653 | typedef R (T::*function_pointer_type)(Args...) const volatile&; | ||
654 | }; | ||
655 | |||
656 | template <typename T, typename R, typename... Args> | ||
657 | struct fx_traits<R (T::*)(Args..., ...) const volatile&, false> : basic_traits<false, true, T, R, Args...> { | ||
658 | typedef R (T::*function_pointer_type)(Args..., ...) const volatile&; | ||
659 | }; | ||
660 | |||
661 | template <typename T, typename R, typename... Args> | ||
662 | struct fx_traits<R (T::*)(Args...)&&, false> : basic_traits<false, false, T, R, Args...> { | ||
663 | typedef R (T::*function_pointer_type)(Args...) &&; | ||
664 | }; | ||
665 | |||
666 | template <typename T, typename R, typename... Args> | ||
667 | struct fx_traits<R (T::*)(Args..., ...)&&, false> : basic_traits<false, true, T, R, Args...> { | ||
668 | typedef R (T::*function_pointer_type)(Args..., ...) &&; | ||
669 | }; | ||
670 | |||
671 | template <typename T, typename R, typename... Args> | ||
672 | struct fx_traits<R (T::*)(Args...) const&&, false> : basic_traits<false, false, T, R, Args...> { | ||
673 | typedef R (T::*function_pointer_type)(Args...) const&&; | ||
674 | }; | ||
675 | |||
676 | template <typename T, typename R, typename... Args> | ||
677 | struct fx_traits<R (T::*)(Args..., ...) const&&, false> : basic_traits<false, true, T, R, Args...> { | ||
678 | typedef R (T::*function_pointer_type)(Args..., ...) const&&; | ||
679 | }; | ||
680 | |||
681 | template <typename T, typename R, typename... Args> | ||
682 | struct fx_traits<R (T::*)(Args...) const volatile&&, false> : basic_traits<false, false, T, R, Args...> { | ||
683 | typedef R (T::*function_pointer_type)(Args...) const volatile&&; | ||
684 | }; | ||
685 | |||
686 | template <typename T, typename R, typename... Args> | ||
687 | struct fx_traits<R (T::*)(Args..., ...) const volatile&&, false> : basic_traits<false, true, T, R, Args...> { | ||
688 | typedef R (T::*function_pointer_type)(Args..., ...) const volatile&&; | ||
689 | }; | ||
690 | |||
691 | #if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE | ||
692 | |||
693 | template <typename R, typename... Args> | ||
694 | struct fx_traits<R(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> { | ||
695 | typedef R (*function_pointer_type)(Args...) noexcept; | ||
696 | }; | ||
697 | |||
698 | template <typename R, typename... Args> | ||
699 | struct fx_traits<R (*)(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> { | ||
700 | typedef R (*function_pointer_type)(Args...) noexcept; | ||
701 | }; | ||
702 | |||
703 | template <typename R, typename... Args> | ||
704 | struct fx_traits<R(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> { | ||
705 | typedef R (*function_pointer_type)(Args..., ...) noexcept; | ||
706 | }; | ||
707 | |||
708 | template <typename R, typename... Args> | ||
709 | struct fx_traits<R (*)(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> { | ||
710 | typedef R (*function_pointer_type)(Args..., ...) noexcept; | ||
711 | }; | ||
712 | |||
713 | template <typename T, typename R, typename... Args> | ||
714 | struct fx_traits<R (T::*)(Args...) noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
715 | typedef R (T::*function_pointer_type)(Args...) noexcept; | ||
716 | }; | ||
717 | |||
718 | template <typename T, typename R, typename... Args> | ||
719 | struct fx_traits<R (T::*)(Args..., ...) noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
720 | typedef R (T::*function_pointer_type)(Args..., ...) noexcept; | ||
721 | }; | ||
722 | |||
723 | /* Const Volatile */ | ||
724 | template <typename T, typename R, typename... Args> | ||
725 | struct fx_traits<R (T::*)(Args...) const noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
726 | typedef R (T::*function_pointer_type)(Args...) const noexcept; | ||
727 | }; | ||
728 | |||
729 | template <typename T, typename R, typename... Args> | ||
730 | struct fx_traits<R (T::*)(Args..., ...) const noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
731 | typedef R (T::*function_pointer_type)(Args..., ...) const noexcept; | ||
732 | }; | ||
733 | |||
734 | template <typename T, typename R, typename... Args> | ||
735 | struct fx_traits<R (T::*)(Args...) const volatile noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
736 | typedef R (T::*function_pointer_type)(Args...) const volatile noexcept; | ||
737 | }; | ||
738 | |||
739 | template <typename T, typename R, typename... Args> | ||
740 | struct fx_traits<R (T::*)(Args..., ...) const volatile noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
741 | typedef R (T::*function_pointer_type)(Args..., ...) const volatile noexcept; | ||
742 | }; | ||
743 | |||
744 | template <typename T, typename R, typename... Args> | ||
745 | struct fx_traits<R (T::*)(Args...) & noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
746 | typedef R (T::*function_pointer_type)(Args...) & noexcept; | ||
747 | }; | ||
748 | |||
749 | template <typename T, typename R, typename... Args> | ||
750 | struct fx_traits<R (T::*)(Args..., ...) & noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
751 | typedef R (T::*function_pointer_type)(Args..., ...) & noexcept; | ||
752 | }; | ||
753 | |||
754 | template <typename T, typename R, typename... Args> | ||
755 | struct fx_traits<R (T::*)(Args...) const& noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
756 | typedef R (T::*function_pointer_type)(Args...) const& noexcept; | ||
757 | }; | ||
758 | |||
759 | template <typename T, typename R, typename... Args> | ||
760 | struct fx_traits<R (T::*)(Args..., ...) const& noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
761 | typedef R (T::*function_pointer_type)(Args..., ...) const& noexcept; | ||
762 | }; | ||
763 | |||
764 | template <typename T, typename R, typename... Args> | ||
765 | struct fx_traits<R (T::*)(Args...) const volatile& noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
766 | typedef R (T::*function_pointer_type)(Args...) const volatile& noexcept; | ||
767 | }; | ||
768 | |||
769 | template <typename T, typename R, typename... Args> | ||
770 | struct fx_traits<R (T::*)(Args..., ...) const volatile& noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
771 | typedef R (T::*function_pointer_type)(Args..., ...) const volatile& noexcept; | ||
772 | }; | ||
773 | |||
774 | template <typename T, typename R, typename... Args> | ||
775 | struct fx_traits<R (T::*)(Args...) && noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
776 | typedef R (T::*function_pointer_type)(Args...) && noexcept; | ||
777 | }; | ||
778 | |||
779 | template <typename T, typename R, typename... Args> | ||
780 | struct fx_traits<R (T::*)(Args..., ...) && noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
781 | typedef R (T::*function_pointer_type)(Args..., ...) && noexcept; | ||
782 | }; | ||
783 | |||
784 | template <typename T, typename R, typename... Args> | ||
785 | struct fx_traits<R (T::*)(Args...) const&& noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
786 | typedef R (T::*function_pointer_type)(Args...) const&& noexcept; | ||
787 | }; | ||
788 | |||
789 | template <typename T, typename R, typename... Args> | ||
790 | struct fx_traits<R (T::*)(Args..., ...) const&& noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
791 | typedef R (T::*function_pointer_type)(Args..., ...) const&& noexcept; | ||
792 | }; | ||
793 | |||
794 | template <typename T, typename R, typename... Args> | ||
795 | struct fx_traits<R (T::*)(Args...) const volatile&& noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
796 | typedef R (T::*function_pointer_type)(Args...) const volatile&& noexcept; | ||
797 | }; | ||
798 | |||
799 | template <typename T, typename R, typename... Args> | ||
800 | struct fx_traits<R (T::*)(Args..., ...) const volatile&& noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
801 | typedef R (T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; | ||
802 | }; | ||
803 | |||
804 | #endif // noexcept is part of a function's type | ||
805 | |||
806 | #if defined(_MSC_VER) && defined(_M_IX86) | ||
807 | template <typename R, typename... Args> | ||
808 | struct fx_traits<R __stdcall(Args...), false> : basic_traits<false, false, void, R, Args...> { | ||
809 | typedef R(__stdcall* function_pointer_type)(Args...); | ||
810 | }; | ||
811 | |||
812 | template <typename R, typename... Args> | ||
813 | struct fx_traits<R(__stdcall*)(Args...), false> : basic_traits<false, false, void, R, Args...> { | ||
814 | typedef R(__stdcall* function_pointer_type)(Args...); | ||
815 | }; | ||
816 | |||
817 | template <typename T, typename R, typename... Args> | ||
818 | struct fx_traits<R (__stdcall T::*)(Args...), false> : basic_traits<false, false, T, R, Args...> { | ||
819 | typedef R (__stdcall T::*function_pointer_type)(Args...); | ||
820 | }; | ||
821 | |||
822 | /* Const Volatile */ | ||
823 | template <typename T, typename R, typename... Args> | ||
824 | struct fx_traits<R (__stdcall T::*)(Args...) const, false> : basic_traits<false, false, T, R, Args...> { | ||
825 | typedef R (__stdcall T::*function_pointer_type)(Args...) const; | ||
826 | }; | ||
827 | |||
828 | template <typename T, typename R, typename... Args> | ||
829 | struct fx_traits<R (__stdcall T::*)(Args...) const volatile, false> : basic_traits<false, false, T, R, Args...> { | ||
830 | typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile; | ||
831 | }; | ||
832 | |||
833 | /* Member Function Qualifiers */ | ||
834 | template <typename T, typename R, typename... Args> | ||
835 | struct fx_traits<R (__stdcall T::*)(Args...)&, false> : basic_traits<false, false, T, R, Args...> { | ||
836 | typedef R (__stdcall T::*function_pointer_type)(Args...) &; | ||
837 | }; | ||
838 | |||
839 | template <typename T, typename R, typename... Args> | ||
840 | struct fx_traits<R (__stdcall T::*)(Args...) const&, false> : basic_traits<false, false, T, R, Args...> { | ||
841 | typedef R (__stdcall T::*function_pointer_type)(Args...) const&; | ||
842 | }; | ||
843 | |||
844 | template <typename T, typename R, typename... Args> | ||
845 | struct fx_traits<R (__stdcall T::*)(Args...) const volatile&, false> : basic_traits<false, false, T, R, Args...> { | ||
846 | typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&; | ||
847 | }; | ||
848 | |||
849 | template <typename T, typename R, typename... Args> | ||
850 | struct fx_traits<R (__stdcall T::*)(Args...)&&, false> : basic_traits<false, false, T, R, Args...> { | ||
851 | typedef R (__stdcall T::*function_pointer_type)(Args...) &&; | ||
852 | }; | ||
853 | |||
854 | template <typename T, typename R, typename... Args> | ||
855 | struct fx_traits<R (__stdcall T::*)(Args...) const&&, false> : basic_traits<false, false, T, R, Args...> { | ||
856 | typedef R (__stdcall T::*function_pointer_type)(Args...) const&&; | ||
857 | }; | ||
858 | |||
859 | template <typename T, typename R, typename... Args> | ||
860 | struct fx_traits<R (__stdcall T::*)(Args...) const volatile&&, false> : basic_traits<false, false, T, R, Args...> { | ||
861 | typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&&; | ||
862 | }; | ||
863 | |||
864 | #if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE | ||
865 | |||
866 | template <typename R, typename... Args> | ||
867 | struct fx_traits<R __stdcall(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> { | ||
868 | typedef R(__stdcall* function_pointer_type)(Args...) noexcept; | ||
869 | }; | ||
870 | |||
871 | template <typename R, typename... Args> | ||
872 | struct fx_traits<R (__stdcall *)(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> { | ||
873 | typedef R(__stdcall* function_pointer_type)(Args...) noexcept; | ||
874 | }; | ||
875 | |||
876 | /* __stdcall cannot be applied to functions with varargs*/ | ||
877 | /*template <typename R, typename... Args> | ||
878 | struct fx_traits<__stdcall R(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> { | ||
879 | typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; | ||
880 | }; | ||
881 | |||
882 | template <typename R, typename... Args> | ||
883 | struct fx_traits<R (__stdcall *)(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> { | ||
884 | typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; | ||
885 | };*/ | ||
886 | |||
887 | template <typename T, typename R, typename... Args> | ||
888 | struct fx_traits<R (__stdcall T::*)(Args...) noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
889 | typedef R (__stdcall T::*function_pointer_type)(Args...) noexcept; | ||
890 | }; | ||
891 | |||
892 | /* __stdcall does not work with varargs */ | ||
893 | /*template <typename T, typename R, typename... Args> | ||
894 | struct fx_traits<R (__stdcall T::*)(Args..., ...) noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
895 | typedef R (__stdcall T::*function_pointer_type)(Args..., ...) noexcept; | ||
896 | };*/ | ||
897 | |||
898 | /* Const Volatile */ | ||
899 | template <typename T, typename R, typename... Args> | ||
900 | struct fx_traits<R (__stdcall T::*)(Args...) const noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
901 | typedef R (__stdcall T::*function_pointer_type)(Args...) const noexcept; | ||
902 | }; | ||
903 | |||
904 | /* __stdcall does not work with varargs */ | ||
905 | /*template <typename T, typename R, typename... Args> | ||
906 | struct fx_traits<R (__stdcall T::*)(Args..., ...) const noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
907 | typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const noexcept; | ||
908 | };*/ | ||
909 | |||
910 | template <typename T, typename R, typename... Args> | ||
911 | struct fx_traits<R (__stdcall T::*)(Args...) const volatile noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
912 | typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile noexcept; | ||
913 | }; | ||
914 | |||
915 | /* __stdcall does not work with varargs */ | ||
916 | /*template <typename T, typename R, typename... Args> | ||
917 | struct fx_traits<R (__stdcall T::*)(Args..., ...) const volatile noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
918 | typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile noexcept; | ||
919 | };*/ | ||
920 | |||
921 | template <typename T, typename R, typename... Args> | ||
922 | struct fx_traits<R (__stdcall T::*)(Args...) & noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
923 | typedef R (__stdcall T::*function_pointer_type)(Args...) & noexcept; | ||
924 | }; | ||
925 | |||
926 | /* __stdcall does not work with varargs */ | ||
927 | /*template <typename T, typename R, typename... Args> | ||
928 | struct fx_traits<R (__stdcall T::*)(Args..., ...) & noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
929 | typedef R (__stdcall T::*function_pointer_type)(Args..., ...) & noexcept; | ||
930 | };*/ | ||
931 | |||
932 | template <typename T, typename R, typename... Args> | ||
933 | struct fx_traits<R (__stdcall T::*)(Args...) const& noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
934 | typedef R (__stdcall T::*function_pointer_type)(Args...) const& noexcept; | ||
935 | }; | ||
936 | |||
937 | /* __stdcall does not work with varargs */ | ||
938 | /*template <typename T, typename R, typename... Args> | ||
939 | struct fx_traits<R (__stdcall T::*)(Args..., ...) const& noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
940 | typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const& noexcept; | ||
941 | };*/ | ||
942 | |||
943 | template <typename T, typename R, typename... Args> | ||
944 | struct fx_traits<R (__stdcall T::*)(Args...) const volatile& noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
945 | typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile& noexcept; | ||
946 | }; | ||
947 | |||
948 | /* __stdcall does not work with varargs */ | ||
949 | /*template <typename T, typename R, typename... Args> | ||
950 | struct fx_traits<R (__stdcall T::*)(Args..., ...) const volatile& noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
951 | typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile& noexcept; | ||
952 | };*/ | ||
953 | |||
954 | template <typename T, typename R, typename... Args> | ||
955 | struct fx_traits<R (__stdcall T::*)(Args...) && noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
956 | typedef R (__stdcall T::*function_pointer_type)(Args...) && noexcept; | ||
957 | }; | ||
958 | |||
959 | /* __stdcall does not work with varargs */ | ||
960 | /*template <typename T, typename R, typename... Args> | ||
961 | struct fx_traits<R (__stdcall T::*)(Args..., ...) && noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
962 | typedef R (__stdcall T::*function_pointer_type)(Args..., ...) && noexcept; | ||
963 | };*/ | ||
964 | |||
965 | template <typename T, typename R, typename... Args> | ||
966 | struct fx_traits<R (__stdcall T::*)(Args...) const&& noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
967 | typedef R (__stdcall T::*function_pointer_type)(Args...) const&& noexcept; | ||
968 | }; | ||
969 | |||
970 | /* __stdcall does not work with varargs */ | ||
971 | /*template <typename T, typename R, typename... Args> | ||
972 | struct fx_traits<R (__stdcall T::*)(Args..., ...) const&& noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
973 | typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const&& noexcept; | ||
974 | };*/ | ||
975 | |||
976 | template <typename T, typename R, typename... Args> | ||
977 | struct fx_traits<R (__stdcall T::*)(Args...) const volatile&& noexcept, false> : basic_traits<true, false, T, R, Args...> { | ||
978 | typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&& noexcept; | ||
979 | }; | ||
980 | |||
981 | /* __stdcall does not work with varargs */ | ||
982 | /*template <typename T, typename R, typename... Args> | ||
983 | struct fx_traits<R (__stdcall T::*)(Args..., ...) const volatile&& noexcept, false> : basic_traits<true, true, T, R, Args...> { | ||
984 | typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; | ||
985 | };*/ | ||
986 | #endif // noexcept is part of a function's type | ||
987 | #endif // __stdcall x86 VC++ bug | ||
988 | |||
989 | template <typename Signature> | ||
990 | struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {}; | ||
991 | |||
992 | template <typename Signature, bool b = std::is_member_object_pointer<Signature>::value> | ||
993 | struct callable_traits : fx_traits<std::decay_t<Signature>> { | ||
994 | }; | ||
995 | |||
996 | template <typename R, typename T> | ||
997 | struct callable_traits<R(T::*), true> { | ||
998 | typedef std::conditional_t<std::is_array<R>::value, std::add_lvalue_reference_t<T>, R> return_type; | ||
999 | typedef return_type Arg; | ||
1000 | typedef T object_type; | ||
1001 | using signature_type = R(T::*); | ||
1002 | static const bool is_noexcept = false; | ||
1003 | static const bool is_member_function = false; | ||
1004 | static const std::size_t arity = 1; | ||
1005 | static const std::size_t free_arity = 2; | ||
1006 | typedef std::tuple<Arg> args_tuple; | ||
1007 | typedef types<Arg> args_list; | ||
1008 | typedef types<T, Arg> free_args_list; | ||
1009 | typedef meta::tuple_types<return_type> returns_list; | ||
1010 | typedef return_type(function_type)(T&, return_type); | ||
1011 | typedef return_type(*function_pointer_type)(T&, Arg); | ||
1012 | typedef return_type(*free_function_pointer_type)(T&, Arg); | ||
1013 | template <std::size_t i> | ||
1014 | using arg_at = void_tuple_element_t<i, args_tuple>; | ||
1015 | }; | ||
1016 | |||
1017 | } // namespace meta_detail | ||
1018 | |||
1019 | template <typename Signature> | ||
1020 | struct bind_traits : meta_detail::callable_traits<Signature> {}; | ||
1021 | |||
1022 | template <typename Signature> | ||
1023 | using function_args_t = typename bind_traits<Signature>::args_list; | ||
1024 | |||
1025 | template <typename Signature> | ||
1026 | using function_signature_t = typename bind_traits<Signature>::signature_type; | ||
1027 | |||
1028 | template <typename Signature> | ||
1029 | using function_return_t = typename bind_traits<Signature>::return_type; | ||
1030 | } | ||
1031 | } // namespace sol::meta | ||
1032 | |||
1033 | // end of sol/bind_traits.hpp | ||
1034 | |||
1035 | // beginning of sol/string_view.hpp | ||
1036 | |||
1037 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
1038 | #include <string_view> | ||
1039 | #endif // C++17 features | ||
1040 | #include <functional> | ||
1041 | #if defined(SOL_USE_BOOST) && SOL_USE_BOOST | ||
1042 | #include <boost/functional/hash.hpp> | ||
1043 | #endif | ||
1044 | |||
1045 | namespace sol { | ||
1046 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
1047 | template <typename C, typename T = std::char_traits<C>> | ||
1048 | using basic_string_view = std::basic_string_view<C, T>; | ||
1049 | typedef std::string_view string_view; | ||
1050 | typedef std::wstring_view wstring_view; | ||
1051 | typedef std::u16string_view u16string_view; | ||
1052 | typedef std::u32string_view u32string_view; | ||
1053 | typedef std::hash<std::string_view> string_view_hash; | ||
1054 | #else | ||
1055 | template <typename Char, typename Traits = std::char_traits<Char>> | ||
1056 | struct basic_string_view { | ||
1057 | std::size_t s; | ||
1058 | const Char* p; | ||
1059 | |||
1060 | basic_string_view(const std::string& r) | ||
1061 | : basic_string_view(r.data(), r.size()) { | ||
1062 | } | ||
1063 | basic_string_view(const Char* ptr) | ||
1064 | : basic_string_view(ptr, Traits::length(ptr)) { | ||
1065 | } | ||
1066 | basic_string_view(const Char* ptr, std::size_t sz) | ||
1067 | : s(sz), p(ptr) { | ||
1068 | } | ||
1069 | |||
1070 | static int compare(const Char* lhs_p, std::size_t lhs_sz, const Char* rhs_p, std::size_t rhs_sz) { | ||
1071 | int result = Traits::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); | ||
1072 | if (result != 0) | ||
1073 | return result; | ||
1074 | if (lhs_sz < rhs_sz) | ||
1075 | return -1; | ||
1076 | if (lhs_sz > rhs_sz) | ||
1077 | return 1; | ||
1078 | return 0; | ||
1079 | } | ||
1080 | |||
1081 | const Char* begin() const { | ||
1082 | return p; | ||
1083 | } | ||
1084 | |||
1085 | const Char* end() const { | ||
1086 | return p + s; | ||
1087 | } | ||
1088 | |||
1089 | const Char* cbegin() const { | ||
1090 | return p; | ||
1091 | } | ||
1092 | |||
1093 | const Char* cend() const { | ||
1094 | return p + s; | ||
1095 | } | ||
1096 | |||
1097 | const Char* data() const { | ||
1098 | return p; | ||
1099 | } | ||
1100 | |||
1101 | std::size_t size() const { | ||
1102 | return s; | ||
1103 | } | ||
1104 | |||
1105 | std::size_t length() const { | ||
1106 | return size(); | ||
1107 | } | ||
1108 | |||
1109 | operator std::basic_string<Char, Traits>() const { | ||
1110 | return std::basic_string<Char, Traits>(data(), size()); | ||
1111 | } | ||
1112 | |||
1113 | bool operator==(const basic_string_view& r) const { | ||
1114 | return compare(p, s, r.data(), r.size()) == 0; | ||
1115 | } | ||
1116 | |||
1117 | bool operator==(const Char* r) const { | ||
1118 | return compare(r, Traits::length(r), p, s) == 0; | ||
1119 | } | ||
1120 | |||
1121 | bool operator==(const std::basic_string<Char, Traits>& r) const { | ||
1122 | return compare(r.data(), r.size(), p, s) == 0; | ||
1123 | } | ||
1124 | |||
1125 | bool operator!=(const basic_string_view& r) const { | ||
1126 | return !(*this == r); | ||
1127 | } | ||
1128 | |||
1129 | bool operator!=(const char* r) const { | ||
1130 | return !(*this == r); | ||
1131 | } | ||
1132 | |||
1133 | bool operator!=(const std::basic_string<Char, Traits>& r) const { | ||
1134 | return !(*this == r); | ||
1135 | } | ||
1136 | }; | ||
1137 | |||
1138 | template <typename Ch, typename Tr = std::char_traits<Ch>> | ||
1139 | struct basic_string_view_hash { | ||
1140 | typedef basic_string_view<Ch, Tr> argument_type; | ||
1141 | typedef std::size_t result_type; | ||
1142 | |||
1143 | template <typename Al> | ||
1144 | result_type operator()(const std::basic_string<Ch, Tr, Al>& r) const { | ||
1145 | return (*this)(argument_type(r.c_str(), r.size())); | ||
1146 | } | ||
1147 | |||
1148 | result_type operator()(const argument_type& r) const { | ||
1149 | #if defined(SOL_USE_BOOST) && SOL_USE_BOOST | ||
1150 | return boost::hash_range(r.begin(), r.end()); | ||
1151 | #else | ||
1152 | // Modified, from libstdc++ | ||
1153 | // An implementation attempt at Fowler No Voll, 1a. | ||
1154 | // Supposedly, used in MSVC, | ||
1155 | // GCC (libstdc++) uses MurmurHash of some sort for 64-bit though...? | ||
1156 | // But, well. Can't win them all, right? | ||
1157 | // This should normally only apply when NOT using boost, | ||
1158 | // so this should almost never be tapped into... | ||
1159 | std::size_t hash = 0; | ||
1160 | const unsigned char* cptr = reinterpret_cast<const unsigned char*>(r.data()); | ||
1161 | for (std::size_t sz = r.size(); sz != 0; --sz) { | ||
1162 | hash ^= static_cast<size_t>(*cptr++); | ||
1163 | hash *= static_cast<size_t>(1099511628211ULL); | ||
1164 | } | ||
1165 | return hash; | ||
1166 | #endif | ||
1167 | } | ||
1168 | }; | ||
1169 | } // namespace sol | ||
1170 | |||
1171 | namespace std { | ||
1172 | template <typename Ch, typename Tr> | ||
1173 | struct hash< ::sol::basic_string_view<Ch, Tr> > : ::sol::basic_string_view_hash<Ch, Tr> {}; | ||
1174 | } // namespace std | ||
1175 | |||
1176 | namespace sol { | ||
1177 | using string_view = basic_string_view<char>; | ||
1178 | using wstring_view = basic_string_view<wchar_t>; | ||
1179 | using u16string_view = basic_string_view<char16_t>; | ||
1180 | using u32string_view = basic_string_view<char32_t>; | ||
1181 | using string_view_hash = std::hash<string_view>; | ||
1182 | #endif // C++17 Support | ||
1183 | } // namespace sol | ||
1184 | |||
1185 | // end of sol/string_view.hpp | ||
1186 | |||
1187 | #include <type_traits> | ||
1188 | #include <cstdint> | ||
1189 | #include <memory> | ||
1190 | #include <iterator> | ||
1191 | #include <iosfwd> | ||
1192 | |||
1193 | namespace sol { | ||
1194 | template <std::size_t I> | ||
1195 | using index_value = std::integral_constant<std::size_t, I>; | ||
1196 | |||
1197 | namespace meta { | ||
1198 | template <typename T> | ||
1199 | struct identity { typedef T type; }; | ||
1200 | |||
1201 | template <typename T> | ||
1202 | using identity_t = typename identity<T>::type; | ||
1203 | |||
1204 | template <typename... Args> | ||
1205 | struct is_tuple : std::false_type {}; | ||
1206 | |||
1207 | template <typename... Args> | ||
1208 | struct is_tuple<std::tuple<Args...>> : std::true_type {}; | ||
1209 | |||
1210 | template <typename T> | ||
1211 | struct is_builtin_type : std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value> {}; | ||
1212 | |||
1213 | template <typename T> | ||
1214 | struct unwrapped { | ||
1215 | typedef T type; | ||
1216 | }; | ||
1217 | |||
1218 | template <typename T> | ||
1219 | struct unwrapped<std::reference_wrapper<T>> { | ||
1220 | typedef T type; | ||
1221 | }; | ||
1222 | |||
1223 | template <typename T> | ||
1224 | using unwrapped_t = typename unwrapped<T>::type; | ||
1225 | |||
1226 | template <typename T> | ||
1227 | struct unwrap_unqualified : unwrapped<unqualified_t<T>> {}; | ||
1228 | |||
1229 | template <typename T> | ||
1230 | using unwrap_unqualified_t = typename unwrap_unqualified<T>::type; | ||
1231 | |||
1232 | template <typename T> | ||
1233 | struct remove_member_pointer; | ||
1234 | |||
1235 | template <typename R, typename T> | ||
1236 | struct remove_member_pointer<R T::*> { | ||
1237 | typedef R type; | ||
1238 | }; | ||
1239 | |||
1240 | template <typename R, typename T> | ||
1241 | struct remove_member_pointer<R T::*const> { | ||
1242 | typedef R type; | ||
1243 | }; | ||
1244 | |||
1245 | template <typename T> | ||
1246 | using remove_member_pointer_t = remove_member_pointer<T>; | ||
1247 | |||
1248 | namespace meta_detail { | ||
1249 | template <typename T, template <typename...> class Templ> | ||
1250 | struct is_specialization_of : std::false_type {}; | ||
1251 | template <typename... T, template <typename...> class Templ> | ||
1252 | struct is_specialization_of<Templ<T...>, Templ> : std::true_type {}; | ||
1253 | } | ||
1254 | |||
1255 | template <typename T, template <typename...> class Templ> | ||
1256 | using is_specialization_of = meta_detail::is_specialization_of<std::remove_cv_t<T>, Templ>; | ||
1257 | |||
1258 | template <class T, class...> | ||
1259 | struct all_same : std::true_type {}; | ||
1260 | |||
1261 | template <class T, class U, class... Args> | ||
1262 | struct all_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value && all_same<T, Args...>::value> {}; | ||
1263 | |||
1264 | template <class T, class...> | ||
1265 | struct any_same : std::false_type {}; | ||
1266 | |||
1267 | template <class T, class U, class... Args> | ||
1268 | struct any_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value || any_same<T, Args...>::value> {}; | ||
1269 | |||
1270 | template <bool B> | ||
1271 | using boolean = std::integral_constant<bool, B>; | ||
1272 | |||
1273 | template <typename T> | ||
1274 | using invoke_t = typename T::type; | ||
1275 | |||
1276 | template <typename T> | ||
1277 | using invoke_b = boolean<T::value>; | ||
1278 | |||
1279 | template <typename T> | ||
1280 | using neg = boolean<!T::value>; | ||
1281 | |||
1282 | template <typename Condition, typename Then, typename Else> | ||
1283 | using condition = std::conditional_t<Condition::value, Then, Else>; | ||
1284 | |||
1285 | template <typename... Args> | ||
1286 | struct all : boolean<true> {}; | ||
1287 | |||
1288 | template <typename T, typename... Args> | ||
1289 | struct all<T, Args...> : condition<T, all<Args...>, boolean<false>> {}; | ||
1290 | |||
1291 | template <typename... Args> | ||
1292 | struct any : boolean<false> {}; | ||
1293 | |||
1294 | template <typename T, typename... Args> | ||
1295 | struct any<T, Args...> : condition<T, boolean<true>, any<Args...>> {}; | ||
1296 | |||
1297 | enum class enable_t { | ||
1298 | _ | ||
1299 | }; | ||
1300 | |||
1301 | constexpr const auto enabler = enable_t::_; | ||
1302 | |||
1303 | template <bool value, typename T = void> | ||
1304 | using disable_if_t = std::enable_if_t<!value, T>; | ||
1305 | |||
1306 | template <typename... Args> | ||
1307 | using enable = std::enable_if_t<all<Args...>::value, enable_t>; | ||
1308 | |||
1309 | template <typename... Args> | ||
1310 | using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>; | ||
1311 | |||
1312 | template <typename... Args> | ||
1313 | using enable_any = std::enable_if_t<any<Args...>::value, enable_t>; | ||
1314 | |||
1315 | template <typename... Args> | ||
1316 | using disable_any = std::enable_if_t<neg<any<Args...>>::value, enable_t>; | ||
1317 | |||
1318 | template <typename V, typename... Vs> | ||
1319 | struct find_in_pack_v : boolean<false> {}; | ||
1320 | |||
1321 | template <typename V, typename Vs1, typename... Vs> | ||
1322 | struct find_in_pack_v<V, Vs1, Vs...> : any<boolean<(V::value == Vs1::value)>, find_in_pack_v<V, Vs...>> {}; | ||
1323 | |||
1324 | namespace meta_detail { | ||
1325 | template <std::size_t I, typename T, typename... Args> | ||
1326 | struct index_in_pack : std::integral_constant<std::size_t, SIZE_MAX> {}; | ||
1327 | |||
1328 | template <std::size_t I, typename T, typename T1, typename... Args> | ||
1329 | struct index_in_pack<I, T, T1, Args...> : std::conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> {}; | ||
1330 | } // namespace meta_detail | ||
1331 | |||
1332 | template <typename T, typename... Args> | ||
1333 | struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> {}; | ||
1334 | |||
1335 | template <typename T, typename List> | ||
1336 | struct index_in : meta_detail::index_in_pack<0, T, List> {}; | ||
1337 | |||
1338 | template <typename T, typename... Args> | ||
1339 | struct index_in<T, types<Args...>> : meta_detail::index_in_pack<0, T, Args...> {}; | ||
1340 | |||
1341 | template <std::size_t I, typename... Args> | ||
1342 | struct at_in_pack {}; | ||
1343 | |||
1344 | template <std::size_t I, typename... Args> | ||
1345 | using at_in_pack_t = typename at_in_pack<I, Args...>::type; | ||
1346 | |||
1347 | template <std::size_t I, typename Arg, typename... Args> | ||
1348 | struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> {}; | ||
1349 | |||
1350 | template <typename Arg, typename... Args> | ||
1351 | struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; | ||
1352 | |||
1353 | namespace meta_detail { | ||
1354 | template <std::size_t Limit, std::size_t I, template <typename...> class Pred, typename... Ts> | ||
1355 | struct count_for_pack : std::integral_constant<std::size_t, 0> {}; | ||
1356 | template <std::size_t Limit, std::size_t I, template <typename...> class Pred, typename T, typename... Ts> | ||
1357 | struct count_for_pack<Limit, I, Pred, T, Ts...> : std::conditional_t < sizeof...(Ts) | ||
1358 | == 0 | ||
1359 | || Limit<2, | ||
1360 | std::integral_constant<std::size_t, I + static_cast<std::size_t>(Limit != 0 && Pred<T>::value)>, | ||
1361 | count_for_pack<Limit - 1, I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...>> {}; | ||
1362 | template <std::size_t I, template <typename...> class Pred, typename... Ts> | ||
1363 | struct count_2_for_pack : std::integral_constant<std::size_t, 0> {}; | ||
1364 | template <std::size_t I, template <typename...> class Pred, typename T, typename U, typename... Ts> | ||
1365 | struct count_2_for_pack<I, Pred, T, U, Ts...> : std::conditional_t<sizeof...(Ts) == 0, | ||
1366 | std::integral_constant<std::size_t, I + static_cast<std::size_t>(Pred<T>::value)>, | ||
1367 | count_2_for_pack<I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...>> {}; | ||
1368 | } // namespace meta_detail | ||
1369 | |||
1370 | template <template <typename...> class Pred, typename... Ts> | ||
1371 | struct count_for_pack : meta_detail::count_for_pack<sizeof...(Ts), 0, Pred, Ts...> {}; | ||
1372 | |||
1373 | template <template <typename...> class Pred, typename List> | ||
1374 | struct count_for; | ||
1375 | |||
1376 | template <template <typename...> class Pred, typename... Args> | ||
1377 | struct count_for<Pred, types<Args...>> : count_for_pack<Pred, Args...> {}; | ||
1378 | |||
1379 | template <std::size_t Limit, template <typename...> class Pred, typename... Ts> | ||
1380 | struct count_for_to_pack : meta_detail::count_for_pack<Limit, 0, Pred, Ts...> {}; | ||
1381 | |||
1382 | template <template <typename...> class Pred, typename... Ts> | ||
1383 | struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> {}; | ||
1384 | |||
1385 | template <typename... Args> | ||
1386 | struct return_type { | ||
1387 | typedef std::tuple<Args...> type; | ||
1388 | }; | ||
1389 | |||
1390 | template <typename T> | ||
1391 | struct return_type<T> { | ||
1392 | typedef T type; | ||
1393 | }; | ||
1394 | |||
1395 | template <> | ||
1396 | struct return_type<> { | ||
1397 | typedef void type; | ||
1398 | }; | ||
1399 | |||
1400 | template <typename... Args> | ||
1401 | using return_type_t = typename return_type<Args...>::type; | ||
1402 | |||
1403 | namespace meta_detail { | ||
1404 | template <typename> | ||
1405 | struct always_true : std::true_type {}; | ||
1406 | struct is_invokable_tester { | ||
1407 | template <typename Fun, typename... Args> | ||
1408 | static always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int); | ||
1409 | template <typename...> | ||
1410 | static std::false_type test(...); | ||
1411 | }; | ||
1412 | } // namespace meta_detail | ||
1413 | |||
1414 | template <typename T> | ||
1415 | struct is_invokable; | ||
1416 | template <typename Fun, typename... Args> | ||
1417 | struct is_invokable<Fun(Args...)> : decltype(meta_detail::is_invokable_tester::test<Fun, Args...>(0)) {}; | ||
1418 | |||
1419 | namespace meta_detail { | ||
1420 | |||
1421 | template <typename T, typename = void> | ||
1422 | struct is_callable : std::is_function<std::remove_pointer_t<T>> {}; | ||
1423 | |||
1424 | template <typename T> | ||
1425 | struct is_callable<T, std::enable_if_t<std::is_final<unqualified_t<T>>::value | ||
1426 | && std::is_class<unqualified_t<T>>::value | ||
1427 | && std::is_same<decltype(void(&T::operator())), void>::value>> { | ||
1428 | |||
1429 | }; | ||
1430 | |||
1431 | template <typename T> | ||
1432 | struct is_callable<T, std::enable_if_t<!std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value && std::is_destructible<unqualified_t<T>>::value>> { | ||
1433 | using yes = char; | ||
1434 | using no = struct { char s[2]; }; | ||
1435 | |||
1436 | struct F { | ||
1437 | void operator()(); | ||
1438 | }; | ||
1439 | struct Derived : T, F {}; | ||
1440 | template <typename U, U> | ||
1441 | struct Check; | ||
1442 | |||
1443 | template <typename V> | ||
1444 | static no test(Check<void (F::*)(), &V::operator()>*); | ||
1445 | |||
1446 | template <typename> | ||
1447 | static yes test(...); | ||
1448 | |||
1449 | static const bool value = sizeof(test<Derived>(0)) == sizeof(yes); | ||
1450 | }; | ||
1451 | |||
1452 | template <typename T> | ||
1453 | struct is_callable<T, std::enable_if_t<!std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value && !std::is_destructible<unqualified_t<T>>::value>> { | ||
1454 | using yes = char; | ||
1455 | using no = struct { char s[2]; }; | ||
1456 | |||
1457 | struct F { | ||
1458 | void operator()(); | ||
1459 | }; | ||
1460 | struct Derived : T, F { | ||
1461 | ~Derived() = delete; | ||
1462 | }; | ||
1463 | template <typename U, U> | ||
1464 | struct Check; | ||
1465 | |||
1466 | template <typename V> | ||
1467 | static no test(Check<void (F::*)(), &V::operator()>*); | ||
1468 | |||
1469 | template <typename> | ||
1470 | static yes test(...); | ||
1471 | |||
1472 | static const bool value = sizeof(test<Derived>(0)) == sizeof(yes); | ||
1473 | }; | ||
1474 | |||
1475 | struct has_begin_end_impl { | ||
1476 | template <typename T, typename U = unqualified_t<T>, | ||
1477 | typename B = decltype(std::declval<U&>().begin()), | ||
1478 | typename E = decltype(std::declval<U&>().end())> | ||
1479 | static std::true_type test(int); | ||
1480 | |||
1481 | template <typename...> | ||
1482 | static std::false_type test(...); | ||
1483 | }; | ||
1484 | |||
1485 | struct has_key_type_impl { | ||
1486 | template <typename T, typename U = unqualified_t<T>, | ||
1487 | typename V = typename U::key_type> | ||
1488 | static std::true_type test(int); | ||
1489 | |||
1490 | template <typename...> | ||
1491 | static std::false_type test(...); | ||
1492 | }; | ||
1493 | |||
1494 | struct has_mapped_type_impl { | ||
1495 | template <typename T, typename U = unqualified_t<T>, | ||
1496 | typename V = typename U::mapped_type> | ||
1497 | static std::true_type test(int); | ||
1498 | |||
1499 | template <typename...> | ||
1500 | static std::false_type test(...); | ||
1501 | }; | ||
1502 | |||
1503 | struct has_value_type_impl { | ||
1504 | template <typename T, typename U = unqualified_t<T>, | ||
1505 | typename V = typename U::value_type> | ||
1506 | static std::true_type test(int); | ||
1507 | |||
1508 | template <typename...> | ||
1509 | static std::false_type test(...); | ||
1510 | }; | ||
1511 | |||
1512 | struct has_iterator_impl { | ||
1513 | template <typename T, typename U = unqualified_t<T>, | ||
1514 | typename V = typename U::iterator> | ||
1515 | static std::true_type test(int); | ||
1516 | |||
1517 | template <typename...> | ||
1518 | static std::false_type test(...); | ||
1519 | }; | ||
1520 | |||
1521 | struct has_key_value_pair_impl { | ||
1522 | template <typename T, typename U = unqualified_t<T>, | ||
1523 | typename V = typename U::value_type, | ||
1524 | typename F = decltype(std::declval<V&>().first), | ||
1525 | typename S = decltype(std::declval<V&>().second)> | ||
1526 | static std::true_type test(int); | ||
1527 | |||
1528 | template <typename...> | ||
1529 | static std::false_type test(...); | ||
1530 | }; | ||
1531 | |||
1532 | template <typename T> | ||
1533 | struct has_push_back_test { | ||
1534 | private: | ||
1535 | typedef std::array<char, 1> one; | ||
1536 | typedef std::array<char, 2> two; | ||
1537 | |||
1538 | template <typename C> | ||
1539 | static one test(decltype(std::declval<C>().push_back(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); | ||
1540 | template <typename C> | ||
1541 | static two test(...); | ||
1542 | |||
1543 | public: | ||
1544 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
1545 | }; | ||
1546 | |||
1547 | template <typename T> | ||
1548 | struct has_insert_test { | ||
1549 | private: | ||
1550 | typedef std::array<char, 1> one; | ||
1551 | typedef std::array<char, 2> two; | ||
1552 | |||
1553 | template <typename C> | ||
1554 | static one test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(), std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); | ||
1555 | template <typename C> | ||
1556 | static two test(...); | ||
1557 | |||
1558 | public: | ||
1559 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
1560 | }; | ||
1561 | |||
1562 | template <typename T> | ||
1563 | struct has_insert_after_test { | ||
1564 | private: | ||
1565 | typedef std::array<char, 1> one; | ||
1566 | typedef std::array<char, 2> two; | ||
1567 | |||
1568 | template <typename C> | ||
1569 | static one test(decltype(std::declval<C>().insert_after(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(), std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); | ||
1570 | template <typename C> | ||
1571 | static two test(...); | ||
1572 | |||
1573 | public: | ||
1574 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
1575 | }; | ||
1576 | |||
1577 | template <typename T> | ||
1578 | struct has_size_test { | ||
1579 | private: | ||
1580 | typedef std::array<char, 1> one; | ||
1581 | typedef std::array<char, 2> two; | ||
1582 | |||
1583 | template <typename C> | ||
1584 | static one test(decltype(std::declval<C>().size())*); | ||
1585 | template <typename C> | ||
1586 | static two test(...); | ||
1587 | |||
1588 | public: | ||
1589 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
1590 | }; | ||
1591 | |||
1592 | template <typename T> | ||
1593 | struct has_to_string_test { | ||
1594 | private: | ||
1595 | typedef std::array<char, 1> one; | ||
1596 | typedef std::array<char, 2> two; | ||
1597 | |||
1598 | template <typename C> | ||
1599 | static one test(decltype(std::declval<C>().to_string())*); | ||
1600 | template <typename C> | ||
1601 | static two test(...); | ||
1602 | |||
1603 | public: | ||
1604 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
1605 | }; | ||
1606 | #if defined(_MSC_VER) && _MSC_VER <= 1910 | ||
1607 | template <typename T, typename U, typename = decltype(std::declval<T&>() < std::declval<U&>())> | ||
1608 | std::true_type supports_op_less_test(std::reference_wrapper<T>, std::reference_wrapper<U>); | ||
1609 | std::false_type supports_op_less_test(...); | ||
1610 | template <typename T, typename U, typename = decltype(std::declval<T&>() == std::declval<U&>())> | ||
1611 | std::true_type supports_op_equal_test(std::reference_wrapper<T>, std::reference_wrapper<U>); | ||
1612 | std::false_type supports_op_equal_test(...); | ||
1613 | template <typename T, typename U, typename = decltype(std::declval<T&>() <= std::declval<U&>())> | ||
1614 | std::true_type supports_op_less_equal_test(std::reference_wrapper<T>, std::reference_wrapper<U>); | ||
1615 | std::false_type supports_op_less_equal_test(...); | ||
1616 | template <typename T, typename OS, typename = decltype(std::declval<OS&>() << std::declval<T&>())> | ||
1617 | std::true_type supports_ostream_op(std::reference_wrapper<T>, std::reference_wrapper<OS>); | ||
1618 | std::false_type supports_ostream_op(...); | ||
1619 | template <typename T, typename = decltype(to_string(std::declval<T&>()))> | ||
1620 | std::true_type supports_adl_to_string(std::reference_wrapper<T>); | ||
1621 | std::false_type supports_adl_to_string(...); | ||
1622 | #else | ||
1623 | template <typename T, typename U, typename = decltype(std::declval<T&>() < std::declval<U&>())> | ||
1624 | std::true_type supports_op_less_test(const T&, const U&); | ||
1625 | std::false_type supports_op_less_test(...); | ||
1626 | template <typename T, typename U, typename = decltype(std::declval<T&>() == std::declval<U&>())> | ||
1627 | std::true_type supports_op_equal_test(const T&, const U&); | ||
1628 | std::false_type supports_op_equal_test(...); | ||
1629 | template <typename T, typename U, typename = decltype(std::declval<T&>() <= std::declval<U&>())> | ||
1630 | std::true_type supports_op_less_equal_test(const T&, const U&); | ||
1631 | std::false_type supports_op_less_equal_test(...); | ||
1632 | template <typename T, typename OS, typename = decltype(std::declval<OS&>() << std::declval<T&>())> | ||
1633 | std::true_type supports_ostream_op(const T&, const OS&); | ||
1634 | std::false_type supports_ostream_op(...); | ||
1635 | template <typename T, typename = decltype(to_string(std::declval<T&>()))> | ||
1636 | std::true_type supports_adl_to_string(const T&); | ||
1637 | std::false_type supports_adl_to_string(...); | ||
1638 | #endif | ||
1639 | |||
1640 | template <typename T, bool b> | ||
1641 | struct is_matched_lookup_impl : std::false_type {}; | ||
1642 | template <typename T> | ||
1643 | struct is_matched_lookup_impl<T, true> : std::is_same<typename T::key_type, typename T::value_type> {}; | ||
1644 | } // namespace meta_detail | ||
1645 | |||
1646 | #if defined(_MSC_VER) && _MSC_VER <= 1910 | ||
1647 | template <typename T, typename U = T> | ||
1648 | using supports_op_less = decltype(meta_detail::supports_op_less_test(std::ref(std::declval<T&>()), std::ref(std::declval<U&>()))); | ||
1649 | template <typename T, typename U = T> | ||
1650 | using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::ref(std::declval<T&>()), std::ref(std::declval<U&>()))); | ||
1651 | template <typename T, typename U = T> | ||
1652 | using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::ref(std::declval<T&>()), std::ref(std::declval<U&>()))); | ||
1653 | template <typename T, typename U = std::ostream> | ||
1654 | using supports_ostream_op = decltype(meta_detail::supports_ostream_op(std::ref(std::declval<T&>()), std::ref(std::declval<U&>()))); | ||
1655 | template <typename T> | ||
1656 | using supports_adl_to_string = decltype(meta_detail::supports_adl_to_string(std::ref(std::declval<T&>()))); | ||
1657 | #else | ||
1658 | template <typename T, typename U = T> | ||
1659 | using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval<T&>(), std::declval<U&>())); | ||
1660 | template <typename T, typename U = T> | ||
1661 | using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval<T&>(), std::declval<U&>())); | ||
1662 | template <typename T, typename U = T> | ||
1663 | using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>(), std::declval<U&>())); | ||
1664 | template <typename T, typename U = std::ostream> | ||
1665 | using supports_ostream_op = decltype(meta_detail::supports_ostream_op(std::declval<T&>(), std::declval<U&>())); | ||
1666 | template <typename T> | ||
1667 | using supports_adl_to_string = decltype(meta_detail::supports_adl_to_string(std::declval<T&>())); | ||
1668 | #endif | ||
1669 | template <typename T> | ||
1670 | using supports_to_string_member = meta::boolean<meta_detail::has_to_string_test<T>::value>; | ||
1671 | |||
1672 | template <typename T> | ||
1673 | struct is_callable : boolean<meta_detail::is_callable<T>::value> {}; | ||
1674 | |||
1675 | template <typename T> | ||
1676 | struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) {}; | ||
1677 | |||
1678 | template <typename T> | ||
1679 | struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {}; | ||
1680 | |||
1681 | template <typename T> | ||
1682 | struct has_key_type : decltype(meta_detail::has_key_type_impl::test<T>(0)) {}; | ||
1683 | |||
1684 | template <typename T> | ||
1685 | struct has_mapped_type : decltype(meta_detail::has_mapped_type_impl::test<T>(0)) {}; | ||
1686 | |||
1687 | template <typename T> | ||
1688 | struct has_iterator : decltype(meta_detail::has_iterator_impl::test<T>(0)) {}; | ||
1689 | |||
1690 | template <typename T> | ||
1691 | struct has_value_type : decltype(meta_detail::has_value_type_impl::test<T>(0)) {}; | ||
1692 | |||
1693 | template <typename T> | ||
1694 | using has_push_back = meta::boolean<meta_detail::has_push_back_test<T>::value>; | ||
1695 | |||
1696 | template <typename T> | ||
1697 | using has_insert = meta::boolean<meta_detail::has_insert_test<T>::value>; | ||
1698 | |||
1699 | template <typename T> | ||
1700 | using has_insert_after = meta::boolean<meta_detail::has_insert_after_test<T>::value>; | ||
1701 | |||
1702 | template <typename T> | ||
1703 | using has_size = meta::boolean<meta_detail::has_size_test<T>::value || meta_detail::has_size_test<const T>::value>; | ||
1704 | |||
1705 | template <typename T> | ||
1706 | struct is_associative : meta::all<has_key_type<T>, has_key_value_pair<T>, has_mapped_type<T>> {}; | ||
1707 | |||
1708 | template <typename T> | ||
1709 | struct is_lookup : meta::all<has_key_type<T>, has_value_type<T>> {}; | ||
1710 | |||
1711 | template <typename T> | ||
1712 | struct is_matched_lookup : meta_detail::is_matched_lookup_impl<T, is_lookup<T>::value> {}; | ||
1713 | |||
1714 | template <typename T> | ||
1715 | using is_string_like = any< | ||
1716 | is_specialization_of<meta::unqualified_t<T>, std::basic_string>, | ||
1717 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
1718 | is_specialization_of<meta::unqualified_t<T>, std::basic_string_view>, | ||
1719 | #else | ||
1720 | is_specialization_of<meta::unqualified_t<T>, basic_string_view>, | ||
1721 | #endif | ||
1722 | meta::all<std::is_array<unqualified_t<T>>, meta::any_same<meta::unqualified_t<std::remove_all_extents_t<meta::unqualified_t<T>>>, char, char16_t, char32_t, wchar_t>> | ||
1723 | >; | ||
1724 | |||
1725 | template <typename T> | ||
1726 | using is_string_constructible = any< | ||
1727 | meta::all<std::is_array<unqualified_t<T>>, std::is_same<meta::unqualified_t<std::remove_all_extents_t<meta::unqualified_t<T>>>, char>>, | ||
1728 | std::is_same<unqualified_t<T>, const char*>, | ||
1729 | std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>> | ||
1730 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
1731 | , std::is_same<unqualified_t<T>, std::string_view> | ||
1732 | #endif | ||
1733 | >; | ||
1734 | |||
1735 | template <typename T> | ||
1736 | struct is_pair : std::false_type {}; | ||
1737 | |||
1738 | template <typename T1, typename T2> | ||
1739 | struct is_pair<std::pair<T1, T2>> : std::true_type {}; | ||
1740 | |||
1741 | template <typename T> | ||
1742 | using is_c_str = any< | ||
1743 | std::is_same<std::decay_t<unqualified_t<T>>, const char*>, | ||
1744 | std::is_same<std::decay_t<unqualified_t<T>>, char*>, | ||
1745 | std::is_same<unqualified_t<T>, std::string>>; | ||
1746 | |||
1747 | template <typename T> | ||
1748 | struct is_move_only : all< | ||
1749 | neg<std::is_reference<T>>, | ||
1750 | neg<std::is_copy_constructible<unqualified_t<T>>>, | ||
1751 | std::is_move_constructible<unqualified_t<T>>> {}; | ||
1752 | |||
1753 | template <typename T> | ||
1754 | using is_not_move_only = neg<is_move_only<T>>; | ||
1755 | |||
1756 | namespace meta_detail { | ||
1757 | template <typename T, meta::disable<meta::is_specialization_of<meta::unqualified_t<T>, std::tuple>> = meta::enabler> | ||
1758 | decltype(auto) force_tuple(T&& x) { | ||
1759 | return std::tuple<std::decay_t<T>>(std::forward<T>(x)); | ||
1760 | } | ||
1761 | |||
1762 | template <typename T, meta::enable<meta::is_specialization_of<meta::unqualified_t<T>, std::tuple>> = meta::enabler> | ||
1763 | decltype(auto) force_tuple(T&& x) { | ||
1764 | return std::forward<T>(x); | ||
1765 | } | ||
1766 | } // namespace meta_detail | ||
1767 | |||
1768 | template <typename... X> | ||
1769 | decltype(auto) tuplefy(X&&... x) { | ||
1770 | return std::tuple_cat(meta_detail::force_tuple(std::forward<X>(x))...); | ||
1771 | } | ||
1772 | |||
1773 | template <typename T, typename = void> | ||
1774 | struct iterator_tag { | ||
1775 | using type = std::input_iterator_tag; | ||
1776 | }; | ||
1777 | |||
1778 | template <typename T> | ||
1779 | struct iterator_tag<T, std::conditional_t<false, typename T::iterator_category, void>> { | ||
1780 | using type = typename T::iterator_category; | ||
1781 | }; | ||
1782 | |||
1783 | } // namespace meta | ||
1784 | |||
1785 | namespace detail { | ||
1786 | template <typename T> | ||
1787 | struct is_pointer_like : std::is_pointer<T> {}; | ||
1788 | template <typename T, typename D> | ||
1789 | struct is_pointer_like<std::unique_ptr<T, D>> : std::true_type {}; | ||
1790 | template <typename T> | ||
1791 | struct is_pointer_like<std::shared_ptr<T>> : std::true_type {}; | ||
1792 | |||
1793 | template <std::size_t I, typename Tuple> | ||
1794 | decltype(auto) forward_get(Tuple&& tuple) { | ||
1795 | return std::forward<meta::tuple_element_t<I, Tuple>>(std::get<I>(tuple)); | ||
1796 | } | ||
1797 | |||
1798 | template <std::size_t... I, typename Tuple> | ||
1799 | auto forward_tuple_impl(std::index_sequence<I...>, Tuple&& tuple) -> decltype(std::tuple<decltype(forward_get<I>(tuple))...>(forward_get<I>(tuple)...)) { | ||
1800 | return std::tuple<decltype(forward_get<I>(tuple))...>(std::move(std::get<I>(tuple))...); | ||
1801 | } | ||
1802 | |||
1803 | template <typename Tuple> | ||
1804 | auto forward_tuple(Tuple&& tuple) { | ||
1805 | auto x = forward_tuple_impl(std::make_index_sequence<std::tuple_size<meta::unqualified_t<Tuple>>::value>(), std::forward<Tuple>(tuple)); | ||
1806 | return x; | ||
1807 | } | ||
1808 | |||
1809 | template <typename T> | ||
1810 | auto unwrap(T&& item) -> decltype(std::forward<T>(item)) { | ||
1811 | return std::forward<T>(item); | ||
1812 | } | ||
1813 | |||
1814 | template <typename T> | ||
1815 | T& unwrap(std::reference_wrapper<T> arg) { | ||
1816 | return arg.get(); | ||
1817 | } | ||
1818 | |||
1819 | template <typename T, meta::enable<meta::neg<is_pointer_like<meta::unqualified_t<T>>>> = meta::enabler> | ||
1820 | auto deref(T&& item) -> decltype(std::forward<T>(item)) { | ||
1821 | return std::forward<T>(item); | ||
1822 | } | ||
1823 | |||
1824 | template <typename T, meta::enable<is_pointer_like<meta::unqualified_t<T>>> = meta::enabler> | ||
1825 | inline auto deref(T&& item) -> decltype(*std::forward<T>(item)) { | ||
1826 | return *std::forward<T>(item); | ||
1827 | } | ||
1828 | |||
1829 | template <typename T, meta::disable<is_pointer_like<meta::unqualified_t<T>>, meta::neg<std::is_pointer<meta::unqualified_t<T>>>> = meta::enabler> | ||
1830 | auto deref_non_pointer(T&& item) -> decltype(std::forward<T>(item)) { | ||
1831 | return std::forward<T>(item); | ||
1832 | } | ||
1833 | |||
1834 | template <typename T, meta::enable<is_pointer_like<meta::unqualified_t<T>>, meta::neg<std::is_pointer<meta::unqualified_t<T>>>> = meta::enabler> | ||
1835 | inline auto deref_non_pointer(T&& item) -> decltype(*std::forward<T>(item)) { | ||
1836 | return *std::forward<T>(item); | ||
1837 | } | ||
1838 | |||
1839 | template <typename T> | ||
1840 | inline T* ptr(T& val) { | ||
1841 | return std::addressof(val); | ||
1842 | } | ||
1843 | |||
1844 | template <typename T> | ||
1845 | inline T* ptr(std::reference_wrapper<T> val) { | ||
1846 | return std::addressof(val.get()); | ||
1847 | } | ||
1848 | |||
1849 | template <typename T> | ||
1850 | inline T* ptr(T* val) { | ||
1851 | return val; | ||
1852 | } | ||
1853 | } // namespace detail | ||
1854 | } // namespace sol | ||
1855 | |||
1856 | // end of sol/traits.hpp | ||
1857 | |||
1858 | // beginning of sol/function.hpp | ||
1859 | |||
1860 | // beginning of sol/stack.hpp | ||
1861 | |||
1862 | // beginning of sol/trampoline.hpp | ||
1863 | |||
1864 | // beginning of sol/types.hpp | ||
1865 | |||
1866 | // beginning of sol/optional.hpp | ||
1867 | |||
1868 | // beginning of sol/compatibility.hpp | ||
1869 | |||
1870 | // beginning of sol/compatibility/version.hpp | ||
1871 | |||
1872 | #if defined(SOL_USING_CXX_LUA) && SOL_USING_CXX_LUA | ||
1873 | #include <lua.h> | ||
1874 | #include <lualib.h> | ||
1875 | #include <lauxlib.h> | ||
1876 | #if defined(SOL_USING_CXX_LUAJIT) && SOL_USING_CXX_LUAJIT | ||
1877 | #include <luajit.h> | ||
1878 | #endif // C++ LuaJIT ... whatever that means | ||
1879 | #if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !(SOL_EXCEPTIONS_SAFE_PROPAGATION)) && (!defined(SOL_EXCEPTIONS_ALWAYS_UNSAFE) || !(SOL_EXCEPTIONS_ALWAYS_UNSAFE)) | ||
1880 | #define SOL_EXCEPTIONS_SAFE_PROPAGATION 1 | ||
1881 | #endif // Exceptions can be propagated safely using C++-compiled Lua | ||
1882 | #else | ||
1883 | #include <lua.hpp> | ||
1884 | #endif // C++ Mangling for Lua | ||
1885 | |||
1886 | #ifdef LUAJIT_VERSION | ||
1887 | #ifndef SOL_LUAJIT | ||
1888 | #define SOL_LUAJIT 1 | ||
1889 | #ifndef SOL_LUAJIT_VERSION | ||
1890 | #define SOL_LUAJIT_VERSION LUAJIT_VERSION_NUM | ||
1891 | #endif // SOL_LUAJIT_VERSION definition, if not present | ||
1892 | #endif // sol luajit | ||
1893 | #endif // luajit | ||
1894 | |||
1895 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 | ||
1896 | #define SOL_LUA_VERSION LUA_VERSION_NUM | ||
1897 | #elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 | ||
1898 | #define SOL_LUA_VERSION LUA_VERSION_NUM | ||
1899 | #elif !defined(LUA_VERSION_NUM) || !(LUA_VERSION_NUM) | ||
1900 | #define SOL_LUA_VERSION 500 | ||
1901 | #else | ||
1902 | #define SOL_LUA_VERSION 502 | ||
1903 | #endif // Lua Version 502, 501 || luajit, 500 | ||
1904 | |||
1905 | // end of sol/compatibility/version.hpp | ||
1906 | |||
1907 | #if !defined(SOL_NO_COMPAT) || !(SOL_NO_COMPAT) | ||
1908 | |||
1909 | #if defined(SOL_USING_CXX_LUA) && SOL_USING_CXX_LUA | ||
1910 | #ifndef COMPAT53_LUA_CPP | ||
1911 | #define COMPAT53_LUA_CPP 1 | ||
1912 | #endif // Build Lua Compat layer as C++ | ||
1913 | #endif | ||
1914 | #ifndef COMPAT53_INCLUDE_SOURCE | ||
1915 | #define COMPAT53_INCLUDE_SOURCE 1 | ||
1916 | #endif // Build Compat Layer Inline | ||
1917 | // beginning of sol/compatibility/compat-5.3.h | ||
1918 | |||
1919 | #ifndef KEPLER_PROJECT_COMPAT53_H_ | ||
1920 | #define KEPLER_PROJECT_COMPAT53_H_ | ||
1921 | |||
1922 | #include <stddef.h> | ||
1923 | #include <limits.h> | ||
1924 | #include <string.h> | ||
1925 | #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) | ||
1926 | extern "C" { | ||
1927 | #endif | ||
1928 | #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) | ||
1929 | } | ||
1930 | #endif | ||
1931 | |||
1932 | #ifndef COMPAT53_PREFIX | ||
1933 | /* we chose this name because many other lua bindings / libs have | ||
1934 | * their own compatibility layer, and that use the compat53 declaration | ||
1935 | * frequently, causing all kinds of linker / compiler issues | ||
1936 | */ | ||
1937 | # define COMPAT53_PREFIX kp_compat53 | ||
1938 | #endif // COMPAT53_PREFIX | ||
1939 | |||
1940 | #ifndef COMPAT53_API | ||
1941 | # if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE | ||
1942 | # if defined(__GNUC__) || defined(__clang__) | ||
1943 | # define COMPAT53_API __attribute__((__unused__)) static | ||
1944 | # else | ||
1945 | # define COMPAT53_API static | ||
1946 | # endif /* Clang/GCC */ | ||
1947 | # else /* COMPAT53_INCLUDE_SOURCE */ | ||
1948 | /* we are not including source, so everything is extern */ | ||
1949 | # define COMPAT53_API extern | ||
1950 | # endif /* COMPAT53_INCLUDE_SOURCE */ | ||
1951 | #endif /* COMPAT53_PREFIX */ | ||
1952 | |||
1953 | #define COMPAT53_CONCAT_HELPER(a, b) a##b | ||
1954 | #define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b) | ||
1955 | |||
1956 | /* declarations for Lua 5.1 */ | ||
1957 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 | ||
1958 | |||
1959 | /* XXX not implemented: | ||
1960 | * lua_arith (new operators) | ||
1961 | * lua_upvalueid | ||
1962 | * lua_upvaluejoin | ||
1963 | * lua_version | ||
1964 | * lua_yieldk | ||
1965 | */ | ||
1966 | |||
1967 | #ifndef LUA_OK | ||
1968 | # define LUA_OK 0 | ||
1969 | #endif | ||
1970 | #ifndef LUA_OPADD | ||
1971 | # define LUA_OPADD 0 | ||
1972 | #endif | ||
1973 | #ifndef LUA_OPSUB | ||
1974 | # define LUA_OPSUB 1 | ||
1975 | #endif | ||
1976 | #ifndef LUA_OPMUL | ||
1977 | # define LUA_OPMUL 2 | ||
1978 | #endif | ||
1979 | #ifndef LUA_OPDIV | ||
1980 | # define LUA_OPDIV 3 | ||
1981 | #endif | ||
1982 | #ifndef LUA_OPMOD | ||
1983 | # define LUA_OPMOD 4 | ||
1984 | #endif | ||
1985 | #ifndef LUA_OPPOW | ||
1986 | # define LUA_OPPOW 5 | ||
1987 | #endif | ||
1988 | #ifndef LUA_OPUNM | ||
1989 | # define LUA_OPUNM 6 | ||
1990 | #endif | ||
1991 | #ifndef LUA_OPEQ | ||
1992 | # define LUA_OPEQ 0 | ||
1993 | #endif | ||
1994 | #ifndef LUA_OPLT | ||
1995 | # define LUA_OPLT 1 | ||
1996 | #endif | ||
1997 | #ifndef LUA_OPLE | ||
1998 | # define LUA_OPLE 2 | ||
1999 | #endif | ||
2000 | |||
2001 | /* LuaJIT/Lua 5.1 does not have the updated | ||
2002 | * error codes for thread status/function returns (but some patched versions do) | ||
2003 | * define it only if it's not found | ||
2004 | */ | ||
2005 | #if !defined(LUA_ERRGCMM) | ||
2006 | /* Use + 2 because in some versions of Lua (Lua 5.1) | ||
2007 | * LUA_ERRFILE is defined as (LUA_ERRERR+1) | ||
2008 | * so we need to avoid it (LuaJIT might have something at this | ||
2009 | * integer value too) | ||
2010 | */ | ||
2011 | # define LUA_ERRGCMM (LUA_ERRERR + 2) | ||
2012 | #endif /* LUA_ERRGCMM define */ | ||
2013 | |||
2014 | typedef size_t lua_Unsigned; | ||
2015 | |||
2016 | typedef struct luaL_Buffer_53 { | ||
2017 | luaL_Buffer b; /* make incorrect code crash! */ | ||
2018 | char *ptr; | ||
2019 | size_t nelems; | ||
2020 | size_t capacity; | ||
2021 | lua_State *L2; | ||
2022 | } luaL_Buffer_53; | ||
2023 | #define luaL_Buffer luaL_Buffer_53 | ||
2024 | |||
2025 | /* In PUC-Rio 5.1, userdata is a simple FILE* | ||
2026 | * In LuaJIT, it's a struct where the first member is a FILE* | ||
2027 | * We can't support the `closef` member | ||
2028 | */ | ||
2029 | typedef struct luaL_Stream { | ||
2030 | FILE *f; | ||
2031 | } luaL_Stream; | ||
2032 | |||
2033 | #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) | ||
2034 | COMPAT53_API int lua_absindex(lua_State *L, int i); | ||
2035 | |||
2036 | #define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith) | ||
2037 | COMPAT53_API void lua_arith(lua_State *L, int op); | ||
2038 | |||
2039 | #define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare) | ||
2040 | COMPAT53_API int lua_compare(lua_State *L, int idx1, int idx2, int op); | ||
2041 | |||
2042 | #define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy) | ||
2043 | COMPAT53_API void lua_copy(lua_State *L, int from, int to); | ||
2044 | |||
2045 | #define lua_getuservalue(L, i) \ | ||
2046 | (lua_getfenv((L), (i)), lua_type((L), -1)) | ||
2047 | #define lua_setuservalue(L, i) \ | ||
2048 | (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i))) | ||
2049 | |||
2050 | #define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len) | ||
2051 | COMPAT53_API void lua_len(lua_State *L, int i); | ||
2052 | |||
2053 | #define lua_pushstring(L, s) \ | ||
2054 | (lua_pushstring((L), (s)), lua_tostring((L), -1)) | ||
2055 | |||
2056 | #define lua_pushlstring(L, s, len) \ | ||
2057 | ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1)) | ||
2058 | |||
2059 | #ifndef luaL_newlibtable | ||
2060 | # define luaL_newlibtable(L, l) \ | ||
2061 | (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1)) | ||
2062 | #endif | ||
2063 | #ifndef luaL_newlib | ||
2064 | # define luaL_newlib(L, l) \ | ||
2065 | (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l))) | ||
2066 | #endif | ||
2067 | |||
2068 | #define lua_pushglobaltable(L) \ | ||
2069 | lua_pushvalue((L), LUA_GLOBALSINDEX) | ||
2070 | |||
2071 | #define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp) | ||
2072 | COMPAT53_API int lua_rawgetp(lua_State *L, int i, const void *p); | ||
2073 | |||
2074 | #define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp) | ||
2075 | COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p); | ||
2076 | |||
2077 | #define lua_rawlen(L, i) lua_objlen((L), (i)) | ||
2078 | |||
2079 | #define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL) | ||
2080 | |||
2081 | #define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx) | ||
2082 | COMPAT53_API lua_Number lua_tonumberx(lua_State *L, int i, int *isnum); | ||
2083 | |||
2084 | #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) | ||
2085 | COMPAT53_API void luaL_checkversion(lua_State *L); | ||
2086 | |||
2087 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) | ||
2088 | COMPAT53_API int lua_load(lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode); | ||
2089 | |||
2090 | #define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) | ||
2091 | COMPAT53_API int luaL_loadfilex(lua_State *L, const char *filename, const char *mode); | ||
2092 | |||
2093 | #define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx) | ||
2094 | COMPAT53_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); | ||
2095 | |||
2096 | #define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53) | ||
2097 | COMPAT53_API void luaL_checkstack(lua_State *L, int sp, const char *msg); | ||
2098 | |||
2099 | #define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable) | ||
2100 | COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char *name); | ||
2101 | |||
2102 | #define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len) | ||
2103 | COMPAT53_API lua_Integer luaL_len(lua_State *L, int i); | ||
2104 | |||
2105 | #define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs) | ||
2106 | COMPAT53_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); | ||
2107 | |||
2108 | #define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable) | ||
2109 | COMPAT53_API void luaL_setmetatable(lua_State *L, const char *tname); | ||
2110 | |||
2111 | #define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata) | ||
2112 | COMPAT53_API void *luaL_testudata(lua_State *L, int i, const char *tname); | ||
2113 | |||
2114 | #define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback) | ||
2115 | COMPAT53_API void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level); | ||
2116 | |||
2117 | #define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult) | ||
2118 | COMPAT53_API int luaL_fileresult(lua_State *L, int stat, const char *fname); | ||
2119 | |||
2120 | #define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult) | ||
2121 | COMPAT53_API int luaL_execresult(lua_State *L, int stat); | ||
2122 | |||
2123 | #define lua_callk(L, na, nr, ctx, cont) \ | ||
2124 | ((void)(ctx), (void)(cont), lua_call((L), (na), (nr))) | ||
2125 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ | ||
2126 | ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err))) | ||
2127 | |||
2128 | #define lua_resume(L, from, nargs) \ | ||
2129 | ((void)(from), lua_resume((L), (nargs))) | ||
2130 | |||
2131 | #define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53) | ||
2132 | COMPAT53_API void luaL_buffinit(lua_State *L, luaL_Buffer_53 *B); | ||
2133 | |||
2134 | #define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53) | ||
2135 | COMPAT53_API char *luaL_prepbuffsize(luaL_Buffer_53 *B, size_t s); | ||
2136 | |||
2137 | #define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53) | ||
2138 | COMPAT53_API void luaL_addlstring(luaL_Buffer_53 *B, const char *s, size_t l); | ||
2139 | |||
2140 | #define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53) | ||
2141 | COMPAT53_API void luaL_addvalue(luaL_Buffer_53 *B); | ||
2142 | |||
2143 | #define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53) | ||
2144 | COMPAT53_API void luaL_pushresult(luaL_Buffer_53 *B); | ||
2145 | |||
2146 | #undef luaL_buffinitsize | ||
2147 | #define luaL_buffinitsize(L, B, s) \ | ||
2148 | (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s))) | ||
2149 | |||
2150 | #undef luaL_prepbuffer | ||
2151 | #define luaL_prepbuffer(B) \ | ||
2152 | luaL_prepbuffsize((B), LUAL_BUFFERSIZE) | ||
2153 | |||
2154 | #undef luaL_addchar | ||
2155 | #define luaL_addchar(B, c) \ | ||
2156 | ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \ | ||
2157 | ((B)->ptr[(B)->nelems++] = (c))) | ||
2158 | |||
2159 | #undef luaL_addsize | ||
2160 | #define luaL_addsize(B, s) \ | ||
2161 | ((B)->nelems += (s)) | ||
2162 | |||
2163 | #undef luaL_addstring | ||
2164 | #define luaL_addstring(B, s) \ | ||
2165 | luaL_addlstring((B), (s), strlen((s))) | ||
2166 | |||
2167 | #undef luaL_pushresultsize | ||
2168 | #define luaL_pushresultsize(B, s) \ | ||
2169 | (luaL_addsize((B), (s)), luaL_pushresult((B))) | ||
2170 | |||
2171 | #if defined(LUA_COMPAT_APIINTCASTS) | ||
2172 | #define lua_pushunsigned(L, n) \ | ||
2173 | lua_pushinteger((L), (lua_Integer)(n)) | ||
2174 | #define lua_tounsignedx(L, i, is) \ | ||
2175 | ((lua_Unsigned)lua_tointegerx((L), (i), (is))) | ||
2176 | #define lua_tounsigned(L, i) \ | ||
2177 | lua_tounsignedx((L), (i), NULL) | ||
2178 | #define luaL_checkunsigned(L, a) \ | ||
2179 | ((lua_Unsigned)luaL_checkinteger((L), (a))) | ||
2180 | #define luaL_optunsigned(L, a, d) \ | ||
2181 | ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d))) | ||
2182 | #endif | ||
2183 | |||
2184 | #endif /* Lua 5.1 only */ | ||
2185 | |||
2186 | /* declarations for Lua 5.1 and 5.2 */ | ||
2187 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502 | ||
2188 | |||
2189 | typedef int lua_KContext; | ||
2190 | |||
2191 | typedef int(*lua_KFunction)(lua_State *L, int status, lua_KContext ctx); | ||
2192 | |||
2193 | #define lua_dump(L, w, d, s) \ | ||
2194 | ((void)(s), lua_dump((L), (w), (d))) | ||
2195 | |||
2196 | #define lua_getfield(L, i, k) \ | ||
2197 | (lua_getfield((L), (i), (k)), lua_type((L), -1)) | ||
2198 | |||
2199 | #define lua_gettable(L, i) \ | ||
2200 | (lua_gettable((L), (i)), lua_type((L), -1)) | ||
2201 | |||
2202 | #define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti) | ||
2203 | COMPAT53_API int lua_geti(lua_State *L, int index, lua_Integer i); | ||
2204 | |||
2205 | #define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger) | ||
2206 | COMPAT53_API int lua_isinteger(lua_State *L, int index); | ||
2207 | |||
2208 | #define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53) | ||
2209 | COMPAT53_API lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum); | ||
2210 | |||
2211 | #define lua_numbertointeger(n, p) \ | ||
2212 | ((*(p) = (lua_Integer)(n)), 1) | ||
2213 | |||
2214 | #define lua_rawget(L, i) \ | ||
2215 | (lua_rawget((L), (i)), lua_type((L), -1)) | ||
2216 | |||
2217 | #define lua_rawgeti(L, i, n) \ | ||
2218 | (lua_rawgeti((L), (i), (n)), lua_type((L), -1)) | ||
2219 | |||
2220 | #define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate) | ||
2221 | COMPAT53_API void lua_rotate(lua_State *L, int idx, int n); | ||
2222 | |||
2223 | #define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti) | ||
2224 | COMPAT53_API void lua_seti(lua_State *L, int index, lua_Integer i); | ||
2225 | |||
2226 | #define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber) | ||
2227 | COMPAT53_API size_t lua_stringtonumber(lua_State *L, const char *s); | ||
2228 | |||
2229 | #define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring) | ||
2230 | COMPAT53_API const char *luaL_tolstring(lua_State *L, int idx, size_t *len); | ||
2231 | |||
2232 | #define luaL_getmetafield(L, o, e) \ | ||
2233 | (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL) | ||
2234 | |||
2235 | #define luaL_newmetatable(L, tn) \ | ||
2236 | (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0) | ||
2237 | |||
2238 | #define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53) | ||
2239 | COMPAT53_API void luaL_requiref(lua_State *L, const char *modname, | ||
2240 | lua_CFunction openf, int glb); | ||
2241 | |||
2242 | #endif /* Lua 5.1 and Lua 5.2 */ | ||
2243 | |||
2244 | /* declarations for Lua 5.2 */ | ||
2245 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502 | ||
2246 | |||
2247 | /* XXX not implemented: | ||
2248 | * lua_isyieldable | ||
2249 | * lua_getextraspace | ||
2250 | * lua_arith (new operators) | ||
2251 | * lua_pushfstring (new formats) | ||
2252 | */ | ||
2253 | |||
2254 | #define lua_getglobal(L, n) \ | ||
2255 | (lua_getglobal((L), (n)), lua_type((L), -1)) | ||
2256 | |||
2257 | #define lua_getuservalue(L, i) \ | ||
2258 | (lua_getuservalue((L), (i)), lua_type((L), -1)) | ||
2259 | |||
2260 | #define lua_pushlstring(L, s, len) \ | ||
2261 | (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))) | ||
2262 | |||
2263 | #define lua_rawgetp(L, i, p) \ | ||
2264 | (lua_rawgetp((L), (i), (p)), lua_type((L), -1)) | ||
2265 | |||
2266 | #define LUA_KFUNCTION(_name) \ | ||
2267 | static int (_name)(lua_State *L, int status, lua_KContext ctx); \ | ||
2268 | static int (_name ## _52)(lua_State *L) { \ | ||
2269 | lua_KContext ctx; \ | ||
2270 | int status = lua_getctx(L, &ctx); \ | ||
2271 | return (_name)(L, status, ctx); \ | ||
2272 | } \ | ||
2273 | static int (_name)(lua_State *L, int status, lua_KContext ctx) | ||
2274 | |||
2275 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ | ||
2276 | lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52) | ||
2277 | |||
2278 | #define lua_callk(L, na, nr, ctx, cont) \ | ||
2279 | lua_callk((L), (na), (nr), (ctx), cont ## _52) | ||
2280 | |||
2281 | #define lua_yieldk(L, nr, ctx, cont) \ | ||
2282 | lua_yieldk((L), (nr), (ctx), cont ## _52) | ||
2283 | |||
2284 | #ifdef lua_call | ||
2285 | # undef lua_call | ||
2286 | # define lua_call(L, na, nr) \ | ||
2287 | (lua_callk)((L), (na), (nr), 0, NULL) | ||
2288 | #endif | ||
2289 | |||
2290 | #ifdef lua_pcall | ||
2291 | # undef lua_pcall | ||
2292 | # define lua_pcall(L, na, nr, err) \ | ||
2293 | (lua_pcallk)((L), (na), (nr), (err), 0, NULL) | ||
2294 | #endif | ||
2295 | |||
2296 | #ifdef lua_yield | ||
2297 | # undef lua_yield | ||
2298 | # define lua_yield(L, nr) \ | ||
2299 | (lua_yieldk)((L), (nr), 0, NULL) | ||
2300 | #endif | ||
2301 | |||
2302 | #endif /* Lua 5.2 only */ | ||
2303 | |||
2304 | /* other Lua versions */ | ||
2305 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 503 | ||
2306 | |||
2307 | # error "unsupported Lua version (i.e. not Lua 5.1, 5.2, or 5.3)" | ||
2308 | |||
2309 | #endif /* other Lua versions except 5.1, 5.2, and 5.3 */ | ||
2310 | |||
2311 | /* helper macro for defining continuation functions (for every version | ||
2312 | * *except* Lua 5.2) */ | ||
2313 | #ifndef LUA_KFUNCTION | ||
2314 | #define LUA_KFUNCTION(_name) \ | ||
2315 | static int (_name)(lua_State *L, int status, lua_KContext ctx) | ||
2316 | #endif | ||
2317 | |||
2318 | #if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE == 1 | ||
2319 | // beginning of sol/compatibility/compat-5.3.c | ||
2320 | |||
2321 | #include <stdlib.h> | ||
2322 | #include <ctype.h> | ||
2323 | #include <errno.h> | ||
2324 | #include <stdio.h> | ||
2325 | |||
2326 | /* don't compile it again if it already is included via compat53.h */ | ||
2327 | #ifndef KEPLER_PROJECT_COMPAT53_C_ | ||
2328 | #define KEPLER_PROJECT_COMPAT53_C_ | ||
2329 | |||
2330 | /* definitions for Lua 5.1 only */ | ||
2331 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 | ||
2332 | |||
2333 | #ifndef COMPAT53_FOPEN_NO_LOCK | ||
2334 | # if defined(_MSC_VER) | ||
2335 | # define COMPAT53_FOPEN_NO_LOCK 1 | ||
2336 | # else /* otherwise */ | ||
2337 | # define COMPAT53_FOPEN_NO_LOCK 0 | ||
2338 | # endif /* VC++ only so far */ | ||
2339 | #endif /* No-lock fopen_s usage if possible */ | ||
2340 | |||
2341 | #if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK | ||
2342 | # include <share.h> | ||
2343 | #endif /* VC++ _fsopen for share-allowed file read */ | ||
2344 | |||
2345 | #ifndef COMPAT53_HAVE_STRERROR_R | ||
2346 | # if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || \ | ||
2347 | (!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6)) | ||
2348 | # define COMPAT53_HAVE_STRERROR_R 1 | ||
2349 | # else /* none of the defines matched: define to 0 */ | ||
2350 | # define COMPAT53_HAVE_STRERROR_R 0 | ||
2351 | # endif /* have strerror_r of some form */ | ||
2352 | #endif /* strerror_r */ | ||
2353 | |||
2354 | #ifndef COMPAT53_HAVE_STRERROR_S | ||
2355 | # if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ | ||
2356 | (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) | ||
2357 | # define COMPAT53_HAVE_STRERROR_S 1 | ||
2358 | # else /* not VC++ or C11 */ | ||
2359 | # define COMPAT53_HAVE_STRERROR_S 0 | ||
2360 | # endif /* strerror_s from VC++ or C11 */ | ||
2361 | #endif /* strerror_s */ | ||
2362 | |||
2363 | #ifndef COMPAT53_LUA_FILE_BUFFER_SIZE | ||
2364 | # define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 | ||
2365 | #endif /* Lua File Buffer Size */ | ||
2366 | |||
2367 | static char* compat53_strerror(int en, char* buff, size_t sz) { | ||
2368 | #if COMPAT53_HAVE_STRERROR_R | ||
2369 | /* use strerror_r here, because it's available on these specific platforms */ | ||
2370 | if (sz > 0) { | ||
2371 | buff[0] = '\0'; | ||
2372 | /* we don't care whether the GNU version or the XSI version is used: */ | ||
2373 | if (strerror_r(en, buff, sz)) { | ||
2374 | /* Yes, we really DO want to ignore the return value! | ||
2375 | * GCC makes that extra hard, not even a (void) cast will do. */ | ||
2376 | } | ||
2377 | if (buff[0] == '\0') { | ||
2378 | /* Buffer is unchanged, so we probably have called GNU strerror_r which | ||
2379 | * returned a static constant string. Chances are that strerror will | ||
2380 | * return the same static constant string and therefore be thread-safe. */ | ||
2381 | return strerror(en); | ||
2382 | } | ||
2383 | } | ||
2384 | return buff; /* sz is 0 *or* strerror_r wrote into the buffer */ | ||
2385 | #elif COMPAT53_HAVE_STRERROR_S | ||
2386 | /* for MSVC and other C11 implementations, use strerror_s since it's | ||
2387 | * provided by default by the libraries */ | ||
2388 | strerror_s(buff, sz, en); | ||
2389 | return buff; | ||
2390 | #else | ||
2391 | /* fallback, but strerror is not guaranteed to be threadsafe due to modifying | ||
2392 | * errno itself and some impls not locking a static buffer for it ... but most | ||
2393 | * known systems have threadsafe errno: this might only change if the locale | ||
2394 | * is changed out from under someone while this function is being called */ | ||
2395 | (void)buff; | ||
2396 | (void)sz; | ||
2397 | return strerror(en); | ||
2398 | #endif | ||
2399 | } | ||
2400 | |||
2401 | COMPAT53_API int lua_absindex(lua_State *L, int i) { | ||
2402 | if (i < 0 && i > LUA_REGISTRYINDEX) | ||
2403 | i += lua_gettop(L) + 1; | ||
2404 | return i; | ||
2405 | } | ||
2406 | |||
2407 | static void compat53_call_lua(lua_State *L, char const code[], size_t len, | ||
2408 | int nargs, int nret) { | ||
2409 | lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); | ||
2410 | if (lua_type(L, -1) != LUA_TFUNCTION) { | ||
2411 | lua_pop(L, 1); | ||
2412 | if (luaL_loadbuffer(L, code, len, "=none")) | ||
2413 | lua_error(L); | ||
2414 | lua_pushvalue(L, -1); | ||
2415 | lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); | ||
2416 | } | ||
2417 | lua_insert(L, -nargs - 1); | ||
2418 | lua_call(L, nargs, nret); | ||
2419 | } | ||
2420 | |||
2421 | static const char compat53_arith_code[] = | ||
2422 | "local op,a,b=...\n" | ||
2423 | "if op==0 then return a+b\n" | ||
2424 | "elseif op==1 then return a-b\n" | ||
2425 | "elseif op==2 then return a*b\n" | ||
2426 | "elseif op==3 then return a/b\n" | ||
2427 | "elseif op==4 then return a%b\n" | ||
2428 | "elseif op==5 then return a^b\n" | ||
2429 | "elseif op==6 then return -a\n" | ||
2430 | "end\n"; | ||
2431 | |||
2432 | COMPAT53_API void lua_arith(lua_State *L, int op) { | ||
2433 | if (op < LUA_OPADD || op > LUA_OPUNM) | ||
2434 | luaL_error(L, "invalid 'op' argument for lua_arith"); | ||
2435 | luaL_checkstack(L, 5, "not enough stack slots"); | ||
2436 | if (op == LUA_OPUNM) | ||
2437 | lua_pushvalue(L, -1); | ||
2438 | lua_pushnumber(L, op); | ||
2439 | lua_insert(L, -3); | ||
2440 | compat53_call_lua(L, compat53_arith_code, | ||
2441 | sizeof(compat53_arith_code) - 1, 3, 1); | ||
2442 | } | ||
2443 | |||
2444 | static const char compat53_compare_code[] = | ||
2445 | "local a,b=...\n" | ||
2446 | "return a<=b\n"; | ||
2447 | |||
2448 | COMPAT53_API int lua_compare(lua_State *L, int idx1, int idx2, int op) { | ||
2449 | int result = 0; | ||
2450 | switch (op) { | ||
2451 | case LUA_OPEQ: | ||
2452 | return lua_equal(L, idx1, idx2); | ||
2453 | case LUA_OPLT: | ||
2454 | return lua_lessthan(L, idx1, idx2); | ||
2455 | case LUA_OPLE: | ||
2456 | luaL_checkstack(L, 5, "not enough stack slots"); | ||
2457 | idx1 = lua_absindex(L, idx1); | ||
2458 | idx2 = lua_absindex(L, idx2); | ||
2459 | lua_pushvalue(L, idx1); | ||
2460 | lua_pushvalue(L, idx2); | ||
2461 | compat53_call_lua(L, compat53_compare_code, | ||
2462 | sizeof(compat53_compare_code) - 1, 2, 1); | ||
2463 | result = lua_toboolean(L, -1); | ||
2464 | lua_pop(L, 1); | ||
2465 | return result; | ||
2466 | default: | ||
2467 | luaL_error(L, "invalid 'op' argument for lua_compare"); | ||
2468 | } | ||
2469 | return 0; | ||
2470 | } | ||
2471 | |||
2472 | COMPAT53_API void lua_copy(lua_State *L, int from, int to) { | ||
2473 | int abs_to = lua_absindex(L, to); | ||
2474 | luaL_checkstack(L, 1, "not enough stack slots"); | ||
2475 | lua_pushvalue(L, from); | ||
2476 | lua_replace(L, abs_to); | ||
2477 | } | ||
2478 | |||
2479 | COMPAT53_API void lua_len(lua_State *L, int i) { | ||
2480 | switch (lua_type(L, i)) { | ||
2481 | case LUA_TSTRING: | ||
2482 | lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); | ||
2483 | break; | ||
2484 | case LUA_TTABLE: | ||
2485 | if (!luaL_callmeta(L, i, "__len")) | ||
2486 | lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); | ||
2487 | break; | ||
2488 | case LUA_TUSERDATA: | ||
2489 | if (luaL_callmeta(L, i, "__len")) | ||
2490 | break; | ||
2491 | /* FALLTHROUGH */ | ||
2492 | default: | ||
2493 | luaL_error(L, "attempt to get length of a %s value", | ||
2494 | lua_typename(L, lua_type(L, i))); | ||
2495 | } | ||
2496 | } | ||
2497 | |||
2498 | COMPAT53_API int lua_rawgetp(lua_State *L, int i, const void *p) { | ||
2499 | int abs_i = lua_absindex(L, i); | ||
2500 | lua_pushlightuserdata(L, (void*)p); | ||
2501 | lua_rawget(L, abs_i); | ||
2502 | return lua_type(L, -1); | ||
2503 | } | ||
2504 | |||
2505 | COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p) { | ||
2506 | int abs_i = lua_absindex(L, i); | ||
2507 | luaL_checkstack(L, 1, "not enough stack slots"); | ||
2508 | lua_pushlightuserdata(L, (void*)p); | ||
2509 | lua_insert(L, -2); | ||
2510 | lua_rawset(L, abs_i); | ||
2511 | } | ||
2512 | |||
2513 | COMPAT53_API lua_Number lua_tonumberx(lua_State *L, int i, int *isnum) { | ||
2514 | lua_Number n = lua_tonumber(L, i); | ||
2515 | if (isnum != NULL) { | ||
2516 | *isnum = (n != 0 || lua_isnumber(L, i)); | ||
2517 | } | ||
2518 | return n; | ||
2519 | } | ||
2520 | |||
2521 | COMPAT53_API void luaL_checkversion(lua_State *L) { | ||
2522 | (void)L; | ||
2523 | } | ||
2524 | |||
2525 | COMPAT53_API void luaL_checkstack(lua_State *L, int sp, const char *msg) { | ||
2526 | if (!lua_checkstack(L, sp + LUA_MINSTACK)) { | ||
2527 | if (msg != NULL) | ||
2528 | luaL_error(L, "stack overflow (%s)", msg); | ||
2529 | else { | ||
2530 | lua_pushliteral(L, "stack overflow"); | ||
2531 | lua_error(L); | ||
2532 | } | ||
2533 | } | ||
2534 | } | ||
2535 | |||
2536 | COMPAT53_API int luaL_getsubtable(lua_State *L, int i, const char *name) { | ||
2537 | int abs_i = lua_absindex(L, i); | ||
2538 | luaL_checkstack(L, 3, "not enough stack slots"); | ||
2539 | lua_pushstring(L, name); | ||
2540 | lua_gettable(L, abs_i); | ||
2541 | if (lua_istable(L, -1)) | ||
2542 | return 1; | ||
2543 | lua_pop(L, 1); | ||
2544 | lua_newtable(L); | ||
2545 | lua_pushstring(L, name); | ||
2546 | lua_pushvalue(L, -2); | ||
2547 | lua_settable(L, abs_i); | ||
2548 | return 0; | ||
2549 | } | ||
2550 | |||
2551 | COMPAT53_API lua_Integer luaL_len(lua_State *L, int i) { | ||
2552 | lua_Integer res = 0; | ||
2553 | int isnum = 0; | ||
2554 | luaL_checkstack(L, 1, "not enough stack slots"); | ||
2555 | lua_len(L, i); | ||
2556 | res = lua_tointegerx(L, -1, &isnum); | ||
2557 | lua_pop(L, 1); | ||
2558 | if (!isnum) | ||
2559 | luaL_error(L, "object length is not an integer"); | ||
2560 | return res; | ||
2561 | } | ||
2562 | |||
2563 | COMPAT53_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { | ||
2564 | luaL_checkstack(L, nup + 1, "too many upvalues"); | ||
2565 | for (; l->name != NULL; l++) { /* fill the table with given functions */ | ||
2566 | int i; | ||
2567 | lua_pushstring(L, l->name); | ||
2568 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ | ||
2569 | lua_pushvalue(L, -(nup + 1)); | ||
2570 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ | ||
2571 | lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ | ||
2572 | } | ||
2573 | lua_pop(L, nup); /* remove upvalues */ | ||
2574 | } | ||
2575 | |||
2576 | COMPAT53_API void luaL_setmetatable(lua_State *L, const char *tname) { | ||
2577 | luaL_checkstack(L, 1, "not enough stack slots"); | ||
2578 | luaL_getmetatable(L, tname); | ||
2579 | lua_setmetatable(L, -2); | ||
2580 | } | ||
2581 | |||
2582 | COMPAT53_API void *luaL_testudata(lua_State *L, int i, const char *tname) { | ||
2583 | void *p = lua_touserdata(L, i); | ||
2584 | luaL_checkstack(L, 2, "not enough stack slots"); | ||
2585 | if (p == NULL || !lua_getmetatable(L, i)) | ||
2586 | return NULL; | ||
2587 | else { | ||
2588 | int res = 0; | ||
2589 | luaL_getmetatable(L, tname); | ||
2590 | res = lua_rawequal(L, -1, -2); | ||
2591 | lua_pop(L, 2); | ||
2592 | if (!res) | ||
2593 | p = NULL; | ||
2594 | } | ||
2595 | return p; | ||
2596 | } | ||
2597 | |||
2598 | static int compat53_countlevels(lua_State *L) { | ||
2599 | lua_Debug ar; | ||
2600 | int li = 1, le = 1; | ||
2601 | /* find an upper bound */ | ||
2602 | while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } | ||
2603 | /* do a binary search */ | ||
2604 | while (li < le) { | ||
2605 | int m = (li + le) / 2; | ||
2606 | if (lua_getstack(L, m, &ar)) li = m + 1; | ||
2607 | else le = m; | ||
2608 | } | ||
2609 | return le - 1; | ||
2610 | } | ||
2611 | |||
2612 | static int compat53_findfield(lua_State *L, int objidx, int level) { | ||
2613 | if (level == 0 || !lua_istable(L, -1)) | ||
2614 | return 0; /* not found */ | ||
2615 | lua_pushnil(L); /* start 'next' loop */ | ||
2616 | while (lua_next(L, -2)) { /* for each pair in table */ | ||
2617 | if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ | ||
2618 | if (lua_rawequal(L, objidx, -1)) { /* found object? */ | ||
2619 | lua_pop(L, 1); /* remove value (but keep name) */ | ||
2620 | return 1; | ||
2621 | } | ||
2622 | else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */ | ||
2623 | lua_remove(L, -2); /* remove table (but keep name) */ | ||
2624 | lua_pushliteral(L, "."); | ||
2625 | lua_insert(L, -2); /* place '.' between the two names */ | ||
2626 | lua_concat(L, 3); | ||
2627 | return 1; | ||
2628 | } | ||
2629 | } | ||
2630 | lua_pop(L, 1); /* remove value */ | ||
2631 | } | ||
2632 | return 0; /* not found */ | ||
2633 | } | ||
2634 | |||
2635 | static int compat53_pushglobalfuncname(lua_State *L, lua_Debug *ar) { | ||
2636 | int top = lua_gettop(L); | ||
2637 | lua_getinfo(L, "f", ar); /* push function */ | ||
2638 | lua_pushvalue(L, LUA_GLOBALSINDEX); | ||
2639 | if (compat53_findfield(L, top + 1, 2)) { | ||
2640 | lua_copy(L, -1, top + 1); /* move name to proper place */ | ||
2641 | lua_pop(L, 2); /* remove pushed values */ | ||
2642 | return 1; | ||
2643 | } | ||
2644 | else { | ||
2645 | lua_settop(L, top); /* remove function and global table */ | ||
2646 | return 0; | ||
2647 | } | ||
2648 | } | ||
2649 | |||
2650 | static void compat53_pushfuncname(lua_State *L, lua_Debug *ar) { | ||
2651 | if (*ar->namewhat != '\0') /* is there a name? */ | ||
2652 | lua_pushfstring(L, "function " LUA_QS, ar->name); | ||
2653 | else if (*ar->what == 'm') /* main? */ | ||
2654 | lua_pushliteral(L, "main chunk"); | ||
2655 | else if (*ar->what == 'C') { | ||
2656 | if (compat53_pushglobalfuncname(L, ar)) { | ||
2657 | lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); | ||
2658 | lua_remove(L, -2); /* remove name */ | ||
2659 | } | ||
2660 | else | ||
2661 | lua_pushliteral(L, "?"); | ||
2662 | } | ||
2663 | else | ||
2664 | lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); | ||
2665 | } | ||
2666 | |||
2667 | #define COMPAT53_LEVELS1 12 /* size of the first part of the stack */ | ||
2668 | #define COMPAT53_LEVELS2 10 /* size of the second part of the stack */ | ||
2669 | |||
2670 | COMPAT53_API void luaL_traceback(lua_State *L, lua_State *L1, | ||
2671 | const char *msg, int level) { | ||
2672 | lua_Debug ar; | ||
2673 | int top = lua_gettop(L); | ||
2674 | int numlevels = compat53_countlevels(L1); | ||
2675 | int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0; | ||
2676 | if (msg) lua_pushfstring(L, "%s\n", msg); | ||
2677 | lua_pushliteral(L, "stack traceback:"); | ||
2678 | while (lua_getstack(L1, level++, &ar)) { | ||
2679 | if (level == mark) { /* too many levels? */ | ||
2680 | lua_pushliteral(L, "\n\t..."); /* add a '...' */ | ||
2681 | level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */ | ||
2682 | } | ||
2683 | else { | ||
2684 | lua_getinfo(L1, "Slnt", &ar); | ||
2685 | lua_pushfstring(L, "\n\t%s:", ar.short_src); | ||
2686 | if (ar.currentline > 0) | ||
2687 | lua_pushfstring(L, "%d:", ar.currentline); | ||
2688 | lua_pushliteral(L, " in "); | ||
2689 | compat53_pushfuncname(L, &ar); | ||
2690 | lua_concat(L, lua_gettop(L) - top); | ||
2691 | } | ||
2692 | } | ||
2693 | lua_concat(L, lua_gettop(L) - top); | ||
2694 | } | ||
2695 | |||
2696 | COMPAT53_API int luaL_fileresult(lua_State *L, int stat, const char *fname) { | ||
2697 | const char *serr = NULL; | ||
2698 | int en = errno; /* calls to Lua API may change this value */ | ||
2699 | char buf[512] = { 0 }; | ||
2700 | if (stat) { | ||
2701 | lua_pushboolean(L, 1); | ||
2702 | return 1; | ||
2703 | } | ||
2704 | else { | ||
2705 | lua_pushnil(L); | ||
2706 | serr = compat53_strerror(en, buf, sizeof(buf)); | ||
2707 | if (fname) | ||
2708 | lua_pushfstring(L, "%s: %s", fname, serr); | ||
2709 | else | ||
2710 | lua_pushstring(L, serr); | ||
2711 | lua_pushnumber(L, (lua_Number)en); | ||
2712 | return 3; | ||
2713 | } | ||
2714 | } | ||
2715 | |||
2716 | static int compat53_checkmode(lua_State *L, const char *mode, const char *modename, int err) { | ||
2717 | if (mode && strchr(mode, modename[0]) == NULL) { | ||
2718 | lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode); | ||
2719 | return err; | ||
2720 | } | ||
2721 | return LUA_OK; | ||
2722 | } | ||
2723 | |||
2724 | typedef struct { | ||
2725 | lua_Reader reader; | ||
2726 | void *ud; | ||
2727 | int has_peeked_data; | ||
2728 | const char *peeked_data; | ||
2729 | size_t peeked_data_size; | ||
2730 | } compat53_reader_data; | ||
2731 | |||
2732 | static const char *compat53_reader(lua_State *L, void *ud, size_t *size) { | ||
2733 | compat53_reader_data *data = (compat53_reader_data *)ud; | ||
2734 | if (data->has_peeked_data) { | ||
2735 | data->has_peeked_data = 0; | ||
2736 | *size = data->peeked_data_size; | ||
2737 | return data->peeked_data; | ||
2738 | } | ||
2739 | else | ||
2740 | return data->reader(L, data->ud, size); | ||
2741 | } | ||
2742 | |||
2743 | COMPAT53_API int lua_load(lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) { | ||
2744 | int status = LUA_OK; | ||
2745 | compat53_reader_data compat53_data = { reader, data, 1, 0, 0 }; | ||
2746 | compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size)); | ||
2747 | if (compat53_data.peeked_data && compat53_data.peeked_data_size && | ||
2748 | compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */ | ||
2749 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); | ||
2750 | else | ||
2751 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); | ||
2752 | if (status != LUA_OK) | ||
2753 | return status; | ||
2754 | /* we need to call the original 5.1 version of lua_load! */ | ||
2755 | #undef lua_load | ||
2756 | return lua_load(L, compat53_reader, &compat53_data, source); | ||
2757 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) | ||
2758 | } | ||
2759 | |||
2760 | typedef struct { | ||
2761 | int n; /* number of pre-read characters */ | ||
2762 | FILE *f; /* file being read */ | ||
2763 | char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ | ||
2764 | } compat53_LoadF; | ||
2765 | |||
2766 | static const char *compat53_getF(lua_State *L, void *ud, size_t *size) { | ||
2767 | compat53_LoadF *lf = (compat53_LoadF *)ud; | ||
2768 | (void)L; /* not used */ | ||
2769 | if (lf->n > 0) { /* are there pre-read characters to be read? */ | ||
2770 | *size = lf->n; /* return them (chars already in buffer) */ | ||
2771 | lf->n = 0; /* no more pre-read characters */ | ||
2772 | } | ||
2773 | else { /* read a block from file */ | ||
2774 | /* 'fread' can return > 0 *and* set the EOF flag. If next call to | ||
2775 | 'compat53_getF' called 'fread', it might still wait for user input. | ||
2776 | The next check avoids this problem. */ | ||
2777 | if (feof(lf->f)) return NULL; | ||
2778 | *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ | ||
2779 | } | ||
2780 | return lf->buff; | ||
2781 | } | ||
2782 | |||
2783 | static int compat53_errfile(lua_State *L, const char *what, int fnameindex) { | ||
2784 | char buf[512] = { 0 }; | ||
2785 | const char *serr = compat53_strerror(errno, buf, sizeof(buf)); | ||
2786 | const char *filename = lua_tostring(L, fnameindex) + 1; | ||
2787 | lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); | ||
2788 | lua_remove(L, fnameindex); | ||
2789 | return LUA_ERRFILE; | ||
2790 | } | ||
2791 | |||
2792 | static int compat53_skipBOM(compat53_LoadF *lf) { | ||
2793 | const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ | ||
2794 | int c; | ||
2795 | lf->n = 0; | ||
2796 | do { | ||
2797 | c = getc(lf->f); | ||
2798 | if (c == EOF || c != *(const unsigned char *)p++) return c; | ||
2799 | lf->buff[lf->n++] = (char)c; /* to be read by the parser */ | ||
2800 | } while (*p != '\0'); | ||
2801 | lf->n = 0; /* prefix matched; discard it */ | ||
2802 | return getc(lf->f); /* return next character */ | ||
2803 | } | ||
2804 | |||
2805 | /* | ||
2806 | ** reads the first character of file 'f' and skips an optional BOM mark | ||
2807 | ** in its beginning plus its first line if it starts with '#'. Returns | ||
2808 | ** true if it skipped the first line. In any case, '*cp' has the | ||
2809 | ** first "valid" character of the file (after the optional BOM and | ||
2810 | ** a first-line comment). | ||
2811 | */ | ||
2812 | static int compat53_skipcomment(compat53_LoadF *lf, int *cp) { | ||
2813 | int c = *cp = compat53_skipBOM(lf); | ||
2814 | if (c == '#') { /* first line is a comment (Unix exec. file)? */ | ||
2815 | do { /* skip first line */ | ||
2816 | c = getc(lf->f); | ||
2817 | } while (c != EOF && c != '\n'); | ||
2818 | *cp = getc(lf->f); /* skip end-of-line, if present */ | ||
2819 | return 1; /* there was a comment */ | ||
2820 | } | ||
2821 | else return 0; /* no comment */ | ||
2822 | } | ||
2823 | |||
2824 | COMPAT53_API int luaL_loadfilex(lua_State *L, const char *filename, const char *mode) { | ||
2825 | compat53_LoadF lf; | ||
2826 | int status, readstatus; | ||
2827 | int c; | ||
2828 | int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ | ||
2829 | if (filename == NULL) { | ||
2830 | lua_pushliteral(L, "=stdin"); | ||
2831 | lf.f = stdin; | ||
2832 | } | ||
2833 | else { | ||
2834 | lua_pushfstring(L, "@%s", filename); | ||
2835 | #if defined(_MSC_VER) | ||
2836 | /* This code is here to stop a deprecation error that stops builds | ||
2837 | * if a certain macro is defined. While normally not caring would | ||
2838 | * be best, some header-only libraries and builds can't afford to | ||
2839 | * dictate this to the user. A quick check shows that fopen_s this | ||
2840 | * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET, | ||
2841 | * possibly even before that so we don't need to do any version | ||
2842 | * number checks, since this has been there since forever. */ | ||
2843 | |||
2844 | /* TO USER: if you want the behavior of typical fopen_s/fopen, | ||
2845 | * which does lock the file on VC++, define the macro used below to 0 */ | ||
2846 | #if COMPAT53_FOPEN_NO_LOCK | ||
2847 | lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ | ||
2848 | if (lf.f == NULL) | ||
2849 | return compat53_errfile(L, "open", fnameindex); | ||
2850 | #else /* use default locking version */ | ||
2851 | if (fopen_s(&lf.f, filename, "r") != 0) | ||
2852 | return compat53_errfile(L, "open", fnameindex); | ||
2853 | #endif /* Locking vs. No-locking fopen variants */ | ||
2854 | #else | ||
2855 | lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ | ||
2856 | if (lf.f == NULL) return compat53_errfile(L, "open", fnameindex); | ||
2857 | #endif | ||
2858 | } | ||
2859 | if (compat53_skipcomment(&lf, &c)) /* read initial portion */ | ||
2860 | lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ | ||
2861 | if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ | ||
2862 | #if defined(_MSC_VER) | ||
2863 | if (freopen_s(&lf.f, filename, "rb", lf.f) != 0) | ||
2864 | return compat53_errfile(L, "reopen", fnameindex); | ||
2865 | #else | ||
2866 | lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ | ||
2867 | if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex); | ||
2868 | #endif | ||
2869 | compat53_skipcomment(&lf, &c); /* re-read initial portion */ | ||
2870 | } | ||
2871 | if (c != EOF) | ||
2872 | lf.buff[lf.n++] = (char)c; /* 'c' is the first character of the stream */ | ||
2873 | status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode); | ||
2874 | readstatus = ferror(lf.f); | ||
2875 | if (filename) fclose(lf.f); /* close file (even in case of errors) */ | ||
2876 | if (readstatus) { | ||
2877 | lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ | ||
2878 | return compat53_errfile(L, "read", fnameindex); | ||
2879 | } | ||
2880 | lua_remove(L, fnameindex); | ||
2881 | return status; | ||
2882 | } | ||
2883 | |||
2884 | COMPAT53_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { | ||
2885 | int status = LUA_OK; | ||
2886 | if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) { | ||
2887 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); | ||
2888 | } | ||
2889 | else { | ||
2890 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); | ||
2891 | } | ||
2892 | if (status != LUA_OK) | ||
2893 | return status; | ||
2894 | return luaL_loadbuffer(L, buff, sz, name); | ||
2895 | } | ||
2896 | |||
2897 | #if !defined(l_inspectstat) && \ | ||
2898 | (defined(unix) || defined(__unix) || defined(__unix__) || \ | ||
2899 | defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \ | ||
2900 | (defined(__APPLE__) && defined(__MACH__))) | ||
2901 | /* some form of unix; check feature macros in unistd.h for details */ | ||
2902 | # include <unistd.h> | ||
2903 | /* check posix version; the relevant include files and macros probably | ||
2904 | * were available before 2001, but I'm not sure */ | ||
2905 | # if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L | ||
2906 | # include <sys/wait.h> | ||
2907 | # define l_inspectstat(stat,what) \ | ||
2908 | if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ | ||
2909 | else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } | ||
2910 | # endif | ||
2911 | #endif | ||
2912 | |||
2913 | /* provide default (no-op) version */ | ||
2914 | #if !defined(l_inspectstat) | ||
2915 | # define l_inspectstat(stat,what) ((void)0) | ||
2916 | #endif | ||
2917 | |||
2918 | COMPAT53_API int luaL_execresult(lua_State *L, int stat) { | ||
2919 | const char *what = "exit"; | ||
2920 | if (stat == -1) | ||
2921 | return luaL_fileresult(L, 0, NULL); | ||
2922 | else { | ||
2923 | l_inspectstat(stat, what); | ||
2924 | if (*what == 'e' && stat == 0) | ||
2925 | lua_pushboolean(L, 1); | ||
2926 | else | ||
2927 | lua_pushnil(L); | ||
2928 | lua_pushstring(L, what); | ||
2929 | lua_pushinteger(L, stat); | ||
2930 | return 3; | ||
2931 | } | ||
2932 | } | ||
2933 | |||
2934 | COMPAT53_API void luaL_buffinit(lua_State *L, luaL_Buffer_53 *B) { | ||
2935 | /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ | ||
2936 | B->b.p = NULL; | ||
2937 | B->b.L = NULL; | ||
2938 | B->b.lvl = 0; | ||
2939 | /* reuse the buffer from the 5.1-style luaL_Buffer though! */ | ||
2940 | B->ptr = B->b.buffer; | ||
2941 | B->capacity = LUAL_BUFFERSIZE; | ||
2942 | B->nelems = 0; | ||
2943 | B->L2 = L; | ||
2944 | } | ||
2945 | |||
2946 | COMPAT53_API char *luaL_prepbuffsize(luaL_Buffer_53 *B, size_t s) { | ||
2947 | if (B->capacity - B->nelems < s) { /* needs to grow */ | ||
2948 | char* newptr = NULL; | ||
2949 | size_t newcap = B->capacity * 2; | ||
2950 | if (newcap - B->nelems < s) | ||
2951 | newcap = B->nelems + s; | ||
2952 | if (newcap < B->capacity) /* overflow */ | ||
2953 | luaL_error(B->L2, "buffer too large"); | ||
2954 | newptr = (char*)lua_newuserdata(B->L2, newcap); | ||
2955 | memcpy(newptr, B->ptr, B->nelems); | ||
2956 | if (B->ptr != B->b.buffer) | ||
2957 | lua_replace(B->L2, -2); /* remove old buffer */ | ||
2958 | B->ptr = newptr; | ||
2959 | B->capacity = newcap; | ||
2960 | } | ||
2961 | return B->ptr + B->nelems; | ||
2962 | } | ||
2963 | |||
2964 | COMPAT53_API void luaL_addlstring(luaL_Buffer_53 *B, const char *s, size_t l) { | ||
2965 | memcpy(luaL_prepbuffsize(B, l), s, l); | ||
2966 | luaL_addsize(B, l); | ||
2967 | } | ||
2968 | |||
2969 | COMPAT53_API void luaL_addvalue(luaL_Buffer_53 *B) { | ||
2970 | size_t len = 0; | ||
2971 | const char *s = lua_tolstring(B->L2, -1, &len); | ||
2972 | if (!s) | ||
2973 | luaL_error(B->L2, "cannot convert value to string"); | ||
2974 | if (B->ptr != B->b.buffer) | ||
2975 | lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ | ||
2976 | luaL_addlstring(B, s, len); | ||
2977 | lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); | ||
2978 | } | ||
2979 | |||
2980 | void luaL_pushresult(luaL_Buffer_53 *B) { | ||
2981 | lua_pushlstring(B->L2, B->ptr, B->nelems); | ||
2982 | if (B->ptr != B->b.buffer) | ||
2983 | lua_replace(B->L2, -2); /* remove userdata buffer */ | ||
2984 | } | ||
2985 | |||
2986 | #endif /* Lua 5.1 */ | ||
2987 | |||
2988 | /* definitions for Lua 5.1 and Lua 5.2 */ | ||
2989 | #if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502 | ||
2990 | |||
2991 | COMPAT53_API int lua_geti(lua_State *L, int index, lua_Integer i) { | ||
2992 | index = lua_absindex(L, index); | ||
2993 | lua_pushinteger(L, i); | ||
2994 | lua_gettable(L, index); | ||
2995 | return lua_type(L, -1); | ||
2996 | } | ||
2997 | |||
2998 | COMPAT53_API int lua_isinteger(lua_State *L, int index) { | ||
2999 | if (lua_type(L, index) == LUA_TNUMBER) { | ||
3000 | lua_Number n = lua_tonumber(L, index); | ||
3001 | lua_Integer i = lua_tointeger(L, index); | ||
3002 | if (i == n) | ||
3003 | return 1; | ||
3004 | } | ||
3005 | return 0; | ||
3006 | } | ||
3007 | |||
3008 | COMPAT53_API lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum) { | ||
3009 | int ok = 0; | ||
3010 | lua_Number n = lua_tonumberx(L, i, &ok); | ||
3011 | if (ok) { | ||
3012 | if (n == (lua_Integer)n) { | ||
3013 | if (isnum) | ||
3014 | *isnum = 1; | ||
3015 | return (lua_Integer)n; | ||
3016 | } | ||
3017 | } | ||
3018 | if (isnum) | ||
3019 | *isnum = 0; | ||
3020 | return 0; | ||
3021 | } | ||
3022 | |||
3023 | static void compat53_reverse(lua_State *L, int a, int b) { | ||
3024 | for (; a < b; ++a, --b) { | ||
3025 | lua_pushvalue(L, a); | ||
3026 | lua_pushvalue(L, b); | ||
3027 | lua_replace(L, a); | ||
3028 | lua_replace(L, b); | ||
3029 | } | ||
3030 | } | ||
3031 | |||
3032 | COMPAT53_API void lua_rotate(lua_State *L, int idx, int n) { | ||
3033 | int n_elems = 0; | ||
3034 | idx = lua_absindex(L, idx); | ||
3035 | n_elems = lua_gettop(L) - idx + 1; | ||
3036 | if (n < 0) | ||
3037 | n += n_elems; | ||
3038 | if (n > 0 && n < n_elems) { | ||
3039 | luaL_checkstack(L, 2, "not enough stack slots available"); | ||
3040 | n = n_elems - n; | ||
3041 | compat53_reverse(L, idx, idx + n - 1); | ||
3042 | compat53_reverse(L, idx + n, idx + n_elems - 1); | ||
3043 | compat53_reverse(L, idx, idx + n_elems - 1); | ||
3044 | } | ||
3045 | } | ||
3046 | |||
3047 | COMPAT53_API void lua_seti(lua_State *L, int index, lua_Integer i) { | ||
3048 | luaL_checkstack(L, 1, "not enough stack slots available"); | ||
3049 | index = lua_absindex(L, index); | ||
3050 | lua_pushinteger(L, i); | ||
3051 | lua_insert(L, -2); | ||
3052 | lua_settable(L, index); | ||
3053 | } | ||
3054 | |||
3055 | #if !defined(lua_str2number) | ||
3056 | # define lua_str2number(s, p) strtod((s), (p)) | ||
3057 | #endif | ||
3058 | |||
3059 | COMPAT53_API size_t lua_stringtonumber(lua_State *L, const char *s) { | ||
3060 | char* endptr; | ||
3061 | lua_Number n = lua_str2number(s, &endptr); | ||
3062 | if (endptr != s) { | ||
3063 | while (*endptr != '\0' && isspace((unsigned char)*endptr)) | ||
3064 | ++endptr; | ||
3065 | if (*endptr == '\0') { | ||
3066 | lua_pushnumber(L, n); | ||
3067 | return endptr - s + 1; | ||
3068 | } | ||
3069 | } | ||
3070 | return 0; | ||
3071 | } | ||
3072 | |||
3073 | COMPAT53_API const char *luaL_tolstring(lua_State *L, int idx, size_t *len) { | ||
3074 | if (!luaL_callmeta(L, idx, "__tostring")) { | ||
3075 | int t = lua_type(L, idx), tt = 0; | ||
3076 | char const* name = NULL; | ||
3077 | switch (t) { | ||
3078 | case LUA_TNIL: | ||
3079 | lua_pushliteral(L, "nil"); | ||
3080 | break; | ||
3081 | case LUA_TSTRING: | ||
3082 | case LUA_TNUMBER: | ||
3083 | lua_pushvalue(L, idx); | ||
3084 | break; | ||
3085 | case LUA_TBOOLEAN: | ||
3086 | if (lua_toboolean(L, idx)) | ||
3087 | lua_pushliteral(L, "true"); | ||
3088 | else | ||
3089 | lua_pushliteral(L, "false"); | ||
3090 | break; | ||
3091 | default: | ||
3092 | tt = luaL_getmetafield(L, idx, "__name"); | ||
3093 | name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t); | ||
3094 | lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx)); | ||
3095 | if (tt != LUA_TNIL) | ||
3096 | lua_replace(L, -2); | ||
3097 | break; | ||
3098 | } | ||
3099 | } | ||
3100 | else { | ||
3101 | if (!lua_isstring(L, -1)) | ||
3102 | luaL_error(L, "'__tostring' must return a string"); | ||
3103 | } | ||
3104 | return lua_tolstring(L, -1, len); | ||
3105 | } | ||
3106 | |||
3107 | COMPAT53_API void luaL_requiref(lua_State *L, const char *modname, | ||
3108 | lua_CFunction openf, int glb) { | ||
3109 | luaL_checkstack(L, 3, "not enough stack slots available"); | ||
3110 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); | ||
3111 | if (lua_getfield(L, -1, modname) == LUA_TNIL) { | ||
3112 | lua_pop(L, 1); | ||
3113 | lua_pushcfunction(L, openf); | ||
3114 | lua_pushstring(L, modname); | ||
3115 | lua_call(L, 1, 1); | ||
3116 | lua_pushvalue(L, -1); | ||
3117 | lua_setfield(L, -3, modname); | ||
3118 | } | ||
3119 | if (glb) { | ||
3120 | lua_pushvalue(L, -1); | ||
3121 | lua_setglobal(L, modname); | ||
3122 | } | ||
3123 | lua_replace(L, -2); | ||
3124 | } | ||
3125 | |||
3126 | #endif /* Lua 5.1 and 5.2 */ | ||
3127 | |||
3128 | #endif /* KEPLER_PROJECT_COMPAT53_C_ */ | ||
3129 | |||
3130 | /********************************************************************* | ||
3131 | * This file contains parts of Lua 5.2's and Lua 5.3's source code: | ||
3132 | * | ||
3133 | * Copyright (C) 1994-2014 Lua.org, PUC-Rio. | ||
3134 | * | ||
3135 | * Permission is hereby granted, free of charge, to any person obtaining | ||
3136 | * a copy of this software and associated documentation files (the | ||
3137 | * "Software"), to deal in the Software without restriction, including | ||
3138 | * without limitation the rights to use, copy, modify, merge, publish, | ||
3139 | * distribute, sublicense, and/or sell copies of the Software, and to | ||
3140 | * permit persons to whom the Software is furnished to do so, subject to | ||
3141 | * the following conditions: | ||
3142 | * | ||
3143 | * The above copyright notice and this permission notice shall be | ||
3144 | * included in all copies or substantial portions of the Software. | ||
3145 | * | ||
3146 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
3147 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
3148 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
3149 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
3150 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
3151 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
3152 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
3153 | *********************************************************************/ | ||
3154 | |||
3155 | // end of sol/compatibility/compat-5.3.c | ||
3156 | |||
3157 | #endif | ||
3158 | |||
3159 | #endif /* KEPLER_PROJECT_COMPAT53_H_ */ | ||
3160 | |||
3161 | // end of sol/compatibility/compat-5.3.h | ||
3162 | |||
3163 | |||
3164 | #endif // SOL_NO_COMPAT | ||
3165 | |||
3166 | // end of sol/compatibility.hpp | ||
3167 | |||
3168 | // beginning of sol/in_place.hpp | ||
3169 | |||
3170 | #include <utility> | ||
3171 | |||
3172 | namespace sol { | ||
3173 | |||
3174 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
3175 | using in_place_t = std::in_place_t; | ||
3176 | constexpr std::in_place_t in_place{}; | ||
3177 | constexpr std::in_place_t in_place_of{}; | ||
3178 | |||
3179 | template <typename T> | ||
3180 | using in_place_type_t = std::in_place_type_t<T>; | ||
3181 | template <typename T> | ||
3182 | constexpr std::in_place_type_t<T> in_place_type{}; | ||
3183 | |||
3184 | template <size_t I> | ||
3185 | using in_place_index_t = std::in_place_index_t<I>; | ||
3186 | template <size_t I> | ||
3187 | constexpr in_place_index_t<I> in_place_index{}; | ||
3188 | #else | ||
3189 | namespace detail { | ||
3190 | struct in_place_of_tag {}; | ||
3191 | template <std::size_t I> | ||
3192 | struct in_place_of_i {}; | ||
3193 | template <typename T> | ||
3194 | struct in_place_of_t {}; | ||
3195 | } // namespace detail | ||
3196 | |||
3197 | struct in_place_tag { | ||
3198 | constexpr in_place_tag() = default; | ||
3199 | }; | ||
3200 | |||
3201 | constexpr inline in_place_tag in_place(detail::in_place_of_tag) { | ||
3202 | return in_place_tag(); | ||
3203 | } | ||
3204 | template <typename T> | ||
3205 | constexpr inline in_place_tag in_place(detail::in_place_of_t<T>) { | ||
3206 | return in_place_tag(); | ||
3207 | } | ||
3208 | template <std::size_t I> | ||
3209 | constexpr inline in_place_tag in_place(detail::in_place_of_i<I>) { | ||
3210 | return in_place_tag(); | ||
3211 | } | ||
3212 | |||
3213 | constexpr inline in_place_tag in_place_of(detail::in_place_of_tag) { | ||
3214 | return in_place_tag(); | ||
3215 | } | ||
3216 | template <typename T> | ||
3217 | constexpr inline in_place_tag in_place_type(detail::in_place_of_t<T>) { | ||
3218 | return in_place_tag(); | ||
3219 | } | ||
3220 | template <std::size_t I> | ||
3221 | constexpr inline in_place_tag in_place_index(detail::in_place_of_i<I>) { | ||
3222 | return in_place_tag(); | ||
3223 | } | ||
3224 | |||
3225 | using in_place_t = in_place_tag (&)(detail::in_place_of_tag); | ||
3226 | template <typename T> | ||
3227 | using in_place_type_t = in_place_tag (&)(detail::in_place_of_t<T>); | ||
3228 | template <std::size_t I> | ||
3229 | using in_place_index_t = in_place_tag (&)(detail::in_place_of_i<I>); | ||
3230 | #endif | ||
3231 | |||
3232 | } // namespace sol | ||
3233 | |||
3234 | // end of sol/in_place.hpp | ||
3235 | |||
3236 | #if defined(SOL_USE_BOOST) && SOL_USE_BOOST | ||
3237 | #include <boost/optional.hpp> | ||
3238 | #else | ||
3239 | // beginning of sol/optional_implementation.hpp | ||
3240 | |||
3241 | #include <initializer_list> | ||
3242 | #include <cassert> | ||
3243 | #if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS | ||
3244 | #include <cstdlib> | ||
3245 | #endif // Exceptions | ||
3246 | |||
3247 | #define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false | ||
3248 | |||
3249 | #if defined __GNUC__ // NOTE: GNUC is also defined for Clang | ||
3250 | #if (__GNUC__ >= 5) | ||
3251 | #define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ | ||
3252 | #define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ | ||
3253 | #elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) | ||
3254 | #define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ | ||
3255 | #elif (__GNUC__ > 4) | ||
3256 | #define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ | ||
3257 | #endif | ||
3258 | # | ||
3259 | #if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) | ||
3260 | #define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ | ||
3261 | #elif (__GNUC__ > 4) | ||
3262 | #define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ | ||
3263 | #endif | ||
3264 | # | ||
3265 | #if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) | ||
3266 | #define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ | ||
3267 | #elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) | ||
3268 | #define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ | ||
3269 | #elif (__GNUC__ > 4) | ||
3270 | #define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ | ||
3271 | #endif | ||
3272 | #endif | ||
3273 | # | ||
3274 | #if defined __clang_major__ | ||
3275 | #if (__clang_major__ == 3 && __clang_minor__ >= 5) | ||
3276 | #define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ | ||
3277 | #elif (__clang_major__ > 3) | ||
3278 | #define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ | ||
3279 | #endif | ||
3280 | #if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ | ||
3281 | #define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ | ||
3282 | #elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) | ||
3283 | #define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ | ||
3284 | #endif | ||
3285 | #endif | ||
3286 | # | ||
3287 | #if defined _MSC_VER | ||
3288 | #if (_MSC_VER >= 1900) | ||
3289 | #define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ | ||
3290 | #endif | ||
3291 | #endif | ||
3292 | |||
3293 | #if defined __clang__ | ||
3294 | #if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) | ||
3295 | #define OPTIONAL_HAS_THIS_RVALUE_REFS 1 | ||
3296 | #else | ||
3297 | #define OPTIONAL_HAS_THIS_RVALUE_REFS 0 | ||
3298 | #endif | ||
3299 | #elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ | ||
3300 | #define OPTIONAL_HAS_THIS_RVALUE_REFS 1 | ||
3301 | #elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ | ||
3302 | #define OPTIONAL_HAS_THIS_RVALUE_REFS 1 | ||
3303 | #else | ||
3304 | #define OPTIONAL_HAS_THIS_RVALUE_REFS 0 | ||
3305 | #endif | ||
3306 | |||
3307 | #if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ | ||
3308 | #define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 | ||
3309 | #define OPTIONAL_CONSTEXPR_INIT_LIST constexpr | ||
3310 | #else | ||
3311 | #define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 | ||
3312 | #define OPTIONAL_CONSTEXPR_INIT_LIST | ||
3313 | #endif | ||
3314 | |||
3315 | #if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || (defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)) | ||
3316 | #define OPTIONAL_HAS_MOVE_ACCESSORS 1 | ||
3317 | #else | ||
3318 | #define OPTIONAL_HAS_MOVE_ACCESSORS 0 | ||
3319 | #endif | ||
3320 | |||
3321 | #// In C++11 constexpr implies const, so we need to make non-const members also non-constexpr | ||
3322 | #if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || ((defined __cplusplus) && (__cplusplus == 201103L)) | ||
3323 | #define OPTIONAL_MUTABLE_CONSTEXPR | ||
3324 | #else | ||
3325 | #define OPTIONAL_MUTABLE_CONSTEXPR constexpr | ||
3326 | #endif | ||
3327 | |||
3328 | #if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ | ||
3329 | #pragma warning(push) | ||
3330 | #pragma warning(disable : 4814) | ||
3331 | #endif | ||
3332 | |||
3333 | namespace sol { | ||
3334 | |||
3335 | // BEGIN workaround for missing is_trivially_destructible | ||
3336 | #if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ | ||
3337 | // leave it: it is already there | ||
3338 | #elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ | ||
3339 | // leave it: it is already there | ||
3340 | #elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ | ||
3341 | // leave it: it is already there | ||
3342 | #elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS | ||
3343 | // leave it: the user doesn't want it | ||
3344 | #else | ||
3345 | template <typename T> | ||
3346 | using is_trivially_destructible = ::std::has_trivial_destructor<T>; | ||
3347 | #endif | ||
3348 | // END workaround for missing is_trivially_destructible | ||
3349 | |||
3350 | #if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) | ||
3351 | // leave it; our metafunctions are already defined. | ||
3352 | #elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ | ||
3353 | // leave it; our metafunctions are already defined. | ||
3354 | #elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ | ||
3355 | // leave it: it is already there | ||
3356 | #elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS | ||
3357 | // leave it: the user doesn't want it | ||
3358 | #else | ||
3359 | |||
3360 | // workaround for missing traits in GCC and CLANG | ||
3361 | template <class T> | ||
3362 | struct is_nothrow_move_constructible { | ||
3363 | static constexprbool value = ::std::is_nothrow_constructible<T, T&&>::value; | ||
3364 | }; | ||
3365 | |||
3366 | template <class T, class U> | ||
3367 | struct is_assignable { | ||
3368 | template <class X, class Y> | ||
3369 | static constexprbool has_assign(...) { | ||
3370 | return false; | ||
3371 | } | ||
3372 | |||
3373 | template <class X, class Y, size_t S = sizeof((::std::declval<X>() = ::std::declval<Y>(), true))> | ||
3374 | // the comma operator is necessary for the cases where operator= returns void | ||
3375 | static constexprbool has_assign(bool) { | ||
3376 | return true; | ||
3377 | } | ||
3378 | |||
3379 | static constexprbool value = has_assign<T, U>(true); | ||
3380 | }; | ||
3381 | |||
3382 | template <class T> | ||
3383 | struct is_nothrow_move_assignable { | ||
3384 | template <class X, bool has_any_move_assign> | ||
3385 | struct has_nothrow_move_assign { | ||
3386 | static constexprbool value = false; | ||
3387 | }; | ||
3388 | |||
3389 | template <class X> | ||
3390 | struct has_nothrow_move_assign<X, true> { | ||
3391 | static constexprbool value = noexcept(::std::declval<X&>() = ::std::declval<X&&>()); | ||
3392 | }; | ||
3393 | |||
3394 | static constexprbool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value; | ||
3395 | }; | ||
3396 | // end workaround | ||
3397 | |||
3398 | #endif | ||
3399 | |||
3400 | // 20.5.4, optional for object types | ||
3401 | template <class T> | ||
3402 | class optional; | ||
3403 | |||
3404 | // 20.5.5, optional for lvalue reference types | ||
3405 | template <class T> | ||
3406 | class optional<T&>; | ||
3407 | |||
3408 | // workaround: std utility functions aren't constexpr yet | ||
3409 | template <class T> | ||
3410 | inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type& t) noexcept { | ||
3411 | return static_cast<T&&>(t); | ||
3412 | } | ||
3413 | |||
3414 | template <class T> | ||
3415 | inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type&& t) noexcept { | ||
3416 | static_assert(!::std::is_lvalue_reference<T>::value, "!!"); | ||
3417 | return static_cast<T&&>(t); | ||
3418 | } | ||
3419 | |||
3420 | template <class T> | ||
3421 | inline constexpr typename ::std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept { | ||
3422 | return static_cast<typename ::std::remove_reference<T>::type&&>(t); | ||
3423 | } | ||
3424 | |||
3425 | #if defined NDEBUG | ||
3426 | #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) | ||
3427 | #else | ||
3428 | #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([] { assert(!#CHECK); }(), (EXPR))) | ||
3429 | #endif | ||
3430 | |||
3431 | namespace detail_ { | ||
3432 | |||
3433 | // static_addressof: a constexpr version of addressof | ||
3434 | template <typename T> | ||
3435 | struct has_overloaded_addressof { | ||
3436 | template <class X> | ||
3437 | static constexpr bool has_overload(...) { | ||
3438 | return false; | ||
3439 | } | ||
3440 | |||
3441 | template <class X, size_t S = sizeof(::std::declval<X&>().operator&())> | ||
3442 | static constexpr bool has_overload(bool) { | ||
3443 | return true; | ||
3444 | } | ||
3445 | |||
3446 | static constexpr bool value = has_overload<T>(true); | ||
3447 | }; | ||
3448 | |||
3449 | template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)> | ||
3450 | constexpr T* static_addressof(T& ref) { | ||
3451 | return &ref; | ||
3452 | } | ||
3453 | |||
3454 | template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)> | ||
3455 | T* static_addressof(T& ref) { | ||
3456 | return ::std::addressof(ref); | ||
3457 | } | ||
3458 | |||
3459 | // the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A | ||
3460 | template <class U> | ||
3461 | constexpr U convert(U v) { | ||
3462 | return v; | ||
3463 | } | ||
3464 | |||
3465 | } // namespace detail_ | ||
3466 | |||
3467 | constexpr struct trivial_init_t { | ||
3468 | } trivial_init{}; | ||
3469 | |||
3470 | // 20.5.7, Disengaged state indicator | ||
3471 | struct nullopt_t { | ||
3472 | struct init {}; | ||
3473 | constexpr explicit nullopt_t(init) { | ||
3474 | } | ||
3475 | }; | ||
3476 | constexpr nullopt_t nullopt{nullopt_t::init()}; | ||
3477 | |||
3478 | // 20.5.8, class bad_optional_access | ||
3479 | class bad_optional_access : public ::std::logic_error { | ||
3480 | public: | ||
3481 | explicit bad_optional_access(const ::std::string& what_arg) | ||
3482 | : ::std::logic_error{what_arg} { | ||
3483 | } | ||
3484 | explicit bad_optional_access(const char* what_arg) | ||
3485 | : ::std::logic_error{what_arg} { | ||
3486 | } | ||
3487 | }; | ||
3488 | |||
3489 | template <class T> | ||
3490 | struct alignas(T) optional_base { | ||
3491 | char storage_[sizeof(T)]; | ||
3492 | bool init_; | ||
3493 | |||
3494 | constexpr optional_base() noexcept | ||
3495 | : storage_(), init_(false){}; | ||
3496 | |||
3497 | explicit optional_base(const T& v) | ||
3498 | : storage_(), init_(true) { | ||
3499 | new (&storage()) T(v); | ||
3500 | } | ||
3501 | |||
3502 | explicit optional_base(T&& v) | ||
3503 | : storage_(), init_(true) { | ||
3504 | new (&storage()) T(constexpr_move(v)); | ||
3505 | } | ||
3506 | |||
3507 | template <class... Args> | ||
3508 | explicit optional_base(in_place_t, Args&&... args) | ||
3509 | : init_(true), storage_() { | ||
3510 | new (&storage()) T(constexpr_forward<Args>(args)...); | ||
3511 | } | ||
3512 | |||
3513 | template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> | ||
3514 | explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) | ||
3515 | : init_(true), storage_() { | ||
3516 | new (&storage()) T(il, constexpr_forward<Args>(args)...); | ||
3517 | } | ||
3518 | #if defined __GNUC__ | ||
3519 | #pragma GCC diagnostic push | ||
3520 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" | ||
3521 | #endif | ||
3522 | T& storage() { | ||
3523 | return *reinterpret_cast<T*>(&storage_[0]); | ||
3524 | } | ||
3525 | |||
3526 | constexpr const T& storage() const { | ||
3527 | return *reinterpret_cast<T const*>(&storage_[0]); | ||
3528 | } | ||
3529 | #if defined __GNUC__ | ||
3530 | #pragma GCC diagnostic pop | ||
3531 | #endif | ||
3532 | |||
3533 | ~optional_base() { | ||
3534 | if (init_) { | ||
3535 | storage().T::~T(); | ||
3536 | } | ||
3537 | } | ||
3538 | }; | ||
3539 | |||
3540 | #if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ | ||
3541 | // Sorry, GCC 4.x; you're just a piece of shit | ||
3542 | template <typename T> | ||
3543 | using constexpr_optional_base = optional_base<T>; | ||
3544 | #else | ||
3545 | template <class T> | ||
3546 | struct alignas(T) constexpr_optional_base { | ||
3547 | char storage_[sizeof(T)]; | ||
3548 | bool init_; | ||
3549 | constexpr constexpr_optional_base() noexcept | ||
3550 | : storage_(), init_(false) { | ||
3551 | } | ||
3552 | |||
3553 | explicit constexpr constexpr_optional_base(const T& v) | ||
3554 | : storage_(), init_(true) { | ||
3555 | new (&storage()) T(v); | ||
3556 | } | ||
3557 | |||
3558 | explicit constexpr constexpr_optional_base(T&& v) | ||
3559 | : storage_(), init_(true) { | ||
3560 | new (&storage()) T(constexpr_move(v)); | ||
3561 | } | ||
3562 | |||
3563 | template <class... Args> | ||
3564 | explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) | ||
3565 | : init_(true), storage_() { | ||
3566 | new (&storage()) T(constexpr_forward<Args>(args)...); | ||
3567 | } | ||
3568 | |||
3569 | template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> | ||
3570 | OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) | ||
3571 | : init_(true), storage_() { | ||
3572 | new (&storage()) T(il, constexpr_forward<Args>(args)...); | ||
3573 | } | ||
3574 | |||
3575 | #if defined __GNUC__ | ||
3576 | #pragma GCC diagnostic push | ||
3577 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" | ||
3578 | #endif | ||
3579 | T& storage() { | ||
3580 | return (*reinterpret_cast<T*>(&storage_[0])); | ||
3581 | } | ||
3582 | |||
3583 | constexpr const T& storage() const { | ||
3584 | return (*reinterpret_cast<T const*>(&storage_[0])); | ||
3585 | } | ||
3586 | #if defined __GNUC__ | ||
3587 | #pragma GCC diagnostic pop | ||
3588 | #endif | ||
3589 | |||
3590 | ~constexpr_optional_base() = default; | ||
3591 | }; | ||
3592 | #endif | ||
3593 | |||
3594 | template <class T> | ||
3595 | using OptionalBase = typename ::std::conditional< | ||
3596 | ::std::is_trivially_destructible<T>::value, | ||
3597 | constexpr_optional_base<typename ::std::remove_const<T>::type>, | ||
3598 | optional_base<typename ::std::remove_const<T>::type>>::type; | ||
3599 | |||
3600 | template <class T> | ||
3601 | class optional : private OptionalBase<T> { | ||
3602 | static_assert(!::std::is_same<typename ::std::decay<T>::type, nullopt_t>::value, "bad T"); | ||
3603 | static_assert(!::std::is_same<typename ::std::decay<T>::type, in_place_t>::value, "bad T"); | ||
3604 | |||
3605 | constexpr bool initialized() const noexcept { | ||
3606 | return OptionalBase<T>::init_; | ||
3607 | } | ||
3608 | typename ::std::remove_const<T>::type* dataptr() { | ||
3609 | return ::std::addressof(OptionalBase<T>::storage()); | ||
3610 | } | ||
3611 | constexpr const T* dataptr() const { | ||
3612 | return detail_::static_addressof(OptionalBase<T>::storage()); | ||
3613 | } | ||
3614 | |||
3615 | #if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 | ||
3616 | constexpr const T& contained_val() const& { | ||
3617 | return OptionalBase<T>::storage(); | ||
3618 | } | ||
3619 | #if OPTIONAL_HAS_MOVE_ACCESSORS == 1 | ||
3620 | OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { | ||
3621 | return ::std::move(OptionalBase<T>::storage()); | ||
3622 | } | ||
3623 | OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { | ||
3624 | return OptionalBase<T>::storage(); | ||
3625 | } | ||
3626 | #else | ||
3627 | T& contained_val() & { | ||
3628 | return OptionalBase<T>::storage(); | ||
3629 | } | ||
3630 | T&& contained_val() && { | ||
3631 | return ::std::move(OptionalBase<T>::storage()); | ||
3632 | } | ||
3633 | #endif | ||
3634 | #else | ||
3635 | constexpr const T& contained_val() const { | ||
3636 | return OptionalBase<T>::storage(); | ||
3637 | } | ||
3638 | T& contained_val() { | ||
3639 | return OptionalBase<T>::storage(); | ||
3640 | } | ||
3641 | #endif | ||
3642 | |||
3643 | void clear() noexcept { | ||
3644 | if (initialized()) | ||
3645 | dataptr()->T::~T(); | ||
3646 | OptionalBase<T>::init_ = false; | ||
3647 | } | ||
3648 | |||
3649 | template <class... Args> | ||
3650 | void initialize(Args&&... args) noexcept(noexcept(T(::std::forward<Args>(args)...))) { | ||
3651 | assert(!OptionalBase<T>::init_); | ||
3652 | ::new (static_cast<void*>(dataptr())) T(::std::forward<Args>(args)...); | ||
3653 | OptionalBase<T>::init_ = true; | ||
3654 | } | ||
3655 | |||
3656 | template <class U, class... Args> | ||
3657 | void initialize(::std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, ::std::forward<Args>(args)...))) { | ||
3658 | assert(!OptionalBase<T>::init_); | ||
3659 | ::new (static_cast<void*>(dataptr())) T(il, ::std::forward<Args>(args)...); | ||
3660 | OptionalBase<T>::init_ = true; | ||
3661 | } | ||
3662 | |||
3663 | public: | ||
3664 | typedef T value_type; | ||
3665 | |||
3666 | // 20.5.5.1, constructors | ||
3667 | constexpr optional() noexcept | ||
3668 | : OptionalBase<T>(){}; | ||
3669 | constexpr optional(nullopt_t) noexcept | ||
3670 | : OptionalBase<T>(){}; | ||
3671 | |||
3672 | optional(const optional& rhs) | ||
3673 | : OptionalBase<T>() { | ||
3674 | if (rhs.initialized()) { | ||
3675 | ::new (static_cast<void*>(dataptr())) T(*rhs); | ||
3676 | OptionalBase<T>::init_ = true; | ||
3677 | } | ||
3678 | } | ||
3679 | |||
3680 | optional(const optional<T&>& rhs) | ||
3681 | : optional() { | ||
3682 | if (rhs) { | ||
3683 | ::new (static_cast<void*>(dataptr())) T(*rhs); | ||
3684 | OptionalBase<T>::init_ = true; | ||
3685 | } | ||
3686 | } | ||
3687 | |||
3688 | optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value) | ||
3689 | : OptionalBase<T>() { | ||
3690 | if (rhs.initialized()) { | ||
3691 | ::new (static_cast<void*>(dataptr())) T(::std::move(*rhs)); | ||
3692 | OptionalBase<T>::init_ = true; | ||
3693 | } | ||
3694 | } | ||
3695 | |||
3696 | constexpr optional(const T& v) | ||
3697 | : OptionalBase<T>(v) { | ||
3698 | } | ||
3699 | |||
3700 | constexpr optional(T&& v) | ||
3701 | : OptionalBase<T>(constexpr_move(v)) { | ||
3702 | } | ||
3703 | |||
3704 | template <class... Args> | ||
3705 | explicit constexpr optional(in_place_t, Args&&... args) | ||
3706 | : OptionalBase<T>(in_place, constexpr_forward<Args>(args)...) { | ||
3707 | } | ||
3708 | |||
3709 | template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> | ||
3710 | OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list<U> il, Args&&... args) | ||
3711 | : OptionalBase<T>(in_place, il, constexpr_forward<Args>(args)...) { | ||
3712 | } | ||
3713 | |||
3714 | // 20.5.4.2, Destructor | ||
3715 | ~optional() = default; | ||
3716 | |||
3717 | // 20.5.4.3, assignment | ||
3718 | optional& operator=(nullopt_t) noexcept { | ||
3719 | clear(); | ||
3720 | return *this; | ||
3721 | } | ||
3722 | |||
3723 | optional& operator=(const optional& rhs) { | ||
3724 | if (initialized() == true && rhs.initialized() == false) | ||
3725 | clear(); | ||
3726 | else if (initialized() == false && rhs.initialized() == true) | ||
3727 | initialize(*rhs); | ||
3728 | else if (initialized() == true && rhs.initialized() == true) | ||
3729 | contained_val() = *rhs; | ||
3730 | return *this; | ||
3731 | } | ||
3732 | |||
3733 | optional& operator=(optional&& rhs) noexcept(::std::is_nothrow_move_assignable<T>::value&& ::std::is_nothrow_move_constructible<T>::value) { | ||
3734 | if (initialized() == true && rhs.initialized() == false) | ||
3735 | clear(); | ||
3736 | else if (initialized() == false && rhs.initialized() == true) | ||
3737 | initialize(::std::move(*rhs)); | ||
3738 | else if (initialized() == true && rhs.initialized() == true) | ||
3739 | contained_val() = ::std::move(*rhs); | ||
3740 | return *this; | ||
3741 | } | ||
3742 | |||
3743 | template <class U> | ||
3744 | auto operator=(U&& v) | ||
3745 | -> typename ::std::enable_if< | ||
3746 | ::std::is_same<typename ::std::decay<U>::type, T>::value, | ||
3747 | optional&>::type { | ||
3748 | if (initialized()) { | ||
3749 | contained_val() = ::std::forward<U>(v); | ||
3750 | } | ||
3751 | else { | ||
3752 | initialize(::std::forward<U>(v)); | ||
3753 | } | ||
3754 | return *this; | ||
3755 | } | ||
3756 | |||
3757 | template <class... Args> | ||
3758 | void emplace(Args&&... args) { | ||
3759 | clear(); | ||
3760 | initialize(::std::forward<Args>(args)...); | ||
3761 | } | ||
3762 | |||
3763 | template <class U, class... Args> | ||
3764 | void emplace(::std::initializer_list<U> il, Args&&... args) { | ||
3765 | clear(); | ||
3766 | initialize<U, Args...>(il, ::std::forward<Args>(args)...); | ||
3767 | } | ||
3768 | |||
3769 | // 20.5.4.4, Swap | ||
3770 | void swap(optional<T>& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value&& noexcept(swap(::std::declval<T&>(), ::std::declval<T&>()))) { | ||
3771 | if (initialized() == true && rhs.initialized() == false) { | ||
3772 | rhs.initialize(::std::move(**this)); | ||
3773 | clear(); | ||
3774 | } | ||
3775 | else if (initialized() == false && rhs.initialized() == true) { | ||
3776 | initialize(::std::move(*rhs)); | ||
3777 | rhs.clear(); | ||
3778 | } | ||
3779 | else if (initialized() == true && rhs.initialized() == true) { | ||
3780 | using ::std::swap; | ||
3781 | swap(**this, *rhs); | ||
3782 | } | ||
3783 | } | ||
3784 | |||
3785 | // 20.5.4.5, Observers | ||
3786 | |||
3787 | explicit constexpr operator bool() const noexcept { | ||
3788 | return initialized(); | ||
3789 | } | ||
3790 | |||
3791 | constexpr T const* operator->() const { | ||
3792 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); | ||
3793 | } | ||
3794 | |||
3795 | #if OPTIONAL_HAS_MOVE_ACCESSORS == 1 | ||
3796 | |||
3797 | OPTIONAL_MUTABLE_CONSTEXPR T* operator->() { | ||
3798 | assert(initialized()); | ||
3799 | return dataptr(); | ||
3800 | } | ||
3801 | |||
3802 | constexpr T const& operator*() const& { | ||
3803 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); | ||
3804 | } | ||
3805 | |||
3806 | OPTIONAL_MUTABLE_CONSTEXPR T& operator*() & { | ||
3807 | assert(initialized()); | ||
3808 | return contained_val(); | ||
3809 | } | ||
3810 | |||
3811 | OPTIONAL_MUTABLE_CONSTEXPR T&& operator*() && { | ||
3812 | assert(initialized()); | ||
3813 | return constexpr_move(contained_val()); | ||
3814 | } | ||
3815 | |||
3816 | constexpr T const& value() const& { | ||
3817 | return initialized() ? contained_val() | ||
3818 | #ifdef SOL_NO_EXCEPTIONS | ||
3819 | // we can't abort here | ||
3820 | // because there's no constexpr abort | ||
3821 | : *static_cast<T*>(nullptr); | ||
3822 | #else | ||
3823 | : (throw bad_optional_access("bad optional access"), contained_val()); | ||
3824 | #endif | ||
3825 | } | ||
3826 | |||
3827 | OPTIONAL_MUTABLE_CONSTEXPR T& value() & { | ||
3828 | return initialized() ? contained_val() | ||
3829 | #ifdef SOL_NO_EXCEPTIONS | ||
3830 | : *static_cast<T*>(nullptr); | ||
3831 | #else | ||
3832 | : (throw bad_optional_access("bad optional access"), contained_val()); | ||
3833 | #endif | ||
3834 | } | ||
3835 | |||
3836 | OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { | ||
3837 | return initialized() ? contained_val() | ||
3838 | #ifdef SOL_NO_EXCEPTIONS | ||
3839 | // we can't abort here | ||
3840 | // because there's no constexpr abort | ||
3841 | : std::move(*static_cast<T*>(nullptr)); | ||
3842 | #else | ||
3843 | : (throw bad_optional_access("bad optional access"), contained_val()); | ||
3844 | #endif | ||
3845 | } | ||
3846 | |||
3847 | #else | ||
3848 | |||
3849 | T* operator->() { | ||
3850 | assert(initialized()); | ||
3851 | return dataptr(); | ||
3852 | } | ||
3853 | |||
3854 | constexpr T const& operator*() const { | ||
3855 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); | ||
3856 | } | ||
3857 | |||
3858 | T& operator*() { | ||
3859 | assert(initialized()); | ||
3860 | return contained_val(); | ||
3861 | } | ||
3862 | |||
3863 | constexpr T const& value() const { | ||
3864 | return initialized() ? contained_val() | ||
3865 | #ifdef SOL_NO_EXCEPTIONS | ||
3866 | // we can't abort here | ||
3867 | // because there's no constexpr abort | ||
3868 | : *static_cast<T*>(nullptr); | ||
3869 | #else | ||
3870 | : (throw bad_optional_access("bad optional access"), contained_val()); | ||
3871 | #endif | ||
3872 | } | ||
3873 | |||
3874 | T& value() { | ||
3875 | return initialized() ? contained_val() | ||
3876 | #ifdef SOL_NO_EXCEPTIONS | ||
3877 | // we can abort here | ||
3878 | // but the others are constexpr, so we can't... | ||
3879 | : (std::abort(), *static_cast<T*>(nullptr)); | ||
3880 | #else | ||
3881 | : (throw bad_optional_access("bad optional access"), contained_val()); | ||
3882 | #endif | ||
3883 | } | ||
3884 | |||
3885 | #endif | ||
3886 | |||
3887 | #if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 | ||
3888 | |||
3889 | template <class V> | ||
3890 | constexpr T value_or(V&& v) const& { | ||
3891 | return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); | ||
3892 | } | ||
3893 | |||
3894 | #if OPTIONAL_HAS_MOVE_ACCESSORS == 1 | ||
3895 | |||
3896 | template <class V> | ||
3897 | OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && { | ||
3898 | return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); | ||
3899 | } | ||
3900 | |||
3901 | #else | ||
3902 | |||
3903 | template <class V> | ||
3904 | T value_or(V&& v) && { | ||
3905 | return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); | ||
3906 | } | ||
3907 | |||
3908 | #endif | ||
3909 | |||
3910 | #else | ||
3911 | |||
3912 | template <class V> | ||
3913 | constexpr T value_or(V&& v) const { | ||
3914 | return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); | ||
3915 | } | ||
3916 | |||
3917 | #endif | ||
3918 | }; | ||
3919 | |||
3920 | template <class T> | ||
3921 | class optional<T&> { | ||
3922 | static_assert(!::std::is_same<T, nullopt_t>::value, "bad T"); | ||
3923 | static_assert(!::std::is_same<T, in_place_t>::value, "bad T"); | ||
3924 | T* ref; | ||
3925 | |||
3926 | public: | ||
3927 | // 20.5.5.1, construction/destruction | ||
3928 | constexpr optional() noexcept | ||
3929 | : ref(nullptr) { | ||
3930 | } | ||
3931 | |||
3932 | constexpr optional(nullopt_t) noexcept | ||
3933 | : ref(nullptr) { | ||
3934 | } | ||
3935 | |||
3936 | constexpr optional(T& v) noexcept | ||
3937 | : ref(detail_::static_addressof(v)) { | ||
3938 | } | ||
3939 | |||
3940 | optional(T&&) = delete; | ||
3941 | |||
3942 | constexpr optional(const optional& rhs) noexcept | ||
3943 | : ref(rhs.ref) { | ||
3944 | } | ||
3945 | |||
3946 | explicit constexpr optional(in_place_t, T& v) noexcept | ||
3947 | : ref(detail_::static_addressof(v)) { | ||
3948 | } | ||
3949 | |||
3950 | explicit optional(in_place_t, T&&) = delete; | ||
3951 | |||
3952 | ~optional() = default; | ||
3953 | |||
3954 | // 20.5.5.2, mutation | ||
3955 | optional& operator=(nullopt_t) noexcept { | ||
3956 | ref = nullptr; | ||
3957 | return *this; | ||
3958 | } | ||
3959 | |||
3960 | // optional& operator=(const optional& rhs) noexcept { | ||
3961 | // ref = rhs.ref; | ||
3962 | // return *this; | ||
3963 | // } | ||
3964 | |||
3965 | // optional& operator=(optional&& rhs) noexcept { | ||
3966 | // ref = rhs.ref; | ||
3967 | // return *this; | ||
3968 | // } | ||
3969 | |||
3970 | template <typename U> | ||
3971 | auto operator=(U&& rhs) noexcept | ||
3972 | -> typename ::std::enable_if< | ||
3973 | ::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, | ||
3974 | optional&>::type { | ||
3975 | ref = rhs.ref; | ||
3976 | return *this; | ||
3977 | } | ||
3978 | |||
3979 | template <typename U> | ||
3980 | auto operator=(U&& rhs) noexcept | ||
3981 | -> typename ::std::enable_if< | ||
3982 | !::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, | ||
3983 | optional&>::type = delete; | ||
3984 | |||
3985 | void emplace(T& v) noexcept { | ||
3986 | ref = detail_::static_addressof(v); | ||
3987 | } | ||
3988 | |||
3989 | void emplace(T&&) = delete; | ||
3990 | |||
3991 | void swap(optional<T&>& rhs) noexcept { | ||
3992 | ::std::swap(ref, rhs.ref); | ||
3993 | } | ||
3994 | |||
3995 | // 20.5.5.3, observers | ||
3996 | constexpr T* operator->() const { | ||
3997 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); | ||
3998 | } | ||
3999 | |||
4000 | constexpr T& operator*() const { | ||
4001 | return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); | ||
4002 | } | ||
4003 | |||
4004 | constexpr T& value() const { | ||
4005 | #ifdef SOL_NO_EXCEPTIONS | ||
4006 | return *ref; | ||
4007 | #else | ||
4008 | return ref ? *ref | ||
4009 | : (throw bad_optional_access("bad optional access"), *ref); | ||
4010 | #endif // Exceptions | ||
4011 | } | ||
4012 | |||
4013 | explicit constexpr operator bool() const noexcept { | ||
4014 | return ref != nullptr; | ||
4015 | } | ||
4016 | |||
4017 | template <typename V> | ||
4018 | constexpr T& value_or(V&& v) const { | ||
4019 | return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v)); | ||
4020 | } | ||
4021 | }; | ||
4022 | |||
4023 | template <class T> | ||
4024 | class optional<T&&> { | ||
4025 | static_assert(sizeof(T) == 0, "optional rvalue references disallowed"); | ||
4026 | }; | ||
4027 | |||
4028 | // 20.5.8, Relational operators | ||
4029 | template <class T> | ||
4030 | constexpr bool operator==(const optional<T>& x, const optional<T>& y) { | ||
4031 | return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; | ||
4032 | } | ||
4033 | |||
4034 | template <class T> | ||
4035 | constexpr bool operator!=(const optional<T>& x, const optional<T>& y) { | ||
4036 | return !(x == y); | ||
4037 | } | ||
4038 | |||
4039 | template <class T> | ||
4040 | constexpr bool operator<(const optional<T>& x, const optional<T>& y) { | ||
4041 | return (!y) ? false : (!x) ? true : *x < *y; | ||
4042 | } | ||
4043 | |||
4044 | template <class T> | ||
4045 | constexpr bool operator>(const optional<T>& x, const optional<T>& y) { | ||
4046 | return (y < x); | ||
4047 | } | ||
4048 | |||
4049 | template <class T> | ||
4050 | constexpr bool operator<=(const optional<T>& x, const optional<T>& y) { | ||
4051 | return !(y < x); | ||
4052 | } | ||
4053 | |||
4054 | template <class T> | ||
4055 | constexpr bool operator>=(const optional<T>& x, const optional<T>& y) { | ||
4056 | return !(x < y); | ||
4057 | } | ||
4058 | |||
4059 | // 20.5.9, Comparison with nullopt | ||
4060 | template <class T> | ||
4061 | constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept { | ||
4062 | return (!x); | ||
4063 | } | ||
4064 | |||
4065 | template <class T> | ||
4066 | constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept { | ||
4067 | return (!x); | ||
4068 | } | ||
4069 | |||
4070 | template <class T> | ||
4071 | constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept { | ||
4072 | return bool(x); | ||
4073 | } | ||
4074 | |||
4075 | template <class T> | ||
4076 | constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept { | ||
4077 | return bool(x); | ||
4078 | } | ||
4079 | |||
4080 | template <class T> | ||
4081 | constexpr bool operator<(const optional<T>&, nullopt_t) noexcept { | ||
4082 | return false; | ||
4083 | } | ||
4084 | |||
4085 | template <class T> | ||
4086 | constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept { | ||
4087 | return bool(x); | ||
4088 | } | ||
4089 | |||
4090 | template <class T> | ||
4091 | constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept { | ||
4092 | return (!x); | ||
4093 | } | ||
4094 | |||
4095 | template <class T> | ||
4096 | constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept { | ||
4097 | return true; | ||
4098 | } | ||
4099 | |||
4100 | template <class T> | ||
4101 | constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept { | ||
4102 | return bool(x); | ||
4103 | } | ||
4104 | |||
4105 | template <class T> | ||
4106 | constexpr bool operator>(nullopt_t, const optional<T>&) noexcept { | ||
4107 | return false; | ||
4108 | } | ||
4109 | |||
4110 | template <class T> | ||
4111 | constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept { | ||
4112 | return true; | ||
4113 | } | ||
4114 | |||
4115 | template <class T> | ||
4116 | constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept { | ||
4117 | return (!x); | ||
4118 | } | ||
4119 | |||
4120 | // 20.5.10, Comparison with T | ||
4121 | template <class T> | ||
4122 | constexpr bool operator==(const optional<T>& x, const T& v) { | ||
4123 | return bool(x) ? *x == v : false; | ||
4124 | } | ||
4125 | |||
4126 | template <class T> | ||
4127 | constexpr bool operator==(const T& v, const optional<T>& x) { | ||
4128 | return bool(x) ? v == *x : false; | ||
4129 | } | ||
4130 | |||
4131 | template <class T> | ||
4132 | constexpr bool operator!=(const optional<T>& x, const T& v) { | ||
4133 | return bool(x) ? *x != v : true; | ||
4134 | } | ||
4135 | |||
4136 | template <class T> | ||
4137 | constexpr bool operator!=(const T& v, const optional<T>& x) { | ||
4138 | return bool(x) ? v != *x : true; | ||
4139 | } | ||
4140 | |||
4141 | template <class T> | ||
4142 | constexpr bool operator<(const optional<T>& x, const T& v) { | ||
4143 | return bool(x) ? *x < v : true; | ||
4144 | } | ||
4145 | |||
4146 | template <class T> | ||
4147 | constexpr bool operator>(const T& v, const optional<T>& x) { | ||
4148 | return bool(x) ? v > *x : true; | ||
4149 | } | ||
4150 | |||
4151 | template <class T> | ||
4152 | constexpr bool operator>(const optional<T>& x, const T& v) { | ||
4153 | return bool(x) ? *x > v : false; | ||
4154 | } | ||
4155 | |||
4156 | template <class T> | ||
4157 | constexpr bool operator<(const T& v, const optional<T>& x) { | ||
4158 | return bool(x) ? v < *x : false; | ||
4159 | } | ||
4160 | |||
4161 | template <class T> | ||
4162 | constexpr bool operator>=(const optional<T>& x, const T& v) { | ||
4163 | return bool(x) ? *x >= v : false; | ||
4164 | } | ||
4165 | |||
4166 | template <class T> | ||
4167 | constexpr bool operator<=(const T& v, const optional<T>& x) { | ||
4168 | return bool(x) ? v <= *x : false; | ||
4169 | } | ||
4170 | |||
4171 | template <class T> | ||
4172 | constexpr bool operator<=(const optional<T>& x, const T& v) { | ||
4173 | return bool(x) ? *x <= v : true; | ||
4174 | } | ||
4175 | |||
4176 | template <class T> | ||
4177 | constexpr bool operator>=(const T& v, const optional<T>& x) { | ||
4178 | return bool(x) ? v >= *x : true; | ||
4179 | } | ||
4180 | |||
4181 | // Comparison of optional<T&> with T | ||
4182 | template <class T> | ||
4183 | constexpr bool operator==(const optional<T&>& x, const T& v) { | ||
4184 | return bool(x) ? *x == v : false; | ||
4185 | } | ||
4186 | |||
4187 | template <class T> | ||
4188 | constexpr bool operator==(const T& v, const optional<T&>& x) { | ||
4189 | return bool(x) ? v == *x : false; | ||
4190 | } | ||
4191 | |||
4192 | template <class T> | ||
4193 | constexpr bool operator!=(const optional<T&>& x, const T& v) { | ||
4194 | return bool(x) ? *x != v : true; | ||
4195 | } | ||
4196 | |||
4197 | template <class T> | ||
4198 | constexpr bool operator!=(const T& v, const optional<T&>& x) { | ||
4199 | return bool(x) ? v != *x : true; | ||
4200 | } | ||
4201 | |||
4202 | template <class T> | ||
4203 | constexpr bool operator<(const optional<T&>& x, const T& v) { | ||
4204 | return bool(x) ? *x < v : true; | ||
4205 | } | ||
4206 | |||
4207 | template <class T> | ||
4208 | constexpr bool operator>(const T& v, const optional<T&>& x) { | ||
4209 | return bool(x) ? v > *x : true; | ||
4210 | } | ||
4211 | |||
4212 | template <class T> | ||
4213 | constexpr bool operator>(const optional<T&>& x, const T& v) { | ||
4214 | return bool(x) ? *x > v : false; | ||
4215 | } | ||
4216 | |||
4217 | template <class T> | ||
4218 | constexpr bool operator<(const T& v, const optional<T&>& x) { | ||
4219 | return bool(x) ? v < *x : false; | ||
4220 | } | ||
4221 | |||
4222 | template <class T> | ||
4223 | constexpr bool operator>=(const optional<T&>& x, const T& v) { | ||
4224 | return bool(x) ? *x >= v : false; | ||
4225 | } | ||
4226 | |||
4227 | template <class T> | ||
4228 | constexpr bool operator<=(const T& v, const optional<T&>& x) { | ||
4229 | return bool(x) ? v <= *x : false; | ||
4230 | } | ||
4231 | |||
4232 | template <class T> | ||
4233 | constexpr bool operator<=(const optional<T&>& x, const T& v) { | ||
4234 | return bool(x) ? *x <= v : true; | ||
4235 | } | ||
4236 | |||
4237 | template <class T> | ||
4238 | constexpr bool operator>=(const T& v, const optional<T&>& x) { | ||
4239 | return bool(x) ? v >= *x : true; | ||
4240 | } | ||
4241 | |||
4242 | // Comparison of optional<T const&> with T | ||
4243 | template <class T> | ||
4244 | constexpr bool operator==(const optional<const T&>& x, const T& v) { | ||
4245 | return bool(x) ? *x == v : false; | ||
4246 | } | ||
4247 | |||
4248 | template <class T> | ||
4249 | constexpr bool operator==(const T& v, const optional<const T&>& x) { | ||
4250 | return bool(x) ? v == *x : false; | ||
4251 | } | ||
4252 | |||
4253 | template <class T> | ||
4254 | constexpr bool operator!=(const optional<const T&>& x, const T& v) { | ||
4255 | return bool(x) ? *x != v : true; | ||
4256 | } | ||
4257 | |||
4258 | template <class T> | ||
4259 | constexpr bool operator!=(const T& v, const optional<const T&>& x) { | ||
4260 | return bool(x) ? v != *x : true; | ||
4261 | } | ||
4262 | |||
4263 | template <class T> | ||
4264 | constexpr bool operator<(const optional<const T&>& x, const T& v) { | ||
4265 | return bool(x) ? *x < v : true; | ||
4266 | } | ||
4267 | |||
4268 | template <class T> | ||
4269 | constexpr bool operator>(const T& v, const optional<const T&>& x) { | ||
4270 | return bool(x) ? v > *x : true; | ||
4271 | } | ||
4272 | |||
4273 | template <class T> | ||
4274 | constexpr bool operator>(const optional<const T&>& x, const T& v) { | ||
4275 | return bool(x) ? *x > v : false; | ||
4276 | } | ||
4277 | |||
4278 | template <class T> | ||
4279 | constexpr bool operator<(const T& v, const optional<const T&>& x) { | ||
4280 | return bool(x) ? v < *x : false; | ||
4281 | } | ||
4282 | |||
4283 | template <class T> | ||
4284 | constexpr bool operator>=(const optional<const T&>& x, const T& v) { | ||
4285 | return bool(x) ? *x >= v : false; | ||
4286 | } | ||
4287 | |||
4288 | template <class T> | ||
4289 | constexpr bool operator<=(const T& v, const optional<const T&>& x) { | ||
4290 | return bool(x) ? v <= *x : false; | ||
4291 | } | ||
4292 | |||
4293 | template <class T> | ||
4294 | constexpr bool operator<=(const optional<const T&>& x, const T& v) { | ||
4295 | return bool(x) ? *x <= v : true; | ||
4296 | } | ||
4297 | |||
4298 | template <class T> | ||
4299 | constexpr bool operator>=(const T& v, const optional<const T&>& x) { | ||
4300 | return bool(x) ? v >= *x : true; | ||
4301 | } | ||
4302 | |||
4303 | // 20.5.12, Specialized algorithms | ||
4304 | template <class T> | ||
4305 | void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) { | ||
4306 | x.swap(y); | ||
4307 | } | ||
4308 | |||
4309 | template <class T> | ||
4310 | constexpr optional<typename ::std::decay<T>::type> make_optional(T&& v) { | ||
4311 | return optional<typename ::std::decay<T>::type>(constexpr_forward<T>(v)); | ||
4312 | } | ||
4313 | |||
4314 | template <class X> | ||
4315 | constexpr optional<X&> make_optional(::std::reference_wrapper<X> v) { | ||
4316 | return optional<X&>(v.get()); | ||
4317 | } | ||
4318 | |||
4319 | } // namespace sol | ||
4320 | |||
4321 | namespace std { | ||
4322 | template <typename T> | ||
4323 | struct hash<sol::optional<T>> { | ||
4324 | typedef typename hash<T>::result_type result_type; | ||
4325 | typedef sol::optional<T> argument_type; | ||
4326 | |||
4327 | constexpr result_type operator()(argument_type const& arg) const { | ||
4328 | return arg ? ::std::hash<T>{}(*arg) : result_type{}; | ||
4329 | } | ||
4330 | }; | ||
4331 | |||
4332 | template <typename T> | ||
4333 | struct hash<sol::optional<T&>> { | ||
4334 | typedef typename hash<T>::result_type result_type; | ||
4335 | typedef sol::optional<T&> argument_type; | ||
4336 | |||
4337 | constexpr result_type operator()(argument_type const& arg) const { | ||
4338 | return arg ? ::std::hash<T>{}(*arg) : result_type{}; | ||
4339 | } | ||
4340 | }; | ||
4341 | } // namespace std | ||
4342 | |||
4343 | #if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ | ||
4344 | #pragma warning(pop) | ||
4345 | #endif | ||
4346 | |||
4347 | #undef TR2_OPTIONAL_REQUIRES | ||
4348 | #undef TR2_OPTIONAL_ASSERTED_EXPRESSION | ||
4349 | |||
4350 | // end of sol/optional_implementation.hpp | ||
4351 | |||
4352 | #endif // Boost vs. Better optional | ||
4353 | |||
4354 | namespace sol { | ||
4355 | |||
4356 | #if defined(SOL_USE_BOOST) && SOL_USE_BOOST | ||
4357 | template <typename T> | ||
4358 | using optional = boost::optional<T>; | ||
4359 | using nullopt_t = boost::none_t; | ||
4360 | const nullopt_t nullopt = boost::none; | ||
4361 | #endif // Boost vs. Better optional | ||
4362 | |||
4363 | namespace meta { | ||
4364 | template <typename T> | ||
4365 | struct is_optional : std::false_type {}; | ||
4366 | template <typename T> | ||
4367 | struct is_optional<optional<T>> : std::true_type {}; | ||
4368 | } // namespace meta | ||
4369 | } // namespace sol | ||
4370 | |||
4371 | // end of sol/optional.hpp | ||
4372 | |||
4373 | // beginning of sol/forward_detail.hpp | ||
4374 | |||
4375 | namespace sol { | ||
4376 | namespace detail { | ||
4377 | const bool default_safe_function_calls = | ||
4378 | #if defined(SOL_SAFE_FUNCTION_CALLS) && SOL_SAFE_FUNCTION_CALLS | ||
4379 | true; | ||
4380 | #else | ||
4381 | false; | ||
4382 | #endif | ||
4383 | } // namespace detail | ||
4384 | |||
4385 | namespace meta { | ||
4386 | namespace meta_detail { | ||
4387 | } | ||
4388 | } // namespace meta::meta_detail | ||
4389 | |||
4390 | namespace stack { | ||
4391 | namespace stack_detail { | ||
4392 | template <typename T> | ||
4393 | struct undefined_metatable; | ||
4394 | } | ||
4395 | } // namespace stack::stack_detail | ||
4396 | |||
4397 | namespace usertype_detail { | ||
4398 | template <typename T, typename Regs, typename Fx> | ||
4399 | void insert_default_registrations(Regs& l, int& index, Fx&& fx); | ||
4400 | |||
4401 | template <typename T, typename Regs, meta::enable<meta::neg<std::is_pointer<T>>, std::is_destructible<T>> = meta::enabler> | ||
4402 | void make_destructor(Regs& l, int& index); | ||
4403 | template <typename T, typename Regs, meta::disable<meta::neg<std::is_pointer<T>>, std::is_destructible<T>> = meta::enabler> | ||
4404 | void make_destructor(Regs& l, int& index); | ||
4405 | } // namespace usertype_detail | ||
4406 | } // namespace sol | ||
4407 | |||
4408 | // end of sol/forward_detail.hpp | ||
4409 | |||
4410 | // beginning of sol/raii.hpp | ||
4411 | |||
4412 | namespace sol { | ||
4413 | namespace detail { | ||
4414 | struct default_construct { | ||
4415 | template <typename T, typename... Args> | ||
4416 | static void construct(T&& obj, Args&&... args) { | ||
4417 | typedef meta::unqualified_t<T> Tu; | ||
4418 | std::allocator<Tu> alloc{}; | ||
4419 | std::allocator_traits<std::allocator<Tu>>::construct(alloc, obj, std::forward<Args>(args)...); | ||
4420 | } | ||
4421 | |||
4422 | template <typename T, typename... Args> | ||
4423 | void operator()(T&& obj, Args&&... args) const { | ||
4424 | construct(std::forward<T>(obj), std::forward<Args>(args)...); | ||
4425 | } | ||
4426 | }; | ||
4427 | |||
4428 | struct default_destruct { | ||
4429 | template <typename T> | ||
4430 | static void destroy(T&& obj) { | ||
4431 | std::allocator<meta::unqualified_t<T>> alloc{}; | ||
4432 | alloc.destroy(obj); | ||
4433 | } | ||
4434 | |||
4435 | template <typename T> | ||
4436 | void operator()(T&& obj) const { | ||
4437 | destroy(std::forward<T>(obj)); | ||
4438 | } | ||
4439 | }; | ||
4440 | |||
4441 | struct deleter { | ||
4442 | template <typename T> | ||
4443 | void operator()(T* p) const { | ||
4444 | delete p; | ||
4445 | } | ||
4446 | }; | ||
4447 | |||
4448 | struct state_deleter { | ||
4449 | void operator()(lua_State* L) const { | ||
4450 | lua_close(L); | ||
4451 | } | ||
4452 | }; | ||
4453 | |||
4454 | template <typename T, typename Dx, typename... Args> | ||
4455 | inline std::unique_ptr<T, Dx> make_unique_deleter(Args&&... args) { | ||
4456 | return std::unique_ptr<T, Dx>(new T(std::forward<Args>(args)...)); | ||
4457 | } | ||
4458 | |||
4459 | template <typename Tag, typename T> | ||
4460 | struct tagged { | ||
4461 | T value; | ||
4462 | template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, tagged>> = meta::enabler> | ||
4463 | tagged(Arg&& arg, Args&&... args) | ||
4464 | : value(std::forward<Arg>(arg), std::forward<Args>(args)...) { | ||
4465 | } | ||
4466 | }; | ||
4467 | } // namespace detail | ||
4468 | |||
4469 | template <typename... Args> | ||
4470 | struct constructor_list {}; | ||
4471 | |||
4472 | template <typename... Args> | ||
4473 | using constructors = constructor_list<Args...>; | ||
4474 | |||
4475 | const auto default_constructor = constructors<types<>>{}; | ||
4476 | |||
4477 | struct no_construction {}; | ||
4478 | const auto no_constructor = no_construction{}; | ||
4479 | |||
4480 | struct call_construction {}; | ||
4481 | const auto call_constructor = call_construction{}; | ||
4482 | |||
4483 | template <typename... Functions> | ||
4484 | struct constructor_wrapper { | ||
4485 | std::tuple<Functions...> functions; | ||
4486 | template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, constructor_wrapper>> = meta::enabler> | ||
4487 | constructor_wrapper(Arg&& arg, Args&&... args) | ||
4488 | : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) { | ||
4489 | } | ||
4490 | }; | ||
4491 | |||
4492 | template <typename... Functions> | ||
4493 | inline auto initializers(Functions&&... functions) { | ||
4494 | return constructor_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...); | ||
4495 | } | ||
4496 | |||
4497 | template <typename... Functions> | ||
4498 | struct factory_wrapper { | ||
4499 | std::tuple<Functions...> functions; | ||
4500 | template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, factory_wrapper>> = meta::enabler> | ||
4501 | factory_wrapper(Arg&& arg, Args&&... args) | ||
4502 | : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) { | ||
4503 | } | ||
4504 | }; | ||
4505 | |||
4506 | template <typename... Functions> | ||
4507 | inline auto factories(Functions&&... functions) { | ||
4508 | return factory_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...); | ||
4509 | } | ||
4510 | |||
4511 | template <typename Function> | ||
4512 | struct destructor_wrapper { | ||
4513 | Function fx; | ||
4514 | destructor_wrapper(Function f) | ||
4515 | : fx(std::move(f)) { | ||
4516 | } | ||
4517 | }; | ||
4518 | |||
4519 | template <> | ||
4520 | struct destructor_wrapper<void> {}; | ||
4521 | |||
4522 | const destructor_wrapper<void> default_destructor{}; | ||
4523 | |||
4524 | template <typename Fx> | ||
4525 | inline auto destructor(Fx&& fx) { | ||
4526 | return destructor_wrapper<std::decay_t<Fx>>(std::forward<Fx>(fx)); | ||
4527 | } | ||
4528 | |||
4529 | } // namespace sol | ||
4530 | |||
4531 | // end of sol/raii.hpp | ||
4532 | |||
4533 | // beginning of sol/filters.hpp | ||
4534 | |||
4535 | #include <array> | ||
4536 | |||
4537 | namespace sol { | ||
4538 | namespace detail { | ||
4539 | struct filter_base_tag {}; | ||
4540 | } // namespace detail | ||
4541 | |||
4542 | template <int Target, int... In> | ||
4543 | struct static_stack_dependencies : detail::filter_base_tag {}; | ||
4544 | typedef static_stack_dependencies<-1, 1> self_dependency; | ||
4545 | template <int... In> | ||
4546 | struct returns_self_with : detail::filter_base_tag {}; | ||
4547 | typedef returns_self_with<> returns_self; | ||
4548 | |||
4549 | struct stack_dependencies : detail::filter_base_tag { | ||
4550 | int target; | ||
4551 | std::array<int, 64> stack_indices; | ||
4552 | std::size_t len; | ||
4553 | |||
4554 | template <typename... Args> | ||
4555 | stack_dependencies(int stack_target, Args&&... args) | ||
4556 | : target(stack_target), stack_indices(), len(sizeof...(Args)) { | ||
4557 | std::size_t i = 0; | ||
4558 | (void)detail::swallow{int(), (stack_indices[i++] = static_cast<int>(std::forward<Args>(args)), int())...}; | ||
4559 | } | ||
4560 | |||
4561 | int& operator[](std::size_t i) { | ||
4562 | return stack_indices[i]; | ||
4563 | } | ||
4564 | |||
4565 | const int& operator[](std::size_t i) const { | ||
4566 | return stack_indices[i]; | ||
4567 | } | ||
4568 | |||
4569 | std::size_t size() const { | ||
4570 | return len; | ||
4571 | } | ||
4572 | }; | ||
4573 | |||
4574 | template <typename F, typename... Filters> | ||
4575 | struct filter_wrapper { | ||
4576 | typedef std::index_sequence_for<Filters...> indices; | ||
4577 | |||
4578 | F value; | ||
4579 | std::tuple<Filters...> filters; | ||
4580 | |||
4581 | template <typename Fx, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Fx>, filter_wrapper>>> = meta::enabler> | ||
4582 | filter_wrapper(Fx&& fx, Args&&... args) | ||
4583 | : value(std::forward<Fx>(fx)), filters(std::forward<Args>(args)...) { | ||
4584 | } | ||
4585 | |||
4586 | filter_wrapper(const filter_wrapper&) = default; | ||
4587 | filter_wrapper& operator=(const filter_wrapper&) = default; | ||
4588 | filter_wrapper(filter_wrapper&&) = default; | ||
4589 | filter_wrapper& operator=(filter_wrapper&&) = default; | ||
4590 | }; | ||
4591 | |||
4592 | template <typename F, typename... Args> | ||
4593 | auto filters(F&& f, Args&&... args) { | ||
4594 | return filter_wrapper<std::decay_t<F>, std::decay_t<Args>...>(std::forward<F>(f), std::forward<Args>(args)...); | ||
4595 | } | ||
4596 | } // namespace sol | ||
4597 | |||
4598 | // end of sol/filters.hpp | ||
4599 | |||
4600 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
4601 | #ifdef SOL_STD_VARIANT | ||
4602 | #include <variant> | ||
4603 | #endif | ||
4604 | #endif // C++17 | ||
4605 | #ifdef SOL_USE_BOOST | ||
4606 | #include <boost/unordered_map.hpp> | ||
4607 | #else | ||
4608 | #include <unordered_map> | ||
4609 | #endif // Using Boost | ||
4610 | |||
4611 | namespace sol { | ||
4612 | namespace usertype_detail { | ||
4613 | #if defined(SOL_USE_BOOST) | ||
4614 | #if defined(SOL_CXX17_FEATURES) | ||
4615 | template <typename K, typename V, typename H = std::hash<K>, typename E = std::equal_to<>> | ||
4616 | using map_t = boost::unordered_map<K, V, H, E>; | ||
4617 | #else | ||
4618 | template <typename K, typename V, typename H = boost::hash<K>, typename E = std::equal_to<>> | ||
4619 | using map_t = boost::unordered_map<K, V, H, E>; | ||
4620 | #endif // C++17 or not, WITH boost | ||
4621 | #else | ||
4622 | template <typename K, typename V, typename H = std::hash<K>, typename E = std::equal_to<>> | ||
4623 | using map_t = std::unordered_map<K, V, H, E>; | ||
4624 | #endif // Boost map target | ||
4625 | } | ||
4626 | |||
4627 | namespace detail { | ||
4628 | #ifdef SOL_NOEXCEPT_FUNCTION_TYPE | ||
4629 | typedef int(*lua_CFunction_noexcept)(lua_State* L) noexcept; | ||
4630 | #else | ||
4631 | typedef int(*lua_CFunction_noexcept)(lua_State* L); | ||
4632 | #endif // noexcept function type for lua_CFunction | ||
4633 | |||
4634 | template <typename T> | ||
4635 | struct unique_usertype {}; | ||
4636 | |||
4637 | template <typename T> | ||
4638 | struct implicit_wrapper { | ||
4639 | T& item; | ||
4640 | implicit_wrapper(T* item) | ||
4641 | : item(*item) { | ||
4642 | } | ||
4643 | implicit_wrapper(T& item) | ||
4644 | : item(item) { | ||
4645 | } | ||
4646 | operator T&() { | ||
4647 | return item; | ||
4648 | } | ||
4649 | operator T*() { | ||
4650 | return std::addressof(item); | ||
4651 | } | ||
4652 | }; | ||
4653 | |||
4654 | struct unchecked_t {}; | ||
4655 | const unchecked_t unchecked = unchecked_t{}; | ||
4656 | |||
4657 | struct yield_tag_t {}; | ||
4658 | const yield_tag_t yield_tag = yield_tag_t{}; | ||
4659 | } // namespace detail | ||
4660 | |||
4661 | struct lua_nil_t {}; | ||
4662 | const lua_nil_t lua_nil{}; | ||
4663 | inline bool operator==(lua_nil_t, lua_nil_t) { | ||
4664 | return true; | ||
4665 | } | ||
4666 | inline bool operator!=(lua_nil_t, lua_nil_t) { | ||
4667 | return false; | ||
4668 | } | ||
4669 | typedef lua_nil_t nil_t; | ||
4670 | #if !defined(SOL_NO_NIL) | ||
4671 | const nil_t nil{}; | ||
4672 | #endif | ||
4673 | |||
4674 | struct metatable_t {}; | ||
4675 | const metatable_t metatable_key = {}; | ||
4676 | |||
4677 | struct env_t {}; | ||
4678 | const env_t env_key = {}; | ||
4679 | |||
4680 | struct no_metatable_t {}; | ||
4681 | const no_metatable_t no_metatable = {}; | ||
4682 | |||
4683 | template <typename T> | ||
4684 | struct yielding_t { | ||
4685 | T func; | ||
4686 | |||
4687 | yielding_t() = default; | ||
4688 | yielding_t(const yielding_t&) = default; | ||
4689 | yielding_t(yielding_t&&) = default; | ||
4690 | yielding_t& operator=(const yielding_t&) = default; | ||
4691 | yielding_t& operator=(yielding_t&&) = default; | ||
4692 | template <typename Arg, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>, yielding_t>>, meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler> | ||
4693 | yielding_t(Arg&& arg) | ||
4694 | : func(std::forward<Arg>(arg)) { | ||
4695 | } | ||
4696 | template <typename Arg0, typename Arg1, typename... Args> | ||
4697 | yielding_t(Arg0&& arg0, Arg1&& arg1, Args&&... args) | ||
4698 | : func(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) { | ||
4699 | } | ||
4700 | }; | ||
4701 | |||
4702 | template <typename F> | ||
4703 | inline yielding_t<std::decay_t<F>> yielding(F&& f) { | ||
4704 | return yielding_t<std::decay_t<F>>(std::forward<F>(f)); | ||
4705 | } | ||
4706 | |||
4707 | typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref; | ||
4708 | |||
4709 | template <typename T> | ||
4710 | struct unique_usertype_traits { | ||
4711 | typedef T type; | ||
4712 | typedef T actual_type; | ||
4713 | static const bool value = false; | ||
4714 | |||
4715 | template <typename U> | ||
4716 | static bool is_null(U&&) { | ||
4717 | return false; | ||
4718 | } | ||
4719 | |||
4720 | template <typename U> | ||
4721 | static auto get(U&& value) { | ||
4722 | return std::addressof(detail::deref(value)); | ||
4723 | } | ||
4724 | }; | ||
4725 | |||
4726 | template <typename T> | ||
4727 | struct unique_usertype_traits<std::shared_ptr<T>> { | ||
4728 | typedef T type; | ||
4729 | typedef std::shared_ptr<T> actual_type; | ||
4730 | static const bool value = true; | ||
4731 | |||
4732 | static bool is_null(const actual_type& p) { | ||
4733 | return p == nullptr; | ||
4734 | } | ||
4735 | |||
4736 | static type* get(const actual_type& p) { | ||
4737 | return p.get(); | ||
4738 | } | ||
4739 | }; | ||
4740 | |||
4741 | template <typename T, typename D> | ||
4742 | struct unique_usertype_traits<std::unique_ptr<T, D>> { | ||
4743 | typedef T type; | ||
4744 | typedef std::unique_ptr<T, D> actual_type; | ||
4745 | static const bool value = true; | ||
4746 | |||
4747 | static bool is_null(const actual_type& p) { | ||
4748 | return p == nullptr; | ||
4749 | } | ||
4750 | |||
4751 | static type* get(const actual_type& p) { | ||
4752 | return p.get(); | ||
4753 | } | ||
4754 | }; | ||
4755 | |||
4756 | template <typename T> | ||
4757 | struct non_null {}; | ||
4758 | |||
4759 | template <typename... Args> | ||
4760 | struct function_sig {}; | ||
4761 | |||
4762 | struct upvalue_index { | ||
4763 | int index; | ||
4764 | upvalue_index(int idx) | ||
4765 | : index(lua_upvalueindex(idx)) { | ||
4766 | } | ||
4767 | |||
4768 | operator int() const { | ||
4769 | return index; | ||
4770 | } | ||
4771 | }; | ||
4772 | |||
4773 | struct raw_index { | ||
4774 | int index; | ||
4775 | raw_index(int i) | ||
4776 | : index(i) { | ||
4777 | } | ||
4778 | |||
4779 | operator int() const { | ||
4780 | return index; | ||
4781 | } | ||
4782 | }; | ||
4783 | |||
4784 | struct absolute_index { | ||
4785 | int index; | ||
4786 | absolute_index(lua_State* L, int idx) | ||
4787 | : index(lua_absindex(L, idx)) { | ||
4788 | } | ||
4789 | |||
4790 | operator int() const { | ||
4791 | return index; | ||
4792 | } | ||
4793 | }; | ||
4794 | |||
4795 | struct ref_index { | ||
4796 | int index; | ||
4797 | ref_index(int idx) | ||
4798 | : index(idx) { | ||
4799 | } | ||
4800 | |||
4801 | operator int() const { | ||
4802 | return index; | ||
4803 | } | ||
4804 | }; | ||
4805 | |||
4806 | struct stack_count { | ||
4807 | int count; | ||
4808 | |||
4809 | stack_count(int cnt) | ||
4810 | : count(cnt) { | ||
4811 | } | ||
4812 | }; | ||
4813 | |||
4814 | struct lightuserdata_value { | ||
4815 | void* value; | ||
4816 | lightuserdata_value(void* data) | ||
4817 | : value(data) { | ||
4818 | } | ||
4819 | operator void*() const { | ||
4820 | return value; | ||
4821 | } | ||
4822 | }; | ||
4823 | |||
4824 | struct userdata_value { | ||
4825 | void* value; | ||
4826 | userdata_value(void* data) | ||
4827 | : value(data) { | ||
4828 | } | ||
4829 | operator void*() const { | ||
4830 | return value; | ||
4831 | } | ||
4832 | }; | ||
4833 | |||
4834 | template <typename L> | ||
4835 | struct light { | ||
4836 | L* value; | ||
4837 | |||
4838 | light(L& x) | ||
4839 | : value(std::addressof(x)) { | ||
4840 | } | ||
4841 | light(L* x) | ||
4842 | : value(x) { | ||
4843 | } | ||
4844 | light(void* x) | ||
4845 | : value(static_cast<L*>(x)) { | ||
4846 | } | ||
4847 | operator L*() const { | ||
4848 | return value; | ||
4849 | } | ||
4850 | operator L&() const { | ||
4851 | return *value; | ||
4852 | } | ||
4853 | }; | ||
4854 | |||
4855 | template <typename T> | ||
4856 | auto make_light(T& l) { | ||
4857 | typedef meta::unwrapped_t<std::remove_pointer_t<std::remove_pointer_t<T>>> L; | ||
4858 | return light<L>(l); | ||
4859 | } | ||
4860 | |||
4861 | template <typename U> | ||
4862 | struct user { | ||
4863 | U value; | ||
4864 | |||
4865 | user(U x) | ||
4866 | : value(std::forward<U>(x)) { | ||
4867 | } | ||
4868 | operator std::add_pointer_t<std::remove_reference_t<U>>() { | ||
4869 | return std::addressof(value); | ||
4870 | } | ||
4871 | operator std::add_lvalue_reference_t<U>() { | ||
4872 | return value; | ||
4873 | } | ||
4874 | operator std::add_const_t<std::add_lvalue_reference_t<U>>&() const { | ||
4875 | return value; | ||
4876 | } | ||
4877 | }; | ||
4878 | |||
4879 | template <typename T> | ||
4880 | auto make_user(T&& u) { | ||
4881 | typedef meta::unwrapped_t<meta::unqualified_t<T>> U; | ||
4882 | return user<U>(std::forward<T>(u)); | ||
4883 | } | ||
4884 | |||
4885 | template <typename T> | ||
4886 | struct metatable_registry_key { | ||
4887 | T key; | ||
4888 | |||
4889 | metatable_registry_key(T key) | ||
4890 | : key(std::forward<T>(key)) { | ||
4891 | } | ||
4892 | }; | ||
4893 | |||
4894 | template <typename T> | ||
4895 | auto meta_registry_key(T&& key) { | ||
4896 | typedef meta::unqualified_t<T> K; | ||
4897 | return metatable_registry_key<K>(std::forward<T>(key)); | ||
4898 | } | ||
4899 | |||
4900 | template <typename... Upvalues> | ||
4901 | struct closure { | ||
4902 | lua_CFunction c_function; | ||
4903 | std::tuple<Upvalues...> upvalues; | ||
4904 | closure(lua_CFunction f, Upvalues... targetupvalues) | ||
4905 | : c_function(f), upvalues(std::forward<Upvalues>(targetupvalues)...) { | ||
4906 | } | ||
4907 | }; | ||
4908 | |||
4909 | template <> | ||
4910 | struct closure<> { | ||
4911 | lua_CFunction c_function; | ||
4912 | int upvalues; | ||
4913 | closure(lua_CFunction f, int upvalue_count = 0) | ||
4914 | : c_function(f), upvalues(upvalue_count) { | ||
4915 | } | ||
4916 | }; | ||
4917 | |||
4918 | typedef closure<> c_closure; | ||
4919 | |||
4920 | template <typename... Args> | ||
4921 | closure<Args...> make_closure(lua_CFunction f, Args&&... args) { | ||
4922 | return closure<Args...>(f, std::forward<Args>(args)...); | ||
4923 | } | ||
4924 | |||
4925 | template <typename Sig, typename... Ps> | ||
4926 | struct function_arguments { | ||
4927 | std::tuple<Ps...> arguments; | ||
4928 | template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, function_arguments>> = meta::enabler> | ||
4929 | function_arguments(Arg&& arg, Args&&... args) | ||
4930 | : arguments(std::forward<Arg>(arg), std::forward<Args>(args)...) { | ||
4931 | } | ||
4932 | }; | ||
4933 | |||
4934 | template <typename Sig = function_sig<>, typename... Args> | ||
4935 | auto as_function(Args&&... args) { | ||
4936 | return function_arguments<Sig, std::decay_t<Args>...>(std::forward<Args>(args)...); | ||
4937 | } | ||
4938 | |||
4939 | template <typename Sig = function_sig<>, typename... Args> | ||
4940 | auto as_function_reference(Args&&... args) { | ||
4941 | return function_arguments<Sig, Args...>(std::forward<Args>(args)...); | ||
4942 | } | ||
4943 | |||
4944 | template <typename T> | ||
4945 | struct as_table_t { | ||
4946 | T source; | ||
4947 | |||
4948 | as_table_t() = default; | ||
4949 | as_table_t(const as_table_t&) = default; | ||
4950 | as_table_t(as_table_t&&) = default; | ||
4951 | as_table_t& operator=(const as_table_t&) = default; | ||
4952 | as_table_t& operator=(as_table_t&&) = default; | ||
4953 | template <typename Arg, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>, as_table_t>>, meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler> | ||
4954 | as_table_t(Arg&& arg) | ||
4955 | : source(std::forward<Arg>(arg)) { | ||
4956 | } | ||
4957 | template <typename Arg0, typename Arg1, typename... Args> | ||
4958 | as_table_t(Arg0&& arg0, Arg1&& arg1, Args&&... args) | ||
4959 | : source(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) { | ||
4960 | } | ||
4961 | |||
4962 | operator std::add_lvalue_reference_t<T>() { | ||
4963 | return source; | ||
4964 | } | ||
4965 | }; | ||
4966 | |||
4967 | template <typename T> | ||
4968 | struct nested { | ||
4969 | T source; | ||
4970 | |||
4971 | nested() = default; | ||
4972 | nested(const nested&) = default; | ||
4973 | nested(nested&&) = default; | ||
4974 | nested& operator=(const nested&) = default; | ||
4975 | nested& operator=(nested&&) = default; | ||
4976 | template <typename Arg, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>, nested>>, meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler> | ||
4977 | nested(Arg&& arg) | ||
4978 | : source(std::forward<Arg>(arg)) { | ||
4979 | } | ||
4980 | template <typename Arg0, typename Arg1, typename... Args> | ||
4981 | nested(Arg0&& arg0, Arg1&& arg1, Args&&... args) | ||
4982 | : source(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) { | ||
4983 | } | ||
4984 | |||
4985 | operator std::add_lvalue_reference_t<T>() { | ||
4986 | return source; | ||
4987 | } | ||
4988 | }; | ||
4989 | |||
4990 | template <typename T> | ||
4991 | as_table_t<T> as_table_ref(T&& container) { | ||
4992 | return as_table_t<T>(std::forward<T>(container)); | ||
4993 | } | ||
4994 | |||
4995 | template <typename T> | ||
4996 | as_table_t<meta::unqualified_t<T>> as_table(T&& container) { | ||
4997 | return as_table_t<meta::unqualified_t<T>>(std::forward<T>(container)); | ||
4998 | } | ||
4999 | |||
5000 | template <typename T> | ||
5001 | nested<T> as_nested_ref(T&& container) { | ||
5002 | return nested<T>(std::forward<T>(container)); | ||
5003 | } | ||
5004 | |||
5005 | template <typename T> | ||
5006 | nested<meta::unqualified_t<T>> as_nested(T&& container) { | ||
5007 | return nested<meta::unqualified_t<T>>(std::forward<T>(container)); | ||
5008 | } | ||
5009 | |||
5010 | struct this_state { | ||
5011 | lua_State* L; | ||
5012 | |||
5013 | this_state(lua_State* Ls) | ||
5014 | : L(Ls) { | ||
5015 | } | ||
5016 | |||
5017 | operator lua_State*() const noexcept { | ||
5018 | return lua_state(); | ||
5019 | } | ||
5020 | |||
5021 | lua_State* operator->() const noexcept { | ||
5022 | return lua_state(); | ||
5023 | } | ||
5024 | |||
5025 | lua_State* lua_state() const noexcept { | ||
5026 | return L; | ||
5027 | } | ||
5028 | }; | ||
5029 | |||
5030 | struct this_main_state { | ||
5031 | lua_State* L; | ||
5032 | |||
5033 | this_main_state(lua_State* Ls) | ||
5034 | : L(Ls) { | ||
5035 | } | ||
5036 | |||
5037 | operator lua_State*() const noexcept { | ||
5038 | return lua_state(); | ||
5039 | } | ||
5040 | |||
5041 | lua_State* operator->() const noexcept { | ||
5042 | return lua_state(); | ||
5043 | } | ||
5044 | |||
5045 | lua_State* lua_state() const noexcept { | ||
5046 | return L; | ||
5047 | } | ||
5048 | }; | ||
5049 | |||
5050 | struct new_table { | ||
5051 | int sequence_hint = 0; | ||
5052 | int map_hint = 0; | ||
5053 | |||
5054 | new_table() = default; | ||
5055 | new_table(const new_table&) = default; | ||
5056 | new_table(new_table&&) = default; | ||
5057 | new_table& operator=(const new_table&) = default; | ||
5058 | new_table& operator=(new_table&&) = default; | ||
5059 | |||
5060 | new_table(int sequence_hint, int map_hint = 0) | ||
5061 | : sequence_hint(sequence_hint), map_hint(map_hint) { | ||
5062 | } | ||
5063 | }; | ||
5064 | |||
5065 | enum class lib : char { | ||
5066 | // print, assert, and other base functions | ||
5067 | base, | ||
5068 | // require and other package functions | ||
5069 | package, | ||
5070 | // coroutine functions and utilities | ||
5071 | coroutine, | ||
5072 | // string library | ||
5073 | string, | ||
5074 | // functionality from the OS | ||
5075 | os, | ||
5076 | // all things math | ||
5077 | math, | ||
5078 | // the table manipulator and observer functions | ||
5079 | table, | ||
5080 | // the debug library | ||
5081 | debug, | ||
5082 | // the bit library: different based on which you're using | ||
5083 | bit32, | ||
5084 | // input/output library | ||
5085 | io, | ||
5086 | // LuaJIT only | ||
5087 | ffi, | ||
5088 | // LuaJIT only | ||
5089 | jit, | ||
5090 | // library for handling utf8: new to Lua | ||
5091 | utf8, | ||
5092 | // do not use | ||
5093 | count | ||
5094 | }; | ||
5095 | |||
5096 | enum class call_syntax { | ||
5097 | dot = 0, | ||
5098 | colon = 1 | ||
5099 | }; | ||
5100 | |||
5101 | enum class load_mode { | ||
5102 | any = 0, | ||
5103 | text = 1, | ||
5104 | binary = 2, | ||
5105 | }; | ||
5106 | |||
5107 | enum class call_status : int { | ||
5108 | ok = LUA_OK, | ||
5109 | yielded = LUA_YIELD, | ||
5110 | runtime = LUA_ERRRUN, | ||
5111 | memory = LUA_ERRMEM, | ||
5112 | handler = LUA_ERRERR, | ||
5113 | gc = LUA_ERRGCMM, | ||
5114 | syntax = LUA_ERRSYNTAX, | ||
5115 | file = LUA_ERRFILE, | ||
5116 | }; | ||
5117 | |||
5118 | enum class thread_status : int { | ||
5119 | ok = LUA_OK, | ||
5120 | yielded = LUA_YIELD, | ||
5121 | runtime = LUA_ERRRUN, | ||
5122 | memory = LUA_ERRMEM, | ||
5123 | gc = LUA_ERRGCMM, | ||
5124 | handler = LUA_ERRERR, | ||
5125 | dead = -1, | ||
5126 | }; | ||
5127 | |||
5128 | enum class load_status : int { | ||
5129 | ok = LUA_OK, | ||
5130 | syntax = LUA_ERRSYNTAX, | ||
5131 | memory = LUA_ERRMEM, | ||
5132 | gc = LUA_ERRGCMM, | ||
5133 | file = LUA_ERRFILE, | ||
5134 | }; | ||
5135 | |||
5136 | enum class type : int { | ||
5137 | none = LUA_TNONE, | ||
5138 | lua_nil = LUA_TNIL, | ||
5139 | #if !defined(SOL_NO_NIL) | ||
5140 | nil = lua_nil, | ||
5141 | #endif // Objective C/C++ Keyword that's found in OSX SDK and OBJC -- check for all forms to protect | ||
5142 | string = LUA_TSTRING, | ||
5143 | number = LUA_TNUMBER, | ||
5144 | thread = LUA_TTHREAD, | ||
5145 | boolean = LUA_TBOOLEAN, | ||
5146 | function = LUA_TFUNCTION, | ||
5147 | userdata = LUA_TUSERDATA, | ||
5148 | lightuserdata = LUA_TLIGHTUSERDATA, | ||
5149 | table = LUA_TTABLE, | ||
5150 | poly = -0xFFFF | ||
5151 | }; | ||
5152 | |||
5153 | inline const std::string& to_string(call_status c) { | ||
5154 | static const std::array<std::string, 10> names{ { | ||
5155 | "ok", | ||
5156 | "yielded", | ||
5157 | "runtime", | ||
5158 | "memory", | ||
5159 | "handler", | ||
5160 | "gc", | ||
5161 | "syntax", | ||
5162 | "file", | ||
5163 | "CRITICAL_EXCEPTION_FAILURE", | ||
5164 | "CRITICAL_INDETERMINATE_STATE_FAILURE" | ||
5165 | } }; | ||
5166 | switch (c) { | ||
5167 | case call_status::ok: | ||
5168 | return names[0]; | ||
5169 | case call_status::yielded: | ||
5170 | return names[1]; | ||
5171 | case call_status::runtime: | ||
5172 | return names[2]; | ||
5173 | case call_status::memory: | ||
5174 | return names[3]; | ||
5175 | case call_status::handler: | ||
5176 | return names[4]; | ||
5177 | case call_status::gc: | ||
5178 | return names[5]; | ||
5179 | case call_status::syntax: | ||
5180 | return names[6]; | ||
5181 | case call_status::file: | ||
5182 | return names[7]; | ||
5183 | } | ||
5184 | if (static_cast<std::ptrdiff_t>(c) == -1) { | ||
5185 | // One of the many cases where a critical exception error has occurred | ||
5186 | return names[8]; | ||
5187 | } | ||
5188 | return names[9]; | ||
5189 | } | ||
5190 | |||
5191 | inline bool is_indeterminate_call_failure(call_status c) { | ||
5192 | switch (c) { | ||
5193 | case call_status::ok: | ||
5194 | case call_status::yielded: | ||
5195 | case call_status::runtime: | ||
5196 | case call_status::memory: | ||
5197 | case call_status::handler: | ||
5198 | case call_status::gc: | ||
5199 | case call_status::syntax: | ||
5200 | case call_status::file: | ||
5201 | return false; | ||
5202 | } | ||
5203 | return true; | ||
5204 | } | ||
5205 | |||
5206 | inline const std::string& to_string(load_status c) { | ||
5207 | static const std::array<std::string, 7> names{ { | ||
5208 | "ok", | ||
5209 | "memory", | ||
5210 | "gc", | ||
5211 | "syntax", | ||
5212 | "file", | ||
5213 | "CRITICAL_EXCEPTION_FAILURE", | ||
5214 | "CRITICAL_INDETERMINATE_STATE_FAILURE" | ||
5215 | } }; | ||
5216 | switch (c) { | ||
5217 | case load_status::ok: | ||
5218 | return names[0]; | ||
5219 | case load_status::memory: | ||
5220 | return names[1]; | ||
5221 | case load_status::gc: | ||
5222 | return names[2]; | ||
5223 | case load_status::syntax: | ||
5224 | return names[3]; | ||
5225 | case load_status::file: | ||
5226 | return names[4]; | ||
5227 | } | ||
5228 | if (static_cast<int>(c) == -1) { | ||
5229 | // One of the many cases where a critical exception error has occurred | ||
5230 | return names[5]; | ||
5231 | } | ||
5232 | return names[6]; | ||
5233 | } | ||
5234 | |||
5235 | inline const std::string& to_string(load_mode c) { | ||
5236 | static const std::array<std::string, 3> names{ { | ||
5237 | "bt", | ||
5238 | "t", | ||
5239 | "b", | ||
5240 | } }; | ||
5241 | return names[static_cast<std::size_t>(c)]; | ||
5242 | } | ||
5243 | |||
5244 | enum class meta_function { | ||
5245 | construct, | ||
5246 | index, | ||
5247 | new_index, | ||
5248 | mode, | ||
5249 | call, | ||
5250 | call_function = call, | ||
5251 | metatable, | ||
5252 | to_string, | ||
5253 | length, | ||
5254 | unary_minus, | ||
5255 | addition, | ||
5256 | subtraction, | ||
5257 | multiplication, | ||
5258 | division, | ||
5259 | modulus, | ||
5260 | power_of, | ||
5261 | involution = power_of, | ||
5262 | concatenation, | ||
5263 | equal_to, | ||
5264 | less_than, | ||
5265 | less_than_or_equal_to, | ||
5266 | garbage_collect, | ||
5267 | floor_division, | ||
5268 | bitwise_left_shift, | ||
5269 | bitwise_right_shift, | ||
5270 | bitwise_not, | ||
5271 | bitwise_and, | ||
5272 | bitwise_or, | ||
5273 | bitwise_xor, | ||
5274 | pairs, | ||
5275 | ipairs, | ||
5276 | next, | ||
5277 | type, | ||
5278 | type_info, | ||
5279 | }; | ||
5280 | |||
5281 | typedef meta_function meta_method; | ||
5282 | |||
5283 | inline const std::array<std::string, 32>& meta_function_names() { | ||
5284 | static const std::array<std::string, 32> names = { { "new", | ||
5285 | "__index", | ||
5286 | "__newindex", | ||
5287 | "__mode", | ||
5288 | "__call", | ||
5289 | "__mt", | ||
5290 | "__tostring", | ||
5291 | "__len", | ||
5292 | "__unm", | ||
5293 | "__add", | ||
5294 | "__sub", | ||
5295 | "__mul", | ||
5296 | "__div", | ||
5297 | "__mod", | ||
5298 | "__pow", | ||
5299 | "__concat", | ||
5300 | "__eq", | ||
5301 | "__lt", | ||
5302 | "__le", | ||
5303 | "__gc", | ||
5304 | |||
5305 | "__idiv", | ||
5306 | "__shl", | ||
5307 | "__shr", | ||
5308 | "__bnot", | ||
5309 | "__band", | ||
5310 | "__bor", | ||
5311 | "__bxor", | ||
5312 | |||
5313 | "__pairs", | ||
5314 | "__ipairs", | ||
5315 | "next", | ||
5316 | "__type", | ||
5317 | "__typeinfo" | ||
5318 | } }; | ||
5319 | return names; | ||
5320 | } | ||
5321 | |||
5322 | inline const std::string& to_string(meta_function mf) { | ||
5323 | return meta_function_names()[static_cast<int>(mf)]; | ||
5324 | } | ||
5325 | |||
5326 | inline type type_of(lua_State* L, int index) { | ||
5327 | return static_cast<type>(lua_type(L, index)); | ||
5328 | } | ||
5329 | |||
5330 | inline std::string type_name(lua_State* L, type t) { | ||
5331 | return lua_typename(L, static_cast<int>(t)); | ||
5332 | } | ||
5333 | |||
5334 | namespace detail { | ||
5335 | template <typename T> | ||
5336 | struct is_initializer_list : std::false_type {}; | ||
5337 | |||
5338 | template <typename T> | ||
5339 | struct is_initializer_list<std::initializer_list<T>> : std::true_type {}; | ||
5340 | |||
5341 | template <typename T, typename C = void> | ||
5342 | struct is_container : std::false_type {}; | ||
5343 | |||
5344 | template <typename T> | ||
5345 | struct is_container<std::initializer_list<T>> : std::false_type {}; | ||
5346 | |||
5347 | template <typename T> | ||
5348 | struct is_container<T, std::enable_if_t<meta::is_string_like<meta::unqualified_t<T>>::value>> : std::false_type {}; | ||
5349 | |||
5350 | template <typename T> | ||
5351 | struct is_container<T, std::enable_if_t<meta::all< | ||
5352 | std::is_array<meta::unqualified_t<T>> | ||
5353 | , meta::neg<meta::any_same<std::remove_all_extents_t<meta::unqualified_t<T>>, char, wchar_t, char16_t, char32_t>> | ||
5354 | >::value | ||
5355 | >> : std::true_type {}; | ||
5356 | |||
5357 | template <typename T> | ||
5358 | struct is_container<T, std::enable_if_t<meta::all< | ||
5359 | meta::has_begin_end<meta::unqualified_t<T>> | ||
5360 | , meta::neg<is_initializer_list<meta::unqualified_t<T>>> | ||
5361 | , meta::neg<meta::is_string_like<meta::unqualified_t<T>>> | ||
5362 | >::value | ||
5363 | >> : std::true_type {}; | ||
5364 | } // namespace detail | ||
5365 | |||
5366 | template <typename T> | ||
5367 | struct is_container : detail::is_container<T> {}; | ||
5368 | |||
5369 | template <typename T> | ||
5370 | struct is_to_stringable : meta::any<meta::supports_to_string_member<meta::unqualified_t<T>>, meta::supports_adl_to_string<meta::unqualified_t<T>>, meta::supports_ostream_op<meta::unqualified_t<T>>> {}; | ||
5371 | |||
5372 | namespace detail { | ||
5373 | template <typename T, typename = void> | ||
5374 | struct lua_type_of : std::integral_constant<type, type::userdata> {}; | ||
5375 | |||
5376 | template <typename C, typename T, typename A> | ||
5377 | struct lua_type_of<std::basic_string<C, T, A>> : std::integral_constant<type, type::string> {}; | ||
5378 | |||
5379 | template <typename C, typename T> | ||
5380 | struct lua_type_of<basic_string_view<C, T>> : std::integral_constant<type, type::string> {}; | ||
5381 | |||
5382 | template <std::size_t N> | ||
5383 | struct lua_type_of<char[N]> : std::integral_constant<type, type::string> {}; | ||
5384 | |||
5385 | template <std::size_t N> | ||
5386 | struct lua_type_of<wchar_t[N]> : std::integral_constant<type, type::string> {}; | ||
5387 | |||
5388 | template <std::size_t N> | ||
5389 | struct lua_type_of<char16_t[N]> : std::integral_constant<type, type::string> {}; | ||
5390 | |||
5391 | template <std::size_t N> | ||
5392 | struct lua_type_of<char32_t[N]> : std::integral_constant<type, type::string> {}; | ||
5393 | |||
5394 | template <> | ||
5395 | struct lua_type_of<char> : std::integral_constant<type, type::string> {}; | ||
5396 | |||
5397 | template <> | ||
5398 | struct lua_type_of<wchar_t> : std::integral_constant<type, type::string> {}; | ||
5399 | |||
5400 | template <> | ||
5401 | struct lua_type_of<char16_t> : std::integral_constant<type, type::string> {}; | ||
5402 | |||
5403 | template <> | ||
5404 | struct lua_type_of<char32_t> : std::integral_constant<type, type::string> {}; | ||
5405 | |||
5406 | template <> | ||
5407 | struct lua_type_of<const char*> : std::integral_constant<type, type::string> {}; | ||
5408 | |||
5409 | template <> | ||
5410 | struct lua_type_of<const char16_t*> : std::integral_constant<type, type::string> {}; | ||
5411 | |||
5412 | template <> | ||
5413 | struct lua_type_of<const char32_t*> : std::integral_constant<type, type::string> {}; | ||
5414 | |||
5415 | template <> | ||
5416 | struct lua_type_of<bool> : std::integral_constant<type, type::boolean> {}; | ||
5417 | |||
5418 | template <> | ||
5419 | struct lua_type_of<lua_nil_t> : std::integral_constant<type, type::lua_nil> {}; | ||
5420 | |||
5421 | template <> | ||
5422 | struct lua_type_of<nullopt_t> : std::integral_constant<type, type::lua_nil> {}; | ||
5423 | |||
5424 | template <> | ||
5425 | struct lua_type_of<std::nullptr_t> : std::integral_constant<type, type::lua_nil> {}; | ||
5426 | |||
5427 | template <> | ||
5428 | struct lua_type_of<error> : std::integral_constant<type, type::string> {}; | ||
5429 | |||
5430 | template <bool b, typename Base> | ||
5431 | struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> {}; | ||
5432 | |||
5433 | template <> | ||
5434 | struct lua_type_of<metatable_t> : std::integral_constant<type, type::table> {}; | ||
5435 | |||
5436 | template <typename B> | ||
5437 | struct lua_type_of<basic_environment<B>> : std::integral_constant<type, type::poly> {}; | ||
5438 | |||
5439 | template <> | ||
5440 | struct lua_type_of<env_t> : std::integral_constant<type, type::poly> {}; | ||
5441 | |||
5442 | template <> | ||
5443 | struct lua_type_of<new_table> : std::integral_constant<type, type::table> {}; | ||
5444 | |||
5445 | template <typename T> | ||
5446 | struct lua_type_of<as_table_t<T>> : std::integral_constant<type, type::table> {}; | ||
5447 | |||
5448 | template <typename T> | ||
5449 | struct lua_type_of<std::initializer_list<T>> : std::integral_constant<type, type::table> {}; | ||
5450 | |||
5451 | template <bool b> | ||
5452 | struct lua_type_of<basic_reference<b>> : std::integral_constant<type, type::poly> {}; | ||
5453 | |||
5454 | template <> | ||
5455 | struct lua_type_of<stack_reference> : std::integral_constant<type, type::poly> {}; | ||
5456 | |||
5457 | template <typename Base> | ||
5458 | struct lua_type_of<basic_object<Base>> : std::integral_constant<type, type::poly> {}; | ||
5459 | |||
5460 | template <typename... Args> | ||
5461 | struct lua_type_of<std::tuple<Args...>> : std::integral_constant<type, type::poly> {}; | ||
5462 | |||
5463 | template <typename A, typename B> | ||
5464 | struct lua_type_of<std::pair<A, B>> : std::integral_constant<type, type::poly> {}; | ||
5465 | |||
5466 | template <> | ||
5467 | struct lua_type_of<void*> : std::integral_constant<type, type::lightuserdata> {}; | ||
5468 | |||
5469 | template <> | ||
5470 | struct lua_type_of<lightuserdata_value> : std::integral_constant<type, type::lightuserdata> {}; | ||
5471 | |||
5472 | template <> | ||
5473 | struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {}; | ||
5474 | |||
5475 | template <typename T> | ||
5476 | struct lua_type_of<light<T>> : std::integral_constant<type, type::lightuserdata> {}; | ||
5477 | |||
5478 | template <typename T> | ||
5479 | struct lua_type_of<user<T>> : std::integral_constant<type, type::userdata> {}; | ||
5480 | |||
5481 | template <typename Base> | ||
5482 | struct lua_type_of<basic_lightuserdata<Base>> : std::integral_constant<type, type::lightuserdata> {}; | ||
5483 | |||
5484 | template <typename Base> | ||
5485 | struct lua_type_of<basic_userdata<Base>> : std::integral_constant<type, type::userdata> {}; | ||
5486 | |||
5487 | template <> | ||
5488 | struct lua_type_of<lua_CFunction> : std::integral_constant<type, type::function> {}; | ||
5489 | |||
5490 | template <> | ||
5491 | struct lua_type_of<std::remove_pointer_t<lua_CFunction>> : std::integral_constant<type, type::function> {}; | ||
5492 | |||
5493 | template <typename Base, bool aligned> | ||
5494 | struct lua_type_of<basic_function<Base, aligned>> : std::integral_constant<type, type::function> {}; | ||
5495 | |||
5496 | template <typename Base, bool aligned, typename Handler> | ||
5497 | struct lua_type_of<basic_protected_function<Base, aligned, Handler>> : std::integral_constant<type, type::function> {}; | ||
5498 | |||
5499 | template <typename Base> | ||
5500 | struct lua_type_of<basic_coroutine<Base>> : std::integral_constant<type, type::function> {}; | ||
5501 | |||
5502 | template <typename Base> | ||
5503 | struct lua_type_of<basic_thread<Base>> : std::integral_constant<type, type::thread> {}; | ||
5504 | |||
5505 | template <typename Signature> | ||
5506 | struct lua_type_of<std::function<Signature>> : std::integral_constant<type, type::function> {}; | ||
5507 | |||
5508 | template <typename T> | ||
5509 | struct lua_type_of<optional<T>> : std::integral_constant<type, type::poly> {}; | ||
5510 | |||
5511 | template <> | ||
5512 | struct lua_type_of<variadic_args> : std::integral_constant<type, type::poly> {}; | ||
5513 | |||
5514 | template <> | ||
5515 | struct lua_type_of<variadic_results> : std::integral_constant<type, type::poly> {}; | ||
5516 | |||
5517 | template <> | ||
5518 | struct lua_type_of<stack_count> : std::integral_constant<type, type::poly> {}; | ||
5519 | |||
5520 | template <> | ||
5521 | struct lua_type_of<this_state> : std::integral_constant<type, type::poly> {}; | ||
5522 | |||
5523 | template <> | ||
5524 | struct lua_type_of<this_main_state> : std::integral_constant<type, type::poly> {}; | ||
5525 | |||
5526 | template <> | ||
5527 | struct lua_type_of<this_environment> : std::integral_constant<type, type::poly> {}; | ||
5528 | |||
5529 | template <> | ||
5530 | struct lua_type_of<type> : std::integral_constant<type, type::poly> {}; | ||
5531 | |||
5532 | template <typename T> | ||
5533 | struct lua_type_of<T*> : std::integral_constant<type, type::userdata> {}; | ||
5534 | |||
5535 | template <typename T> | ||
5536 | struct lua_type_of<T, std::enable_if_t<std::is_arithmetic<T>::value>> : std::integral_constant<type, type::number> {}; | ||
5537 | |||
5538 | template <typename T> | ||
5539 | struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {}; | ||
5540 | |||
5541 | template <> | ||
5542 | struct lua_type_of<meta_function> : std::integral_constant<type, type::string> {}; | ||
5543 | |||
5544 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
5545 | #ifdef SOL_STD_VARIANT | ||
5546 | template <typename... Tn> | ||
5547 | struct lua_type_of<std::variant<Tn...>> : std::integral_constant<type, type::poly> {}; | ||
5548 | #endif // SOL_STD_VARIANT | ||
5549 | #endif // SOL_CXX17_FEATURES | ||
5550 | |||
5551 | template <typename T> | ||
5552 | struct lua_type_of<nested<T>, std::enable_if_t<::sol::is_container<T>::value>> : std::integral_constant<type, type::table> {}; | ||
5553 | |||
5554 | template <typename T> | ||
5555 | struct lua_type_of<nested<T>, std::enable_if_t<!::sol::is_container<T>::value>> : lua_type_of<T> {}; | ||
5556 | |||
5557 | template <typename C, C v, template <typename...> class V, typename... Args> | ||
5558 | struct accumulate : std::integral_constant<C, v> {}; | ||
5559 | |||
5560 | template <typename C, C v, template <typename...> class V, typename T, typename... Args> | ||
5561 | struct accumulate<C, v, V, T, Args...> : accumulate<C, v + V<T>::value, V, Args...> {}; | ||
5562 | } // namespace detail | ||
5563 | |||
5564 | template <typename T> | ||
5565 | struct is_unique_usertype : std::integral_constant<bool, unique_usertype_traits<T>::value> {}; | ||
5566 | |||
5567 | template <typename T> | ||
5568 | struct lua_type_of : detail::lua_type_of<T> { | ||
5569 | typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; | ||
5570 | }; | ||
5571 | |||
5572 | template <typename T> | ||
5573 | struct lua_size : std::integral_constant<int, 1> { | ||
5574 | typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; | ||
5575 | }; | ||
5576 | |||
5577 | template <typename A, typename B> | ||
5578 | struct lua_size<std::pair<A, B>> : std::integral_constant<int, lua_size<A>::value + lua_size<B>::value> {}; | ||
5579 | |||
5580 | template <typename... Args> | ||
5581 | struct lua_size<std::tuple<Args...>> : std::integral_constant<int, detail::accumulate<int, 0, lua_size, Args...>::value> {}; | ||
5582 | |||
5583 | namespace detail { | ||
5584 | template <typename...> | ||
5585 | struct void_ { typedef void type; }; | ||
5586 | template <typename T, typename = void> | ||
5587 | struct has_internal_marker_impl : std::false_type {}; | ||
5588 | template <typename T> | ||
5589 | struct has_internal_marker_impl<T, typename void_<typename T::SOL_INTERNAL_UNSPECIALIZED_MARKER_>::type> : std::true_type {}; | ||
5590 | |||
5591 | template <typename T> | ||
5592 | struct has_internal_marker : has_internal_marker_impl<T> {}; | ||
5593 | } // namespace detail | ||
5594 | |||
5595 | template <typename T> | ||
5596 | struct is_lua_primitive : std::integral_constant<bool, | ||
5597 | type::userdata != lua_type_of<meta::unqualified_t<T>>::value | ||
5598 | || ((type::userdata == lua_type_of<meta::unqualified_t<T>>::value) | ||
5599 | && detail::has_internal_marker<lua_type_of<meta::unqualified_t<T>>>::value | ||
5600 | && !detail::has_internal_marker<lua_size<meta::unqualified_t<T>>>::value) | ||
5601 | || std::is_base_of<reference, meta::unqualified_t<T>>::value | ||
5602 | || std::is_base_of<main_reference, meta::unqualified_t<T>>::value | ||
5603 | || std::is_base_of<stack_reference, meta::unqualified_t<T>>::value | ||
5604 | || meta::is_specialization_of<meta::unqualified_t<T>, std::tuple>::value | ||
5605 | || meta::is_specialization_of<meta::unqualified_t<T>, std::pair>::value> {}; | ||
5606 | |||
5607 | template <typename T> | ||
5608 | struct is_lua_reference : std::integral_constant<bool, | ||
5609 | std::is_base_of<reference, meta::unqualified_t<T>>::value | ||
5610 | || std::is_base_of<main_reference, meta::unqualified_t<T>>::value | ||
5611 | || std::is_base_of<stack_reference, meta::unqualified_t<T>>::value> {}; | ||
5612 | |||
5613 | template <typename T> | ||
5614 | struct is_lua_reference_or_proxy : std::integral_constant<bool, | ||
5615 | is_lua_reference<meta::unqualified_t<T>>::value | ||
5616 | || meta::is_specialization_of<meta::unqualified_t<T>, proxy>::value> {}; | ||
5617 | |||
5618 | template <typename T> | ||
5619 | struct is_main_threaded : std::is_base_of<main_reference, T> {}; | ||
5620 | |||
5621 | template <typename T> | ||
5622 | struct is_stack_based : std::is_base_of<stack_reference, T> {}; | ||
5623 | template <> | ||
5624 | struct is_stack_based<variadic_args> : std::true_type {}; | ||
5625 | template <> | ||
5626 | struct is_stack_based<unsafe_function_result> : std::true_type {}; | ||
5627 | template <> | ||
5628 | struct is_stack_based<protected_function_result> : std::true_type {}; | ||
5629 | template <> | ||
5630 | struct is_stack_based<stack_proxy> : std::true_type {}; | ||
5631 | template <> | ||
5632 | struct is_stack_based<stack_proxy_base> : std::true_type {}; | ||
5633 | |||
5634 | template <typename T> | ||
5635 | struct is_lua_primitive<T*> : std::true_type {}; | ||
5636 | template <> | ||
5637 | struct is_lua_primitive<unsafe_function_result> : std::true_type {}; | ||
5638 | template <> | ||
5639 | struct is_lua_primitive<protected_function_result> : std::true_type {}; | ||
5640 | template <typename T> | ||
5641 | struct is_lua_primitive<std::reference_wrapper<T>> : std::true_type {}; | ||
5642 | template <typename T> | ||
5643 | struct is_lua_primitive<user<T>> : std::true_type {}; | ||
5644 | template <typename T> | ||
5645 | struct is_lua_primitive<light<T>> : is_lua_primitive<T*> {}; | ||
5646 | template <typename T> | ||
5647 | struct is_lua_primitive<optional<T>> : std::true_type {}; | ||
5648 | template <typename T> | ||
5649 | struct is_lua_primitive<as_table_t<T>> : std::true_type {}; | ||
5650 | template <typename T> | ||
5651 | struct is_lua_primitive<nested<T>> : std::true_type {}; | ||
5652 | template <> | ||
5653 | struct is_lua_primitive<userdata_value> : std::true_type {}; | ||
5654 | template <> | ||
5655 | struct is_lua_primitive<lightuserdata_value> : std::true_type {}; | ||
5656 | template <typename T> | ||
5657 | struct is_lua_primitive<non_null<T>> : is_lua_primitive<T*> {}; | ||
5658 | |||
5659 | template <typename T> | ||
5660 | struct is_proxy_primitive : is_lua_primitive<T> {}; | ||
5661 | |||
5662 | template <typename T> | ||
5663 | struct is_transparent_argument : std::false_type {}; | ||
5664 | template <> | ||
5665 | struct is_transparent_argument<this_state> : std::true_type {}; | ||
5666 | template <> | ||
5667 | struct is_transparent_argument<this_main_state> : std::true_type {}; | ||
5668 | template <> | ||
5669 | struct is_transparent_argument<this_environment> : std::true_type {}; | ||
5670 | template <> | ||
5671 | struct is_transparent_argument<variadic_args> : std::true_type {}; | ||
5672 | template <typename T> | ||
5673 | struct is_variadic_arguments : std::is_same<meta::unqualified_t<T>, variadic_args> {}; | ||
5674 | |||
5675 | template <typename T> | ||
5676 | struct is_lua_index : std::is_integral<T> {}; | ||
5677 | template <> | ||
5678 | struct is_lua_index<raw_index> : std::true_type {}; | ||
5679 | template <> | ||
5680 | struct is_lua_index<absolute_index> : std::true_type {}; | ||
5681 | template <> | ||
5682 | struct is_lua_index<ref_index> : std::true_type {}; | ||
5683 | template <> | ||
5684 | struct is_lua_index<upvalue_index> : std::true_type {}; | ||
5685 | |||
5686 | template <typename Signature> | ||
5687 | struct lua_bind_traits : meta::bind_traits<Signature> { | ||
5688 | private: | ||
5689 | typedef meta::bind_traits<Signature> base_t; | ||
5690 | |||
5691 | public: | ||
5692 | typedef std::integral_constant<bool, meta::count_for<is_variadic_arguments, typename base_t::args_list>::value != 0> runtime_variadics_t; | ||
5693 | static const std::size_t true_arity = base_t::arity; | ||
5694 | static const std::size_t arity = base_t::arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value; | ||
5695 | static const std::size_t true_free_arity = base_t::free_arity; | ||
5696 | static const std::size_t free_arity = base_t::free_arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value; | ||
5697 | }; | ||
5698 | |||
5699 | template <typename T> | ||
5700 | struct is_table : std::false_type {}; | ||
5701 | template <bool x, typename T> | ||
5702 | struct is_table<basic_table_core<x, T>> : std::true_type {}; | ||
5703 | |||
5704 | template <typename T> | ||
5705 | struct is_function : std::false_type {}; | ||
5706 | template <typename T, bool aligned> | ||
5707 | struct is_function<basic_function<T, aligned>> : std::true_type {}; | ||
5708 | template <typename T, bool aligned, typename Handler> | ||
5709 | struct is_function<basic_protected_function<T, aligned, Handler>> : std::true_type {}; | ||
5710 | |||
5711 | template <typename T> | ||
5712 | struct is_lightuserdata : std::false_type {}; | ||
5713 | template <typename T> | ||
5714 | struct is_lightuserdata<basic_lightuserdata<T>> : std::true_type {}; | ||
5715 | |||
5716 | template <typename T> | ||
5717 | struct is_userdata : std::false_type {}; | ||
5718 | template <typename T> | ||
5719 | struct is_userdata<basic_userdata<T>> : std::true_type {}; | ||
5720 | |||
5721 | template <typename T> | ||
5722 | struct is_environment : std::integral_constant<bool, is_userdata<T>::value || is_table<T>::value> {}; | ||
5723 | |||
5724 | template <typename T> | ||
5725 | struct is_automagical : std::true_type {}; | ||
5726 | |||
5727 | template <typename T> | ||
5728 | inline type type_of() { | ||
5729 | return lua_type_of<meta::unqualified_t<T>>::value; | ||
5730 | } | ||
5731 | |||
5732 | namespace detail { | ||
5733 | template <typename T> | ||
5734 | struct is_non_factory_constructor : std::false_type {}; | ||
5735 | |||
5736 | template <typename... Args> | ||
5737 | struct is_non_factory_constructor<constructors<Args...>> : std::true_type {}; | ||
5738 | |||
5739 | template <typename... Args> | ||
5740 | struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type {}; | ||
5741 | |||
5742 | template <> | ||
5743 | struct is_non_factory_constructor<no_construction> : std::true_type {}; | ||
5744 | |||
5745 | template <typename T> | ||
5746 | struct is_constructor : is_non_factory_constructor<T> {}; | ||
5747 | |||
5748 | template <typename... Args> | ||
5749 | struct is_constructor<factory_wrapper<Args...>> : std::true_type {}; | ||
5750 | |||
5751 | template <typename T> | ||
5752 | struct is_constructor<protect_t<T>> : is_constructor<meta::unqualified_t<T>> {}; | ||
5753 | |||
5754 | template <typename F, typename... Filters> | ||
5755 | struct is_constructor<filter_wrapper<F, Filters...>> : is_constructor<meta::unqualified_t<F>> {}; | ||
5756 | |||
5757 | template <typename... Args> | ||
5758 | using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>; | ||
5759 | |||
5760 | template <typename T> | ||
5761 | struct is_destructor : std::false_type {}; | ||
5762 | |||
5763 | template <typename Fx> | ||
5764 | struct is_destructor<destructor_wrapper<Fx>> : std::true_type {}; | ||
5765 | |||
5766 | template <typename... Args> | ||
5767 | using has_destructor = meta::any<is_destructor<meta::unqualified_t<Args>>...>; | ||
5768 | |||
5769 | struct add_destructor_tag {}; | ||
5770 | struct check_destructor_tag {}; | ||
5771 | struct verified_tag { | ||
5772 | } const verified{}; | ||
5773 | } // namespace detail | ||
5774 | } // namespace sol | ||
5775 | |||
5776 | // end of sol/types.hpp | ||
5777 | |||
5778 | #include <exception> | ||
5779 | #include <cstring> | ||
5780 | |||
5781 | #ifdef SOL_PRINT_ERRORS | ||
5782 | #include <iostream> | ||
5783 | #endif | ||
5784 | |||
5785 | namespace sol { | ||
5786 | // must push a single object to be the error object | ||
5787 | // NOTE: the VAST MAJORITY of all Lua libraries -- C or otherwise -- expect a string for the type of error | ||
5788 | // break this convention at your own risk | ||
5789 | using exception_handler_function = int(*)(lua_State*, optional<const std::exception&>, string_view); | ||
5790 | |||
5791 | namespace detail { | ||
5792 | inline const char(&default_exception_handler_name())[11]{ | ||
5793 | static const char name[11] = "sol.\xE2\x98\xA2\xE2\x98\xA2"; | ||
5794 | return name; | ||
5795 | } | ||
5796 | |||
5797 | // must push at least 1 object on the stack | ||
5798 | inline int default_exception_handler(lua_State* L, optional<const std::exception&>, string_view what) { | ||
5799 | #ifdef SOL_PRINT_ERRORS | ||
5800 | std::cerr << "[sol2] An exception occurred: "; | ||
5801 | std::cerr.write(what.data(), what.size()); | ||
5802 | std::cerr << std::endl; | ||
5803 | #endif | ||
5804 | lua_pushlstring(L, what.data(), what.size()); | ||
5805 | return 1; | ||
5806 | } | ||
5807 | |||
5808 | inline int call_exception_handler(lua_State* L, optional<const std::exception&> maybe_ex, string_view what) { | ||
5809 | lua_getglobal(L, default_exception_handler_name()); | ||
5810 | type t = static_cast<type>(lua_type(L, -1)); | ||
5811 | if (t != type::lightuserdata) { | ||
5812 | lua_pop(L, 1); | ||
5813 | return default_exception_handler(L, std::move(maybe_ex), std::move(what)); | ||
5814 | } | ||
5815 | void* vfunc = lua_touserdata(L, -1); | ||
5816 | lua_pop(L, 1); | ||
5817 | if (vfunc == nullptr) { | ||
5818 | return default_exception_handler(L, std::move(maybe_ex), std::move(what)); | ||
5819 | } | ||
5820 | exception_handler_function exfunc = reinterpret_cast<exception_handler_function>(vfunc); | ||
5821 | return exfunc(L, std::move(maybe_ex), std::move(what)); | ||
5822 | } | ||
5823 | |||
5824 | #ifdef SOL_NO_EXCEPTIONS | ||
5825 | template <lua_CFunction f> | ||
5826 | int static_trampoline(lua_State* L) noexcept { | ||
5827 | return f(L); | ||
5828 | } | ||
5829 | |||
5830 | #ifdef SOL_NOEXCEPT_FUNCTION_TYPE | ||
5831 | template <lua_CFunction_noexcept f> | ||
5832 | int static_trampoline_noexcept(lua_State* L) noexcept { | ||
5833 | return f(L); | ||
5834 | } | ||
5835 | #else | ||
5836 | template <lua_CFunction f> | ||
5837 | int static_trampoline_noexcept(lua_State* L) noexcept { | ||
5838 | return f(L); | ||
5839 | } | ||
5840 | #endif | ||
5841 | |||
5842 | template <typename Fx, typename... Args> | ||
5843 | int trampoline(lua_State* L, Fx&& f, Args&&... args) noexcept { | ||
5844 | return f(L, std::forward<Args>(args)...); | ||
5845 | } | ||
5846 | |||
5847 | inline int c_trampoline(lua_State* L, lua_CFunction f) noexcept { | ||
5848 | return trampoline(L, f); | ||
5849 | } | ||
5850 | #else | ||
5851 | template <lua_CFunction f> | ||
5852 | int static_trampoline(lua_State* L) { | ||
5853 | #if defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) && !defined(SOL_LUAJIT) | ||
5854 | return f(L); | ||
5855 | |||
5856 | #else | ||
5857 | try { | ||
5858 | return f(L); | ||
5859 | } | ||
5860 | catch (const char* cs) { | ||
5861 | call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(cs)); | ||
5862 | } | ||
5863 | catch (const std::string& s) { | ||
5864 | call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(s.c_str(), s.size())); | ||
5865 | } | ||
5866 | catch (const std::exception& e) { | ||
5867 | call_exception_handler(L, optional<const std::exception&>(e), e.what()); | ||
5868 | } | ||
5869 | #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) | ||
5870 | // LuaJIT cannot have the catchall when the safe propagation is on | ||
5871 | // but LuaJIT will swallow all C++ errors | ||
5872 | // if we don't at least catch std::exception ones | ||
5873 | catch (...) { | ||
5874 | call_exception_handler(L, optional<const std::exception&>(nullopt), "caught (...) exception"); | ||
5875 | } | ||
5876 | #endif // LuaJIT cannot have the catchall, but we must catch std::exceps for it | ||
5877 | return lua_error(L); | ||
5878 | #endif // Safe exceptions | ||
5879 | } | ||
5880 | |||
5881 | #ifdef SOL_NOEXCEPT_FUNCTION_TYPE | ||
5882 | #if 0 | ||
5883 | // impossible: g++/clang++ choke as they think this function is ambiguous: | ||
5884 | // to fix, wait for template <auto X> and then switch on no-exceptness of the function | ||
5885 | template <lua_CFunction_noexcept f> | ||
5886 | int static_trampoline(lua_State* L) noexcept { | ||
5887 | return f(L); | ||
5888 | } | ||
5889 | #else | ||
5890 | template <lua_CFunction_noexcept f> | ||
5891 | int static_trampoline_noexcept(lua_State* L) noexcept { | ||
5892 | return f(L); | ||
5893 | } | ||
5894 | #endif // impossible | ||
5895 | |||
5896 | #else | ||
5897 | template <lua_CFunction f> | ||
5898 | int static_trampoline_noexcept(lua_State* L) noexcept { | ||
5899 | return f(L); | ||
5900 | } | ||
5901 | #endif // noexcept lua_CFunction type | ||
5902 | |||
5903 | template <typename Fx, typename... Args> | ||
5904 | int trampoline(lua_State* L, Fx&& f, Args&&... args) { | ||
5905 | if (meta::bind_traits<meta::unqualified_t<Fx>>::is_noexcept) { | ||
5906 | return f(L, std::forward<Args>(args)...); | ||
5907 | } | ||
5908 | #if defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) && !defined(SOL_LUAJIT) | ||
5909 | return f(L, std::forward<Args>(args)...); | ||
5910 | #else | ||
5911 | try { | ||
5912 | return f(L, std::forward<Args>(args)...); | ||
5913 | } | ||
5914 | catch (const char* cs) { | ||
5915 | call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(cs)); | ||
5916 | } | ||
5917 | catch (const std::string& s) { | ||
5918 | call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(s.c_str(), s.size())); | ||
5919 | } | ||
5920 | catch (const std::exception& e) { | ||
5921 | call_exception_handler(L, optional<const std::exception&>(e), e.what()); | ||
5922 | } | ||
5923 | #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) | ||
5924 | // LuaJIT cannot have the catchall when the safe propagation is on | ||
5925 | // but LuaJIT will swallow all C++ errors | ||
5926 | // if we don't at least catch std::exception ones | ||
5927 | catch (...) { | ||
5928 | call_exception_handler(L, optional<const std::exception&>(nullopt), "caught (...) exception"); | ||
5929 | } | ||
5930 | #endif | ||
5931 | return lua_error(L); | ||
5932 | #endif | ||
5933 | } | ||
5934 | |||
5935 | inline int c_trampoline(lua_State* L, lua_CFunction f) { | ||
5936 | return trampoline(L, f); | ||
5937 | } | ||
5938 | #endif // Exceptions vs. No Exceptions | ||
5939 | |||
5940 | template <typename F, F fx> | ||
5941 | inline int typed_static_trampoline_raw(std::true_type, lua_State* L) { | ||
5942 | return static_trampoline_noexcept<fx>(L); | ||
5943 | } | ||
5944 | |||
5945 | template <typename F, F fx> | ||
5946 | inline int typed_static_trampoline_raw(std::false_type, lua_State* L) { | ||
5947 | return static_trampoline<fx>(L); | ||
5948 | } | ||
5949 | |||
5950 | template <typename F, F fx> | ||
5951 | inline int typed_static_trampoline(lua_State* L) { | ||
5952 | return typed_static_trampoline_raw<F, fx>(std::integral_constant<bool, meta::bind_traits<F>::is_noexcept>(), L); | ||
5953 | } | ||
5954 | } // namespace detail | ||
5955 | |||
5956 | inline void set_default_exception_handler(lua_State* L, exception_handler_function exf = &detail::default_exception_handler) { | ||
5957 | static_assert(sizeof(void*) >= sizeof(exception_handler_function), "void* storage is too small to transport the exception handler: please file a bug on the issue tracker"); | ||
5958 | void* storage; | ||
5959 | std::memcpy(&storage, &exf, sizeof(exception_handler_function)); | ||
5960 | lua_pushlightuserdata(L, storage); | ||
5961 | lua_setglobal(L, detail::default_exception_handler_name()); | ||
5962 | } | ||
5963 | } // sol | ||
5964 | |||
5965 | // end of sol/trampoline.hpp | ||
5966 | |||
5967 | // beginning of sol/stack_core.hpp | ||
5968 | |||
5969 | // beginning of sol/error_handler.hpp | ||
5970 | |||
5971 | // beginning of sol/demangle.hpp | ||
5972 | |||
5973 | #include <cctype> | ||
5974 | #if defined(__GNUC__) && defined(__MINGW32__) && (__GNUC__ < 6) | ||
5975 | extern "C" { | ||
5976 | } | ||
5977 | #endif // MinGW is on some stuff | ||
5978 | #include <locale> | ||
5979 | |||
5980 | namespace sol { | ||
5981 | namespace detail { | ||
5982 | #if defined(__GNUC__) || defined(__clang__) | ||
5983 | template <typename T, class seperator_mark = int> | ||
5984 | inline std::string ctti_get_type_name() { | ||
5985 | // cardinal sins from MINGW | ||
5986 | using namespace std; | ||
5987 | static const std::array<std::string, 2> removals = {{"{anonymous}", "(anonymous namespace)"}}; | ||
5988 | std::string name = __PRETTY_FUNCTION__; | ||
5989 | std::size_t start = name.find_first_of('['); | ||
5990 | start = name.find_first_of('=', start); | ||
5991 | std::size_t end = name.find_last_of(']'); | ||
5992 | if (end == std::string::npos) | ||
5993 | end = name.size(); | ||
5994 | if (start == std::string::npos) | ||
5995 | start = 0; | ||
5996 | if (start < name.size() - 1) | ||
5997 | start += 1; | ||
5998 | name = name.substr(start, end - start); | ||
5999 | start = name.rfind("seperator_mark"); | ||
6000 | if (start != std::string::npos) { | ||
6001 | name.erase(start - 2, name.length()); | ||
6002 | } | ||
6003 | while (!name.empty() && isblank(name.front())) | ||
6004 | name.erase(name.begin()); | ||
6005 | while (!name.empty() && isblank(name.back())) | ||
6006 | name.pop_back(); | ||
6007 | |||
6008 | for (std::size_t r = 0; r < removals.size(); ++r) { | ||
6009 | auto found = name.find(removals[r]); | ||
6010 | while (found != std::string::npos) { | ||
6011 | name.erase(found, removals[r].size()); | ||
6012 | found = name.find(removals[r]); | ||
6013 | } | ||
6014 | } | ||
6015 | |||
6016 | return name; | ||
6017 | } | ||
6018 | #elif defined(_MSC_VER) | ||
6019 | template <typename T> | ||
6020 | inline std::string ctti_get_type_name() { | ||
6021 | static const std::array<std::string, 7> removals = {{"public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'"}}; | ||
6022 | std::string name = __FUNCSIG__; | ||
6023 | std::size_t start = name.find("get_type_name"); | ||
6024 | if (start == std::string::npos) | ||
6025 | start = 0; | ||
6026 | else | ||
6027 | start += 13; | ||
6028 | if (start < name.size() - 1) | ||
6029 | start += 1; | ||
6030 | std::size_t end = name.find_last_of('>'); | ||
6031 | if (end == std::string::npos) | ||
6032 | end = name.size(); | ||
6033 | name = name.substr(start, end - start); | ||
6034 | if (name.find("struct", 0) == 0) | ||
6035 | name.replace(0, 6, "", 0); | ||
6036 | if (name.find("class", 0) == 0) | ||
6037 | name.replace(0, 5, "", 0); | ||
6038 | while (!name.empty() && isblank(name.front())) | ||
6039 | name.erase(name.begin()); | ||
6040 | while (!name.empty() && isblank(name.back())) | ||
6041 | name.pop_back(); | ||
6042 | |||
6043 | for (std::size_t r = 0; r < removals.size(); ++r) { | ||
6044 | auto found = name.find(removals[r]); | ||
6045 | while (found != std::string::npos) { | ||
6046 | name.erase(found, removals[r].size()); | ||
6047 | found = name.find(removals[r]); | ||
6048 | } | ||
6049 | } | ||
6050 | |||
6051 | return name; | ||
6052 | } | ||
6053 | #else | ||
6054 | #error Compiler not supported for demangling | ||
6055 | #endif // compilers | ||
6056 | |||
6057 | template <typename T> | ||
6058 | inline std::string demangle_once() { | ||
6059 | std::string realname = ctti_get_type_name<T>(); | ||
6060 | return realname; | ||
6061 | } | ||
6062 | |||
6063 | template <typename T> | ||
6064 | inline std::string short_demangle_once() { | ||
6065 | std::string realname = ctti_get_type_name<T>(); | ||
6066 | // This isn't the most complete but it'll do for now...? | ||
6067 | static const std::array<std::string, 10> ops = {{"operator<", "operator<<", "operator<<=", "operator<=", "operator>", "operator>>", "operator>>=", "operator>=", "operator->", "operator->*"}}; | ||
6068 | int level = 0; | ||
6069 | std::ptrdiff_t idx = 0; | ||
6070 | for (idx = static_cast<std::ptrdiff_t>(realname.empty() ? 0 : realname.size() - 1); idx > 0; --idx) { | ||
6071 | if (level == 0 && realname[idx] == ':') { | ||
6072 | break; | ||
6073 | } | ||
6074 | bool isleft = realname[idx] == '<'; | ||
6075 | bool isright = realname[idx] == '>'; | ||
6076 | if (!isleft && !isright) | ||
6077 | continue; | ||
6078 | bool earlybreak = false; | ||
6079 | for (const auto& op : ops) { | ||
6080 | std::size_t nisop = realname.rfind(op, idx); | ||
6081 | if (nisop == std::string::npos) | ||
6082 | continue; | ||
6083 | std::size_t nisopidx = idx - op.size() + 1; | ||
6084 | if (nisop == nisopidx) { | ||
6085 | idx = static_cast<std::ptrdiff_t>(nisopidx); | ||
6086 | earlybreak = true; | ||
6087 | } | ||
6088 | break; | ||
6089 | } | ||
6090 | if (earlybreak) { | ||
6091 | continue; | ||
6092 | } | ||
6093 | level += isleft ? -1 : 1; | ||
6094 | } | ||
6095 | if (idx > 0) { | ||
6096 | realname.erase(0, realname.length() < static_cast<std::size_t>(idx) ? realname.length() : idx + 1); | ||
6097 | } | ||
6098 | return realname; | ||
6099 | } | ||
6100 | |||
6101 | template <typename T> | ||
6102 | inline const std::string& demangle() { | ||
6103 | static const std::string d = demangle_once<T>(); | ||
6104 | return d; | ||
6105 | } | ||
6106 | |||
6107 | template <typename T> | ||
6108 | inline const std::string& short_demangle() { | ||
6109 | static const std::string d = short_demangle_once<T>(); | ||
6110 | return d; | ||
6111 | } | ||
6112 | } | ||
6113 | } // namespace sol::detail | ||
6114 | |||
6115 | // end of sol/demangle.hpp | ||
6116 | |||
6117 | namespace sol { | ||
6118 | |||
6119 | inline std::string associated_type_name(lua_State* L, int index, type t) { | ||
6120 | switch (t) { | ||
6121 | case type::poly: | ||
6122 | return "anything"; | ||
6123 | case type::userdata: | ||
6124 | { | ||
6125 | if (lua_getmetatable(L, index) == 0) { | ||
6126 | break; | ||
6127 | } | ||
6128 | lua_pushlstring(L, "__name", 6); | ||
6129 | lua_rawget(L, -2); | ||
6130 | size_t sz; | ||
6131 | const char* name = lua_tolstring(L, -1, &sz); | ||
6132 | std::string tn(name, static_cast<std::string::size_type>(sz)); | ||
6133 | lua_pop(L, 2); | ||
6134 | return name; | ||
6135 | } | ||
6136 | default: | ||
6137 | break; | ||
6138 | } | ||
6139 | return lua_typename(L, static_cast<int>(t)); | ||
6140 | } | ||
6141 | |||
6142 | inline int type_panic_string(lua_State* L, int index, type expected, type actual, const std::string& message = "") noexcept(false) { | ||
6143 | const char* err = message.empty() ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s"; | ||
6144 | std::string actualname = associated_type_name(L, index, actual); | ||
6145 | return luaL_error(L, err, index, | ||
6146 | expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)), | ||
6147 | actualname.c_str(), | ||
6148 | message.c_str()); | ||
6149 | } | ||
6150 | |||
6151 | inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) { | ||
6152 | const char* err = message == nullptr || (std::char_traits<char>::length(message) == 0) ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s"; | ||
6153 | std::string actualname = associated_type_name(L, index, actual); | ||
6154 | return luaL_error(L, err, index, | ||
6155 | expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)), | ||
6156 | actualname.c_str(), | ||
6157 | message); | ||
6158 | } | ||
6159 | |||
6160 | struct type_panic_t { | ||
6161 | int operator()(lua_State* L, int index, type expected, type actual) const noexcept(false) { | ||
6162 | return type_panic_c_str(L, index, expected, actual, nullptr); | ||
6163 | } | ||
6164 | int operator()(lua_State* L, int index, type expected, type actual, const char* message) const noexcept(false) { | ||
6165 | return type_panic_c_str(L, index, expected, actual, message); | ||
6166 | } | ||
6167 | int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { | ||
6168 | return type_panic_string(L, index, expected, actual, message); | ||
6169 | } | ||
6170 | }; | ||
6171 | |||
6172 | const type_panic_t type_panic = {}; | ||
6173 | |||
6174 | struct constructor_handler { | ||
6175 | int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { | ||
6176 | std::string str = "(type check failed in constructor)"; | ||
6177 | return type_panic_string(L, index, expected, actual, message.empty() ? str : message + " " + str); | ||
6178 | } | ||
6179 | }; | ||
6180 | |||
6181 | template <typename F = void> | ||
6182 | struct argument_handler { | ||
6183 | int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { | ||
6184 | std::string str = "(bad argument to variable or function call)"; | ||
6185 | return type_panic_string(L, index, expected, actual, message.empty() ? str : message + " " + str ); | ||
6186 | } | ||
6187 | }; | ||
6188 | |||
6189 | template <typename R, typename... Args> | ||
6190 | struct argument_handler<types<R, Args...>> { | ||
6191 | int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { | ||
6192 | std::string addendum = "(bad argument into '"; | ||
6193 | addendum += detail::demangle<R>(); | ||
6194 | addendum += "("; | ||
6195 | int marker = 0; | ||
6196 | auto action = [&addendum, &marker](const std::string& n) { | ||
6197 | if (marker > 0) { | ||
6198 | addendum += ", "; | ||
6199 | } | ||
6200 | addendum += n; | ||
6201 | ++marker; | ||
6202 | }; | ||
6203 | (void)detail::swallow{int(), (action(detail::demangle<Args>()), int())...}; | ||
6204 | addendum += ")')"; | ||
6205 | return type_panic_string(L, index, expected, actual, message.empty() ? addendum : message + " " + addendum); | ||
6206 | } | ||
6207 | }; | ||
6208 | |||
6209 | // Specify this function as the handler for lua::check if you know there's nothing wrong | ||
6210 | inline int no_panic(lua_State*, int, type, type, const char* = nullptr) noexcept { | ||
6211 | return 0; | ||
6212 | } | ||
6213 | |||
6214 | inline void type_error(lua_State* L, int expected, int actual) noexcept(false) { | ||
6215 | luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual)); | ||
6216 | } | ||
6217 | |||
6218 | inline void type_error(lua_State* L, type expected, type actual) noexcept(false) { | ||
6219 | type_error(L, static_cast<int>(expected), static_cast<int>(actual)); | ||
6220 | } | ||
6221 | |||
6222 | inline void type_assert(lua_State* L, int index, type expected, type actual) noexcept(false) { | ||
6223 | if (expected != type::poly && expected != actual) { | ||
6224 | type_panic_c_str(L, index, expected, actual, nullptr); | ||
6225 | } | ||
6226 | } | ||
6227 | |||
6228 | inline void type_assert(lua_State* L, int index, type expected) { | ||
6229 | type actual = type_of(L, index); | ||
6230 | type_assert(L, index, expected, actual); | ||
6231 | } | ||
6232 | |||
6233 | } // namespace sol | ||
6234 | |||
6235 | // end of sol/error_handler.hpp | ||
6236 | |||
6237 | // beginning of sol/reference.hpp | ||
6238 | |||
6239 | // beginning of sol/stack_reference.hpp | ||
6240 | |||
6241 | namespace sol { | ||
6242 | namespace detail { | ||
6243 | inline bool xmovable(lua_State* leftL, lua_State* rightL) { | ||
6244 | if (rightL == nullptr || leftL == nullptr || leftL == rightL) { | ||
6245 | return false; | ||
6246 | } | ||
6247 | const void* leftregistry = lua_topointer(leftL, LUA_REGISTRYINDEX); | ||
6248 | const void* rightregistry = lua_topointer(rightL, LUA_REGISTRYINDEX); | ||
6249 | return leftregistry == rightregistry; | ||
6250 | } | ||
6251 | } // namespace detail | ||
6252 | |||
6253 | class stack_reference { | ||
6254 | private: | ||
6255 | lua_State* luastate = nullptr; | ||
6256 | int index = 0; | ||
6257 | |||
6258 | protected: | ||
6259 | int registry_index() const noexcept { | ||
6260 | return LUA_NOREF; | ||
6261 | } | ||
6262 | |||
6263 | public: | ||
6264 | stack_reference() noexcept = default; | ||
6265 | stack_reference(lua_nil_t) noexcept | ||
6266 | : stack_reference(){}; | ||
6267 | stack_reference(lua_State* L, lua_nil_t) noexcept | ||
6268 | : luastate(L), index(0) { | ||
6269 | } | ||
6270 | stack_reference(lua_State* L, int i) noexcept | ||
6271 | : stack_reference(L, absolute_index(L, i)) { | ||
6272 | } | ||
6273 | stack_reference(lua_State* L, absolute_index i) noexcept | ||
6274 | : luastate(L), index(i) { | ||
6275 | } | ||
6276 | stack_reference(lua_State* L, raw_index i) noexcept | ||
6277 | : luastate(L), index(i) { | ||
6278 | } | ||
6279 | stack_reference(lua_State* L, ref_index i) noexcept = delete; | ||
6280 | stack_reference(lua_State* L, const reference& r) noexcept = delete; | ||
6281 | stack_reference(lua_State* L, const stack_reference& r) noexcept | ||
6282 | : luastate(L) { | ||
6283 | if (!r.valid()) { | ||
6284 | index = 0; | ||
6285 | return; | ||
6286 | } | ||
6287 | int i = r.stack_index(); | ||
6288 | if (detail::xmovable(lua_state(), r.lua_state())) { | ||
6289 | lua_pushvalue(r.lua_state(), r.index); | ||
6290 | lua_xmove(r.lua_state(), luastate, 1); | ||
6291 | i = absolute_index(luastate, -1); | ||
6292 | } | ||
6293 | index = i; | ||
6294 | } | ||
6295 | stack_reference(stack_reference&& o) noexcept = default; | ||
6296 | stack_reference& operator=(stack_reference&&) noexcept = default; | ||
6297 | stack_reference(const stack_reference&) noexcept = default; | ||
6298 | stack_reference& operator=(const stack_reference&) noexcept = default; | ||
6299 | |||
6300 | int push() const noexcept { | ||
6301 | return push(lua_state()); | ||
6302 | } | ||
6303 | |||
6304 | int push(lua_State* Ls) const noexcept { | ||
6305 | if (lua_state() == nullptr) { | ||
6306 | lua_pushnil(Ls); | ||
6307 | return 1; | ||
6308 | } | ||
6309 | lua_pushvalue(lua_state(), index); | ||
6310 | if (Ls != lua_state()) { | ||
6311 | lua_xmove(lua_state(), Ls, 1); | ||
6312 | } | ||
6313 | return 1; | ||
6314 | } | ||
6315 | |||
6316 | void pop() const noexcept { | ||
6317 | pop(lua_state()); | ||
6318 | } | ||
6319 | |||
6320 | void pop(lua_State* Ls, int n = 1) const noexcept { | ||
6321 | lua_pop(Ls, n); | ||
6322 | } | ||
6323 | |||
6324 | int stack_index() const noexcept { | ||
6325 | return index; | ||
6326 | } | ||
6327 | |||
6328 | type get_type() const noexcept { | ||
6329 | int result = lua_type(lua_state(), index); | ||
6330 | return static_cast<type>(result); | ||
6331 | } | ||
6332 | |||
6333 | lua_State* lua_state() const noexcept { | ||
6334 | return luastate; | ||
6335 | } | ||
6336 | |||
6337 | bool valid() const noexcept { | ||
6338 | type t = get_type(); | ||
6339 | return t != type::lua_nil && t != type::none; | ||
6340 | } | ||
6341 | }; | ||
6342 | |||
6343 | inline bool operator==(const stack_reference& l, const stack_reference& r) { | ||
6344 | return lua_compare(l.lua_state(), l.stack_index(), r.stack_index(), LUA_OPEQ) == 0; | ||
6345 | } | ||
6346 | |||
6347 | inline bool operator!=(const stack_reference& l, const stack_reference& r) { | ||
6348 | return !operator==(l, r); | ||
6349 | } | ||
6350 | |||
6351 | inline bool operator==(const stack_reference& lhs, const lua_nil_t&) { | ||
6352 | return !lhs.valid(); | ||
6353 | } | ||
6354 | |||
6355 | inline bool operator==(const lua_nil_t&, const stack_reference& rhs) { | ||
6356 | return !rhs.valid(); | ||
6357 | } | ||
6358 | |||
6359 | inline bool operator!=(const stack_reference& lhs, const lua_nil_t&) { | ||
6360 | return lhs.valid(); | ||
6361 | } | ||
6362 | |||
6363 | inline bool operator!=(const lua_nil_t&, const stack_reference& rhs) { | ||
6364 | return rhs.valid(); | ||
6365 | } | ||
6366 | } // namespace sol | ||
6367 | |||
6368 | // end of sol/stack_reference.hpp | ||
6369 | |||
6370 | namespace sol { | ||
6371 | namespace detail { | ||
6372 | inline const char (&default_main_thread_name())[9] { | ||
6373 | static const char name[9] = "sol.\xF0\x9F\x93\x8C"; | ||
6374 | return name; | ||
6375 | } | ||
6376 | } // namespace detail | ||
6377 | |||
6378 | namespace stack { | ||
6379 | inline void remove(lua_State* L, int rawindex, int count) { | ||
6380 | if (count < 1) | ||
6381 | return; | ||
6382 | int top = lua_gettop(L); | ||
6383 | if (top < 1) { | ||
6384 | return; | ||
6385 | } | ||
6386 | if (rawindex == -count || top == rawindex) { | ||
6387 | // Slice them right off the top | ||
6388 | lua_pop(L, static_cast<int>(count)); | ||
6389 | return; | ||
6390 | } | ||
6391 | |||
6392 | // Remove each item one at a time using stack operations | ||
6393 | // Probably slower, maybe, haven't benchmarked, | ||
6394 | // but necessary | ||
6395 | int index = lua_absindex(L, rawindex); | ||
6396 | if (index < 0) { | ||
6397 | index = lua_gettop(L) + (index + 1); | ||
6398 | } | ||
6399 | int last = index + count; | ||
6400 | for (int i = index; i < last; ++i) { | ||
6401 | lua_remove(L, index); | ||
6402 | } | ||
6403 | } | ||
6404 | |||
6405 | struct push_popper_at { | ||
6406 | lua_State* L; | ||
6407 | int index; | ||
6408 | int count; | ||
6409 | push_popper_at(lua_State* luastate, int index = -1, int count = 1) | ||
6410 | : L(luastate), index(index), count(count) { | ||
6411 | } | ||
6412 | ~push_popper_at() { | ||
6413 | remove(L, index, count); | ||
6414 | } | ||
6415 | }; | ||
6416 | |||
6417 | template <bool top_level> | ||
6418 | struct push_popper_n { | ||
6419 | lua_State* L; | ||
6420 | int t; | ||
6421 | push_popper_n(lua_State* luastate, int x) | ||
6422 | : L(luastate), t(x) { | ||
6423 | } | ||
6424 | push_popper_n(const push_popper_n&) = delete; | ||
6425 | push_popper_n(push_popper_n&&) = default; | ||
6426 | push_popper_n& operator=(const push_popper_n&) = delete; | ||
6427 | push_popper_n& operator=(push_popper_n&&) = default; | ||
6428 | ~push_popper_n() { | ||
6429 | lua_pop(L, t); | ||
6430 | } | ||
6431 | }; | ||
6432 | template <> | ||
6433 | struct push_popper_n<true> { | ||
6434 | push_popper_n(lua_State*, int) { | ||
6435 | } | ||
6436 | }; | ||
6437 | template <bool, typename T, typename = void> | ||
6438 | struct push_popper { | ||
6439 | T t; | ||
6440 | push_popper(T x) | ||
6441 | : t(x) { | ||
6442 | t.push(); | ||
6443 | } | ||
6444 | ~push_popper() { | ||
6445 | t.pop(); | ||
6446 | } | ||
6447 | }; | ||
6448 | template <typename T, typename C> | ||
6449 | struct push_popper<true, T, C> { | ||
6450 | push_popper(T) { | ||
6451 | } | ||
6452 | ~push_popper() { | ||
6453 | } | ||
6454 | }; | ||
6455 | template <typename T> | ||
6456 | struct push_popper<false, T, std::enable_if_t<std::is_base_of<stack_reference, meta::unqualified_t<T>>::value>> { | ||
6457 | push_popper(T) { | ||
6458 | } | ||
6459 | ~push_popper() { | ||
6460 | } | ||
6461 | }; | ||
6462 | |||
6463 | template <bool top_level = false, typename T> | ||
6464 | push_popper<top_level, T> push_pop(T&& x) { | ||
6465 | return push_popper<top_level, T>(std::forward<T>(x)); | ||
6466 | } | ||
6467 | template <typename T> | ||
6468 | push_popper_at push_pop_at(T&& x) { | ||
6469 | int c = x.push(); | ||
6470 | lua_State* L = x.lua_state(); | ||
6471 | return push_popper_at(L, lua_absindex(L, -c), c); | ||
6472 | } | ||
6473 | template <bool top_level = false> | ||
6474 | push_popper_n<top_level> pop_n(lua_State* L, int x) { | ||
6475 | return push_popper_n<top_level>(L, x); | ||
6476 | } | ||
6477 | } // namespace stack | ||
6478 | |||
6479 | inline lua_State* main_thread(lua_State* L, lua_State* backup_if_unsupported = nullptr) { | ||
6480 | #if SOL_LUA_VERSION < 502 | ||
6481 | if (L == nullptr) | ||
6482 | return backup_if_unsupported; | ||
6483 | lua_getglobal(L, detail::default_main_thread_name()); | ||
6484 | auto pp = stack::pop_n(L, 1); | ||
6485 | if (type_of(L, -1) == type::thread) { | ||
6486 | return lua_tothread(L, -1); | ||
6487 | } | ||
6488 | return backup_if_unsupported; | ||
6489 | #else | ||
6490 | if (L == nullptr) | ||
6491 | return backup_if_unsupported; | ||
6492 | lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); | ||
6493 | lua_State* Lmain = lua_tothread(L, -1); | ||
6494 | lua_pop(L, 1); | ||
6495 | return Lmain; | ||
6496 | #endif // Lua 5.2+ has the main thread getter | ||
6497 | } | ||
6498 | |||
6499 | namespace detail { | ||
6500 | struct global_tag { | ||
6501 | } const global_{}; | ||
6502 | struct no_safety_tag { | ||
6503 | } const no_safety{}; | ||
6504 | |||
6505 | template <bool b> | ||
6506 | inline lua_State* pick_main_thread(lua_State* L, lua_State* backup_if_unsupported = nullptr) { | ||
6507 | (void)L; | ||
6508 | (void)backup_if_unsupported; | ||
6509 | if (b) { | ||
6510 | return main_thread(L, backup_if_unsupported); | ||
6511 | } | ||
6512 | return L; | ||
6513 | } | ||
6514 | } // namespace detail | ||
6515 | |||
6516 | template <bool main_only = false> | ||
6517 | class basic_reference { | ||
6518 | private: | ||
6519 | template <bool o_main_only> | ||
6520 | friend class basic_reference; | ||
6521 | lua_State* luastate = nullptr; // non-owning | ||
6522 | int ref = LUA_NOREF; | ||
6523 | |||
6524 | int copy() const noexcept { | ||
6525 | if (ref == LUA_NOREF) | ||
6526 | return LUA_NOREF; | ||
6527 | push(); | ||
6528 | return luaL_ref(lua_state(), LUA_REGISTRYINDEX); | ||
6529 | } | ||
6530 | |||
6531 | template <bool r_main_only> | ||
6532 | void copy_assign(const basic_reference<r_main_only>& r) { | ||
6533 | if (valid()) { | ||
6534 | deref(); | ||
6535 | } | ||
6536 | if (r.ref == LUA_REFNIL) { | ||
6537 | luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state()); | ||
6538 | ref = LUA_REFNIL; | ||
6539 | return; | ||
6540 | } | ||
6541 | if (r.ref == LUA_NOREF) { | ||
6542 | luastate = r.luastate; | ||
6543 | ref = LUA_NOREF; | ||
6544 | return; | ||
6545 | } | ||
6546 | if (detail::xmovable(lua_state(), r.lua_state())) { | ||
6547 | r.push(lua_state()); | ||
6548 | ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); | ||
6549 | return; | ||
6550 | } | ||
6551 | luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state()); | ||
6552 | ref = r.copy(); | ||
6553 | } | ||
6554 | |||
6555 | template <bool r_main_only> | ||
6556 | void move_assign(basic_reference<r_main_only>&& r) { | ||
6557 | if (valid()) { | ||
6558 | deref(); | ||
6559 | } | ||
6560 | if (r.ref == LUA_REFNIL) { | ||
6561 | luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state()); | ||
6562 | ref = LUA_REFNIL; | ||
6563 | return; | ||
6564 | } | ||
6565 | if (r.ref == LUA_NOREF) { | ||
6566 | luastate = r.luastate; | ||
6567 | ref = LUA_NOREF; | ||
6568 | return; | ||
6569 | } | ||
6570 | if (detail::xmovable(lua_state(), r.lua_state())) { | ||
6571 | r.push(lua_state()); | ||
6572 | ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); | ||
6573 | return; | ||
6574 | } | ||
6575 | |||
6576 | luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state()); | ||
6577 | ref = r.ref; | ||
6578 | r.ref = LUA_NOREF; | ||
6579 | r.luastate = nullptr; | ||
6580 | } | ||
6581 | |||
6582 | protected: | ||
6583 | basic_reference(lua_State* L, detail::global_tag) noexcept | ||
6584 | : luastate(detail::pick_main_thread<main_only>(L, L)) { | ||
6585 | lua_pushglobaltable(lua_state()); | ||
6586 | ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); | ||
6587 | } | ||
6588 | |||
6589 | int stack_index() const noexcept { | ||
6590 | return -1; | ||
6591 | } | ||
6592 | |||
6593 | void deref() const noexcept { | ||
6594 | luaL_unref(lua_state(), LUA_REGISTRYINDEX, ref); | ||
6595 | } | ||
6596 | |||
6597 | public: | ||
6598 | basic_reference() noexcept = default; | ||
6599 | basic_reference(lua_nil_t) noexcept | ||
6600 | : basic_reference() { | ||
6601 | } | ||
6602 | basic_reference(const stack_reference& r) noexcept | ||
6603 | : basic_reference(r.lua_state(), r.stack_index()) { | ||
6604 | } | ||
6605 | basic_reference(stack_reference&& r) noexcept | ||
6606 | : basic_reference(r.lua_state(), r.stack_index()) { | ||
6607 | } | ||
6608 | template <bool r_main_only> | ||
6609 | basic_reference(lua_State* L, const basic_reference<r_main_only>& r) noexcept | ||
6610 | : luastate(detail::pick_main_thread<main_only>(L, L)) { | ||
6611 | if (r.ref == LUA_REFNIL) { | ||
6612 | ref = LUA_REFNIL; | ||
6613 | return; | ||
6614 | } | ||
6615 | if (r.ref == LUA_NOREF || lua_state() == nullptr) { | ||
6616 | ref = LUA_NOREF; | ||
6617 | return; | ||
6618 | } | ||
6619 | if (detail::xmovable(lua_state(), r.lua_state())) { | ||
6620 | r.push(lua_state()); | ||
6621 | ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); | ||
6622 | return; | ||
6623 | } | ||
6624 | ref = r.copy(); | ||
6625 | } | ||
6626 | |||
6627 | template <bool r_main_only> | ||
6628 | basic_reference(lua_State* L, basic_reference<r_main_only>&& r) noexcept | ||
6629 | : luastate(detail::pick_main_thread<main_only>(L, L)) { | ||
6630 | if (r.ref == LUA_REFNIL) { | ||
6631 | ref = LUA_REFNIL; | ||
6632 | return; | ||
6633 | } | ||
6634 | if (r.ref == LUA_NOREF || lua_state() == nullptr) { | ||
6635 | ref = LUA_NOREF; | ||
6636 | return; | ||
6637 | } | ||
6638 | if (detail::xmovable(lua_state(), r.lua_state())) { | ||
6639 | r.push(lua_state()); | ||
6640 | ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); | ||
6641 | return; | ||
6642 | } | ||
6643 | ref = r.ref; | ||
6644 | r.ref = LUA_NOREF; | ||
6645 | r.luastate = nullptr; | ||
6646 | } | ||
6647 | |||
6648 | basic_reference(lua_State* L, const stack_reference& r) noexcept | ||
6649 | : luastate(detail::pick_main_thread<main_only>(L, L)) { | ||
6650 | if (lua_state() == nullptr || r.lua_state() == nullptr || r.get_type() == type::none) { | ||
6651 | ref = LUA_NOREF; | ||
6652 | return; | ||
6653 | } | ||
6654 | if (r.get_type() == type::lua_nil) { | ||
6655 | ref = LUA_REFNIL; | ||
6656 | return; | ||
6657 | } | ||
6658 | if (lua_state() != r.lua_state() && !detail::xmovable(lua_state(), r.lua_state())) { | ||
6659 | return; | ||
6660 | } | ||
6661 | r.push(lua_state()); | ||
6662 | ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); | ||
6663 | } | ||
6664 | basic_reference(lua_State* L, int index = -1) noexcept | ||
6665 | : luastate(detail::pick_main_thread<main_only>(L, L)) { | ||
6666 | // use L to stick with that state's execution stack | ||
6667 | lua_pushvalue(L, index); | ||
6668 | ref = luaL_ref(L, LUA_REGISTRYINDEX); | ||
6669 | } | ||
6670 | basic_reference(lua_State* L, ref_index index) noexcept | ||
6671 | : luastate(detail::pick_main_thread<main_only>(L, L)) { | ||
6672 | lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, index.index); | ||
6673 | ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); | ||
6674 | } | ||
6675 | basic_reference(lua_State* L, lua_nil_t) noexcept | ||
6676 | : luastate(detail::pick_main_thread<main_only>(L, L)) { | ||
6677 | } | ||
6678 | |||
6679 | ~basic_reference() noexcept { | ||
6680 | if (lua_state() == nullptr || ref == LUA_NOREF) | ||
6681 | return; | ||
6682 | deref(); | ||
6683 | } | ||
6684 | |||
6685 | basic_reference(const basic_reference& o) noexcept | ||
6686 | : luastate(o.lua_state()), ref(o.copy()) { | ||
6687 | } | ||
6688 | |||
6689 | basic_reference(basic_reference&& o) noexcept | ||
6690 | : luastate(o.lua_state()), ref(o.ref) { | ||
6691 | o.luastate = nullptr; | ||
6692 | o.ref = LUA_NOREF; | ||
6693 | } | ||
6694 | |||
6695 | basic_reference(const basic_reference<!main_only>& o) noexcept | ||
6696 | : luastate(detail::pick_main_thread < main_only && !main_only > (o.lua_state(), o.lua_state())), ref(o.copy()) { | ||
6697 | } | ||
6698 | |||
6699 | basic_reference(basic_reference<!main_only>&& o) noexcept | ||
6700 | : luastate(detail::pick_main_thread < main_only && !main_only > (o.lua_state(), o.lua_state())), ref(o.ref) { | ||
6701 | o.luastate = nullptr; | ||
6702 | o.ref = LUA_NOREF; | ||
6703 | } | ||
6704 | |||
6705 | basic_reference& operator=(basic_reference&& r) noexcept { | ||
6706 | move_assign(std::move(r)); | ||
6707 | return *this; | ||
6708 | } | ||
6709 | |||
6710 | basic_reference& operator=(const basic_reference& r) noexcept { | ||
6711 | copy_assign(r); | ||
6712 | return *this; | ||
6713 | } | ||
6714 | |||
6715 | basic_reference& operator=(basic_reference<!main_only>&& r) noexcept { | ||
6716 | move_assign(std::move(r)); | ||
6717 | return *this; | ||
6718 | } | ||
6719 | |||
6720 | basic_reference& operator=(const basic_reference<!main_only>& r) noexcept { | ||
6721 | copy_assign(r); | ||
6722 | return *this; | ||
6723 | } | ||
6724 | |||
6725 | basic_reference& operator=(const lua_nil_t&) noexcept { | ||
6726 | if (valid()) { | ||
6727 | deref(); | ||
6728 | } | ||
6729 | luastate = nullptr; | ||
6730 | ref = LUA_NOREF; | ||
6731 | return *this; | ||
6732 | } | ||
6733 | |||
6734 | template <typename Super> | ||
6735 | basic_reference& operator=(proxy_base<Super>&& r); | ||
6736 | |||
6737 | template <typename Super> | ||
6738 | basic_reference& operator=(const proxy_base<Super>& r); | ||
6739 | |||
6740 | int push() const noexcept { | ||
6741 | return push(lua_state()); | ||
6742 | } | ||
6743 | |||
6744 | int push(lua_State* Ls) const noexcept { | ||
6745 | if (lua_state() == nullptr) { | ||
6746 | lua_pushnil(Ls); | ||
6747 | return 1; | ||
6748 | } | ||
6749 | lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, ref); | ||
6750 | if (Ls != lua_state()) { | ||
6751 | lua_xmove(lua_state(), Ls, 1); | ||
6752 | } | ||
6753 | return 1; | ||
6754 | } | ||
6755 | |||
6756 | void pop() const noexcept { | ||
6757 | pop(lua_state()); | ||
6758 | } | ||
6759 | |||
6760 | void pop(lua_State* Ls, int n = 1) const noexcept { | ||
6761 | lua_pop(Ls, n); | ||
6762 | } | ||
6763 | |||
6764 | int registry_index() const noexcept { | ||
6765 | return ref; | ||
6766 | } | ||
6767 | |||
6768 | bool valid() const noexcept { | ||
6769 | return !(ref == LUA_NOREF || ref == LUA_REFNIL); | ||
6770 | } | ||
6771 | |||
6772 | explicit operator bool() const noexcept { | ||
6773 | return valid(); | ||
6774 | } | ||
6775 | |||
6776 | type get_type() const noexcept { | ||
6777 | auto pp = stack::push_pop(*this); | ||
6778 | int result = lua_type(lua_state(), -1); | ||
6779 | return static_cast<type>(result); | ||
6780 | } | ||
6781 | |||
6782 | lua_State* lua_state() const noexcept { | ||
6783 | return luastate; | ||
6784 | } | ||
6785 | }; | ||
6786 | |||
6787 | template <bool lb, bool rb> | ||
6788 | inline bool operator==(const basic_reference<lb>& l, const basic_reference<rb>& r) { | ||
6789 | auto ppl = stack::push_pop(l); | ||
6790 | auto ppr = stack::push_pop(r); | ||
6791 | return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1; | ||
6792 | } | ||
6793 | |||
6794 | template <bool lb, bool rb> | ||
6795 | inline bool operator!=(const basic_reference<lb>& l, const basic_reference<rb>& r) { | ||
6796 | return !operator==(l, r); | ||
6797 | } | ||
6798 | |||
6799 | template <bool lb> | ||
6800 | inline bool operator==(const basic_reference<lb>& lhs, const lua_nil_t&) { | ||
6801 | return !lhs.valid(); | ||
6802 | } | ||
6803 | |||
6804 | template <bool rb> | ||
6805 | inline bool operator==(const lua_nil_t&, const basic_reference<rb>& rhs) { | ||
6806 | return !rhs.valid(); | ||
6807 | } | ||
6808 | |||
6809 | template <bool lb> | ||
6810 | inline bool operator!=(const basic_reference<lb>& lhs, const lua_nil_t&) { | ||
6811 | return lhs.valid(); | ||
6812 | } | ||
6813 | |||
6814 | template <bool rb> | ||
6815 | inline bool operator!=(const lua_nil_t&, const basic_reference<rb>& rhs) { | ||
6816 | return rhs.valid(); | ||
6817 | } | ||
6818 | } // namespace sol | ||
6819 | |||
6820 | // end of sol/reference.hpp | ||
6821 | |||
6822 | // beginning of sol/tie.hpp | ||
6823 | |||
6824 | namespace sol { | ||
6825 | |||
6826 | namespace detail { | ||
6827 | template <typename T> | ||
6828 | struct is_speshul : std::false_type {}; | ||
6829 | } // namespace detail | ||
6830 | |||
6831 | template <typename T> | ||
6832 | struct tie_size : std::tuple_size<T> {}; | ||
6833 | |||
6834 | template <typename T> | ||
6835 | struct is_tieable : std::integral_constant<bool, (::sol::tie_size<T>::value > 0)> {}; | ||
6836 | |||
6837 | template <typename... Tn> | ||
6838 | struct tie_t : public std::tuple<std::add_lvalue_reference_t<Tn>...> { | ||
6839 | private: | ||
6840 | typedef std::tuple<std::add_lvalue_reference_t<Tn>...> base_t; | ||
6841 | |||
6842 | template <typename T> | ||
6843 | void set(std::false_type, T&& target) { | ||
6844 | std::get<0>(*this) = std::forward<T>(target); | ||
6845 | } | ||
6846 | |||
6847 | template <typename T> | ||
6848 | void set(std::true_type, T&& target) { | ||
6849 | typedef tie_size<meta::unqualified_t<T>> value_size; | ||
6850 | typedef tie_size<std::tuple<Tn...>> tie_size; | ||
6851 | typedef std::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size; | ||
6852 | typedef std::make_index_sequence<indices_size::value> indices; | ||
6853 | set_extra(detail::is_speshul<meta::unqualified_t<T>>(), indices(), std::forward<T>(target)); | ||
6854 | } | ||
6855 | |||
6856 | template <std::size_t... I, typename T> | ||
6857 | void set_extra(std::true_type, std::index_sequence<I...>, T&& target) { | ||
6858 | using std::get; | ||
6859 | (void)detail::swallow{0, | ||
6860 | (get<I>(static_cast<base_t&>(*this)) = get<I>(types<Tn...>(), target), 0)..., 0}; | ||
6861 | } | ||
6862 | |||
6863 | template <std::size_t... I, typename T> | ||
6864 | void set_extra(std::false_type, std::index_sequence<I...>, T&& target) { | ||
6865 | using std::get; | ||
6866 | (void)detail::swallow{0, | ||
6867 | (get<I>(static_cast<base_t&>(*this)) = get<I>(target), 0)..., 0}; | ||
6868 | } | ||
6869 | |||
6870 | public: | ||
6871 | using base_t::base_t; | ||
6872 | |||
6873 | template <typename T> | ||
6874 | tie_t& operator=(T&& value) { | ||
6875 | typedef is_tieable<meta::unqualified_t<T>> tieable; | ||
6876 | set(tieable(), std::forward<T>(value)); | ||
6877 | return *this; | ||
6878 | } | ||
6879 | }; | ||
6880 | |||
6881 | template <typename... Tn> | ||
6882 | struct tie_size<tie_t<Tn...>> : std::tuple_size<std::tuple<Tn...>> {}; | ||
6883 | |||
6884 | namespace adl_barrier_detail { | ||
6885 | template <typename... Tn> | ||
6886 | inline tie_t<std::remove_reference_t<Tn>...> tie(Tn&&... argn) { | ||
6887 | return tie_t<std::remove_reference_t<Tn>...>(std::forward<Tn>(argn)...); | ||
6888 | } | ||
6889 | } // namespace adl_barrier_detail | ||
6890 | |||
6891 | using namespace adl_barrier_detail; | ||
6892 | |||
6893 | } // namespace sol | ||
6894 | |||
6895 | // end of sol/tie.hpp | ||
6896 | |||
6897 | // beginning of sol/stack_guard.hpp | ||
6898 | |||
6899 | namespace sol { | ||
6900 | namespace detail { | ||
6901 | inline void stack_fail(int, int) { | ||
6902 | #if !(defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS) | ||
6903 | throw error(detail::direct_error, "imbalanced stack after operation finish"); | ||
6904 | #else | ||
6905 | // Lol, what do you want, an error printout? :3c | ||
6906 | // There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so | ||
6907 | // hopefully someone will register their own stack_fail thing for the `fx` parameter of stack_guard. | ||
6908 | #endif // No Exceptions | ||
6909 | } | ||
6910 | } // namespace detail | ||
6911 | |||
6912 | struct stack_guard { | ||
6913 | lua_State* L; | ||
6914 | int top; | ||
6915 | std::function<void(int, int)> on_mismatch; | ||
6916 | |||
6917 | stack_guard(lua_State* L) | ||
6918 | : stack_guard(L, lua_gettop(L)) { | ||
6919 | } | ||
6920 | stack_guard(lua_State* L, int top, std::function<void(int, int)> fx = detail::stack_fail) | ||
6921 | : L(L), top(top), on_mismatch(std::move(fx)) { | ||
6922 | } | ||
6923 | bool check_stack(int modification = 0) const { | ||
6924 | int bottom = lua_gettop(L) + modification; | ||
6925 | if (top == bottom) { | ||
6926 | return true; | ||
6927 | } | ||
6928 | on_mismatch(top, bottom); | ||
6929 | return false; | ||
6930 | } | ||
6931 | ~stack_guard() { | ||
6932 | check_stack(); | ||
6933 | } | ||
6934 | }; | ||
6935 | } // namespace sol | ||
6936 | |||
6937 | // end of sol/stack_guard.hpp | ||
6938 | |||
6939 | #include <vector> | ||
6940 | #include <forward_list> | ||
6941 | #include <algorithm> | ||
6942 | |||
6943 | namespace sol { | ||
6944 | namespace detail { | ||
6945 | struct as_reference_tag {}; | ||
6946 | template <typename T> | ||
6947 | struct as_pointer_tag {}; | ||
6948 | template <typename T> | ||
6949 | struct as_value_tag {}; | ||
6950 | template <typename T> | ||
6951 | struct as_table_tag {}; | ||
6952 | |||
6953 | using unique_destructor = void (*)(void*); | ||
6954 | |||
6955 | inline void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space, std::size_t& required_space) { | ||
6956 | // this handels arbitrary alignments... | ||
6957 | // make this into a power-of-2-only? | ||
6958 | // actually can't: this is a C++14-compatible framework, | ||
6959 | // power of 2 alignment is C++17 | ||
6960 | std::uintptr_t initial = reinterpret_cast<std::uintptr_t>(ptr); | ||
6961 | std::uintptr_t offby = static_cast<std::uintptr_t>(initial % alignment); | ||
6962 | std::uintptr_t padding = (alignment - offby) % alignment; | ||
6963 | required_space += size + padding; | ||
6964 | if (space < required_space) { | ||
6965 | return nullptr; | ||
6966 | } | ||
6967 | ptr = static_cast<void*>(static_cast<char*>(ptr) + padding); | ||
6968 | space -= padding; | ||
6969 | return ptr; | ||
6970 | } | ||
6971 | |||
6972 | inline void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space) { | ||
6973 | std::size_t required_space = 0; | ||
6974 | return align(alignment, size, ptr, space, required_space); | ||
6975 | } | ||
6976 | |||
6977 | template <typename... Args> | ||
6978 | inline std::size_t aligned_space_for(void* alignment = nullptr) { | ||
6979 | char* start = static_cast<char*>(alignment); | ||
6980 | auto specific_align = [&alignment](std::size_t a, std::size_t s) { | ||
6981 | std::size_t space = (std::numeric_limits<std::size_t>::max)(); | ||
6982 | alignment = align(a, s, alignment, space); | ||
6983 | alignment = static_cast<void*>(static_cast<char*>(alignment) + s); | ||
6984 | }; | ||
6985 | (void)detail::swallow{ int{}, (specific_align(std::alignment_of<Args>::value, sizeof(Args)), int{})... }; | ||
6986 | return static_cast<char*>(alignment) - start; | ||
6987 | } | ||
6988 | |||
6989 | inline void* align_usertype_pointer(void* ptr) { | ||
6990 | typedef std::integral_constant<bool, | ||
6991 | #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT | ||
6992 | false | ||
6993 | #else | ||
6994 | (std::alignment_of<void*>::value > 1) | ||
6995 | #endif | ||
6996 | > | ||
6997 | use_align; | ||
6998 | if (!use_align::value) { | ||
6999 | return ptr; | ||
7000 | } | ||
7001 | std::size_t space = (std::numeric_limits<std::size_t>::max)(); | ||
7002 | return align(std::alignment_of<void*>::value, sizeof(void*), ptr, space); | ||
7003 | } | ||
7004 | |||
7005 | inline void* align_usertype_unique_destructor(void* ptr) { | ||
7006 | typedef std::integral_constant<bool, | ||
7007 | #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT | ||
7008 | false | ||
7009 | #else | ||
7010 | (std::alignment_of<unique_destructor>::value > 1) | ||
7011 | #endif | ||
7012 | > | ||
7013 | use_align; | ||
7014 | if (!use_align::value) { | ||
7015 | return static_cast<void*>(static_cast<void**>(ptr) + 1); | ||
7016 | } | ||
7017 | ptr = align_usertype_pointer(ptr); | ||
7018 | ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(void*)); | ||
7019 | std::size_t space = (std::numeric_limits<std::size_t>::max)(); | ||
7020 | return align(std::alignment_of<unique_destructor>::value, sizeof(unique_destructor), ptr, space); | ||
7021 | } | ||
7022 | |||
7023 | template <typename T, bool pre_aligned = false> | ||
7024 | inline void* align_usertype_unique(void* ptr) { | ||
7025 | typedef std::integral_constant<bool, | ||
7026 | #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT | ||
7027 | false | ||
7028 | #else | ||
7029 | (std::alignment_of<T>::value > 1) | ||
7030 | #endif | ||
7031 | > | ||
7032 | use_align; | ||
7033 | if (!pre_aligned) { | ||
7034 | ptr = align_usertype_unique_destructor(ptr); | ||
7035 | ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_destructor)); | ||
7036 | } | ||
7037 | if (!use_align::value) { | ||
7038 | return ptr; | ||
7039 | } | ||
7040 | std::size_t space = (std::numeric_limits<std::size_t>::max)(); | ||
7041 | return align(std::alignment_of<T>::value, sizeof(T), ptr, space); | ||
7042 | } | ||
7043 | |||
7044 | template <typename T> | ||
7045 | inline void* align_user(void* ptr) { | ||
7046 | typedef std::integral_constant<bool, | ||
7047 | #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT | ||
7048 | false | ||
7049 | #else | ||
7050 | (std::alignment_of<T>::value > 1) | ||
7051 | #endif | ||
7052 | > | ||
7053 | use_align; | ||
7054 | if (!use_align::value) { | ||
7055 | return ptr; | ||
7056 | } | ||
7057 | std::size_t space = (std::numeric_limits<std::size_t>::max)(); | ||
7058 | return align(std::alignment_of<T>::value, sizeof(T), ptr, space); | ||
7059 | } | ||
7060 | |||
7061 | template <typename T> | ||
7062 | inline T** usertype_allocate_pointer(lua_State* L) { | ||
7063 | typedef std::integral_constant<bool, | ||
7064 | #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT | ||
7065 | false | ||
7066 | #else | ||
7067 | (std::alignment_of<T*>::value > 1) | ||
7068 | #endif | ||
7069 | > | ||
7070 | use_align; | ||
7071 | if (!use_align::value) { | ||
7072 | T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*))); | ||
7073 | return pointerpointer; | ||
7074 | } | ||
7075 | static const std::size_t initial_size = aligned_space_for<T*>(nullptr); | ||
7076 | static const std::size_t misaligned_size = aligned_space_for<T*>(reinterpret_cast<void*>(0x1)); | ||
7077 | |||
7078 | std::size_t allocated_size = initial_size; | ||
7079 | void* unadjusted = lua_newuserdata(L, initial_size); | ||
7080 | void* adjusted = align(std::alignment_of<T*>::value, sizeof(T*), unadjusted, allocated_size); | ||
7081 | if (adjusted == nullptr) { | ||
7082 | lua_pop(L, 1); | ||
7083 | // what kind of absolute garbage trash allocator are we dealing with? | ||
7084 | // whatever, add some padding in the case of MAXIMAL alignment waste... | ||
7085 | allocated_size = misaligned_size; | ||
7086 | unadjusted = lua_newuserdata(L, allocated_size); | ||
7087 | adjusted = align(std::alignment_of<T*>::value, sizeof(T*), unadjusted, allocated_size); | ||
7088 | if (adjusted == nullptr) { | ||
7089 | // trash allocator can burn in hell | ||
7090 | lua_pop(L, 1); | ||
7091 | //luaL_error(L, "if you are the one that wrote this allocator you should feel bad for doing a worse job than malloc/realloc and should go read some books, yeah?"); | ||
7092 | luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T*>().data()); | ||
7093 | } | ||
7094 | } | ||
7095 | return static_cast<T**>(adjusted); | ||
7096 | } | ||
7097 | |||
7098 | template <typename T> | ||
7099 | inline T* usertype_allocate(lua_State* L) { | ||
7100 | typedef std::integral_constant<bool, | ||
7101 | #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT | ||
7102 | false | ||
7103 | #else | ||
7104 | (std::alignment_of<T*>::value > 1 || std::alignment_of<T>::value > 1) | ||
7105 | #endif | ||
7106 | > | ||
7107 | use_align; | ||
7108 | if (!use_align::value) { | ||
7109 | T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); | ||
7110 | T*& pointerreference = *pointerpointer; | ||
7111 | T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1); | ||
7112 | pointerreference = allocationtarget; | ||
7113 | return allocationtarget; | ||
7114 | } | ||
7115 | |||
7116 | /* the assumption is that `lua_newuserdata` -- unless someone | ||
7117 | passes a specific lua_Alloc that gives us bogus, un-aligned pointers | ||
7118 | -- uses malloc, which tends to hand out more or less aligned pointers to memory | ||
7119 | (most of the time, anyhow) | ||
7120 | |||
7121 | but it's not guaranteed, so we have to do a post-adjustment check and increase padding | ||
7122 | |||
7123 | we do this preliminarily with compile-time stuff, to see | ||
7124 | if we strike lucky with the allocator and alignment values | ||
7125 | |||
7126 | otherwise, we have to re-allocate the userdata and | ||
7127 | over-allocate some space for additional padding because | ||
7128 | compilers are optimized for aligned reads/writes | ||
7129 | (and clang will barf UBsan errors on us for not being aligned) | ||
7130 | */ | ||
7131 | static const std::size_t initial_size = aligned_space_for<T*, T>(nullptr); | ||
7132 | static const std::size_t misaligned_size = aligned_space_for<T*, T>(reinterpret_cast<void*>(0x1)); | ||
7133 | |||
7134 | void* pointer_adjusted; | ||
7135 | void* data_adjusted; | ||
7136 | auto attempt_alloc = [](lua_State* L, std::size_t allocated_size, void*& pointer_adjusted, void*& data_adjusted) -> bool { | ||
7137 | void* adjusted = lua_newuserdata(L, allocated_size); | ||
7138 | pointer_adjusted = align(std::alignment_of<T*>::value, sizeof(T*), adjusted, allocated_size); | ||
7139 | if (pointer_adjusted == nullptr) { | ||
7140 | lua_pop(L, 1); | ||
7141 | return false; | ||
7142 | } | ||
7143 | // subtract size of what we're going to allocate there | ||
7144 | allocated_size -= sizeof(T*); | ||
7145 | adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + sizeof(T*)); | ||
7146 | data_adjusted = align(std::alignment_of<T>::value, sizeof(T), adjusted, allocated_size); | ||
7147 | if (data_adjusted == nullptr) { | ||
7148 | lua_pop(L, 1); | ||
7149 | return false; | ||
7150 | } | ||
7151 | return true; | ||
7152 | }; | ||
7153 | bool result = attempt_alloc(L, initial_size, pointer_adjusted, data_adjusted); | ||
7154 | if (!result) { | ||
7155 | // we're likely to get something that fails to perform the proper allocation a second time, | ||
7156 | // so we use the suggested_new_size bump to help us out here | ||
7157 | pointer_adjusted = nullptr; | ||
7158 | data_adjusted = nullptr; | ||
7159 | result = attempt_alloc(L, misaligned_size, pointer_adjusted, data_adjusted); | ||
7160 | if (!result) { | ||
7161 | if (pointer_adjusted == nullptr) { | ||
7162 | luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str()); | ||
7163 | } | ||
7164 | else { | ||
7165 | luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str()); | ||
7166 | } | ||
7167 | return nullptr; | ||
7168 | } | ||
7169 | } | ||
7170 | |||
7171 | T** pointerpointer = reinterpret_cast<T**>(pointer_adjusted); | ||
7172 | T*& pointerreference = *pointerpointer; | ||
7173 | T* allocationtarget = reinterpret_cast<T*>(data_adjusted); | ||
7174 | pointerreference = allocationtarget; | ||
7175 | return allocationtarget; | ||
7176 | } | ||
7177 | |||
7178 | template <typename T, typename Real> | ||
7179 | inline Real* usertype_unique_allocate(lua_State* L, T**& pref, unique_destructor*& dx) { | ||
7180 | typedef std::integral_constant<bool, | ||
7181 | #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT | ||
7182 | false | ||
7183 | #else | ||
7184 | (std::alignment_of<T*>::value > 1 || std::alignment_of<unique_destructor>::value > 1 || std::alignment_of<Real>::value > 1) | ||
7185 | #endif | ||
7186 | > | ||
7187 | use_align; | ||
7188 | if (!use_align::value) { | ||
7189 | pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(detail::unique_destructor) + sizeof(Real))); | ||
7190 | dx = static_cast<detail::unique_destructor*>(static_cast<void*>(pref + 1)); | ||
7191 | Real* mem = static_cast<Real*>(static_cast<void*>(dx + 1)); | ||
7192 | return mem; | ||
7193 | } | ||
7194 | |||
7195 | static const std::size_t initial_size = aligned_space_for<T*, unique_destructor, Real>(nullptr); | ||
7196 | static const std::size_t misaligned_size = aligned_space_for<T*, unique_destructor, Real>(reinterpret_cast<void*>(0x1)); | ||
7197 | |||
7198 | void* pointer_adjusted; | ||
7199 | void* dx_adjusted; | ||
7200 | void* data_adjusted; | ||
7201 | auto attempt_alloc = [](lua_State* L, std::size_t allocated_size, void*& pointer_adjusted, void*& dx_adjusted, void*& data_adjusted) -> bool { | ||
7202 | void* adjusted = lua_newuserdata(L, allocated_size); | ||
7203 | pointer_adjusted = align(std::alignment_of<T*>::value, sizeof(T*), adjusted, allocated_size); | ||
7204 | if (pointer_adjusted == nullptr) { | ||
7205 | lua_pop(L, 1); | ||
7206 | return false; | ||
7207 | } | ||
7208 | allocated_size -= sizeof(T*); | ||
7209 | adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + sizeof(T*)); | ||
7210 | dx_adjusted = align(std::alignment_of<unique_destructor>::value, sizeof(unique_destructor), adjusted, allocated_size); | ||
7211 | if (dx_adjusted == nullptr) { | ||
7212 | lua_pop(L, 1); | ||
7213 | return false; | ||
7214 | } | ||
7215 | allocated_size -= sizeof(unique_destructor); | ||
7216 | adjusted = static_cast<void*>(static_cast<char*>(dx_adjusted) + sizeof(unique_destructor)); | ||
7217 | data_adjusted = align(std::alignment_of<Real>::value, sizeof(Real), adjusted, allocated_size); | ||
7218 | if (data_adjusted == nullptr) { | ||
7219 | lua_pop(L, 1); | ||
7220 | return false; | ||
7221 | } | ||
7222 | return true; | ||
7223 | }; | ||
7224 | bool result = attempt_alloc(L, initial_size, pointer_adjusted, dx_adjusted, data_adjusted); | ||
7225 | if (!result) { | ||
7226 | // we're likely to get something that fails to perform the proper allocation a second time, | ||
7227 | // so we use the suggested_new_size bump to help us out here | ||
7228 | pointer_adjusted = nullptr; | ||
7229 | dx_adjusted = nullptr; | ||
7230 | data_adjusted = nullptr; | ||
7231 | result = attempt_alloc(L, misaligned_size, pointer_adjusted, dx_adjusted, data_adjusted); | ||
7232 | if (!result) { | ||
7233 | if (pointer_adjusted == nullptr) { | ||
7234 | luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str()); | ||
7235 | } | ||
7236 | else if (dx_adjusted == nullptr) { | ||
7237 | luaL_error(L, "aligned allocation of userdata block (deleter section) for '%s' failed", detail::demangle<Real>().c_str()); | ||
7238 | } | ||
7239 | else { | ||
7240 | luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<Real>().c_str()); | ||
7241 | } | ||
7242 | return nullptr; | ||
7243 | } | ||
7244 | } | ||
7245 | |||
7246 | pref = static_cast<T**>(pointer_adjusted); | ||
7247 | dx = static_cast<detail::unique_destructor*>(dx_adjusted); | ||
7248 | Real* mem = static_cast<Real*>(data_adjusted); | ||
7249 | return mem; | ||
7250 | } | ||
7251 | |||
7252 | template <typename T> | ||
7253 | inline T* user_allocate(lua_State* L) { | ||
7254 | typedef std::integral_constant<bool, | ||
7255 | #if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT | ||
7256 | false | ||
7257 | #else | ||
7258 | (std::alignment_of<T>::value > 1) | ||
7259 | #endif | ||
7260 | > | ||
7261 | use_align; | ||
7262 | if (!use_align::value) { | ||
7263 | T* pointer = static_cast<T*>(lua_newuserdata(L, sizeof(T))); | ||
7264 | return pointer; | ||
7265 | } | ||
7266 | |||
7267 | static const std::size_t initial_size = aligned_space_for<T>(nullptr); | ||
7268 | static const std::size_t misaligned_size = aligned_space_for<T>(reinterpret_cast<void*>(0x1)); | ||
7269 | |||
7270 | std::size_t allocated_size = initial_size; | ||
7271 | void* unadjusted = lua_newuserdata(L, allocated_size); | ||
7272 | void* adjusted = align(std::alignment_of<T>::value, sizeof(T), unadjusted, allocated_size); | ||
7273 | if (adjusted == nullptr) { | ||
7274 | lua_pop(L, 1); | ||
7275 | // try again, add extra space for alignment padding | ||
7276 | allocated_size = misaligned_size; | ||
7277 | unadjusted = lua_newuserdata(L, allocated_size); | ||
7278 | adjusted = align(std::alignment_of<T>::value, sizeof(T), unadjusted, allocated_size); | ||
7279 | if (adjusted == nullptr) { | ||
7280 | lua_pop(L, 1); | ||
7281 | luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T>().data()); | ||
7282 | } | ||
7283 | } | ||
7284 | return static_cast<T*>(adjusted); | ||
7285 | } | ||
7286 | |||
7287 | template <typename T> | ||
7288 | inline int usertype_alloc_destruct(lua_State* L) { | ||
7289 | void* memory = lua_touserdata(L, 1); | ||
7290 | memory = align_usertype_pointer(memory); | ||
7291 | T** pdata = static_cast<T**>(memory); | ||
7292 | T* data = *pdata; | ||
7293 | std::allocator<T> alloc{}; | ||
7294 | std::allocator_traits<std::allocator<T>>::destroy(alloc, data); | ||
7295 | return 0; | ||
7296 | } | ||
7297 | |||
7298 | template <typename T> | ||
7299 | inline int unique_destruct(lua_State* L) { | ||
7300 | void* memory = lua_touserdata(L, 1); | ||
7301 | memory = align_usertype_unique_destructor(memory); | ||
7302 | unique_destructor& dx = *static_cast<unique_destructor*>(memory); | ||
7303 | memory = static_cast<void*>(static_cast<char*>(memory) + sizeof(unique_destructor)); | ||
7304 | (dx)(memory); | ||
7305 | return 0; | ||
7306 | } | ||
7307 | |||
7308 | template <typename T> | ||
7309 | inline int user_alloc_destruct(lua_State* L) { | ||
7310 | void* memory = lua_touserdata(L, 1); | ||
7311 | memory = align_user<T>(memory); | ||
7312 | T* data = static_cast<T*>(memory); | ||
7313 | std::allocator<T> alloc; | ||
7314 | std::allocator_traits<std::allocator<T>>::destroy(alloc, data); | ||
7315 | return 0; | ||
7316 | } | ||
7317 | |||
7318 | template <typename T, typename Real> | ||
7319 | inline void usertype_unique_alloc_destroy(void* memory) { | ||
7320 | memory = align_usertype_unique<Real, true>(memory); | ||
7321 | Real* target = static_cast<Real*>(memory); | ||
7322 | std::allocator<Real> alloc; | ||
7323 | std::allocator_traits<std::allocator<Real>>::destroy(alloc, target); | ||
7324 | } | ||
7325 | |||
7326 | template <typename T> | ||
7327 | inline int cannot_destruct(lua_State* L) { | ||
7328 | return luaL_error(L, "cannot call the destructor for '%s': it is either hidden (protected/private) or removed with '= delete' and thusly this type is being destroyed without properly destructing, invoking undefined behavior: please bind a usertype and specify a custom destructor to define the behavior properly", detail::demangle<T>().data()); | ||
7329 | } | ||
7330 | |||
7331 | template <typename T> | ||
7332 | void reserve(T&, std::size_t) { | ||
7333 | } | ||
7334 | |||
7335 | template <typename T, typename Al> | ||
7336 | void reserve(std::vector<T, Al>& arr, std::size_t hint) { | ||
7337 | arr.reserve(hint); | ||
7338 | } | ||
7339 | |||
7340 | template <typename T, typename Tr, typename Al> | ||
7341 | void reserve(std::basic_string<T, Tr, Al>& arr, std::size_t hint) { | ||
7342 | arr.reserve(hint); | ||
7343 | } | ||
7344 | } // namespace detail | ||
7345 | |||
7346 | namespace stack { | ||
7347 | |||
7348 | template <typename T> | ||
7349 | struct extensible {}; | ||
7350 | |||
7351 | template <typename T, bool global = false, bool raw = false, typename = void> | ||
7352 | struct field_getter; | ||
7353 | template <typename T, bool global = false, bool raw = false, typename = void> | ||
7354 | struct probe_field_getter; | ||
7355 | template <typename T, bool global = false, bool raw = false, typename = void> | ||
7356 | struct field_setter; | ||
7357 | template <typename T, typename = void> | ||
7358 | struct getter; | ||
7359 | template <typename T, typename = void> | ||
7360 | struct userdata_getter; | ||
7361 | template <typename T, typename = void> | ||
7362 | struct popper; | ||
7363 | template <typename T, typename = void> | ||
7364 | struct pusher; | ||
7365 | template <typename T, type = lua_type_of<T>::value, typename = void> | ||
7366 | struct checker; | ||
7367 | template <typename T, typename = void> | ||
7368 | struct userdata_checker; | ||
7369 | template <typename T, typename = void> | ||
7370 | struct check_getter; | ||
7371 | |||
7372 | struct probe { | ||
7373 | bool success; | ||
7374 | int levels; | ||
7375 | |||
7376 | probe(bool s, int l) | ||
7377 | : success(s), levels(l) { | ||
7378 | } | ||
7379 | |||
7380 | operator bool() const { | ||
7381 | return success; | ||
7382 | }; | ||
7383 | }; | ||
7384 | |||
7385 | struct record { | ||
7386 | int last; | ||
7387 | int used; | ||
7388 | |||
7389 | record() | ||
7390 | : last(), used() { | ||
7391 | } | ||
7392 | void use(int count) { | ||
7393 | last = count; | ||
7394 | used += count; | ||
7395 | } | ||
7396 | }; | ||
7397 | |||
7398 | namespace stack_detail { | ||
7399 | template <typename T> | ||
7400 | struct strip { | ||
7401 | typedef T type; | ||
7402 | }; | ||
7403 | template <typename T> | ||
7404 | struct strip<std::reference_wrapper<T>> { | ||
7405 | typedef T& type; | ||
7406 | }; | ||
7407 | template <typename T> | ||
7408 | struct strip<user<T>> { | ||
7409 | typedef T& type; | ||
7410 | }; | ||
7411 | template <typename T> | ||
7412 | struct strip<non_null<T>> { | ||
7413 | typedef T type; | ||
7414 | }; | ||
7415 | template <typename T> | ||
7416 | using strip_t = typename strip<T>::type; | ||
7417 | |||
7418 | template <typename T> | ||
7419 | struct strip_extensible { typedef T type; }; | ||
7420 | |||
7421 | template <typename T> | ||
7422 | struct strip_extensible<extensible<T>> { typedef T type; }; | ||
7423 | |||
7424 | template <typename T> | ||
7425 | using strip_extensible_t = typename strip_extensible<T>::type; | ||
7426 | |||
7427 | template <typename C> | ||
7428 | static int get_size_hint(const C& c) { | ||
7429 | return static_cast<int>(c.size()); | ||
7430 | } | ||
7431 | |||
7432 | template <typename V, typename Al> | ||
7433 | static int get_size_hint(const std::forward_list<V, Al>&) { | ||
7434 | // forward_list makes me sad | ||
7435 | return static_cast<int>(32); | ||
7436 | } | ||
7437 | |||
7438 | template <typename T> | ||
7439 | inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { | ||
7440 | getter<meta::unqualified_t<T>> g{}; | ||
7441 | (void)g; | ||
7442 | return g.get(L, index, tracking); | ||
7443 | } | ||
7444 | |||
7445 | template <typename T, typename Arg, typename... Args> | ||
7446 | inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) { | ||
7447 | typedef meta::all< | ||
7448 | std::is_lvalue_reference<T>, | ||
7449 | meta::neg<std::is_const<T>>, | ||
7450 | meta::neg<is_lua_primitive<meta::unqualified_t<T>>>, | ||
7451 | meta::neg<is_unique_usertype<meta::unqualified_t<T>>>> | ||
7452 | use_reference_tag; | ||
7453 | return pusher<std::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>>{}.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...); | ||
7454 | } | ||
7455 | |||
7456 | template <typename T, typename Handler> | ||
7457 | bool check_usertype(std::false_type, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) { | ||
7458 | typedef meta::unqualified_t<T> Tu; | ||
7459 | typedef detail::as_value_tag<Tu> detail_t; | ||
7460 | return checker<detail_t, type::userdata>{}.check(types<meta::unqualified_t<T>>(), L, index, indextype, std::forward<Handler>(handler), tracking); | ||
7461 | } | ||
7462 | |||
7463 | template <typename T, typename Handler> | ||
7464 | bool check_usertype(std::true_type, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) { | ||
7465 | typedef meta::unqualified_t<std::remove_pointer_t<meta::unqualified_t<T>>> Tu; | ||
7466 | typedef detail::as_pointer_tag<Tu> detail_t; | ||
7467 | return checker<detail_t, type::userdata>{}.check(L, index, indextype, std::forward<Handler>(handler), tracking); | ||
7468 | } | ||
7469 | } // namespace stack_detail | ||
7470 | |||
7471 | inline bool maybe_indexable(lua_State* L, int index = -1) { | ||
7472 | type t = type_of(L, index); | ||
7473 | return t == type::userdata || t == type::table; | ||
7474 | } | ||
7475 | |||
7476 | inline int top(lua_State* L) { | ||
7477 | return lua_gettop(L); | ||
7478 | } | ||
7479 | |||
7480 | inline bool is_main_thread(lua_State* L) { | ||
7481 | int ismainthread = lua_pushthread(L); | ||
7482 | lua_pop(L, 1); | ||
7483 | return ismainthread == 1; | ||
7484 | } | ||
7485 | |||
7486 | inline void coroutine_create_guard(lua_State* L) { | ||
7487 | if (is_main_thread(L)) { | ||
7488 | return; | ||
7489 | } | ||
7490 | int stacksize = lua_gettop(L); | ||
7491 | if (stacksize < 1) { | ||
7492 | return; | ||
7493 | } | ||
7494 | if (type_of(L, 1) != type::function) { | ||
7495 | return; | ||
7496 | } | ||
7497 | // well now we're screwed... | ||
7498 | // we can clean the stack and pray it doesn't destroy anything? | ||
7499 | lua_pop(L, stacksize); | ||
7500 | } | ||
7501 | |||
7502 | template <typename T, typename... Args> | ||
7503 | inline int push(lua_State* L, T&& t, Args&&... args) { | ||
7504 | return pusher<meta::unqualified_t<T>>{}.push(L, std::forward<T>(t), std::forward<Args>(args)...); | ||
7505 | } | ||
7506 | |||
7507 | // overload allows to use a pusher of a specific type, but pass in any kind of args | ||
7508 | template <typename T, typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same<T, Arg>::value>> | ||
7509 | inline int push(lua_State* L, Arg&& arg, Args&&... args) { | ||
7510 | return pusher<meta::unqualified_t<T>>{}.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...); | ||
7511 | } | ||
7512 | |||
7513 | template <typename T, typename... Args> | ||
7514 | inline int push_reference(lua_State* L, T&& t, Args&&... args) { | ||
7515 | return stack_detail::push_reference<T>(L, std::forward<T>(t), std::forward<Args>(args)...); | ||
7516 | } | ||
7517 | |||
7518 | template <typename T, typename Arg, typename... Args> | ||
7519 | inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) { | ||
7520 | return stack_detail::push_reference<T>(L, std::forward<Arg>(arg), std::forward<Args>(args)...); | ||
7521 | } | ||
7522 | |||
7523 | inline int multi_push(lua_State*) { | ||
7524 | // do nothing | ||
7525 | return 0; | ||
7526 | } | ||
7527 | |||
7528 | template <typename T, typename... Args> | ||
7529 | inline int multi_push(lua_State* L, T&& t, Args&&... args) { | ||
7530 | int pushcount = push(L, std::forward<T>(t)); | ||
7531 | void(detail::swallow{ (pushcount += stack::push(L, std::forward<Args>(args)), 0)... }); | ||
7532 | return pushcount; | ||
7533 | } | ||
7534 | |||
7535 | inline int multi_push_reference(lua_State*) { | ||
7536 | // do nothing | ||
7537 | return 0; | ||
7538 | } | ||
7539 | |||
7540 | template <typename T, typename... Args> | ||
7541 | inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) { | ||
7542 | int pushcount = push_reference(L, std::forward<T>(t)); | ||
7543 | void(detail::swallow{ (pushcount += stack::push_reference(L, std::forward<Args>(args)), 0)... }); | ||
7544 | return pushcount; | ||
7545 | } | ||
7546 | |||
7547 | template <typename T, typename Handler> | ||
7548 | bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
7549 | typedef meta::unqualified_t<T> Tu; | ||
7550 | checker<Tu> c; | ||
7551 | // VC++ has a bad warning here: shut it up | ||
7552 | (void)c; | ||
7553 | return c.check(L, index, std::forward<Handler>(handler), tracking); | ||
7554 | } | ||
7555 | |||
7556 | template <typename T, typename Handler> | ||
7557 | bool check(lua_State* L, int index, Handler&& handler) { | ||
7558 | record tracking{}; | ||
7559 | return check<T>(L, index, std::forward<Handler>(handler), tracking); | ||
7560 | } | ||
7561 | |||
7562 | template <typename T> | ||
7563 | bool check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { | ||
7564 | auto handler = no_panic; | ||
7565 | return check<T>(L, index, handler); | ||
7566 | } | ||
7567 | |||
7568 | template <typename T, typename Handler> | ||
7569 | bool check_usertype(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
7570 | type indextype = type_of(L, index); | ||
7571 | return stack_detail::check_usertype<T>(std::is_pointer<T>(), L, index, indextype, std::forward<Handler>(handler), tracking); | ||
7572 | } | ||
7573 | |||
7574 | template <typename T, typename Handler> | ||
7575 | bool check_usertype(lua_State* L, int index, Handler&& handler) { | ||
7576 | record tracking{}; | ||
7577 | return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking); | ||
7578 | } | ||
7579 | |||
7580 | template <typename T> | ||
7581 | bool check_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { | ||
7582 | auto handler = no_panic; | ||
7583 | return check_usertype<T>(L, index, handler); | ||
7584 | } | ||
7585 | |||
7586 | template <typename T, typename Handler> | ||
7587 | inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
7588 | typedef meta::unqualified_t<T> Tu; | ||
7589 | check_getter<Tu> cg{}; | ||
7590 | (void)cg; | ||
7591 | return cg.get(L, index, std::forward<Handler>(handler), tracking); | ||
7592 | } | ||
7593 | |||
7594 | template <typename T, typename Handler> | ||
7595 | inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { | ||
7596 | record tracking{}; | ||
7597 | return check_get<T>(L, index, handler, tracking); | ||
7598 | } | ||
7599 | |||
7600 | template <typename T> | ||
7601 | inline decltype(auto) check_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { | ||
7602 | auto handler = no_panic; | ||
7603 | return check_get<T>(L, index, handler); | ||
7604 | } | ||
7605 | |||
7606 | namespace stack_detail { | ||
7607 | |||
7608 | #if defined(SOL_SAFE_GETTER) && SOL_SAFE_GETTER | ||
7609 | template <typename T> | ||
7610 | inline auto tagged_get(types<T>, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) { | ||
7611 | auto op = check_get<T>(L, index, type_panic_c_str, tracking); | ||
7612 | return *std::move(op); | ||
7613 | } | ||
7614 | |||
7615 | template <typename T> | ||
7616 | inline decltype(auto) tagged_get(types<optional<T>>, lua_State* L, int index, record& tracking) { | ||
7617 | return stack_detail::unchecked_get<optional<T>>(L, index, tracking); | ||
7618 | } | ||
7619 | #else | ||
7620 | template <typename T> | ||
7621 | inline decltype(auto) tagged_get(types<T>, lua_State* L, int index, record& tracking) { | ||
7622 | return stack_detail::unchecked_get<T>(L, index, tracking); | ||
7623 | } | ||
7624 | #endif | ||
7625 | |||
7626 | template <bool b> | ||
7627 | struct check_types { | ||
7628 | template <typename T, typename... Args, typename Handler> | ||
7629 | static bool check(types<T, Args...>, lua_State* L, int firstargument, Handler&& handler, record& tracking) { | ||
7630 | if (!stack::check<T>(L, firstargument + tracking.used, handler, tracking)) | ||
7631 | return false; | ||
7632 | return check(types<Args...>(), L, firstargument, std::forward<Handler>(handler), tracking); | ||
7633 | } | ||
7634 | |||
7635 | template <typename Handler> | ||
7636 | static bool check(types<>, lua_State*, int, Handler&&, record&) { | ||
7637 | return true; | ||
7638 | } | ||
7639 | }; | ||
7640 | |||
7641 | template <> | ||
7642 | struct check_types<false> { | ||
7643 | template <typename... Args, typename Handler> | ||
7644 | static bool check(types<Args...>, lua_State*, int, Handler&&, record&) { | ||
7645 | return true; | ||
7646 | } | ||
7647 | }; | ||
7648 | |||
7649 | } // namespace stack_detail | ||
7650 | |||
7651 | template <bool b, typename... Args, typename Handler> | ||
7652 | bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
7653 | return stack_detail::check_types<b>{}.check(types<meta::unqualified_t<Args>...>(), L, index, std::forward<Handler>(handler), tracking); | ||
7654 | } | ||
7655 | |||
7656 | template <bool b, typename... Args, typename Handler> | ||
7657 | bool multi_check(lua_State* L, int index, Handler&& handler) { | ||
7658 | record tracking{}; | ||
7659 | return multi_check<b, Args...>(L, index, std::forward<Handler>(handler), tracking); | ||
7660 | } | ||
7661 | |||
7662 | template <bool b, typename... Args> | ||
7663 | bool multi_check(lua_State* L, int index) { | ||
7664 | auto handler = no_panic; | ||
7665 | return multi_check<b, Args...>(L, index, handler); | ||
7666 | } | ||
7667 | |||
7668 | template <typename... Args, typename Handler> | ||
7669 | bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
7670 | return multi_check<true, Args...>(L, index, std::forward<Handler>(handler), tracking); | ||
7671 | } | ||
7672 | |||
7673 | template <typename... Args, typename Handler> | ||
7674 | bool multi_check(lua_State* L, int index, Handler&& handler) { | ||
7675 | return multi_check<true, Args...>(L, index, std::forward<Handler>(handler)); | ||
7676 | } | ||
7677 | |||
7678 | template <typename... Args> | ||
7679 | bool multi_check(lua_State* L, int index) { | ||
7680 | return multi_check<true, Args...>(L, index); | ||
7681 | } | ||
7682 | |||
7683 | template <typename T> | ||
7684 | inline decltype(auto) get_usertype(lua_State* L, int index, record& tracking) { | ||
7685 | #if defined(SOL_SAFE_GETTER) && SOL_SAFE_GETTER | ||
7686 | return stack_detail::tagged_get(types<std::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>>(), L, index, tracking); | ||
7687 | #else | ||
7688 | return stack_detail::unchecked_get<std::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>>(L, index, tracking); | ||
7689 | #endif | ||
7690 | } | ||
7691 | |||
7692 | template <typename T> | ||
7693 | inline decltype(auto) get_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { | ||
7694 | record tracking{}; | ||
7695 | return get_usertype<T>(L, index, tracking); | ||
7696 | } | ||
7697 | |||
7698 | template <typename T> | ||
7699 | inline decltype(auto) get(lua_State* L, int index, record& tracking) { | ||
7700 | return stack_detail::tagged_get(types<T>(), L, index, tracking); | ||
7701 | } | ||
7702 | |||
7703 | template <typename T> | ||
7704 | inline decltype(auto) get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { | ||
7705 | record tracking{}; | ||
7706 | return get<T>(L, index, tracking); | ||
7707 | } | ||
7708 | |||
7709 | template <typename T> | ||
7710 | inline decltype(auto) pop(lua_State* L) { | ||
7711 | return popper<meta::unqualified_t<T>>{}.pop(L); | ||
7712 | } | ||
7713 | |||
7714 | template <bool global = false, bool raw = false, typename Key> | ||
7715 | void get_field(lua_State* L, Key&& key) { | ||
7716 | field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key)); | ||
7717 | } | ||
7718 | |||
7719 | template <bool global = false, bool raw = false, typename Key> | ||
7720 | void get_field(lua_State* L, Key&& key, int tableindex) { | ||
7721 | field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key), tableindex); | ||
7722 | } | ||
7723 | |||
7724 | template <bool global = false, typename Key> | ||
7725 | void raw_get_field(lua_State* L, Key&& key) { | ||
7726 | get_field<global, true>(L, std::forward<Key>(key)); | ||
7727 | } | ||
7728 | |||
7729 | template <bool global = false, typename Key> | ||
7730 | void raw_get_field(lua_State* L, Key&& key, int tableindex) { | ||
7731 | get_field<global, true>(L, std::forward<Key>(key), tableindex); | ||
7732 | } | ||
7733 | |||
7734 | template <bool global = false, bool raw = false, typename Key> | ||
7735 | probe probe_get_field(lua_State* L, Key&& key) { | ||
7736 | return probe_field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key)); | ||
7737 | } | ||
7738 | |||
7739 | template <bool global = false, bool raw = false, typename Key> | ||
7740 | probe probe_get_field(lua_State* L, Key&& key, int tableindex) { | ||
7741 | return probe_field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key), tableindex); | ||
7742 | } | ||
7743 | |||
7744 | template <bool global = false, typename Key> | ||
7745 | probe probe_raw_get_field(lua_State* L, Key&& key) { | ||
7746 | return probe_get_field<global, true>(L, std::forward<Key>(key)); | ||
7747 | } | ||
7748 | |||
7749 | template <bool global = false, typename Key> | ||
7750 | probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) { | ||
7751 | return probe_get_field<global, true>(L, std::forward<Key>(key), tableindex); | ||
7752 | } | ||
7753 | |||
7754 | template <bool global = false, bool raw = false, typename Key, typename Value> | ||
7755 | void set_field(lua_State* L, Key&& key, Value&& value) { | ||
7756 | field_setter<meta::unqualified_t<Key>, global, raw>{}.set(L, std::forward<Key>(key), std::forward<Value>(value)); | ||
7757 | } | ||
7758 | |||
7759 | template <bool global = false, bool raw = false, typename Key, typename Value> | ||
7760 | void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { | ||
7761 | field_setter<meta::unqualified_t<Key>, global, raw>{}.set(L, std::forward<Key>(key), std::forward<Value>(value), tableindex); | ||
7762 | } | ||
7763 | |||
7764 | template <bool global = false, typename Key, typename Value> | ||
7765 | void raw_set_field(lua_State* L, Key&& key, Value&& value) { | ||
7766 | set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value)); | ||
7767 | } | ||
7768 | |||
7769 | template <bool global = false, typename Key, typename Value> | ||
7770 | void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { | ||
7771 | set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value), tableindex); | ||
7772 | } | ||
7773 | |||
7774 | template <typename T, typename F> | ||
7775 | inline void modify_unique_usertype_as(const stack_reference& obj, F&& f) { | ||
7776 | typedef unique_usertype_traits<T> u_traits; | ||
7777 | void* raw = lua_touserdata(obj.lua_state(), obj.stack_index()); | ||
7778 | void* ptr_memory = detail::align_usertype_pointer(raw); | ||
7779 | void* uu_memory = detail::align_usertype_unique<T>(raw); | ||
7780 | T& uu = *static_cast<T*>(uu_memory); | ||
7781 | f(uu); | ||
7782 | *static_cast<void**>(ptr_memory) = static_cast<void*>(u_traits::get(uu)); | ||
7783 | } | ||
7784 | |||
7785 | template <typename F> | ||
7786 | inline void modify_unique_usertype(const stack_reference& obj, F&& f) { | ||
7787 | typedef meta::bind_traits<meta::unqualified_t<F>> bt; | ||
7788 | typedef typename bt::template arg_at<0> T; | ||
7789 | modify_unique_usertype_as<meta::unqualified_t<T>>(obj, std::forward<F>(f)); | ||
7790 | } | ||
7791 | } // namespace stack | ||
7792 | } // namespace sol | ||
7793 | |||
7794 | // end of sol/stack_core.hpp | ||
7795 | |||
7796 | // beginning of sol/stack_check.hpp | ||
7797 | |||
7798 | // beginning of sol/usertype_traits.hpp | ||
7799 | |||
7800 | namespace sol { | ||
7801 | |||
7802 | template <typename T> | ||
7803 | struct usertype_traits { | ||
7804 | static const std::string& name() { | ||
7805 | static const std::string& n = detail::short_demangle<T>(); | ||
7806 | return n; | ||
7807 | } | ||
7808 | static const std::string& qualified_name() { | ||
7809 | static const std::string& q_n = detail::demangle<T>(); | ||
7810 | return q_n; | ||
7811 | } | ||
7812 | static const std::string& metatable() { | ||
7813 | static const std::string m = std::string("sol.").append(detail::demangle<T>()); | ||
7814 | return m; | ||
7815 | } | ||
7816 | static const std::string& user_metatable() { | ||
7817 | static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user"); | ||
7818 | return u_m; | ||
7819 | } | ||
7820 | static const std::string& user_gc_metatable() { | ||
7821 | static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB"); | ||
7822 | return u_g_m; | ||
7823 | } | ||
7824 | static const std::string& gc_table() { | ||
7825 | static const std::string g_t = std::string("sol.").append(detail::demangle<T>()).append(".\xE2\x99\xBB"); | ||
7826 | return g_t; | ||
7827 | } | ||
7828 | }; | ||
7829 | |||
7830 | } // namespace sol | ||
7831 | |||
7832 | // end of sol/usertype_traits.hpp | ||
7833 | |||
7834 | // beginning of sol/inheritance.hpp | ||
7835 | |||
7836 | namespace sol { | ||
7837 | template <typename... Args> | ||
7838 | struct base_list {}; | ||
7839 | template <typename... Args> | ||
7840 | using bases = base_list<Args...>; | ||
7841 | |||
7842 | typedef bases<> base_classes_tag; | ||
7843 | const auto base_classes = base_classes_tag(); | ||
7844 | |||
7845 | namespace detail { | ||
7846 | |||
7847 | template <typename T> | ||
7848 | struct has_derived { | ||
7849 | static bool value; | ||
7850 | }; | ||
7851 | |||
7852 | template <typename T> | ||
7853 | bool has_derived<T>::value = false; | ||
7854 | |||
7855 | inline decltype(auto) base_class_check_key() { | ||
7856 | static const auto& key = "class_check"; | ||
7857 | return key; | ||
7858 | } | ||
7859 | |||
7860 | inline decltype(auto) base_class_cast_key() { | ||
7861 | static const auto& key = "class_cast"; | ||
7862 | return key; | ||
7863 | } | ||
7864 | |||
7865 | inline decltype(auto) base_class_index_propogation_key() { | ||
7866 | static const auto& key = u8"\xF0\x9F\x8C\xB2.index"; | ||
7867 | return key; | ||
7868 | } | ||
7869 | |||
7870 | inline decltype(auto) base_class_new_index_propogation_key() { | ||
7871 | static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index"; | ||
7872 | return key; | ||
7873 | } | ||
7874 | |||
7875 | template <typename T, typename... Bases> | ||
7876 | struct inheritance { | ||
7877 | static bool type_check_bases(types<>, const std::string&) { | ||
7878 | return false; | ||
7879 | } | ||
7880 | |||
7881 | template <typename Base, typename... Args> | ||
7882 | static bool type_check_bases(types<Base, Args...>, const std::string& ti) { | ||
7883 | return ti == usertype_traits<Base>::qualified_name() || type_check_bases(types<Args...>(), ti); | ||
7884 | } | ||
7885 | |||
7886 | static bool type_check(const std::string& ti) { | ||
7887 | return ti == usertype_traits<T>::qualified_name() || type_check_bases(types<Bases...>(), ti); | ||
7888 | } | ||
7889 | |||
7890 | static void* type_cast_bases(types<>, T*, const std::string&) { | ||
7891 | return nullptr; | ||
7892 | } | ||
7893 | |||
7894 | template <typename Base, typename... Args> | ||
7895 | static void* type_cast_bases(types<Base, Args...>, T* data, const std::string& ti) { | ||
7896 | // Make sure to convert to T first, and then dynamic cast to the proper type | ||
7897 | return ti != usertype_traits<Base>::qualified_name() ? type_cast_bases(types<Args...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data)); | ||
7898 | } | ||
7899 | |||
7900 | static void* type_cast(void* voiddata, const std::string& ti) { | ||
7901 | T* data = static_cast<T*>(voiddata); | ||
7902 | return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(types<Bases...>(), data, ti) : data); | ||
7903 | } | ||
7904 | }; | ||
7905 | |||
7906 | using inheritance_check_function = decltype(&inheritance<void>::type_check); | ||
7907 | using inheritance_cast_function = decltype(&inheritance<void>::type_cast); | ||
7908 | |||
7909 | } // namespace detail | ||
7910 | } // namespace sol | ||
7911 | |||
7912 | // end of sol/inheritance.hpp | ||
7913 | |||
7914 | #include <cmath> | ||
7915 | #ifdef SOL_CXX17_FEATURES | ||
7916 | #ifdef SOL_STD_VARIANT | ||
7917 | #endif // SOL_STD_VARIANT | ||
7918 | #endif // SOL_CXX17_FEATURES | ||
7919 | |||
7920 | namespace sol { | ||
7921 | namespace stack { | ||
7922 | namespace stack_detail { | ||
7923 | template <typename T, bool poptable = true> | ||
7924 | inline bool check_metatable(lua_State* L, int index = -2) { | ||
7925 | const auto& metakey = usertype_traits<T>::metatable(); | ||
7926 | luaL_getmetatable(L, &metakey[0]); | ||
7927 | const type expectedmetatabletype = static_cast<type>(lua_type(L, -1)); | ||
7928 | if (expectedmetatabletype != type::lua_nil) { | ||
7929 | if (lua_rawequal(L, -1, index) == 1) { | ||
7930 | lua_pop(L, 1 + static_cast<int>(poptable)); | ||
7931 | return true; | ||
7932 | } | ||
7933 | } | ||
7934 | lua_pop(L, 1); | ||
7935 | return false; | ||
7936 | } | ||
7937 | |||
7938 | template <type expected, int (*check_func)(lua_State*, int)> | ||
7939 | struct basic_check { | ||
7940 | template <typename Handler> | ||
7941 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
7942 | tracking.use(1); | ||
7943 | bool success = check_func(L, index) == 1; | ||
7944 | if (!success) { | ||
7945 | // expected type, actual type | ||
7946 | handler(L, index, expected, type_of(L, index), ""); | ||
7947 | } | ||
7948 | return success; | ||
7949 | } | ||
7950 | }; | ||
7951 | } // namespace stack_detail | ||
7952 | |||
7953 | template <typename T, typename> | ||
7954 | struct userdata_checker { | ||
7955 | template <typename Handler> | ||
7956 | static bool check(lua_State*, int, type, Handler&&, record&) { | ||
7957 | return false; | ||
7958 | } | ||
7959 | }; | ||
7960 | |||
7961 | template <typename T, type expected, typename> | ||
7962 | struct checker { | ||
7963 | template <typename Handler> | ||
7964 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
7965 | tracking.use(1); | ||
7966 | const type indextype = type_of(L, index); | ||
7967 | bool success = expected == indextype; | ||
7968 | if (!success) { | ||
7969 | // expected type, actual type, message | ||
7970 | handler(L, index, expected, indextype, ""); | ||
7971 | } | ||
7972 | return success; | ||
7973 | } | ||
7974 | }; | ||
7975 | |||
7976 | template <typename T> | ||
7977 | struct checker<T, type::number, std::enable_if_t<std::is_integral<T>::value>> { | ||
7978 | template <typename Handler> | ||
7979 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
7980 | tracking.use(1); | ||
7981 | #if SOL_LUA_VERSION >= 503 | ||
7982 | #if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS | ||
7983 | int isnum = 0; | ||
7984 | lua_tointegerx(L, index, &isnum); | ||
7985 | const bool success = isnum != 0; | ||
7986 | if (!success) { | ||
7987 | // expected type, actual type | ||
7988 | handler(L, index, type::number, type_of(L, index), "not a numeric type or numeric string"); | ||
7989 | } | ||
7990 | #elif (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION) | ||
7991 | // this check is precise, does not convert | ||
7992 | if (lua_isinteger(L, index) == 1) { | ||
7993 | return true; | ||
7994 | } | ||
7995 | const bool success = false; | ||
7996 | if (!success) { | ||
7997 | // expected type, actual type | ||
7998 | handler(L, index, type::number, type_of(L, index), "not a numeric (integral) type"); | ||
7999 | } | ||
8000 | #else | ||
8001 | type t = type_of(L, index); | ||
8002 | const bool success = t == type::number; | ||
8003 | #endif // If numbers are enabled, use the imprecise check | ||
8004 | if (!success) { | ||
8005 | // expected type, actual type | ||
8006 | handler(L, index, type::number, type_of(L, index), "not a numeric type"); | ||
8007 | } | ||
8008 | return success; | ||
8009 | #else | ||
8010 | #if !defined(SOL_STRINGS_ARE_NUMBERS) || !SOL_STRINGS_ARE_NUMBERS | ||
8011 | // must pre-check, because it will convert | ||
8012 | type t = type_of(L, index); | ||
8013 | if (t != type::number) { | ||
8014 | // expected type, actual type | ||
8015 | handler(L, index, type::number, t, "not a numeric type"); | ||
8016 | return false; | ||
8017 | } | ||
8018 | #endif // Do not allow strings to be numbers | ||
8019 | int isnum = 0; | ||
8020 | const lua_Number v = lua_tonumberx(L, index, &isnum); | ||
8021 | const bool success = isnum != 0 | ||
8022 | #if (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION) | ||
8023 | && static_cast<lua_Number>(llround(v)) == v | ||
8024 | #endif // Safe numerics and number precision checking | ||
8025 | ; | ||
8026 | if (!success) { | ||
8027 | // expected type, actual type | ||
8028 | #if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS | ||
8029 | handler(L, index, type::number, t, "not a numeric type"); | ||
8030 | #else | ||
8031 | handler(L, index, type::number, type_of(L, index), "not a numeric type or numeric string"); | ||
8032 | #endif | ||
8033 | } | ||
8034 | return success; | ||
8035 | #endif // Lua Version 5.3 versus others | ||
8036 | } | ||
8037 | }; | ||
8038 | |||
8039 | template <typename T> | ||
8040 | struct checker<T, type::number, std::enable_if_t<std::is_floating_point<T>::value>> { | ||
8041 | template <typename Handler> | ||
8042 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8043 | tracking.use(1); | ||
8044 | #if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS | ||
8045 | bool success = lua_isnumber(L, index) == 1; | ||
8046 | if (!success) { | ||
8047 | // expected type, actual type | ||
8048 | handler(L, index, type::number, type_of(L, index), "not a numeric type or numeric string"); | ||
8049 | } | ||
8050 | return success; | ||
8051 | #else | ||
8052 | type t = type_of(L, index); | ||
8053 | bool success = t == type::number; | ||
8054 | if (!success) { | ||
8055 | // expected type, actual type | ||
8056 | handler(L, index, type::number, t, "not a numeric type"); | ||
8057 | } | ||
8058 | return success; | ||
8059 | #endif // Strings are Numbers | ||
8060 | } | ||
8061 | }; | ||
8062 | |||
8063 | template <type expected, typename C> | ||
8064 | struct checker<lua_nil_t, expected, C> { | ||
8065 | template <typename Handler> | ||
8066 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8067 | bool success = lua_isnil(L, index); | ||
8068 | if (success) { | ||
8069 | tracking.use(1); | ||
8070 | return success; | ||
8071 | } | ||
8072 | tracking.use(0); | ||
8073 | success = lua_isnone(L, index); | ||
8074 | if (!success) { | ||
8075 | // expected type, actual type | ||
8076 | handler(L, index, expected, type_of(L, index), ""); | ||
8077 | } | ||
8078 | return success; | ||
8079 | } | ||
8080 | }; | ||
8081 | |||
8082 | template <type expected, typename C> | ||
8083 | struct checker<nullopt_t, expected, C> : checker<lua_nil_t> {}; | ||
8084 | |||
8085 | template <typename C> | ||
8086 | struct checker<this_state, type::poly, C> { | ||
8087 | template <typename Handler> | ||
8088 | static bool check(lua_State*, int, Handler&&, record& tracking) { | ||
8089 | tracking.use(0); | ||
8090 | return true; | ||
8091 | } | ||
8092 | }; | ||
8093 | |||
8094 | template <typename C> | ||
8095 | struct checker<this_main_state, type::poly, C> { | ||
8096 | template <typename Handler> | ||
8097 | static bool check(lua_State*, int, Handler&&, record& tracking) { | ||
8098 | tracking.use(0); | ||
8099 | return true; | ||
8100 | } | ||
8101 | }; | ||
8102 | |||
8103 | template <typename C> | ||
8104 | struct checker<this_environment, type::poly, C> { | ||
8105 | template <typename Handler> | ||
8106 | static bool check(lua_State*, int, Handler&&, record& tracking) { | ||
8107 | tracking.use(0); | ||
8108 | return true; | ||
8109 | } | ||
8110 | }; | ||
8111 | |||
8112 | template <typename C> | ||
8113 | struct checker<variadic_args, type::poly, C> { | ||
8114 | template <typename Handler> | ||
8115 | static bool check(lua_State*, int, Handler&&, record& tracking) { | ||
8116 | tracking.use(0); | ||
8117 | return true; | ||
8118 | } | ||
8119 | }; | ||
8120 | |||
8121 | template <typename C> | ||
8122 | struct checker<type, type::poly, C> { | ||
8123 | template <typename Handler> | ||
8124 | static bool check(lua_State*, int, Handler&&, record& tracking) { | ||
8125 | tracking.use(0); | ||
8126 | return true; | ||
8127 | } | ||
8128 | }; | ||
8129 | |||
8130 | template <typename T, typename C> | ||
8131 | struct checker<T, type::poly, C> { | ||
8132 | template <typename Handler> | ||
8133 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8134 | tracking.use(1); | ||
8135 | bool success = is_lua_reference<T>::value || !lua_isnone(L, index); | ||
8136 | if (!success) { | ||
8137 | // expected type, actual type | ||
8138 | handler(L, index, type::poly, type_of(L, index), ""); | ||
8139 | } | ||
8140 | return success; | ||
8141 | } | ||
8142 | }; | ||
8143 | |||
8144 | template <typename T, typename C> | ||
8145 | struct checker<T, type::lightuserdata, C> { | ||
8146 | template <typename Handler> | ||
8147 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8148 | tracking.use(1); | ||
8149 | type t = type_of(L, index); | ||
8150 | bool success = t == type::userdata || t == type::lightuserdata; | ||
8151 | if (!success) { | ||
8152 | // expected type, actual type | ||
8153 | handler(L, index, type::lightuserdata, t, ""); | ||
8154 | } | ||
8155 | return success; | ||
8156 | } | ||
8157 | }; | ||
8158 | |||
8159 | template <typename C> | ||
8160 | struct checker<userdata_value, type::userdata, C> { | ||
8161 | template <typename Handler> | ||
8162 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8163 | tracking.use(1); | ||
8164 | type t = type_of(L, index); | ||
8165 | bool success = t == type::userdata; | ||
8166 | if (!success) { | ||
8167 | // expected type, actual type | ||
8168 | handler(L, index, type::userdata, t, ""); | ||
8169 | } | ||
8170 | return success; | ||
8171 | } | ||
8172 | }; | ||
8173 | |||
8174 | template <typename B, typename C> | ||
8175 | struct checker<basic_userdata<B>, type::userdata, C> { | ||
8176 | template <typename Handler> | ||
8177 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8178 | return stack::check<userdata_value>(L, index, std::forward<Handler>(handler), tracking); | ||
8179 | } | ||
8180 | }; | ||
8181 | |||
8182 | template <typename T, typename C> | ||
8183 | struct checker<user<T>, type::userdata, C> : checker<user<T>, type::lightuserdata, C> {}; | ||
8184 | |||
8185 | template <typename T, typename C> | ||
8186 | struct checker<non_null<T>, type::userdata, C> : checker<T, lua_type_of<T>::value, C> {}; | ||
8187 | |||
8188 | template <typename C> | ||
8189 | struct checker<lua_CFunction, type::function, C> : stack_detail::basic_check<type::function, lua_iscfunction> {}; | ||
8190 | template <typename C> | ||
8191 | struct checker<std::remove_pointer_t<lua_CFunction>, type::function, C> : checker<lua_CFunction, type::function, C> {}; | ||
8192 | template <typename C> | ||
8193 | struct checker<c_closure, type::function, C> : checker<lua_CFunction, type::function, C> {}; | ||
8194 | |||
8195 | template <typename T, typename C> | ||
8196 | struct checker<T, type::function, C> { | ||
8197 | template <typename Handler> | ||
8198 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8199 | tracking.use(1); | ||
8200 | type t = type_of(L, index); | ||
8201 | if (t == type::lua_nil || t == type::none || t == type::function) { | ||
8202 | // allow for lua_nil to be returned | ||
8203 | return true; | ||
8204 | } | ||
8205 | if (t != type::userdata && t != type::table) { | ||
8206 | handler(L, index, type::function, t, "must be a function or table or a userdata"); | ||
8207 | return false; | ||
8208 | } | ||
8209 | // Do advanced check for call-style userdata? | ||
8210 | static const auto& callkey = to_string(meta_function::call); | ||
8211 | if (lua_getmetatable(L, index) == 0) { | ||
8212 | // No metatable, no __call key possible | ||
8213 | handler(L, index, type::function, t, "value is not a function and does not have overriden metatable"); | ||
8214 | return false; | ||
8215 | } | ||
8216 | if (lua_isnoneornil(L, -1)) { | ||
8217 | lua_pop(L, 1); | ||
8218 | handler(L, index, type::function, t, "value is not a function and does not have valid metatable"); | ||
8219 | return false; | ||
8220 | } | ||
8221 | lua_getfield(L, -1, &callkey[0]); | ||
8222 | if (lua_isnoneornil(L, -1)) { | ||
8223 | lua_pop(L, 2); | ||
8224 | handler(L, index, type::function, t, "value's metatable does not have __call overridden in metatable, cannot call this type"); | ||
8225 | return false; | ||
8226 | } | ||
8227 | // has call, is definitely a function | ||
8228 | lua_pop(L, 2); | ||
8229 | return true; | ||
8230 | } | ||
8231 | }; | ||
8232 | |||
8233 | template <typename T, typename C> | ||
8234 | struct checker<T, type::table, C> { | ||
8235 | template <typename Handler> | ||
8236 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8237 | tracking.use(1); | ||
8238 | type t = type_of(L, index); | ||
8239 | if (t == type::table) { | ||
8240 | return true; | ||
8241 | } | ||
8242 | if (t != type::userdata) { | ||
8243 | handler(L, index, type::table, t, "value is not a table or a userdata that can behave like one"); | ||
8244 | return false; | ||
8245 | } | ||
8246 | return true; | ||
8247 | } | ||
8248 | }; | ||
8249 | |||
8250 | template <type expected, typename C> | ||
8251 | struct checker<metatable_t, expected, C> { | ||
8252 | template <typename Handler> | ||
8253 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8254 | tracking.use(1); | ||
8255 | if (lua_getmetatable(L, index) == 0) { | ||
8256 | return true; | ||
8257 | } | ||
8258 | type t = type_of(L, -1); | ||
8259 | if (t == type::table || t == type::none || t == type::lua_nil) { | ||
8260 | lua_pop(L, 1); | ||
8261 | return true; | ||
8262 | } | ||
8263 | if (t != type::userdata) { | ||
8264 | lua_pop(L, 1); | ||
8265 | handler(L, index, expected, t, "value does not have a valid metatable"); | ||
8266 | return false; | ||
8267 | } | ||
8268 | return true; | ||
8269 | } | ||
8270 | }; | ||
8271 | |||
8272 | template <typename C> | ||
8273 | struct checker<env_t, type::poly, C> { | ||
8274 | template <typename Handler> | ||
8275 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8276 | tracking.use(1); | ||
8277 | type t = type_of(L, index); | ||
8278 | if (t == type::table || t == type::none || t == type::lua_nil || t == type::userdata) { | ||
8279 | return true; | ||
8280 | } | ||
8281 | handler(L, index, type::table, t, "value cannot not have a valid environment"); | ||
8282 | return true; | ||
8283 | } | ||
8284 | }; | ||
8285 | |||
8286 | template <typename E, typename C> | ||
8287 | struct checker<basic_environment<E>, type::poly, C> { | ||
8288 | template <typename Handler> | ||
8289 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8290 | tracking.use(1); | ||
8291 | if (lua_getmetatable(L, index) == 0) { | ||
8292 | return true; | ||
8293 | } | ||
8294 | type t = type_of(L, -1); | ||
8295 | if (t == type::table || t == type::none || t == type::lua_nil) { | ||
8296 | lua_pop(L, 1); | ||
8297 | return true; | ||
8298 | } | ||
8299 | if (t != type::userdata) { | ||
8300 | lua_pop(L, 1); | ||
8301 | handler(L, index, type::table, t, "value does not have a valid metatable"); | ||
8302 | return false; | ||
8303 | } | ||
8304 | return true; | ||
8305 | } | ||
8306 | }; | ||
8307 | |||
8308 | template <typename T, typename C> | ||
8309 | struct checker<detail::as_value_tag<T>, type::userdata, C> { | ||
8310 | template <typename Handler> | ||
8311 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8312 | const type indextype = type_of(L, index); | ||
8313 | return check(types<T>(), L, index, indextype, handler, tracking); | ||
8314 | } | ||
8315 | |||
8316 | template <typename U, typename Handler> | ||
8317 | static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) { | ||
8318 | #if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP | ||
8319 | userdata_checker<extensible<T>> uc; | ||
8320 | (void)uc; | ||
8321 | if (uc.check(L, index, indextype, handler, tracking)) { | ||
8322 | return true; | ||
8323 | } | ||
8324 | #endif // interop extensibility | ||
8325 | tracking.use(1); | ||
8326 | if (indextype != type::userdata) { | ||
8327 | handler(L, index, type::userdata, indextype, "value is not a valid userdata"); | ||
8328 | return false; | ||
8329 | } | ||
8330 | if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value) | ||
8331 | return true; | ||
8332 | if (lua_getmetatable(L, index) == 0) { | ||
8333 | return true; | ||
8334 | } | ||
8335 | int metatableindex = lua_gettop(L); | ||
8336 | if (stack_detail::check_metatable<U>(L, metatableindex)) | ||
8337 | return true; | ||
8338 | if (stack_detail::check_metatable<U*>(L, metatableindex)) | ||
8339 | return true; | ||
8340 | if (stack_detail::check_metatable<detail::unique_usertype<U>>(L, metatableindex)) | ||
8341 | return true; | ||
8342 | if (stack_detail::check_metatable<as_container_t<U>>(L, metatableindex)) | ||
8343 | return true; | ||
8344 | bool success = false; | ||
8345 | if (detail::has_derived<T>::value) { | ||
8346 | auto pn = stack::pop_n(L, 1); | ||
8347 | lua_pushstring(L, &detail::base_class_check_key()[0]); | ||
8348 | lua_rawget(L, metatableindex); | ||
8349 | if (type_of(L, -1) != type::lua_nil) { | ||
8350 | void* basecastdata = lua_touserdata(L, -1); | ||
8351 | detail::inheritance_check_function ic = reinterpret_cast<detail::inheritance_check_function>(basecastdata); | ||
8352 | success = ic(usertype_traits<T>::qualified_name()); | ||
8353 | } | ||
8354 | } | ||
8355 | if (!success) { | ||
8356 | lua_pop(L, 1); | ||
8357 | handler(L, index, type::userdata, indextype, "value at this index does not properly reflect the desired type"); | ||
8358 | return false; | ||
8359 | } | ||
8360 | lua_pop(L, 1); | ||
8361 | return true; | ||
8362 | } | ||
8363 | }; | ||
8364 | |||
8365 | template <typename T, typename C> | ||
8366 | struct checker<detail::as_pointer_tag<T>, type::userdata, C> { | ||
8367 | template <typename Handler> | ||
8368 | static bool check(lua_State* L, int index, type indextype, Handler&& handler, record& tracking) { | ||
8369 | if (indextype == type::lua_nil) { | ||
8370 | tracking.use(1); | ||
8371 | return true; | ||
8372 | } | ||
8373 | return stack_detail::check_usertype<T>(std::false_type(), L, index, indextype, std::forward<Handler>(handler), tracking); | ||
8374 | } | ||
8375 | |||
8376 | template <typename Handler> | ||
8377 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8378 | const type indextype = type_of(L, index); | ||
8379 | return check(L, index, handler, indextype, tracking); | ||
8380 | } | ||
8381 | }; | ||
8382 | |||
8383 | template <typename T, typename C> | ||
8384 | struct checker<T, type::userdata, C> { | ||
8385 | template <typename Handler> | ||
8386 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8387 | return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking); | ||
8388 | } | ||
8389 | }; | ||
8390 | |||
8391 | template <typename T, typename C> | ||
8392 | struct checker<T*, type::userdata, C> { | ||
8393 | template <typename Handler> | ||
8394 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8395 | return check_usertype<T*>(L, index, std::forward<Handler>(handler), tracking); | ||
8396 | } | ||
8397 | }; | ||
8398 | |||
8399 | template <typename X> | ||
8400 | struct checker<X, type::userdata, std::enable_if_t<is_unique_usertype<X>::value>> { | ||
8401 | typedef typename unique_usertype_traits<X>::type T; | ||
8402 | template <typename Handler> | ||
8403 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8404 | const type indextype = type_of(L, index); | ||
8405 | tracking.use(1); | ||
8406 | if (indextype != type::userdata) { | ||
8407 | handler(L, index, type::userdata, indextype, "value is not a userdata"); | ||
8408 | return false; | ||
8409 | } | ||
8410 | if (lua_getmetatable(L, index) == 0) { | ||
8411 | return true; | ||
8412 | } | ||
8413 | int metatableindex = lua_gettop(L); | ||
8414 | if (stack_detail::check_metatable<detail::unique_usertype<T>>(L, metatableindex)) { | ||
8415 | void* memory = lua_touserdata(L, index); | ||
8416 | memory = detail::align_usertype_unique_destructor(memory); | ||
8417 | detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory); | ||
8418 | bool success = &detail::usertype_unique_alloc_destroy<T, X> == pdx; | ||
8419 | if (!success) { | ||
8420 | handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype"); | ||
8421 | } | ||
8422 | return success; | ||
8423 | } | ||
8424 | lua_pop(L, 1); | ||
8425 | handler(L, index, type::userdata, indextype, "unrecognized userdata (not pushed by sol?)"); | ||
8426 | return false; | ||
8427 | } | ||
8428 | }; | ||
8429 | |||
8430 | template <typename T, typename C> | ||
8431 | struct checker<std::reference_wrapper<T>, type::userdata, C> { | ||
8432 | template <typename Handler> | ||
8433 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8434 | return checker<T, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking); | ||
8435 | } | ||
8436 | }; | ||
8437 | |||
8438 | template <typename... Args, typename C> | ||
8439 | struct checker<std::tuple<Args...>, type::poly, C> { | ||
8440 | template <typename Handler> | ||
8441 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8442 | return stack::multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking); | ||
8443 | } | ||
8444 | }; | ||
8445 | |||
8446 | template <typename A, typename B, typename C> | ||
8447 | struct checker<std::pair<A, B>, type::poly, C> { | ||
8448 | template <typename Handler> | ||
8449 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8450 | return stack::multi_check<A, B>(L, index, std::forward<Handler>(handler), tracking); | ||
8451 | } | ||
8452 | }; | ||
8453 | |||
8454 | template <typename T, typename C> | ||
8455 | struct checker<optional<T>, type::poly, C> { | ||
8456 | template <typename Handler> | ||
8457 | static bool check(lua_State* L, int index, Handler&&, record& tracking) { | ||
8458 | type t = type_of(L, index); | ||
8459 | if (t == type::none) { | ||
8460 | tracking.use(0); | ||
8461 | return true; | ||
8462 | } | ||
8463 | if (t == type::lua_nil) { | ||
8464 | tracking.use(1); | ||
8465 | return true; | ||
8466 | } | ||
8467 | return stack::check<T>(L, index, no_panic, tracking); | ||
8468 | } | ||
8469 | }; | ||
8470 | |||
8471 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
8472 | #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT | ||
8473 | template <typename... Tn, typename C> | ||
8474 | struct checker<std::variant<Tn...>, type::poly, C> { | ||
8475 | typedef std::variant<Tn...> V; | ||
8476 | typedef std::variant_size<V> V_size; | ||
8477 | typedef std::integral_constant<bool, V_size::value == 0> V_is_empty; | ||
8478 | |||
8479 | template <typename Handler> | ||
8480 | static bool is_one(std::integral_constant<std::size_t, 0>, lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8481 | if (V_is_empty::value && lua_isnone(L, index)) { | ||
8482 | return true; | ||
8483 | } | ||
8484 | tracking.use(1); | ||
8485 | handler(L, index, type::poly, type_of(L, index), "value does not fit any type present in the variant"); | ||
8486 | return false; | ||
8487 | } | ||
8488 | |||
8489 | template <std::size_t I, typename Handler> | ||
8490 | static bool is_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8491 | typedef std::variant_alternative_t<I - 1, V> T; | ||
8492 | if (stack::check<T>(L, index, no_panic, tracking)) { | ||
8493 | return true; | ||
8494 | } | ||
8495 | return is_one(std::integral_constant<std::size_t, I - 1>(), L, index, std::forward<Handler>(handler), tracking); | ||
8496 | } | ||
8497 | |||
8498 | template <typename Handler> | ||
8499 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
8500 | return is_one(std::integral_constant<std::size_t, V_size::value>(), L, index, std::forward<Handler>(handler), tracking); | ||
8501 | } | ||
8502 | }; | ||
8503 | #endif // SOL_STD_VARIANT | ||
8504 | #endif // SOL_CXX17_FEATURES | ||
8505 | } | ||
8506 | } // namespace sol::stack | ||
8507 | |||
8508 | // end of sol/stack_check.hpp | ||
8509 | |||
8510 | // beginning of sol/stack_get.hpp | ||
8511 | |||
8512 | // beginning of sol/overload.hpp | ||
8513 | |||
8514 | namespace sol { | ||
8515 | template <typename... Functions> | ||
8516 | struct overload_set { | ||
8517 | std::tuple<Functions...> functions; | ||
8518 | template <typename Arg, typename... Args, meta::disable<std::is_same<overload_set, meta::unqualified_t<Arg>>> = meta::enabler> | ||
8519 | overload_set(Arg&& arg, Args&&... args) | ||
8520 | : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) { | ||
8521 | } | ||
8522 | overload_set(const overload_set&) = default; | ||
8523 | overload_set(overload_set&&) = default; | ||
8524 | overload_set& operator=(const overload_set&) = default; | ||
8525 | overload_set& operator=(overload_set&&) = default; | ||
8526 | }; | ||
8527 | |||
8528 | template <typename... Args> | ||
8529 | decltype(auto) overload(Args&&... args) { | ||
8530 | return overload_set<std::decay_t<Args>...>(std::forward<Args>(args)...); | ||
8531 | } | ||
8532 | } // namespace sol | ||
8533 | |||
8534 | // end of sol/overload.hpp | ||
8535 | |||
8536 | // beginning of sol/unicode.hpp | ||
8537 | |||
8538 | namespace sol { | ||
8539 | // Everything here was lifted pretty much straight out of | ||
8540 | // ogonek, because fuck figuring it out= | ||
8541 | namespace unicode { | ||
8542 | enum class error_code { | ||
8543 | ok = 0, | ||
8544 | invalid_code_point, | ||
8545 | invalid_code_unit, | ||
8546 | invalid_leading_surrogate, | ||
8547 | invalid_trailing_surrogate, | ||
8548 | sequence_too_short, | ||
8549 | overlong_sequence, | ||
8550 | }; | ||
8551 | |||
8552 | inline const string_view& to_string(error_code ec) { | ||
8553 | static const string_view arr[4] = { | ||
8554 | "ok", | ||
8555 | "invalid code points", | ||
8556 | "invalid code unit", | ||
8557 | "overlong sequence" | ||
8558 | }; | ||
8559 | return arr[static_cast<std::size_t>(ec)]; | ||
8560 | } | ||
8561 | |||
8562 | template <typename It> | ||
8563 | struct decoded_result { | ||
8564 | error_code error; | ||
8565 | char32_t codepoint; | ||
8566 | It next; | ||
8567 | }; | ||
8568 | |||
8569 | template <typename C> | ||
8570 | struct encoded_result { | ||
8571 | error_code error; | ||
8572 | std::size_t code_units_size; | ||
8573 | std::array<C, 4> code_units; | ||
8574 | }; | ||
8575 | |||
8576 | struct unicode_detail { | ||
8577 | // codepoint related | ||
8578 | static constexpr char32_t last_code_point = 0x10FFFF; | ||
8579 | |||
8580 | static constexpr char32_t first_lead_surrogate = 0xD800; | ||
8581 | static constexpr char32_t last_lead_surrogate = 0xDBFF; | ||
8582 | |||
8583 | static constexpr char32_t first_trail_surrogate = 0xDC00; | ||
8584 | static constexpr char32_t last_trail_surrogate = 0xDFFF; | ||
8585 | |||
8586 | static constexpr char32_t first_surrogate = first_lead_surrogate; | ||
8587 | static constexpr char32_t last_surrogate = last_trail_surrogate; | ||
8588 | |||
8589 | static constexpr bool is_lead_surrogate(char32_t u) { | ||
8590 | return u >= first_lead_surrogate && u <= last_lead_surrogate; | ||
8591 | } | ||
8592 | static constexpr bool is_trail_surrogate(char32_t u) { | ||
8593 | return u >= first_trail_surrogate && u <= last_trail_surrogate; | ||
8594 | } | ||
8595 | static constexpr bool is_surrogate(char32_t u) { | ||
8596 | return u >= first_surrogate && u <= last_surrogate; | ||
8597 | } | ||
8598 | |||
8599 | // utf8 related | ||
8600 | static constexpr auto last_1byte_value = 0x7Fu; | ||
8601 | static constexpr auto last_2byte_value = 0x7FFu; | ||
8602 | static constexpr auto last_3byte_value = 0xFFFFu; | ||
8603 | |||
8604 | static constexpr auto start_2byte_mask = 0x80u; | ||
8605 | static constexpr auto start_3byte_mask = 0xE0u; | ||
8606 | static constexpr auto start_4byte_mask = 0xF0u; | ||
8607 | |||
8608 | static constexpr auto continuation_mask = 0xC0u; | ||
8609 | static constexpr auto continuation_signature = 0x80u; | ||
8610 | |||
8611 | static constexpr int sequence_length(unsigned char b) { | ||
8612 | return (b & start_2byte_mask) == 0 ? 1 | ||
8613 | : (b & start_3byte_mask) != start_3byte_mask ? 2 | ||
8614 | : (b & start_4byte_mask) != start_4byte_mask ? 3 | ||
8615 | : 4; | ||
8616 | } | ||
8617 | |||
8618 | static constexpr char32_t decode(unsigned char b0, unsigned char b1) { | ||
8619 | return ((b0 & 0x1F) << 6) | (b1 & 0x3F); | ||
8620 | } | ||
8621 | static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2) { | ||
8622 | return ((b0 & 0x0F) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F); | ||
8623 | } | ||
8624 | static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3) { | ||
8625 | return ((b0 & 0x07) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F); | ||
8626 | } | ||
8627 | |||
8628 | // utf16 related | ||
8629 | static constexpr char32_t last_bmp_value = 0xFFFF; | ||
8630 | static constexpr char32_t normalizing_value = 0x10000; | ||
8631 | static constexpr int lead_surrogate_bitmask = 0xFFC00; | ||
8632 | static constexpr int trail_surrogate_bitmask = 0x3FF; | ||
8633 | static constexpr int lead_shifted_bits = 10; | ||
8634 | static constexpr char32_t replacement = 0xFFFD; | ||
8635 | |||
8636 | static char32_t combine_surrogates(char16_t lead, char16_t trail) { | ||
8637 | auto hi = lead - first_lead_surrogate; | ||
8638 | auto lo = trail - first_trail_surrogate; | ||
8639 | return normalizing_value + ((hi << lead_shifted_bits) | lo); | ||
8640 | } | ||
8641 | }; | ||
8642 | |||
8643 | inline encoded_result<char> code_point_to_utf8(char32_t codepoint) { | ||
8644 | encoded_result<char> er; | ||
8645 | er.error = error_code::ok; | ||
8646 | if (codepoint <= unicode_detail::last_1byte_value) { | ||
8647 | er.code_units_size = 1; | ||
8648 | er.code_units = std::array<char, 4>{ { static_cast<char>(codepoint) } }; | ||
8649 | } | ||
8650 | else if (codepoint <= unicode_detail::last_2byte_value) { | ||
8651 | er.code_units_size = 2; | ||
8652 | er.code_units = std::array<char, 4>{{ | ||
8653 | static_cast<char>(0xC0 | ((codepoint & 0x7C0) >> 6)), | ||
8654 | static_cast<char>(0x80 | (codepoint & 0x3F)), | ||
8655 | }}; | ||
8656 | } | ||
8657 | else if (codepoint <= unicode_detail::last_3byte_value) { | ||
8658 | er.code_units_size = 3; | ||
8659 | er.code_units = std::array<char, 4>{{ | ||
8660 | static_cast<char>(0xE0 | ((codepoint & 0xF000) >> 12)), | ||
8661 | static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)), | ||
8662 | static_cast<char>(0x80 | (codepoint & 0x3F)), | ||
8663 | }}; | ||
8664 | } | ||
8665 | else { | ||
8666 | er.code_units_size = 4; | ||
8667 | er.code_units = std::array<char, 4>{ { | ||
8668 | static_cast<char>(0xF0 | ((codepoint & 0x1C0000) >> 18)), | ||
8669 | static_cast<char>(0x80 | ((codepoint & 0x3F000) >> 12)), | ||
8670 | static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)), | ||
8671 | static_cast<char>(0x80 | (codepoint & 0x3F)), | ||
8672 | } }; | ||
8673 | } | ||
8674 | return er; | ||
8675 | } | ||
8676 | |||
8677 | inline encoded_result<char16_t> code_point_to_utf16(char32_t codepoint) { | ||
8678 | encoded_result<char16_t> er; | ||
8679 | |||
8680 | if (codepoint <= unicode_detail::last_bmp_value) { | ||
8681 | er.code_units_size = 1; | ||
8682 | er.code_units = std::array<char16_t, 4>{ { static_cast<char16_t>(codepoint) } }; | ||
8683 | er.error = error_code::ok; | ||
8684 | } | ||
8685 | else { | ||
8686 | auto normal = codepoint - unicode_detail::normalizing_value; | ||
8687 | auto lead = unicode_detail::first_lead_surrogate + ((normal & unicode_detail::lead_surrogate_bitmask) >> unicode_detail::lead_shifted_bits); | ||
8688 | auto trail = unicode_detail::first_trail_surrogate + (normal & unicode_detail::trail_surrogate_bitmask); | ||
8689 | er.code_units = std::array<char16_t, 4>{ { | ||
8690 | static_cast<char16_t>(lead), | ||
8691 | static_cast<char16_t>(trail) | ||
8692 | } }; | ||
8693 | er.code_units_size = 2; | ||
8694 | er.error = error_code::ok; | ||
8695 | } | ||
8696 | return er; | ||
8697 | } | ||
8698 | |||
8699 | inline encoded_result<char32_t> code_point_to_utf32(char32_t codepoint) { | ||
8700 | encoded_result<char32_t> er; | ||
8701 | er.code_units_size = 1; | ||
8702 | er.code_units[0] = codepoint; | ||
8703 | er.error = error_code::ok; | ||
8704 | return er; | ||
8705 | } | ||
8706 | |||
8707 | template <typename It> | ||
8708 | inline decoded_result<It> utf8_to_code_point(It it, It last) { | ||
8709 | decoded_result<It> dr; | ||
8710 | if (it == last) { | ||
8711 | dr.next = it; | ||
8712 | dr.error = error_code::sequence_too_short; | ||
8713 | return dr; | ||
8714 | } | ||
8715 | |||
8716 | unsigned char b0 = *it; | ||
8717 | std::size_t length = unicode_detail::sequence_length(b0); | ||
8718 | |||
8719 | if (length == 1) { | ||
8720 | dr.codepoint = static_cast<char32_t>(b0); | ||
8721 | dr.error = error_code::ok; | ||
8722 | ++it; | ||
8723 | dr.next = it; | ||
8724 | return dr; | ||
8725 | } | ||
8726 | |||
8727 | auto is_invalid = [](unsigned char b) { return b == 0xC0 || b == 0xC1 || b > 0xF4; }; | ||
8728 | auto is_continuation = [](unsigned char b) { | ||
8729 | return (b & unicode_detail::continuation_mask) == unicode_detail::continuation_signature; | ||
8730 | }; | ||
8731 | |||
8732 | if (is_invalid(b0) || is_continuation(b0)) { | ||
8733 | dr.error = error_code::invalid_code_unit; | ||
8734 | dr.next = it; | ||
8735 | return dr; | ||
8736 | } | ||
8737 | |||
8738 | ++it; | ||
8739 | std::array<unsigned char, 4> b; | ||
8740 | b[0] = b0; | ||
8741 | for (std::size_t i = 1; i < length; ++i) { | ||
8742 | b[i] = *it; | ||
8743 | if (!is_continuation(b[i])) { | ||
8744 | dr.error = error_code::invalid_code_unit; | ||
8745 | dr.next = it; | ||
8746 | return dr; | ||
8747 | } | ||
8748 | ++it; | ||
8749 | } | ||
8750 | |||
8751 | char32_t decoded; | ||
8752 | switch (length) { | ||
8753 | case 2: | ||
8754 | decoded = unicode_detail::decode(b[0], b[1]); | ||
8755 | break; | ||
8756 | case 3: | ||
8757 | decoded = unicode_detail::decode(b[0], b[1], b[2]); | ||
8758 | break; | ||
8759 | default: | ||
8760 | decoded = unicode_detail::decode(b[0], b[1], b[2], b[3]); | ||
8761 | break; | ||
8762 | } | ||
8763 | |||
8764 | auto is_overlong = [](char32_t u, std::size_t bytes) { | ||
8765 | return u <= unicode_detail::last_1byte_value | ||
8766 | || (u <= unicode_detail::last_2byte_value && bytes > 2) | ||
8767 | || (u <= unicode_detail::last_3byte_value && bytes > 3); | ||
8768 | }; | ||
8769 | if (is_overlong(decoded, length)) { | ||
8770 | dr.error = error_code::overlong_sequence; | ||
8771 | return dr; | ||
8772 | } | ||
8773 | if (unicode_detail::is_surrogate(decoded) || decoded > unicode_detail::last_code_point) { | ||
8774 | dr.error = error_code::invalid_code_point; | ||
8775 | return dr; | ||
8776 | } | ||
8777 | |||
8778 | // then everything is fine | ||
8779 | dr.codepoint = decoded; | ||
8780 | dr.error = error_code::ok; | ||
8781 | dr.next = it; | ||
8782 | return dr; | ||
8783 | } | ||
8784 | |||
8785 | template <typename It> | ||
8786 | inline decoded_result<It> utf16_to_code_point(It it, It last) { | ||
8787 | decoded_result<It> dr; | ||
8788 | if (it == last) { | ||
8789 | dr.next = it; | ||
8790 | dr.error = error_code::sequence_too_short; | ||
8791 | return dr; | ||
8792 | } | ||
8793 | |||
8794 | char16_t lead = static_cast<char16_t>(*it); | ||
8795 | |||
8796 | if (!unicode_detail::is_surrogate(lead)) { | ||
8797 | ++it; | ||
8798 | dr.codepoint = static_cast<char32_t>(lead); | ||
8799 | dr.next = it; | ||
8800 | dr.error = error_code::ok; | ||
8801 | return dr; | ||
8802 | } | ||
8803 | if (!unicode_detail::is_lead_surrogate(lead)) { | ||
8804 | dr.error = error_code::invalid_leading_surrogate; | ||
8805 | dr.next = it; | ||
8806 | return dr; | ||
8807 | } | ||
8808 | |||
8809 | ++it; | ||
8810 | auto trail = *it; | ||
8811 | if (!unicode_detail::is_trail_surrogate(trail)) { | ||
8812 | dr.error = error_code::invalid_trailing_surrogate; | ||
8813 | dr.next = it; | ||
8814 | return dr; | ||
8815 | } | ||
8816 | |||
8817 | dr.codepoint = unicode_detail::combine_surrogates(lead, trail); | ||
8818 | dr.next = ++it; | ||
8819 | dr.error = error_code::ok; | ||
8820 | return dr; | ||
8821 | } | ||
8822 | |||
8823 | template <typename It> | ||
8824 | inline decoded_result<It> utf32_to_code_point(It it, It last) { | ||
8825 | decoded_result<It> dr; | ||
8826 | if (it == last) { | ||
8827 | dr.next = it; | ||
8828 | dr.error = error_code::sequence_too_short; | ||
8829 | return dr; | ||
8830 | } | ||
8831 | dr.codepoint = static_cast<char32_t>(*it); | ||
8832 | dr.next = ++it; | ||
8833 | dr.error = error_code::ok; | ||
8834 | return dr; | ||
8835 | } | ||
8836 | } | ||
8837 | } | ||
8838 | // end of sol/unicode.hpp | ||
8839 | |||
8840 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
8841 | #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT | ||
8842 | #endif // Apple clang screwed up | ||
8843 | #endif // C++17 | ||
8844 | |||
8845 | namespace sol { | ||
8846 | namespace stack { | ||
8847 | |||
8848 | template <typename U> | ||
8849 | struct userdata_getter<U> { | ||
8850 | typedef stack_detail::strip_extensible_t<U> T; | ||
8851 | |||
8852 | static std::pair<bool, T*> get(lua_State*, int, void*, record&) { | ||
8853 | return { false, nullptr }; | ||
8854 | } | ||
8855 | }; | ||
8856 | |||
8857 | template <typename T, typename> | ||
8858 | struct getter { | ||
8859 | static T& get(lua_State* L, int index, record& tracking) { | ||
8860 | return getter<detail::as_value_tag<T>>{}.get(L, index, tracking); | ||
8861 | } | ||
8862 | }; | ||
8863 | |||
8864 | template <typename T> | ||
8865 | struct getter<T, std::enable_if_t<std::is_floating_point<T>::value>> { | ||
8866 | static T get(lua_State* L, int index, record& tracking) { | ||
8867 | tracking.use(1); | ||
8868 | return static_cast<T>(lua_tonumber(L, index)); | ||
8869 | } | ||
8870 | }; | ||
8871 | |||
8872 | template <typename T> | ||
8873 | struct getter<T, std::enable_if_t<std::is_integral<T>::value>> { | ||
8874 | static T get(lua_State* L, int index, record& tracking) { | ||
8875 | tracking.use(1); | ||
8876 | #if SOL_LUA_VERSION >= 503 | ||
8877 | if (lua_isinteger(L, index) != 0) { | ||
8878 | return static_cast<T>(lua_tointeger(L, index)); | ||
8879 | } | ||
8880 | #endif | ||
8881 | return static_cast<T>(llround(lua_tonumber(L, index))); | ||
8882 | } | ||
8883 | }; | ||
8884 | |||
8885 | template <typename T> | ||
8886 | struct getter<T, std::enable_if_t<std::is_enum<T>::value>> { | ||
8887 | static T get(lua_State* L, int index, record& tracking) { | ||
8888 | tracking.use(1); | ||
8889 | return static_cast<T>(lua_tointegerx(L, index, nullptr)); | ||
8890 | } | ||
8891 | }; | ||
8892 | |||
8893 | template <typename T> | ||
8894 | struct getter<as_table_t<T>> { | ||
8895 | typedef meta::unqualified_t<T> Tu; | ||
8896 | |||
8897 | template <typename V> | ||
8898 | static void push_back_at_end(std::true_type, types<V>, lua_State* L, T& arr, std::size_t) { | ||
8899 | arr.push_back(stack::get<V>(L, -lua_size<V>::value)); | ||
8900 | } | ||
8901 | |||
8902 | template <typename V> | ||
8903 | static void push_back_at_end(std::false_type, types<V> t, lua_State* L, T& arr, std::size_t idx) { | ||
8904 | insert_at_end(meta::has_insert<Tu>(), t, L, arr, idx); | ||
8905 | } | ||
8906 | |||
8907 | template <typename V> | ||
8908 | static void insert_at_end(std::true_type, types<V>, lua_State* L, T& arr, std::size_t) { | ||
8909 | using std::end; | ||
8910 | arr.insert(end(arr), stack::get<V>(L, -lua_size<V>::value)); | ||
8911 | } | ||
8912 | |||
8913 | template <typename V> | ||
8914 | static void insert_at_end(std::false_type, types<V>, lua_State* L, T& arr, std::size_t idx) { | ||
8915 | arr[idx] = stack::get<V>(L, -lua_size<V>::value); | ||
8916 | } | ||
8917 | |||
8918 | static T get(lua_State* L, int relindex, record& tracking) { | ||
8919 | return get(meta::has_key_value_pair<meta::unqualified_t<T>>(), L, relindex, tracking); | ||
8920 | } | ||
8921 | |||
8922 | static T get(std::false_type, lua_State* L, int relindex, record& tracking) { | ||
8923 | typedef typename T::value_type V; | ||
8924 | return get(types<V>(), L, relindex, tracking); | ||
8925 | } | ||
8926 | |||
8927 | template <typename V> | ||
8928 | static T get(types<V> t, lua_State* L, int relindex, record& tracking) { | ||
8929 | tracking.use(1); | ||
8930 | |||
8931 | int index = lua_absindex(L, relindex); | ||
8932 | T arr; | ||
8933 | std::size_t idx = 0; | ||
8934 | #if SOL_LUA_VERSION >= 503 | ||
8935 | // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 | ||
8936 | for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { | ||
8937 | if (idx >= arr.max_size()) { | ||
8938 | return arr; | ||
8939 | } | ||
8940 | bool isnil = false; | ||
8941 | for (int vi = 0; vi < lua_size<V>::value; ++vi) { | ||
8942 | type vt = static_cast<type>(lua_geti(L, index, i + vi)); | ||
8943 | isnil = vt == type::lua_nil; | ||
8944 | if (isnil) { | ||
8945 | if (i == 0) { | ||
8946 | break; | ||
8947 | } | ||
8948 | lua_pop(L, (vi + 1)); | ||
8949 | return arr; | ||
8950 | } | ||
8951 | } | ||
8952 | if (isnil) | ||
8953 | continue; | ||
8954 | push_back_at_end(meta::has_push_back<Tu>(), t, L, arr, idx); | ||
8955 | ++idx; | ||
8956 | } | ||
8957 | #else | ||
8958 | // Zzzz slower but necessary thanks to the lower version API and missing functions qq | ||
8959 | for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { | ||
8960 | if (idx >= arr.max_size()) { | ||
8961 | return arr; | ||
8962 | } | ||
8963 | bool isnil = false; | ||
8964 | for (int vi = 0; vi < lua_size<V>::value; ++vi) { | ||
8965 | lua_pushinteger(L, i); | ||
8966 | lua_gettable(L, index); | ||
8967 | type vt = type_of(L, -1); | ||
8968 | isnil = vt == type::lua_nil; | ||
8969 | if (isnil) { | ||
8970 | if (i == 0) { | ||
8971 | break; | ||
8972 | } | ||
8973 | lua_pop(L, (vi + 1)); | ||
8974 | return arr; | ||
8975 | } | ||
8976 | } | ||
8977 | if (isnil) | ||
8978 | continue; | ||
8979 | push_back_at_end(meta::has_push_back<Tu>(), t, L, arr, idx); | ||
8980 | ++idx; | ||
8981 | } | ||
8982 | #endif | ||
8983 | return arr; | ||
8984 | } | ||
8985 | |||
8986 | static T get(std::true_type, lua_State* L, int index, record& tracking) { | ||
8987 | typedef typename T::value_type P; | ||
8988 | typedef typename P::first_type K; | ||
8989 | typedef typename P::second_type V; | ||
8990 | return get(types<K, V>(), L, index, tracking); | ||
8991 | } | ||
8992 | |||
8993 | template <typename K, typename V> | ||
8994 | static T get(types<K, V>, lua_State* L, int relindex, record& tracking) { | ||
8995 | tracking.use(1); | ||
8996 | |||
8997 | T associative; | ||
8998 | int index = lua_absindex(L, relindex); | ||
8999 | lua_pushnil(L); | ||
9000 | while (lua_next(L, index) != 0) { | ||
9001 | decltype(auto) key = stack::check_get<K>(L, -2); | ||
9002 | if (!key) { | ||
9003 | lua_pop(L, 1); | ||
9004 | continue; | ||
9005 | } | ||
9006 | associative.emplace(std::forward<decltype(*key)>(*key), stack::get<V>(L, -1)); | ||
9007 | lua_pop(L, 1); | ||
9008 | } | ||
9009 | return associative; | ||
9010 | } | ||
9011 | }; | ||
9012 | |||
9013 | template <typename T, typename Al> | ||
9014 | struct getter<as_table_t<std::forward_list<T, Al>>> { | ||
9015 | typedef std::forward_list<T, Al> C; | ||
9016 | |||
9017 | static C get(lua_State* L, int relindex, record& tracking) { | ||
9018 | return get(meta::has_key_value_pair<C>(), L, relindex, tracking); | ||
9019 | } | ||
9020 | |||
9021 | static C get(std::true_type, lua_State* L, int index, record& tracking) { | ||
9022 | typedef typename T::value_type P; | ||
9023 | typedef typename P::first_type K; | ||
9024 | typedef typename P::second_type V; | ||
9025 | return get(types<K, V>(), L, index, tracking); | ||
9026 | } | ||
9027 | |||
9028 | static C get(std::false_type, lua_State* L, int relindex, record& tracking) { | ||
9029 | typedef typename C::value_type V; | ||
9030 | return get(types<V>(), L, relindex, tracking); | ||
9031 | } | ||
9032 | |||
9033 | template <typename V> | ||
9034 | static C get(types<V>, lua_State* L, int relindex, record& tracking) { | ||
9035 | tracking.use(1); | ||
9036 | |||
9037 | int index = lua_absindex(L, relindex); | ||
9038 | C arr; | ||
9039 | auto at = arr.cbefore_begin(); | ||
9040 | std::size_t idx = 0; | ||
9041 | #if SOL_LUA_VERSION >= 503 | ||
9042 | // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 | ||
9043 | for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { | ||
9044 | if (idx >= arr.max_size()) { | ||
9045 | return arr; | ||
9046 | } | ||
9047 | bool isnil = false; | ||
9048 | for (int vi = 0; vi < lua_size<V>::value; ++vi) { | ||
9049 | type t = static_cast<type>(lua_geti(L, index, i + vi)); | ||
9050 | isnil = t == type::lua_nil; | ||
9051 | if (isnil) { | ||
9052 | if (i == 0) { | ||
9053 | break; | ||
9054 | } | ||
9055 | lua_pop(L, (vi + 1)); | ||
9056 | return arr; | ||
9057 | } | ||
9058 | } | ||
9059 | if (isnil) | ||
9060 | continue; | ||
9061 | at = arr.insert_after(at, stack::get<V>(L, -lua_size<V>::value)); | ||
9062 | ++idx; | ||
9063 | } | ||
9064 | #else | ||
9065 | // Zzzz slower but necessary thanks to the lower version API and missing functions qq | ||
9066 | for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { | ||
9067 | if (idx >= arr.max_size()) { | ||
9068 | return arr; | ||
9069 | } | ||
9070 | bool isnil = false; | ||
9071 | for (int vi = 0; vi < lua_size<V>::value; ++vi) { | ||
9072 | lua_pushinteger(L, i); | ||
9073 | lua_gettable(L, index); | ||
9074 | type t = type_of(L, -1); | ||
9075 | isnil = t == type::lua_nil; | ||
9076 | if (isnil) { | ||
9077 | if (i == 0) { | ||
9078 | break; | ||
9079 | } | ||
9080 | lua_pop(L, (vi + 1)); | ||
9081 | return arr; | ||
9082 | } | ||
9083 | } | ||
9084 | if (isnil) | ||
9085 | continue; | ||
9086 | at = arr.insert_after(at, stack::get<V>(L, -lua_size<V>::value)); | ||
9087 | ++idx; | ||
9088 | } | ||
9089 | #endif | ||
9090 | return arr; | ||
9091 | } | ||
9092 | |||
9093 | template <typename K, typename V> | ||
9094 | static C get(types<K, V>, lua_State* L, int relindex, record& tracking) { | ||
9095 | tracking.use(1); | ||
9096 | |||
9097 | C associative; | ||
9098 | auto at = associative.cbefore_begin(); | ||
9099 | int index = lua_absindex(L, relindex); | ||
9100 | lua_pushnil(L); | ||
9101 | while (lua_next(L, index) != 0) { | ||
9102 | decltype(auto) key = stack::check_get<K>(L, -2); | ||
9103 | if (!key) { | ||
9104 | lua_pop(L, 1); | ||
9105 | continue; | ||
9106 | } | ||
9107 | at = associative.emplace_after(at, std::forward<decltype(*key)>(*key), stack::get<V>(L, -1)); | ||
9108 | lua_pop(L, 1); | ||
9109 | } | ||
9110 | return associative; | ||
9111 | } | ||
9112 | }; | ||
9113 | |||
9114 | template <typename T> | ||
9115 | struct getter<nested<T>, std::enable_if_t<!is_container<T>::value>> { | ||
9116 | static T get(lua_State* L, int index, record& tracking) { | ||
9117 | getter<T> g; | ||
9118 | // VC++ has a bad warning here: shut it up | ||
9119 | (void)g; | ||
9120 | return g.get(L, index, tracking); | ||
9121 | } | ||
9122 | }; | ||
9123 | |||
9124 | template <typename T> | ||
9125 | struct getter<nested<T>, std::enable_if_t<meta::all<is_container<T>, meta::neg<meta::has_key_value_pair<meta::unqualified_t<T>>>>::value>> { | ||
9126 | static T get(lua_State* L, int index, record& tracking) { | ||
9127 | typedef typename T::value_type V; | ||
9128 | getter<as_table_t<T>> g; | ||
9129 | // VC++ has a bad warning here: shut it up | ||
9130 | (void)g; | ||
9131 | return g.get(types<nested<V>>(), L, index, tracking); | ||
9132 | } | ||
9133 | }; | ||
9134 | |||
9135 | template <typename T> | ||
9136 | struct getter<nested<T>, std::enable_if_t<meta::all<is_container<T>, meta::has_key_value_pair<meta::unqualified_t<T>>>::value>> { | ||
9137 | static T get(lua_State* L, int index, record& tracking) { | ||
9138 | typedef typename T::value_type P; | ||
9139 | typedef typename P::first_type K; | ||
9140 | typedef typename P::second_type V; | ||
9141 | getter<as_table_t<T>> g; | ||
9142 | // VC++ has a bad warning here: shut it up | ||
9143 | (void)g; | ||
9144 | return g.get(types<K, nested<V>>(), L, index, tracking); | ||
9145 | } | ||
9146 | }; | ||
9147 | |||
9148 | template <typename T> | ||
9149 | struct getter<T, std::enable_if_t<is_lua_reference<T>::value>> { | ||
9150 | static T get(lua_State* L, int index, record& tracking) { | ||
9151 | tracking.use(1); | ||
9152 | return T(L, index); | ||
9153 | } | ||
9154 | }; | ||
9155 | |||
9156 | template <> | ||
9157 | struct getter<userdata_value> { | ||
9158 | static userdata_value get(lua_State* L, int index, record& tracking) { | ||
9159 | tracking.use(1); | ||
9160 | return userdata_value(lua_touserdata(L, index)); | ||
9161 | } | ||
9162 | }; | ||
9163 | |||
9164 | template <> | ||
9165 | struct getter<lightuserdata_value> { | ||
9166 | static lightuserdata_value get(lua_State* L, int index, record& tracking) { | ||
9167 | tracking.use(1); | ||
9168 | return lightuserdata_value(lua_touserdata(L, index)); | ||
9169 | } | ||
9170 | }; | ||
9171 | |||
9172 | template <typename T> | ||
9173 | struct getter<light<T>> { | ||
9174 | static light<T> get(lua_State* L, int index, record& tracking) { | ||
9175 | tracking.use(1); | ||
9176 | void* memory = lua_touserdata(L, index); | ||
9177 | return light<T>(static_cast<T*>(memory)); | ||
9178 | } | ||
9179 | }; | ||
9180 | |||
9181 | template <typename T> | ||
9182 | struct getter<user<T>> { | ||
9183 | static std::add_lvalue_reference_t<T> get(lua_State* L, int index, record& tracking) { | ||
9184 | tracking.use(1); | ||
9185 | void* memory = lua_touserdata(L, index); | ||
9186 | memory = detail::align_user<T>(memory); | ||
9187 | return *static_cast<std::remove_reference_t<T>*>(memory); | ||
9188 | } | ||
9189 | }; | ||
9190 | |||
9191 | template <typename T> | ||
9192 | struct getter<user<T*>> { | ||
9193 | static T* get(lua_State* L, int index, record& tracking) { | ||
9194 | tracking.use(1); | ||
9195 | void* memory = lua_touserdata(L, index); | ||
9196 | memory = detail::align_user<T*>(memory); | ||
9197 | return static_cast<T*>(memory); | ||
9198 | } | ||
9199 | }; | ||
9200 | |||
9201 | template <> | ||
9202 | struct getter<type> { | ||
9203 | static type get(lua_State* L, int index, record& tracking) { | ||
9204 | tracking.use(1); | ||
9205 | return static_cast<type>(lua_type(L, index)); | ||
9206 | } | ||
9207 | }; | ||
9208 | |||
9209 | template <> | ||
9210 | struct getter<bool> { | ||
9211 | static bool get(lua_State* L, int index, record& tracking) { | ||
9212 | tracking.use(1); | ||
9213 | return lua_toboolean(L, index) != 0; | ||
9214 | } | ||
9215 | }; | ||
9216 | |||
9217 | template <> | ||
9218 | struct getter<std::string> { | ||
9219 | static std::string get(lua_State* L, int index, record& tracking) { | ||
9220 | tracking.use(1); | ||
9221 | std::size_t len; | ||
9222 | auto str = lua_tolstring(L, index, &len); | ||
9223 | return std::string(str, len); | ||
9224 | } | ||
9225 | }; | ||
9226 | |||
9227 | template <> | ||
9228 | struct getter<const char*> { | ||
9229 | static const char* get(lua_State* L, int index, record& tracking) { | ||
9230 | tracking.use(1); | ||
9231 | size_t sz; | ||
9232 | return lua_tolstring(L, index, &sz); | ||
9233 | } | ||
9234 | }; | ||
9235 | |||
9236 | template <> | ||
9237 | struct getter<char> { | ||
9238 | static char get(lua_State* L, int index, record& tracking) { | ||
9239 | tracking.use(1); | ||
9240 | size_t len; | ||
9241 | auto str = lua_tolstring(L, index, &len); | ||
9242 | return len > 0 ? str[0] : '\0'; | ||
9243 | } | ||
9244 | }; | ||
9245 | |||
9246 | template <typename Traits> | ||
9247 | struct getter<basic_string_view<char, Traits>> { | ||
9248 | static string_view get(lua_State* L, int index, record& tracking) { | ||
9249 | tracking.use(1); | ||
9250 | size_t sz; | ||
9251 | const char* str = lua_tolstring(L, index, &sz); | ||
9252 | return basic_string_view<char, Traits>(str, sz); | ||
9253 | } | ||
9254 | }; | ||
9255 | |||
9256 | template <typename Traits, typename Al> | ||
9257 | struct getter<std::basic_string<wchar_t, Traits, Al>> { | ||
9258 | typedef std::basic_string<wchar_t, Traits, Al> S; | ||
9259 | static S get(lua_State* L, int index, record& tracking) { | ||
9260 | typedef std::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t> Ch; | ||
9261 | typedef typename std::allocator_traits<Al>::template rebind_alloc<Ch> ChAl; | ||
9262 | typedef std::char_traits<Ch> ChTraits; | ||
9263 | getter<std::basic_string<Ch, ChTraits, ChAl>> g; | ||
9264 | (void)g; | ||
9265 | return g.template get_into<S>(L, index, tracking); | ||
9266 | } | ||
9267 | }; | ||
9268 | |||
9269 | template <typename Traits, typename Al> | ||
9270 | struct getter<std::basic_string<char16_t, Traits, Al>> { | ||
9271 | template <typename F> | ||
9272 | static void convert(const char* strb, const char* stre, F&& f) { | ||
9273 | char32_t cp = 0; | ||
9274 | for (const char* strtarget = strb; strtarget < stre;) { | ||
9275 | auto dr = unicode::utf8_to_code_point(strtarget, stre); | ||
9276 | if (dr.error != unicode::error_code::ok) { | ||
9277 | cp = unicode::unicode_detail::replacement; | ||
9278 | ++strtarget; | ||
9279 | } | ||
9280 | else { | ||
9281 | cp = dr.codepoint; | ||
9282 | strtarget = dr.next; | ||
9283 | } | ||
9284 | auto er = unicode::code_point_to_utf16(cp); | ||
9285 | f(er); | ||
9286 | } | ||
9287 | } | ||
9288 | |||
9289 | template <typename S> | ||
9290 | static S get_into(lua_State* L, int index, record& tracking) { | ||
9291 | typedef typename S::value_type Ch; | ||
9292 | tracking.use(1); | ||
9293 | size_t len; | ||
9294 | auto utf8p = lua_tolstring(L, index, &len); | ||
9295 | if (len < 1) | ||
9296 | return S(); | ||
9297 | std::size_t needed_size = 0; | ||
9298 | const char* strb = utf8p; | ||
9299 | const char* stre = utf8p + len; | ||
9300 | auto count_units = [&needed_size](const unicode::encoded_result<char16_t> er) { | ||
9301 | needed_size += er.code_units_size; | ||
9302 | }; | ||
9303 | convert(strb, stre, count_units); | ||
9304 | S r(needed_size, static_cast<Ch>(0)); | ||
9305 | r.resize(needed_size); | ||
9306 | Ch* target = &r[0]; | ||
9307 | auto copy_units = [&target](const unicode::encoded_result<char16_t> er) { | ||
9308 | std::memcpy(target, er.code_units.data(), er.code_units_size * sizeof(Ch)); | ||
9309 | target += er.code_units_size; | ||
9310 | }; | ||
9311 | convert(strb, stre, copy_units); | ||
9312 | return r; | ||
9313 | } | ||
9314 | |||
9315 | static std::basic_string<char16_t, Traits, Al> get(lua_State* L, int index, record& tracking) { | ||
9316 | return get_into<std::basic_string<char16_t, Traits, Al>>(L, index, tracking); | ||
9317 | } | ||
9318 | }; | ||
9319 | |||
9320 | template <typename Traits, typename Al> | ||
9321 | struct getter<std::basic_string<char32_t, Traits, Al>> { | ||
9322 | template <typename F> | ||
9323 | static void convert(const char* strb, const char* stre, F&& f) { | ||
9324 | char32_t cp = 0; | ||
9325 | for (const char* strtarget = strb; strtarget < stre;) { | ||
9326 | auto dr = unicode::utf8_to_code_point(strtarget, stre); | ||
9327 | if (dr.error != unicode::error_code::ok) { | ||
9328 | cp = unicode::unicode_detail::replacement; | ||
9329 | ++strtarget; | ||
9330 | } | ||
9331 | else { | ||
9332 | cp = dr.codepoint; | ||
9333 | strtarget = dr.next; | ||
9334 | } | ||
9335 | auto er = unicode::code_point_to_utf32(cp); | ||
9336 | f(er); | ||
9337 | } | ||
9338 | } | ||
9339 | |||
9340 | template <typename S> | ||
9341 | static S get_into(lua_State* L, int index, record& tracking) { | ||
9342 | typedef typename S::value_type Ch; | ||
9343 | tracking.use(1); | ||
9344 | size_t len; | ||
9345 | auto utf8p = lua_tolstring(L, index, &len); | ||
9346 | if (len < 1) | ||
9347 | return S(); | ||
9348 | std::size_t needed_size = 0; | ||
9349 | const char* strb = utf8p; | ||
9350 | const char* stre = utf8p + len; | ||
9351 | auto count_units = [&needed_size](const unicode::encoded_result<char32_t> er) { | ||
9352 | needed_size += er.code_units_size; | ||
9353 | }; | ||
9354 | convert(strb, stre, count_units); | ||
9355 | S r(needed_size, static_cast<Ch>(0)); | ||
9356 | r.resize(needed_size); | ||
9357 | Ch* target = &r[0]; | ||
9358 | auto copy_units = [&target](const unicode::encoded_result<char32_t> er) { | ||
9359 | std::memcpy(target, er.code_units.data(), er.code_units_size * sizeof(Ch)); | ||
9360 | target += er.code_units_size; | ||
9361 | }; | ||
9362 | convert(strb, stre, copy_units); | ||
9363 | return r; | ||
9364 | } | ||
9365 | |||
9366 | static std::basic_string<char32_t, Traits, Al> get(lua_State* L, int index, record& tracking) { | ||
9367 | return get_into<std::basic_string<char32_t, Traits, Al>>(L, index, tracking); | ||
9368 | } | ||
9369 | }; | ||
9370 | |||
9371 | template <> | ||
9372 | struct getter<char16_t> { | ||
9373 | static char16_t get(lua_State* L, int index, record& tracking) { | ||
9374 | string_view utf8 = stack::get<string_view>(L, index, tracking); | ||
9375 | const char* strb = utf8.data(); | ||
9376 | const char* stre = utf8.data() + utf8.size(); | ||
9377 | char32_t cp = 0; | ||
9378 | auto dr = unicode::utf8_to_code_point(strb, stre); | ||
9379 | if (dr.error != unicode::error_code::ok) { | ||
9380 | cp = unicode::unicode_detail::replacement; | ||
9381 | } | ||
9382 | else { | ||
9383 | cp = dr.codepoint; | ||
9384 | } | ||
9385 | auto er = unicode::code_point_to_utf16(cp); | ||
9386 | return er.code_units[0]; | ||
9387 | } | ||
9388 | }; | ||
9389 | |||
9390 | template <> | ||
9391 | struct getter<char32_t> { | ||
9392 | static char32_t get(lua_State* L, int index, record& tracking) { | ||
9393 | string_view utf8 = stack::get<string_view>(L, index, tracking); | ||
9394 | const char* strb = utf8.data(); | ||
9395 | const char* stre = utf8.data() + utf8.size(); | ||
9396 | char32_t cp = 0; | ||
9397 | auto dr = unicode::utf8_to_code_point(strb, stre); | ||
9398 | if (dr.error != unicode::error_code::ok) { | ||
9399 | cp = unicode::unicode_detail::replacement; | ||
9400 | } | ||
9401 | else { | ||
9402 | cp = dr.codepoint; | ||
9403 | } | ||
9404 | auto er = unicode::code_point_to_utf32(cp); | ||
9405 | return er.code_units[0]; | ||
9406 | } | ||
9407 | }; | ||
9408 | |||
9409 | template <> | ||
9410 | struct getter<wchar_t> { | ||
9411 | static wchar_t get(lua_State* L, int index, record& tracking) { | ||
9412 | typedef std::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t> Ch; | ||
9413 | getter<Ch> g; | ||
9414 | (void)g; | ||
9415 | auto c = g.get(L, index, tracking); | ||
9416 | return static_cast<wchar_t>(c); | ||
9417 | } | ||
9418 | }; | ||
9419 | |||
9420 | template <> | ||
9421 | struct getter<meta_function> { | ||
9422 | static meta_function get(lua_State* L, int index, record& tracking) { | ||
9423 | tracking.use(1); | ||
9424 | const char* name = getter<const char*>{}.get(L, index, tracking); | ||
9425 | const auto& mfnames = meta_function_names(); | ||
9426 | for (std::size_t i = 0; i < mfnames.size(); ++i) | ||
9427 | if (mfnames[i] == name) | ||
9428 | return static_cast<meta_function>(i); | ||
9429 | return meta_function::construct; | ||
9430 | } | ||
9431 | }; | ||
9432 | |||
9433 | template <> | ||
9434 | struct getter<lua_nil_t> { | ||
9435 | static lua_nil_t get(lua_State*, int, record& tracking) { | ||
9436 | tracking.use(1); | ||
9437 | return lua_nil; | ||
9438 | } | ||
9439 | }; | ||
9440 | |||
9441 | template <> | ||
9442 | struct getter<std::nullptr_t> { | ||
9443 | static std::nullptr_t get(lua_State*, int, record& tracking) { | ||
9444 | tracking.use(1); | ||
9445 | return nullptr; | ||
9446 | } | ||
9447 | }; | ||
9448 | |||
9449 | template <> | ||
9450 | struct getter<nullopt_t> { | ||
9451 | static nullopt_t get(lua_State*, int, record& tracking) { | ||
9452 | tracking.use(1); | ||
9453 | return nullopt; | ||
9454 | } | ||
9455 | }; | ||
9456 | |||
9457 | template <> | ||
9458 | struct getter<this_state> { | ||
9459 | static this_state get(lua_State* L, int, record& tracking) { | ||
9460 | tracking.use(0); | ||
9461 | return this_state(L); | ||
9462 | } | ||
9463 | }; | ||
9464 | |||
9465 | template <> | ||
9466 | struct getter<this_main_state> { | ||
9467 | static this_main_state get(lua_State* L, int, record& tracking) { | ||
9468 | tracking.use(0); | ||
9469 | return this_main_state(main_thread(L, L)); | ||
9470 | } | ||
9471 | }; | ||
9472 | |||
9473 | template <> | ||
9474 | struct getter<lua_CFunction> { | ||
9475 | static lua_CFunction get(lua_State* L, int index, record& tracking) { | ||
9476 | tracking.use(1); | ||
9477 | return lua_tocfunction(L, index); | ||
9478 | } | ||
9479 | }; | ||
9480 | |||
9481 | template <> | ||
9482 | struct getter<c_closure> { | ||
9483 | static c_closure get(lua_State* L, int index, record& tracking) { | ||
9484 | tracking.use(1); | ||
9485 | return c_closure(lua_tocfunction(L, index), -1); | ||
9486 | } | ||
9487 | }; | ||
9488 | |||
9489 | template <> | ||
9490 | struct getter<error> { | ||
9491 | static error get(lua_State* L, int index, record& tracking) { | ||
9492 | tracking.use(1); | ||
9493 | size_t sz = 0; | ||
9494 | const char* err = lua_tolstring(L, index, &sz); | ||
9495 | if (err == nullptr) { | ||
9496 | return error(detail::direct_error, ""); | ||
9497 | } | ||
9498 | return error(detail::direct_error, std::string(err, sz)); | ||
9499 | } | ||
9500 | }; | ||
9501 | |||
9502 | template <> | ||
9503 | struct getter<void*> { | ||
9504 | static void* get(lua_State* L, int index, record& tracking) { | ||
9505 | tracking.use(1); | ||
9506 | return lua_touserdata(L, index); | ||
9507 | } | ||
9508 | }; | ||
9509 | |||
9510 | template <typename T> | ||
9511 | struct getter<detail::as_value_tag<T>> { | ||
9512 | static T* get_no_lua_nil(lua_State* L, int index, record& tracking) { | ||
9513 | void* memory = lua_touserdata(L, index); | ||
9514 | #if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP | ||
9515 | userdata_getter<extensible<T>> ug; | ||
9516 | (void)ug; | ||
9517 | auto ugr = ug.get(L, index, memory, tracking); | ||
9518 | if (ugr.first) { | ||
9519 | return ugr.second; | ||
9520 | } | ||
9521 | #endif // interop extensibility | ||
9522 | tracking.use(1); | ||
9523 | void* rawdata = detail::align_usertype_pointer(memory); | ||
9524 | void** pudata = static_cast<void**>(rawdata); | ||
9525 | void* udata = *pudata; | ||
9526 | return get_no_lua_nil_from(L, udata, index, tracking); | ||
9527 | } | ||
9528 | |||
9529 | static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) { | ||
9530 | if (detail::has_derived<T>::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) { | ||
9531 | void* basecastdata = lua_touserdata(L, -1); | ||
9532 | detail::inheritance_cast_function ic = reinterpret_cast<detail::inheritance_cast_function>(basecastdata); | ||
9533 | // use the casting function to properly adjust the pointer for the desired T | ||
9534 | udata = ic(udata, usertype_traits<T>::qualified_name()); | ||
9535 | lua_pop(L, 1); | ||
9536 | } | ||
9537 | T* obj = static_cast<T*>(udata); | ||
9538 | return obj; | ||
9539 | } | ||
9540 | |||
9541 | static T& get(lua_State* L, int index, record& tracking) { | ||
9542 | return *get_no_lua_nil(L, index, tracking); | ||
9543 | } | ||
9544 | }; | ||
9545 | |||
9546 | template <typename T> | ||
9547 | struct getter<detail::as_pointer_tag<T>> { | ||
9548 | static T* get(lua_State* L, int index, record& tracking) { | ||
9549 | type t = type_of(L, index); | ||
9550 | if (t == type::lua_nil) { | ||
9551 | tracking.use(1); | ||
9552 | return nullptr; | ||
9553 | } | ||
9554 | getter<detail::as_value_tag<T>> g; | ||
9555 | // Avoid VC++ warning | ||
9556 | (void)g; | ||
9557 | return g.get_no_lua_nil(L, index, tracking); | ||
9558 | } | ||
9559 | }; | ||
9560 | |||
9561 | template <typename T> | ||
9562 | struct getter<non_null<T*>> { | ||
9563 | static T* get(lua_State* L, int index, record& tracking) { | ||
9564 | getter<detail::as_value_tag<T>> g; | ||
9565 | // Avoid VC++ warning | ||
9566 | (void)g; | ||
9567 | return g.get_no_lua_nil(L, index, tracking); | ||
9568 | } | ||
9569 | }; | ||
9570 | |||
9571 | template <typename T> | ||
9572 | struct getter<T&> { | ||
9573 | static T& get(lua_State* L, int index, record& tracking) { | ||
9574 | getter<detail::as_value_tag<T>> g; | ||
9575 | // Avoid VC++ warning | ||
9576 | (void)g; | ||
9577 | return g.get(L, index, tracking); | ||
9578 | } | ||
9579 | }; | ||
9580 | |||
9581 | template <typename T> | ||
9582 | struct getter<std::reference_wrapper<T>> { | ||
9583 | static T& get(lua_State* L, int index, record& tracking) { | ||
9584 | getter<T&> g; | ||
9585 | // Avoid VC++ warning | ||
9586 | (void)g; | ||
9587 | return g.get(L, index, tracking); | ||
9588 | } | ||
9589 | }; | ||
9590 | |||
9591 | template <typename T> | ||
9592 | struct getter<T*> { | ||
9593 | static T* get(lua_State* L, int index, record& tracking) { | ||
9594 | getter<detail::as_pointer_tag<T>> g; | ||
9595 | // Avoid VC++ warning | ||
9596 | (void)g; | ||
9597 | return g.get(L, index, tracking); | ||
9598 | } | ||
9599 | }; | ||
9600 | |||
9601 | template <typename T> | ||
9602 | struct getter<T, std::enable_if_t<is_unique_usertype<T>::value>> { | ||
9603 | typedef typename unique_usertype_traits<T>::type P; | ||
9604 | typedef typename unique_usertype_traits<T>::actual_type Real; | ||
9605 | |||
9606 | static Real& get(lua_State* L, int index, record& tracking) { | ||
9607 | tracking.use(1); | ||
9608 | void* memory = lua_touserdata(L, index); | ||
9609 | memory = detail::align_usertype_unique<Real>(memory); | ||
9610 | Real* mem = static_cast<Real*>(memory); | ||
9611 | return *mem; | ||
9612 | } | ||
9613 | }; | ||
9614 | |||
9615 | template <typename... Tn> | ||
9616 | struct getter<std::tuple<Tn...>> { | ||
9617 | typedef std::tuple<decltype(stack::get<Tn>(nullptr, 0))...> R; | ||
9618 | |||
9619 | template <typename... Args> | ||
9620 | static R apply(std::index_sequence<>, lua_State*, int, record&, Args&&... args) { | ||
9621 | // Fuck you too, VC++ | ||
9622 | return R{ std::forward<Args>(args)... }; | ||
9623 | } | ||
9624 | |||
9625 | template <std::size_t I, std::size_t... Ix, typename... Args> | ||
9626 | static R apply(std::index_sequence<I, Ix...>, lua_State* L, int index, record& tracking, Args&&... args) { | ||
9627 | // Fuck you too, VC++ | ||
9628 | typedef std::tuple_element_t<I, std::tuple<Tn...>> T; | ||
9629 | return apply(std::index_sequence<Ix...>(), L, index, tracking, std::forward<Args>(args)..., stack::get<T>(L, index + tracking.used, tracking)); | ||
9630 | } | ||
9631 | |||
9632 | static R get(lua_State* L, int index, record& tracking) { | ||
9633 | return apply(std::make_index_sequence<sizeof...(Tn)>(), L, index, tracking); | ||
9634 | } | ||
9635 | }; | ||
9636 | |||
9637 | template <typename A, typename B> | ||
9638 | struct getter<std::pair<A, B>> { | ||
9639 | static decltype(auto) get(lua_State* L, int index, record& tracking) { | ||
9640 | return std::pair<decltype(stack::get<A>(L, index)), decltype(stack::get<B>(L, index))>{ stack::get<A>(L, index, tracking), stack::get<B>(L, index + tracking.used, tracking) }; | ||
9641 | } | ||
9642 | }; | ||
9643 | |||
9644 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
9645 | #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT | ||
9646 | template <typename... Tn> | ||
9647 | struct getter<std::variant<Tn...>> { | ||
9648 | typedef std::variant<Tn...> V; | ||
9649 | typedef std::variant_size<V> V_size; | ||
9650 | typedef std::integral_constant<bool, V_size::value == 0> V_is_empty; | ||
9651 | |||
9652 | static V get_empty(std::true_type, lua_State*, int, record&) { | ||
9653 | return V(); | ||
9654 | } | ||
9655 | |||
9656 | static V get_empty(std::false_type, lua_State* L, int index, record& tracking) { | ||
9657 | typedef std::variant_alternative_t<0, V> T; | ||
9658 | // This should never be reached... | ||
9659 | // please check your code and understand what you did to bring yourself here | ||
9660 | std::abort(); | ||
9661 | return V(std::in_place_index<0>, stack::get<T>(L, index, tracking)); | ||
9662 | } | ||
9663 | |||
9664 | static V get_one(std::integral_constant<std::size_t, 0>, lua_State* L, int index, record& tracking) { | ||
9665 | return get_empty(V_is_empty(), L, index, tracking); | ||
9666 | } | ||
9667 | |||
9668 | template <std::size_t I> | ||
9669 | static V get_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, record& tracking) { | ||
9670 | typedef std::variant_alternative_t<I - 1, V> T; | ||
9671 | if (stack::check<T>(L, index, no_panic, tracking)) { | ||
9672 | return V(std::in_place_index<I - 1>, stack::get<T>(L, index)); | ||
9673 | } | ||
9674 | return get_one(std::integral_constant<std::size_t, I - 1>(), L, index, tracking); | ||
9675 | } | ||
9676 | |||
9677 | static V get(lua_State* L, int index, record& tracking) { | ||
9678 | return get_one(std::integral_constant<std::size_t, V_size::value>(), L, index, tracking); | ||
9679 | } | ||
9680 | }; | ||
9681 | #endif // SOL_STD_VARIANT | ||
9682 | #endif // SOL_CXX17_FEATURES | ||
9683 | } | ||
9684 | } // namespace sol::stack | ||
9685 | |||
9686 | // end of sol/stack_get.hpp | ||
9687 | |||
9688 | // beginning of sol/stack_check_get.hpp | ||
9689 | |||
9690 | namespace sol { | ||
9691 | namespace stack { | ||
9692 | template <typename T, typename> | ||
9693 | struct check_getter { | ||
9694 | typedef decltype(stack_detail::unchecked_get<T>(nullptr, 0, std::declval<record&>())) R; | ||
9695 | |||
9696 | template <typename Handler> | ||
9697 | static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
9698 | if (!check<T>(L, index, std::forward<Handler>(handler))) { | ||
9699 | tracking.use(static_cast<int>(!lua_isnone(L, index))); | ||
9700 | return nullopt; | ||
9701 | } | ||
9702 | return stack_detail::unchecked_get<T>(L, index, tracking); | ||
9703 | } | ||
9704 | }; | ||
9705 | |||
9706 | template <typename T> | ||
9707 | struct check_getter<T, std::enable_if_t<is_lua_reference<T>::value>> { | ||
9708 | template <typename Handler> | ||
9709 | static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
9710 | // actually check if it's none here, otherwise | ||
9711 | // we'll have a none object inside an optional! | ||
9712 | bool success = !lua_isnone(L, index); | ||
9713 | if (!success) { | ||
9714 | // expected type, actual type | ||
9715 | tracking.use(static_cast<int>(success)); | ||
9716 | handler(L, index, type::poly, type_of(L, index), ""); | ||
9717 | return nullopt; | ||
9718 | } | ||
9719 | return stack_detail::unchecked_get<T>(L, index, tracking); | ||
9720 | } | ||
9721 | }; | ||
9722 | |||
9723 | template <typename T> | ||
9724 | struct check_getter<optional<T>> { | ||
9725 | template <typename Handler> | ||
9726 | static decltype(auto) get(lua_State* L, int index, Handler&&, record& tracking) { | ||
9727 | return check_get<T>(L, index, no_panic, tracking); | ||
9728 | } | ||
9729 | }; | ||
9730 | |||
9731 | template <typename T> | ||
9732 | struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> { | ||
9733 | template <typename Handler> | ||
9734 | static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
9735 | #if SOL_LUA_VERSION >= 503 | ||
9736 | if (lua_isinteger(L, index) != 0) { | ||
9737 | tracking.use(1); | ||
9738 | return static_cast<T>(lua_tointeger(L, index)); | ||
9739 | } | ||
9740 | #endif | ||
9741 | int isnum = 0; | ||
9742 | const lua_Number value = lua_tonumberx(L, index, &isnum); | ||
9743 | if (isnum != 0) { | ||
9744 | #if (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION) | ||
9745 | const auto integer_value = llround(value); | ||
9746 | if (static_cast<lua_Number>(integer_value) == value) { | ||
9747 | tracking.use(1); | ||
9748 | return static_cast<T>(integer_value); | ||
9749 | } | ||
9750 | #else | ||
9751 | tracking.use(1); | ||
9752 | return static_cast<T>(value); | ||
9753 | #endif | ||
9754 | } | ||
9755 | const type t = type_of(L, index); | ||
9756 | tracking.use(static_cast<int>(t != type::none)); | ||
9757 | handler(L, index, type::number, t, "not an integer"); | ||
9758 | return nullopt; | ||
9759 | } | ||
9760 | }; | ||
9761 | |||
9762 | template <typename T> | ||
9763 | struct check_getter<T, std::enable_if_t<std::is_enum<T>::value && !meta::any_same<T, meta_function, type>::value>> { | ||
9764 | template <typename Handler> | ||
9765 | static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
9766 | int isnum = 0; | ||
9767 | lua_Integer value = lua_tointegerx(L, index, &isnum); | ||
9768 | if (isnum == 0) { | ||
9769 | type t = type_of(L, index); | ||
9770 | tracking.use(static_cast<int>(t != type::none)); | ||
9771 | handler(L, index, type::number, t, "not a valid enumeration value"); | ||
9772 | return nullopt; | ||
9773 | } | ||
9774 | tracking.use(1); | ||
9775 | return static_cast<T>(value); | ||
9776 | } | ||
9777 | }; | ||
9778 | |||
9779 | template <typename T> | ||
9780 | struct check_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> { | ||
9781 | template <typename Handler> | ||
9782 | static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
9783 | int isnum = 0; | ||
9784 | lua_Number value = lua_tonumberx(L, index, &isnum); | ||
9785 | if (isnum == 0) { | ||
9786 | type t = type_of(L, index); | ||
9787 | tracking.use(static_cast<int>(t != type::none)); | ||
9788 | handler(L, index, type::number, t, "not a valid floating point number"); | ||
9789 | return nullopt; | ||
9790 | } | ||
9791 | tracking.use(1); | ||
9792 | return static_cast<T>(value); | ||
9793 | } | ||
9794 | }; | ||
9795 | |||
9796 | template <typename T> | ||
9797 | struct getter<optional<T>> { | ||
9798 | static decltype(auto) get(lua_State* L, int index, record& tracking) { | ||
9799 | return check_get<T>(L, index, no_panic, tracking); | ||
9800 | } | ||
9801 | }; | ||
9802 | |||
9803 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
9804 | #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT | ||
9805 | template <typename... Tn> | ||
9806 | struct check_getter<std::variant<Tn...>> { | ||
9807 | typedef std::variant<Tn...> V; | ||
9808 | typedef std::variant_size<V> V_size; | ||
9809 | typedef std::integral_constant<bool, V_size::value == 0> V_is_empty; | ||
9810 | |||
9811 | template <typename Handler> | ||
9812 | static optional<V> get_empty(std::true_type, lua_State*, int, Handler&&, record&) { | ||
9813 | return nullopt; | ||
9814 | } | ||
9815 | |||
9816 | template <typename Handler> | ||
9817 | static optional<V> get_empty(std::false_type, lua_State* L, int index, Handler&& handler, record&) { | ||
9818 | // This should never be reached... | ||
9819 | // please check your code and understand what you did to bring yourself here | ||
9820 | // maybe file a bug report, or 5 | ||
9821 | handler(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"); | ||
9822 | return nullopt; | ||
9823 | } | ||
9824 | |||
9825 | template <typename Handler> | ||
9826 | static optional<V> get_one(std::integral_constant<std::size_t, 0>, lua_State* L, int index, Handler&& handler, record& tracking) { | ||
9827 | return get_empty(V_is_empty(), L, index, std::forward<Handler>(handler), tracking); | ||
9828 | } | ||
9829 | |||
9830 | template <std::size_t I, typename Handler> | ||
9831 | static optional<V> get_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, Handler&& handler, record& tracking) { | ||
9832 | typedef std::variant_alternative_t<I - 1, V> T; | ||
9833 | if (stack::check<T>(L, index, no_panic, tracking)) { | ||
9834 | return V(std::in_place_index<I - 1>, stack::get<T>(L, index)); | ||
9835 | } | ||
9836 | return get_one(std::integral_constant<std::size_t, I - 1>(), L, index, std::forward<Handler>(handler), tracking); | ||
9837 | } | ||
9838 | |||
9839 | template <typename Handler> | ||
9840 | static optional<V> get(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
9841 | return get_one(std::integral_constant<std::size_t, V_size::value>(), L, index, std::forward<Handler>(handler), tracking); | ||
9842 | } | ||
9843 | }; | ||
9844 | #endif // SOL_STD_VARIANT | ||
9845 | #endif // SOL_CXX17_FEATURES | ||
9846 | } | ||
9847 | } // namespace sol::stack | ||
9848 | |||
9849 | // end of sol/stack_check_get.hpp | ||
9850 | |||
9851 | // beginning of sol/stack_push.hpp | ||
9852 | |||
9853 | #include <limits> | ||
9854 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
9855 | #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT | ||
9856 | #endif // Can use variant | ||
9857 | #endif // C++17 | ||
9858 | |||
9859 | namespace sol { | ||
9860 | namespace stack { | ||
9861 | inline int push_environment_of(lua_State* L, int index = -1) { | ||
9862 | #if SOL_LUA_VERSION < 502 | ||
9863 | // Use lua_getfenv | ||
9864 | lua_getfenv(L, index); | ||
9865 | return 1; | ||
9866 | #else | ||
9867 | // Use upvalues as explained in Lua 5.2 and beyond's manual | ||
9868 | if (lua_getupvalue(L, index, 1) == nullptr) { | ||
9869 | push(L, lua_nil); | ||
9870 | return 1; | ||
9871 | } | ||
9872 | #endif | ||
9873 | return 1; | ||
9874 | } | ||
9875 | |||
9876 | template <typename T> | ||
9877 | int push_environment_of(const T& target) { | ||
9878 | target.push(); | ||
9879 | return push_environment_of(target.lua_state(), -1) + 1; | ||
9880 | } | ||
9881 | |||
9882 | template <typename T> | ||
9883 | struct pusher<detail::as_value_tag<T>> { | ||
9884 | template <typename F, typename... Args> | ||
9885 | static int push_fx(lua_State* L, F&& f, Args&&... args) { | ||
9886 | // Basically, we store all user-data like this: | ||
9887 | // If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new | ||
9888 | // data in the first sizeof(T*) bytes, and then however many bytes it takes to | ||
9889 | // do the actual object. Things that are std::ref or plain T* are stored as | ||
9890 | // just the sizeof(T*), and nothing else. | ||
9891 | T* obj = detail::usertype_allocate<T>(L); | ||
9892 | std::allocator<T> alloc{}; | ||
9893 | std::allocator_traits<std::allocator<T>>::construct(alloc, obj, std::forward<Args>(args)...); | ||
9894 | f(); | ||
9895 | return 1; | ||
9896 | } | ||
9897 | |||
9898 | template <typename K, typename... Args> | ||
9899 | static int push_keyed(lua_State* L, K&& k, Args&&... args) { | ||
9900 | stack_detail::undefined_metatable<T> fx(L, &k[0]); | ||
9901 | return push_fx(L, fx, std::forward<Args>(args)...); | ||
9902 | } | ||
9903 | |||
9904 | template <typename... Args> | ||
9905 | static int push(lua_State* L, Args&&... args) { | ||
9906 | return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Args>(args)...); | ||
9907 | } | ||
9908 | }; | ||
9909 | |||
9910 | template <typename T> | ||
9911 | struct pusher<detail::as_pointer_tag<T>> { | ||
9912 | typedef meta::unqualified_t<T> U; | ||
9913 | |||
9914 | template <typename F> | ||
9915 | static int push_fx(lua_State* L, F&& f, T* obj) { | ||
9916 | if (obj == nullptr) | ||
9917 | return stack::push(L, lua_nil); | ||
9918 | T** pref = detail::usertype_allocate_pointer<T>(L); | ||
9919 | *pref = obj; | ||
9920 | f(); | ||
9921 | return 1; | ||
9922 | } | ||
9923 | |||
9924 | template <typename K> | ||
9925 | static int push_keyed(lua_State* L, K&& k, T* obj) { | ||
9926 | stack_detail::undefined_metatable<U*> fx(L, &k[0]); | ||
9927 | return push_fx(L, fx, obj); | ||
9928 | } | ||
9929 | |||
9930 | static int push(lua_State* L, T* obj) { | ||
9931 | return push_keyed(L, usertype_traits<U*>::metatable(), obj); | ||
9932 | } | ||
9933 | }; | ||
9934 | |||
9935 | template <> | ||
9936 | struct pusher<detail::as_reference_tag> { | ||
9937 | template <typename T> | ||
9938 | static int push(lua_State* L, T&& obj) { | ||
9939 | return stack::push(L, detail::ptr(obj)); | ||
9940 | } | ||
9941 | }; | ||
9942 | |||
9943 | template <typename T, typename> | ||
9944 | struct pusher { | ||
9945 | template <typename... Args> | ||
9946 | static int push(lua_State* L, Args&&... args) { | ||
9947 | return pusher<detail::as_value_tag<T>>{}.push(L, std::forward<Args>(args)...); | ||
9948 | } | ||
9949 | }; | ||
9950 | |||
9951 | template <typename T> | ||
9952 | struct pusher<T*, meta::disable_if_t<meta::any<is_container<meta::unqualified_t<T>>, std::is_function<meta::unqualified_t<T>>, is_lua_reference<meta::unqualified_t<T>>>::value>> { | ||
9953 | template <typename... Args> | ||
9954 | static int push(lua_State* L, Args&&... args) { | ||
9955 | return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...); | ||
9956 | } | ||
9957 | }; | ||
9958 | |||
9959 | template <typename T> | ||
9960 | struct pusher<T, std::enable_if_t<is_unique_usertype<T>::value>> { | ||
9961 | typedef typename unique_usertype_traits<T>::type P; | ||
9962 | typedef typename unique_usertype_traits<T>::actual_type Real; | ||
9963 | |||
9964 | template <typename Arg, meta::enable<std::is_base_of<Real, meta::unqualified_t<Arg>>> = meta::enabler> | ||
9965 | static int push(lua_State* L, Arg&& arg) { | ||
9966 | if (unique_usertype_traits<T>::is_null(arg)) { | ||
9967 | return stack::push(L, lua_nil); | ||
9968 | } | ||
9969 | return push_deep(L, std::forward<Arg>(arg)); | ||
9970 | } | ||
9971 | |||
9972 | template <typename Arg0, typename Arg1, typename... Args> | ||
9973 | static int push(lua_State* L, Arg0&& arg0, Arg0&& arg1, Args&&... args) { | ||
9974 | return push_deep(L, std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...); | ||
9975 | } | ||
9976 | |||
9977 | template <typename... Args> | ||
9978 | static int push_deep(lua_State* L, Args&&... args) { | ||
9979 | P** pref = nullptr; | ||
9980 | detail::unique_destructor* fx = nullptr; | ||
9981 | Real* mem = detail::usertype_unique_allocate<P, Real>(L, pref, fx); | ||
9982 | *fx = detail::usertype_unique_alloc_destroy<P, Real>; | ||
9983 | detail::default_construct::construct(mem, std::forward<Args>(args)...); | ||
9984 | *pref = unique_usertype_traits<T>::get(*mem); | ||
9985 | if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable()[0]) == 1) { | ||
9986 | luaL_Reg l[32]{}; | ||
9987 | int index = 0; | ||
9988 | auto prop_fx = [](meta_function) { return true; }; | ||
9989 | usertype_detail::insert_default_registrations<P>(l, index, prop_fx); | ||
9990 | usertype_detail::make_destructor<T>(l, index); | ||
9991 | luaL_setfuncs(L, l, 0); | ||
9992 | } | ||
9993 | lua_setmetatable(L, -2); | ||
9994 | return 1; | ||
9995 | } | ||
9996 | }; | ||
9997 | |||
9998 | template <typename T> | ||
9999 | struct pusher<std::reference_wrapper<T>> { | ||
10000 | static int push(lua_State* L, const std::reference_wrapper<T>& t) { | ||
10001 | return stack::push(L, std::addressof(detail::deref(t.get()))); | ||
10002 | } | ||
10003 | }; | ||
10004 | |||
10005 | template <typename T> | ||
10006 | struct pusher<T, std::enable_if_t<std::is_floating_point<T>::value>> { | ||
10007 | static int push(lua_State* L, const T& value) { | ||
10008 | lua_pushnumber(L, value); | ||
10009 | return 1; | ||
10010 | } | ||
10011 | }; | ||
10012 | |||
10013 | template <typename T> | ||
10014 | struct pusher<T, std::enable_if_t<std::is_integral<T>::value>> { | ||
10015 | static int push(lua_State* L, const T& value) { | ||
10016 | #if SOL_LUA_VERSION >= 503 | ||
10017 | static auto integer_value_fits = [](T const& value) { | ||
10018 | if (sizeof(T) < sizeof(lua_Integer) || (std::is_signed<T>::value && sizeof(T) == sizeof(lua_Integer))) { | ||
10019 | return true; | ||
10020 | } | ||
10021 | auto u_min = static_cast<std::intmax_t>((std::numeric_limits<lua_Integer>::min)()); | ||
10022 | auto u_max = static_cast<std::uintmax_t>((std::numeric_limits<lua_Integer>::max)()); | ||
10023 | auto t_min = static_cast<std::intmax_t>((std::numeric_limits<T>::min)()); | ||
10024 | auto t_max = static_cast<std::uintmax_t>((std::numeric_limits<T>::max)()); | ||
10025 | return (u_min <= t_min || value >= static_cast<T>(u_min)) && (u_max >= t_max || value <= static_cast<T>(u_max)); | ||
10026 | }; | ||
10027 | if (integer_value_fits(value)) { | ||
10028 | lua_pushinteger(L, static_cast<lua_Integer>(value)); | ||
10029 | return 1; | ||
10030 | } | ||
10031 | #endif // Lua 5.3 and above | ||
10032 | #if (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION) | ||
10033 | if (static_cast<T>(llround(static_cast<lua_Number>(value))) != value) { | ||
10034 | #if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS | ||
10035 | // Is this really worth it? | ||
10036 | assert(false && "integer value will be misrepresented in lua"); | ||
10037 | lua_pushnumber(L, static_cast<lua_Number>(value)); | ||
10038 | return 1; | ||
10039 | #else | ||
10040 | throw error(detail::direct_error, "integer value will be misrepresented in lua"); | ||
10041 | #endif // No Exceptions | ||
10042 | } | ||
10043 | #endif // Safe Numerics and Number Precision Check | ||
10044 | lua_pushnumber(L, static_cast<lua_Number>(value)); | ||
10045 | return 1; | ||
10046 | } | ||
10047 | }; | ||
10048 | |||
10049 | template <typename T> | ||
10050 | struct pusher<T, std::enable_if_t<std::is_enum<T>::value>> { | ||
10051 | static int push(lua_State* L, const T& value) { | ||
10052 | if (std::is_same<char, std::underlying_type_t<T>>::value) { | ||
10053 | return stack::push(L, static_cast<int>(value)); | ||
10054 | } | ||
10055 | return stack::push(L, static_cast<std::underlying_type_t<T>>(value)); | ||
10056 | } | ||
10057 | }; | ||
10058 | |||
10059 | template <typename T> | ||
10060 | struct pusher<detail::as_table_tag<T>> { | ||
10061 | static int push(lua_State* L, const T& tablecont) { | ||
10062 | typedef meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>> has_kvp; | ||
10063 | return push(has_kvp(), L, tablecont); | ||
10064 | } | ||
10065 | |||
10066 | static int push(std::true_type, lua_State* L, const T& tablecont) { | ||
10067 | auto& cont = detail::deref(detail::unwrap(tablecont)); | ||
10068 | lua_createtable(L, static_cast<int>(cont.size()), 0); | ||
10069 | int tableindex = lua_gettop(L); | ||
10070 | for (const auto& pair : cont) { | ||
10071 | set_field(L, pair.first, pair.second, tableindex); | ||
10072 | } | ||
10073 | return 1; | ||
10074 | } | ||
10075 | |||
10076 | static int push(std::false_type, lua_State* L, const T& tablecont) { | ||
10077 | auto& cont = detail::deref(detail::unwrap(tablecont)); | ||
10078 | lua_createtable(L, stack_detail::get_size_hint(cont), 0); | ||
10079 | int tableindex = lua_gettop(L); | ||
10080 | std::size_t index = 1; | ||
10081 | for (const auto& i : cont) { | ||
10082 | #if SOL_LUA_VERSION >= 503 | ||
10083 | int p = stack::push(L, i); | ||
10084 | for (int pi = 0; pi < p; ++pi) { | ||
10085 | lua_seti(L, tableindex, static_cast<lua_Integer>(index++)); | ||
10086 | } | ||
10087 | #else | ||
10088 | lua_pushinteger(L, static_cast<lua_Integer>(index)); | ||
10089 | int p = stack::push(L, i); | ||
10090 | if (p == 1) { | ||
10091 | ++index; | ||
10092 | lua_settable(L, tableindex); | ||
10093 | } | ||
10094 | else { | ||
10095 | int firstindex = tableindex + 1 + 1; | ||
10096 | for (int pi = 0; pi < p; ++pi) { | ||
10097 | stack::push(L, index); | ||
10098 | lua_pushvalue(L, firstindex); | ||
10099 | lua_settable(L, tableindex); | ||
10100 | ++index; | ||
10101 | ++firstindex; | ||
10102 | } | ||
10103 | lua_pop(L, 1 + p); | ||
10104 | } | ||
10105 | #endif // Lua Version 5.3 and others | ||
10106 | } | ||
10107 | // TODO: figure out a better way to do this...? | ||
10108 | //set_field(L, -1, cont.size()); | ||
10109 | return 1; | ||
10110 | } | ||
10111 | }; | ||
10112 | |||
10113 | template <typename T> | ||
10114 | struct pusher<as_table_t<T>, std::enable_if_t<is_container<std::remove_pointer_t<meta::unwrap_unqualified_t<T>>>::value>> { | ||
10115 | static int push(lua_State* L, const T& tablecont) { | ||
10116 | return stack::push<detail::as_table_tag<T>>(L, tablecont); | ||
10117 | } | ||
10118 | }; | ||
10119 | |||
10120 | template <typename T> | ||
10121 | struct pusher<as_table_t<T>, std::enable_if_t<!is_container<std::remove_pointer_t<meta::unwrap_unqualified_t<T>>>::value>> { | ||
10122 | static int push(lua_State* L, const T& v) { | ||
10123 | return stack::push(L, v); | ||
10124 | } | ||
10125 | }; | ||
10126 | |||
10127 | template <typename T> | ||
10128 | struct pusher<nested<T>> { | ||
10129 | static int push(lua_State* L, const T& tablecont) { | ||
10130 | pusher<as_table_t<T>> p{}; | ||
10131 | // silence annoying VC++ warning | ||
10132 | (void)p; | ||
10133 | return p.push(L, tablecont); | ||
10134 | } | ||
10135 | }; | ||
10136 | |||
10137 | template <typename T> | ||
10138 | struct pusher<std::initializer_list<T>> { | ||
10139 | static int push(lua_State* L, const std::initializer_list<T>& il) { | ||
10140 | pusher<detail::as_table_tag<std::initializer_list<T>>> p{}; | ||
10141 | // silence annoying VC++ warning | ||
10142 | (void)p; | ||
10143 | return p.push(L, il); | ||
10144 | } | ||
10145 | }; | ||
10146 | |||
10147 | template <typename T> | ||
10148 | struct pusher<T, std::enable_if_t<is_lua_reference<T>::value>> { | ||
10149 | static int push(lua_State* L, const T& ref) { | ||
10150 | return ref.push(L); | ||
10151 | } | ||
10152 | |||
10153 | static int push(lua_State* L, T&& ref) { | ||
10154 | return ref.push(L); | ||
10155 | } | ||
10156 | }; | ||
10157 | |||
10158 | template <> | ||
10159 | struct pusher<bool> { | ||
10160 | static int push(lua_State* L, bool b) { | ||
10161 | lua_pushboolean(L, b); | ||
10162 | return 1; | ||
10163 | } | ||
10164 | }; | ||
10165 | |||
10166 | template <> | ||
10167 | struct pusher<lua_nil_t> { | ||
10168 | static int push(lua_State* L, lua_nil_t) { | ||
10169 | lua_pushnil(L); | ||
10170 | return 1; | ||
10171 | } | ||
10172 | }; | ||
10173 | |||
10174 | template <> | ||
10175 | struct pusher<stack_count> { | ||
10176 | static int push(lua_State*, stack_count st) { | ||
10177 | return st.count; | ||
10178 | } | ||
10179 | }; | ||
10180 | |||
10181 | template <> | ||
10182 | struct pusher<metatable_t> { | ||
10183 | static int push(lua_State* L, metatable_t) { | ||
10184 | lua_pushlstring(L, "__mt", 4); | ||
10185 | return 1; | ||
10186 | } | ||
10187 | }; | ||
10188 | |||
10189 | template <> | ||
10190 | struct pusher<std::remove_pointer_t<lua_CFunction>> { | ||
10191 | static int push(lua_State* L, lua_CFunction func, int n = 0) { | ||
10192 | lua_pushcclosure(L, func, n); | ||
10193 | return 1; | ||
10194 | } | ||
10195 | }; | ||
10196 | |||
10197 | template <> | ||
10198 | struct pusher<lua_CFunction> { | ||
10199 | static int push(lua_State* L, lua_CFunction func, int n = 0) { | ||
10200 | lua_pushcclosure(L, func, n); | ||
10201 | return 1; | ||
10202 | } | ||
10203 | }; | ||
10204 | |||
10205 | #if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE | ||
10206 | template <> | ||
10207 | struct pusher<std::remove_pointer_t<detail::lua_CFunction_noexcept>> { | ||
10208 | static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { | ||
10209 | lua_pushcclosure(L, func, n); | ||
10210 | return 1; | ||
10211 | } | ||
10212 | }; | ||
10213 | |||
10214 | template <> | ||
10215 | struct pusher<detail::lua_CFunction_noexcept> { | ||
10216 | static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { | ||
10217 | lua_pushcclosure(L, func, n); | ||
10218 | return 1; | ||
10219 | } | ||
10220 | }; | ||
10221 | #endif // noexcept function type | ||
10222 | |||
10223 | template <> | ||
10224 | struct pusher<c_closure> { | ||
10225 | static int push(lua_State* L, c_closure cc) { | ||
10226 | lua_pushcclosure(L, cc.c_function, cc.upvalues); | ||
10227 | return 1; | ||
10228 | } | ||
10229 | }; | ||
10230 | |||
10231 | template <typename Arg, typename... Args> | ||
10232 | struct pusher<closure<Arg, Args...>> { | ||
10233 | template <std::size_t... I, typename T> | ||
10234 | static int push(std::index_sequence<I...>, lua_State* L, T&& c) { | ||
10235 | int pushcount = multi_push(L, detail::forward_get<I>(c.upvalues)...); | ||
10236 | return stack::push(L, c_closure(c.c_function, pushcount)); | ||
10237 | } | ||
10238 | |||
10239 | template <typename T> | ||
10240 | static int push(lua_State* L, T&& c) { | ||
10241 | return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward<T>(c)); | ||
10242 | } | ||
10243 | }; | ||
10244 | |||
10245 | template <> | ||
10246 | struct pusher<void*> { | ||
10247 | static int push(lua_State* L, void* userdata) { | ||
10248 | lua_pushlightuserdata(L, userdata); | ||
10249 | return 1; | ||
10250 | } | ||
10251 | }; | ||
10252 | |||
10253 | template <> | ||
10254 | struct pusher<lightuserdata_value> { | ||
10255 | static int push(lua_State* L, lightuserdata_value userdata) { | ||
10256 | lua_pushlightuserdata(L, userdata); | ||
10257 | return 1; | ||
10258 | } | ||
10259 | }; | ||
10260 | |||
10261 | template <typename T> | ||
10262 | struct pusher<light<T>> { | ||
10263 | static int push(lua_State* L, light<T> l) { | ||
10264 | lua_pushlightuserdata(L, static_cast<void*>(l.value)); | ||
10265 | return 1; | ||
10266 | } | ||
10267 | }; | ||
10268 | |||
10269 | template <typename T> | ||
10270 | struct pusher<user<T>> { | ||
10271 | template <bool with_meta = true, typename Key, typename... Args> | ||
10272 | static int push_with(lua_State* L, Key&& name, Args&&... args) { | ||
10273 | // A dumb pusher | ||
10274 | T* data = detail::user_allocate<T>(L); | ||
10275 | std::allocator<T> alloc{}; | ||
10276 | std::allocator_traits<std::allocator<T>>::construct(alloc, data, std::forward<Args>(args)...); | ||
10277 | if (with_meta) { | ||
10278 | // Make sure we have a plain GC set for this data | ||
10279 | if (luaL_newmetatable(L, name) != 0) { | ||
10280 | lua_CFunction cdel = detail::user_alloc_destruct<T>; | ||
10281 | lua_pushcclosure(L, cdel, 0); | ||
10282 | lua_setfield(L, -2, "__gc"); | ||
10283 | } | ||
10284 | lua_setmetatable(L, -2); | ||
10285 | } | ||
10286 | return 1; | ||
10287 | } | ||
10288 | |||
10289 | template <typename Arg, typename... Args, meta::disable<meta::any_same<meta::unqualified_t<Arg>, no_metatable_t, metatable_t>> = meta::enabler> | ||
10290 | static int push(lua_State* L, Arg&& arg, Args&&... args) { | ||
10291 | const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; | ||
10292 | return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...); | ||
10293 | } | ||
10294 | |||
10295 | template <typename... Args> | ||
10296 | static int push(lua_State* L, no_metatable_t, Args&&... args) { | ||
10297 | const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; | ||
10298 | return push_with<false>(L, name, std::forward<Args>(args)...); | ||
10299 | } | ||
10300 | |||
10301 | template <typename Key, typename... Args> | ||
10302 | static int push(lua_State* L, metatable_t, Key&& key, Args&&... args) { | ||
10303 | const auto name = &key[0]; | ||
10304 | return push_with<true>(L, name, std::forward<Args>(args)...); | ||
10305 | } | ||
10306 | |||
10307 | static int push(lua_State* L, const user<T>& u) { | ||
10308 | const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; | ||
10309 | return push_with(L, name, u.value); | ||
10310 | } | ||
10311 | |||
10312 | static int push(lua_State* L, user<T>&& u) { | ||
10313 | const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; | ||
10314 | return push_with(L, name, std::move(u.value)); | ||
10315 | } | ||
10316 | |||
10317 | static int push(lua_State* L, no_metatable_t, const user<T>& u) { | ||
10318 | const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; | ||
10319 | return push_with<false>(L, name, u.value); | ||
10320 | } | ||
10321 | |||
10322 | static int push(lua_State* L, no_metatable_t, user<T>&& u) { | ||
10323 | const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; | ||
10324 | return push_with<false>(L, name, std::move(u.value)); | ||
10325 | } | ||
10326 | }; | ||
10327 | |||
10328 | template <> | ||
10329 | struct pusher<userdata_value> { | ||
10330 | static int push(lua_State* L, userdata_value data) { | ||
10331 | void** ud = detail::usertype_allocate_pointer<void>(L); | ||
10332 | *ud = data.value; | ||
10333 | return 1; | ||
10334 | } | ||
10335 | }; | ||
10336 | |||
10337 | template <> | ||
10338 | struct pusher<const char*> { | ||
10339 | static int push_sized(lua_State* L, const char* str, std::size_t len) { | ||
10340 | lua_pushlstring(L, str, len); | ||
10341 | return 1; | ||
10342 | } | ||
10343 | |||
10344 | static int push(lua_State* L, const char* str) { | ||
10345 | if (str == nullptr) | ||
10346 | return stack::push(L, lua_nil); | ||
10347 | return push_sized(L, str, std::char_traits<char>::length(str)); | ||
10348 | } | ||
10349 | |||
10350 | static int push(lua_State* L, const char* strb, const char* stre) { | ||
10351 | return push_sized(L, strb, stre - strb); | ||
10352 | } | ||
10353 | |||
10354 | static int push(lua_State* L, const char* str, std::size_t len) { | ||
10355 | return push_sized(L, str, len); | ||
10356 | } | ||
10357 | }; | ||
10358 | |||
10359 | template <> | ||
10360 | struct pusher<char*> { | ||
10361 | static int push_sized(lua_State* L, const char* str, std::size_t len) { | ||
10362 | pusher<const char*> p{}; | ||
10363 | (void)p; | ||
10364 | return p.push_sized(L, str, len); | ||
10365 | } | ||
10366 | |||
10367 | static int push(lua_State* L, const char* str) { | ||
10368 | pusher<const char*> p{}; | ||
10369 | (void)p; | ||
10370 | return p.push(L, str); | ||
10371 | } | ||
10372 | |||
10373 | static int push(lua_State* L, const char* strb, const char* stre) { | ||
10374 | pusher<const char*> p{}; | ||
10375 | (void)p; | ||
10376 | return p.push(L, strb, stre); | ||
10377 | } | ||
10378 | |||
10379 | static int push(lua_State* L, const char* str, std::size_t len) { | ||
10380 | pusher<const char*> p{}; | ||
10381 | (void)p; | ||
10382 | return p.push(L, str, len); | ||
10383 | } | ||
10384 | }; | ||
10385 | |||
10386 | template <size_t N> | ||
10387 | struct pusher<char[N]> { | ||
10388 | static int push(lua_State* L, const char (&str)[N]) { | ||
10389 | lua_pushlstring(L, str, N - 1); | ||
10390 | return 1; | ||
10391 | } | ||
10392 | |||
10393 | static int push(lua_State* L, const char (&str)[N], std::size_t sz) { | ||
10394 | lua_pushlstring(L, str, sz); | ||
10395 | return 1; | ||
10396 | } | ||
10397 | }; | ||
10398 | |||
10399 | template <> | ||
10400 | struct pusher<char> { | ||
10401 | static int push(lua_State* L, char c) { | ||
10402 | const char str[2] = { c, '\0' }; | ||
10403 | return stack::push(L, str, 1); | ||
10404 | } | ||
10405 | }; | ||
10406 | |||
10407 | template <typename Traits, typename Al> | ||
10408 | struct pusher<std::basic_string<char, Traits, Al>> { | ||
10409 | static int push(lua_State* L, const std::basic_string<char, Traits, Al>& str) { | ||
10410 | lua_pushlstring(L, str.c_str(), str.size()); | ||
10411 | return 1; | ||
10412 | } | ||
10413 | |||
10414 | static int push(lua_State* L, const std::basic_string<char, Traits, Al>& str, std::size_t sz) { | ||
10415 | lua_pushlstring(L, str.c_str(), sz); | ||
10416 | return 1; | ||
10417 | } | ||
10418 | }; | ||
10419 | |||
10420 | template <typename Ch, typename Traits> | ||
10421 | struct pusher<basic_string_view<Ch, Traits>> { | ||
10422 | static int push(lua_State* L, const basic_string_view<Ch, Traits>& sv) { | ||
10423 | return stack::push(L, sv.data(), sv.length()); | ||
10424 | } | ||
10425 | |||
10426 | static int push(lua_State* L, const basic_string_view<Ch, Traits>& sv, std::size_t n) { | ||
10427 | return stack::push(L, sv.data(), n); | ||
10428 | } | ||
10429 | }; | ||
10430 | |||
10431 | template <> | ||
10432 | struct pusher<meta_function> { | ||
10433 | static int push(lua_State* L, meta_function m) { | ||
10434 | const std::string& str = to_string(m); | ||
10435 | lua_pushlstring(L, str.c_str(), str.size()); | ||
10436 | return 1; | ||
10437 | } | ||
10438 | }; | ||
10439 | |||
10440 | template <> | ||
10441 | struct pusher<absolute_index> { | ||
10442 | static int push(lua_State* L, absolute_index ai) { | ||
10443 | lua_pushvalue(L, ai); | ||
10444 | return 1; | ||
10445 | } | ||
10446 | }; | ||
10447 | |||
10448 | template <> | ||
10449 | struct pusher<raw_index> { | ||
10450 | static int push(lua_State* L, raw_index ri) { | ||
10451 | lua_pushvalue(L, ri); | ||
10452 | return 1; | ||
10453 | } | ||
10454 | }; | ||
10455 | |||
10456 | template <> | ||
10457 | struct pusher<ref_index> { | ||
10458 | static int push(lua_State* L, ref_index ri) { | ||
10459 | lua_rawgeti(L, LUA_REGISTRYINDEX, ri); | ||
10460 | return 1; | ||
10461 | } | ||
10462 | }; | ||
10463 | |||
10464 | template <> | ||
10465 | struct pusher<const wchar_t*> { | ||
10466 | static int push(lua_State* L, const wchar_t* wstr) { | ||
10467 | return push(L, wstr, std::char_traits<wchar_t>::length(wstr)); | ||
10468 | } | ||
10469 | |||
10470 | static int push(lua_State* L, const wchar_t* wstr, std::size_t sz) { | ||
10471 | return push(L, wstr, wstr + sz); | ||
10472 | } | ||
10473 | |||
10474 | static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { | ||
10475 | if (sizeof(wchar_t) == 2) { | ||
10476 | const char16_t* sb = reinterpret_cast<const char16_t*>(strb); | ||
10477 | const char16_t* se = reinterpret_cast<const char16_t*>(stre); | ||
10478 | return stack::push(L, sb, se); | ||
10479 | } | ||
10480 | const char32_t* sb = reinterpret_cast<const char32_t*>(strb); | ||
10481 | const char32_t* se = reinterpret_cast<const char32_t*>(stre); | ||
10482 | return stack::push(L, sb, se); | ||
10483 | } | ||
10484 | }; | ||
10485 | |||
10486 | template <> | ||
10487 | struct pusher<wchar_t*> { | ||
10488 | static int push(lua_State* L, const wchar_t* str) { | ||
10489 | pusher<const wchar_t*> p{}; | ||
10490 | (void)p; | ||
10491 | return p.push(L, str); | ||
10492 | } | ||
10493 | |||
10494 | static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { | ||
10495 | pusher<const wchar_t*> p{}; | ||
10496 | (void)p; | ||
10497 | return p.push(L, strb, stre); | ||
10498 | } | ||
10499 | |||
10500 | static int push(lua_State* L, const wchar_t* str, std::size_t len) { | ||
10501 | pusher<const wchar_t*> p{}; | ||
10502 | (void)p; | ||
10503 | return p.push(L, str, len); | ||
10504 | } | ||
10505 | }; | ||
10506 | |||
10507 | template <> | ||
10508 | struct pusher<const char16_t*> { | ||
10509 | static int convert_into(lua_State* L, char* start, std::size_t, const char16_t* strb, const char16_t* stre) { | ||
10510 | char* target = start; | ||
10511 | char32_t cp = 0; | ||
10512 | for (const char16_t* strtarget = strb; strtarget < stre;) { | ||
10513 | auto dr = unicode::utf16_to_code_point(strtarget, stre); | ||
10514 | if (dr.error != unicode::error_code::ok) { | ||
10515 | cp = unicode::unicode_detail::replacement; | ||
10516 | } | ||
10517 | else { | ||
10518 | cp = dr.codepoint; | ||
10519 | } | ||
10520 | auto er = unicode::code_point_to_utf8(cp); | ||
10521 | const char* utf8data = er.code_units.data(); | ||
10522 | std::memcpy(target, utf8data, er.code_units_size); | ||
10523 | target += er.code_units_size; | ||
10524 | strtarget = dr.next; | ||
10525 | } | ||
10526 | |||
10527 | return stack::push(L, start, target); | ||
10528 | } | ||
10529 | |||
10530 | static int push(lua_State* L, const char16_t* u16str) { | ||
10531 | return push(L, u16str, std::char_traits<char16_t>::length(u16str)); | ||
10532 | } | ||
10533 | |||
10534 | static int push(lua_State* L, const char16_t* u16str, std::size_t sz) { | ||
10535 | return push(L, u16str, u16str + sz); | ||
10536 | } | ||
10537 | |||
10538 | static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { | ||
10539 | // TODO: use new unicode methods | ||
10540 | // TODO: use new unicode methods | ||
10541 | char sbo[SOL_STACK_STRING_OPTIMIZATION_SIZE]; | ||
10542 | // if our max string space is small enough, use SBO | ||
10543 | // right off the bat | ||
10544 | std::size_t max_possible_code_units = (stre - strb) * 4; | ||
10545 | if (max_possible_code_units <= SOL_STACK_STRING_OPTIMIZATION_SIZE) { | ||
10546 | return convert_into(L, sbo, max_possible_code_units, strb, stre); | ||
10547 | } | ||
10548 | // otherwise, we must manually count/check size | ||
10549 | std::size_t needed_size = 0; | ||
10550 | for (const char16_t* strtarget = strb; strtarget < stre;) { | ||
10551 | auto dr = unicode::utf16_to_code_point(strtarget, stre); | ||
10552 | auto er = unicode::code_point_to_utf8(dr.codepoint); | ||
10553 | needed_size += er.code_units_size; | ||
10554 | strtarget = dr.next; | ||
10555 | } | ||
10556 | if (needed_size < SOL_STACK_STRING_OPTIMIZATION_SIZE) { | ||
10557 | return convert_into(L, sbo, needed_size, strb, stre); | ||
10558 | } | ||
10559 | std::string u8str("", 0); | ||
10560 | u8str.resize(needed_size); | ||
10561 | char* target = &u8str[0]; | ||
10562 | return convert_into(L, target, needed_size, strb, stre); | ||
10563 | } | ||
10564 | }; | ||
10565 | |||
10566 | template <> | ||
10567 | struct pusher<char16_t*> { | ||
10568 | static int push(lua_State* L, const char16_t* str) { | ||
10569 | pusher<const char16_t*> p{}; | ||
10570 | (void)p; | ||
10571 | return p.push(L, str); | ||
10572 | } | ||
10573 | |||
10574 | static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { | ||
10575 | pusher<const char16_t*> p{}; | ||
10576 | (void)p; | ||
10577 | return p.push(L, strb, stre); | ||
10578 | } | ||
10579 | |||
10580 | static int push(lua_State* L, const char16_t* str, std::size_t len) { | ||
10581 | pusher<const char16_t*> p{}; | ||
10582 | (void)p; | ||
10583 | return p.push(L, str, len); | ||
10584 | } | ||
10585 | }; | ||
10586 | |||
10587 | template <> | ||
10588 | struct pusher<const char32_t*> { | ||
10589 | static int convert_into(lua_State* L, char* start, std::size_t, const char32_t* strb, const char32_t* stre) { | ||
10590 | char* target = start; | ||
10591 | char32_t cp = 0; | ||
10592 | for (const char32_t* strtarget = strb; strtarget < stre;) { | ||
10593 | auto dr = unicode::utf32_to_code_point(strtarget, stre); | ||
10594 | if (dr.error != unicode::error_code::ok) { | ||
10595 | cp = unicode::unicode_detail::replacement; | ||
10596 | } | ||
10597 | else { | ||
10598 | cp = dr.codepoint; | ||
10599 | } | ||
10600 | auto er = unicode::code_point_to_utf8(cp); | ||
10601 | const char* data = er.code_units.data(); | ||
10602 | std::memcpy(target, data, er.code_units_size); | ||
10603 | target += er.code_units_size; | ||
10604 | strtarget = dr.next; | ||
10605 | } | ||
10606 | return stack::push(L, start, target); | ||
10607 | } | ||
10608 | |||
10609 | static int push(lua_State* L, const char32_t* u32str) { | ||
10610 | return push(L, u32str, u32str + std::char_traits<char32_t>::length(u32str)); | ||
10611 | } | ||
10612 | |||
10613 | static int push(lua_State* L, const char32_t* u32str, std::size_t sz) { | ||
10614 | return push(L, u32str, u32str + sz); | ||
10615 | } | ||
10616 | |||
10617 | static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { | ||
10618 | // TODO: use new unicode methods | ||
10619 | char sbo[SOL_STACK_STRING_OPTIMIZATION_SIZE]; | ||
10620 | // if our max string space is small enough, use SBO | ||
10621 | // right off the bat | ||
10622 | std::size_t max_possible_code_units = (stre - strb) * 4; | ||
10623 | if (max_possible_code_units <= SOL_STACK_STRING_OPTIMIZATION_SIZE) { | ||
10624 | return convert_into(L, sbo, max_possible_code_units, strb, stre); | ||
10625 | } | ||
10626 | // otherwise, we must manually count/check size | ||
10627 | std::size_t needed_size = 0; | ||
10628 | for (const char32_t* strtarget = strb; strtarget < stre;) { | ||
10629 | auto dr = unicode::utf32_to_code_point(strtarget, stre); | ||
10630 | auto er = unicode::code_point_to_utf8(dr.codepoint); | ||
10631 | needed_size += er.code_units_size; | ||
10632 | strtarget = dr.next; | ||
10633 | } | ||
10634 | if (needed_size < SOL_STACK_STRING_OPTIMIZATION_SIZE) { | ||
10635 | return convert_into(L, sbo, needed_size, strb, stre); | ||
10636 | } | ||
10637 | std::string u8str("", 0); | ||
10638 | u8str.resize(needed_size); | ||
10639 | char* target = &u8str[0]; | ||
10640 | return convert_into(L, target, needed_size, strb, stre); | ||
10641 | } | ||
10642 | }; | ||
10643 | |||
10644 | template <> | ||
10645 | struct pusher<char32_t*> { | ||
10646 | static int push(lua_State* L, const char32_t* str) { | ||
10647 | pusher<const char32_t*> p{}; | ||
10648 | (void)p; | ||
10649 | return p.push(L, str); | ||
10650 | } | ||
10651 | |||
10652 | static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { | ||
10653 | pusher<const char32_t*> p{}; | ||
10654 | (void)p; | ||
10655 | return p.push(L, strb, stre); | ||
10656 | } | ||
10657 | |||
10658 | static int push(lua_State* L, const char32_t* str, std::size_t len) { | ||
10659 | pusher<const char32_t*> p{}; | ||
10660 | (void)p; | ||
10661 | return p.push(L, str, len); | ||
10662 | } | ||
10663 | }; | ||
10664 | |||
10665 | template <size_t N> | ||
10666 | struct pusher<wchar_t[N]> { | ||
10667 | static int push(lua_State* L, const wchar_t (&str)[N]) { | ||
10668 | return push(L, str, N - 1); | ||
10669 | } | ||
10670 | |||
10671 | static int push(lua_State* L, const wchar_t (&str)[N], std::size_t sz) { | ||
10672 | return stack::push<const wchar_t*>(L, str, str + sz); | ||
10673 | } | ||
10674 | }; | ||
10675 | |||
10676 | template <size_t N> | ||
10677 | struct pusher<char16_t[N]> { | ||
10678 | static int push(lua_State* L, const char16_t (&str)[N]) { | ||
10679 | return push(L, str, N - 1); | ||
10680 | } | ||
10681 | |||
10682 | static int push(lua_State* L, const char16_t (&str)[N], std::size_t sz) { | ||
10683 | return stack::push<const char16_t*>(L, str, str + sz); | ||
10684 | } | ||
10685 | }; | ||
10686 | |||
10687 | template <size_t N> | ||
10688 | struct pusher<char32_t[N]> { | ||
10689 | static int push(lua_State* L, const char32_t (&str)[N]) { | ||
10690 | return push(L, str, N - 1); | ||
10691 | } | ||
10692 | |||
10693 | static int push(lua_State* L, const char32_t (&str)[N], std::size_t sz) { | ||
10694 | return stack::push<const char32_t*>(L, str, str + sz); | ||
10695 | } | ||
10696 | }; | ||
10697 | |||
10698 | template <> | ||
10699 | struct pusher<wchar_t> { | ||
10700 | static int push(lua_State* L, wchar_t c) { | ||
10701 | const wchar_t str[2] = { c, '\0' }; | ||
10702 | return stack::push(L, &str[0], 1); | ||
10703 | } | ||
10704 | }; | ||
10705 | |||
10706 | template <> | ||
10707 | struct pusher<char16_t> { | ||
10708 | static int push(lua_State* L, char16_t c) { | ||
10709 | const char16_t str[2] = { c, '\0' }; | ||
10710 | return stack::push(L, &str[0], 1); | ||
10711 | } | ||
10712 | }; | ||
10713 | |||
10714 | template <> | ||
10715 | struct pusher<char32_t> { | ||
10716 | static int push(lua_State* L, char32_t c) { | ||
10717 | const char32_t str[2] = { c, '\0' }; | ||
10718 | return stack::push(L, &str[0], 1); | ||
10719 | } | ||
10720 | }; | ||
10721 | |||
10722 | template <typename Ch, typename Traits, typename Al> | ||
10723 | struct pusher<std::basic_string<Ch, Traits, Al>, std::enable_if_t<!std::is_same<Ch, char>::value>> { | ||
10724 | static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& wstr) { | ||
10725 | return push(L, wstr, wstr.size()); | ||
10726 | } | ||
10727 | |||
10728 | static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& wstr, std::size_t sz) { | ||
10729 | return stack::push(L, wstr.data(), wstr.data() + sz); | ||
10730 | } | ||
10731 | }; | ||
10732 | |||
10733 | template <typename... Args> | ||
10734 | struct pusher<std::tuple<Args...>> { | ||
10735 | template <std::size_t... I, typename T> | ||
10736 | static int push(std::index_sequence<I...>, lua_State* L, T&& t) { | ||
10737 | int pushcount = 0; | ||
10738 | (void)detail::swallow{ 0, (pushcount += stack::push(L, detail::forward_get<I>(t)), 0)... }; | ||
10739 | return pushcount; | ||
10740 | } | ||
10741 | |||
10742 | template <typename T> | ||
10743 | static int push(lua_State* L, T&& t) { | ||
10744 | return push(std::index_sequence_for<Args...>(), L, std::forward<T>(t)); | ||
10745 | } | ||
10746 | }; | ||
10747 | |||
10748 | template <typename A, typename B> | ||
10749 | struct pusher<std::pair<A, B>> { | ||
10750 | template <typename T> | ||
10751 | static int push(lua_State* L, T&& t) { | ||
10752 | int pushcount = stack::push(L, detail::forward_get<0>(t)); | ||
10753 | pushcount += stack::push(L, detail::forward_get<1>(t)); | ||
10754 | return pushcount; | ||
10755 | } | ||
10756 | }; | ||
10757 | |||
10758 | template <typename O> | ||
10759 | struct pusher<optional<O>> { | ||
10760 | template <typename T> | ||
10761 | static int push(lua_State* L, T&& t) { | ||
10762 | if (t == nullopt) { | ||
10763 | return stack::push(L, nullopt); | ||
10764 | } | ||
10765 | return stack::push(L, static_cast<std::conditional_t<std::is_lvalue_reference<T>::value, O&, O&&>>(t.value())); | ||
10766 | } | ||
10767 | }; | ||
10768 | |||
10769 | template <> | ||
10770 | struct pusher<nullopt_t> { | ||
10771 | static int push(lua_State* L, nullopt_t) { | ||
10772 | return stack::push(L, lua_nil); | ||
10773 | } | ||
10774 | }; | ||
10775 | |||
10776 | template <> | ||
10777 | struct pusher<std::nullptr_t> { | ||
10778 | static int push(lua_State* L, std::nullptr_t) { | ||
10779 | return stack::push(L, lua_nil); | ||
10780 | } | ||
10781 | }; | ||
10782 | |||
10783 | template <> | ||
10784 | struct pusher<this_state> { | ||
10785 | static int push(lua_State*, const this_state&) { | ||
10786 | return 0; | ||
10787 | } | ||
10788 | }; | ||
10789 | |||
10790 | template <> | ||
10791 | struct pusher<this_main_state> { | ||
10792 | static int push(lua_State*, const this_main_state&) { | ||
10793 | return 0; | ||
10794 | } | ||
10795 | }; | ||
10796 | |||
10797 | template <> | ||
10798 | struct pusher<new_table> { | ||
10799 | static int push(lua_State* L, const new_table& nt) { | ||
10800 | lua_createtable(L, nt.sequence_hint, nt.map_hint); | ||
10801 | return 1; | ||
10802 | } | ||
10803 | }; | ||
10804 | |||
10805 | #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES | ||
10806 | #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT | ||
10807 | namespace stack_detail { | ||
10808 | |||
10809 | struct push_function { | ||
10810 | lua_State* L; | ||
10811 | |||
10812 | push_function(lua_State* L) | ||
10813 | : L(L) { | ||
10814 | } | ||
10815 | |||
10816 | template <typename T> | ||
10817 | int operator()(T&& value) const { | ||
10818 | return stack::push<T>(L, std::forward<T>(value)); | ||
10819 | } | ||
10820 | }; | ||
10821 | |||
10822 | } // namespace stack_detail | ||
10823 | |||
10824 | template <typename... Tn> | ||
10825 | struct pusher<std::variant<Tn...>> { | ||
10826 | static int push(lua_State* L, const std::variant<Tn...>& v) { | ||
10827 | return std::visit(stack_detail::push_function(L), v); | ||
10828 | } | ||
10829 | |||
10830 | static int push(lua_State* L, std::variant<Tn...>&& v) { | ||
10831 | return std::visit(stack_detail::push_function(L), std::move(v)); | ||
10832 | } | ||
10833 | }; | ||
10834 | #endif // Variant because Clang is terrible | ||
10835 | #endif // C++17 Support | ||
10836 | } | ||
10837 | } // namespace sol::stack | ||
10838 | |||
10839 | // end of sol/stack_push.hpp | ||
10840 | |||
10841 | // beginning of sol/stack_pop.hpp | ||
10842 | |||
10843 | namespace sol { | ||
10844 | namespace stack { | ||
10845 | template <typename T, typename> | ||
10846 | struct popper { | ||
10847 | inline static decltype(auto) pop(lua_State* L) { | ||
10848 | record tracking{}; | ||
10849 | #ifdef __INTEL_COMPILER | ||
10850 | auto&& r = get<T>(L, -lua_size<T>::value, tracking); | ||
10851 | #else | ||
10852 | decltype(auto) r = get<T>(L, -lua_size<T>::value, tracking); | ||
10853 | #endif | ||
10854 | lua_pop(L, tracking.used); | ||
10855 | return r; | ||
10856 | } | ||
10857 | }; | ||
10858 | |||
10859 | template <typename T> | ||
10860 | struct popper<T, std::enable_if_t<is_stack_based<meta::unqualified_t<T>>::value>> { | ||
10861 | static_assert(meta::neg<is_stack_based<meta::unqualified_t<T>>>::value, "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 scope!"); | ||
10862 | }; | ||
10863 | } | ||
10864 | } // namespace sol::stack | ||
10865 | |||
10866 | // end of sol/stack_pop.hpp | ||
10867 | |||
10868 | // beginning of sol/stack_field.hpp | ||
10869 | |||
10870 | namespace sol { | ||
10871 | namespace stack { | ||
10872 | template <typename T, bool, bool, typename> | ||
10873 | struct field_getter { | ||
10874 | template <typename Key> | ||
10875 | void get(lua_State* L, Key&& key, int tableindex = -2) { | ||
10876 | push(L, std::forward<Key>(key)); | ||
10877 | lua_gettable(L, tableindex); | ||
10878 | } | ||
10879 | }; | ||
10880 | |||
10881 | template <typename T, bool global, typename C> | ||
10882 | struct field_getter<T, global, true, C> { | ||
10883 | template <typename Key> | ||
10884 | void get(lua_State* L, Key&& key, int tableindex = -2) { | ||
10885 | push(L, std::forward<Key>(key)); | ||
10886 | lua_rawget(L, tableindex); | ||
10887 | } | ||
10888 | }; | ||
10889 | |||
10890 | template <bool b, bool raw, typename C> | ||
10891 | struct field_getter<metatable_t, b, raw, C> { | ||
10892 | void get(lua_State* L, metatable_t, int tableindex = -1) { | ||
10893 | if (lua_getmetatable(L, tableindex) == 0) | ||
10894 | push(L, lua_nil); | ||
10895 | } | ||
10896 | }; | ||
10897 | |||
10898 | template <bool b, bool raw, typename C> | ||
10899 | struct field_getter<env_t, b, raw, C> { | ||
10900 | void get(lua_State* L, env_t, int tableindex = -1) { | ||
10901 | #if SOL_LUA_VERSION < 502 | ||
10902 | // Use lua_setfenv | ||
10903 | lua_getfenv(L, tableindex); | ||
10904 | #else | ||
10905 | // Use upvalues as explained in Lua 5.2 and beyond's manual | ||
10906 | if (lua_getupvalue(L, tableindex, 1) == nullptr) { | ||
10907 | push(L, lua_nil); | ||
10908 | } | ||
10909 | #endif | ||
10910 | } | ||
10911 | }; | ||
10912 | |||
10913 | template <typename T, bool raw> | ||
10914 | struct field_getter<T, true, raw, std::enable_if_t<meta::is_c_str<T>::value>> { | ||
10915 | template <typename Key> | ||
10916 | void get(lua_State* L, Key&& key, int = -1) { | ||
10917 | lua_getglobal(L, &key[0]); | ||
10918 | } | ||
10919 | }; | ||
10920 | |||
10921 | template <typename T> | ||
10922 | struct field_getter<T, false, false, std::enable_if_t<meta::is_c_str<T>::value>> { | ||
10923 | template <typename Key> | ||
10924 | void get(lua_State* L, Key&& key, int tableindex = -1) { | ||
10925 | lua_getfield(L, tableindex, &key[0]); | ||
10926 | } | ||
10927 | }; | ||
10928 | |||
10929 | #if SOL_LUA_VERSION >= 503 | ||
10930 | template <typename T> | ||
10931 | struct field_getter<T, false, false, std::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>> { | ||
10932 | template <typename Key> | ||
10933 | void get(lua_State* L, Key&& key, int tableindex = -1) { | ||
10934 | lua_geti(L, tableindex, static_cast<lua_Integer>(key)); | ||
10935 | } | ||
10936 | }; | ||
10937 | #endif // Lua 5.3.x | ||
10938 | |||
10939 | #if SOL_LUA_VERSION >= 502 | ||
10940 | template <typename C> | ||
10941 | struct field_getter<void*, false, true, C> { | ||
10942 | void get(lua_State* L, void* key, int tableindex = -1) { | ||
10943 | lua_rawgetp(L, tableindex, key); | ||
10944 | } | ||
10945 | }; | ||
10946 | #endif // Lua 5.3.x | ||
10947 | |||
10948 | template <typename T> | ||
10949 | struct field_getter<T, false, true, std::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>> { | ||
10950 | template <typename Key> | ||
10951 | void get(lua_State* L, Key&& key, int tableindex = -1) { | ||
10952 | lua_rawgeti(L, tableindex, static_cast<lua_Integer>(key)); | ||
10953 | } | ||
10954 | }; | ||
10955 | |||
10956 | template <typename... Args, bool b, bool raw, typename C> | ||
10957 | struct field_getter<std::tuple<Args...>, b, raw, C> { | ||
10958 | template <std::size_t... I, typename Keys> | ||
10959 | void apply(std::index_sequence<0, I...>, lua_State* L, Keys&& keys, int tableindex) { | ||
10960 | get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex); | ||
10961 | void(detail::swallow{(get_field<false, raw>(L, detail::forward_get<I>(keys)), 0)...}); | ||
10962 | reference saved(L, -1); | ||
10963 | lua_pop(L, static_cast<int>(sizeof...(I))); | ||
10964 | saved.push(); | ||
10965 | } | ||
10966 | |||
10967 | template <typename Keys> | ||
10968 | void get(lua_State* L, Keys&& keys) { | ||
10969 | apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), lua_absindex(L, -1)); | ||
10970 | } | ||
10971 | |||
10972 | template <typename Keys> | ||
10973 | void get(lua_State* L, Keys&& keys, int tableindex) { | ||
10974 | apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), tableindex); | ||
10975 | } | ||
10976 | }; | ||
10977 | |||
10978 | template <typename A, typename B, bool b, bool raw, typename C> | ||
10979 | struct field_getter<std::pair<A, B>, b, raw, C> { | ||
10980 | template <typename Keys> | ||
10981 | void get(lua_State* L, Keys&& keys, int tableindex) { | ||
10982 | get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex); | ||
10983 | get_field<false, raw>(L, detail::forward_get<1>(keys)); | ||
10984 | reference saved(L, -1); | ||
10985 | lua_pop(L, static_cast<int>(2)); | ||
10986 | saved.push(); | ||
10987 | } | ||
10988 | |||
10989 | template <typename Keys> | ||
10990 | void get(lua_State* L, Keys&& keys) { | ||
10991 | get_field<b, raw>(L, detail::forward_get<0>(keys)); | ||
10992 | get_field<false, raw>(L, detail::forward_get<1>(keys)); | ||
10993 | reference saved(L, -1); | ||
10994 | lua_pop(L, static_cast<int>(2)); | ||
10995 | saved.push(); | ||
10996 | } | ||
10997 | }; | ||
10998 | |||
10999 | template <typename T, bool, bool, typename> | ||
11000 | struct field_setter { | ||
11001 | template <typename Key, typename Value> | ||
11002 | void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { | ||
11003 | push(L, std::forward<Key>(key)); | ||
11004 | push(L, std::forward<Value>(value)); | ||
11005 | lua_settable(L, tableindex); | ||
11006 | } | ||
11007 | }; | ||
11008 | |||
11009 | template <typename T, bool b, typename C> | ||
11010 | struct field_setter<T, b, true, C> { | ||
11011 | template <typename Key, typename Value> | ||
11012 | void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { | ||
11013 | push(L, std::forward<Key>(key)); | ||
11014 | push(L, std::forward<Value>(value)); | ||
11015 | lua_rawset(L, tableindex); | ||
11016 | } | ||
11017 | }; | ||
11018 | |||
11019 | template <bool b, bool raw, typename C> | ||
11020 | struct field_setter<metatable_t, b, raw, C> { | ||
11021 | template <typename Value> | ||
11022 | void set(lua_State* L, metatable_t, Value&& value, int tableindex = -2) { | ||
11023 | push(L, std::forward<Value>(value)); | ||
11024 | lua_setmetatable(L, tableindex); | ||
11025 | } | ||
11026 | }; | ||
11027 | |||
11028 | template <typename T, bool raw> | ||
11029 | struct field_setter<T, true, raw, std::enable_if_t<meta::is_c_str<T>::value>> { | ||
11030 | template <typename Key, typename Value> | ||
11031 | void set(lua_State* L, Key&& key, Value&& value, int = -2) { | ||
11032 | push(L, std::forward<Value>(value)); | ||
11033 | lua_setglobal(L, &key[0]); | ||
11034 | } | ||
11035 | }; | ||
11036 | |||
11037 | template <typename T> | ||
11038 | struct field_setter<T, false, false, std::enable_if_t<meta::is_c_str<T>::value>> { | ||
11039 | template <typename Key, typename Value> | ||
11040 | void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { | ||
11041 | push(L, std::forward<Value>(value)); | ||
11042 | lua_setfield(L, tableindex, &key[0]); | ||
11043 | } | ||
11044 | }; | ||
11045 | |||
11046 | #if SOL_LUA_VERSION >= 503 | ||
11047 | template <typename T> | ||
11048 | struct field_setter<T, false, false, std::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>> { | ||
11049 | template <typename Key, typename Value> | ||
11050 | void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { | ||
11051 | push(L, std::forward<Value>(value)); | ||
11052 | lua_seti(L, tableindex, static_cast<lua_Integer>(key)); | ||
11053 | } | ||
11054 | }; | ||
11055 | #endif // Lua 5.3.x | ||
11056 | |||
11057 | template <typename T> | ||
11058 | struct field_setter<T, false, true, std::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>> { | ||
11059 | template <typename Key, typename Value> | ||
11060 | void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { | ||
11061 | push(L, std::forward<Value>(value)); | ||
11062 | lua_rawseti(L, tableindex, static_cast<lua_Integer>(key)); | ||
11063 | } | ||
11064 | }; | ||
11065 | |||
11066 | #if SOL_LUA_VERSION >= 502 | ||
11067 | template <typename C> | ||
11068 | struct field_setter<void*, false, true, C> { | ||
11069 | template <typename Key, typename Value> | ||
11070 | void set(lua_State* L, void* key, Value&& value, int tableindex = -2) { | ||
11071 | push(L, std::forward<Value>(value)); | ||
11072 | lua_rawsetp(L, tableindex, key); | ||
11073 | } | ||
11074 | }; | ||
11075 | #endif // Lua 5.2.x | ||
11076 | |||
11077 | template <typename... Args, bool b, bool raw, typename C> | ||
11078 | struct field_setter<std::tuple<Args...>, b, raw, C> { | ||
11079 | template <bool g, std::size_t I, typename Key, typename Value> | ||
11080 | void apply(std::index_sequence<I>, lua_State* L, Key&& keys, Value&& value, int tableindex) { | ||
11081 | I < 1 ? set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value), tableindex) : set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value)); | ||
11082 | } | ||
11083 | |||
11084 | template <bool g, std::size_t I0, std::size_t I1, std::size_t... I, typename Keys, typename Value> | ||
11085 | void apply(std::index_sequence<I0, I1, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) { | ||
11086 | I0 < 1 ? get_field<g, raw>(L, detail::forward_get<I0>(keys), tableindex) : get_field<g, raw>(L, detail::forward_get<I0>(keys), -1); | ||
11087 | apply<false>(std::index_sequence<I1, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), -1); | ||
11088 | } | ||
11089 | |||
11090 | template <bool g, std::size_t I0, std::size_t... I, typename Keys, typename Value> | ||
11091 | void top_apply(std::index_sequence<I0, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) { | ||
11092 | apply<g>(std::index_sequence<I0, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex); | ||
11093 | lua_pop(L, static_cast<int>(sizeof...(I))); | ||
11094 | } | ||
11095 | |||
11096 | template <typename Keys, typename Value> | ||
11097 | void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) { | ||
11098 | top_apply<b>(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex); | ||
11099 | } | ||
11100 | }; | ||
11101 | |||
11102 | template <typename A, typename B, bool b, bool raw, typename C> | ||
11103 | struct field_setter<std::pair<A, B>, b, raw, C> { | ||
11104 | template <typename Keys, typename Value> | ||
11105 | void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) { | ||
11106 | get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex); | ||
11107 | set_field<false, raw>(L, detail::forward_get<1>(keys), std::forward<Value>(value)); | ||
11108 | lua_pop(L, 1); | ||
11109 | } | ||
11110 | }; | ||
11111 | } | ||
11112 | } // namespace sol::stack | ||
11113 | |||
11114 | // end of sol/stack_field.hpp | ||
11115 | |||
11116 | // beginning of sol/stack_probe.hpp | ||
11117 | |||
11118 | namespace sol { | ||
11119 | namespace stack { | ||
11120 | template <typename T, bool b, bool raw, typename> | ||
11121 | struct probe_field_getter { | ||
11122 | template <typename Key> | ||
11123 | probe get(lua_State* L, Key&& key, int tableindex = -2) { | ||
11124 | if (!b && !maybe_indexable(L, tableindex)) { | ||
11125 | return probe(false, 0); | ||
11126 | } | ||
11127 | get_field<b, raw>(L, std::forward<Key>(key), tableindex); | ||
11128 | return probe(!check<lua_nil_t>(L), 1); | ||
11129 | } | ||
11130 | }; | ||
11131 | |||
11132 | template <typename A, typename B, bool b, bool raw, typename C> | ||
11133 | struct probe_field_getter<std::pair<A, B>, b, raw, C> { | ||
11134 | template <typename Keys> | ||
11135 | probe get(lua_State* L, Keys&& keys, int tableindex = -2) { | ||
11136 | if (!b && !maybe_indexable(L, tableindex)) { | ||
11137 | return probe(false, 0); | ||
11138 | } | ||
11139 | get_field<b, raw>(L, std::get<0>(keys), tableindex); | ||
11140 | if (!maybe_indexable(L)) { | ||
11141 | return probe(false, 1); | ||
11142 | } | ||
11143 | get_field<false, raw>(L, std::get<1>(keys), tableindex); | ||
11144 | return probe(!check<lua_nil_t>(L), 2); | ||
11145 | } | ||
11146 | }; | ||
11147 | |||
11148 | template <typename... Args, bool b, bool raw, typename C> | ||
11149 | struct probe_field_getter<std::tuple<Args...>, b, raw, C> { | ||
11150 | template <std::size_t I, typename Keys> | ||
11151 | probe apply(std::index_sequence<I>, int sofar, lua_State* L, Keys&& keys, int tableindex) { | ||
11152 | get_field < I<1 && b, raw>(L, std::get<I>(keys), tableindex); | ||
11153 | return probe(!check<lua_nil_t>(L), sofar); | ||
11154 | } | ||
11155 | |||
11156 | template <std::size_t I, std::size_t I1, std::size_t... In, typename Keys> | ||
11157 | probe apply(std::index_sequence<I, I1, In...>, int sofar, lua_State* L, Keys&& keys, int tableindex) { | ||
11158 | get_field < I<1 && b, raw>(L, std::get<I>(keys), tableindex); | ||
11159 | if (!maybe_indexable(L)) { | ||
11160 | return probe(false, sofar); | ||
11161 | } | ||
11162 | return apply(std::index_sequence<I1, In...>(), sofar + 1, L, std::forward<Keys>(keys), -1); | ||
11163 | } | ||
11164 | |||
11165 | template <typename Keys> | ||
11166 | probe get(lua_State* L, Keys&& keys, int tableindex = -2) { | ||
11167 | if (!b && !maybe_indexable(L, tableindex)) { | ||
11168 | return probe(false, 0); | ||
11169 | } | ||
11170 | return apply(std::index_sequence_for<Args...>(), 1, L, std::forward<Keys>(keys), tableindex); | ||
11171 | } | ||
11172 | }; | ||
11173 | } | ||
11174 | } // namespace sol::stack | ||
11175 | |||
11176 | // end of sol/stack_probe.hpp | ||
11177 | |||
11178 | namespace sol { | ||
11179 | namespace detail { | ||
11180 | using typical_chunk_name_t = char[32]; | ||
11181 | |||
11182 | inline const std::string& default_chunk_name() { | ||
11183 | static const std::string name = ""; | ||
11184 | return name; | ||
11185 | } | ||
11186 | |||
11187 | template <std::size_t N> | ||
11188 | const char* make_chunk_name(const string_view& code, const std::string& chunkname, char (&basechunkname)[N]) { | ||
11189 | if (chunkname.empty()) { | ||
11190 | auto it = code.cbegin(); | ||
11191 | auto e = code.cend(); | ||
11192 | std::size_t i = 0; | ||
11193 | static const std::size_t n = N - 4; | ||
11194 | for (i = 0; i < n && it != e; ++i, ++it) { | ||
11195 | basechunkname[i] = *it; | ||
11196 | } | ||
11197 | if (it != e) { | ||
11198 | for (std::size_t c = 0; c < 3; ++i, ++c) { | ||
11199 | basechunkname[i] = '.'; | ||
11200 | } | ||
11201 | } | ||
11202 | basechunkname[i] = '\0'; | ||
11203 | return &basechunkname[0]; | ||
11204 | } | ||
11205 | else { | ||
11206 | return chunkname.c_str(); | ||
11207 | } | ||
11208 | } | ||
11209 | } // namespace detail | ||
11210 | |||
11211 | namespace stack { | ||
11212 | namespace stack_detail { | ||
11213 | template <typename T> | ||
11214 | inline int push_as_upvalues(lua_State* L, T& item) { | ||
11215 | typedef std::decay_t<T> TValue; | ||
11216 | static const std::size_t itemsize = sizeof(TValue); | ||
11217 | static const std::size_t voidsize = sizeof(void*); | ||
11218 | static const std::size_t voidsizem1 = voidsize - 1; | ||
11219 | static const std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; | ||
11220 | typedef std::array<void*, data_t_count> data_t; | ||
11221 | |||
11222 | data_t data{ {} }; | ||
11223 | std::memcpy(&data[0], std::addressof(item), itemsize); | ||
11224 | int pushcount = 0; | ||
11225 | for (auto&& v : data) { | ||
11226 | pushcount += push(L, lightuserdata_value(v)); | ||
11227 | } | ||
11228 | return pushcount; | ||
11229 | } | ||
11230 | |||
11231 | template <typename T> | ||
11232 | inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 2) { | ||
11233 | static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); | ||
11234 | typedef std::array<void*, data_t_count> data_t; | ||
11235 | data_t voiddata{ {} }; | ||
11236 | for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { | ||
11237 | voiddata[i] = get<lightuserdata_value>(L, upvalue_index(index++)); | ||
11238 | } | ||
11239 | return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index); | ||
11240 | } | ||
11241 | |||
11242 | struct evaluator { | ||
11243 | template <typename Fx, typename... Args> | ||
11244 | static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, record&, Fx&& fx, Args&&... args) { | ||
11245 | return std::forward<Fx>(fx)(std::forward<Args>(args)...); | ||
11246 | } | ||
11247 | |||
11248 | template <typename Fx, typename Arg, typename... Args, std::size_t I, std::size_t... Is, typename... FxArgs> | ||
11249 | static decltype(auto) eval(types<Arg, Args...>, std::index_sequence<I, Is...>, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { | ||
11250 | return eval(types<Args...>(), std::index_sequence<Is...>(), L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)..., stack_detail::unchecked_get<Arg>(L, start + tracking.used, tracking)); | ||
11251 | } | ||
11252 | }; | ||
11253 | |||
11254 | template <bool checkargs = detail::default_safe_function_calls , std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value >> | ||
11255 | inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { | ||
11256 | #ifndef _MSC_VER | ||
11257 | static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "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 a reference and std::move it manually if this was your intention."); | ||
11258 | #endif // This compiler make me so sad | ||
11259 | argument_handler<types<R, Args...>> handler{}; | ||
11260 | multi_check<checkargs, Args...>(L, start, handler); | ||
11261 | record tracking{}; | ||
11262 | return evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); | ||
11263 | } | ||
11264 | |||
11265 | template <bool checkargs = detail::default_safe_function_calls, std::size_t... I, typename... Args, typename Fx, typename... FxArgs> | ||
11266 | inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { | ||
11267 | #ifndef _MSC_VER | ||
11268 | static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "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 a reference and std::move it manually if this was your intention."); | ||
11269 | #endif // This compiler make me so fucking sad | ||
11270 | argument_handler<types<void, Args...>> handler{}; | ||
11271 | multi_check<checkargs, Args...>(L, start, handler); | ||
11272 | record tracking{}; | ||
11273 | evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); | ||
11274 | } | ||
11275 | } // namespace stack_detail | ||
11276 | |||
11277 | template <typename T> | ||
11278 | int set_ref(lua_State* L, T&& arg, int tableindex = -2) { | ||
11279 | push(L, std::forward<T>(arg)); | ||
11280 | return luaL_ref(L, tableindex); | ||
11281 | } | ||
11282 | |||
11283 | template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> | ||
11284 | inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { | ||
11285 | typedef std::make_index_sequence<sizeof...(Args)> args_indices; | ||
11286 | return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); | ||
11287 | } | ||
11288 | |||
11289 | template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> | ||
11290 | inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { | ||
11291 | return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); | ||
11292 | } | ||
11293 | |||
11294 | template <bool check_args = detail::default_safe_function_calls, typename... Args, typename Fx, typename... FxArgs> | ||
11295 | inline void call(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { | ||
11296 | typedef std::make_index_sequence<sizeof...(Args)> args_indices; | ||
11297 | stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); | ||
11298 | } | ||
11299 | |||
11300 | template <bool check_args = detail::default_safe_function_calls, typename... Args, typename Fx, typename... FxArgs> | ||
11301 | inline void call(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { | ||
11302 | call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); | ||
11303 | } | ||
11304 | |||
11305 | template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> | ||
11306 | inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { | ||
11307 | typedef meta::count_for_pack<lua_size, Args...> expected_count; | ||
11308 | return call<check_args>(tr, ta, L, (std::max)(static_cast<int>(lua_gettop(L) - expected_count::value), static_cast<int>(0)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...); | ||
11309 | } | ||
11310 | |||
11311 | template <bool check_args = detail::default_safe_function_calls, typename... Args, typename Fx, typename... FxArgs> | ||
11312 | inline void call_from_top(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { | ||
11313 | typedef meta::count_for_pack<lua_size, Args...> expected_count; | ||
11314 | call<check_args>(tr, ta, L, (std::max)(static_cast<int>(lua_gettop(L) - expected_count::value), static_cast<int>(0)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...); | ||
11315 | } | ||
11316 | |||
11317 | template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename... Args, typename Fx, typename... FxArgs> | ||
11318 | inline int call_into_lua(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { | ||
11319 | call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); | ||
11320 | if (clean_stack) { | ||
11321 | lua_settop(L, 0); | ||
11322 | } | ||
11323 | return 0; | ||
11324 | } | ||
11325 | |||
11326 | template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::neg<std::is_void<Ret0>>::value>> | ||
11327 | inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { | ||
11328 | decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); | ||
11329 | typedef meta::unqualified_t<decltype(r)> R; | ||
11330 | typedef meta::any<is_stack_based<R>, | ||
11331 | std::is_same<R, absolute_index>, | ||
11332 | std::is_same<R, ref_index>, | ||
11333 | std::is_same<R, raw_index>> | ||
11334 | is_stack; | ||
11335 | if (clean_stack && !is_stack::value) { | ||
11336 | lua_settop(L, 0); | ||
11337 | } | ||
11338 | return push_reference(L, std::forward<decltype(r)>(r)); | ||
11339 | } | ||
11340 | |||
11341 | template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... FxArgs> | ||
11342 | inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { | ||
11343 | typedef lua_bind_traits<meta::unqualified_t<Fx>> traits_type; | ||
11344 | typedef typename traits_type::args_list args_list; | ||
11345 | typedef typename traits_type::returns_list returns_list; | ||
11346 | return call_into_lua<check_args, clean_stack>(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); | ||
11347 | } | ||
11348 | |||
11349 | inline call_syntax get_call_syntax(lua_State* L, const string_view& key, int index) { | ||
11350 | if (lua_gettop(L) == 0) { | ||
11351 | return call_syntax::dot; | ||
11352 | } | ||
11353 | luaL_getmetatable(L, key.data()); | ||
11354 | auto pn = pop_n(L, 1); | ||
11355 | if (lua_compare(L, -1, index, LUA_OPEQ) != 1) { | ||
11356 | return call_syntax::dot; | ||
11357 | } | ||
11358 | return call_syntax::colon; | ||
11359 | } | ||
11360 | |||
11361 | inline void script(lua_State* L, const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
11362 | detail::typical_chunk_name_t basechunkname = {}; | ||
11363 | const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); | ||
11364 | if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { | ||
11365 | lua_error(L); | ||
11366 | } | ||
11367 | } | ||
11368 | |||
11369 | inline void script_file(lua_State* L, const std::string& filename, load_mode mode = load_mode::any) { | ||
11370 | if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { | ||
11371 | lua_error(L); | ||
11372 | } | ||
11373 | } | ||
11374 | |||
11375 | inline void luajit_exception_handler(lua_State* L, int (*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { | ||
11376 | #if defined(SOL_LUAJIT) && !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) | ||
11377 | if (L == nullptr) { | ||
11378 | return; | ||
11379 | } | ||
11380 | lua_pushlightuserdata(L, (void*)handler); | ||
11381 | auto pn = pop_n(L, 1); | ||
11382 | luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); | ||
11383 | #else | ||
11384 | (void)L; | ||
11385 | (void)handler; | ||
11386 | #endif | ||
11387 | } | ||
11388 | |||
11389 | inline void luajit_exception_off(lua_State* L) { | ||
11390 | #if defined(SOL_LUAJIT) | ||
11391 | if (L == nullptr) { | ||
11392 | return; | ||
11393 | } | ||
11394 | luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF); | ||
11395 | #else | ||
11396 | (void)L; | ||
11397 | #endif | ||
11398 | } | ||
11399 | } // namespace stack | ||
11400 | } // namespace sol | ||
11401 | |||
11402 | // end of sol/stack.hpp | ||
11403 | |||
11404 | // beginning of sol/unsafe_function.hpp | ||
11405 | |||
11406 | // beginning of sol/function_result.hpp | ||
11407 | |||
11408 | // beginning of sol/protected_function_result.hpp | ||
11409 | |||
11410 | // beginning of sol/proxy_base.hpp | ||
11411 | |||
11412 | namespace sol { | ||
11413 | struct proxy_base_tag {}; | ||
11414 | |||
11415 | template <typename Super> | ||
11416 | struct proxy_base : proxy_base_tag { | ||
11417 | operator std::string() const { | ||
11418 | const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); | ||
11419 | return super.template get<std::string>(); | ||
11420 | } | ||
11421 | |||
11422 | template <typename T, meta::enable<meta::neg<meta::is_string_constructible<T>>, is_proxy_primitive<meta::unqualified_t<T>>> = meta::enabler> | ||
11423 | operator T() const { | ||
11424 | const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); | ||
11425 | return super.template get<T>(); | ||
11426 | } | ||
11427 | |||
11428 | template <typename T, meta::enable<meta::neg<meta::is_string_constructible<T>>, meta::neg<is_proxy_primitive<meta::unqualified_t<T>>>> = meta::enabler> | ||
11429 | operator T&() const { | ||
11430 | const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); | ||
11431 | return super.template get<T&>(); | ||
11432 | } | ||
11433 | |||
11434 | lua_State* lua_state() const { | ||
11435 | const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); | ||
11436 | return super.lua_state(); | ||
11437 | } | ||
11438 | }; | ||
11439 | } // namespace sol | ||
11440 | |||
11441 | // end of sol/proxy_base.hpp | ||
11442 | |||
11443 | // beginning of sol/stack_iterator.hpp | ||
11444 | |||
11445 | namespace sol { | ||
11446 | template <typename proxy_t, bool is_const> | ||
11447 | struct stack_iterator { | ||
11448 | typedef std::conditional_t<is_const, const proxy_t, proxy_t> reference; | ||
11449 | typedef std::conditional_t<is_const, const proxy_t*, proxy_t*> pointer; | ||
11450 | typedef proxy_t value_type; | ||
11451 | typedef std::ptrdiff_t difference_type; | ||
11452 | typedef std::random_access_iterator_tag iterator_category; | ||
11453 | lua_State* L; | ||
11454 | int index; | ||
11455 | int stacktop; | ||
11456 | proxy_t sp; | ||
11457 | |||
11458 | stack_iterator() | ||
11459 | : L(nullptr), index((std::numeric_limits<int>::max)()), stacktop((std::numeric_limits<int>::max)()), sp() { | ||
11460 | } | ||
11461 | stack_iterator(const stack_iterator<proxy_t, true>& r) | ||
11462 | : L(r.L), index(r.index), stacktop(r.stacktop), sp(r.sp) { | ||
11463 | } | ||
11464 | stack_iterator(lua_State* luastate, int idx, int topidx) | ||
11465 | : L(luastate), index(idx), stacktop(topidx), sp(luastate, idx) { | ||
11466 | } | ||
11467 | |||
11468 | reference operator*() { | ||
11469 | return proxy_t(L, index); | ||
11470 | } | ||
11471 | |||
11472 | reference operator*() const { | ||
11473 | return proxy_t(L, index); | ||
11474 | } | ||
11475 | |||
11476 | pointer operator->() { | ||
11477 | sp = proxy_t(L, index); | ||
11478 | return &sp; | ||
11479 | } | ||
11480 | |||
11481 | pointer operator->() const { | ||
11482 | const_cast<proxy_t&>(sp) = proxy_t(L, index); | ||
11483 | return &sp; | ||
11484 | } | ||
11485 | |||
11486 | stack_iterator& operator++() { | ||
11487 | ++index; | ||
11488 | return *this; | ||
11489 | } | ||
11490 | |||
11491 | stack_iterator operator++(int) { | ||
11492 | auto r = *this; | ||
11493 | this->operator++(); | ||
11494 | return r; | ||
11495 | } | ||
11496 | |||
11497 | stack_iterator& operator--() { | ||
11498 | --index; | ||
11499 | return *this; | ||
11500 | } | ||
11501 | |||
11502 | stack_iterator operator--(int) { | ||
11503 | auto r = *this; | ||
11504 | this->operator--(); | ||
11505 | return r; | ||
11506 | } | ||
11507 | |||
11508 | stack_iterator& operator+=(difference_type idx) { | ||
11509 | index += static_cast<int>(idx); | ||
11510 | return *this; | ||
11511 | } | ||
11512 | |||
11513 | stack_iterator& operator-=(difference_type idx) { | ||
11514 | index -= static_cast<int>(idx); | ||
11515 | return *this; | ||
11516 | } | ||
11517 | |||
11518 | difference_type operator-(const stack_iterator& r) const { | ||
11519 | return index - r.index; | ||
11520 | } | ||
11521 | |||
11522 | stack_iterator operator+(difference_type idx) const { | ||
11523 | stack_iterator r = *this; | ||
11524 | r += idx; | ||
11525 | return r; | ||
11526 | } | ||
11527 | |||
11528 | reference operator[](difference_type idx) const { | ||
11529 | return proxy_t(L, index + static_cast<int>(idx)); | ||
11530 | } | ||
11531 | |||
11532 | bool operator==(const stack_iterator& r) const { | ||
11533 | if (stacktop == (std::numeric_limits<int>::max)()) { | ||
11534 | return r.index == r.stacktop; | ||
11535 | } | ||
11536 | else if (r.stacktop == (std::numeric_limits<int>::max)()) { | ||
11537 | return index == stacktop; | ||
11538 | } | ||
11539 | return index == r.index; | ||
11540 | } | ||
11541 | |||
11542 | bool operator!=(const stack_iterator& r) const { | ||
11543 | return !(this->operator==(r)); | ||
11544 | } | ||
11545 | |||
11546 | bool operator<(const stack_iterator& r) const { | ||
11547 | return index < r.index; | ||
11548 | } | ||
11549 | |||
11550 | bool operator>(const stack_iterator& r) const { | ||
11551 | return index > r.index; | ||
11552 | } | ||
11553 | |||
11554 | bool operator<=(const stack_iterator& r) const { | ||
11555 | return index <= r.index; | ||
11556 | } | ||
11557 | |||
11558 | bool operator>=(const stack_iterator& r) const { | ||
11559 | return index >= r.index; | ||
11560 | } | ||
11561 | }; | ||
11562 | |||
11563 | template <typename proxy_t, bool is_const> | ||
11564 | 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) { | ||
11565 | return r + n; | ||
11566 | } | ||
11567 | } // namespace sol | ||
11568 | |||
11569 | // end of sol/stack_iterator.hpp | ||
11570 | |||
11571 | // beginning of sol/stack_proxy.hpp | ||
11572 | |||
11573 | // beginning of sol/stack_proxy_base.hpp | ||
11574 | |||
11575 | namespace sol { | ||
11576 | struct stack_proxy_base : public proxy_base<stack_proxy_base> { | ||
11577 | private: | ||
11578 | lua_State* L; | ||
11579 | int index; | ||
11580 | |||
11581 | public: | ||
11582 | stack_proxy_base() | ||
11583 | : L(nullptr), index(0) { | ||
11584 | } | ||
11585 | stack_proxy_base(lua_State* L, int index) | ||
11586 | : L(L), index(index) { | ||
11587 | } | ||
11588 | |||
11589 | template <typename T> | ||
11590 | decltype(auto) get() const { | ||
11591 | return stack::get<T>(L, stack_index()); | ||
11592 | } | ||
11593 | |||
11594 | template <typename T> | ||
11595 | bool is() const { | ||
11596 | return stack::check<T>(L, stack_index()); | ||
11597 | } | ||
11598 | |||
11599 | template <typename T> | ||
11600 | decltype(auto) as() const { | ||
11601 | return get<T>(); | ||
11602 | } | ||
11603 | |||
11604 | type get_type() const noexcept { | ||
11605 | return type_of(lua_state(), stack_index()); | ||
11606 | } | ||
11607 | |||
11608 | int push() const { | ||
11609 | return push(L); | ||
11610 | } | ||
11611 | |||
11612 | int push(lua_State* Ls) const { | ||
11613 | lua_pushvalue(Ls, index); | ||
11614 | return 1; | ||
11615 | } | ||
11616 | |||
11617 | lua_State* lua_state() const { | ||
11618 | return L; | ||
11619 | } | ||
11620 | int stack_index() const { | ||
11621 | return index; | ||
11622 | } | ||
11623 | }; | ||
11624 | |||
11625 | namespace stack { | ||
11626 | template <> | ||
11627 | struct getter<stack_proxy_base> { | ||
11628 | static stack_proxy_base get(lua_State* L, int index = -1) { | ||
11629 | return stack_proxy_base(L, index); | ||
11630 | } | ||
11631 | }; | ||
11632 | |||
11633 | template <> | ||
11634 | struct pusher<stack_proxy_base> { | ||
11635 | static int push(lua_State*, const stack_proxy_base& ref) { | ||
11636 | return ref.push(); | ||
11637 | } | ||
11638 | }; | ||
11639 | } // namespace stack | ||
11640 | |||
11641 | } // namespace sol | ||
11642 | |||
11643 | // end of sol/stack_proxy_base.hpp | ||
11644 | |||
11645 | namespace sol { | ||
11646 | struct stack_proxy : public stack_proxy_base { | ||
11647 | public: | ||
11648 | stack_proxy() | ||
11649 | : stack_proxy_base() { | ||
11650 | } | ||
11651 | stack_proxy(lua_State* L, int index) | ||
11652 | : stack_proxy_base(L, index) { | ||
11653 | } | ||
11654 | |||
11655 | template <typename... Ret, typename... Args> | ||
11656 | decltype(auto) call(Args&&... args); | ||
11657 | |||
11658 | template <typename... Args> | ||
11659 | decltype(auto) operator()(Args&&... args) { | ||
11660 | return call<>(std::forward<Args>(args)...); | ||
11661 | } | ||
11662 | }; | ||
11663 | |||
11664 | namespace stack { | ||
11665 | template <> | ||
11666 | struct getter<stack_proxy> { | ||
11667 | static stack_proxy get(lua_State* L, int index = -1) { | ||
11668 | return stack_proxy(L, index); | ||
11669 | } | ||
11670 | }; | ||
11671 | |||
11672 | template <> | ||
11673 | struct pusher<stack_proxy> { | ||
11674 | static int push(lua_State*, const stack_proxy& ref) { | ||
11675 | return ref.push(); | ||
11676 | } | ||
11677 | }; | ||
11678 | } // namespace stack | ||
11679 | } // namespace sol | ||
11680 | |||
11681 | // end of sol/stack_proxy.hpp | ||
11682 | |||
11683 | namespace sol { | ||
11684 | struct protected_function_result : public proxy_base<protected_function_result> { | ||
11685 | private: | ||
11686 | lua_State* L; | ||
11687 | int index; | ||
11688 | int returncount; | ||
11689 | int popcount; | ||
11690 | call_status err; | ||
11691 | |||
11692 | template <typename T> | ||
11693 | decltype(auto) tagged_get(types<optional<T>>, int index_offset) const { | ||
11694 | typedef decltype(stack::get<optional<T>>(L, index)) ret_t; | ||
11695 | int target = index + index_offset; | ||
11696 | if (!valid()) { | ||
11697 | return ret_t(nullopt); | ||
11698 | } | ||
11699 | return stack::get<optional<T>>(L, target); | ||
11700 | } | ||
11701 | |||
11702 | template <typename T> | ||
11703 | decltype(auto) tagged_get(types<T>, int index_offset) const { | ||
11704 | int target = index + index_offset; | ||
11705 | #if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES | ||
11706 | if (!valid()) { | ||
11707 | type t = type_of(L, target); | ||
11708 | type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is not an error)"); | ||
11709 | } | ||
11710 | #endif // Check Argument Safety | ||
11711 | return stack::get<T>(L, target); | ||
11712 | } | ||
11713 | |||
11714 | optional<error> tagged_get(types<optional<error>>, int index_offset) const { | ||
11715 | int target = index + index_offset; | ||
11716 | if (valid()) { | ||
11717 | return nullopt; | ||
11718 | } | ||
11719 | return error(detail::direct_error, stack::get<std::string>(L, target)); | ||
11720 | } | ||
11721 | |||
11722 | error tagged_get(types<error>, int index_offset) const { | ||
11723 | int target = index + index_offset; | ||
11724 | #if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES | ||
11725 | if (valid()) { | ||
11726 | type t = type_of(L, target); | ||
11727 | type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is an error)"); | ||
11728 | } | ||
11729 | #endif // Check Argument Safety | ||
11730 | return error(detail::direct_error, stack::get<std::string>(L, target)); | ||
11731 | } | ||
11732 | |||
11733 | public: | ||
11734 | typedef stack_proxy reference_type; | ||
11735 | typedef stack_proxy value_type; | ||
11736 | typedef stack_proxy* pointer; | ||
11737 | typedef std::ptrdiff_t difference_type; | ||
11738 | typedef std::size_t size_type; | ||
11739 | typedef stack_iterator<stack_proxy, false> iterator; | ||
11740 | typedef stack_iterator<stack_proxy, true> const_iterator; | ||
11741 | typedef std::reverse_iterator<iterator> reverse_iterator; | ||
11742 | typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | ||
11743 | |||
11744 | protected_function_result() = default; | ||
11745 | protected_function_result(lua_State* Ls, int idx = -1, int retnum = 0, int popped = 0, call_status pferr = call_status::ok) noexcept | ||
11746 | : L(Ls), index(idx), returncount(retnum), popcount(popped), err(pferr) { | ||
11747 | } | ||
11748 | protected_function_result(const protected_function_result&) = default; | ||
11749 | protected_function_result& operator=(const protected_function_result&) = default; | ||
11750 | protected_function_result(protected_function_result&& o) noexcept | ||
11751 | : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { | ||
11752 | // Must be manual, otherwise destructor will screw us | ||
11753 | // return count being 0 is enough to keep things clean | ||
11754 | // but we will be thorough | ||
11755 | o.abandon(); | ||
11756 | } | ||
11757 | protected_function_result& operator=(protected_function_result&& o) noexcept { | ||
11758 | L = o.L; | ||
11759 | index = o.index; | ||
11760 | returncount = o.returncount; | ||
11761 | popcount = o.popcount; | ||
11762 | err = o.err; | ||
11763 | // Must be manual, otherwise destructor will screw us | ||
11764 | // return count being 0 is enough to keep things clean | ||
11765 | // but we will be thorough | ||
11766 | o.abandon(); | ||
11767 | return *this; | ||
11768 | } | ||
11769 | |||
11770 | protected_function_result(const unsafe_function_result& o) = delete; | ||
11771 | protected_function_result& operator=(const unsafe_function_result& o) = delete; | ||
11772 | protected_function_result(unsafe_function_result&& o) noexcept; | ||
11773 | protected_function_result& operator=(unsafe_function_result&& o) noexcept; | ||
11774 | |||
11775 | call_status status() const noexcept { | ||
11776 | return err; | ||
11777 | } | ||
11778 | |||
11779 | bool valid() const noexcept { | ||
11780 | return status() == call_status::ok || status() == call_status::yielded; | ||
11781 | } | ||
11782 | |||
11783 | template <typename T> | ||
11784 | decltype(auto) get(int index_offset = 0) const { | ||
11785 | return tagged_get(types<meta::unqualified_t<T>>(), index_offset); | ||
11786 | } | ||
11787 | |||
11788 | type get_type(difference_type index_offset = 0) const noexcept { | ||
11789 | return type_of(L, index + static_cast<int>(index_offset)); | ||
11790 | } | ||
11791 | |||
11792 | stack_proxy operator[](difference_type index_offset) const { | ||
11793 | return stack_proxy(L, index + static_cast<int>(index_offset)); | ||
11794 | } | ||
11795 | |||
11796 | iterator begin() { | ||
11797 | return iterator(L, index, stack_index() + return_count()); | ||
11798 | } | ||
11799 | iterator end() { | ||
11800 | return iterator(L, stack_index() + return_count(), stack_index() + return_count()); | ||
11801 | } | ||
11802 | const_iterator begin() const { | ||
11803 | return const_iterator(L, index, stack_index() + return_count()); | ||
11804 | } | ||
11805 | const_iterator end() const { | ||
11806 | return const_iterator(L, stack_index() + return_count(), stack_index() + return_count()); | ||
11807 | } | ||
11808 | const_iterator cbegin() const { | ||
11809 | return begin(); | ||
11810 | } | ||
11811 | const_iterator cend() const { | ||
11812 | return end(); | ||
11813 | } | ||
11814 | |||
11815 | reverse_iterator rbegin() { | ||
11816 | return std::reverse_iterator<iterator>(begin()); | ||
11817 | } | ||
11818 | reverse_iterator rend() { | ||
11819 | return std::reverse_iterator<iterator>(end()); | ||
11820 | } | ||
11821 | const_reverse_iterator rbegin() const { | ||
11822 | return std::reverse_iterator<const_iterator>(begin()); | ||
11823 | } | ||
11824 | const_reverse_iterator rend() const { | ||
11825 | return std::reverse_iterator<const_iterator>(end()); | ||
11826 | } | ||
11827 | const_reverse_iterator crbegin() const { | ||
11828 | return std::reverse_iterator<const_iterator>(cbegin()); | ||
11829 | } | ||
11830 | const_reverse_iterator crend() const { | ||
11831 | return std::reverse_iterator<const_iterator>(cend()); | ||
11832 | } | ||
11833 | |||
11834 | lua_State* lua_state() const noexcept { | ||
11835 | return L; | ||
11836 | }; | ||
11837 | int stack_index() const noexcept { | ||
11838 | return index; | ||
11839 | }; | ||
11840 | int return_count() const noexcept { | ||
11841 | return returncount; | ||
11842 | }; | ||
11843 | int pop_count() const noexcept { | ||
11844 | return popcount; | ||
11845 | }; | ||
11846 | void abandon() noexcept { | ||
11847 | //L = nullptr; | ||
11848 | index = 0; | ||
11849 | returncount = 0; | ||
11850 | popcount = 0; | ||
11851 | err = call_status::runtime; | ||
11852 | } | ||
11853 | ~protected_function_result() { | ||
11854 | stack::remove(L, index, popcount); | ||
11855 | } | ||
11856 | }; | ||
11857 | |||
11858 | namespace stack { | ||
11859 | template <> | ||
11860 | struct pusher<protected_function_result> { | ||
11861 | static int push(lua_State* L, const protected_function_result& pfr) { | ||
11862 | int p = 0; | ||
11863 | for (int i = 0; i < pfr.pop_count(); ++i) { | ||
11864 | lua_pushvalue(L, i + pfr.stack_index()); | ||
11865 | ++p; | ||
11866 | } | ||
11867 | return p; | ||
11868 | } | ||
11869 | }; | ||
11870 | } // namespace stack | ||
11871 | } // namespace sol | ||
11872 | |||
11873 | // end of sol/protected_function_result.hpp | ||
11874 | |||
11875 | // beginning of sol/unsafe_function_result.hpp | ||
11876 | |||
11877 | namespace sol { | ||
11878 | struct unsafe_function_result : public proxy_base<unsafe_function_result> { | ||
11879 | private: | ||
11880 | lua_State* L; | ||
11881 | int index; | ||
11882 | int returncount; | ||
11883 | |||
11884 | public: | ||
11885 | typedef stack_proxy reference_type; | ||
11886 | typedef stack_proxy value_type; | ||
11887 | typedef stack_proxy* pointer; | ||
11888 | typedef std::ptrdiff_t difference_type; | ||
11889 | typedef std::size_t size_type; | ||
11890 | typedef stack_iterator<stack_proxy, false> iterator; | ||
11891 | typedef stack_iterator<stack_proxy, true> const_iterator; | ||
11892 | typedef std::reverse_iterator<iterator> reverse_iterator; | ||
11893 | typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | ||
11894 | |||
11895 | unsafe_function_result() = default; | ||
11896 | unsafe_function_result(lua_State* Ls, int idx = -1, int retnum = 0) | ||
11897 | : L(Ls), index(idx), returncount(retnum) { | ||
11898 | } | ||
11899 | unsafe_function_result(const unsafe_function_result&) = default; | ||
11900 | unsafe_function_result& operator=(const unsafe_function_result&) = default; | ||
11901 | unsafe_function_result(unsafe_function_result&& o) | ||
11902 | : L(o.L), index(o.index), returncount(o.returncount) { | ||
11903 | // Must be manual, otherwise destructor will screw us | ||
11904 | // return count being 0 is enough to keep things clean | ||
11905 | // but will be thorough | ||
11906 | o.abandon(); | ||
11907 | } | ||
11908 | unsafe_function_result& operator=(unsafe_function_result&& o) { | ||
11909 | L = o.L; | ||
11910 | index = o.index; | ||
11911 | returncount = o.returncount; | ||
11912 | // Must be manual, otherwise destructor will screw us | ||
11913 | // return count being 0 is enough to keep things clean | ||
11914 | // but will be thorough | ||
11915 | o.abandon(); | ||
11916 | return *this; | ||
11917 | } | ||
11918 | |||
11919 | unsafe_function_result(const protected_function_result& o) = delete; | ||
11920 | unsafe_function_result& operator=(const protected_function_result& o) = delete; | ||
11921 | unsafe_function_result(protected_function_result&& o) noexcept; | ||
11922 | unsafe_function_result& operator=(protected_function_result&& o) noexcept; | ||
11923 | |||
11924 | template <typename T> | ||
11925 | decltype(auto) get(difference_type index_offset = 0) const { | ||
11926 | return stack::get<T>(L, index + static_cast<int>(index_offset)); | ||
11927 | } | ||
11928 | |||
11929 | type get_type(difference_type index_offset = 0) const noexcept { | ||
11930 | return type_of(L, index + static_cast<int>(index_offset)); | ||
11931 | } | ||
11932 | |||
11933 | stack_proxy operator[](difference_type index_offset) const { | ||
11934 | return stack_proxy(L, index + static_cast<int>(index_offset)); | ||
11935 | } | ||
11936 | |||
11937 | iterator begin() { | ||
11938 | return iterator(L, index, stack_index() + return_count()); | ||
11939 | } | ||
11940 | iterator end() { | ||
11941 | return iterator(L, stack_index() + return_count(), stack_index() + return_count()); | ||
11942 | } | ||
11943 | const_iterator begin() const { | ||
11944 | return const_iterator(L, index, stack_index() + return_count()); | ||
11945 | } | ||
11946 | const_iterator end() const { | ||
11947 | return const_iterator(L, stack_index() + return_count(), stack_index() + return_count()); | ||
11948 | } | ||
11949 | const_iterator cbegin() const { | ||
11950 | return begin(); | ||
11951 | } | ||
11952 | const_iterator cend() const { | ||
11953 | return end(); | ||
11954 | } | ||
11955 | |||
11956 | reverse_iterator rbegin() { | ||
11957 | return std::reverse_iterator<iterator>(begin()); | ||
11958 | } | ||
11959 | reverse_iterator rend() { | ||
11960 | return std::reverse_iterator<iterator>(end()); | ||
11961 | } | ||
11962 | const_reverse_iterator rbegin() const { | ||
11963 | return std::reverse_iterator<const_iterator>(begin()); | ||
11964 | } | ||
11965 | const_reverse_iterator rend() const { | ||
11966 | return std::reverse_iterator<const_iterator>(end()); | ||
11967 | } | ||
11968 | const_reverse_iterator crbegin() const { | ||
11969 | return std::reverse_iterator<const_iterator>(cbegin()); | ||
11970 | } | ||
11971 | const_reverse_iterator crend() const { | ||
11972 | return std::reverse_iterator<const_iterator>(cend()); | ||
11973 | } | ||
11974 | |||
11975 | call_status status() const noexcept { | ||
11976 | return call_status::ok; | ||
11977 | } | ||
11978 | |||
11979 | bool valid() const noexcept { | ||
11980 | return status() == call_status::ok || status() == call_status::yielded; | ||
11981 | } | ||
11982 | |||
11983 | lua_State* lua_state() const { | ||
11984 | return L; | ||
11985 | }; | ||
11986 | int stack_index() const { | ||
11987 | return index; | ||
11988 | }; | ||
11989 | int return_count() const { | ||
11990 | return returncount; | ||
11991 | }; | ||
11992 | void abandon() noexcept { | ||
11993 | //L = nullptr; | ||
11994 | index = 0; | ||
11995 | returncount = 0; | ||
11996 | } | ||
11997 | ~unsafe_function_result() { | ||
11998 | lua_pop(L, returncount); | ||
11999 | } | ||
12000 | }; | ||
12001 | |||
12002 | namespace stack { | ||
12003 | template <> | ||
12004 | struct pusher<unsafe_function_result> { | ||
12005 | static int push(lua_State* L, const unsafe_function_result& fr) { | ||
12006 | int p = 0; | ||
12007 | for (int i = 0; i < fr.return_count(); ++i) { | ||
12008 | lua_pushvalue(L, i + fr.stack_index()); | ||
12009 | ++p; | ||
12010 | } | ||
12011 | return p; | ||
12012 | } | ||
12013 | }; | ||
12014 | } // namespace stack | ||
12015 | } // namespace sol | ||
12016 | |||
12017 | // end of sol/unsafe_function_result.hpp | ||
12018 | |||
12019 | namespace sol { | ||
12020 | |||
12021 | namespace detail { | ||
12022 | template <> | ||
12023 | struct is_speshul<unsafe_function_result> : std::true_type {}; | ||
12024 | template <> | ||
12025 | struct is_speshul<protected_function_result> : std::true_type {}; | ||
12026 | |||
12027 | template <std::size_t I, typename... Args, typename T> | ||
12028 | stack_proxy get(types<Args...>, index_value<0>, index_value<I>, const T& fr) { | ||
12029 | return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I)); | ||
12030 | } | ||
12031 | |||
12032 | template <std::size_t I, std::size_t N, typename Arg, typename... Args, typename T, meta::enable<meta::boolean<(N > 0)>> = meta::enabler> | ||
12033 | stack_proxy get(types<Arg, Args...>, index_value<N>, index_value<I>, const T& fr) { | ||
12034 | return get(types<Args...>(), index_value<N - 1>(), index_value<I + lua_size<Arg>::value>(), fr); | ||
12035 | } | ||
12036 | } // namespace detail | ||
12037 | |||
12038 | template <> | ||
12039 | struct tie_size<unsafe_function_result> : std::integral_constant<std::size_t, SIZE_MAX> {}; | ||
12040 | |||
12041 | template <> | ||
12042 | struct tie_size<protected_function_result> : std::integral_constant<std::size_t, SIZE_MAX> {}; | ||
12043 | |||
12044 | template <std::size_t I> | ||
12045 | stack_proxy get(const unsafe_function_result& fr) { | ||
12046 | return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I)); | ||
12047 | } | ||
12048 | |||
12049 | template <std::size_t I, typename... Args> | ||
12050 | stack_proxy get(types<Args...> t, const unsafe_function_result& fr) { | ||
12051 | return detail::get(t, index_value<I>(), index_value<0>(), fr); | ||
12052 | } | ||
12053 | |||
12054 | template <std::size_t I> | ||
12055 | stack_proxy get(const protected_function_result& fr) { | ||
12056 | return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I)); | ||
12057 | } | ||
12058 | |||
12059 | template <std::size_t I, typename... Args> | ||
12060 | stack_proxy get(types<Args...> t, const protected_function_result& fr) { | ||
12061 | return detail::get(t, index_value<I>(), index_value<0>(), fr); | ||
12062 | } | ||
12063 | } // namespace sol | ||
12064 | |||
12065 | // end of sol/function_result.hpp | ||
12066 | |||
12067 | // beginning of sol/function_types.hpp | ||
12068 | |||
12069 | // beginning of sol/function_types_core.hpp | ||
12070 | |||
12071 | // beginning of sol/wrapper.hpp | ||
12072 | |||
12073 | namespace sol { | ||
12074 | |||
12075 | namespace detail { | ||
12076 | template <typename T> | ||
12077 | using array_return_type = std::conditional_t<std::is_array<T>::value, std::add_lvalue_reference_t<T>, T>; | ||
12078 | } | ||
12079 | |||
12080 | template <typename F, typename = void> | ||
12081 | struct wrapper { | ||
12082 | typedef lua_bind_traits<meta::unqualified_t<F>> traits_type; | ||
12083 | typedef typename traits_type::args_list args_list; | ||
12084 | typedef typename traits_type::args_list free_args_list; | ||
12085 | typedef typename traits_type::returns_list returns_list; | ||
12086 | |||
12087 | template <typename... Args> | ||
12088 | static decltype(auto) call(F& f, Args&&... args) { | ||
12089 | return f(std::forward<Args>(args)...); | ||
12090 | } | ||
12091 | |||
12092 | struct caller { | ||
12093 | template <typename... Args> | ||
12094 | decltype(auto) operator()(F& fx, Args&&... args) const { | ||
12095 | return call(fx, std::forward<Args>(args)...); | ||
12096 | } | ||
12097 | }; | ||
12098 | }; | ||
12099 | |||
12100 | template <typename F> | ||
12101 | struct wrapper<F, std::enable_if_t<std::is_function<std::remove_pointer_t<meta::unqualified_t<F>>>::value>> { | ||
12102 | typedef lua_bind_traits<std::remove_pointer_t<meta::unqualified_t<F>>> traits_type; | ||
12103 | typedef typename traits_type::args_list args_list; | ||
12104 | typedef typename traits_type::args_list free_args_list; | ||
12105 | typedef typename traits_type::returns_list returns_list; | ||
12106 | |||
12107 | template <F fx, typename... Args> | ||
12108 | static decltype(auto) invoke(Args&&... args) { | ||
12109 | return fx(std::forward<Args>(args)...); | ||
12110 | } | ||
12111 | |||
12112 | template <typename... Args> | ||
12113 | static decltype(auto) call(F& fx, Args&&... args) { | ||
12114 | return fx(std::forward<Args>(args)...); | ||
12115 | } | ||
12116 | |||
12117 | struct caller { | ||
12118 | template <typename... Args> | ||
12119 | decltype(auto) operator()(F& fx, Args&&... args) const { | ||
12120 | return call(fx, std::forward<Args>(args)...); | ||
12121 | } | ||
12122 | }; | ||
12123 | |||
12124 | template <F fx> | ||
12125 | struct invoker { | ||
12126 | template <typename... Args> | ||
12127 | decltype(auto) operator()(Args&&... args) const { | ||
12128 | return invoke<fx>(std::forward<Args>(args)...); | ||
12129 | } | ||
12130 | }; | ||
12131 | }; | ||
12132 | |||
12133 | template <typename F> | ||
12134 | struct wrapper<F, std::enable_if_t<std::is_member_object_pointer<meta::unqualified_t<F>>::value>> { | ||
12135 | typedef lua_bind_traits<meta::unqualified_t<F>> traits_type; | ||
12136 | typedef typename traits_type::object_type object_type; | ||
12137 | typedef typename traits_type::return_type return_type; | ||
12138 | typedef typename traits_type::args_list args_list; | ||
12139 | typedef types<object_type&, return_type> free_args_list; | ||
12140 | typedef typename traits_type::returns_list returns_list; | ||
12141 | |||
12142 | template <F fx> | ||
12143 | static auto call(object_type& mem) -> detail::array_return_type<decltype(mem.*fx)> { | ||
12144 | return mem.*fx; | ||
12145 | } | ||
12146 | |||
12147 | template <F fx, typename Arg, typename... Args> | ||
12148 | static decltype(auto) invoke(object_type& mem, Arg&& arg, Args&&...) { | ||
12149 | return mem.*fx = std::forward<Arg>(arg); | ||
12150 | } | ||
12151 | |||
12152 | template <typename Fx> | ||
12153 | static auto call(Fx&& fx, object_type& mem) -> detail::array_return_type<decltype(mem.*fx)> { | ||
12154 | return mem.*fx; | ||
12155 | } | ||
12156 | |||
12157 | template <typename Fx, typename Arg, typename... Args> | ||
12158 | static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) { | ||
12159 | (mem.*fx) = std::forward<Arg>(arg); | ||
12160 | } | ||
12161 | |||
12162 | struct caller { | ||
12163 | template <typename Fx, typename... Args> | ||
12164 | decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const { | ||
12165 | return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...); | ||
12166 | } | ||
12167 | }; | ||
12168 | |||
12169 | template <F fx> | ||
12170 | struct invoker { | ||
12171 | template <typename... Args> | ||
12172 | decltype(auto) operator()(Args&&... args) const { | ||
12173 | return invoke<fx>(std::forward<Args>(args)...); | ||
12174 | } | ||
12175 | }; | ||
12176 | }; | ||
12177 | |||
12178 | template <typename F, typename R, typename O, typename... FArgs> | ||
12179 | struct member_function_wrapper { | ||
12180 | typedef O object_type; | ||
12181 | typedef lua_bind_traits<F> traits_type; | ||
12182 | typedef typename traits_type::args_list args_list; | ||
12183 | typedef types<object_type&, FArgs...> free_args_list; | ||
12184 | typedef meta::tuple_types<R> returns_list; | ||
12185 | |||
12186 | template <F fx, typename... Args> | ||
12187 | static R invoke(O& mem, Args&&... args) { | ||
12188 | return (mem.*fx)(std::forward<Args>(args)...); | ||
12189 | } | ||
12190 | |||
12191 | template <typename Fx, typename... Args> | ||
12192 | static R call(Fx&& fx, O& mem, Args&&... args) { | ||
12193 | return (mem.*fx)(std::forward<Args>(args)...); | ||
12194 | } | ||
12195 | |||
12196 | struct caller { | ||
12197 | template <typename Fx, typename... Args> | ||
12198 | decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const { | ||
12199 | return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...); | ||
12200 | } | ||
12201 | }; | ||
12202 | |||
12203 | template <F fx> | ||
12204 | struct invoker { | ||
12205 | template <typename... Args> | ||
12206 | decltype(auto) operator()(O& mem, Args&&... args) const { | ||
12207 | return invoke<fx>(mem, std::forward<Args>(args)...); | ||
12208 | } | ||
12209 | }; | ||
12210 | }; | ||
12211 | |||
12212 | template <typename R, typename O, typename... Args> | ||
12213 | struct wrapper<R (O::*)(Args...)> : public member_function_wrapper<R (O::*)(Args...), R, O, Args...> { | ||
12214 | }; | ||
12215 | |||
12216 | template <typename R, typename O, typename... Args> | ||
12217 | struct wrapper<R (O::*)(Args...) const> : public member_function_wrapper<R (O::*)(Args...) const, R, O, Args...> { | ||
12218 | }; | ||
12219 | |||
12220 | template <typename R, typename O, typename... Args> | ||
12221 | struct wrapper<R (O::*)(Args...) const volatile> : public member_function_wrapper<R (O::*)(Args...) const volatile, R, O, Args...> { | ||
12222 | }; | ||
12223 | |||
12224 | template <typename R, typename O, typename... Args> | ||
12225 | struct wrapper<R (O::*)(Args...)&> : public member_function_wrapper<R (O::*)(Args...)&, R, O, Args...> { | ||
12226 | }; | ||
12227 | |||
12228 | template <typename R, typename O, typename... Args> | ||
12229 | struct wrapper<R (O::*)(Args...) const&> : public member_function_wrapper<R (O::*)(Args...) const&, R, O, Args...> { | ||
12230 | }; | ||
12231 | |||
12232 | template <typename R, typename O, typename... Args> | ||
12233 | struct wrapper<R (O::*)(Args...) const volatile&> : public member_function_wrapper<R (O::*)(Args...) const volatile&, R, O, Args...> { | ||
12234 | }; | ||
12235 | |||
12236 | template <typename R, typename O, typename... Args> | ||
12237 | struct wrapper<R (O::*)(Args..., ...)&> : public member_function_wrapper<R (O::*)(Args..., ...)&, R, O, Args...> { | ||
12238 | }; | ||
12239 | |||
12240 | template <typename R, typename O, typename... Args> | ||
12241 | struct wrapper<R (O::*)(Args..., ...) const&> : public member_function_wrapper<R (O::*)(Args..., ...) const&, R, O, Args...> { | ||
12242 | }; | ||
12243 | |||
12244 | template <typename R, typename O, typename... Args> | ||
12245 | struct wrapper<R (O::*)(Args..., ...) const volatile&> : public member_function_wrapper<R (O::*)(Args..., ...) const volatile&, R, O, Args...> { | ||
12246 | }; | ||
12247 | |||
12248 | template <typename R, typename O, typename... Args> | ||
12249 | struct wrapper<R (O::*)(Args...) &&> : public member_function_wrapper<R (O::*)(Args...)&, R, O, Args...> { | ||
12250 | }; | ||
12251 | |||
12252 | template <typename R, typename O, typename... Args> | ||
12253 | struct wrapper<R (O::*)(Args...) const&&> : public member_function_wrapper<R (O::*)(Args...) const&, R, O, Args...> { | ||
12254 | }; | ||
12255 | |||
12256 | template <typename R, typename O, typename... Args> | ||
12257 | struct wrapper<R (O::*)(Args...) const volatile&&> : public member_function_wrapper<R (O::*)(Args...) const volatile&, R, O, Args...> { | ||
12258 | }; | ||
12259 | |||
12260 | template <typename R, typename O, typename... Args> | ||
12261 | struct wrapper<R (O::*)(Args..., ...) &&> : public member_function_wrapper<R (O::*)(Args..., ...)&, R, O, Args...> { | ||
12262 | }; | ||
12263 | |||
12264 | template <typename R, typename O, typename... Args> | ||
12265 | struct wrapper<R (O::*)(Args..., ...) const&&> : public member_function_wrapper<R (O::*)(Args..., ...) const&, R, O, Args...> { | ||
12266 | }; | ||
12267 | |||
12268 | template <typename R, typename O, typename... Args> | ||
12269 | struct wrapper<R (O::*)(Args..., ...) const volatile&&> : public member_function_wrapper<R (O::*)(Args..., ...) const volatile&, R, O, Args...> { | ||
12270 | }; | ||
12271 | |||
12272 | #if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE | ||
12273 | //noexcept has become a part of a function's type | ||
12274 | |||
12275 | template <typename R, typename O, typename... Args> | ||
12276 | struct wrapper<R (O::*)(Args...) noexcept> : public member_function_wrapper<R (O::*)(Args...) noexcept, R, O, Args...> { | ||
12277 | }; | ||
12278 | |||
12279 | template <typename R, typename O, typename... Args> | ||
12280 | struct wrapper<R (O::*)(Args...) const noexcept> : public member_function_wrapper<R (O::*)(Args...) const noexcept, R, O, Args...> { | ||
12281 | }; | ||
12282 | |||
12283 | template <typename R, typename O, typename... Args> | ||
12284 | struct wrapper<R (O::*)(Args...) const volatile noexcept> : public member_function_wrapper<R (O::*)(Args...) const volatile noexcept, R, O, Args...> { | ||
12285 | }; | ||
12286 | |||
12287 | template <typename R, typename O, typename... Args> | ||
12288 | struct wrapper<R (O::*)(Args...) & noexcept> : public member_function_wrapper<R (O::*)(Args...) & noexcept, R, O, Args...> { | ||
12289 | }; | ||
12290 | |||
12291 | template <typename R, typename O, typename... Args> | ||
12292 | struct wrapper<R (O::*)(Args...) const& noexcept> : public member_function_wrapper<R (O::*)(Args...) const& noexcept, R, O, Args...> { | ||
12293 | }; | ||
12294 | |||
12295 | template <typename R, typename O, typename... Args> | ||
12296 | struct wrapper<R (O::*)(Args...) const volatile& noexcept> : public member_function_wrapper<R (O::*)(Args...) const volatile& noexcept, R, O, Args...> { | ||
12297 | }; | ||
12298 | |||
12299 | template <typename R, typename O, typename... Args> | ||
12300 | struct wrapper<R (O::*)(Args..., ...) & noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) & noexcept, R, O, Args...> { | ||
12301 | }; | ||
12302 | |||
12303 | template <typename R, typename O, typename... Args> | ||
12304 | struct wrapper<R (O::*)(Args..., ...) const& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) const& noexcept, R, O, Args...> { | ||
12305 | }; | ||
12306 | |||
12307 | template <typename R, typename O, typename... Args> | ||
12308 | struct wrapper<R (O::*)(Args..., ...) const volatile& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) const volatile& noexcept, R, O, Args...> { | ||
12309 | }; | ||
12310 | |||
12311 | template <typename R, typename O, typename... Args> | ||
12312 | struct wrapper<R (O::*)(Args...) && noexcept> : public member_function_wrapper<R (O::*)(Args...) & noexcept, R, O, Args...> { | ||
12313 | }; | ||
12314 | |||
12315 | template <typename R, typename O, typename... Args> | ||
12316 | struct wrapper<R (O::*)(Args...) const&& noexcept> : public member_function_wrapper<R (O::*)(Args...) const& noexcept, R, O, Args...> { | ||
12317 | }; | ||
12318 | |||
12319 | template <typename R, typename O, typename... Args> | ||
12320 | struct wrapper<R (O::*)(Args...) const volatile&& noexcept> : public member_function_wrapper<R (O::*)(Args...) const volatile& noexcept, R, O, Args...> { | ||
12321 | }; | ||
12322 | |||
12323 | template <typename R, typename O, typename... Args> | ||
12324 | struct wrapper<R (O::*)(Args..., ...) && noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) & noexcept, R, O, Args...> { | ||
12325 | }; | ||
12326 | |||
12327 | template <typename R, typename O, typename... Args> | ||
12328 | struct wrapper<R (O::*)(Args..., ...) const&& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) const& noexcept, R, O, Args...> { | ||
12329 | }; | ||
12330 | |||
12331 | template <typename R, typename O, typename... Args> | ||
12332 | struct wrapper<R (O::*)(Args..., ...) const volatile&& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) const volatile& noexcept, R, O, Args...> { | ||
12333 | }; | ||
12334 | |||
12335 | #endif // noexcept is part of a function's type | ||
12336 | |||
12337 | } // namespace sol | ||
12338 | |||
12339 | // end of sol/wrapper.hpp | ||
12340 | |||
12341 | namespace sol { | ||
12342 | namespace function_detail { | ||
12343 | template <typename Fx, int start = 1, bool is_yielding = false> | ||
12344 | inline int call(lua_State* L) { | ||
12345 | Fx& fx = stack::get<user<Fx>>(L, upvalue_index(start)); | ||
12346 | int nr = fx(L); | ||
12347 | if (is_yielding) { | ||
12348 | return lua_yield(L, nr); | ||
12349 | } | ||
12350 | else { | ||
12351 | return nr; | ||
12352 | } | ||
12353 | } | ||
12354 | } | ||
12355 | } // namespace sol::function_detail | ||
12356 | |||
12357 | // end of sol/function_types_core.hpp | ||
12358 | |||
12359 | // beginning of sol/function_types_templated.hpp | ||
12360 | |||
12361 | // beginning of sol/call.hpp | ||
12362 | |||
12363 | // beginning of sol/protect.hpp | ||
12364 | |||
12365 | namespace sol { | ||
12366 | |||
12367 | template <typename T> | ||
12368 | struct protect_t { | ||
12369 | T value; | ||
12370 | |||
12371 | template <typename Arg, typename... Args, meta::disable<std::is_same<protect_t, meta::unqualified_t<Arg>>> = meta::enabler> | ||
12372 | protect_t(Arg&& arg, Args&&... args) | ||
12373 | : value(std::forward<Arg>(arg), std::forward<Args>(args)...) { | ||
12374 | } | ||
12375 | |||
12376 | protect_t(const protect_t&) = default; | ||
12377 | protect_t(protect_t&&) = default; | ||
12378 | protect_t& operator=(const protect_t&) = default; | ||
12379 | protect_t& operator=(protect_t&&) = default; | ||
12380 | }; | ||
12381 | |||
12382 | template <typename T> | ||
12383 | auto protect(T&& value) { | ||
12384 | return protect_t<std::decay_t<T>>(std::forward<T>(value)); | ||
12385 | } | ||
12386 | |||
12387 | } // namespace sol | ||
12388 | |||
12389 | // end of sol/protect.hpp | ||
12390 | |||
12391 | // beginning of sol/property.hpp | ||
12392 | |||
12393 | namespace sol { | ||
12394 | |||
12395 | struct no_prop {}; | ||
12396 | |||
12397 | template <typename R, typename W> | ||
12398 | struct property_wrapper { | ||
12399 | typedef std::integral_constant<bool, !std::is_void<R>::value> can_read; | ||
12400 | typedef std::integral_constant<bool, !std::is_void<W>::value> can_write; | ||
12401 | typedef std::conditional_t<can_read::value, R, no_prop> Read; | ||
12402 | typedef std::conditional_t<can_write::value, W, no_prop> Write; | ||
12403 | Read read; | ||
12404 | Write write; | ||
12405 | |||
12406 | template <typename Rx, typename Wx> | ||
12407 | property_wrapper(Rx&& r, Wx&& w) | ||
12408 | : read(std::forward<Rx>(r)), write(std::forward<Wx>(w)) { | ||
12409 | } | ||
12410 | }; | ||
12411 | |||
12412 | namespace property_detail { | ||
12413 | template <typename R, typename W> | ||
12414 | inline decltype(auto) property(std::true_type, R&& read, W&& write) { | ||
12415 | return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write)); | ||
12416 | } | ||
12417 | template <typename W, typename R> | ||
12418 | inline decltype(auto) property(std::false_type, W&& write, R&& read) { | ||
12419 | return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write)); | ||
12420 | } | ||
12421 | template <typename R> | ||
12422 | inline decltype(auto) property(std::true_type, R&& read) { | ||
12423 | return property_wrapper<std::decay_t<R>, void>(std::forward<R>(read), no_prop()); | ||
12424 | } | ||
12425 | template <typename W> | ||
12426 | inline decltype(auto) property(std::false_type, W&& write) { | ||
12427 | return property_wrapper<void, std::decay_t<W>>(no_prop(), std::forward<W>(write)); | ||
12428 | } | ||
12429 | } // namespace property_detail | ||
12430 | |||
12431 | template <typename F, typename G> | ||
12432 | inline decltype(auto) property(F&& f, G&& g) { | ||
12433 | typedef lua_bind_traits<meta::unqualified_t<F>> left_traits; | ||
12434 | typedef lua_bind_traits<meta::unqualified_t<G>> right_traits; | ||
12435 | return property_detail::property(meta::boolean<(left_traits::free_arity < right_traits::free_arity)>(), std::forward<F>(f), std::forward<G>(g)); | ||
12436 | } | ||
12437 | |||
12438 | template <typename F> | ||
12439 | inline decltype(auto) property(F&& f) { | ||
12440 | typedef lua_bind_traits<meta::unqualified_t<F>> left_traits; | ||
12441 | return property_detail::property(meta::boolean<(left_traits::free_arity < 2)>(), std::forward<F>(f)); | ||
12442 | } | ||
12443 | |||
12444 | template <typename F> | ||
12445 | inline decltype(auto) readonly_property(F&& f) { | ||
12446 | return property_detail::property(std::true_type(), std::forward<F>(f)); | ||
12447 | } | ||
12448 | |||
12449 | template <typename F> | ||
12450 | inline decltype(auto) writeonly_property(F&& f) { | ||
12451 | return property_detail::property(std::false_type(), std::forward<F>(f)); | ||
12452 | } | ||
12453 | |||
12454 | template <typename T> | ||
12455 | struct readonly_wrapper { | ||
12456 | T v; | ||
12457 | |||
12458 | readonly_wrapper(T v) | ||
12459 | : v(std::move(v)) { | ||
12460 | } | ||
12461 | |||
12462 | operator T&() { | ||
12463 | return v; | ||
12464 | } | ||
12465 | operator const T&() const { | ||
12466 | return v; | ||
12467 | } | ||
12468 | }; | ||
12469 | |||
12470 | // Allow someone to make a member variable readonly (const) | ||
12471 | template <typename R, typename T> | ||
12472 | inline auto readonly(R T::*v) { | ||
12473 | return readonly_wrapper<meta::unqualified_t<decltype(v)>>(v); | ||
12474 | } | ||
12475 | |||
12476 | template <typename T> | ||
12477 | struct var_wrapper { | ||
12478 | T value; | ||
12479 | template <typename... Args> | ||
12480 | var_wrapper(Args&&... args) | ||
12481 | : value(std::forward<Args>(args)...) { | ||
12482 | } | ||
12483 | var_wrapper(const var_wrapper&) = default; | ||
12484 | var_wrapper(var_wrapper&&) = default; | ||
12485 | var_wrapper& operator=(const var_wrapper&) = default; | ||
12486 | var_wrapper& operator=(var_wrapper&&) = default; | ||
12487 | }; | ||
12488 | |||
12489 | template <typename V> | ||
12490 | inline auto var(V&& v) { | ||
12491 | typedef meta::unqualified_t<V> T; | ||
12492 | return var_wrapper<T>(std::forward<V>(v)); | ||
12493 | } | ||
12494 | |||
12495 | namespace meta { | ||
12496 | template <typename T> | ||
12497 | struct is_member_object : std::is_member_object_pointer<T> {}; | ||
12498 | |||
12499 | template <typename T> | ||
12500 | struct is_member_object<readonly_wrapper<T>> : std::true_type {}; | ||
12501 | } // namespace meta | ||
12502 | |||
12503 | } // namespace sol | ||
12504 | |||
12505 | // end of sol/property.hpp | ||
12506 | |||
12507 | namespace sol { | ||
12508 | namespace usertype_detail { | ||
12509 | |||
12510 | } // namespace usertype_detail | ||
12511 | |||
12512 | namespace filter_detail { | ||
12513 | template <int I, int... In> | ||
12514 | inline void handle_filter(static_stack_dependencies<I, In...>, lua_State* L, int&) { | ||
12515 | if (sizeof...(In) == 0) { | ||
12516 | return; | ||
12517 | } | ||
12518 | absolute_index ai(L, I); | ||
12519 | if (type_of(L, ai) != type::userdata) { | ||
12520 | return; | ||
12521 | } | ||
12522 | lua_createtable(L, static_cast<int>(sizeof...(In)), 0); | ||
12523 | stack_reference deps(L, -1); | ||
12524 | auto per_dep = [&L, &deps](int i) { | ||
12525 | lua_pushvalue(L, i); | ||
12526 | luaL_ref(L, deps.stack_index()); | ||
12527 | }; | ||
12528 | (void)per_dep; | ||
12529 | (void)detail::swallow{ int(), (per_dep(In), int())... }; | ||
12530 | lua_setuservalue(L, ai); | ||
12531 | } | ||
12532 | |||
12533 | template <int... In> | ||
12534 | inline void handle_filter(returns_self_with<In...>, lua_State* L, int& pushed) { | ||
12535 | pushed = stack::push(L, raw_index(1)); | ||
12536 | handle_filter(static_stack_dependencies<-1, In...>(), L, pushed); | ||
12537 | } | ||
12538 | |||
12539 | inline void handle_filter(const stack_dependencies& sdeps, lua_State* L, int&) { | ||
12540 | absolute_index ai(L, sdeps.target); | ||
12541 | if (type_of(L, ai) != type::userdata) { | ||
12542 | return; | ||
12543 | } | ||
12544 | lua_createtable(L, static_cast<int>(sdeps.size()), 0); | ||
12545 | stack_reference deps(L, -1); | ||
12546 | for (std::size_t i = 0; i < sdeps.size(); ++i) { | ||
12547 | lua_pushvalue(L, sdeps.stack_indices[i]); | ||
12548 | luaL_ref(L, deps.stack_index()); | ||
12549 | } | ||
12550 | lua_setuservalue(L, ai); | ||
12551 | } | ||
12552 | |||
12553 | template <typename P, meta::disable<std::is_base_of<detail::filter_base_tag, meta::unqualified_t<P>>> = meta::enabler> | ||
12554 | inline void handle_filter(P&& p, lua_State* L, int& pushed) { | ||
12555 | pushed = std::forward<P>(p)(L, pushed); | ||
12556 | } | ||
12557 | } // namespace filter_detail | ||
12558 | |||
12559 | namespace function_detail { | ||
12560 | inline int no_construction_error(lua_State* L) { | ||
12561 | return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); | ||
12562 | } | ||
12563 | } // namespace function_detail | ||
12564 | |||
12565 | namespace call_detail { | ||
12566 | |||
12567 | template <typename R, typename W> | ||
12568 | inline auto& pick(std::true_type, property_wrapper<R, W>& f) { | ||
12569 | return f.read; | ||
12570 | } | ||
12571 | |||
12572 | template <typename R, typename W> | ||
12573 | inline auto& pick(std::false_type, property_wrapper<R, W>& f) { | ||
12574 | return f.write; | ||
12575 | } | ||
12576 | |||
12577 | template <typename T, typename List> | ||
12578 | struct void_call : void_call<T, meta::function_args_t<List>> {}; | ||
12579 | |||
12580 | template <typename T, typename... Args> | ||
12581 | struct void_call<T, types<Args...>> { | ||
12582 | static void call(Args...) { | ||
12583 | } | ||
12584 | }; | ||
12585 | |||
12586 | template <typename T, bool checked, bool clean_stack> | ||
12587 | struct constructor_match { | ||
12588 | T* obj; | ||
12589 | |||
12590 | constructor_match(T* o) | ||
12591 | : obj(o) { | ||
12592 | } | ||
12593 | |||
12594 | template <typename Fx, std::size_t I, typename... R, typename... Args> | ||
12595 | int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const { | ||
12596 | detail::default_construct func{}; | ||
12597 | return stack::call_into_lua<checked, clean_stack>(r, a, L, start, func, obj); | ||
12598 | } | ||
12599 | }; | ||
12600 | |||
12601 | namespace overload_detail { | ||
12602 | template <std::size_t... M, typename Match, typename... Args> | ||
12603 | inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) { | ||
12604 | return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types"); | ||
12605 | } | ||
12606 | |||
12607 | template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args> | ||
12608 | inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { | ||
12609 | typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits; | ||
12610 | typedef meta::tuple_types<typename traits::return_type> return_types; | ||
12611 | typedef typename traits::free_args_list args_list; | ||
12612 | // compile-time eliminate any functions that we know ahead of time are of improper arity | ||
12613 | if (!traits::runtime_variadics_t::value && meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { | ||
12614 | return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12615 | } | ||
12616 | if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { | ||
12617 | return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12618 | } | ||
12619 | stack::record tracking{}; | ||
12620 | if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) { | ||
12621 | return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12622 | } | ||
12623 | return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); | ||
12624 | } | ||
12625 | |||
12626 | template <std::size_t... M, typename Match, typename... Args> | ||
12627 | inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { | ||
12628 | return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12629 | } | ||
12630 | |||
12631 | template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args> | ||
12632 | inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { | ||
12633 | typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits; | ||
12634 | typedef meta::tuple_types<typename traits::return_type> return_types; | ||
12635 | typedef typename traits::free_args_list args_list; | ||
12636 | // compile-time eliminate any functions that we know ahead of time are of improper arity | ||
12637 | if (!traits::runtime_variadics_t::value && meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { | ||
12638 | return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12639 | } | ||
12640 | if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { | ||
12641 | return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12642 | } | ||
12643 | return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); | ||
12644 | } | ||
12645 | |||
12646 | 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, typename... Args> | ||
12647 | inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { | ||
12648 | typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits; | ||
12649 | typedef meta::tuple_types<typename traits::return_type> return_types; | ||
12650 | typedef typename traits::free_args_list args_list; | ||
12651 | // compile-time eliminate any functions that we know ahead of time are of improper arity | ||
12652 | if (!traits::runtime_variadics_t::value && meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { | ||
12653 | return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12654 | } | ||
12655 | if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { | ||
12656 | return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12657 | } | ||
12658 | stack::record tracking{}; | ||
12659 | if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) { | ||
12660 | return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12661 | } | ||
12662 | return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); | ||
12663 | } | ||
12664 | } // namespace overload_detail | ||
12665 | |||
12666 | template <typename... Functions, typename Match, typename... Args> | ||
12667 | inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { | ||
12668 | return overload_detail::overload_match_arity_single(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12669 | } | ||
12670 | |||
12671 | template <typename... Functions, typename Match, typename... Args> | ||
12672 | inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) { | ||
12673 | int fxarity = lua_gettop(L) - (start - 1); | ||
12674 | return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12675 | } | ||
12676 | |||
12677 | template <typename T, typename... TypeLists, typename Match, typename... Args> | ||
12678 | inline int construct_match(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { | ||
12679 | // use same overload resolution matching as all other parts of the framework | ||
12680 | return overload_match_arity<decltype(void_call<T, TypeLists>::call)...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); | ||
12681 | } | ||
12682 | |||
12683 | template <typename T, bool checked, bool clean_stack, typename... TypeLists> | ||
12684 | inline int construct(lua_State* L) { | ||
12685 | static const auto& meta = usertype_traits<T>::metatable(); | ||
12686 | int argcount = lua_gettop(L); | ||
12687 | call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot; | ||
12688 | argcount -= static_cast<int>(syntax); | ||
12689 | |||
12690 | T* obj = detail::usertype_allocate<T>(L); | ||
12691 | reference userdataref(L, -1); | ||
12692 | userdataref.pop(); | ||
12693 | |||
12694 | construct_match<T, TypeLists...>(constructor_match<T, checked, clean_stack>(obj), L, argcount, 1 + static_cast<int>(syntax)); | ||
12695 | |||
12696 | userdataref.push(); | ||
12697 | stack::stack_detail::undefined_metatable<T> umf(L, &meta[0]); | ||
12698 | umf(); | ||
12699 | |||
12700 | return 1; | ||
12701 | } | ||
12702 | |||
12703 | template <typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename = void> | ||
12704 | struct agnostic_lua_call_wrapper { | ||
12705 | typedef wrapper<meta::unqualified_t<F>> wrap; | ||
12706 | |||
12707 | template <typename Fx, typename... Args> | ||
12708 | static int convertible_call(std::true_type, lua_State* L, Fx&& f, Args&&... args) { | ||
12709 | typedef typename wrap::traits_type traits_type; | ||
12710 | typedef typename traits_type::function_pointer_type fp_t; | ||
12711 | fp_t fx = f; | ||
12712 | return agnostic_lua_call_wrapper<fp_t, is_index, is_variable, checked, boost, clean_stack>{}.call(L, fx, std::forward<Args>(args)...); | ||
12713 | } | ||
12714 | |||
12715 | template <typename Fx, typename... Args> | ||
12716 | static int convertible_call(std::false_type, lua_State* L, Fx&& f, Args&&... args) { | ||
12717 | typedef typename wrap::returns_list returns_list; | ||
12718 | typedef typename wrap::free_args_list args_list; | ||
12719 | typedef typename wrap::caller caller; | ||
12720 | return stack::call_into_lua<checked, clean_stack>(returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f), std::forward<Args>(args)...); | ||
12721 | } | ||
12722 | |||
12723 | template <typename Fx, typename... Args> | ||
12724 | static int call(lua_State* L, Fx&& f, Args&&... args) { | ||
12725 | typedef typename wrap::traits_type traits_type; | ||
12726 | typedef typename traits_type::function_pointer_type fp_t; | ||
12727 | return convertible_call(std::conditional_t<std::is_class<meta::unqualified_t<F>>::value, std::is_convertible<std::decay_t<Fx>, fp_t>, std::false_type>(), L, std::forward<Fx>(f), std::forward<Args>(args)...); | ||
12728 | } | ||
12729 | }; | ||
12730 | |||
12731 | template <typename T, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12732 | struct agnostic_lua_call_wrapper<var_wrapper<T>, true, is_variable, checked, boost, clean_stack, C> { | ||
12733 | template <typename F> | ||
12734 | static int call(lua_State* L, F&& f) { | ||
12735 | typedef is_stack_based<meta::unqualified_t<decltype(detail::unwrap(f.value))>> is_stack; | ||
12736 | if (clean_stack && !is_stack::value) { | ||
12737 | lua_settop(L, 0); | ||
12738 | } | ||
12739 | return stack::push_reference(L, detail::unwrap(f.value)); | ||
12740 | } | ||
12741 | }; | ||
12742 | |||
12743 | template <typename T, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12744 | struct agnostic_lua_call_wrapper<var_wrapper<T>, false, is_variable, checked, boost, clean_stack, C> { | ||
12745 | template <typename V> | ||
12746 | static int call_assign(std::true_type, lua_State* L, V&& f) { | ||
12747 | detail::unwrap(f.value) = stack::get<meta::unwrapped_t<T>>(L, boost + (is_variable ? 3 : 1)); | ||
12748 | if (clean_stack) { | ||
12749 | lua_settop(L, 0); | ||
12750 | } | ||
12751 | return 0; | ||
12752 | } | ||
12753 | |||
12754 | template <typename... Args> | ||
12755 | static int call_assign(std::false_type, lua_State* L, Args&&...) { | ||
12756 | return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); | ||
12757 | } | ||
12758 | |||
12759 | template <typename... Args> | ||
12760 | static int call_const(std::false_type, lua_State* L, Args&&... args) { | ||
12761 | typedef meta::unwrapped_t<T> R; | ||
12762 | return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, std::forward<Args>(args)...); | ||
12763 | } | ||
12764 | |||
12765 | template <typename... Args> | ||
12766 | static int call_const(std::true_type, lua_State* L, Args&&...) { | ||
12767 | return luaL_error(L, "sol: cannot write to a readonly (const) variable"); | ||
12768 | } | ||
12769 | |||
12770 | template <typename V> | ||
12771 | static int call(lua_State* L, V&& f) { | ||
12772 | return call_const(std::is_const<meta::unwrapped_t<T>>(), L, f); | ||
12773 | } | ||
12774 | }; | ||
12775 | |||
12776 | template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12777 | struct agnostic_lua_call_wrapper<lua_CFunction_ref, is_index, is_variable, checked, boost, clean_stack, C> { | ||
12778 | static int call(lua_State* L, lua_CFunction_ref f) { | ||
12779 | return f(L); | ||
12780 | } | ||
12781 | }; | ||
12782 | |||
12783 | template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12784 | struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, boost, clean_stack, C> { | ||
12785 | static int call(lua_State* L, lua_CFunction f) { | ||
12786 | return f(L); | ||
12787 | } | ||
12788 | }; | ||
12789 | |||
12790 | #if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE | ||
12791 | template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12792 | struct agnostic_lua_call_wrapper<detail::lua_CFunction_noexcept, is_index, is_variable, checked, boost, clean_stack, C> { | ||
12793 | static int call(lua_State* L, detail::lua_CFunction_noexcept f) { | ||
12794 | return f(L); | ||
12795 | } | ||
12796 | }; | ||
12797 | #endif // noexcept function types | ||
12798 | |||
12799 | template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12800 | struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, checked, boost, clean_stack, C> { | ||
12801 | static int call(lua_State* L, const no_prop&) { | ||
12802 | return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); | ||
12803 | } | ||
12804 | }; | ||
12805 | |||
12806 | template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12807 | struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, boost, clean_stack, C> { | ||
12808 | static int call(lua_State* L, const no_construction&) { | ||
12809 | return function_detail::no_construction_error(L); | ||
12810 | } | ||
12811 | }; | ||
12812 | |||
12813 | template <typename... Args, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12814 | struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
12815 | static int call(lua_State*, const bases<Args...>&) { | ||
12816 | // Uh. How did you even call this, lul | ||
12817 | return 0; | ||
12818 | } | ||
12819 | }; | ||
12820 | |||
12821 | template <typename T, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12822 | struct agnostic_lua_call_wrapper<std::reference_wrapper<T>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
12823 | static int call(lua_State* L, std::reference_wrapper<T> f) { | ||
12824 | return agnostic_lua_call_wrapper<T, is_index, is_variable, checked, boost, clean_stack>{}.call(L, f.get()); | ||
12825 | } | ||
12826 | }; | ||
12827 | |||
12828 | template <typename T, typename F, bool is_index, bool is_variable, bool checked = detail::default_safe_function_calls, int boost = 0, bool clean_stack = true, typename = void> | ||
12829 | struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost, clean_stack> {}; | ||
12830 | |||
12831 | template <typename T, typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack> | ||
12832 | struct lua_call_wrapper<T, F, is_index, is_variable, checked, boost, clean_stack, std::enable_if_t<std::is_member_function_pointer<F>::value>> { | ||
12833 | typedef wrapper<meta::unqualified_t<F>> wrap; | ||
12834 | typedef typename wrap::object_type object_type; | ||
12835 | |||
12836 | template <typename Fx> | ||
12837 | static int call(lua_State* L, Fx&& f, object_type& o) { | ||
12838 | typedef typename wrap::returns_list returns_list; | ||
12839 | typedef typename wrap::args_list args_list; | ||
12840 | typedef typename wrap::caller caller; | ||
12841 | return stack::call_into_lua<checked, clean_stack>(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(f), o); | ||
12842 | } | ||
12843 | |||
12844 | template <typename Fx> | ||
12845 | static int call(lua_State* L, Fx&& f) { | ||
12846 | typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta; | ||
12847 | #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE | ||
12848 | auto maybeo = stack::check_get<Ta*>(L, 1); | ||
12849 | if (!maybeo || maybeo.value() == nullptr) { | ||
12850 | return luaL_error(L, "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); | ||
12851 | } | ||
12852 | object_type* o = static_cast<object_type*>(maybeo.value()); | ||
12853 | return call(L, std::forward<Fx>(f), *o); | ||
12854 | #else | ||
12855 | object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); | ||
12856 | return call(L, std::forward<Fx>(f), o); | ||
12857 | #endif // Safety | ||
12858 | } | ||
12859 | }; | ||
12860 | |||
12861 | template <typename T, typename F, bool is_variable, bool checked, int boost, bool clean_stack> | ||
12862 | struct lua_call_wrapper<T, F, false, is_variable, checked, boost, clean_stack, std::enable_if_t<std::is_member_object_pointer<F>::value>> { | ||
12863 | typedef lua_bind_traits<F> traits_type; | ||
12864 | typedef wrapper<meta::unqualified_t<F>> wrap; | ||
12865 | typedef typename wrap::object_type object_type; | ||
12866 | |||
12867 | template <typename V> | ||
12868 | static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) { | ||
12869 | typedef typename wrap::args_list args_list; | ||
12870 | typedef typename wrap::caller caller; | ||
12871 | return stack::call_into_lua<checked, clean_stack>(types<void>(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, o); | ||
12872 | } | ||
12873 | |||
12874 | template <typename V> | ||
12875 | static int call_assign(std::true_type, lua_State* L, V&& f) { | ||
12876 | typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta; | ||
12877 | #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE | ||
12878 | auto maybeo = stack::check_get<Ta*>(L, 1); | ||
12879 | if (!maybeo || maybeo.value() == nullptr) { | ||
12880 | if (is_variable) { | ||
12881 | return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); | ||
12882 | } | ||
12883 | return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); | ||
12884 | } | ||
12885 | object_type* o = static_cast<object_type*>(maybeo.value()); | ||
12886 | return call_assign(std::true_type(), L, f, *o); | ||
12887 | #else | ||
12888 | object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); | ||
12889 | return call_assign(std::true_type(), L, f, o); | ||
12890 | #endif // Safety | ||
12891 | } | ||
12892 | |||
12893 | template <typename... Args> | ||
12894 | static int call_assign(std::false_type, lua_State* L, Args&&...) { | ||
12895 | return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); | ||
12896 | } | ||
12897 | |||
12898 | template <typename... Args> | ||
12899 | static int call_const(std::false_type, lua_State* L, Args&&... args) { | ||
12900 | typedef typename traits_type::return_type R; | ||
12901 | return call_assign(std::is_copy_assignable<meta::unqualified_t<R>>(), L, std::forward<Args>(args)...); | ||
12902 | } | ||
12903 | |||
12904 | template <typename... Args> | ||
12905 | static int call_const(std::true_type, lua_State* L, Args&&...) { | ||
12906 | return luaL_error(L, "sol: cannot write to a readonly (const) variable"); | ||
12907 | } | ||
12908 | |||
12909 | template <typename V> | ||
12910 | static int call(lua_State* L, V&& f) { | ||
12911 | return call_const(std::is_const<typename traits_type::return_type>(), L, std::forward<V>(f)); | ||
12912 | } | ||
12913 | |||
12914 | template <typename V> | ||
12915 | static int call(lua_State* L, V&& f, object_type& o) { | ||
12916 | return call_const(std::is_const<typename traits_type::return_type>(), L, std::forward<V>(f), o); | ||
12917 | } | ||
12918 | }; | ||
12919 | |||
12920 | template <typename T, typename F, bool is_variable, bool checked, int boost, bool clean_stack> | ||
12921 | struct lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, std::enable_if_t<std::is_member_object_pointer<F>::value>> { | ||
12922 | typedef lua_bind_traits<F> traits_type; | ||
12923 | typedef wrapper<meta::unqualified_t<F>> wrap; | ||
12924 | typedef typename wrap::object_type object_type; | ||
12925 | |||
12926 | template <typename V> | ||
12927 | static int call(lua_State* L, V&& v, object_type& o) { | ||
12928 | typedef typename wrap::returns_list returns_list; | ||
12929 | typedef typename wrap::caller caller; | ||
12930 | F f(std::forward<V>(v)); | ||
12931 | return stack::call_into_lua<checked, clean_stack>(returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), f, o); | ||
12932 | } | ||
12933 | |||
12934 | template <typename V> | ||
12935 | static int call(lua_State* L, V&& f) { | ||
12936 | typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta; | ||
12937 | #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE | ||
12938 | auto maybeo = stack::check_get<Ta*>(L, 1); | ||
12939 | if (!maybeo || maybeo.value() == nullptr) { | ||
12940 | if (is_variable) { | ||
12941 | return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); | ||
12942 | } | ||
12943 | return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); | ||
12944 | } | ||
12945 | object_type* o = static_cast<object_type*>(maybeo.value()); | ||
12946 | return call(L, f, *o); | ||
12947 | #else | ||
12948 | object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); | ||
12949 | return call(L, f, o); | ||
12950 | #endif // Safety | ||
12951 | } | ||
12952 | }; | ||
12953 | |||
12954 | template <typename T, typename F, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12955 | struct lua_call_wrapper<T, readonly_wrapper<F>, false, is_variable, checked, boost, clean_stack, C> { | ||
12956 | typedef lua_bind_traits<F> traits_type; | ||
12957 | typedef wrapper<meta::unqualified_t<F>> wrap; | ||
12958 | typedef typename wrap::object_type object_type; | ||
12959 | |||
12960 | template <typename V> | ||
12961 | static int call(lua_State* L, V&&) { | ||
12962 | return luaL_error(L, "sol: cannot write to a sol::readonly variable"); | ||
12963 | } | ||
12964 | |||
12965 | template <typename V> | ||
12966 | static int call(lua_State* L, V&&, object_type&) { | ||
12967 | return luaL_error(L, "sol: cannot write to a sol::readonly variable"); | ||
12968 | } | ||
12969 | }; | ||
12970 | |||
12971 | template <typename T, typename F, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12972 | struct lua_call_wrapper<T, readonly_wrapper<F>, true, is_variable, checked, boost, clean_stack, C> : lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> { | ||
12973 | }; | ||
12974 | |||
12975 | template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12976 | struct lua_call_wrapper<T, constructor_list<Args...>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
12977 | typedef constructor_list<Args...> F; | ||
12978 | |||
12979 | static int call(lua_State* L, F&) { | ||
12980 | const auto& meta = usertype_traits<T>::metatable(); | ||
12981 | int argcount = lua_gettop(L); | ||
12982 | call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot; | ||
12983 | argcount -= static_cast<int>(syntax); | ||
12984 | |||
12985 | T* obj = detail::usertype_allocate<T>(L); | ||
12986 | reference userdataref(L, -1); | ||
12987 | |||
12988 | construct_match<T, Args...>(constructor_match<T, false, clean_stack>(obj), L, argcount, boost + 1 + static_cast<int>(syntax)); | ||
12989 | |||
12990 | userdataref.push(); | ||
12991 | stack::stack_detail::undefined_metatable<T> umf(L, &meta[0]); | ||
12992 | umf(); | ||
12993 | |||
12994 | return 1; | ||
12995 | } | ||
12996 | }; | ||
12997 | |||
12998 | template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
12999 | struct lua_call_wrapper<T, constructor_wrapper<Cxs...>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
13000 | typedef constructor_wrapper<Cxs...> F; | ||
13001 | |||
13002 | struct onmatch { | ||
13003 | template <typename Fx, std::size_t I, typename... R, typename... Args> | ||
13004 | int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) { | ||
13005 | const auto& meta = usertype_traits<T>::metatable(); | ||
13006 | T* obj = detail::usertype_allocate<T>(L); | ||
13007 | reference userdataref(L, -1); | ||
13008 | |||
13009 | auto& func = std::get<I>(f.functions); | ||
13010 | stack::call_into_lua<checked, clean_stack>(r, a, L, boost + start, func, detail::implicit_wrapper<T>(obj)); | ||
13011 | |||
13012 | userdataref.push(); | ||
13013 | stack::stack_detail::undefined_metatable<T> umf(L, &meta[0]); | ||
13014 | umf(); | ||
13015 | |||
13016 | return 1; | ||
13017 | } | ||
13018 | }; | ||
13019 | |||
13020 | static int call(lua_State* L, F& f) { | ||
13021 | call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1); | ||
13022 | int syntaxval = static_cast<int>(syntax); | ||
13023 | int argcount = lua_gettop(L) - syntaxval; | ||
13024 | return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f); | ||
13025 | } | ||
13026 | }; | ||
13027 | |||
13028 | template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack> | ||
13029 | struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, clean_stack, std::enable_if_t<std::is_void<Fx>::value>> { | ||
13030 | typedef destructor_wrapper<Fx> F; | ||
13031 | |||
13032 | static int call(lua_State* L, const F&) { | ||
13033 | return detail::usertype_alloc_destruct<T>(L); | ||
13034 | } | ||
13035 | }; | ||
13036 | |||
13037 | template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack> | ||
13038 | struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, clean_stack, std::enable_if_t<!std::is_void<Fx>::value>> { | ||
13039 | typedef destructor_wrapper<Fx> F; | ||
13040 | |||
13041 | static int call_void(std::true_type, lua_State* L, const F& f) { | ||
13042 | typedef meta::bind_traits<meta::unqualified_t<decltype(f.fx)>> bt; | ||
13043 | typedef typename bt::template arg_at<0> arg0; | ||
13044 | typedef meta::unqualified_t<arg0> O; | ||
13045 | |||
13046 | O& obj = stack::get<O>(L); | ||
13047 | f.fx(detail::implicit_wrapper<O>(obj)); | ||
13048 | return 0; | ||
13049 | } | ||
13050 | |||
13051 | static int call_void(std::false_type, lua_State* L, const F& f) { | ||
13052 | T& obj = stack::get<T>(L); | ||
13053 | f.fx(detail::implicit_wrapper<T>(obj)); | ||
13054 | return 0; | ||
13055 | } | ||
13056 | |||
13057 | static int call(lua_State* L, const F& f) { | ||
13058 | return call_void(std::is_void<T>(), L, f); | ||
13059 | } | ||
13060 | }; | ||
13061 | |||
13062 | template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
13063 | struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
13064 | typedef overload_set<Fs...> F; | ||
13065 | |||
13066 | struct on_match { | ||
13067 | template <typename Fx, std::size_t I, typename... R, typename... Args> | ||
13068 | int operator()(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) { | ||
13069 | auto& f = std::get<I>(fx.functions); | ||
13070 | return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost>{}.call(L, f); | ||
13071 | } | ||
13072 | }; | ||
13073 | |||
13074 | static int call(lua_State* L, F& fx) { | ||
13075 | return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx); | ||
13076 | } | ||
13077 | }; | ||
13078 | |||
13079 | template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
13080 | struct lua_call_wrapper<T, factory_wrapper<Fs...>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
13081 | typedef factory_wrapper<Fs...> F; | ||
13082 | |||
13083 | struct on_match { | ||
13084 | template <typename Fx, std::size_t I, typename... R, typename... Args> | ||
13085 | int operator()(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) { | ||
13086 | auto& f = std::get<I>(fx.functions); | ||
13087 | return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost, clean_stack>{}.call(L, f); | ||
13088 | } | ||
13089 | }; | ||
13090 | |||
13091 | static int call(lua_State* L, F& fx) { | ||
13092 | return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx); | ||
13093 | } | ||
13094 | }; | ||
13095 | |||
13096 | template <typename T, typename R, typename W, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
13097 | struct lua_call_wrapper<T, property_wrapper<R, W>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
13098 | typedef std::conditional_t<is_index, R, W> P; | ||
13099 | typedef meta::unqualified_t<P> U; | ||
13100 | typedef wrapper<U> wrap; | ||
13101 | typedef lua_bind_traits<U> traits_type; | ||
13102 | typedef meta::unqualified_t<typename traits_type::template arg_at<0>> object_type; | ||
13103 | |||
13104 | template <typename F> | ||
13105 | static int self_call(std::true_type, lua_State* L, F&& f) { | ||
13106 | // The type being void means we don't have any arguments, so it might be a free functions? | ||
13107 | typedef typename traits_type::free_args_list args_list; | ||
13108 | typedef typename wrap::returns_list returns_list; | ||
13109 | typedef typename wrap::caller caller; | ||
13110 | return stack::call_into_lua<checked, clean_stack>(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f); | ||
13111 | } | ||
13112 | |||
13113 | template <typename F> | ||
13114 | static int self_call(std::false_type, lua_State* L, F&& f) { | ||
13115 | typedef meta::pop_front_type_t<typename traits_type::free_args_list> args_list; | ||
13116 | typedef T Ta; | ||
13117 | typedef std::remove_pointer_t<object_type> Oa; | ||
13118 | #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE | ||
13119 | auto maybeo = stack::check_get<Ta*>(L, 1); | ||
13120 | if (!maybeo || maybeo.value() == nullptr) { | ||
13121 | if (is_variable) { | ||
13122 | return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); | ||
13123 | } | ||
13124 | return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); | ||
13125 | } | ||
13126 | Oa* o = static_cast<Oa*>(maybeo.value()); | ||
13127 | #else | ||
13128 | Oa* o = static_cast<Oa*>(stack::get<non_null<Ta*>>(L, 1)); | ||
13129 | #endif // Safety | ||
13130 | typedef typename wrap::returns_list returns_list; | ||
13131 | typedef typename wrap::caller caller; | ||
13132 | return stack::call_into_lua<checked, clean_stack>(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, detail::implicit_wrapper<Oa>(*o)); | ||
13133 | } | ||
13134 | |||
13135 | template <typename F, typename... Args> | ||
13136 | static int defer_call(std::false_type, lua_State* L, F&& f, Args&&... args) { | ||
13137 | return self_call(meta::any<std::is_void<object_type>, meta::boolean<lua_type_of<meta::unwrap_unqualified_t<object_type>>::value != type::userdata>>(), L, pick(meta::boolean<is_index>(), f), std::forward<Args>(args)...); | ||
13138 | } | ||
13139 | |||
13140 | template <typename F, typename... Args> | ||
13141 | static int defer_call(std::true_type, lua_State* L, F&& f, Args&&... args) { | ||
13142 | auto& p = pick(meta::boolean<is_index>(), std::forward<F>(f)); | ||
13143 | return lua_call_wrapper<T, meta::unqualified_t<decltype(p)>, is_index, is_variable, checked, boost, clean_stack>{}.call(L, p, std::forward<Args>(args)...); | ||
13144 | } | ||
13145 | |||
13146 | template <typename F, typename... Args> | ||
13147 | static int call(lua_State* L, F&& f, Args&&... args) { | ||
13148 | typedef meta::any< | ||
13149 | std::is_void<U>, | ||
13150 | std::is_same<U, no_prop>, | ||
13151 | meta::is_specialization_of<U, var_wrapper>, | ||
13152 | meta::is_specialization_of<U, constructor_wrapper>, | ||
13153 | meta::is_specialization_of<U, constructor_list>, | ||
13154 | std::is_member_pointer<U>> | ||
13155 | is_specialized; | ||
13156 | return defer_call(is_specialized(), L, std::forward<F>(f), std::forward<Args>(args)...); | ||
13157 | } | ||
13158 | }; | ||
13159 | |||
13160 | template <typename T, typename V, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
13161 | struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
13162 | typedef protect_t<V> F; | ||
13163 | |||
13164 | template <typename... Args> | ||
13165 | static int call(lua_State* L, F& fx, Args&&... args) { | ||
13166 | return lua_call_wrapper<T, V, is_index, is_variable, true, boost, clean_stack>{}.call(L, fx.value, std::forward<Args>(args)...); | ||
13167 | } | ||
13168 | }; | ||
13169 | |||
13170 | template <typename T, typename F, typename... Filters, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
13171 | struct lua_call_wrapper<T, filter_wrapper<F, Filters...>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
13172 | typedef filter_wrapper<F, Filters...> P; | ||
13173 | |||
13174 | template <std::size_t... In> | ||
13175 | static int call(std::index_sequence<In...>, lua_State* L, P& fx) { | ||
13176 | int pushed = lua_call_wrapper<T, F, is_index, is_variable, checked, boost, false, C>{}.call(L, fx.value); | ||
13177 | (void)detail::swallow{ int(), (filter_detail::handle_filter(std::get<In>(fx.filters), L, pushed), int())... }; | ||
13178 | return pushed; | ||
13179 | } | ||
13180 | |||
13181 | static int call(lua_State* L, P& fx) { | ||
13182 | typedef typename P::indices indices; | ||
13183 | return call(indices(), L, fx); | ||
13184 | } | ||
13185 | }; | ||
13186 | |||
13187 | template <typename T, typename Sig, typename P, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> | ||
13188 | struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, clean_stack, C> { | ||
13189 | template <typename F> | ||
13190 | static int call(lua_State* L, F&& f) { | ||
13191 | return lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack>{}.call(L, std::get<0>(f.arguments)); | ||
13192 | } | ||
13193 | }; | ||
13194 | |||
13195 | template <typename T, bool is_index, bool is_variable, int boost = 0, bool checked = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... Args> | ||
13196 | inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { | ||
13197 | return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable, checked, boost, clean_stack>{}.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...); | ||
13198 | } | ||
13199 | |||
13200 | template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls, bool clean_stack = true> | ||
13201 | inline int call_user(lua_State* L) { | ||
13202 | auto& fx = stack::get<user<F>>(L, upvalue_index(start)); | ||
13203 | return call_wrapped<T, is_index, is_variable, 0, checked, clean_stack>(L, fx); | ||
13204 | } | ||
13205 | |||
13206 | template <typename T, typename = void> | ||
13207 | struct is_var_bind : std::false_type {}; | ||
13208 | |||
13209 | template <typename T> | ||
13210 | struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type {}; | ||
13211 | |||
13212 | template <> | ||
13213 | struct is_var_bind<no_prop> : std::true_type {}; | ||
13214 | |||
13215 | template <typename R, typename W> | ||
13216 | struct is_var_bind<property_wrapper<R, W>> : std::true_type {}; | ||
13217 | |||
13218 | template <typename T> | ||
13219 | struct is_var_bind<var_wrapper<T>> : std::true_type {}; | ||
13220 | |||
13221 | template <typename T> | ||
13222 | struct is_var_bind<readonly_wrapper<T>> : is_var_bind<meta::unqualified_t<T>> {}; | ||
13223 | |||
13224 | template <typename F, typename... Filters> | ||
13225 | struct is_var_bind<filter_wrapper<F, Filters...>> : is_var_bind<meta::unqualified_t<F>> {}; | ||
13226 | } // namespace call_detail | ||
13227 | |||
13228 | template <typename T> | ||
13229 | struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> {}; | ||
13230 | |||
13231 | template <typename T> | ||
13232 | struct is_function_binding : meta::neg<is_variable_binding<T>> {}; | ||
13233 | |||
13234 | } // namespace sol | ||
13235 | |||
13236 | // end of sol/call.hpp | ||
13237 | |||
13238 | namespace sol { | ||
13239 | namespace function_detail { | ||
13240 | template <typename F, F fx> | ||
13241 | inline int call_wrapper_variable(std::false_type, lua_State* L) { | ||
13242 | typedef meta::bind_traits<meta::unqualified_t<F>> traits_type; | ||
13243 | typedef typename traits_type::args_list args_list; | ||
13244 | typedef meta::tuple_types<typename traits_type::return_type> return_type; | ||
13245 | return stack::call_into_lua(return_type(), args_list(), L, 1, fx); | ||
13246 | } | ||
13247 | |||
13248 | template <typename R, typename V, V, typename T> | ||
13249 | inline int call_set_assignable(std::false_type, T&&, lua_State* L) { | ||
13250 | return luaL_error(L, "cannot write to this type: copy assignment/constructor not available"); | ||
13251 | } | ||
13252 | |||
13253 | template <typename R, typename V, V variable, typename T> | ||
13254 | inline int call_set_assignable(std::true_type, lua_State* L, T&& mem) { | ||
13255 | (mem.*variable) = stack::get<R>(L, 2); | ||
13256 | return 0; | ||
13257 | } | ||
13258 | |||
13259 | template <typename R, typename V, V, typename T> | ||
13260 | inline int call_set_variable(std::false_type, lua_State* L, T&&) { | ||
13261 | return luaL_error(L, "cannot write to a const variable"); | ||
13262 | } | ||
13263 | |||
13264 | template <typename R, typename V, V variable, typename T> | ||
13265 | inline int call_set_variable(std::true_type, lua_State* L, T&& mem) { | ||
13266 | return call_set_assignable<R, V, variable>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, std::forward<T>(mem)); | ||
13267 | } | ||
13268 | |||
13269 | template <typename V, V variable> | ||
13270 | inline int call_wrapper_variable(std::true_type, lua_State* L) { | ||
13271 | typedef meta::bind_traits<meta::unqualified_t<V>> traits_type; | ||
13272 | typedef typename traits_type::object_type T; | ||
13273 | typedef typename traits_type::return_type R; | ||
13274 | auto& mem = stack::get<T>(L, 1); | ||
13275 | switch (lua_gettop(L)) { | ||
13276 | case 1: { | ||
13277 | decltype(auto) r = (mem.*variable); | ||
13278 | stack::push_reference(L, std::forward<decltype(r)>(r)); | ||
13279 | return 1; | ||
13280 | } | ||
13281 | case 2: | ||
13282 | return call_set_variable<R, V, variable>(meta::neg<std::is_const<R>>(), L, mem); | ||
13283 | default: | ||
13284 | return luaL_error(L, "incorrect number of arguments to member variable function call"); | ||
13285 | } | ||
13286 | } | ||
13287 | |||
13288 | template <typename F, F fx> | ||
13289 | inline int call_wrapper_function(std::false_type, lua_State* L) { | ||
13290 | return call_wrapper_variable<F, fx>(std::is_member_object_pointer<F>(), L); | ||
13291 | } | ||
13292 | |||
13293 | template <typename F, F fx> | ||
13294 | inline int call_wrapper_function(std::true_type, lua_State* L) { | ||
13295 | return call_detail::call_wrapped<void, false, false>(L, fx); | ||
13296 | } | ||
13297 | |||
13298 | template <typename F, F fx> | ||
13299 | int call_wrapper_entry(lua_State* L) noexcept(meta::bind_traits<F>::is_noexcept) { | ||
13300 | return call_wrapper_function<F, fx>(std::is_member_function_pointer<meta::unqualified_t<F>>(), L); | ||
13301 | } | ||
13302 | |||
13303 | template <typename... Fxs> | ||
13304 | struct c_call_matcher { | ||
13305 | template <typename Fx, std::size_t I, typename R, typename... Args> | ||
13306 | int operator()(types<Fx>, index_value<I>, types<R>, types<Args...>, lua_State* L, int, int) const { | ||
13307 | typedef meta::at_in_pack_t<I, Fxs...> target; | ||
13308 | return target::call(L); | ||
13309 | } | ||
13310 | }; | ||
13311 | |||
13312 | template <typename F, F fx> | ||
13313 | inline int c_call_raw(std::true_type, lua_State* L) { | ||
13314 | return fx(L); | ||
13315 | } | ||
13316 | |||
13317 | template <typename F, F fx> | ||
13318 | inline int c_call_raw(std::false_type, lua_State* L) { | ||
13319 | #ifdef __clang__ | ||
13320 | return detail::trampoline(L, function_detail::call_wrapper_entry<F, fx>); | ||
13321 | #else | ||
13322 | return detail::typed_static_trampoline<decltype(&function_detail::call_wrapper_entry<F, fx>), (&function_detail::call_wrapper_entry<F, fx>)>(L); | ||
13323 | #endif // fuck you clang :c | ||
13324 | } | ||
13325 | |||
13326 | } // namespace function_detail | ||
13327 | |||
13328 | template <typename F, F fx> | ||
13329 | inline int c_call(lua_State* L) { | ||
13330 | typedef meta::unqualified_t<F> Fu; | ||
13331 | typedef std::integral_constant<bool, std::is_same<Fu, lua_CFunction>::value | ||
13332 | #if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE | ||
13333 | || std::is_same<Fu, detail::lua_CFunction_noexcept>::value | ||
13334 | #endif | ||
13335 | > is_raw; | ||
13336 | return function_detail::c_call_raw<F, fx>(is_raw(), L); | ||
13337 | } | ||
13338 | |||
13339 | template <typename F, F f> | ||
13340 | struct wrap { | ||
13341 | typedef F type; | ||
13342 | |||
13343 | static int call(lua_State* L) { | ||
13344 | return c_call<type, f>(L); | ||
13345 | } | ||
13346 | }; | ||
13347 | |||
13348 | template <typename... Fxs> | ||
13349 | inline int c_call(lua_State* L) { | ||
13350 | if (sizeof...(Fxs) < 2) { | ||
13351 | return meta::at_in_pack_t<0, Fxs...>::call(L); | ||
13352 | } | ||
13353 | else { | ||
13354 | return call_detail::overload_match_arity<typename Fxs::type...>(function_detail::c_call_matcher<Fxs...>(), L, lua_gettop(L), 1); | ||
13355 | } | ||
13356 | } | ||
13357 | |||
13358 | } // namespace sol | ||
13359 | |||
13360 | // end of sol/function_types_templated.hpp | ||
13361 | |||
13362 | // beginning of sol/function_types_stateless.hpp | ||
13363 | |||
13364 | namespace sol { | ||
13365 | namespace function_detail { | ||
13366 | template <typename Function, bool is_yielding> | ||
13367 | struct upvalue_free_function { | ||
13368 | typedef std::remove_pointer_t<std::decay_t<Function>> function_type; | ||
13369 | typedef meta::bind_traits<function_type> traits_type; | ||
13370 | |||
13371 | static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { | ||
13372 | auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L); | ||
13373 | function_type* fx = udata.first; | ||
13374 | return call_detail::call_wrapped<void, true, false>(L, fx); | ||
13375 | } | ||
13376 | |||
13377 | static int call(lua_State* L) { | ||
13378 | int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); | ||
13379 | if (is_yielding) { | ||
13380 | return lua_yield(L, nr); | ||
13381 | } | ||
13382 | else { | ||
13383 | return nr; | ||
13384 | } | ||
13385 | } | ||
13386 | |||
13387 | int operator()(lua_State* L) { | ||
13388 | return call(L); | ||
13389 | } | ||
13390 | }; | ||
13391 | |||
13392 | template <typename T, typename Function, bool is_yielding> | ||
13393 | struct upvalue_member_function { | ||
13394 | typedef std::remove_pointer_t<std::decay_t<Function>> function_type; | ||
13395 | typedef lua_bind_traits<function_type> traits_type; | ||
13396 | |||
13397 | static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { | ||
13398 | // Layout: | ||
13399 | // idx 1...n: verbatim data of member function pointer | ||
13400 | // idx n + 1: is the object's void pointer | ||
13401 | // We don't need to store the size, because the other side is templated | ||
13402 | // with the same member function pointer type | ||
13403 | auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); | ||
13404 | auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second); | ||
13405 | function_type& memfx = memberdata.first; | ||
13406 | auto& item = *objdata.first; | ||
13407 | return call_detail::call_wrapped<T, true, false, -1>(L, memfx, item); | ||
13408 | } | ||
13409 | |||
13410 | static int call(lua_State* L) { | ||
13411 | int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); | ||
13412 | if (is_yielding) { | ||
13413 | return lua_yield(L, nr); | ||
13414 | } | ||
13415 | else { | ||
13416 | return nr; | ||
13417 | } | ||
13418 | } | ||
13419 | |||
13420 | int operator()(lua_State* L) { | ||
13421 | return call(L); | ||
13422 | } | ||
13423 | }; | ||
13424 | |||
13425 | template <typename T, typename Function, bool is_yielding> | ||
13426 | struct upvalue_member_variable { | ||
13427 | typedef std::remove_pointer_t<std::decay_t<Function>> function_type; | ||
13428 | typedef lua_bind_traits<function_type> traits_type; | ||
13429 | |||
13430 | static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { | ||
13431 | // Layout: | ||
13432 | // idx 1...n: verbatim data of member variable pointer | ||
13433 | // idx n + 1: is the object's void pointer | ||
13434 | // We don't need to store the size, because the other side is templated | ||
13435 | // with the same member function pointer type | ||
13436 | auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); | ||
13437 | auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second); | ||
13438 | auto& mem = *objdata.first; | ||
13439 | function_type& var = memberdata.first; | ||
13440 | switch (lua_gettop(L)) { | ||
13441 | case 0: | ||
13442 | return call_detail::call_wrapped<T, true, false, -1>(L, var, mem); | ||
13443 | case 1: | ||
13444 | return call_detail::call_wrapped<T, false, false, -1>(L, var, mem); | ||
13445 | default: | ||
13446 | return luaL_error(L, "sol: incorrect number of arguments to member variable function"); | ||
13447 | } | ||
13448 | } | ||
13449 | |||
13450 | static int call(lua_State* L) { | ||
13451 | int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); | ||
13452 | if (is_yielding) { | ||
13453 | return lua_yield(L, nr); | ||
13454 | } | ||
13455 | else { | ||
13456 | return nr; | ||
13457 | } | ||
13458 | } | ||
13459 | |||
13460 | int operator()(lua_State* L) { | ||
13461 | return call(L); | ||
13462 | } | ||
13463 | }; | ||
13464 | |||
13465 | template <typename T, typename Function, bool is_yielding> | ||
13466 | struct upvalue_member_variable<T, readonly_wrapper<Function>, is_yielding> { | ||
13467 | typedef std::remove_pointer_t<std::decay_t<Function>> function_type; | ||
13468 | typedef lua_bind_traits<function_type> traits_type; | ||
13469 | |||
13470 | static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { | ||
13471 | // Layout: | ||
13472 | // idx 1...n: verbatim data of member variable pointer | ||
13473 | // idx n + 1: is the object's void pointer | ||
13474 | // We don't need to store the size, because the other side is templated | ||
13475 | // with the same member function pointer type | ||
13476 | auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); | ||
13477 | auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second); | ||
13478 | auto& mem = *objdata.first; | ||
13479 | function_type& var = memberdata.first; | ||
13480 | switch (lua_gettop(L)) { | ||
13481 | case 0: | ||
13482 | return call_detail::call_wrapped<T, true, false, -1>(L, var, mem); | ||
13483 | default: | ||
13484 | return luaL_error(L, "sol: incorrect number of arguments to member variable function"); | ||
13485 | } | ||
13486 | } | ||
13487 | |||
13488 | static int call(lua_State* L) { | ||
13489 | int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); | ||
13490 | if (is_yielding) { | ||
13491 | return lua_yield(L, nr); | ||
13492 | } | ||
13493 | else { | ||
13494 | return nr; | ||
13495 | } | ||
13496 | } | ||
13497 | |||
13498 | int operator()(lua_State* L) { | ||
13499 | return call(L); | ||
13500 | } | ||
13501 | }; | ||
13502 | |||
13503 | template <typename T, typename Function, bool is_yielding> | ||
13504 | struct upvalue_this_member_function { | ||
13505 | typedef std::remove_pointer_t<std::decay_t<Function>> function_type; | ||
13506 | typedef lua_bind_traits<function_type> traits_type; | ||
13507 | |||
13508 | static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { | ||
13509 | // Layout: | ||
13510 | // idx 1...n: verbatim data of member variable pointer | ||
13511 | auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); | ||
13512 | function_type& memfx = memberdata.first; | ||
13513 | return call_detail::call_wrapped<T, false, false>(L, memfx); | ||
13514 | } | ||
13515 | |||
13516 | static int call(lua_State* L) { | ||
13517 | int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); | ||
13518 | if (is_yielding) { | ||
13519 | return lua_yield(L, nr); | ||
13520 | } | ||
13521 | else { | ||
13522 | return nr; | ||
13523 | } | ||
13524 | } | ||
13525 | |||
13526 | int operator()(lua_State* L) { | ||
13527 | return call(L); | ||
13528 | } | ||
13529 | }; | ||
13530 | |||
13531 | template <typename T, typename Function, bool is_yielding> | ||
13532 | struct upvalue_this_member_variable { | ||
13533 | typedef std::remove_pointer_t<std::decay_t<Function>> function_type; | ||
13534 | |||
13535 | static int real_call(lua_State* L) noexcept(false) { | ||
13536 | // Layout: | ||
13537 | // idx 1...n: verbatim data of member variable pointer | ||
13538 | auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); | ||
13539 | function_type& var = memberdata.first; | ||
13540 | switch (lua_gettop(L)) { | ||
13541 | case 1: | ||
13542 | return call_detail::call_wrapped<T, true, false>(L, var); | ||
13543 | case 2: | ||
13544 | return call_detail::call_wrapped<T, false, false>(L, var); | ||
13545 | default: | ||
13546 | return luaL_error(L, "sol: incorrect number of arguments to member variable function"); | ||
13547 | } | ||
13548 | } | ||
13549 | |||
13550 | static int call(lua_State* L) { | ||
13551 | int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); | ||
13552 | if (is_yielding) { | ||
13553 | return lua_yield(L, nr); | ||
13554 | } | ||
13555 | else { | ||
13556 | return nr; | ||
13557 | } | ||
13558 | } | ||
13559 | |||
13560 | int operator()(lua_State* L) { | ||
13561 | return call(L); | ||
13562 | } | ||
13563 | }; | ||
13564 | |||
13565 | template <typename T, typename Function, bool is_yielding> | ||
13566 | struct upvalue_this_member_variable<T, readonly_wrapper<Function>, is_yielding> { | ||
13567 | typedef std::remove_pointer_t<std::decay_t<Function>> function_type; | ||
13568 | typedef lua_bind_traits<function_type> traits_type; | ||
13569 | |||
13570 | static int real_call(lua_State* L) noexcept(false) { | ||
13571 | // Layout: | ||
13572 | // idx 1...n: verbatim data of member variable pointer | ||
13573 | auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); | ||
13574 | function_type& var = memberdata.first; | ||
13575 | switch (lua_gettop(L)) { | ||
13576 | case 1: | ||
13577 | return call_detail::call_wrapped<T, true, false>(L, var); | ||
13578 | default: | ||
13579 | return luaL_error(L, "sol: incorrect number of arguments to member variable function"); | ||
13580 | } | ||
13581 | } | ||
13582 | |||
13583 | static int call(lua_State* L) { | ||
13584 | int nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); | ||
13585 | if (is_yielding) { | ||
13586 | return lua_yield(L, nr); | ||
13587 | } | ||
13588 | else { | ||
13589 | return nr; | ||
13590 | } | ||
13591 | } | ||
13592 | |||
13593 | int operator()(lua_State* L) { | ||
13594 | return call(L); | ||
13595 | } | ||
13596 | }; | ||
13597 | } | ||
13598 | } // namespace sol::function_detail | ||
13599 | |||
13600 | // end of sol/function_types_stateless.hpp | ||
13601 | |||
13602 | // beginning of sol/function_types_stateful.hpp | ||
13603 | |||
13604 | namespace sol { | ||
13605 | namespace function_detail { | ||
13606 | template <typename Func, bool is_yielding> | ||
13607 | struct functor_function { | ||
13608 | typedef std::decay_t<meta::unwrap_unqualified_t<Func>> function_type; | ||
13609 | function_type fx; | ||
13610 | |||
13611 | template <typename... Args> | ||
13612 | functor_function(function_type f, Args&&... args) | ||
13613 | : fx(std::move(f), std::forward<Args>(args)...) { | ||
13614 | } | ||
13615 | |||
13616 | int call(lua_State* L) { | ||
13617 | int nr = call_detail::call_wrapped<void, true, false>(L, fx); | ||
13618 | if (is_yielding) { | ||
13619 | return lua_yield(L, nr); | ||
13620 | } | ||
13621 | else { | ||
13622 | return nr; | ||
13623 | } | ||
13624 | } | ||
13625 | |||
13626 | int operator()(lua_State* L) { | ||
13627 | auto f = [&](lua_State*) -> int { return this->call(L); }; | ||
13628 | return detail::trampoline(L, f); | ||
13629 | } | ||
13630 | }; | ||
13631 | |||
13632 | template <typename T, typename Function, bool is_yielding> | ||
13633 | struct member_function { | ||
13634 | typedef std::remove_pointer_t<std::decay_t<Function>> function_type; | ||
13635 | typedef meta::function_return_t<function_type> return_type; | ||
13636 | typedef meta::function_args_t<function_type> args_lists; | ||
13637 | function_type invocation; | ||
13638 | T member; | ||
13639 | |||
13640 | template <typename... Args> | ||
13641 | member_function(function_type f, Args&&... args) | ||
13642 | : invocation(std::move(f)), member(std::forward<Args>(args)...) { | ||
13643 | } | ||
13644 | |||
13645 | int call(lua_State* L) { | ||
13646 | int nr = call_detail::call_wrapped<T, true, false, -1>(L, invocation, detail::unwrap(detail::deref(member))); | ||
13647 | if (is_yielding) { | ||
13648 | return lua_yield(L, nr); | ||
13649 | } | ||
13650 | else { | ||
13651 | return nr; | ||
13652 | } | ||
13653 | } | ||
13654 | |||
13655 | int operator()(lua_State* L) { | ||
13656 | auto f = [&](lua_State*) -> int { return this->call(L); }; | ||
13657 | return detail::trampoline(L, f); | ||
13658 | } | ||
13659 | }; | ||
13660 | |||
13661 | template <typename T, typename Function, bool is_yielding> | ||
13662 | struct member_variable { | ||
13663 | typedef std::remove_pointer_t<std::decay_t<Function>> function_type; | ||
13664 | typedef typename meta::bind_traits<function_type>::return_type return_type; | ||
13665 | typedef typename meta::bind_traits<function_type>::args_list args_lists; | ||
13666 | function_type var; | ||
13667 | T member; | ||
13668 | typedef std::add_lvalue_reference_t<meta::unwrapped_t<std::remove_reference_t<decltype(detail::deref(member))>>> M; | ||
13669 | |||
13670 | template <typename... Args> | ||
13671 | member_variable(function_type v, Args&&... args) | ||
13672 | : var(std::move(v)), member(std::forward<Args>(args)...) { | ||
13673 | } | ||
13674 | |||
13675 | int call(lua_State* L) { | ||
13676 | int nr; | ||
13677 | { | ||
13678 | M mem = detail::unwrap(detail::deref(member)); | ||
13679 | switch (lua_gettop(L)) { | ||
13680 | case 0: | ||
13681 | nr = call_detail::call_wrapped<T, true, false, -1>(L, var, mem); | ||
13682 | break; | ||
13683 | case 1: | ||
13684 | nr = call_detail::call_wrapped<T, false, false, -1>(L, var, mem); | ||
13685 | break; | ||
13686 | default: | ||
13687 | nr = luaL_error(L, "sol: incorrect number of arguments to member variable function"); | ||
13688 | break; | ||
13689 | } | ||
13690 | } | ||
13691 | if (is_yielding) { | ||
13692 | return lua_yield(L, nr); | ||
13693 | } | ||
13694 | else { | ||
13695 | return nr; | ||
13696 | } | ||
13697 | } | ||
13698 | |||
13699 | int operator()(lua_State* L) { | ||
13700 | auto f = [&](lua_State*) -> int { return this->call(L); }; | ||
13701 | return detail::trampoline(L, f); | ||
13702 | } | ||
13703 | }; | ||
13704 | } | ||
13705 | } // namespace sol::function_detail | ||
13706 | |||
13707 | // end of sol/function_types_stateful.hpp | ||
13708 | |||
13709 | // beginning of sol/function_types_overloaded.hpp | ||
13710 | |||
13711 | namespace sol { | ||
13712 | namespace function_detail { | ||
13713 | template <int start_skew = 0, typename... Functions> | ||
13714 | struct overloaded_function { | ||
13715 | typedef std::tuple<Functions...> overload_list; | ||
13716 | typedef std::make_index_sequence<sizeof...(Functions)> indices; | ||
13717 | overload_list overloads; | ||
13718 | |||
13719 | overloaded_function(overload_list set) | ||
13720 | : overloads(std::move(set)) { | ||
13721 | } | ||
13722 | |||
13723 | overloaded_function(Functions... fxs) | ||
13724 | : overloads(fxs...) { | ||
13725 | } | ||
13726 | |||
13727 | template <typename Fx, std::size_t I, typename... R, typename... Args> | ||
13728 | int call(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int) { | ||
13729 | auto& func = std::get<I>(overloads); | ||
13730 | return call_detail::call_wrapped<void, true, false, start_skew>(L, func); | ||
13731 | } | ||
13732 | |||
13733 | int operator()(lua_State* L) { | ||
13734 | auto mfx = [&](auto&&... args) { return this->call(std::forward<decltype(args)>(args)...); }; | ||
13735 | return call_detail::overload_match<Functions...>(mfx, L, 1 + start_skew); | ||
13736 | } | ||
13737 | }; | ||
13738 | } | ||
13739 | } // namespace sol::function_detail | ||
13740 | |||
13741 | // end of sol/function_types_overloaded.hpp | ||
13742 | |||
13743 | // beginning of sol/resolve.hpp | ||
13744 | |||
13745 | namespace sol { | ||
13746 | |||
13747 | #ifndef __clang__ | ||
13748 | // constexpr is fine for not-clang | ||
13749 | |||
13750 | namespace detail { | ||
13751 | template <typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>> | ||
13752 | inline constexpr auto resolve_i(types<R(Args...)>, F &&) -> R (meta::unqualified_t<F>::*)(Args...) { | ||
13753 | using Sig = R(Args...); | ||
13754 | typedef meta::unqualified_t<F> Fu; | ||
13755 | return static_cast<Sig Fu::*>(&Fu::operator()); | ||
13756 | } | ||
13757 | |||
13758 | template <typename F, typename U = meta::unqualified_t<F>> | ||
13759 | inline constexpr auto resolve_f(std::true_type, F&& f) | ||
13760 | -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { | ||
13761 | return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); | ||
13762 | } | ||
13763 | |||
13764 | template <typename F> | ||
13765 | inline constexpr void resolve_f(std::false_type, F&&) { | ||
13766 | static_assert(meta::has_deducible_signature<F>::value, | ||
13767 | "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); | ||
13768 | } | ||
13769 | |||
13770 | template <typename F, typename U = meta::unqualified_t<F>> | ||
13771 | inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) { | ||
13772 | return resolve_f(meta::has_deducible_signature<U>{}, std::forward<F>(f)); | ||
13773 | } | ||
13774 | |||
13775 | template <typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>> | ||
13776 | inline constexpr auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) { | ||
13777 | return resolve_i(types<R(Args...)>(), std::forward<F>(f)); | ||
13778 | } | ||
13779 | |||
13780 | template <typename Sig, typename C> | ||
13781 | inline constexpr Sig C::*resolve_v(std::false_type, Sig C::*mem_func_ptr) { | ||
13782 | return mem_func_ptr; | ||
13783 | } | ||
13784 | |||
13785 | template <typename Sig, typename C> | ||
13786 | inline constexpr Sig C::*resolve_v(std::true_type, Sig C::*mem_variable_ptr) { | ||
13787 | return mem_variable_ptr; | ||
13788 | } | ||
13789 | } // namespace detail | ||
13790 | |||
13791 | template <typename... Args, typename R> | ||
13792 | inline constexpr auto resolve(R fun_ptr(Args...)) -> R (*)(Args...) { | ||
13793 | return fun_ptr; | ||
13794 | } | ||
13795 | |||
13796 | template <typename Sig> | ||
13797 | inline constexpr Sig* resolve(Sig* fun_ptr) { | ||
13798 | return fun_ptr; | ||
13799 | } | ||
13800 | |||
13801 | template <typename... Args, typename R, typename C> | ||
13802 | inline constexpr auto resolve(R (C::*mem_ptr)(Args...)) -> R (C::*)(Args...) { | ||
13803 | return mem_ptr; | ||
13804 | } | ||
13805 | |||
13806 | template <typename Sig, typename C> | ||
13807 | inline constexpr Sig C::*resolve(Sig C::*mem_ptr) { | ||
13808 | return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); | ||
13809 | } | ||
13810 | |||
13811 | template <typename... Sig, typename F, meta::disable<std::is_function<meta::unqualified_t<F>>> = meta::enabler> | ||
13812 | inline constexpr auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { | ||
13813 | return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); | ||
13814 | } | ||
13815 | #else | ||
13816 | |||
13817 | // Clang has distinct problems with constexpr arguments, | ||
13818 | // so don't use the constexpr versions inside of clang. | ||
13819 | |||
13820 | namespace detail { | ||
13821 | template <typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>> | ||
13822 | inline auto resolve_i(types<R(Args...)>, F &&) -> R (meta::unqualified_t<F>::*)(Args...) { | ||
13823 | using Sig = R(Args...); | ||
13824 | typedef meta::unqualified_t<F> Fu; | ||
13825 | return static_cast<Sig Fu::*>(&Fu::operator()); | ||
13826 | } | ||
13827 | |||
13828 | template <typename F, typename U = meta::unqualified_t<F>> | ||
13829 | inline auto resolve_f(std::true_type, F&& f) | ||
13830 | -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { | ||
13831 | return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); | ||
13832 | } | ||
13833 | |||
13834 | template <typename F> | ||
13835 | inline void resolve_f(std::false_type, F&&) { | ||
13836 | static_assert(meta::has_deducible_signature<F>::value, | ||
13837 | "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); | ||
13838 | } | ||
13839 | |||
13840 | template <typename F, typename U = meta::unqualified_t<F>> | ||
13841 | inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) { | ||
13842 | return resolve_f(meta::has_deducible_signature<U>{}, std::forward<F>(f)); | ||
13843 | } | ||
13844 | |||
13845 | template <typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>> | ||
13846 | inline auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) { | ||
13847 | return resolve_i(types<R(Args...)>(), std::forward<F>(f)); | ||
13848 | } | ||
13849 | |||
13850 | template <typename Sig, typename C> | ||
13851 | inline Sig C::*resolve_v(std::false_type, Sig C::*mem_func_ptr) { | ||
13852 | return mem_func_ptr; | ||
13853 | } | ||
13854 | |||
13855 | template <typename Sig, typename C> | ||
13856 | inline Sig C::*resolve_v(std::true_type, Sig C::*mem_variable_ptr) { | ||
13857 | return mem_variable_ptr; | ||
13858 | } | ||
13859 | } // namespace detail | ||
13860 | |||
13861 | template <typename... Args, typename R> | ||
13862 | inline auto resolve(R fun_ptr(Args...)) -> R (*)(Args...) { | ||
13863 | return fun_ptr; | ||
13864 | } | ||
13865 | |||
13866 | template <typename Sig> | ||
13867 | inline Sig* resolve(Sig* fun_ptr) { | ||
13868 | return fun_ptr; | ||
13869 | } | ||
13870 | |||
13871 | template <typename... Args, typename R, typename C> | ||
13872 | inline auto resolve(R (C::*mem_ptr)(Args...)) -> R (C::*)(Args...) { | ||
13873 | return mem_ptr; | ||
13874 | } | ||
13875 | |||
13876 | template <typename Sig, typename C> | ||
13877 | inline Sig C::*resolve(Sig C::*mem_ptr) { | ||
13878 | return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); | ||
13879 | } | ||
13880 | |||
13881 | template <typename... Sig, typename F> | ||
13882 | inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { | ||
13883 | return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); | ||
13884 | } | ||
13885 | |||
13886 | #endif | ||
13887 | |||
13888 | } // namespace sol | ||
13889 | |||
13890 | // end of sol/resolve.hpp | ||
13891 | |||
13892 | namespace sol { | ||
13893 | namespace function_detail { | ||
13894 | template <typename T> | ||
13895 | struct class_indicator {}; | ||
13896 | |||
13897 | struct call_indicator {}; | ||
13898 | } // namespace function_detail | ||
13899 | |||
13900 | namespace stack { | ||
13901 | template <typename... Sigs> | ||
13902 | struct pusher<function_sig<Sigs...>> { | ||
13903 | template <bool is_yielding, typename... Sig, typename Fx, typename... Args> | ||
13904 | static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) { | ||
13905 | typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx; | ||
13906 | typedef function_detail::functor_function<clean_fx, is_yielding> F; | ||
13907 | set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); | ||
13908 | } | ||
13909 | |||
13910 | template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args> | ||
13911 | static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) { | ||
13912 | using fx_ptr_t = R (*)(A...); | ||
13913 | fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx)); | ||
13914 | select_function<is_yielding>(std::true_type(), L, fxptr, std::forward<Args>(args)...); | ||
13915 | } | ||
13916 | |||
13917 | template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args> | ||
13918 | static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) { | ||
13919 | typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t; | ||
13920 | typedef R (*fx_ptr_t)(A...); | ||
13921 | typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible; | ||
13922 | select_convertible<is_yielding>(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...); | ||
13923 | } | ||
13924 | |||
13925 | template <bool is_yielding, typename Fx, typename... Args> | ||
13926 | static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { | ||
13927 | typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig; | ||
13928 | select_convertible<is_yielding>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); | ||
13929 | } | ||
13930 | |||
13931 | template <bool is_yielding, typename Fx, typename T, typename... Args> | ||
13932 | static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { | ||
13933 | typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx; | ||
13934 | typedef function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx, is_yielding> F; | ||
13935 | set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); | ||
13936 | } | ||
13937 | |||
13938 | template <bool is_yielding, typename Fx, typename T, typename... Args> | ||
13939 | static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { | ||
13940 | typedef std::decay_t<Fx> dFx; | ||
13941 | dFx memfxptr(std::forward<Fx>(fx)); | ||
13942 | auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...); | ||
13943 | lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call; | ||
13944 | |||
13945 | int upvalues = 0; | ||
13946 | upvalues += stack::push(L, nullptr); | ||
13947 | upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr); | ||
13948 | upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr))); | ||
13949 | stack::push(L, c_closure(freefunc, upvalues)); | ||
13950 | } | ||
13951 | |||
13952 | template <bool is_yielding, typename Fx, typename... Args> | ||
13953 | static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { | ||
13954 | select_convertible<is_yielding>(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); | ||
13955 | } | ||
13956 | |||
13957 | template <bool is_yielding, typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<meta::unqualified_t<T>, function_detail::class_indicator>> = meta::enabler> | ||
13958 | static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { | ||
13959 | typedef meta::boolean<meta::is_specialization_of<meta::unqualified_t<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference; | ||
13960 | select_reference_member_variable<is_yielding>(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); | ||
13961 | } | ||
13962 | |||
13963 | template <bool is_yielding, typename Fx, typename C> | ||
13964 | static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) { | ||
13965 | lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx, is_yielding>::call; | ||
13966 | |||
13967 | int upvalues = 0; | ||
13968 | upvalues += stack::push(L, nullptr); | ||
13969 | upvalues += stack::stack_detail::push_as_upvalues(L, fx); | ||
13970 | stack::push(L, c_closure(freefunc, upvalues)); | ||
13971 | } | ||
13972 | |||
13973 | template <bool is_yielding, typename Fx> | ||
13974 | static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { | ||
13975 | typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; | ||
13976 | lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx, is_yielding>::call; | ||
13977 | |||
13978 | int upvalues = 0; | ||
13979 | upvalues += stack::push(L, nullptr); | ||
13980 | upvalues += stack::stack_detail::push_as_upvalues(L, fx); | ||
13981 | stack::push(L, c_closure(freefunc, upvalues)); | ||
13982 | } | ||
13983 | |||
13984 | template <bool is_yielding, typename Fx, typename T, typename... Args> | ||
13985 | static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { | ||
13986 | typedef std::decay_t<Fx> clean_fx; | ||
13987 | typedef function_detail::member_function<meta::unwrap_unqualified_t<T>, clean_fx, is_yielding> F; | ||
13988 | set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); | ||
13989 | } | ||
13990 | |||
13991 | template <bool is_yielding, typename Fx, typename T, typename... Args> | ||
13992 | static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { | ||
13993 | typedef std::decay_t<Fx> dFx; | ||
13994 | dFx memfxptr(std::forward<Fx>(fx)); | ||
13995 | auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...); | ||
13996 | lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call; | ||
13997 | |||
13998 | int upvalues = 0; | ||
13999 | upvalues += stack::push(L, nullptr); | ||
14000 | upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr); | ||
14001 | upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr))); | ||
14002 | stack::push(L, c_closure(freefunc, upvalues)); | ||
14003 | } | ||
14004 | |||
14005 | template <bool is_yielding, typename Fx, typename... Args> | ||
14006 | static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { | ||
14007 | select_member_variable<is_yielding>(meta::is_member_object<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); | ||
14008 | } | ||
14009 | |||
14010 | template <bool is_yielding, typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<meta::unqualified_t<T>, function_detail::class_indicator>> = meta::enabler> | ||
14011 | static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { | ||
14012 | typedef meta::boolean<meta::is_specialization_of<meta::unqualified_t<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference; | ||
14013 | select_reference_member_function<is_yielding>(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); | ||
14014 | } | ||
14015 | |||
14016 | template <bool is_yielding, typename Fx, typename C> | ||
14017 | static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) { | ||
14018 | lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx, is_yielding>::call; | ||
14019 | |||
14020 | int upvalues = 0; | ||
14021 | upvalues += stack::push(L, nullptr); | ||
14022 | upvalues += stack::stack_detail::push_as_upvalues(L, fx); | ||
14023 | stack::push(L, c_closure(freefunc, upvalues)); | ||
14024 | } | ||
14025 | |||
14026 | template <bool is_yielding, typename Fx> | ||
14027 | static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { | ||
14028 | typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; | ||
14029 | lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx, is_yielding>::call; | ||
14030 | |||
14031 | int upvalues = 0; | ||
14032 | upvalues += stack::push(L, nullptr); | ||
14033 | upvalues += stack::stack_detail::push_as_upvalues(L, fx); | ||
14034 | stack::push(L, c_closure(freefunc, upvalues)); | ||
14035 | } | ||
14036 | |||
14037 | template <bool is_yielding, typename Fx, typename... Args> | ||
14038 | static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { | ||
14039 | select_member_function<is_yielding>(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); | ||
14040 | } | ||
14041 | |||
14042 | template <bool is_yielding, typename Fx, typename... Args> | ||
14043 | static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { | ||
14044 | std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...); | ||
14045 | lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx, is_yielding>::call; | ||
14046 | |||
14047 | int upvalues = 0; | ||
14048 | upvalues += stack::push(L, nullptr); | ||
14049 | upvalues += stack::stack_detail::push_as_upvalues(L, target); | ||
14050 | stack::push(L, c_closure(freefunc, upvalues)); | ||
14051 | } | ||
14052 | |||
14053 | template <bool is_yielding> | ||
14054 | static void select_function(std::true_type, lua_State* L, lua_CFunction f) { | ||
14055 | // TODO: support yielding | ||
14056 | stack::push(L, f); | ||
14057 | } | ||
14058 | |||
14059 | #if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE | ||
14060 | template <bool is_yielding> | ||
14061 | static void select_function(std::true_type, lua_State* L, detail::lua_CFunction_noexcept f) { | ||
14062 | // TODO: support yielding | ||
14063 | stack::push(L, f); | ||
14064 | } | ||
14065 | #endif // noexcept function type | ||
14066 | |||
14067 | template <bool is_yielding, typename Fx, typename... Args, meta::disable<is_lua_reference<meta::unqualified_t<Fx>>> = meta::enabler> | ||
14068 | static void select(lua_State* L, Fx&& fx, Args&&... args) { | ||
14069 | select_function<is_yielding>(std::is_function<std::remove_pointer_t<meta::unqualified_t<Fx>>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); | ||
14070 | } | ||
14071 | |||
14072 | template <bool is_yielding, typename Fx, meta::enable<is_lua_reference<meta::unqualified_t<Fx>>> = meta::enabler> | ||
14073 | static void select(lua_State* L, Fx&& fx) { | ||
14074 | // TODO: hoist into lambda in this case?? | ||
14075 | stack::push(L, std::forward<Fx>(fx)); | ||
14076 | } | ||
14077 | |||
14078 | template <bool is_yielding, typename Fx, typename... Args> | ||
14079 | static void set_fx(lua_State* L, Args&&... args) { | ||
14080 | lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>; | ||
14081 | |||
14082 | int upvalues = 0; | ||
14083 | upvalues += stack::push(L, nullptr); | ||
14084 | upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...); | ||
14085 | stack::push(L, c_closure(freefunc, upvalues)); | ||
14086 | } | ||
14087 | |||
14088 | template <typename Arg0, typename... Args, meta::disable<std::is_same<detail::yield_tag_t, meta::unqualified_t<Arg0>>> = meta::enabler> | ||
14089 | static int push(lua_State* L, Arg0&& arg0, Args&&... args) { | ||
14090 | // Set will always place one thing (function) on the stack | ||
14091 | select<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...); | ||
14092 | return 1; | ||
14093 | } | ||
14094 | |||
14095 | template <typename... Args> | ||
14096 | static int push(lua_State* L, detail::yield_tag_t, Args&&... args) { | ||
14097 | // Set will always place one thing (function) on the stack | ||
14098 | select<true>(L, std::forward<Args>(args)...); | ||
14099 | return 1; | ||
14100 | } | ||
14101 | }; | ||
14102 | |||
14103 | template <typename T> | ||
14104 | struct pusher<yielding_t<T>> { | ||
14105 | template <typename... Args> | ||
14106 | static int push(lua_State* L, const yielding_t<T>& f, Args&&... args) { | ||
14107 | pusher<function_sig<>> p{}; | ||
14108 | (void)p; | ||
14109 | return p.push(L, detail::yield_tag, f.func, std::forward<Args>(args)...); | ||
14110 | } | ||
14111 | |||
14112 | template <typename... Args> | ||
14113 | static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) { | ||
14114 | pusher<function_sig<>> p{}; | ||
14115 | (void)p; | ||
14116 | return p.push(L, detail::yield_tag, f.func, std::forward<Args>(args)...); | ||
14117 | } | ||
14118 | }; | ||
14119 | |||
14120 | template <typename T, typename... Args> | ||
14121 | struct pusher<function_arguments<T, Args...>> { | ||
14122 | template <std::size_t... I, typename FP> | ||
14123 | static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) { | ||
14124 | return stack::push<T>(L, detail::forward_get<I>(fp.arguments)...); | ||
14125 | } | ||
14126 | |||
14127 | static int push(lua_State* L, const function_arguments<T, Args...>& fp) { | ||
14128 | return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp); | ||
14129 | } | ||
14130 | |||
14131 | static int push(lua_State* L, function_arguments<T, Args...>&& fp) { | ||
14132 | return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp)); | ||
14133 | } | ||
14134 | }; | ||
14135 | |||
14136 | template <typename Signature> | ||
14137 | struct pusher<std::function<Signature>> { | ||
14138 | static int push(lua_State* L, const std::function<Signature>& fx) { | ||
14139 | return pusher<function_sig<Signature>>{}.push(L, fx); | ||
14140 | } | ||
14141 | |||
14142 | static int push(lua_State* L, std::function<Signature>&& fx) { | ||
14143 | return pusher<function_sig<Signature>>{}.push(L, std::move(fx)); | ||
14144 | } | ||
14145 | }; | ||
14146 | |||
14147 | template <typename Signature> | ||
14148 | struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> { | ||
14149 | template <typename F, typename... Args> | ||
14150 | static int push(lua_State* L, F&& f, Args&&... args) { | ||
14151 | pusher<function_sig<>> p{}; | ||
14152 | (void)p; | ||
14153 | return p.push(L, std::forward<F>(f), std::forward<Args>(args)...); | ||
14154 | } | ||
14155 | }; | ||
14156 | |||
14157 | template <typename Signature> | ||
14158 | struct pusher<Signature, std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>> | ||
14159 | #if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE | ||
14160 | , | ||
14161 | meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>> | ||
14162 | #endif // noexcept function types | ||
14163 | >::value>> { | ||
14164 | template <typename F> | ||
14165 | static int push(lua_State* L, F&& f) { | ||
14166 | return pusher<function_sig<>>{}.push(L, std::forward<F>(f)); | ||
14167 | } | ||
14168 | }; | ||
14169 | |||
14170 | template <typename... Functions> | ||
14171 | struct pusher<overload_set<Functions...>> { | ||
14172 | static int push(lua_State* L, overload_set<Functions...>&& set) { | ||
14173 | // TODO: yielding | ||
14174 | typedef function_detail::overloaded_function<0, Functions...> F; | ||
14175 | pusher<function_sig<>>{}.set_fx<false, F>(L, std::move(set.functions)); | ||
14176 | return 1; | ||
14177 | } | ||
14178 | |||
14179 | static int push(lua_State* L, const overload_set<Functions...>& set) { | ||
14180 | // TODO: yielding | ||
14181 | typedef function_detail::overloaded_function<0, Functions...> F; | ||
14182 | pusher<function_sig<>>{}.set_fx<false, F>(L, set.functions); | ||
14183 | return 1; | ||
14184 | } | ||
14185 | }; | ||
14186 | |||
14187 | template <typename T> | ||
14188 | struct pusher<protect_t<T>> { | ||
14189 | static int push(lua_State* L, protect_t<T>&& pw) { | ||
14190 | lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>; | ||
14191 | int upvalues = 0; | ||
14192 | upvalues += stack::push(L, nullptr); | ||
14193 | upvalues += stack::push<user<protect_t<T>>>(L, std::move(pw.value)); | ||
14194 | return stack::push(L, c_closure(cf, upvalues)); | ||
14195 | } | ||
14196 | |||
14197 | static int push(lua_State* L, const protect_t<T>& pw) { | ||
14198 | lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>; | ||
14199 | int upvalues = 0; | ||
14200 | upvalues += stack::push(L, nullptr); | ||
14201 | upvalues += stack::push<user<protect_t<T>>>(L, pw.value); | ||
14202 | return stack::push(L, c_closure(cf, upvalues)); | ||
14203 | } | ||
14204 | }; | ||
14205 | |||
14206 | template <typename F, typename G> | ||
14207 | struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> { | ||
14208 | static int push(lua_State* L, property_wrapper<F, G>&& pw) { | ||
14209 | return stack::push(L, overload(std::move(pw.read), std::move(pw.write))); | ||
14210 | } | ||
14211 | static int push(lua_State* L, const property_wrapper<F, G>& pw) { | ||
14212 | return stack::push(L, overload(pw.read, pw.write)); | ||
14213 | } | ||
14214 | }; | ||
14215 | |||
14216 | template <typename F> | ||
14217 | struct pusher<property_wrapper<F, void>> { | ||
14218 | static int push(lua_State* L, property_wrapper<F, void>&& pw) { | ||
14219 | return stack::push(L, std::move(pw.read)); | ||
14220 | } | ||
14221 | static int push(lua_State* L, const property_wrapper<F, void>& pw) { | ||
14222 | return stack::push(L, pw.read); | ||
14223 | } | ||
14224 | }; | ||
14225 | |||
14226 | template <typename F> | ||
14227 | struct pusher<property_wrapper<void, F>> { | ||
14228 | static int push(lua_State* L, property_wrapper<void, F>&& pw) { | ||
14229 | return stack::push(L, std::move(pw.write)); | ||
14230 | } | ||
14231 | static int push(lua_State* L, const property_wrapper<void, F>& pw) { | ||
14232 | return stack::push(L, pw.write); | ||
14233 | } | ||
14234 | }; | ||
14235 | |||
14236 | template <typename T> | ||
14237 | struct pusher<var_wrapper<T>> { | ||
14238 | static int push(lua_State* L, var_wrapper<T>&& vw) { | ||
14239 | return stack::push(L, std::move(vw.value)); | ||
14240 | } | ||
14241 | static int push(lua_State* L, const var_wrapper<T>& vw) { | ||
14242 | return stack::push(L, vw.value); | ||
14243 | } | ||
14244 | }; | ||
14245 | |||
14246 | template <typename... Functions> | ||
14247 | struct pusher<factory_wrapper<Functions...>> { | ||
14248 | static int push(lua_State* L, const factory_wrapper<Functions...>& fw) { | ||
14249 | typedef function_detail::overloaded_function<0, Functions...> F; | ||
14250 | pusher<function_sig<>>{}.set_fx<false, F>(L, fw.functions); | ||
14251 | return 1; | ||
14252 | } | ||
14253 | |||
14254 | static int push(lua_State* L, factory_wrapper<Functions...>&& fw) { | ||
14255 | typedef function_detail::overloaded_function<0, Functions...> F; | ||
14256 | pusher<function_sig<>>{}.set_fx<false, F>(L, std::move(fw.functions)); | ||
14257 | return 1; | ||
14258 | } | ||
14259 | |||
14260 | static int push(lua_State* L, const factory_wrapper<Functions...>& set, function_detail::call_indicator) { | ||
14261 | typedef function_detail::overloaded_function<1, Functions...> F; | ||
14262 | pusher<function_sig<>>{}.set_fx<false, F>(L, set.functions); | ||
14263 | return 1; | ||
14264 | } | ||
14265 | |||
14266 | static int push(lua_State* L, factory_wrapper<Functions...>&& set, function_detail::call_indicator) { | ||
14267 | typedef function_detail::overloaded_function<1, Functions...> F; | ||
14268 | pusher<function_sig<>>{}.set_fx<false, F>(L, std::move(set.functions)); | ||
14269 | return 1; | ||
14270 | } | ||
14271 | }; | ||
14272 | |||
14273 | template <> | ||
14274 | struct pusher<no_construction> { | ||
14275 | static int push(lua_State* L, no_construction) { | ||
14276 | lua_CFunction cf = &function_detail::no_construction_error; | ||
14277 | return stack::push(L, cf); | ||
14278 | } | ||
14279 | |||
14280 | static int push(lua_State* L, no_construction c, function_detail::call_indicator) { | ||
14281 | return push(L, c); | ||
14282 | } | ||
14283 | }; | ||
14284 | |||
14285 | template <typename T, typename... Lists> | ||
14286 | struct pusher<detail::tagged<T, constructor_list<Lists...>>> { | ||
14287 | static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) { | ||
14288 | lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls, true, Lists...>; | ||
14289 | return stack::push(L, cf); | ||
14290 | } | ||
14291 | |||
14292 | static int push(lua_State* L, constructor_list<Lists...>) { | ||
14293 | lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls, true, Lists...>; | ||
14294 | return stack::push(L, cf); | ||
14295 | } | ||
14296 | }; | ||
14297 | |||
14298 | template <typename L0, typename... Lists> | ||
14299 | struct pusher<constructor_list<L0, Lists...>> { | ||
14300 | typedef constructor_list<L0, Lists...> cl_t; | ||
14301 | static int push(lua_State* L, cl_t cl) { | ||
14302 | typedef typename meta::bind_traits<L0>::return_type T; | ||
14303 | return stack::push<detail::tagged<T, cl_t>>(L, cl); | ||
14304 | } | ||
14305 | }; | ||
14306 | |||
14307 | template <typename T, typename... Fxs> | ||
14308 | struct pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> { | ||
14309 | template <typename C> | ||
14310 | static int push(lua_State* L, C&& c) { | ||
14311 | lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>, 2>; | ||
14312 | int upvalues = 0; | ||
14313 | upvalues += stack::push(L, nullptr); | ||
14314 | upvalues += stack::push<user<constructor_wrapper<Fxs...>>>(L, std::forward<C>(c)); | ||
14315 | return stack::push(L, c_closure(cf, upvalues)); | ||
14316 | } | ||
14317 | }; | ||
14318 | |||
14319 | template <typename F, typename... Fxs> | ||
14320 | struct pusher<constructor_wrapper<F, Fxs...>> { | ||
14321 | template <typename C> | ||
14322 | static int push(lua_State* L, C&& c) { | ||
14323 | typedef typename meta::bind_traits<F>::template arg_at<0> arg0; | ||
14324 | typedef meta::unqualified_t<std::remove_pointer_t<arg0>> T; | ||
14325 | return stack::push<detail::tagged<T, constructor_wrapper<F, Fxs...>>>(L, std::forward<C>(c)); | ||
14326 | } | ||
14327 | }; | ||
14328 | |||
14329 | template <typename T> | ||
14330 | struct pusher<detail::tagged<T, destructor_wrapper<void>>> { | ||
14331 | static int push(lua_State* L, destructor_wrapper<void>) { | ||
14332 | lua_CFunction cf = detail::usertype_alloc_destruct<T>; | ||
14333 | return stack::push(L, cf); | ||
14334 | } | ||
14335 | }; | ||
14336 | |||
14337 | template <typename T, typename Fx> | ||
14338 | struct pusher<detail::tagged<T, destructor_wrapper<Fx>>> { | ||
14339 | static int push(lua_State* L, destructor_wrapper<Fx>&& c) { | ||
14340 | lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>; | ||
14341 | int upvalues = 0; | ||
14342 | upvalues += stack::push(L, nullptr); | ||
14343 | upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c)); | ||
14344 | return stack::push(L, c_closure(cf, upvalues)); | ||
14345 | } | ||
14346 | |||
14347 | static int push(lua_State* L, const destructor_wrapper<Fx>& c) { | ||
14348 | lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>; | ||
14349 | int upvalues = 0; | ||
14350 | upvalues += stack::push(L, nullptr); | ||
14351 | upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c); | ||
14352 | return stack::push(L, c_closure(cf, upvalues)); | ||
14353 | } | ||
14354 | }; | ||
14355 | |||
14356 | template <typename Fx> | ||
14357 | struct pusher<destructor_wrapper<Fx>> { | ||
14358 | static int push(lua_State* L, destructor_wrapper<Fx>&& c) { | ||
14359 | lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>; | ||
14360 | int upvalues = 0; | ||
14361 | upvalues += stack::push(L, nullptr); | ||
14362 | upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c)); | ||
14363 | return stack::push(L, c_closure(cf, upvalues)); | ||
14364 | } | ||
14365 | |||
14366 | static int push(lua_State* L, const destructor_wrapper<Fx>& c) { | ||
14367 | lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>; | ||
14368 | int upvalues = 0; | ||
14369 | upvalues += stack::push(L, nullptr); | ||
14370 | upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c); | ||
14371 | return stack::push(L, c_closure(cf, upvalues)); | ||
14372 | } | ||
14373 | }; | ||
14374 | |||
14375 | template <typename F, typename... Filters> | ||
14376 | struct pusher<filter_wrapper<F, Filters...>> { | ||
14377 | typedef filter_wrapper<F, Filters...> P; | ||
14378 | |||
14379 | static int push(lua_State* L, const P& p) { | ||
14380 | lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>; | ||
14381 | int upvalues = 0; | ||
14382 | upvalues += stack::push(L, nullptr); | ||
14383 | upvalues += stack::push<user<P>>(L, p); | ||
14384 | return stack::push(L, c_closure(cf, upvalues)); | ||
14385 | } | ||
14386 | |||
14387 | static int push(lua_State* L, P&& p) { | ||
14388 | lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>; | ||
14389 | int upvalues = 0; | ||
14390 | upvalues += stack::push(L, nullptr); | ||
14391 | upvalues += stack::push<user<P>>(L, std::move(p)); | ||
14392 | return stack::push(L, c_closure(cf, upvalues)); | ||
14393 | } | ||
14394 | }; | ||
14395 | } // namespace stack | ||
14396 | } // namespace sol | ||
14397 | |||
14398 | // end of sol/function_types.hpp | ||
14399 | |||
14400 | namespace sol { | ||
14401 | template <typename base_t, bool aligned = false> | ||
14402 | class basic_function : public base_t { | ||
14403 | private: | ||
14404 | void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const { | ||
14405 | lua_call(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount)); | ||
14406 | } | ||
14407 | |||
14408 | template <std::size_t... I, typename... Ret> | ||
14409 | auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) const { | ||
14410 | luacall(n, lua_size<std::tuple<Ret...>>::value); | ||
14411 | return stack::pop<std::tuple<Ret...>>(lua_state()); | ||
14412 | } | ||
14413 | |||
14414 | template <std::size_t I, typename Ret> | ||
14415 | Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) const { | ||
14416 | luacall(n, lua_size<Ret>::value); | ||
14417 | return stack::pop<Ret>(lua_state()); | ||
14418 | } | ||
14419 | |||
14420 | template <std::size_t I> | ||
14421 | void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) const { | ||
14422 | luacall(n, 0); | ||
14423 | } | ||
14424 | |||
14425 | unsafe_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const { | ||
14426 | int stacksize = lua_gettop(lua_state()); | ||
14427 | int firstreturn = (std::max)(1, stacksize - static_cast<int>(n)); | ||
14428 | luacall(n, LUA_MULTRET); | ||
14429 | int poststacksize = lua_gettop(lua_state()); | ||
14430 | int returncount = poststacksize - (firstreturn - 1); | ||
14431 | return unsafe_function_result(lua_state(), firstreturn, returncount); | ||
14432 | } | ||
14433 | |||
14434 | public: | ||
14435 | using base_t::lua_state; | ||
14436 | |||
14437 | basic_function() = default; | ||
14438 | 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> | ||
14439 | basic_function(T&& r) noexcept | ||
14440 | : base_t(std::forward<T>(r)) { | ||
14441 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14442 | if (!is_function<meta::unqualified_t<T>>::value) { | ||
14443 | auto pp = stack::push_pop(*this); | ||
14444 | constructor_handler handler{}; | ||
14445 | stack::check<basic_function>(lua_state(), -1, handler); | ||
14446 | } | ||
14447 | #endif // Safety | ||
14448 | } | ||
14449 | basic_function(const basic_function&) = default; | ||
14450 | basic_function& operator=(const basic_function&) = default; | ||
14451 | basic_function(basic_function&&) = default; | ||
14452 | basic_function& operator=(basic_function&&) = default; | ||
14453 | basic_function(const stack_reference& r) | ||
14454 | : basic_function(r.lua_state(), r.stack_index()) { | ||
14455 | } | ||
14456 | basic_function(stack_reference&& r) | ||
14457 | : basic_function(r.lua_state(), r.stack_index()) { | ||
14458 | } | ||
14459 | basic_function(lua_nil_t n) | ||
14460 | : base_t(n) { | ||
14461 | } | ||
14462 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
14463 | basic_function(lua_State* L, T&& r) | ||
14464 | : base_t(L, std::forward<T>(r)) { | ||
14465 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14466 | auto pp = stack::push_pop(*this); | ||
14467 | constructor_handler handler{}; | ||
14468 | stack::check<basic_function>(lua_state(), -1, handler); | ||
14469 | #endif // Safety | ||
14470 | } | ||
14471 | basic_function(lua_State* L, int index = -1) | ||
14472 | : base_t(L, index) { | ||
14473 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14474 | constructor_handler handler{}; | ||
14475 | stack::check<basic_function>(L, index, handler); | ||
14476 | #endif // Safety | ||
14477 | } | ||
14478 | basic_function(lua_State* L, ref_index index) | ||
14479 | : base_t(L, index) { | ||
14480 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14481 | auto pp = stack::push_pop(*this); | ||
14482 | constructor_handler handler{}; | ||
14483 | stack::check<basic_function>(lua_state(), -1, handler); | ||
14484 | #endif // Safety | ||
14485 | } | ||
14486 | |||
14487 | template <typename... Args> | ||
14488 | unsafe_function_result operator()(Args&&... args) const { | ||
14489 | return call<>(std::forward<Args>(args)...); | ||
14490 | } | ||
14491 | |||
14492 | template <typename... Ret, typename... Args> | ||
14493 | decltype(auto) operator()(types<Ret...>, Args&&... args) const { | ||
14494 | return call<Ret...>(std::forward<Args>(args)...); | ||
14495 | } | ||
14496 | |||
14497 | template <typename... Ret, typename... Args> | ||
14498 | decltype(auto) call(Args&&... args) const { | ||
14499 | if (!aligned) { | ||
14500 | base_t::push(); | ||
14501 | } | ||
14502 | int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); | ||
14503 | return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount); | ||
14504 | } | ||
14505 | }; | ||
14506 | } // namespace sol | ||
14507 | |||
14508 | // end of sol/unsafe_function.hpp | ||
14509 | |||
14510 | // beginning of sol/protected_function.hpp | ||
14511 | |||
14512 | // beginning of sol/protected_handler.hpp | ||
14513 | |||
14514 | namespace sol { | ||
14515 | namespace detail { | ||
14516 | inline const char(&default_handler_name())[9]{ | ||
14517 | static const char name[9] = "sol.\xF0\x9F\x94\xA9"; | ||
14518 | return name; | ||
14519 | } | ||
14520 | |||
14521 | template <bool b, typename target_t = reference> | ||
14522 | struct protected_handler { | ||
14523 | typedef is_stack_based<target_t> is_stack; | ||
14524 | const target_t& target; | ||
14525 | int stackindex; | ||
14526 | |||
14527 | protected_handler(std::false_type, const target_t& target) | ||
14528 | : target(target), stackindex(0) { | ||
14529 | if (b) { | ||
14530 | stackindex = lua_gettop(target.lua_state()) + 1; | ||
14531 | target.push(); | ||
14532 | } | ||
14533 | } | ||
14534 | |||
14535 | protected_handler(std::true_type, const target_t& target) | ||
14536 | : target(target), stackindex(0) { | ||
14537 | if (b) { | ||
14538 | stackindex = target.stack_index(); | ||
14539 | } | ||
14540 | } | ||
14541 | |||
14542 | protected_handler(const target_t& target) | ||
14543 | : protected_handler(is_stack(), target) { | ||
14544 | } | ||
14545 | |||
14546 | bool valid() const noexcept { | ||
14547 | return b; | ||
14548 | } | ||
14549 | |||
14550 | ~protected_handler() { | ||
14551 | if (!is_stack::value && stackindex != 0) { | ||
14552 | lua_remove(target.lua_state(), stackindex); | ||
14553 | } | ||
14554 | } | ||
14555 | }; | ||
14556 | |||
14557 | template <typename base_t, typename T> | ||
14558 | basic_function<base_t> force_cast(T& p) { | ||
14559 | return p; | ||
14560 | } | ||
14561 | |||
14562 | template <typename Reference, bool is_main_ref = false> | ||
14563 | static Reference get_default_handler(lua_State* L) { | ||
14564 | if (is_stack_based<Reference>::value || L == nullptr) | ||
14565 | return Reference(L, lua_nil); | ||
14566 | L = is_main_ref ? main_thread(L, L) : L; | ||
14567 | lua_getglobal(L, default_handler_name()); | ||
14568 | auto pp = stack::pop_n(L, 1); | ||
14569 | return Reference(L, -1); | ||
14570 | } | ||
14571 | |||
14572 | template <typename T> | ||
14573 | static void set_default_handler(lua_State* L, const T& ref) { | ||
14574 | if (L == nullptr) { | ||
14575 | return; | ||
14576 | } | ||
14577 | if (!ref.valid()) { | ||
14578 | lua_pushnil(L); | ||
14579 | lua_setglobal(L, default_handler_name()); | ||
14580 | } | ||
14581 | else { | ||
14582 | ref.push(L); | ||
14583 | lua_setglobal(L, default_handler_name()); | ||
14584 | } | ||
14585 | } | ||
14586 | } // namespace detail | ||
14587 | } // namespace sol | ||
14588 | |||
14589 | // end of sol/protected_handler.hpp | ||
14590 | |||
14591 | namespace sol { | ||
14592 | template <typename base_t, bool aligned = false, typename handler_t = reference> | ||
14593 | class basic_protected_function : public base_t { | ||
14594 | public: | ||
14595 | typedef is_stack_based<handler_t> is_stack_handler; | ||
14596 | |||
14597 | static handler_t get_default_handler(lua_State* L) { | ||
14598 | return detail::get_default_handler<handler_t, is_main_threaded<base_t>::value>(L); | ||
14599 | } | ||
14600 | |||
14601 | template <typename T> | ||
14602 | static void set_default_handler(const T& ref) { | ||
14603 | detail::set_default_handler(ref.lua_state(), ref); | ||
14604 | } | ||
14605 | |||
14606 | private: | ||
14607 | template <bool b> | ||
14608 | call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, detail::protected_handler<b, handler_t>& h) const { | ||
14609 | return static_cast<call_status>(lua_pcall(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex)); | ||
14610 | } | ||
14611 | |||
14612 | template <std::size_t... I, bool b, typename... Ret> | ||
14613 | auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const { | ||
14614 | luacall(n, sizeof...(Ret), h); | ||
14615 | return stack::pop<std::tuple<Ret...>>(lua_state()); | ||
14616 | } | ||
14617 | |||
14618 | template <std::size_t I, bool b, typename Ret> | ||
14619 | Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const { | ||
14620 | luacall(n, 1, h); | ||
14621 | return stack::pop<Ret>(lua_state()); | ||
14622 | } | ||
14623 | |||
14624 | template <std::size_t I, bool b> | ||
14625 | void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const { | ||
14626 | luacall(n, 0, h); | ||
14627 | } | ||
14628 | |||
14629 | template <bool b> | ||
14630 | protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const { | ||
14631 | int stacksize = lua_gettop(lua_state()); | ||
14632 | int poststacksize = stacksize; | ||
14633 | int firstreturn = 1; | ||
14634 | int returncount = 0; | ||
14635 | call_status code = call_status::ok; | ||
14636 | #if !defined(SOL_NO_EXCEPTIONS) || !SOL_NO_EXCEPTIONS | ||
14637 | auto onexcept = [&](optional<const std::exception&> maybe_ex, const char* error) { | ||
14638 | h.stackindex = 0; | ||
14639 | if (b) { | ||
14640 | h.target.push(); | ||
14641 | detail::call_exception_handler(lua_state(), maybe_ex, error); | ||
14642 | lua_call(lua_state(), 1, 1); | ||
14643 | } | ||
14644 | else { | ||
14645 | detail::call_exception_handler(lua_state(), maybe_ex, error); | ||
14646 | } | ||
14647 | }; | ||
14648 | (void)onexcept; | ||
14649 | #if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) || (defined(SOL_LUAJIT) && SOL_LUAJIT) | ||
14650 | try { | ||
14651 | #endif // Safe Exception Propagation | ||
14652 | #endif // No Exceptions | ||
14653 | firstreturn = (std::max)(1, static_cast<int>(stacksize - n - static_cast<int>(h.valid()))); | ||
14654 | code = luacall(n, LUA_MULTRET, h); | ||
14655 | poststacksize = lua_gettop(lua_state()) - static_cast<int>(h.valid()); | ||
14656 | returncount = poststacksize - (firstreturn - 1); | ||
14657 | #ifndef SOL_NO_EXCEPTIONS | ||
14658 | #if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) || (defined(SOL_LUAJIT) && SOL_LUAJIT) | ||
14659 | } | ||
14660 | // Handle C++ errors thrown from C++ functions bound inside of lua | ||
14661 | catch (const char* error) { | ||
14662 | onexcept(optional<const std::exception&>(nullopt), error); | ||
14663 | firstreturn = lua_gettop(lua_state()); | ||
14664 | return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); | ||
14665 | } | ||
14666 | catch (const std::string& error) { | ||
14667 | onexcept(optional<const std::exception&>(nullopt), error.c_str()); | ||
14668 | firstreturn = lua_gettop(lua_state()); | ||
14669 | return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); | ||
14670 | } | ||
14671 | catch (const std::exception& error) { | ||
14672 | onexcept(optional<const std::exception&>(error), error.what()); | ||
14673 | firstreturn = lua_gettop(lua_state()); | ||
14674 | return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); | ||
14675 | } | ||
14676 | #if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) | ||
14677 | // LuaJIT cannot have the catchall when the safe propagation is on | ||
14678 | // but LuaJIT will swallow all C++ errors | ||
14679 | // if we don't at least catch std::exception ones | ||
14680 | catch (...) { | ||
14681 | onexcept(optional<const std::exception&>(nullopt), "caught (...) unknown error during protected_function call"); | ||
14682 | firstreturn = lua_gettop(lua_state()); | ||
14683 | return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); | ||
14684 | } | ||
14685 | #endif // LuaJIT | ||
14686 | #else | ||
14687 | // do not handle exceptions: they can be propogated into C++ and keep all type information / rich information | ||
14688 | #endif // Safe Exception Propagation | ||
14689 | #endif // Exceptions vs. No Exceptions | ||
14690 | return protected_function_result(lua_state(), firstreturn, returncount, returncount, code); | ||
14691 | } | ||
14692 | |||
14693 | public: | ||
14694 | using base_t::lua_state; | ||
14695 | |||
14696 | handler_t error_handler; | ||
14697 | |||
14698 | basic_protected_function() = default; | ||
14699 | 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> | ||
14700 | basic_protected_function(T&& r) noexcept | ||
14701 | : base_t(std::forward<T>(r)), error_handler(get_default_handler(r.lua_state())) { | ||
14702 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14703 | if (!is_function<meta::unqualified_t<T>>::value) { | ||
14704 | auto pp = stack::push_pop(*this); | ||
14705 | constructor_handler handler{}; | ||
14706 | stack::check<basic_protected_function>(lua_state(), -1, handler); | ||
14707 | } | ||
14708 | #endif // Safety | ||
14709 | } | ||
14710 | basic_protected_function(const basic_protected_function&) = default; | ||
14711 | basic_protected_function& operator=(const basic_protected_function&) = default; | ||
14712 | basic_protected_function(basic_protected_function&&) = default; | ||
14713 | basic_protected_function& operator=(basic_protected_function&&) = default; | ||
14714 | basic_protected_function(const basic_function<base_t>& b) | ||
14715 | : basic_protected_function(b, get_default_handler(b.lua_state())) { | ||
14716 | } | ||
14717 | basic_protected_function(basic_function<base_t>&& b) | ||
14718 | : basic_protected_function(std::move(b), get_default_handler(b.lua_state())) { | ||
14719 | } | ||
14720 | basic_protected_function(const basic_function<base_t>& b, handler_t eh) | ||
14721 | : base_t(b), error_handler(std::move(eh)) { | ||
14722 | } | ||
14723 | basic_protected_function(basic_function<base_t>&& b, handler_t eh) | ||
14724 | : base_t(std::move(b)), error_handler(std::move(eh)) { | ||
14725 | } | ||
14726 | basic_protected_function(const stack_reference& r) | ||
14727 | : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) { | ||
14728 | } | ||
14729 | basic_protected_function(stack_reference&& r) | ||
14730 | : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) { | ||
14731 | } | ||
14732 | basic_protected_function(const stack_reference& r, handler_t eh) | ||
14733 | : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) { | ||
14734 | } | ||
14735 | basic_protected_function(stack_reference&& r, handler_t eh) | ||
14736 | : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) { | ||
14737 | } | ||
14738 | |||
14739 | template <typename Super> | ||
14740 | basic_protected_function(const proxy_base<Super>& p) | ||
14741 | : basic_protected_function(p, get_default_handler(p.lua_state())) { | ||
14742 | } | ||
14743 | template <typename Super> | ||
14744 | basic_protected_function(proxy_base<Super>&& p) | ||
14745 | : basic_protected_function(std::move(p), get_default_handler(p.lua_state())) { | ||
14746 | } | ||
14747 | 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> | ||
14748 | basic_protected_function(Proxy&& p, Handler&& eh) | ||
14749 | : basic_protected_function(detail::force_cast<base_t>(p), std::forward<Handler>(eh)) { | ||
14750 | } | ||
14751 | |||
14752 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
14753 | basic_protected_function(lua_State* L, T&& r) | ||
14754 | : basic_protected_function(L, std::forward<T>(r), get_default_handler(L)) { | ||
14755 | } | ||
14756 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
14757 | basic_protected_function(lua_State* L, T&& r, handler_t eh) | ||
14758 | : base_t(L, std::forward<T>(r)), error_handler(std::move(eh)) { | ||
14759 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14760 | auto pp = stack::push_pop(*this); | ||
14761 | constructor_handler handler{}; | ||
14762 | stack::check<basic_protected_function>(lua_state(), -1, handler); | ||
14763 | #endif // Safety | ||
14764 | } | ||
14765 | |||
14766 | basic_protected_function(lua_nil_t n) | ||
14767 | : base_t(n), error_handler(n) { | ||
14768 | } | ||
14769 | |||
14770 | basic_protected_function(lua_State* L, int index = -1) | ||
14771 | : basic_protected_function(L, index, get_default_handler(L)) { | ||
14772 | } | ||
14773 | basic_protected_function(lua_State* L, int index, handler_t eh) | ||
14774 | : base_t(L, index), error_handler(std::move(eh)) { | ||
14775 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14776 | constructor_handler handler{}; | ||
14777 | stack::check<basic_protected_function>(L, index, handler); | ||
14778 | #endif // Safety | ||
14779 | } | ||
14780 | basic_protected_function(lua_State* L, absolute_index index) | ||
14781 | : basic_protected_function(L, index, get_default_handler(L)) { | ||
14782 | } | ||
14783 | basic_protected_function(lua_State* L, absolute_index index, handler_t eh) | ||
14784 | : base_t(L, index), error_handler(std::move(eh)) { | ||
14785 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14786 | constructor_handler handler{}; | ||
14787 | stack::check<basic_protected_function>(L, index, handler); | ||
14788 | #endif // Safety | ||
14789 | } | ||
14790 | basic_protected_function(lua_State* L, raw_index index) | ||
14791 | : basic_protected_function(L, index, get_default_handler(L)) { | ||
14792 | } | ||
14793 | basic_protected_function(lua_State* L, raw_index index, handler_t eh) | ||
14794 | : base_t(L, index), error_handler(std::move(eh)) { | ||
14795 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14796 | constructor_handler handler{}; | ||
14797 | stack::check<basic_protected_function>(L, index, handler); | ||
14798 | #endif // Safety | ||
14799 | } | ||
14800 | basic_protected_function(lua_State* L, ref_index index) | ||
14801 | : basic_protected_function(L, index, get_default_handler(L)) { | ||
14802 | } | ||
14803 | basic_protected_function(lua_State* L, ref_index index, handler_t eh) | ||
14804 | : base_t(L, index), error_handler(std::move(eh)) { | ||
14805 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
14806 | auto pp = stack::push_pop(*this); | ||
14807 | constructor_handler handler{}; | ||
14808 | stack::check<basic_protected_function>(lua_state(), -1, handler); | ||
14809 | #endif // Safety | ||
14810 | } | ||
14811 | |||
14812 | template <typename... Args> | ||
14813 | protected_function_result operator()(Args&&... args) const { | ||
14814 | return call<>(std::forward<Args>(args)...); | ||
14815 | } | ||
14816 | |||
14817 | template <typename... Ret, typename... Args> | ||
14818 | decltype(auto) operator()(types<Ret...>, Args&&... args) const { | ||
14819 | return call<Ret...>(std::forward<Args>(args)...); | ||
14820 | } | ||
14821 | |||
14822 | template <typename... Ret, typename... Args> | ||
14823 | decltype(auto) call(Args&&... args) const { | ||
14824 | if (!aligned) { | ||
14825 | // we do not expect the function to already be on the stack: push it | ||
14826 | if (error_handler.valid()) { | ||
14827 | detail::protected_handler<true, handler_t> h(error_handler); | ||
14828 | base_t::push(); | ||
14829 | int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); | ||
14830 | return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); | ||
14831 | } | ||
14832 | else { | ||
14833 | detail::protected_handler<false, handler_t> h(error_handler); | ||
14834 | base_t::push(); | ||
14835 | int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); | ||
14836 | return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); | ||
14837 | } | ||
14838 | } | ||
14839 | else { | ||
14840 | // the function is already on the stack at the right location | ||
14841 | if (error_handler.valid()) { | ||
14842 | // the handler will be pushed onto the stack manually, | ||
14843 | // since it's not already on the stack this means we need to push our own | ||
14844 | // function on the stack too and swap things to be in-place | ||
14845 | if (!is_stack_handler::value) { | ||
14846 | // so, we need to remove the function at the top and then dump the handler out ourselves | ||
14847 | base_t::push(); | ||
14848 | } | ||
14849 | detail::protected_handler<true, handler_t> h(error_handler); | ||
14850 | if (!is_stack_handler::value) { | ||
14851 | lua_replace(lua_state(), -3); | ||
14852 | h.stackindex = lua_absindex(lua_state(), -2); | ||
14853 | } | ||
14854 | int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); | ||
14855 | return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); | ||
14856 | } | ||
14857 | else { | ||
14858 | detail::protected_handler<false, handler_t> h(error_handler); | ||
14859 | int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); | ||
14860 | return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); | ||
14861 | } | ||
14862 | } | ||
14863 | } | ||
14864 | }; | ||
14865 | } // namespace sol | ||
14866 | |||
14867 | // end of sol/protected_function.hpp | ||
14868 | |||
14869 | namespace sol { | ||
14870 | template <typename... Ret, typename... Args> | ||
14871 | inline decltype(auto) stack_proxy::call(Args&&... args) { | ||
14872 | stack_function sf(this->lua_state(), this->stack_index()); | ||
14873 | return sf.template call<Ret...>(std::forward<Args>(args)...); | ||
14874 | } | ||
14875 | |||
14876 | inline protected_function_result::protected_function_result(unsafe_function_result&& o) noexcept | ||
14877 | : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()), popcount(o.return_count()), err(o.status()) { | ||
14878 | // Must be manual, otherwise destructor will screw us | ||
14879 | // return count being 0 is enough to keep things clean | ||
14880 | // but we will be thorough | ||
14881 | o.abandon(); | ||
14882 | } | ||
14883 | |||
14884 | inline protected_function_result& protected_function_result::operator=(unsafe_function_result&& o) noexcept { | ||
14885 | L = o.lua_state(); | ||
14886 | index = o.stack_index(); | ||
14887 | returncount = o.return_count(); | ||
14888 | popcount = o.return_count(); | ||
14889 | err = o.status(); | ||
14890 | // Must be manual, otherwise destructor will screw us | ||
14891 | // return count being 0 is enough to keep things clean | ||
14892 | // but we will be thorough | ||
14893 | o.abandon(); | ||
14894 | return *this; | ||
14895 | } | ||
14896 | |||
14897 | inline unsafe_function_result::unsafe_function_result(protected_function_result&& o) noexcept | ||
14898 | : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) { | ||
14899 | // Must be manual, otherwise destructor will screw us | ||
14900 | // return count being 0 is enough to keep things clean | ||
14901 | // but we will be thorough | ||
14902 | o.abandon(); | ||
14903 | } | ||
14904 | inline unsafe_function_result& unsafe_function_result::operator=(protected_function_result&& o) noexcept { | ||
14905 | L = o.lua_state(); | ||
14906 | index = o.stack_index(); | ||
14907 | returncount = o.return_count(); | ||
14908 | // Must be manual, otherwise destructor will screw us | ||
14909 | // return count being 0 is enough to keep things clean | ||
14910 | // but we will be thorough | ||
14911 | o.abandon(); | ||
14912 | return *this; | ||
14913 | } | ||
14914 | |||
14915 | namespace stack { | ||
14916 | template <typename Signature> | ||
14917 | struct getter<std::function<Signature>> { | ||
14918 | typedef meta::bind_traits<Signature> fx_t; | ||
14919 | typedef typename fx_t::args_list args_lists; | ||
14920 | typedef meta::tuple_types<typename fx_t::return_type> return_types; | ||
14921 | |||
14922 | template <typename... Args, typename... Ret> | ||
14923 | static std::function<Signature> get_std_func(types<Ret...>, types<Args...>, lua_State* L, int index) { | ||
14924 | unsafe_function f(L, index); | ||
14925 | auto fx = [ f = std::move(f) ](Args && ... args) -> meta::return_type_t<Ret...> { | ||
14926 | return f.call<Ret...>(std::forward<Args>(args)...); | ||
14927 | }; | ||
14928 | return std::move(fx); | ||
14929 | } | ||
14930 | |||
14931 | template <typename... FxArgs> | ||
14932 | static std::function<Signature> get_std_func(types<void>, types<FxArgs...>, lua_State* L, int index) { | ||
14933 | unsafe_function f(L, index); | ||
14934 | auto fx = [f = std::move(f)](FxArgs&&... args) -> void { | ||
14935 | f(std::forward<FxArgs>(args)...); | ||
14936 | }; | ||
14937 | return std::move(fx); | ||
14938 | } | ||
14939 | |||
14940 | template <typename... FxArgs> | ||
14941 | static std::function<Signature> get_std_func(types<>, types<FxArgs...> t, lua_State* L, int index) { | ||
14942 | return get_std_func(types<void>(), t, L, index); | ||
14943 | } | ||
14944 | |||
14945 | static std::function<Signature> get(lua_State* L, int index, record& tracking) { | ||
14946 | tracking.last = 1; | ||
14947 | tracking.used += 1; | ||
14948 | type t = type_of(L, index); | ||
14949 | if (t == type::none || t == type::lua_nil) { | ||
14950 | return nullptr; | ||
14951 | } | ||
14952 | return get_std_func(return_types(), args_lists(), L, index); | ||
14953 | } | ||
14954 | }; | ||
14955 | } // namespace stack | ||
14956 | |||
14957 | } // namespace sol | ||
14958 | |||
14959 | // end of sol/function.hpp | ||
14960 | |||
14961 | namespace sol { | ||
14962 | template <typename Table, typename Key> | ||
14963 | struct proxy : public proxy_base<proxy<Table, Key>> { | ||
14964 | private: | ||
14965 | typedef meta::condition<meta::is_specialization_of<Key, std::tuple>, Key, std::tuple<meta::condition<std::is_array<meta::unqualified_t<Key>>, Key&, meta::unqualified_t<Key>>>> key_type; | ||
14966 | |||
14967 | template <typename T, std::size_t... I> | ||
14968 | decltype(auto) tuple_get(std::index_sequence<I...>) const { | ||
14969 | return tbl.template traverse_get<T>(std::get<I>(key)...); | ||
14970 | } | ||
14971 | |||
14972 | template <std::size_t... I, typename T> | ||
14973 | void tuple_set(std::index_sequence<I...>, T&& value) { | ||
14974 | tbl.traverse_set(std::get<I>(key)..., std::forward<T>(value)); | ||
14975 | } | ||
14976 | |||
14977 | auto setup_table(std::true_type) { | ||
14978 | auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, tbl.stack_index()); | ||
14979 | lua_pop(lua_state(), p.levels); | ||
14980 | return p; | ||
14981 | } | ||
14982 | |||
14983 | bool is_valid(std::false_type) { | ||
14984 | auto pp = stack::push_pop(tbl); | ||
14985 | auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state())); | ||
14986 | lua_pop(lua_state(), p.levels); | ||
14987 | return p; | ||
14988 | } | ||
14989 | |||
14990 | public: | ||
14991 | Table tbl; | ||
14992 | key_type key; | ||
14993 | |||
14994 | template <typename T> | ||
14995 | proxy(Table table, T&& k) | ||
14996 | : tbl(table), key(std::forward<T>(k)) { | ||
14997 | } | ||
14998 | |||
14999 | template <typename T> | ||
15000 | proxy& set(T&& item) { | ||
15001 | tuple_set(std::make_index_sequence<std::tuple_size<meta::unqualified_t<key_type>>::value>(), std::forward<T>(item)); | ||
15002 | return *this; | ||
15003 | } | ||
15004 | |||
15005 | template <typename... Args> | ||
15006 | proxy& set_function(Args&&... args) { | ||
15007 | tbl.set_function(key, std::forward<Args>(args)...); | ||
15008 | return *this; | ||
15009 | } | ||
15010 | |||
15011 | template <typename U, meta::enable<meta::neg<is_lua_reference_or_proxy<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler> | ||
15012 | proxy& operator=(U&& other) { | ||
15013 | return set_function(std::forward<U>(other)); | ||
15014 | } | ||
15015 | |||
15016 | template <typename U, meta::disable<meta::neg<is_lua_reference_or_proxy<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler> | ||
15017 | proxy& operator=(U&& other) { | ||
15018 | return set(std::forward<U>(other)); | ||
15019 | } | ||
15020 | |||
15021 | template <typename T> | ||
15022 | proxy& operator=(std::initializer_list<T> other) { | ||
15023 | return set(std::move(other)); | ||
15024 | } | ||
15025 | |||
15026 | template <typename T> | ||
15027 | decltype(auto) get() const { | ||
15028 | return tuple_get<T>(std::make_index_sequence<std::tuple_size<meta::unqualified_t<key_type>>::value>()); | ||
15029 | } | ||
15030 | |||
15031 | template <typename T> | ||
15032 | decltype(auto) get_or(T&& otherwise) const { | ||
15033 | typedef decltype(get<T>()) U; | ||
15034 | optional<U> option = get<optional<U>>(); | ||
15035 | if (option) { | ||
15036 | return static_cast<U>(option.value()); | ||
15037 | } | ||
15038 | return static_cast<U>(std::forward<T>(otherwise)); | ||
15039 | } | ||
15040 | |||
15041 | template <typename T, typename D> | ||
15042 | decltype(auto) get_or(D&& otherwise) const { | ||
15043 | optional<T> option = get<optional<T>>(); | ||
15044 | if (option) { | ||
15045 | return static_cast<T>(option.value()); | ||
15046 | } | ||
15047 | return static_cast<T>(std::forward<D>(otherwise)); | ||
15048 | } | ||
15049 | |||
15050 | template <typename K> | ||
15051 | decltype(auto) operator[](K&& k) const { | ||
15052 | auto keys = meta::tuplefy(key, std::forward<K>(k)); | ||
15053 | return proxy<Table, decltype(keys)>(tbl, std::move(keys)); | ||
15054 | } | ||
15055 | |||
15056 | template <typename... Ret, typename... Args> | ||
15057 | decltype(auto) call(Args&&... args) { | ||
15058 | #if defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 191326131 && _MSC_FULL_VER >= 191200000 | ||
15059 | // MSVC is ass sometimes | ||
15060 | return get<function>().call<Ret...>(std::forward<Args>(args)...); | ||
15061 | #else | ||
15062 | return get<function>().template call<Ret...>(std::forward<Args>(args)...); | ||
15063 | #endif | ||
15064 | } | ||
15065 | |||
15066 | template <typename... Args> | ||
15067 | decltype(auto) operator()(Args&&... args) { | ||
15068 | return call<>(std::forward<Args>(args)...); | ||
15069 | } | ||
15070 | |||
15071 | bool valid() const { | ||
15072 | auto pp = stack::push_pop(tbl); | ||
15073 | auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state())); | ||
15074 | lua_pop(lua_state(), p.levels); | ||
15075 | return p; | ||
15076 | } | ||
15077 | |||
15078 | int push() const noexcept { | ||
15079 | return push(this->lua_state()); | ||
15080 | } | ||
15081 | |||
15082 | int push(lua_State* L) const noexcept { | ||
15083 | return get<reference>().push(L); | ||
15084 | } | ||
15085 | |||
15086 | type get_type() const { | ||
15087 | type t = type::none; | ||
15088 | auto pp = stack::push_pop(tbl); | ||
15089 | auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state())); | ||
15090 | if (p) { | ||
15091 | t = type_of(lua_state(), -1); | ||
15092 | } | ||
15093 | lua_pop(lua_state(), p.levels); | ||
15094 | return t; | ||
15095 | } | ||
15096 | |||
15097 | lua_State* lua_state() const { | ||
15098 | return tbl.lua_state(); | ||
15099 | } | ||
15100 | }; | ||
15101 | |||
15102 | template <typename Table, typename Key, typename T> | ||
15103 | inline bool operator==(T&& left, const proxy<Table, Key>& right) { | ||
15104 | typedef decltype(stack::get<T>(nullptr, 0)) U; | ||
15105 | return right.template get<optional<U>>() == left; | ||
15106 | } | ||
15107 | |||
15108 | template <typename Table, typename Key, typename T> | ||
15109 | inline bool operator==(const proxy<Table, Key>& right, T&& left) { | ||
15110 | typedef decltype(stack::get<T>(nullptr, 0)) U; | ||
15111 | return right.template get<optional<U>>() == left; | ||
15112 | } | ||
15113 | |||
15114 | template <typename Table, typename Key, typename T> | ||
15115 | inline bool operator!=(T&& left, const proxy<Table, Key>& right) { | ||
15116 | typedef decltype(stack::get<T>(nullptr, 0)) U; | ||
15117 | return right.template get<optional<U>>() != left; | ||
15118 | } | ||
15119 | |||
15120 | template <typename Table, typename Key, typename T> | ||
15121 | inline bool operator!=(const proxy<Table, Key>& right, T&& left) { | ||
15122 | typedef decltype(stack::get<T>(nullptr, 0)) U; | ||
15123 | return right.template get<optional<U>>() != left; | ||
15124 | } | ||
15125 | |||
15126 | template <typename Table, typename Key> | ||
15127 | inline bool operator==(lua_nil_t, const proxy<Table, Key>& right) { | ||
15128 | return !right.valid(); | ||
15129 | } | ||
15130 | |||
15131 | template <typename Table, typename Key> | ||
15132 | inline bool operator==(const proxy<Table, Key>& right, lua_nil_t) { | ||
15133 | return !right.valid(); | ||
15134 | } | ||
15135 | |||
15136 | template <typename Table, typename Key> | ||
15137 | inline bool operator!=(lua_nil_t, const proxy<Table, Key>& right) { | ||
15138 | return right.valid(); | ||
15139 | } | ||
15140 | |||
15141 | template <typename Table, typename Key> | ||
15142 | inline bool operator!=(const proxy<Table, Key>& right, lua_nil_t) { | ||
15143 | return right.valid(); | ||
15144 | } | ||
15145 | |||
15146 | template <bool b> | ||
15147 | template <typename Super> | ||
15148 | basic_reference<b>& basic_reference<b>::operator=(proxy_base<Super>&& r) { | ||
15149 | basic_reference<b> v = r; | ||
15150 | this->operator=(std::move(v)); | ||
15151 | return *this; | ||
15152 | } | ||
15153 | |||
15154 | template <bool b> | ||
15155 | template <typename Super> | ||
15156 | basic_reference<b>& basic_reference<b>::operator=(const proxy_base<Super>& r) { | ||
15157 | basic_reference<b> v = r; | ||
15158 | this->operator=(std::move(v)); | ||
15159 | return *this; | ||
15160 | } | ||
15161 | |||
15162 | namespace stack { | ||
15163 | template <typename Table, typename Key> | ||
15164 | struct pusher<proxy<Table, Key>> { | ||
15165 | static int push(lua_State* L, const proxy<Table, Key>& p) { | ||
15166 | reference r = p; | ||
15167 | return r.push(L); | ||
15168 | } | ||
15169 | }; | ||
15170 | } // namespace stack | ||
15171 | } // namespace sol | ||
15172 | |||
15173 | // end of sol/proxy.hpp | ||
15174 | |||
15175 | // beginning of sol/usertype.hpp | ||
15176 | |||
15177 | // beginning of sol/usertype_metatable.hpp | ||
15178 | |||
15179 | // beginning of sol/deprecate.hpp | ||
15180 | |||
15181 | #ifndef SOL_DEPRECATED | ||
15182 | #ifdef _MSC_VER | ||
15183 | #define SOL_DEPRECATED __declspec(deprecated) | ||
15184 | #elif __GNUC__ | ||
15185 | #define SOL_DEPRECATED __attribute__((deprecated)) | ||
15186 | #else | ||
15187 | #define SOL_DEPRECATED [[deprecated]] | ||
15188 | #endif // compilers | ||
15189 | #endif // SOL_DEPRECATED | ||
15190 | |||
15191 | namespace sol { | ||
15192 | namespace detail { | ||
15193 | template <typename T> | ||
15194 | struct SOL_DEPRECATED deprecate_type { | ||
15195 | using type = T; | ||
15196 | }; | ||
15197 | } | ||
15198 | } // namespace sol::detail | ||
15199 | |||
15200 | // end of sol/deprecate.hpp | ||
15201 | |||
15202 | // beginning of sol/object.hpp | ||
15203 | |||
15204 | // beginning of sol/object_base.hpp | ||
15205 | |||
15206 | namespace sol { | ||
15207 | |||
15208 | template <typename base_t> | ||
15209 | class basic_object_base : public base_t { | ||
15210 | private: | ||
15211 | template <typename T> | ||
15212 | decltype(auto) as_stack(std::true_type) const { | ||
15213 | return stack::get<T>(base_t::lua_state(), base_t::stack_index()); | ||
15214 | } | ||
15215 | |||
15216 | template <typename T> | ||
15217 | decltype(auto) as_stack(std::false_type) const { | ||
15218 | base_t::push(); | ||
15219 | return stack::pop<T>(base_t::lua_state()); | ||
15220 | } | ||
15221 | |||
15222 | template <typename T> | ||
15223 | bool is_stack(std::true_type) const { | ||
15224 | return stack::check<T>(base_t::lua_state(), base_t::stack_index(), no_panic); | ||
15225 | } | ||
15226 | |||
15227 | template <typename T> | ||
15228 | bool is_stack(std::false_type) const { | ||
15229 | int r = base_t::registry_index(); | ||
15230 | if (r == LUA_REFNIL) | ||
15231 | return meta::any_same<meta::unqualified_t<T>, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false; | ||
15232 | if (r == LUA_NOREF) | ||
15233 | return false; | ||
15234 | auto pp = stack::push_pop(*this); | ||
15235 | return stack::check<T>(base_t::lua_state(), -1, no_panic); | ||
15236 | } | ||
15237 | |||
15238 | public: | ||
15239 | basic_object_base() noexcept = default; | ||
15240 | basic_object_base(const basic_object_base&) = default; | ||
15241 | basic_object_base(basic_object_base&&) = default; | ||
15242 | basic_object_base& operator=(const basic_object_base&) = default; | ||
15243 | basic_object_base& operator=(basic_object_base&&) = default; | ||
15244 | template <typename T, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_object_base>>> = meta::enabler> | ||
15245 | basic_object_base(T&& arg, Args&&... args) | ||
15246 | : base_t(std::forward<T>(arg), std::forward<Args>(args)...) { | ||
15247 | } | ||
15248 | |||
15249 | template <typename T> | ||
15250 | decltype(auto) as() const { | ||
15251 | return as_stack<T>(is_stack_based<base_t>()); | ||
15252 | } | ||
15253 | |||
15254 | template <typename T> | ||
15255 | bool is() const { | ||
15256 | return is_stack<T>(is_stack_based<base_t>()); | ||
15257 | } | ||
15258 | }; | ||
15259 | } // namespace sol | ||
15260 | |||
15261 | // end of sol/object_base.hpp | ||
15262 | |||
15263 | // beginning of sol/userdata.hpp | ||
15264 | |||
15265 | namespace sol { | ||
15266 | template <typename base_type> | ||
15267 | class basic_userdata : public basic_table<base_type> { | ||
15268 | typedef basic_table<base_type> base_t; | ||
15269 | |||
15270 | public: | ||
15271 | using base_t::lua_state; | ||
15272 | |||
15273 | basic_userdata() noexcept = default; | ||
15274 | 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> | ||
15275 | basic_userdata(T&& r) noexcept | ||
15276 | : base_t(std::forward<T>(r)) { | ||
15277 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
15278 | if (!is_userdata<meta::unqualified_t<T>>::value) { | ||
15279 | auto pp = stack::push_pop(*this); | ||
15280 | type_assert(lua_state(), -1, type::userdata); | ||
15281 | } | ||
15282 | #endif // Safety | ||
15283 | } | ||
15284 | basic_userdata(const basic_userdata&) = default; | ||
15285 | basic_userdata(basic_userdata&&) = default; | ||
15286 | basic_userdata& operator=(const basic_userdata&) = default; | ||
15287 | basic_userdata& operator=(basic_userdata&&) = default; | ||
15288 | basic_userdata(const stack_reference& r) | ||
15289 | : basic_userdata(r.lua_state(), r.stack_index()) { | ||
15290 | } | ||
15291 | basic_userdata(stack_reference&& r) | ||
15292 | : basic_userdata(r.lua_state(), r.stack_index()) { | ||
15293 | } | ||
15294 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
15295 | basic_userdata(lua_State* L, T&& r) | ||
15296 | : base_t(L, std::forward<T>(r)) { | ||
15297 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
15298 | auto pp = stack::push_pop(*this); | ||
15299 | constructor_handler handler{}; | ||
15300 | stack::check<basic_userdata>(L, -1, handler); | ||
15301 | #endif // Safety | ||
15302 | } | ||
15303 | basic_userdata(lua_State* L, int index = -1) | ||
15304 | : base_t(detail::no_safety, L, index) { | ||
15305 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
15306 | constructor_handler handler{}; | ||
15307 | stack::check<basic_userdata>(L, index, handler); | ||
15308 | #endif // Safety | ||
15309 | } | ||
15310 | basic_userdata(lua_State* L, ref_index index) | ||
15311 | : base_t(detail::no_safety, L, index) { | ||
15312 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
15313 | auto pp = stack::push_pop(*this); | ||
15314 | constructor_handler handler{}; | ||
15315 | stack::check<basic_userdata>(L, -1, handler); | ||
15316 | #endif // Safety | ||
15317 | } | ||
15318 | }; | ||
15319 | |||
15320 | template <typename base_type> | ||
15321 | class basic_lightuserdata : public basic_object_base<base_type> { | ||
15322 | typedef basic_object_base<base_type> base_t; | ||
15323 | |||
15324 | public: | ||
15325 | using base_t::lua_state; | ||
15326 | |||
15327 | basic_lightuserdata() noexcept = default; | ||
15328 | 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> | ||
15329 | basic_lightuserdata(T&& r) noexcept | ||
15330 | : base_t(std::forward<T>(r)) { | ||
15331 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
15332 | if (!is_lightuserdata<meta::unqualified_t<T>>::value) { | ||
15333 | auto pp = stack::push_pop(*this); | ||
15334 | type_assert(lua_state(), -1, type::lightuserdata); | ||
15335 | } | ||
15336 | #endif // Safety | ||
15337 | } | ||
15338 | basic_lightuserdata(const basic_lightuserdata&) = default; | ||
15339 | basic_lightuserdata(basic_lightuserdata&&) = default; | ||
15340 | basic_lightuserdata& operator=(const basic_lightuserdata&) = default; | ||
15341 | basic_lightuserdata& operator=(basic_lightuserdata&&) = default; | ||
15342 | basic_lightuserdata(const stack_reference& r) | ||
15343 | : basic_lightuserdata(r.lua_state(), r.stack_index()) { | ||
15344 | } | ||
15345 | basic_lightuserdata(stack_reference&& r) | ||
15346 | : basic_lightuserdata(r.lua_state(), r.stack_index()) { | ||
15347 | } | ||
15348 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
15349 | basic_lightuserdata(lua_State* L, T&& r) | ||
15350 | : basic_lightuserdata(L, std::forward<T>(r)) { | ||
15351 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
15352 | auto pp = stack::push_pop(*this); | ||
15353 | constructor_handler handler{}; | ||
15354 | stack::check<basic_lightuserdata>(lua_state(), -1, handler); | ||
15355 | #endif // Safety | ||
15356 | } | ||
15357 | basic_lightuserdata(lua_State* L, int index = -1) | ||
15358 | : base_t(L, index) { | ||
15359 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
15360 | constructor_handler handler{}; | ||
15361 | stack::check<basic_lightuserdata>(L, index, handler); | ||
15362 | #endif // Safety | ||
15363 | } | ||
15364 | basic_lightuserdata(lua_State* L, ref_index index) | ||
15365 | : base_t(L, index) { | ||
15366 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
15367 | auto pp = stack::push_pop(*this); | ||
15368 | constructor_handler handler{}; | ||
15369 | stack::check<basic_lightuserdata>(lua_state(), index, handler); | ||
15370 | #endif // Safety | ||
15371 | } | ||
15372 | }; | ||
15373 | |||
15374 | } // namespace sol | ||
15375 | |||
15376 | // end of sol/userdata.hpp | ||
15377 | |||
15378 | // beginning of sol/as_args.hpp | ||
15379 | |||
15380 | namespace sol { | ||
15381 | template <typename T> | ||
15382 | struct as_args_t { | ||
15383 | T src; | ||
15384 | }; | ||
15385 | |||
15386 | template <typename Source> | ||
15387 | auto as_args(Source&& source) { | ||
15388 | return as_args_t<Source>{ std::forward<Source>(source) }; | ||
15389 | } | ||
15390 | |||
15391 | namespace stack { | ||
15392 | template <typename T> | ||
15393 | struct pusher<as_args_t<T>> { | ||
15394 | int push(lua_State* L, const as_args_t<T>& e) { | ||
15395 | int p = 0; | ||
15396 | for (const auto& i : e.src) { | ||
15397 | p += stack::push(L, i); | ||
15398 | } | ||
15399 | return p; | ||
15400 | } | ||
15401 | }; | ||
15402 | } // namespace stack | ||
15403 | } // namespace sol | ||
15404 | |||
15405 | // end of sol/as_args.hpp | ||
15406 | |||
15407 | // beginning of sol/variadic_args.hpp | ||
15408 | |||
15409 | namespace sol { | ||
15410 | struct variadic_args { | ||
15411 | private: | ||
15412 | lua_State* L; | ||
15413 | int index; | ||
15414 | int stacktop; | ||
15415 | |||
15416 | public: | ||
15417 | typedef stack_proxy reference_type; | ||
15418 | typedef stack_proxy value_type; | ||
15419 | typedef stack_proxy* pointer; | ||
15420 | typedef std::ptrdiff_t difference_type; | ||
15421 | typedef std::size_t size_type; | ||
15422 | typedef stack_iterator<stack_proxy, false> iterator; | ||
15423 | typedef stack_iterator<stack_proxy, true> const_iterator; | ||
15424 | typedef std::reverse_iterator<iterator> reverse_iterator; | ||
15425 | typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | ||
15426 | |||
15427 | variadic_args() = default; | ||
15428 | variadic_args(lua_State* luastate, int stackindex = -1) | ||
15429 | : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lua_gettop(luastate)) { | ||
15430 | } | ||
15431 | variadic_args(lua_State* luastate, int stackindex, int lastindex) | ||
15432 | : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lastindex) { | ||
15433 | } | ||
15434 | variadic_args(const variadic_args&) = default; | ||
15435 | variadic_args& operator=(const variadic_args&) = default; | ||
15436 | variadic_args(variadic_args&& o) | ||
15437 | : L(o.L), index(o.index), stacktop(o.stacktop) { | ||
15438 | // Must be manual, otherwise destructor will screw us | ||
15439 | // return count being 0 is enough to keep things clean | ||
15440 | // but will be thorough | ||
15441 | o.L = nullptr; | ||
15442 | o.index = 0; | ||
15443 | o.stacktop = 0; | ||
15444 | } | ||
15445 | variadic_args& operator=(variadic_args&& o) { | ||
15446 | L = o.L; | ||
15447 | index = o.index; | ||
15448 | stacktop = o.stacktop; | ||
15449 | // Must be manual, otherwise destructor will screw us | ||
15450 | // return count being 0 is enough to keep things clean | ||
15451 | // but will be thorough | ||
15452 | o.L = nullptr; | ||
15453 | o.index = 0; | ||
15454 | o.stacktop = 0; | ||
15455 | return *this; | ||
15456 | } | ||
15457 | |||
15458 | iterator begin() { | ||
15459 | return iterator(L, index, stacktop + 1); | ||
15460 | } | ||
15461 | iterator end() { | ||
15462 | return iterator(L, stacktop + 1, stacktop + 1); | ||
15463 | } | ||
15464 | const_iterator begin() const { | ||
15465 | return const_iterator(L, index, stacktop + 1); | ||
15466 | } | ||
15467 | const_iterator end() const { | ||
15468 | return const_iterator(L, stacktop + 1, stacktop + 1); | ||
15469 | } | ||
15470 | const_iterator cbegin() const { | ||
15471 | return begin(); | ||
15472 | } | ||
15473 | const_iterator cend() const { | ||
15474 | return end(); | ||
15475 | } | ||
15476 | |||
15477 | reverse_iterator rbegin() { | ||
15478 | return std::reverse_iterator<iterator>(begin()); | ||
15479 | } | ||
15480 | reverse_iterator rend() { | ||
15481 | return std::reverse_iterator<iterator>(end()); | ||
15482 | } | ||
15483 | const_reverse_iterator rbegin() const { | ||
15484 | return std::reverse_iterator<const_iterator>(begin()); | ||
15485 | } | ||
15486 | const_reverse_iterator rend() const { | ||
15487 | return std::reverse_iterator<const_iterator>(end()); | ||
15488 | } | ||
15489 | const_reverse_iterator crbegin() const { | ||
15490 | return std::reverse_iterator<const_iterator>(cbegin()); | ||
15491 | } | ||
15492 | const_reverse_iterator crend() const { | ||
15493 | return std::reverse_iterator<const_iterator>(cend()); | ||
15494 | } | ||
15495 | |||
15496 | int push() const { | ||
15497 | return push(L); | ||
15498 | } | ||
15499 | |||
15500 | int push(lua_State* target) const { | ||
15501 | int pushcount = 0; | ||
15502 | for (int i = index; i <= stacktop; ++i) { | ||
15503 | lua_pushvalue(L, i); | ||
15504 | pushcount += 1; | ||
15505 | } | ||
15506 | if (target != L) { | ||
15507 | lua_xmove(L, target, pushcount); | ||
15508 | } | ||
15509 | return pushcount; | ||
15510 | } | ||
15511 | |||
15512 | template <typename T> | ||
15513 | decltype(auto) get(difference_type index_offset = 0) const { | ||
15514 | return stack::get<T>(L, index + static_cast<int>(index_offset)); | ||
15515 | } | ||
15516 | |||
15517 | type get_type(difference_type index_offset = 0) const noexcept { | ||
15518 | return type_of(L, index + static_cast<int>(index_offset)); | ||
15519 | } | ||
15520 | |||
15521 | stack_proxy operator[](difference_type index_offset) const { | ||
15522 | return stack_proxy(L, index + static_cast<int>(index_offset)); | ||
15523 | } | ||
15524 | |||
15525 | lua_State* lua_state() const { | ||
15526 | return L; | ||
15527 | }; | ||
15528 | int stack_index() const { | ||
15529 | return index; | ||
15530 | }; | ||
15531 | int leftover_count() const { | ||
15532 | return stacktop - (index - 1); | ||
15533 | } | ||
15534 | std::size_t size() const { | ||
15535 | return static_cast<std::size_t>(leftover_count()); | ||
15536 | } | ||
15537 | int top() const { | ||
15538 | return stacktop; | ||
15539 | } | ||
15540 | }; | ||
15541 | |||
15542 | namespace stack { | ||
15543 | template <> | ||
15544 | struct getter<variadic_args> { | ||
15545 | static variadic_args get(lua_State* L, int index, record& tracking) { | ||
15546 | tracking.last = 0; | ||
15547 | return variadic_args(L, index); | ||
15548 | } | ||
15549 | }; | ||
15550 | |||
15551 | template <> | ||
15552 | struct pusher<variadic_args> { | ||
15553 | static int push(lua_State* L, const variadic_args& ref) { | ||
15554 | return ref.push(L); | ||
15555 | } | ||
15556 | }; | ||
15557 | } // namespace stack | ||
15558 | } // namespace sol | ||
15559 | |||
15560 | // end of sol/variadic_args.hpp | ||
15561 | |||
15562 | namespace sol { | ||
15563 | |||
15564 | template <typename R = reference, bool should_pop = !is_stack_based<R>::value, typename T> | ||
15565 | R make_reference(lua_State* L, T&& value) { | ||
15566 | int backpedal = stack::push(L, std::forward<T>(value)); | ||
15567 | R r = stack::get<R>(L, -backpedal); | ||
15568 | if (should_pop) { | ||
15569 | lua_pop(L, backpedal); | ||
15570 | } | ||
15571 | return r; | ||
15572 | } | ||
15573 | |||
15574 | template <typename T, typename R = reference, bool should_pop = !is_stack_based<R>::value, typename... Args> | ||
15575 | R make_reference(lua_State* L, Args&&... args) { | ||
15576 | int backpedal = stack::push<T>(L, std::forward<Args>(args)...); | ||
15577 | R r = stack::get<R>(L, -backpedal); | ||
15578 | if (should_pop) { | ||
15579 | lua_pop(L, backpedal); | ||
15580 | } | ||
15581 | return r; | ||
15582 | } | ||
15583 | |||
15584 | template <typename base_type> | ||
15585 | class basic_object : public basic_object_base<base_type> { | ||
15586 | private: | ||
15587 | typedef basic_object_base<base_type> base_t; | ||
15588 | |||
15589 | template <bool invert_and_pop = false> | ||
15590 | basic_object(std::integral_constant<bool, invert_and_pop>, lua_State* L, int index = -1) noexcept | ||
15591 | : base_t(L, index) { | ||
15592 | if (invert_and_pop) { | ||
15593 | lua_pop(L, -index); | ||
15594 | } | ||
15595 | } | ||
15596 | |||
15597 | public: | ||
15598 | basic_object() noexcept = default; | ||
15599 | 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> | ||
15600 | basic_object(T&& r) | ||
15601 | : base_t(std::forward<T>(r)) { | ||
15602 | } | ||
15603 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
15604 | basic_object(lua_State* L, T&& r) | ||
15605 | : base_t(L, std::forward<T>(r)) { | ||
15606 | } | ||
15607 | basic_object(lua_nil_t r) | ||
15608 | : base_t(r) { | ||
15609 | } | ||
15610 | basic_object(const basic_object&) = default; | ||
15611 | basic_object(basic_object&&) = default; | ||
15612 | basic_object(const stack_reference& r) noexcept | ||
15613 | : basic_object(r.lua_state(), r.stack_index()) { | ||
15614 | } | ||
15615 | basic_object(stack_reference&& r) noexcept | ||
15616 | : basic_object(r.lua_state(), r.stack_index()) { | ||
15617 | } | ||
15618 | template <typename Super> | ||
15619 | basic_object(const proxy_base<Super>& r) noexcept | ||
15620 | : basic_object(r.operator basic_object()) { | ||
15621 | } | ||
15622 | template <typename Super> | ||
15623 | basic_object(proxy_base<Super>&& r) noexcept | ||
15624 | : basic_object(r.operator basic_object()) { | ||
15625 | } | ||
15626 | basic_object(lua_State* L, lua_nil_t r) noexcept | ||
15627 | : base_t(L, r) { | ||
15628 | } | ||
15629 | basic_object(lua_State* L, int index = -1) noexcept | ||
15630 | : base_t(L, index) { | ||
15631 | } | ||
15632 | basic_object(lua_State* L, absolute_index index) noexcept | ||
15633 | : base_t(L, index) { | ||
15634 | } | ||
15635 | basic_object(lua_State* L, raw_index index) noexcept | ||
15636 | : base_t(L, index) { | ||
15637 | } | ||
15638 | basic_object(lua_State* L, ref_index index) noexcept | ||
15639 | : base_t(L, index) { | ||
15640 | } | ||
15641 | template <typename T, typename... Args> | ||
15642 | basic_object(lua_State* L, in_place_type_t<T>, Args&&... args) noexcept | ||
15643 | : basic_object(std::integral_constant<bool, !is_stack_based<base_t>::value>(), L, -stack::push<T>(L, std::forward<Args>(args)...)) { | ||
15644 | } | ||
15645 | template <typename T, typename... Args> | ||
15646 | basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept | ||
15647 | : basic_object(L, in_place_type<T>, std::forward<T>(arg), std::forward<Args>(args)...) { | ||
15648 | } | ||
15649 | basic_object& operator=(const basic_object&) = default; | ||
15650 | basic_object& operator=(basic_object&&) = default; | ||
15651 | basic_object& operator=(const base_type& b) { | ||
15652 | base_t::operator=(b); | ||
15653 | return *this; | ||
15654 | } | ||
15655 | basic_object& operator=(base_type&& b) { | ||
15656 | base_t::operator=(std::move(b)); | ||
15657 | return *this; | ||
15658 | } | ||
15659 | template <typename Super> | ||
15660 | basic_object& operator=(const proxy_base<Super>& r) { | ||
15661 | this->operator=(r.operator basic_object()); | ||
15662 | return *this; | ||
15663 | } | ||
15664 | template <typename Super> | ||
15665 | basic_object& operator=(proxy_base<Super>&& r) { | ||
15666 | this->operator=(r.operator basic_object()); | ||
15667 | return *this; | ||
15668 | } | ||
15669 | }; | ||
15670 | |||
15671 | template <typename T> | ||
15672 | object make_object(lua_State* L, T&& value) { | ||
15673 | return make_reference<object, true>(L, std::forward<T>(value)); | ||
15674 | } | ||
15675 | |||
15676 | template <typename T, typename... Args> | ||
15677 | object make_object(lua_State* L, Args&&... args) { | ||
15678 | return make_reference<T, object, true>(L, std::forward<Args>(args)...); | ||
15679 | } | ||
15680 | } // namespace sol | ||
15681 | |||
15682 | // end of sol/object.hpp | ||
15683 | |||
15684 | // beginning of sol/container_usertype_metatable.hpp | ||
15685 | |||
15686 | // beginning of sol/container_traits.hpp | ||
15687 | |||
15688 | namespace sol { | ||
15689 | |||
15690 | template <typename T> | ||
15691 | struct container_traits; | ||
15692 | |||
15693 | template <typename T> | ||
15694 | struct as_container_t { | ||
15695 | T source; | ||
15696 | |||
15697 | as_container_t(T value) | ||
15698 | : source(std::move(value)) { | ||
15699 | } | ||
15700 | |||
15701 | operator std::add_rvalue_reference_t<T>() { | ||
15702 | return std::move(source); | ||
15703 | } | ||
15704 | |||
15705 | operator std::add_lvalue_reference_t<std::add_const_t<T>>() const { | ||
15706 | return source; | ||
15707 | } | ||
15708 | }; | ||
15709 | |||
15710 | template <typename T> | ||
15711 | struct as_container_t<T&> { | ||
15712 | std::reference_wrapper<T> source; | ||
15713 | |||
15714 | as_container_t(T& value) | ||
15715 | : source(value) { | ||
15716 | } | ||
15717 | |||
15718 | operator T&() { | ||
15719 | return source; | ||
15720 | } | ||
15721 | }; | ||
15722 | |||
15723 | template <typename T> | ||
15724 | auto as_container(T&& value) { | ||
15725 | return as_container_t<T>(std::forward<T>(value)); | ||
15726 | } | ||
15727 | |||
15728 | namespace container_detail { | ||
15729 | |||
15730 | template <typename T> | ||
15731 | struct has_clear_test { | ||
15732 | private: | ||
15733 | typedef std::array<char, 1> one; | ||
15734 | typedef std::array<char, 2> two; | ||
15735 | |||
15736 | template <typename C> | ||
15737 | static one test(decltype(&C::clear)); | ||
15738 | template <typename C> | ||
15739 | static two test(...); | ||
15740 | |||
15741 | public: | ||
15742 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15743 | }; | ||
15744 | |||
15745 | template <typename T> | ||
15746 | struct has_empty_test { | ||
15747 | private: | ||
15748 | typedef std::array<char, 1> one; | ||
15749 | typedef std::array<char, 2> two; | ||
15750 | |||
15751 | template <typename C> | ||
15752 | static one test(decltype(&C::empty)); | ||
15753 | template <typename C> | ||
15754 | static two test(...); | ||
15755 | |||
15756 | public: | ||
15757 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15758 | }; | ||
15759 | |||
15760 | template <typename T> | ||
15761 | struct has_erase_after_test { | ||
15762 | private: | ||
15763 | typedef std::array<char, 1> one; | ||
15764 | typedef std::array<char, 2> two; | ||
15765 | |||
15766 | template <typename C> | ||
15767 | static one test(decltype(std::declval<C>().erase_after(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>()))*); | ||
15768 | template <typename C> | ||
15769 | static two test(...); | ||
15770 | |||
15771 | public: | ||
15772 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15773 | }; | ||
15774 | |||
15775 | template <typename T, typename = void> | ||
15776 | struct has_find_test { | ||
15777 | private: | ||
15778 | typedef std::array<char, 1> one; | ||
15779 | typedef std::array<char, 2> two; | ||
15780 | |||
15781 | template <typename C> | ||
15782 | static one test(decltype(std::declval<C>().find(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); | ||
15783 | template <typename C> | ||
15784 | static two test(...); | ||
15785 | |||
15786 | public: | ||
15787 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15788 | }; | ||
15789 | |||
15790 | template <typename T> | ||
15791 | struct has_find_test<T, std::enable_if_t<meta::is_lookup<T>::value>> { | ||
15792 | private: | ||
15793 | typedef std::array<char, 1> one; | ||
15794 | typedef std::array<char, 2> two; | ||
15795 | |||
15796 | template <typename C> | ||
15797 | static one test(decltype(std::declval<C>().find(std::declval<std::add_rvalue_reference_t<typename C::key_type>>()))*); | ||
15798 | template <typename C> | ||
15799 | static two test(...); | ||
15800 | |||
15801 | public: | ||
15802 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15803 | }; | ||
15804 | |||
15805 | template <typename T> | ||
15806 | struct has_erase_test { | ||
15807 | private: | ||
15808 | typedef std::array<char, 1> one; | ||
15809 | typedef std::array<char, 2> two; | ||
15810 | |||
15811 | template <typename C> | ||
15812 | static one test(decltype(std::declval<C>().erase(std::declval<typename C::iterator>()))*); | ||
15813 | template <typename C> | ||
15814 | static two test(...); | ||
15815 | |||
15816 | public: | ||
15817 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15818 | }; | ||
15819 | |||
15820 | template <typename T> | ||
15821 | struct has_traits_find_test { | ||
15822 | private: | ||
15823 | typedef std::array<char, 1> one; | ||
15824 | typedef std::array<char, 2> two; | ||
15825 | |||
15826 | template <typename C> | ||
15827 | static one test(decltype(&C::find)); | ||
15828 | template <typename C> | ||
15829 | static two test(...); | ||
15830 | |||
15831 | public: | ||
15832 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15833 | }; | ||
15834 | |||
15835 | template <typename T> | ||
15836 | struct has_traits_insert_test { | ||
15837 | private: | ||
15838 | typedef std::array<char, 1> one; | ||
15839 | typedef std::array<char, 2> two; | ||
15840 | |||
15841 | template <typename C> | ||
15842 | static one test(decltype(&C::insert)); | ||
15843 | template <typename C> | ||
15844 | static two test(...); | ||
15845 | |||
15846 | public: | ||
15847 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15848 | }; | ||
15849 | |||
15850 | template <typename T> | ||
15851 | struct has_traits_erase_test { | ||
15852 | private: | ||
15853 | typedef std::array<char, 1> one; | ||
15854 | typedef std::array<char, 2> two; | ||
15855 | |||
15856 | template <typename C> | ||
15857 | static one test(decltype(&C::erase)); | ||
15858 | template <typename C> | ||
15859 | static two test(...); | ||
15860 | |||
15861 | public: | ||
15862 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15863 | }; | ||
15864 | |||
15865 | template <typename T> | ||
15866 | struct has_traits_index_set_test { | ||
15867 | private: | ||
15868 | typedef std::array<char, 1> one; | ||
15869 | typedef std::array<char, 2> two; | ||
15870 | |||
15871 | template <typename C> | ||
15872 | static one test(decltype(&C::index_set)); | ||
15873 | template <typename C> | ||
15874 | static two test(...); | ||
15875 | |||
15876 | public: | ||
15877 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15878 | }; | ||
15879 | |||
15880 | template <typename T> | ||
15881 | struct has_traits_index_get_test { | ||
15882 | private: | ||
15883 | typedef std::array<char, 1> one; | ||
15884 | typedef std::array<char, 2> two; | ||
15885 | |||
15886 | template <typename C> | ||
15887 | static one test(decltype(&C::index_get)); | ||
15888 | template <typename C> | ||
15889 | static two test(...); | ||
15890 | |||
15891 | public: | ||
15892 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15893 | }; | ||
15894 | |||
15895 | template <typename T> | ||
15896 | struct has_traits_set_test { | ||
15897 | private: | ||
15898 | typedef std::array<char, 1> one; | ||
15899 | typedef std::array<char, 2> two; | ||
15900 | |||
15901 | template <typename C> | ||
15902 | static one test(decltype(&C::set)); | ||
15903 | template <typename C> | ||
15904 | static two test(...); | ||
15905 | |||
15906 | public: | ||
15907 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15908 | }; | ||
15909 | |||
15910 | template <typename T> | ||
15911 | struct has_traits_get_test { | ||
15912 | private: | ||
15913 | typedef std::array<char, 1> one; | ||
15914 | typedef std::array<char, 2> two; | ||
15915 | |||
15916 | template <typename C> | ||
15917 | static one test(decltype(&C::get)); | ||
15918 | template <typename C> | ||
15919 | static two test(...); | ||
15920 | |||
15921 | public: | ||
15922 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15923 | }; | ||
15924 | |||
15925 | template <typename T> | ||
15926 | struct has_traits_at_test { | ||
15927 | private: | ||
15928 | typedef std::array<char, 1> one; | ||
15929 | typedef std::array<char, 2> two; | ||
15930 | |||
15931 | template <typename C> | ||
15932 | static one test(decltype(&C::at)); | ||
15933 | template <typename C> | ||
15934 | static two test(...); | ||
15935 | |||
15936 | public: | ||
15937 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15938 | }; | ||
15939 | |||
15940 | template <typename T> | ||
15941 | struct has_traits_pairs_test { | ||
15942 | private: | ||
15943 | typedef std::array<char, 1> one; | ||
15944 | typedef std::array<char, 2> two; | ||
15945 | |||
15946 | template <typename C> | ||
15947 | static one test(decltype(&C::pairs)); | ||
15948 | template <typename C> | ||
15949 | static two test(...); | ||
15950 | |||
15951 | public: | ||
15952 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15953 | }; | ||
15954 | |||
15955 | template <typename T> | ||
15956 | struct has_traits_ipairs_test { | ||
15957 | private: | ||
15958 | typedef std::array<char, 1> one; | ||
15959 | typedef std::array<char, 2> two; | ||
15960 | |||
15961 | template <typename C> | ||
15962 | static one test(decltype(&C::ipairs)); | ||
15963 | template <typename C> | ||
15964 | static two test(...); | ||
15965 | |||
15966 | public: | ||
15967 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15968 | }; | ||
15969 | |||
15970 | template <typename T> | ||
15971 | struct has_traits_next_test { | ||
15972 | private: | ||
15973 | typedef std::array<char, 1> one; | ||
15974 | typedef std::array<char, 2> two; | ||
15975 | |||
15976 | template <typename C> | ||
15977 | static one test(decltype(&C::next)); | ||
15978 | template <typename C> | ||
15979 | static two test(...); | ||
15980 | |||
15981 | public: | ||
15982 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15983 | }; | ||
15984 | |||
15985 | template <typename T> | ||
15986 | struct has_traits_add_test { | ||
15987 | private: | ||
15988 | typedef std::array<char, 1> one; | ||
15989 | typedef std::array<char, 2> two; | ||
15990 | |||
15991 | template <typename C> | ||
15992 | static one test(decltype(&C::add)); | ||
15993 | template <typename C> | ||
15994 | static two test(...); | ||
15995 | |||
15996 | public: | ||
15997 | static const bool value = sizeof(test<T>(0)) == sizeof(char); | ||
15998 | }; | ||
15999 | |||
16000 | template <typename T> | ||
16001 | using has_clear = meta::boolean<has_clear_test<T>::value>; | ||
16002 | |||
16003 | template <typename T> | ||
16004 | using has_empty = meta::boolean<has_empty_test<T>::value>; | ||
16005 | |||
16006 | template <typename T> | ||
16007 | using has_find = meta::boolean<has_find_test<T>::value>; | ||
16008 | |||
16009 | template <typename T> | ||
16010 | using has_erase = meta::boolean<has_erase_test<T>::value>; | ||
16011 | |||
16012 | template <typename T> | ||
16013 | using has_erase_after = meta::boolean<has_erase_after_test<T>::value>; | ||
16014 | |||
16015 | template <typename T> | ||
16016 | using has_traits_get = meta::boolean<has_traits_get_test<T>::value>; | ||
16017 | |||
16018 | template <typename T> | ||
16019 | using has_traits_at = meta::boolean<has_traits_at_test<T>::value>; | ||
16020 | |||
16021 | template <typename T> | ||
16022 | using has_traits_set = meta::boolean<has_traits_set_test<T>::value>; | ||
16023 | |||
16024 | template <typename T> | ||
16025 | using has_traits_index_get = meta::boolean<has_traits_index_get_test<T>::value>; | ||
16026 | |||
16027 | template <typename T> | ||
16028 | using has_traits_index_set = meta::boolean<has_traits_index_set_test<T>::value>; | ||
16029 | |||
16030 | template <typename T> | ||
16031 | using has_traits_pairs = meta::boolean<has_traits_pairs_test<T>::value>; | ||
16032 | |||
16033 | template <typename T> | ||
16034 | using has_traits_ipairs = meta::boolean<has_traits_ipairs_test<T>::value>; | ||
16035 | |||
16036 | template <typename T> | ||
16037 | using has_traits_next = meta::boolean<has_traits_next_test<T>::value>; | ||
16038 | |||
16039 | template <typename T> | ||
16040 | using has_traits_add = meta::boolean<has_traits_add_test<T>::value>; | ||
16041 | |||
16042 | template <typename T> | ||
16043 | using has_traits_size = meta::has_size<T>; | ||
16044 | |||
16045 | template <typename T> | ||
16046 | using has_traits_clear = has_clear<T>; | ||
16047 | |||
16048 | template <typename T> | ||
16049 | using has_traits_empty = has_empty<T>; | ||
16050 | |||
16051 | template <typename T> | ||
16052 | using has_traits_find = meta::boolean<has_traits_find_test<T>::value>; | ||
16053 | |||
16054 | template <typename T> | ||
16055 | using has_traits_insert = meta::boolean<has_traits_insert_test<T>::value>; | ||
16056 | |||
16057 | template <typename T> | ||
16058 | using has_traits_erase = meta::boolean<has_traits_erase_test<T>::value>; | ||
16059 | |||
16060 | template <typename T> | ||
16061 | struct is_forced_container : is_container<T> {}; | ||
16062 | |||
16063 | template <typename T> | ||
16064 | struct is_forced_container<as_container_t<T>> : std::true_type {}; | ||
16065 | |||
16066 | template <typename T> | ||
16067 | struct container_decay { | ||
16068 | typedef T type; | ||
16069 | }; | ||
16070 | |||
16071 | template <typename T> | ||
16072 | struct container_decay<as_container_t<T>> { | ||
16073 | typedef T type; | ||
16074 | }; | ||
16075 | |||
16076 | template <typename T> | ||
16077 | using container_decay_t = typename container_decay<meta::unqualified_t<T>>::type; | ||
16078 | |||
16079 | template <typename T> | ||
16080 | decltype(auto) get_key(std::false_type, T&& t) { | ||
16081 | return std::forward<T>(t); | ||
16082 | } | ||
16083 | |||
16084 | template <typename T> | ||
16085 | decltype(auto) get_key(std::true_type, T&& t) { | ||
16086 | return t.first; | ||
16087 | } | ||
16088 | |||
16089 | template <typename T> | ||
16090 | decltype(auto) get_value(std::false_type, T&& t) { | ||
16091 | return std::forward<T>(t); | ||
16092 | } | ||
16093 | |||
16094 | template <typename T> | ||
16095 | decltype(auto) get_value(std::true_type, T&& t) { | ||
16096 | return t.second; | ||
16097 | } | ||
16098 | |||
16099 | struct error_result { | ||
16100 | int results; | ||
16101 | const char* fmt; | ||
16102 | std::array<const char*, 4> args; | ||
16103 | |||
16104 | error_result() : results(0), fmt(nullptr) { | ||
16105 | } | ||
16106 | |||
16107 | error_result(int results) : results(results), fmt(nullptr) { | ||
16108 | } | ||
16109 | |||
16110 | error_result(const char* fmt, const char* msg) : results(0), fmt(fmt) { | ||
16111 | args[0] = msg; | ||
16112 | } | ||
16113 | }; | ||
16114 | |||
16115 | inline int handle_errors(lua_State* L, const error_result& er) { | ||
16116 | if (er.fmt == nullptr) { | ||
16117 | return er.results; | ||
16118 | } | ||
16119 | return luaL_error(L, er.fmt, er.args[0], er.args[1], er.args[2], er.args[3]); | ||
16120 | } | ||
16121 | |||
16122 | template <typename X, typename = void> | ||
16123 | struct container_traits_default { | ||
16124 | private: | ||
16125 | typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> T; | ||
16126 | |||
16127 | public: | ||
16128 | typedef lua_nil_t iterator; | ||
16129 | typedef lua_nil_t value_type; | ||
16130 | |||
16131 | static int at(lua_State* L) { | ||
16132 | return luaL_error(L, "sol: cannot call 'at(index)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16133 | } | ||
16134 | |||
16135 | static int get(lua_State* L) { | ||
16136 | return luaL_error(L, "sol: cannot call 'get(key)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16137 | } | ||
16138 | |||
16139 | static int index_get(lua_State* L) { | ||
16140 | return luaL_error(L, "sol: cannot call 'container[key]' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16141 | } | ||
16142 | |||
16143 | static int set(lua_State* L) { | ||
16144 | 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()); | ||
16145 | } | ||
16146 | |||
16147 | static int index_set(lua_State* L) { | ||
16148 | return luaL_error(L, "sol: cannot call 'container[key] = value' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16149 | } | ||
16150 | |||
16151 | static int add(lua_State* L) { | ||
16152 | return luaL_error(L, "sol: cannot call 'add' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16153 | } | ||
16154 | |||
16155 | static int insert(lua_State* L) { | ||
16156 | return luaL_error(L, "sol: cannot call 'insert' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16157 | } | ||
16158 | |||
16159 | static int find(lua_State* L) { | ||
16160 | return luaL_error(L, "sol: cannot call 'find' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16161 | } | ||
16162 | |||
16163 | static int size(lua_State* L) { | ||
16164 | return luaL_error(L, "sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16165 | } | ||
16166 | |||
16167 | static int clear(lua_State* L) { | ||
16168 | return luaL_error(L, "sol: cannot call 'clear' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16169 | } | ||
16170 | |||
16171 | static int empty(lua_State* L) { | ||
16172 | return luaL_error(L, "sol: cannot call 'empty' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16173 | } | ||
16174 | |||
16175 | static int erase(lua_State* L) { | ||
16176 | return luaL_error(L, "sol: cannot call 'erase' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16177 | } | ||
16178 | |||
16179 | static int next(lua_State* L) { | ||
16180 | return luaL_error(L, "sol: cannot call 'next' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16181 | } | ||
16182 | |||
16183 | static int pairs(lua_State* L) { | ||
16184 | return luaL_error(L, "sol: cannot call '__pairs/pairs' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16185 | } | ||
16186 | |||
16187 | static int ipairs(lua_State* L) { | ||
16188 | return luaL_error(L, "sol: cannot call '__ipairs' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16189 | } | ||
16190 | |||
16191 | static iterator begin(lua_State* L, T&) { | ||
16192 | luaL_error(L, "sol: cannot call 'being' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16193 | return lua_nil; | ||
16194 | } | ||
16195 | |||
16196 | static iterator end(lua_State* L, T&) { | ||
16197 | luaL_error(L, "sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); | ||
16198 | return lua_nil; | ||
16199 | } | ||
16200 | }; | ||
16201 | |||
16202 | template <typename X> | ||
16203 | struct container_traits_default<X, std::enable_if_t<meta::all<is_forced_container<meta::unqualified_t<X>>, meta::has_value_type<meta::unqualified_t<container_decay_t<X>>>, meta::has_iterator<meta::unqualified_t<container_decay_t<X>>>>::value>> { | ||
16204 | private: | ||
16205 | typedef std::remove_pointer_t<meta::unwrap_unqualified_t<container_decay_t<X>>> T; | ||
16206 | |||
16207 | private: | ||
16208 | typedef container_traits<X> deferred_traits; | ||
16209 | typedef meta::is_associative<T> is_associative; | ||
16210 | typedef meta::is_lookup<T> is_lookup; | ||
16211 | typedef meta::is_matched_lookup<T> is_matched_lookup; | ||
16212 | typedef typename T::iterator iterator; | ||
16213 | typedef typename T::value_type value_type; | ||
16214 | typedef std::conditional_t<is_matched_lookup::value, | ||
16215 | std::pair<value_type, value_type>, | ||
16216 | std::conditional_t<is_associative::value || is_lookup::value, | ||
16217 | value_type, | ||
16218 | std::pair<std::ptrdiff_t, value_type> | ||
16219 | > | ||
16220 | > KV; | ||
16221 | typedef typename KV::first_type K; | ||
16222 | typedef typename KV::second_type V; | ||
16223 | typedef std::conditional_t<is_matched_lookup::value, std::ptrdiff_t, K> next_K; | ||
16224 | typedef decltype(*std::declval<iterator&>()) iterator_return; | ||
16225 | typedef std::conditional_t<is_associative::value || is_matched_lookup::value, | ||
16226 | std::add_lvalue_reference_t<V>, | ||
16227 | std::conditional_t<is_lookup::value, | ||
16228 | V, | ||
16229 | iterator_return | ||
16230 | > | ||
16231 | > captured_type; | ||
16232 | typedef typename meta::iterator_tag<iterator>::type iterator_category; | ||
16233 | typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator; | ||
16234 | typedef std::conditional_t<is_input_iterator::value, | ||
16235 | V, | ||
16236 | decltype(detail::deref_non_pointer(std::declval<captured_type>())) | ||
16237 | > push_type; | ||
16238 | typedef std::is_copy_assignable<V> is_copyable; | ||
16239 | typedef meta::neg<meta::any< | ||
16240 | std::is_const<V>, std::is_const<std::remove_reference_t<iterator_return>>, meta::neg<is_copyable> | ||
16241 | >> is_writable; | ||
16242 | typedef meta::unqualified_t<decltype(get_key(is_associative(), std::declval<std::add_lvalue_reference_t<value_type>>()))> key_type; | ||
16243 | typedef meta::all<std::is_integral<K>, meta::neg<meta::any<is_associative, is_lookup>>> is_linear_integral; | ||
16244 | |||
16245 | struct iter { | ||
16246 | T& source; | ||
16247 | iterator it; | ||
16248 | std::size_t i; | ||
16249 | |||
16250 | iter(T& source, iterator it) | ||
16251 | : source(source), it(std::move(it)), i(0) { | ||
16252 | } | ||
16253 | }; | ||
16254 | |||
16255 | static auto& get_src(lua_State* L) { | ||
16256 | #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE | ||
16257 | auto p = stack::check_get<T*>(L, 1); | ||
16258 | if (!p) { | ||
16259 | luaL_error(L, "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle<T>().c_str()); | ||
16260 | } | ||
16261 | if (p.value() == nullptr) { | ||
16262 | luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle<T>().c_str()); | ||
16263 | } | ||
16264 | return *p.value(); | ||
16265 | #else | ||
16266 | return stack::get<T>(L, 1); | ||
16267 | #endif // Safe getting with error | ||
16268 | } | ||
16269 | |||
16270 | static error_result at_category(std::input_iterator_tag, lua_State* L, T& self, std::ptrdiff_t pos) { | ||
16271 | pos += deferred_traits::index_adjustment(L, self); | ||
16272 | if (pos < 0) { | ||
16273 | return stack::push(L, lua_nil); | ||
16274 | } | ||
16275 | auto it = deferred_traits::begin(L, self); | ||
16276 | auto e = deferred_traits::end(L, self); | ||
16277 | if (it == e) { | ||
16278 | return stack::push(L, lua_nil); | ||
16279 | } | ||
16280 | while (pos > 0) { | ||
16281 | --pos; | ||
16282 | ++it; | ||
16283 | if (it == e) { | ||
16284 | return stack::push(L, lua_nil); | ||
16285 | } | ||
16286 | } | ||
16287 | return get_associative(is_associative(), L, it); | ||
16288 | } | ||
16289 | |||
16290 | static error_result at_category(std::random_access_iterator_tag, lua_State* L, T& self, std::ptrdiff_t pos) { | ||
16291 | std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self)); | ||
16292 | pos += deferred_traits::index_adjustment(L, self); | ||
16293 | if (pos < 0 || pos >= len) { | ||
16294 | return stack::push(L, lua_nil); | ||
16295 | } | ||
16296 | auto it = std::next(deferred_traits::begin(L, self), pos); | ||
16297 | return get_associative(is_associative(), L, it); | ||
16298 | } | ||
16299 | |||
16300 | static error_result at_start(lua_State* L, T& self, std::ptrdiff_t pos) { | ||
16301 | return at_category(iterator_category(), L, self, pos); | ||
16302 | } | ||
16303 | |||
16304 | static error_result get_associative(std::true_type, lua_State* L, iterator& it) { | ||
16305 | auto& v = *it; | ||
16306 | return stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(v.second)); | ||
16307 | } | ||
16308 | |||
16309 | static error_result get_associative(std::false_type, lua_State* L, iterator& it) { | ||
16310 | return stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(*it)); | ||
16311 | } | ||
16312 | |||
16313 | static error_result get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) { | ||
16314 | key += deferred_traits::index_adjustment(L, self); | ||
16315 | if (key < 0) { | ||
16316 | return stack::push(L, lua_nil); | ||
16317 | } | ||
16318 | auto it = deferred_traits::begin(L, self); | ||
16319 | auto e = deferred_traits::end(L, self); | ||
16320 | if (it == e) { | ||
16321 | return stack::push(L, lua_nil); | ||
16322 | } | ||
16323 | while (key > 0) { | ||
16324 | --key; | ||
16325 | ++it; | ||
16326 | if (it == e) { | ||
16327 | return stack::push(L, lua_nil); | ||
16328 | } | ||
16329 | } | ||
16330 | return get_associative(is_associative(), L, it); | ||
16331 | } | ||
16332 | |||
16333 | static error_result get_category(std::random_access_iterator_tag, lua_State* L, T& self, K& key) { | ||
16334 | std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self)); | ||
16335 | key += deferred_traits::index_adjustment(L, self); | ||
16336 | if (key < 0 || key >= len) { | ||
16337 | return stack::push(L, lua_nil); | ||
16338 | } | ||
16339 | auto it = std::next(deferred_traits::begin(L, self), key); | ||
16340 | return get_associative(is_associative(), L, it); | ||
16341 | } | ||
16342 | |||
16343 | static error_result get_it(std::true_type, lua_State* L, T& self, K& key) { | ||
16344 | return get_category(iterator_category(), L, self, key); | ||
16345 | } | ||
16346 | |||
16347 | static error_result get_comparative(std::true_type, lua_State* L, T& self, K& key) { | ||
16348 | auto fx = [&](const value_type& r) -> bool { | ||
16349 | return key == get_key(is_associative(), r); | ||
16350 | }; | ||
16351 | auto e = deferred_traits::end(L, self); | ||
16352 | auto it = std::find_if(deferred_traits::begin(L, self), e, std::ref(fx)); | ||
16353 | if (it == e) { | ||
16354 | return stack::push(L, lua_nil); | ||
16355 | } | ||
16356 | return get_associative(is_associative(), L, it); | ||
16357 | } | ||
16358 | |||
16359 | static error_result get_comparative(std::false_type, lua_State*, T&, K&) { | ||
16360 | return error_result("cannot get this key on '%s': no suitable way to increment iterator and compare to key value '%s'", detail::demangle<T>().data(), detail::demangle<K>().data()); | ||
16361 | } | ||
16362 | |||
16363 | static error_result get_it(std::false_type, lua_State* L, T& self, K& key) { | ||
16364 | return get_comparative(meta::supports_op_equal<K, key_type>(), L, self, key); | ||
16365 | } | ||
16366 | |||
16367 | static error_result set_associative(std::true_type, iterator& it, stack_object value) { | ||
16368 | auto& v = *it; | ||
16369 | v.second = value.as<V>(); | ||
16370 | return {}; | ||
16371 | } | ||
16372 | |||
16373 | static error_result set_associative(std::false_type, iterator& it, stack_object value) { | ||
16374 | auto& v = *it; | ||
16375 | v = value.as<V>(); | ||
16376 | return {}; | ||
16377 | } | ||
16378 | |||
16379 | static error_result set_writable(std::true_type, lua_State*, T&, iterator& it, stack_object value) { | ||
16380 | return set_associative(is_associative(), it, std::move(value)); | ||
16381 | } | ||
16382 | |||
16383 | static error_result set_writable(std::false_type, lua_State*, T&, iterator&, stack_object) { | ||
16384 | return error_result("cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle<T>().data()); | ||
16385 | } | ||
16386 | |||
16387 | static error_result set_category(std::input_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) { | ||
16388 | decltype(auto) key = okey.as<K>(); | ||
16389 | key += deferred_traits::index_adjustment(L, self); | ||
16390 | auto e = deferred_traits::end(L, self); | ||
16391 | auto it = deferred_traits::begin(L, self); | ||
16392 | auto backit = it; | ||
16393 | for (; key > 0 && it != e; --key, ++it) { | ||
16394 | backit = it; | ||
16395 | } | ||
16396 | if (it == e) { | ||
16397 | if (key == 0) { | ||
16398 | return add_copyable(is_copyable(), L, self, std::move(value), meta::has_insert_after<T>::value ? backit : it); | ||
16399 | } | ||
16400 | return error_result("out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str()); | ||
16401 | } | ||
16402 | return set_writable(is_writable(), L, self, it, std::move(value)); | ||
16403 | } | ||
16404 | |||
16405 | static error_result set_category(std::random_access_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) { | ||
16406 | decltype(auto) key = okey.as<K>(); | ||
16407 | if (key <= 0) { | ||
16408 | return error_result("sol: out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str()); | ||
16409 | } | ||
16410 | key += deferred_traits::index_adjustment(L, self); | ||
16411 | std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self)); | ||
16412 | if (key == len) { | ||
16413 | return add_copyable(is_copyable(), L, self, std::move(value)); | ||
16414 | } | ||
16415 | else if (key > len) { | ||
16416 | return error_result("sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str()); | ||
16417 | } | ||
16418 | auto it = std::next(deferred_traits::begin(L, self), key); | ||
16419 | return set_writable(is_writable(), L, self, it, std::move(value)); | ||
16420 | } | ||
16421 | |||
16422 | static error_result set_comparative(std::true_type, lua_State* L, T& self, stack_object okey, stack_object value) { | ||
16423 | decltype(auto) key = okey.as<K>(); | ||
16424 | if (!is_writable::value) { | ||
16425 | return error_result("cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle<T>().data()); | ||
16426 | } | ||
16427 | auto fx = [&](const value_type& r) -> bool { | ||
16428 | return key == get_key(is_associative(), r); | ||
16429 | }; | ||
16430 | auto e = deferred_traits::end(L, self); | ||
16431 | auto it = std::find_if(deferred_traits::begin(L, self), e, std::ref(fx)); | ||
16432 | if (it == e) { | ||
16433 | return {}; | ||
16434 | } | ||
16435 | return set_writable(is_writable(), L, self, it, std::move(value)); | ||
16436 | } | ||
16437 | |||
16438 | static error_result set_comparative(std::false_type, lua_State*, T&, stack_object, stack_object) { | ||
16439 | return error_result("cannot set this value on '%s': no suitable way to increment iterator or compare to '%s' key", detail::demangle<T>().data(), detail::demangle<K>().data()); | ||
16440 | } | ||
16441 | |||
16442 | static error_result set_associative_insert(std::true_type, lua_State*, T& self, iterator& it, K& key, stack_object value) { | ||
16443 | self.insert(it, value_type(key, value.as<V>())); | ||
16444 | return {}; | ||
16445 | } | ||
16446 | |||
16447 | static error_result set_associative_insert(std::false_type, lua_State*, T& self, iterator& it, K& key, stack_object) { | ||
16448 | self.insert(it, key); | ||
16449 | return {}; | ||
16450 | } | ||
16451 | |||
16452 | static error_result set_associative_find(std::true_type, lua_State* L, T& self, stack_object okey, stack_object value) { | ||
16453 | decltype(auto) key = okey.as<K>(); | ||
16454 | auto it = self.find(key); | ||
16455 | if (it == deferred_traits::end(L, self)) { | ||
16456 | return set_associative_insert(is_associative(), L, self, it, key, std::move(value)); | ||
16457 | } | ||
16458 | return set_writable(is_writable(), L, self, it, std::move(value)); | ||
16459 | } | ||
16460 | |||
16461 | static error_result set_associative_find(std::false_type, lua_State* L, T& self, stack_object key, stack_object value) { | ||
16462 | return set_comparative(meta::supports_op_equal<K, key_type>(), L, self, std::move(key), std::move(value)); | ||
16463 | } | ||
16464 | |||
16465 | static error_result set_it(std::true_type, lua_State* L, T& self, stack_object key, stack_object value) { | ||
16466 | return set_category(iterator_category(), L, self, std::move(key), std::move(value)); | ||
16467 | } | ||
16468 | |||
16469 | static error_result set_it(std::false_type, lua_State* L, T& self, stack_object key, stack_object value) { | ||
16470 | return set_associative_find(meta::all<has_find<T>, meta::any<is_associative, is_lookup>>(), L, self, std::move(key), std::move(value)); | ||
16471 | } | ||
16472 | |||
16473 | static error_result find_has_associative_lookup(std::true_type, lua_State* L, T& self) { | ||
16474 | decltype(auto) key = stack::get<K>(L, 2); | ||
16475 | auto it = self.find(key); | ||
16476 | if (it == deferred_traits::end(L, self)) { | ||
16477 | return stack::push(L, lua_nil); | ||
16478 | } | ||
16479 | return get_associative(is_associative(), L, it); | ||
16480 | } | ||
16481 | |||
16482 | static error_result find_has_associative_lookup(std::false_type, lua_State* L, T& self) { | ||
16483 | decltype(auto) value = stack::get<V>(L, 2); | ||
16484 | auto it = self.find(value); | ||
16485 | if (it == deferred_traits::end(L, self)) { | ||
16486 | return stack::push(L, lua_nil); | ||
16487 | } | ||
16488 | return get_associative(is_associative(), L, it); | ||
16489 | } | ||
16490 | |||
16491 | static error_result find_has(std::true_type, lua_State* L, T& self) { | ||
16492 | return find_has_associative_lookup(meta::any<is_lookup, is_associative>(), L, self); | ||
16493 | } | ||
16494 | |||
16495 | static error_result find_associative_lookup(std::true_type, lua_State* L, iterator& it, std::size_t) { | ||
16496 | return get_associative(is_associative(), L, it); | ||
16497 | } | ||
16498 | |||
16499 | static error_result find_associative_lookup(std::false_type, lua_State* L, iterator&, std::size_t index) { | ||
16500 | return stack::push(L, index); | ||
16501 | } | ||
16502 | |||
16503 | static error_result find_comparative(std::false_type, lua_State*, T&) { | ||
16504 | return error_result("cannot call 'find' on '%s': there is no 'find' function and the value_type is not equality comparable", detail::demangle<T>().c_str()); | ||
16505 | } | ||
16506 | |||
16507 | static error_result find_comparative(std::true_type, lua_State* L, T& self) { | ||
16508 | decltype(auto) value = stack::get<V>(L, 2); | ||
16509 | auto it = deferred_traits::begin(L, self); | ||
16510 | auto e = deferred_traits::end(L, self); | ||
16511 | std::size_t index = 1; | ||
16512 | for (;; ++it, ++index) { | ||
16513 | if (it == e) { | ||
16514 | return stack::push(L, lua_nil); | ||
16515 | } | ||
16516 | if (value == get_value(is_associative(), *it)) { | ||
16517 | break; | ||
16518 | } | ||
16519 | } | ||
16520 | return find_associative_lookup(meta::any<is_lookup, is_associative>(), L, it, index); | ||
16521 | } | ||
16522 | |||
16523 | static error_result find_has(std::false_type, lua_State* L, T& self) { | ||
16524 | return find_comparative(meta::supports_op_equal<V>(), L, self); | ||
16525 | } | ||
16526 | |||
16527 | static error_result add_insert_after(std::false_type, lua_State* L, T& self, stack_object value, iterator&) { | ||
16528 | return add_insert_after(std::false_type(), L, self, value); | ||
16529 | } | ||
16530 | |||
16531 | static error_result add_insert_after(std::false_type, lua_State*, T&, stack_object) { | ||
16532 | return error_result("cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", detail::demangle<T>().data()); | ||
16533 | } | ||
16534 | |||
16535 | static error_result add_insert_after(std::true_type, lua_State*, T& self, stack_object value, iterator& pos) { | ||
16536 | self.insert_after(pos, value.as<V>()); | ||
16537 | return {}; | ||
16538 | } | ||
16539 | |||
16540 | static error_result add_insert_after(std::true_type, lua_State* L, T& self, stack_object value) { | ||
16541 | auto backit = self.before_begin(); | ||
16542 | { | ||
16543 | auto e = deferred_traits::end(L, self); | ||
16544 | for (auto it = deferred_traits::begin(L, self); it != e; ++backit, ++it) { | ||
16545 | } | ||
16546 | } | ||
16547 | return add_insert_after(std::true_type(), L, self, value, backit); | ||
16548 | } | ||
16549 | |||
16550 | static error_result add_insert(std::true_type, lua_State*, T& self, stack_object value, iterator& pos) { | ||
16551 | self.insert(pos, value.as<V>()); | ||
16552 | return {}; | ||
16553 | } | ||
16554 | |||
16555 | static error_result add_insert(std::true_type, lua_State* L, T& self, stack_object value) { | ||
16556 | auto pos = deferred_traits::end(L, self); | ||
16557 | return add_insert(std::true_type(), L, self, value, pos); | ||
16558 | } | ||
16559 | |||
16560 | static error_result add_insert(std::false_type, lua_State* L, T& self, stack_object value, iterator& pos) { | ||
16561 | return add_insert_after(meta::has_insert_after<T>(), L, self, std::move(value), pos); | ||
16562 | } | ||
16563 | |||
16564 | static error_result add_insert(std::false_type, lua_State* L, T& self, stack_object value) { | ||
16565 | return add_insert_after(meta::has_insert_after<T>(), L, self, std::move(value)); | ||
16566 | } | ||
16567 | |||
16568 | static error_result add_push_back(std::true_type, lua_State*, T& self, stack_object value, iterator&) { | ||
16569 | self.push_back(value.as<V>()); | ||
16570 | return {}; | ||
16571 | } | ||
16572 | |||
16573 | static error_result add_push_back(std::true_type, lua_State*, T& self, stack_object value) { | ||
16574 | self.push_back(value.as<V>()); | ||
16575 | return {}; | ||
16576 | } | ||
16577 | |||
16578 | static error_result add_push_back(std::false_type, lua_State* L, T& self, stack_object value, iterator& pos) { | ||
16579 | return add_insert(meta::has_insert<T>(), L, self, value, pos); | ||
16580 | } | ||
16581 | |||
16582 | static error_result add_push_back(std::false_type, lua_State* L, T& self, stack_object value) { | ||
16583 | return add_insert(meta::has_insert<T>(), L, self, value); | ||
16584 | } | ||
16585 | |||
16586 | static error_result add_associative(std::true_type, lua_State* L, T& self, stack_object key, iterator& pos) { | ||
16587 | self.insert(pos, value_type(key.as<K>(), stack::get<V>(L, 3))); | ||
16588 | return {}; | ||
16589 | } | ||
16590 | |||
16591 | static error_result add_associative(std::true_type, lua_State* L, T& self, stack_object key) { | ||
16592 | auto pos = deferred_traits::end(L, self); | ||
16593 | return add_associative(std::true_type(), L, self, std::move(key), pos); | ||
16594 | } | ||
16595 | |||
16596 | static error_result add_associative(std::false_type, lua_State* L, T& self, stack_object value, iterator& pos) { | ||
16597 | return add_push_back(meta::has_push_back<T>(), L, self, value, pos); | ||
16598 | } | ||
16599 | |||
16600 | static error_result add_associative(std::false_type, lua_State* L, T& self, stack_object value) { | ||
16601 | return add_push_back(meta::has_push_back<T>(), L, self, value); | ||
16602 | } | ||
16603 | |||
16604 | static error_result add_copyable(std::true_type, lua_State* L, T& self, stack_object value, iterator& pos) { | ||
16605 | return add_associative(is_associative(), L, self, std::move(value), pos); | ||
16606 | } | ||
16607 | |||
16608 | static error_result add_copyable(std::true_type, lua_State* L, T& self, stack_object value) { | ||
16609 | return add_associative(is_associative(), L, self, value); | ||
16610 | } | ||
16611 | |||
16612 | static error_result add_copyable(std::false_type, lua_State* L, T& self, stack_object value, iterator&) { | ||
16613 | return add_copyable(std::false_type(), L, self, std::move(value)); | ||
16614 | } | ||
16615 | |||
16616 | static error_result add_copyable(std::false_type, lua_State*, T&, stack_object) { | ||
16617 | return error_result("cannot call 'add' on '%s': value_type is non-copyable", detail::demangle<T>().data()); | ||
16618 | } | ||
16619 | |||
16620 | static error_result insert_lookup(std::true_type, lua_State* L, T& self, stack_object, stack_object value) { | ||
16621 | // TODO: should we warn or error about someone calling insert on an ordered / lookup container with no associativity? | ||
16622 | return add_copyable(std::true_type(), L, self, std::move(value)); | ||
16623 | } | ||
16624 | |||
16625 | static error_result insert_lookup(std::false_type, lua_State* L, T& self, stack_object where, stack_object value) { | ||
16626 | auto it = deferred_traits::begin(L, self); | ||
16627 | auto key = where.as<K>(); | ||
16628 | key += deferred_traits::index_adjustment(L, self); | ||
16629 | std::advance(it, key); | ||
16630 | self.insert(it, value.as<V>()); | ||
16631 | return {}; | ||
16632 | } | ||
16633 | |||
16634 | static error_result insert_after_has(std::true_type, lua_State* L, T& self, stack_object where, stack_object value) { | ||
16635 | auto key = where.as<K>(); | ||
16636 | auto backit = self.before_begin(); | ||
16637 | { | ||
16638 | key += deferred_traits::index_adjustment(L, self); | ||
16639 | auto e = deferred_traits::end(L, self); | ||
16640 | for (auto it = deferred_traits::begin(L, self); key > 0; ++backit, ++it, --key) { | ||
16641 | if (backit == e) { | ||
16642 | return error_result("sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str()); | ||
16643 | } | ||
16644 | } | ||
16645 | } | ||
16646 | self.insert_after(backit, value.as<V>()); | ||
16647 | return {}; | ||
16648 | } | ||
16649 | |||
16650 | static error_result insert_after_has(std::false_type, lua_State*, T&, stack_object, stack_object) { | ||
16651 | return error_result("cannot call 'insert' on '%s': no suitable or similar functionality detected on this container", detail::demangle<T>().data()); | ||
16652 | } | ||
16653 | |||
16654 | static error_result insert_has(std::true_type, lua_State* L, T& self, stack_object key, stack_object value) { | ||
16655 | return insert_lookup(meta::any<is_associative, is_lookup>(), L, self, std::move(key), std::move(value)); | ||
16656 | } | ||
16657 | |||
16658 | static error_result insert_has(std::false_type, lua_State* L, T& self, stack_object where, stack_object value) { | ||
16659 | return insert_after_has(meta::has_insert_after<T>(), L, self, where, value); | ||
16660 | } | ||
16661 | |||
16662 | static error_result insert_copyable(std::true_type, lua_State* L, T& self, stack_object key, stack_object value) { | ||
16663 | return insert_has(meta::has_insert<T>(), L, self, std::move(key), std::move(value)); | ||
16664 | } | ||
16665 | |||
16666 | static error_result insert_copyable(std::false_type, lua_State*, T&, stack_object, stack_object) { | ||
16667 | return error_result("cannot call 'insert' on '%s': value_type is non-copyable", detail::demangle<T>().data()); | ||
16668 | } | ||
16669 | |||
16670 | static error_result erase_integral(std::true_type, lua_State* L, T& self, K& key) { | ||
16671 | auto it = deferred_traits::begin(L, self); | ||
16672 | key += deferred_traits::index_adjustment(L, self); | ||
16673 | std::advance(it, key); | ||
16674 | self.erase(it); | ||
16675 | |||
16676 | return {}; | ||
16677 | } | ||
16678 | |||
16679 | static error_result erase_integral(std::false_type, lua_State* L, T& self, const K& key) { | ||
16680 | auto fx = [&](const value_type& r) -> bool { | ||
16681 | return key == r; | ||
16682 | }; | ||
16683 | auto e = deferred_traits::end(L, self); | ||
16684 | auto it = std::find_if(deferred_traits::begin(L, self), e, std::ref(fx)); | ||
16685 | if (it == e) { | ||
16686 | return {}; | ||
16687 | } | ||
16688 | self.erase(it); | ||
16689 | |||
16690 | return {}; | ||
16691 | } | ||
16692 | |||
16693 | static error_result erase_associative_lookup(std::true_type, lua_State*, T& self, const K& key) { | ||
16694 | self.erase(key); | ||
16695 | return {}; | ||
16696 | } | ||
16697 | |||
16698 | static error_result erase_associative_lookup(std::false_type, lua_State* L, T& self, K& key) { | ||
16699 | return erase_integral(std::is_integral<K>(), L, self, key); | ||
16700 | } | ||
16701 | |||
16702 | static error_result erase_after_has(std::true_type, lua_State* L, T& self, K& key) { | ||
16703 | auto backit = self.before_begin(); | ||
16704 | { | ||
16705 | key += deferred_traits::index_adjustment(L, self); | ||
16706 | auto e = deferred_traits::end(L, self); | ||
16707 | for (auto it = deferred_traits::begin(L, self); key > 0; ++backit, ++it, --key) { | ||
16708 | if (backit == e) { | ||
16709 | return error_result("sol: out of bounds for erase on '%s'", detail::demangle<T>().c_str()); | ||
16710 | } | ||
16711 | } | ||
16712 | } | ||
16713 | self.erase_after(backit); | ||
16714 | return {}; | ||
16715 | } | ||
16716 | |||
16717 | static error_result erase_after_has(std::false_type, lua_State*, T&, const K&) { | ||
16718 | return error_result("sol: cannot call erase on '%s'", detail::demangle<T>().c_str()); | ||
16719 | } | ||
16720 | |||
16721 | static error_result erase_has(std::true_type, lua_State* L, T& self, K& key) { | ||
16722 | return erase_associative_lookup(meta::any<is_associative, is_lookup>(), L, self, key); | ||
16723 | } | ||
16724 | |||
16725 | static error_result erase_has(std::false_type, lua_State* L, T& self, K& key) { | ||
16726 | return erase_after_has(has_erase_after<T>(), L, self, key); | ||
16727 | } | ||
16728 | |||
16729 | static auto size_has(std::false_type, lua_State* L, T& self) { | ||
16730 | return std::distance(deferred_traits::begin(L, self), deferred_traits::end(L, self)); | ||
16731 | } | ||
16732 | |||
16733 | static auto size_has(std::true_type, lua_State*, T& self) { | ||
16734 | return self.size(); | ||
16735 | } | ||
16736 | |||
16737 | static void clear_has(std::true_type, lua_State*, T& self) { | ||
16738 | self.clear(); | ||
16739 | } | ||
16740 | |||
16741 | static void clear_has(std::false_type, lua_State* L, T&) { | ||
16742 | luaL_error(L, "sol: cannot call clear on '%s'", detail::demangle<T>().c_str()); | ||
16743 | } | ||
16744 | |||
16745 | static bool empty_has(std::true_type, lua_State*, T& self) { | ||
16746 | return self.empty(); | ||
16747 | } | ||
16748 | |||
16749 | static bool empty_has(std::false_type, lua_State* L, T& self) { | ||
16750 | return deferred_traits::begin(L, self) == deferred_traits::end(L, self); | ||
16751 | } | ||
16752 | |||
16753 | static error_result get_start(lua_State* L, T& self, K& key) { | ||
16754 | return get_it(is_linear_integral(), L, self, key); | ||
16755 | } | ||
16756 | |||
16757 | static error_result set_start(lua_State* L, T& self, stack_object key, stack_object value) { | ||
16758 | return set_it(is_linear_integral(), L, self, std::move(key), std::move(value)); | ||
16759 | } | ||
16760 | |||
16761 | static std::size_t size_start(lua_State* L, T& self) { | ||
16762 | return size_has(meta::has_size<T>(), L, self); | ||
16763 | } | ||
16764 | |||
16765 | static void clear_start(lua_State* L, T& self) { | ||
16766 | clear_has(has_clear<T>(), L, self); | ||
16767 | } | ||
16768 | |||
16769 | static bool empty_start(lua_State* L, T& self) { | ||
16770 | return empty_has(has_empty<T>(), L, self); | ||
16771 | } | ||
16772 | |||
16773 | static error_result erase_start(lua_State* L, T& self, K& key) { | ||
16774 | return erase_has(has_erase<T>(), L, self, key); | ||
16775 | } | ||
16776 | |||
16777 | template <bool ip> | ||
16778 | static int next_associative(std::true_type, lua_State* L) { | ||
16779 | iter& i = stack::get<user<iter>>(L, 1); | ||
16780 | auto& source = i.source; | ||
16781 | auto& it = i.it; | ||
16782 | if (it == deferred_traits::end(L, source)) { | ||
16783 | return 0; | ||
16784 | } | ||
16785 | int p; | ||
16786 | if (ip) { | ||
16787 | ++i.i; | ||
16788 | p = stack::push_reference(L, i.i); | ||
16789 | } | ||
16790 | else { | ||
16791 | p = stack::push_reference(L, it->first); | ||
16792 | } | ||
16793 | p += stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(it->second)); | ||
16794 | std::advance(it, 1); | ||
16795 | return p; | ||
16796 | } | ||
16797 | |||
16798 | template <bool> | ||
16799 | static int next_associative(std::false_type, lua_State* L) { | ||
16800 | iter& i = stack::get<user<iter>>(L, 1); | ||
16801 | auto& source = i.source; | ||
16802 | auto& it = i.it; | ||
16803 | next_K k = stack::get<next_K>(L, 2); | ||
16804 | if (it == deferred_traits::end(L, source)) { | ||
16805 | return 0; | ||
16806 | } | ||
16807 | int p; | ||
16808 | p = stack::push_reference(L, k + 1); | ||
16809 | p += stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(*it)); | ||
16810 | std::advance(it, 1); | ||
16811 | return p; | ||
16812 | } | ||
16813 | |||
16814 | template <bool ip> | ||
16815 | static int next_iter(lua_State* L) { | ||
16816 | typedef meta::any<is_associative, meta::all<is_lookup, meta::neg<is_matched_lookup>>> is_assoc; | ||
16817 | return next_associative<ip>(is_assoc(), L); | ||
16818 | } | ||
16819 | |||
16820 | template <bool ip> | ||
16821 | static int pairs_associative(std::true_type, lua_State* L) { | ||
16822 | auto& src = get_src(L); | ||
16823 | stack::push(L, next_iter<ip>); | ||
16824 | stack::push<user<iter>>(L, src, deferred_traits::begin(L, src)); | ||
16825 | stack::push(L, lua_nil); | ||
16826 | return 3; | ||
16827 | } | ||
16828 | |||
16829 | template <bool ip> | ||
16830 | static int pairs_associative(std::false_type, lua_State* L) { | ||
16831 | auto& src = get_src(L); | ||
16832 | stack::push(L, next_iter<ip>); | ||
16833 | stack::push<user<iter>>(L, src, deferred_traits::begin(L, src)); | ||
16834 | stack::push(L, 0); | ||
16835 | return 3; | ||
16836 | } | ||
16837 | |||
16838 | public: | ||
16839 | static int at(lua_State* L) { | ||
16840 | auto& self = get_src(L); | ||
16841 | error_result er; | ||
16842 | { | ||
16843 | std::ptrdiff_t pos = stack::get<std::ptrdiff_t>(L); | ||
16844 | er = at_start(L, self, pos); | ||
16845 | } | ||
16846 | return handle_errors(L, er); | ||
16847 | } | ||
16848 | |||
16849 | static int get(lua_State* L) { | ||
16850 | auto& self = get_src(L); | ||
16851 | error_result er; | ||
16852 | { | ||
16853 | decltype(auto) key = stack::get<K>(L); | ||
16854 | er = get_start(L, self, key); | ||
16855 | } | ||
16856 | return handle_errors(L, er); | ||
16857 | } | ||
16858 | |||
16859 | static int index_get(lua_State* L) { | ||
16860 | return get(L); | ||
16861 | } | ||
16862 | |||
16863 | static int set(lua_State* L) { | ||
16864 | stack_object value = stack_object(L, raw_index(3)); | ||
16865 | if (type_of(L, 3) == type::lua_nil) { | ||
16866 | return erase(L); | ||
16867 | } | ||
16868 | auto& self = get_src(L); | ||
16869 | error_result er = set_start(L, self, stack_object(L, raw_index(2)), std::move(value)); | ||
16870 | return handle_errors(L, er); | ||
16871 | } | ||
16872 | |||
16873 | static int index_set(lua_State* L) { | ||
16874 | return set(L); | ||
16875 | } | ||
16876 | |||
16877 | static int add(lua_State* L) { | ||
16878 | auto& self = get_src(L); | ||
16879 | error_result er = add_copyable(is_copyable(), L, self, stack_object(L, raw_index(2))); | ||
16880 | return handle_errors(L, er); | ||
16881 | } | ||
16882 | |||
16883 | static int insert(lua_State* L) { | ||
16884 | auto& self = get_src(L); | ||
16885 | error_result er = insert_copyable(is_copyable(), L, self, stack_object(L, raw_index(2)), stack_object(L, raw_index(3))); | ||
16886 | return handle_errors(L, er); | ||
16887 | } | ||
16888 | |||
16889 | static int find(lua_State* L) { | ||
16890 | auto& self = get_src(L); | ||
16891 | error_result er = find_has(has_find<T>(), L, self); | ||
16892 | return handle_errors(L, er); | ||
16893 | } | ||
16894 | |||
16895 | static iterator begin(lua_State*, T& self) { | ||
16896 | using std::begin; | ||
16897 | return begin(self); | ||
16898 | } | ||
16899 | |||
16900 | static iterator end(lua_State*, T& self) { | ||
16901 | using std::end; | ||
16902 | return end(self); | ||
16903 | } | ||
16904 | |||
16905 | static int size(lua_State* L) { | ||
16906 | auto& self = get_src(L); | ||
16907 | std::size_t r = size_start(L, self); | ||
16908 | return stack::push(L, r); | ||
16909 | } | ||
16910 | |||
16911 | static int clear(lua_State* L) { | ||
16912 | auto& self = get_src(L); | ||
16913 | clear_start(L, self); | ||
16914 | return 0; | ||
16915 | } | ||
16916 | |||
16917 | static int erase(lua_State* L) { | ||
16918 | auto& self = get_src(L); | ||
16919 | error_result er; | ||
16920 | { | ||
16921 | decltype(auto) key = stack::get<K>(L, 2); | ||
16922 | er = erase_start(L, self, key); | ||
16923 | } | ||
16924 | return handle_errors(L, er); | ||
16925 | } | ||
16926 | |||
16927 | static int empty(lua_State* L) { | ||
16928 | auto& self = get_src(L); | ||
16929 | return stack::push(L, empty_start(L, self)); | ||
16930 | } | ||
16931 | |||
16932 | static std::ptrdiff_t index_adjustment(lua_State*, T&) { | ||
16933 | return static_cast<std::ptrdiff_t>(-1); | ||
16934 | } | ||
16935 | |||
16936 | static int pairs(lua_State* L) { | ||
16937 | typedef meta::any<is_associative, meta::all<is_lookup, meta::neg<is_matched_lookup>>> is_assoc; | ||
16938 | return pairs_associative<false>(is_assoc(), L); | ||
16939 | } | ||
16940 | |||
16941 | static int ipairs(lua_State* L) { | ||
16942 | typedef meta::any<is_associative, meta::all<is_lookup, meta::neg<is_matched_lookup>>> is_assoc; | ||
16943 | return pairs_associative<true>(is_assoc(), L); | ||
16944 | } | ||
16945 | |||
16946 | static int next(lua_State* L) { | ||
16947 | return stack::push(L, next_iter<false>); | ||
16948 | } | ||
16949 | }; | ||
16950 | |||
16951 | template <typename X> | ||
16952 | struct container_traits_default<X, std::enable_if_t<std::is_array<std::remove_pointer_t<meta::unwrap_unqualified_t<X>>>::value>> { | ||
16953 | private: | ||
16954 | typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> T; | ||
16955 | typedef container_traits<X> deferred_traits; | ||
16956 | |||
16957 | public: | ||
16958 | typedef std::remove_extent_t<T> value_type; | ||
16959 | typedef value_type* iterator; | ||
16960 | |||
16961 | private: | ||
16962 | struct iter { | ||
16963 | T& source; | ||
16964 | iterator it; | ||
16965 | |||
16966 | iter(T& source, iterator it) | ||
16967 | : source(source), it(std::move(it)) { | ||
16968 | } | ||
16969 | }; | ||
16970 | |||
16971 | static auto& get_src(lua_State* L) { | ||
16972 | auto p = stack::check_get<T*>(L, 1); | ||
16973 | #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE | ||
16974 | if (!p) { | ||
16975 | luaL_error(L, "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle<T>().c_str()); | ||
16976 | } | ||
16977 | if (p.value() == nullptr) { | ||
16978 | luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle<T>().c_str()); | ||
16979 | } | ||
16980 | #endif // Safe getting with error | ||
16981 | return *p.value(); | ||
16982 | } | ||
16983 | |||
16984 | static int find(std::true_type, lua_State* L) { | ||
16985 | T& self = get_src(L); | ||
16986 | decltype(auto) value = stack::get<value_type>(L, 2); | ||
16987 | std::size_t N = std::extent<T>::value; | ||
16988 | for (std::size_t idx = 0; idx < N; ++idx) { | ||
16989 | const auto& v = self[idx]; | ||
16990 | if (v == value) { | ||
16991 | return stack::push(L, idx + 1); | ||
16992 | } | ||
16993 | } | ||
16994 | return stack::push(L, lua_nil); | ||
16995 | } | ||
16996 | |||
16997 | static int find(std::false_type, lua_State* L) { | ||
16998 | return luaL_error(L, "sol: cannot call 'find' on '%s': no supported comparison operator for the value type", detail::demangle<T>().c_str()); | ||
16999 | } | ||
17000 | |||
17001 | static int next_iter(lua_State* L) { | ||
17002 | iter& i = stack::get<user<iter>>(L, 1); | ||
17003 | auto& source = i.source; | ||
17004 | auto& it = i.it; | ||
17005 | std::size_t k = stack::get<std::size_t>(L, 2); | ||
17006 | if (it == deferred_traits::end(L, source)) { | ||
17007 | return 0; | ||
17008 | } | ||
17009 | int p; | ||
17010 | p = stack::push_reference(L, k + 1); | ||
17011 | p += stack::push_reference(L, detail::deref_non_pointer(*it)); | ||
17012 | std::advance(it, 1); | ||
17013 | return p; | ||
17014 | } | ||
17015 | |||
17016 | public: | ||
17017 | static int clear(lua_State* L) { | ||
17018 | return luaL_error(L, "sol: cannot call 'clear' on type '%s': cannot remove all items from a fixed array", detail::demangle<T>().c_str()); | ||
17019 | } | ||
17020 | |||
17021 | static int erase(lua_State* L) { | ||
17022 | return luaL_error(L, "sol: cannot call 'erase' on type '%s': cannot remove an item from fixed arrays", detail::demangle<T>().c_str()); | ||
17023 | } | ||
17024 | |||
17025 | static int add(lua_State* L) { | ||
17026 | return luaL_error(L, "sol: cannot call 'add' on type '%s': cannot add to fixed arrays", detail::demangle<T>().c_str()); | ||
17027 | } | ||
17028 | |||
17029 | static int insert(lua_State* L) { | ||
17030 | return luaL_error(L, "sol: cannot call 'insert' on type '%s': cannot insert new entries into fixed arrays", detail::demangle<T>().c_str()); | ||
17031 | } | ||
17032 | |||
17033 | static int at(lua_State* L) { | ||
17034 | return get(L); | ||
17035 | } | ||
17036 | |||
17037 | static int get(lua_State* L) { | ||
17038 | T& self = get_src(L); | ||
17039 | std::ptrdiff_t idx = stack::get<std::ptrdiff_t>(L, 2); | ||
17040 | idx += deferred_traits::index_adjustment(L, self); | ||
17041 | if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value) || idx < 0) { | ||
17042 | return stack::push(L, lua_nil); | ||
17043 | } | ||
17044 | return stack::push_reference(L, detail::deref_non_pointer(self[idx])); | ||
17045 | } | ||
17046 | |||
17047 | static int index_get(lua_State* L) { | ||
17048 | return get(L); | ||
17049 | } | ||
17050 | |||
17051 | static int set(lua_State* L) { | ||
17052 | T& self = get_src(L); | ||
17053 | std::ptrdiff_t idx = stack::get<std::ptrdiff_t>(L, 2); | ||
17054 | idx += deferred_traits::index_adjustment(L, self); | ||
17055 | if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value)) { | ||
17056 | return luaL_error(L, "sol: index out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str()); | ||
17057 | } | ||
17058 | if (idx < 0) { | ||
17059 | return luaL_error(L, "sol: index out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str()); | ||
17060 | } | ||
17061 | self[idx] = stack::get<value_type>(L, 3); | ||
17062 | return 0; | ||
17063 | } | ||
17064 | |||
17065 | static int index_set(lua_State* L) { | ||
17066 | return set(L); | ||
17067 | } | ||
17068 | |||
17069 | static int find(lua_State* L) { | ||
17070 | return find(meta::supports_op_equal<value_type, value_type>(), L); | ||
17071 | } | ||
17072 | |||
17073 | static int size(lua_State* L) { | ||
17074 | return stack::push(L, std::extent<T>::value); | ||
17075 | } | ||
17076 | |||
17077 | static int empty(lua_State* L) { | ||
17078 | return stack::push(L, std::extent<T>::value > 0); | ||
17079 | } | ||
17080 | |||
17081 | static int pairs(lua_State* L) { | ||
17082 | auto& src = get_src(L); | ||
17083 | stack::push(L, next_iter); | ||
17084 | stack::push<user<iter>>(L, src, deferred_traits::begin(L, src)); | ||
17085 | stack::push(L, 0); | ||
17086 | return 3; | ||
17087 | } | ||
17088 | |||
17089 | static int ipairs(lua_State* L) { | ||
17090 | return pairs(L); | ||
17091 | } | ||
17092 | |||
17093 | static int next(lua_State* L) { | ||
17094 | return stack::push(L, next_iter); | ||
17095 | } | ||
17096 | |||
17097 | static std::ptrdiff_t index_adjustment(lua_State*, T&) { | ||
17098 | #if defined(SOL_CONTAINERS_START_INDEX) | ||
17099 | return (SOL_CONTAINERS_START) == 0 ? 0 : -(SOL_CONTAINERS_START); | ||
17100 | #else | ||
17101 | return -1; | ||
17102 | #endif | ||
17103 | } | ||
17104 | |||
17105 | static iterator begin(lua_State*, T& self) { | ||
17106 | return std::addressof(self[0]); | ||
17107 | } | ||
17108 | |||
17109 | static iterator end(lua_State*, T& self) { | ||
17110 | return std::addressof(self[0]) + std::extent<T>::value; | ||
17111 | } | ||
17112 | }; | ||
17113 | |||
17114 | template <typename X> | ||
17115 | struct container_traits_default<container_traits<X>> : container_traits_default<X> {}; | ||
17116 | } // namespace container_detail | ||
17117 | |||
17118 | template <typename T> | ||
17119 | struct container_traits : container_detail::container_traits_default<T> {}; | ||
17120 | |||
17121 | } // namespace sol | ||
17122 | |||
17123 | // end of sol/container_traits.hpp | ||
17124 | |||
17125 | namespace sol { | ||
17126 | |||
17127 | template <typename X> | ||
17128 | struct container_usertype_metatable { | ||
17129 | typedef std::remove_pointer_t<meta::unqualified_t<X>> T; | ||
17130 | typedef container_traits<T> traits; | ||
17131 | typedef container_detail::container_traits_default<T> default_traits; | ||
17132 | |||
17133 | static int real_index_get_traits(std::true_type, lua_State* L) { | ||
17134 | return traits::index_get(L); | ||
17135 | } | ||
17136 | |||
17137 | static int real_index_get_traits(std::false_type, lua_State* L) { | ||
17138 | return default_traits::index_get(L); | ||
17139 | } | ||
17140 | |||
17141 | static int real_index_call(lua_State* L) { | ||
17142 | typedef usertype_detail::map_t<std::string, lua_CFunction> call_map; | ||
17143 | static const call_map calls{ | ||
17144 | { "at", &at_call }, | ||
17145 | { "get", &real_get_call }, | ||
17146 | { "set", &real_set_call }, | ||
17147 | { "size", &real_length_call }, | ||
17148 | { "add", &real_add_call }, | ||
17149 | { "empty", &real_empty_call }, | ||
17150 | { "insert", &real_insert_call }, | ||
17151 | { "clear", &real_clear_call }, | ||
17152 | { "find", &real_find_call }, | ||
17153 | { "erase", &real_erase_call }, | ||
17154 | { "pairs", &pairs_call }, | ||
17155 | { "next", &next_call }, | ||
17156 | }; | ||
17157 | auto maybenameview = stack::check_get<string_view>(L, 2); | ||
17158 | if (maybenameview) { | ||
17159 | const string_view& nameview = *maybenameview; | ||
17160 | #if defined(SOL_UNORDERED_MAP_COMPATIBLE_HASH) && SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
17161 | auto it = calls.find(nameview, string_view_hash(), std::equal_to<string_view>()); | ||
17162 | #else | ||
17163 | std::string name(nameview.data(), nameview.size()); | ||
17164 | auto it = calls.find(name); | ||
17165 | #endif | ||
17166 | if (it != calls.cend()) { | ||
17167 | return stack::push(L, it->second); | ||
17168 | } | ||
17169 | } | ||
17170 | return real_index_get_traits(container_detail::has_traits_index_get<traits>(), L); | ||
17171 | } | ||
17172 | |||
17173 | static int real_at_traits(std::true_type, lua_State* L) { | ||
17174 | return traits::at(L); | ||
17175 | } | ||
17176 | |||
17177 | static int real_at_traits(std::false_type, lua_State* L) { | ||
17178 | return default_traits::at(L); | ||
17179 | } | ||
17180 | |||
17181 | static int real_at_call(lua_State* L) { | ||
17182 | return real_at_traits(container_detail::has_traits_at<traits>(), L); | ||
17183 | } | ||
17184 | |||
17185 | static int real_get_traits(std::true_type, lua_State* L) { | ||
17186 | return traits::get(L); | ||
17187 | } | ||
17188 | |||
17189 | static int real_get_traits(std::false_type, lua_State* L) { | ||
17190 | return default_traits::get(L); | ||
17191 | } | ||
17192 | |||
17193 | static int real_get_call(lua_State* L) { | ||
17194 | return real_get_traits(container_detail::has_traits_get<traits>(), L); | ||
17195 | } | ||
17196 | |||
17197 | static int real_set_traits(std::true_type, lua_State* L) { | ||
17198 | return traits::set(L); | ||
17199 | } | ||
17200 | |||
17201 | static int real_set_traits(std::false_type, lua_State* L) { | ||
17202 | return default_traits::set(L); | ||
17203 | } | ||
17204 | |||
17205 | static int real_set_call(lua_State* L) { | ||
17206 | return real_set_traits(container_detail::has_traits_set<traits>(), L); | ||
17207 | } | ||
17208 | |||
17209 | static int real_index_set_traits(std::true_type, lua_State* L) { | ||
17210 | return traits::index_set(L); | ||
17211 | } | ||
17212 | |||
17213 | static int real_index_set_traits(std::false_type, lua_State* L) { | ||
17214 | return default_traits::index_set(L); | ||
17215 | } | ||
17216 | |||
17217 | static int real_new_index_call(lua_State* L) { | ||
17218 | return real_index_set_traits(container_detail::has_traits_index_set<traits>(), L); | ||
17219 | } | ||
17220 | |||
17221 | static int real_pairs_traits(std::true_type, lua_State* L) { | ||
17222 | return traits::pairs(L); | ||
17223 | } | ||
17224 | |||
17225 | static int real_pairs_traits(std::false_type, lua_State* L) { | ||
17226 | return default_traits::pairs(L); | ||
17227 | } | ||
17228 | |||
17229 | static int real_pairs_call(lua_State* L) { | ||
17230 | return real_pairs_traits(container_detail::has_traits_pairs<traits>(), L); | ||
17231 | } | ||
17232 | |||
17233 | static int real_ipairs_traits(std::true_type, lua_State* L) { | ||
17234 | return traits::ipairs(L); | ||
17235 | } | ||
17236 | |||
17237 | static int real_ipairs_traits(std::false_type, lua_State* L) { | ||
17238 | return default_traits::ipairs(L); | ||
17239 | } | ||
17240 | |||
17241 | static int real_ipairs_call(lua_State* L) { | ||
17242 | return real_ipairs_traits(container_detail::has_traits_ipairs<traits>(), L); | ||
17243 | } | ||
17244 | |||
17245 | static int real_next_traits(std::true_type, lua_State* L) { | ||
17246 | return traits::next(L); | ||
17247 | } | ||
17248 | |||
17249 | static int real_next_traits(std::false_type, lua_State* L) { | ||
17250 | return default_traits::next(L); | ||
17251 | } | ||
17252 | |||
17253 | static int real_next_call(lua_State* L) { | ||
17254 | return real_next_traits(container_detail::has_traits_next<traits>(), L); | ||
17255 | } | ||
17256 | |||
17257 | static int real_size_traits(std::true_type, lua_State* L) { | ||
17258 | return traits::size(L); | ||
17259 | } | ||
17260 | |||
17261 | static int real_size_traits(std::false_type, lua_State* L) { | ||
17262 | return default_traits::size(L); | ||
17263 | } | ||
17264 | |||
17265 | static int real_length_call(lua_State* L) { | ||
17266 | return real_size_traits(container_detail::has_traits_size<traits>(), L); | ||
17267 | } | ||
17268 | |||
17269 | static int real_add_traits(std::true_type, lua_State* L) { | ||
17270 | return traits::add(L); | ||
17271 | } | ||
17272 | |||
17273 | static int real_add_traits(std::false_type, lua_State* L) { | ||
17274 | return default_traits::add(L); | ||
17275 | } | ||
17276 | |||
17277 | static int real_add_call(lua_State* L) { | ||
17278 | return real_add_traits(container_detail::has_traits_add<traits>(), L); | ||
17279 | } | ||
17280 | |||
17281 | static int real_insert_traits(std::true_type, lua_State* L) { | ||
17282 | return traits::insert(L); | ||
17283 | } | ||
17284 | |||
17285 | static int real_insert_traits(std::false_type, lua_State* L) { | ||
17286 | return default_traits::insert(L); | ||
17287 | } | ||
17288 | |||
17289 | static int real_insert_call(lua_State* L) { | ||
17290 | return real_insert_traits(container_detail::has_traits_insert<traits>(), L); | ||
17291 | } | ||
17292 | |||
17293 | static int real_clear_traits(std::true_type, lua_State* L) { | ||
17294 | return traits::clear(L); | ||
17295 | } | ||
17296 | |||
17297 | static int real_clear_traits(std::false_type, lua_State* L) { | ||
17298 | return default_traits::clear(L); | ||
17299 | } | ||
17300 | |||
17301 | static int real_clear_call(lua_State* L) { | ||
17302 | return real_clear_traits(container_detail::has_traits_clear<traits>(), L); | ||
17303 | } | ||
17304 | |||
17305 | static int real_empty_traits(std::true_type, lua_State* L) { | ||
17306 | return traits::empty(L); | ||
17307 | } | ||
17308 | |||
17309 | static int real_empty_traits(std::false_type, lua_State* L) { | ||
17310 | return default_traits::empty(L); | ||
17311 | } | ||
17312 | |||
17313 | static int real_empty_call(lua_State* L) { | ||
17314 | return real_empty_traits(container_detail::has_traits_empty<traits>(), L); | ||
17315 | } | ||
17316 | |||
17317 | static int real_erase_traits(std::true_type, lua_State* L) { | ||
17318 | return traits::erase(L); | ||
17319 | } | ||
17320 | |||
17321 | static int real_erase_traits(std::false_type, lua_State* L) { | ||
17322 | return default_traits::erase(L); | ||
17323 | } | ||
17324 | |||
17325 | static int real_erase_call(lua_State* L) { | ||
17326 | return real_erase_traits(container_detail::has_traits_erase<traits>(), L); | ||
17327 | } | ||
17328 | |||
17329 | static int real_find_traits(std::true_type, lua_State* L) { | ||
17330 | return traits::find(L); | ||
17331 | } | ||
17332 | |||
17333 | static int real_find_traits(std::false_type, lua_State* L) { | ||
17334 | return default_traits::find(L); | ||
17335 | } | ||
17336 | |||
17337 | static int real_find_call(lua_State* L) { | ||
17338 | return real_find_traits(container_detail::has_traits_find<traits>(), L); | ||
17339 | } | ||
17340 | |||
17341 | static int add_call(lua_State* L) { | ||
17342 | return detail::typed_static_trampoline<decltype(&real_add_call), (&real_add_call)>(L); | ||
17343 | } | ||
17344 | |||
17345 | static int erase_call(lua_State* L) { | ||
17346 | return detail::typed_static_trampoline<decltype(&real_erase_call), (&real_erase_call)>(L); | ||
17347 | } | ||
17348 | |||
17349 | static int insert_call(lua_State* L) { | ||
17350 | return detail::typed_static_trampoline<decltype(&real_insert_call), (&real_insert_call)>(L); | ||
17351 | } | ||
17352 | |||
17353 | static int clear_call(lua_State* L) { | ||
17354 | return detail::typed_static_trampoline<decltype(&real_clear_call), (&real_clear_call)>(L); | ||
17355 | } | ||
17356 | |||
17357 | static int empty_call(lua_State* L) { | ||
17358 | return detail::typed_static_trampoline<decltype(&real_empty_call), (&real_empty_call)>(L); | ||
17359 | } | ||
17360 | |||
17361 | static int find_call(lua_State* L) { | ||
17362 | return detail::typed_static_trampoline<decltype(&real_find_call), (&real_find_call)>(L); | ||
17363 | } | ||
17364 | |||
17365 | static int length_call(lua_State* L) { | ||
17366 | return detail::typed_static_trampoline<decltype(&real_length_call), (&real_length_call)>(L); | ||
17367 | } | ||
17368 | |||
17369 | static int pairs_call(lua_State* L) { | ||
17370 | return detail::typed_static_trampoline<decltype(&real_pairs_call), (&real_pairs_call)>(L); | ||
17371 | } | ||
17372 | |||
17373 | static int ipairs_call(lua_State* L) { | ||
17374 | return detail::typed_static_trampoline<decltype(&real_ipairs_call), (&real_ipairs_call)>(L); | ||
17375 | } | ||
17376 | |||
17377 | static int next_call(lua_State* L) { | ||
17378 | return detail::typed_static_trampoline<decltype(&real_next_call), (&real_next_call)>(L); | ||
17379 | } | ||
17380 | |||
17381 | static int at_call(lua_State* L) { | ||
17382 | return detail::typed_static_trampoline<decltype(&real_at_call), (&real_at_call)>(L); | ||
17383 | } | ||
17384 | |||
17385 | static int get_call(lua_State* L) { | ||
17386 | return detail::typed_static_trampoline<decltype(&real_get_call), (&real_get_call)>(L); | ||
17387 | } | ||
17388 | |||
17389 | static int set_call(lua_State* L) { | ||
17390 | return detail::typed_static_trampoline<decltype(&real_set_call), (&real_set_call)>(L); | ||
17391 | } | ||
17392 | |||
17393 | static int index_call(lua_State* L) { | ||
17394 | return detail::typed_static_trampoline<decltype(&real_index_call), (&real_index_call)>(L); | ||
17395 | } | ||
17396 | |||
17397 | static int new_index_call(lua_State* L) { | ||
17398 | return detail::typed_static_trampoline<decltype(&real_new_index_call), (&real_new_index_call)>(L); | ||
17399 | } | ||
17400 | }; | ||
17401 | |||
17402 | namespace stack { | ||
17403 | namespace stack_detail { | ||
17404 | template <typename T, bool is_shim = false> | ||
17405 | struct metatable_setup { | ||
17406 | lua_State* L; | ||
17407 | |||
17408 | metatable_setup(lua_State* L) | ||
17409 | : L(L) { | ||
17410 | } | ||
17411 | |||
17412 | void operator()() { | ||
17413 | typedef container_usertype_metatable<std::conditional_t<is_shim, | ||
17414 | as_container_t<std::remove_pointer_t<T>>, | ||
17415 | std::remove_pointer_t<T>>> | ||
17416 | meta_cumt; | ||
17417 | static const char* metakey = is_shim ? &usertype_traits<as_container_t<std::remove_pointer_t<T>>>::metatable()[0] : &usertype_traits<T>::metatable()[0]; | ||
17418 | static const std::array<luaL_Reg, 19> reg = { { | ||
17419 | { "__pairs", &meta_cumt::pairs_call }, | ||
17420 | { "__ipairs", &meta_cumt::ipairs_call }, | ||
17421 | { "__len", &meta_cumt::length_call }, | ||
17422 | { "__index", &meta_cumt::index_call }, | ||
17423 | { "__newindex", &meta_cumt::new_index_call }, | ||
17424 | { "pairs", &meta_cumt::pairs_call }, | ||
17425 | { "next", &meta_cumt::next_call }, | ||
17426 | { "at", &meta_cumt::at_call }, | ||
17427 | { "get", &meta_cumt::get_call }, | ||
17428 | { "set", &meta_cumt::set_call }, | ||
17429 | { "size", &meta_cumt::length_call }, | ||
17430 | { "empty", &meta_cumt::empty_call }, | ||
17431 | { "clear", &meta_cumt::clear_call }, | ||
17432 | { "insert", &meta_cumt::insert_call }, | ||
17433 | { "add", &meta_cumt::add_call }, | ||
17434 | { "find", &meta_cumt::find_call }, | ||
17435 | { "erase", &meta_cumt::erase_call }, | ||
17436 | std::is_pointer<T>::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destruct<T> }, | ||
17437 | { nullptr, nullptr } | ||
17438 | } }; | ||
17439 | |||
17440 | if (luaL_newmetatable(L, metakey) == 1) { | ||
17441 | luaL_setfuncs(L, reg.data(), 0); | ||
17442 | } | ||
17443 | lua_setmetatable(L, -2); | ||
17444 | } | ||
17445 | }; | ||
17446 | } // namespace stack_detail | ||
17447 | |||
17448 | template <typename T> | ||
17449 | struct pusher<as_container_t<T>> { | ||
17450 | typedef meta::unqualified_t<T> C; | ||
17451 | |||
17452 | static int push_lvalue(std::true_type, lua_State* L, const C& cont) { | ||
17453 | stack_detail::metatable_setup<C*, true> fx(L); | ||
17454 | return pusher<detail::as_pointer_tag<const C>>{}.push_fx(L, fx, detail::ptr(cont)); | ||
17455 | } | ||
17456 | |||
17457 | static int push_lvalue(std::false_type, lua_State* L, const C& cont) { | ||
17458 | stack_detail::metatable_setup<C, true> fx(L); | ||
17459 | return pusher<detail::as_value_tag<C>>{}.push_fx(L, fx, cont); | ||
17460 | } | ||
17461 | |||
17462 | static int push_rvalue(std::true_type, lua_State* L, C&& cont) { | ||
17463 | stack_detail::metatable_setup<C, true> fx(L); | ||
17464 | return pusher<detail::as_value_tag<C>>{}.push_fx(L, fx, std::move(cont)); | ||
17465 | } | ||
17466 | |||
17467 | static int push_rvalue(std::false_type, lua_State* L, const C& cont) { | ||
17468 | return push_lvalue(std::is_lvalue_reference<T>(), L, cont); | ||
17469 | } | ||
17470 | |||
17471 | static int push(lua_State* L, const as_container_t<T>& as_cont) { | ||
17472 | return push_lvalue(std::is_lvalue_reference<T>(), L, as_cont.source); | ||
17473 | } | ||
17474 | |||
17475 | static int push(lua_State* L, as_container_t<T>&& as_cont) { | ||
17476 | return push_rvalue(meta::all<std::is_rvalue_reference<T>, meta::neg<std::is_lvalue_reference<T>>>(), L, std::forward<T>(as_cont.source)); | ||
17477 | } | ||
17478 | }; | ||
17479 | |||
17480 | template <typename T> | ||
17481 | struct pusher<as_container_t<T*>> { | ||
17482 | typedef std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>> C; | ||
17483 | |||
17484 | static int push(lua_State* L, T* cont) { | ||
17485 | stack_detail::metatable_setup<C> fx(L); | ||
17486 | return pusher<detail::as_pointer_tag<T>>{}.push_fx(L, fx, cont); | ||
17487 | } | ||
17488 | }; | ||
17489 | |||
17490 | template <typename T> | ||
17491 | struct pusher<T, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<is_lua_reference<meta::unqualified_t<T>>>>::value>> { | ||
17492 | typedef meta::unqualified_t<T> C; | ||
17493 | |||
17494 | static int push(lua_State* L, const T& cont) { | ||
17495 | stack_detail::metatable_setup<C> fx(L); | ||
17496 | return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, cont); | ||
17497 | } | ||
17498 | |||
17499 | static int push(lua_State* L, T&& cont) { | ||
17500 | stack_detail::metatable_setup<C> fx(L); | ||
17501 | return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, std::move(cont)); | ||
17502 | } | ||
17503 | }; | ||
17504 | |||
17505 | template <typename T> | ||
17506 | struct pusher<T*, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<is_lua_reference<meta::unqualified_t<T>>>>::value>> { | ||
17507 | typedef std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>> C; | ||
17508 | |||
17509 | static int push(lua_State* L, T* cont) { | ||
17510 | stack_detail::metatable_setup<C> fx(L); | ||
17511 | return pusher<detail::as_pointer_tag<T>>{}.push_fx(L, fx, cont); | ||
17512 | } | ||
17513 | }; | ||
17514 | |||
17515 | template <typename T, typename C> | ||
17516 | struct checker<as_container_t<T>, type::userdata, C> { | ||
17517 | template <typename Handler> | ||
17518 | static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
17519 | return stack::check<T>(L, index, std::forward<Handler>(handler), tracking); | ||
17520 | } | ||
17521 | }; | ||
17522 | |||
17523 | template <typename T> | ||
17524 | struct getter<as_container_t<T>> { | ||
17525 | static decltype(auto) get(lua_State* L, int index, record& tracking) { | ||
17526 | return stack::get<T>(L, index, tracking); | ||
17527 | } | ||
17528 | }; | ||
17529 | |||
17530 | template <typename T> | ||
17531 | struct getter<as_container_t<T>*> { | ||
17532 | static decltype(auto) get(lua_State* L, int index, record& tracking) { | ||
17533 | return stack::get<T*>(L, index, tracking); | ||
17534 | } | ||
17535 | }; | ||
17536 | } // namespace stack | ||
17537 | |||
17538 | } // namespace sol | ||
17539 | |||
17540 | // end of sol/container_usertype_metatable.hpp | ||
17541 | |||
17542 | // beginning of sol/usertype_core.hpp | ||
17543 | |||
17544 | #include <sstream> | ||
17545 | |||
17546 | namespace sol { | ||
17547 | namespace usertype_detail { | ||
17548 | struct no_comp { | ||
17549 | template <typename A, typename B> | ||
17550 | bool operator()(A&&, B&&) const { | ||
17551 | return false; | ||
17552 | } | ||
17553 | }; | ||
17554 | |||
17555 | template <typename T> | ||
17556 | int is_check(lua_State* L) { | ||
17557 | return stack::push(L, stack::check<T>(L, 1, &no_panic)); | ||
17558 | } | ||
17559 | |||
17560 | template <typename T> | ||
17561 | inline int member_default_to_string(std::true_type, lua_State* L) { | ||
17562 | decltype(auto) ts = stack::get<T>(L, 1).to_string(); | ||
17563 | return stack::push(L, std::forward<decltype(ts)>(ts)); | ||
17564 | } | ||
17565 | |||
17566 | template <typename T> | ||
17567 | inline int member_default_to_string(std::false_type, lua_State* L) { | ||
17568 | return luaL_error(L, "cannot perform to_string on '%s': no 'to_string' overload in namespace, 'to_string' member function, or operator<<(ostream&, ...) present", detail::demangle<T>().data()); | ||
17569 | } | ||
17570 | |||
17571 | template <typename T> | ||
17572 | inline int adl_default_to_string(std::true_type, lua_State* L) { | ||
17573 | using namespace std; | ||
17574 | decltype(auto) ts = to_string(stack::get<T>(L, 1)); | ||
17575 | return stack::push(L, std::forward<decltype(ts)>(ts)); | ||
17576 | } | ||
17577 | |||
17578 | template <typename T> | ||
17579 | inline int adl_default_to_string(std::false_type, lua_State* L) { | ||
17580 | return member_default_to_string<T>(meta::supports_to_string_member<T>(), L); | ||
17581 | } | ||
17582 | |||
17583 | template <typename T> | ||
17584 | inline int oss_default_to_string(std::true_type, lua_State* L) { | ||
17585 | std::ostringstream oss; | ||
17586 | oss << stack::get<T>(L, 1); | ||
17587 | return stack::push(L, oss.str()); | ||
17588 | } | ||
17589 | |||
17590 | template <typename T> | ||
17591 | inline int oss_default_to_string(std::false_type, lua_State* L) { | ||
17592 | return adl_default_to_string<T>(meta::supports_adl_to_string<T>(), L); | ||
17593 | } | ||
17594 | |||
17595 | template <typename T> | ||
17596 | inline int default_to_string(lua_State* L) { | ||
17597 | return oss_default_to_string<T>(meta::supports_ostream_op<T>(), L); | ||
17598 | } | ||
17599 | |||
17600 | template <typename T, typename Op> | ||
17601 | int comparsion_operator_wrap(lua_State* L) { | ||
17602 | auto maybel = stack::check_get<T>(L, 1); | ||
17603 | if (maybel) { | ||
17604 | auto mayber = stack::check_get<T>(L, 2); | ||
17605 | if (mayber) { | ||
17606 | auto& l = *maybel; | ||
17607 | auto& r = *mayber; | ||
17608 | if (std::is_same<no_comp, Op>::value) { | ||
17609 | return stack::push(L, detail::ptr(l) == detail::ptr(r)); | ||
17610 | } | ||
17611 | else { | ||
17612 | Op op; | ||
17613 | return stack::push(L, (detail::ptr(l) == detail::ptr(r)) || op(detail::deref(l), detail::deref(r))); | ||
17614 | } | ||
17615 | } | ||
17616 | } | ||
17617 | return stack::push(L, false); | ||
17618 | } | ||
17619 | |||
17620 | template <typename T, typename Op, typename Supports, typename Regs, meta::enable<Supports> = meta::enabler> | ||
17621 | inline void make_reg_op(Regs& l, int& index, const char* name) { | ||
17622 | lua_CFunction f = &comparsion_operator_wrap<T, Op>; | ||
17623 | l[index] = luaL_Reg{ name, f }; | ||
17624 | ++index; | ||
17625 | } | ||
17626 | |||
17627 | template <typename T, typename Op, typename Supports, typename Regs, meta::disable<Supports> = meta::enabler> | ||
17628 | inline void make_reg_op(Regs&, int&, const char*) { | ||
17629 | // Do nothing if there's no support | ||
17630 | } | ||
17631 | |||
17632 | template <typename T, typename Supports, typename Regs, meta::enable<Supports> = meta::enabler> | ||
17633 | inline void make_to_string_op(Regs& l, int& index) { | ||
17634 | const char* name = to_string(meta_function::to_string).c_str(); | ||
17635 | lua_CFunction f = &detail::static_trampoline<&default_to_string<T>>; | ||
17636 | l[index] = luaL_Reg{ name, f }; | ||
17637 | ++index; | ||
17638 | } | ||
17639 | |||
17640 | template <typename T, typename Supports, typename Regs, meta::disable<Supports> = meta::enabler> | ||
17641 | inline void make_to_string_op(Regs&, int&) { | ||
17642 | // Do nothing if there's no support | ||
17643 | } | ||
17644 | |||
17645 | template <typename T, typename Regs, meta::enable<meta::has_deducible_signature<T>> = meta::enabler> | ||
17646 | inline void make_call_op(Regs& l, int& index) { | ||
17647 | const char* name = to_string(meta_function::call).c_str(); | ||
17648 | lua_CFunction f = &c_call<decltype(&T::operator()), &T::operator()>; | ||
17649 | l[index] = luaL_Reg{ name, f }; | ||
17650 | ++index; | ||
17651 | } | ||
17652 | |||
17653 | template <typename T, typename Regs, meta::disable<meta::has_deducible_signature<T>> = meta::enabler> | ||
17654 | inline void make_call_op(Regs&, int&) { | ||
17655 | // Do nothing if there's no support | ||
17656 | } | ||
17657 | |||
17658 | template <typename T, typename Regs> | ||
17659 | inline void make_length_op_const(std::true_type, Regs& l, int& index) { | ||
17660 | const char* name = to_string(meta_function::length).c_str(); | ||
17661 | #if defined(__clang__) | ||
17662 | l[index] = luaL_Reg{ name, &c_call<decltype(&T::size), &T::size> }; | ||
17663 | #else | ||
17664 | typedef decltype(std::declval<T>().size()) R; | ||
17665 | using sz_func = R(T::*)()const; | ||
17666 | l[index] = luaL_Reg{ name, &c_call<decltype(static_cast<sz_func>(&T::size)), static_cast<sz_func>(&T::size)> }; | ||
17667 | #endif | ||
17668 | ++index; | ||
17669 | } | ||
17670 | |||
17671 | template <typename T, typename Regs> | ||
17672 | inline void make_length_op_const(std::false_type, Regs& l, int& index) { | ||
17673 | const char* name = to_string(meta_function::length).c_str(); | ||
17674 | #if defined(__clang__) | ||
17675 | l[index] = luaL_Reg{ name, &c_call<decltype(&T::size), &T::size> }; | ||
17676 | #else | ||
17677 | typedef decltype(std::declval<T>().size()) R; | ||
17678 | using sz_func = R(T::*)(); | ||
17679 | l[index] = luaL_Reg{ name, &c_call<decltype(static_cast<sz_func>(&T::size)), static_cast<sz_func>(&T::size)> }; | ||
17680 | #endif | ||
17681 | ++index; | ||
17682 | } | ||
17683 | |||
17684 | template <typename T, typename Regs, meta::enable<meta::has_size<T>, meta::has_size<const T>> = meta::enabler> | ||
17685 | inline void make_length_op(Regs& l, int& index) { | ||
17686 | make_length_op_const<T>(meta::has_size<const T>(), l, index); | ||
17687 | } | ||
17688 | |||
17689 | template <typename T, typename Regs, meta::disable<meta::has_size<T>, meta::has_size<const T>> = meta::enabler> | ||
17690 | inline void make_length_op(Regs&, int&) { | ||
17691 | // Do nothing if there's no support | ||
17692 | } | ||
17693 | |||
17694 | template <typename T, typename Regs, meta::enable<meta::neg<std::is_pointer<T>>, std::is_destructible<T>>> | ||
17695 | void make_destructor(Regs& l, int& index) { | ||
17696 | const char* name = to_string(meta_function::garbage_collect).c_str(); | ||
17697 | l[index] = luaL_Reg{ name, is_unique_usertype<T>::value ? &detail::unique_destruct<T> : &detail::usertype_alloc_destruct<T> }; | ||
17698 | ++index; | ||
17699 | } | ||
17700 | |||
17701 | template <typename T, typename Regs, meta::disable<meta::neg<std::is_pointer<T>>, std::is_destructible<T>>> | ||
17702 | void make_destructor(Regs& l, int& index) { | ||
17703 | if (!std::is_destructible<T>::value) { | ||
17704 | // if the value is not destructible, plant an erroring __gc method | ||
17705 | // to warn the user of a problem when it comes around | ||
17706 | // this won't trigger if the user performs `new_usertype` / `new_simple_usertype` and | ||
17707 | // rigs the class up properly | ||
17708 | const char* name = to_string(meta_function::garbage_collect).c_str(); | ||
17709 | l[index] = luaL_Reg{ name, &detail::cannot_destruct<T> }; | ||
17710 | ++index; | ||
17711 | } | ||
17712 | } | ||
17713 | |||
17714 | template <typename T, typename Regs, typename Fx> | ||
17715 | void insert_default_registrations(std::false_type, Regs&, int&, Fx&&) { | ||
17716 | // no-op | ||
17717 | } | ||
17718 | |||
17719 | template <typename T, typename Regs, typename Fx> | ||
17720 | void insert_default_registrations(std::true_type, Regs& l, int& index, Fx&& fx) { | ||
17721 | if (fx(meta_function::less_than)) { | ||
17722 | const char* name = to_string(meta_function::less_than).c_str(); | ||
17723 | usertype_detail::make_reg_op<T, std::less<>, meta::supports_op_less<T>>(l, index, name); | ||
17724 | } | ||
17725 | if (fx(meta_function::less_than_or_equal_to)) { | ||
17726 | const char* name = to_string(meta_function::less_than_or_equal_to).c_str(); | ||
17727 | usertype_detail::make_reg_op<T, std::less_equal<>, meta::supports_op_less_equal<T>>(l, index, name); | ||
17728 | } | ||
17729 | if (fx(meta_function::equal_to)) { | ||
17730 | const char* name = to_string(meta_function::equal_to).c_str(); | ||
17731 | usertype_detail::make_reg_op<T, std::conditional_t<meta::supports_op_equal<T>::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(l, index, name); | ||
17732 | } | ||
17733 | if (fx(meta_function::pairs)) { | ||
17734 | const char* name = to_string(meta_function::pairs).c_str(); | ||
17735 | l[index] = luaL_Reg{ name, container_usertype_metatable<as_container_t<T>>::pairs_call }; | ||
17736 | ++index; | ||
17737 | } | ||
17738 | if (fx(meta_function::length)) { | ||
17739 | usertype_detail::make_length_op<T>(l, index); | ||
17740 | } | ||
17741 | if (fx(meta_function::to_string)) { | ||
17742 | usertype_detail::make_to_string_op<T, is_to_stringable<T>>(l, index); | ||
17743 | } | ||
17744 | if (fx(meta_function::call_function)) { | ||
17745 | usertype_detail::make_call_op<T>(l, index); | ||
17746 | } | ||
17747 | } | ||
17748 | |||
17749 | template <typename T, typename Regs, typename Fx> | ||
17750 | void insert_default_registrations(Regs& l, int& index, Fx&& fx) { | ||
17751 | insert_default_registrations<T>(is_automagical<T>(), l, index, std::forward<Fx>(fx)); | ||
17752 | } | ||
17753 | } // namespace usertype_detail | ||
17754 | |||
17755 | namespace stack { namespace stack_detail { | ||
17756 | template <typename T> | ||
17757 | struct undefined_metatable { | ||
17758 | typedef meta::all<meta::neg<std::is_pointer<T>>, std::is_destructible<T>> is_destructible; | ||
17759 | typedef std::remove_pointer_t<T> P; | ||
17760 | lua_State* L; | ||
17761 | const char* key; | ||
17762 | |||
17763 | undefined_metatable(lua_State* l, const char* k) | ||
17764 | : L(l), key(k) { | ||
17765 | } | ||
17766 | |||
17767 | void operator()() const { | ||
17768 | if (luaL_newmetatable(L, key) == 1) { | ||
17769 | luaL_Reg l[32]{}; | ||
17770 | int index = 0; | ||
17771 | auto fx = [](meta_function) { return true; }; | ||
17772 | usertype_detail::insert_default_registrations<P>(l, index, fx); | ||
17773 | usertype_detail::make_destructor<T>(l, index); | ||
17774 | luaL_setfuncs(L, l, 0); | ||
17775 | |||
17776 | // __type table | ||
17777 | lua_createtable(L, 0, 2); | ||
17778 | const std::string& name = detail::demangle<T>(); | ||
17779 | lua_pushlstring(L, name.c_str(), name.size()); | ||
17780 | lua_setfield(L, -2, "name"); | ||
17781 | lua_CFunction is_func = &usertype_detail::is_check<T>; | ||
17782 | lua_pushcclosure(L, is_func, 0); | ||
17783 | lua_setfield(L, -2, "is"); | ||
17784 | lua_setfield(L, -2, to_string(meta_function::type).c_str()); | ||
17785 | } | ||
17786 | lua_setmetatable(L, -2); | ||
17787 | } | ||
17788 | }; | ||
17789 | } | ||
17790 | } // namespace stack::stack_detail | ||
17791 | } // namespace sol | ||
17792 | |||
17793 | // end of sol/usertype_core.hpp | ||
17794 | |||
17795 | #include <cstdio> | ||
17796 | #include <bitset> | ||
17797 | |||
17798 | namespace sol { | ||
17799 | namespace usertype_detail { | ||
17800 | const int metatable_index = 2; | ||
17801 | const int metatable_core_index = 3; | ||
17802 | const int filler_index = 4; | ||
17803 | const int magic_index = 5; | ||
17804 | |||
17805 | const int simple_metatable_index = 2; | ||
17806 | const int index_function_index = 3; | ||
17807 | const int newindex_function_index = 4; | ||
17808 | |||
17809 | typedef void (*base_walk)(lua_State*, bool&, int&, string_view&); | ||
17810 | typedef int (*member_search)(lua_State*, void*, int); | ||
17811 | |||
17812 | struct call_information { | ||
17813 | member_search index; | ||
17814 | member_search new_index; | ||
17815 | int runtime_target; | ||
17816 | |||
17817 | call_information(member_search index, member_search newindex) | ||
17818 | : call_information(index, newindex, -1) { | ||
17819 | } | ||
17820 | call_information(member_search index, member_search newindex, int runtimetarget) | ||
17821 | : index(index), new_index(newindex), runtime_target(runtimetarget) { | ||
17822 | } | ||
17823 | }; | ||
17824 | |||
17825 | typedef map_t<std::string, call_information> mapping_t; | ||
17826 | |||
17827 | struct variable_wrapper { | ||
17828 | virtual int index(lua_State* L) = 0; | ||
17829 | virtual int new_index(lua_State* L) = 0; | ||
17830 | virtual ~variable_wrapper(){}; | ||
17831 | }; | ||
17832 | |||
17833 | template <typename T, typename F> | ||
17834 | struct callable_binding : variable_wrapper { | ||
17835 | F fx; | ||
17836 | |||
17837 | template <typename Arg> | ||
17838 | callable_binding(Arg&& arg) | ||
17839 | : fx(std::forward<Arg>(arg)) { | ||
17840 | } | ||
17841 | |||
17842 | virtual int index(lua_State* L) override { | ||
17843 | return call_detail::call_wrapped<T, true, true>(L, fx); | ||
17844 | } | ||
17845 | |||
17846 | virtual int new_index(lua_State* L) override { | ||
17847 | return call_detail::call_wrapped<T, false, true>(L, fx); | ||
17848 | } | ||
17849 | }; | ||
17850 | |||
17851 | typedef map_t<std::string, std::unique_ptr<variable_wrapper>> variable_map; | ||
17852 | typedef map_t<std::string, object> function_map; | ||
17853 | |||
17854 | struct simple_map { | ||
17855 | const char* metakey; | ||
17856 | variable_map variables; | ||
17857 | function_map functions; | ||
17858 | object index; | ||
17859 | object newindex; | ||
17860 | base_walk indexbaseclasspropogation; | ||
17861 | base_walk newindexbaseclasspropogation; | ||
17862 | |||
17863 | simple_map(const char* mkey, base_walk index, base_walk newindex, object i, object ni, variable_map&& vars, function_map&& funcs) | ||
17864 | : metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)), index(std::move(i)), newindex(std::move(ni)), indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) { | ||
17865 | } | ||
17866 | }; | ||
17867 | } // namespace usertype_detail | ||
17868 | |||
17869 | struct usertype_metatable_core { | ||
17870 | usertype_detail::mapping_t mapping; | ||
17871 | lua_CFunction indexfunc; | ||
17872 | lua_CFunction newindexfunc; | ||
17873 | std::vector<object> runtime; | ||
17874 | bool mustindex; | ||
17875 | |||
17876 | usertype_metatable_core(lua_CFunction ifx, lua_CFunction nifx) | ||
17877 | : mapping(), indexfunc(ifx), newindexfunc(nifx), runtime(), mustindex(false) { | ||
17878 | } | ||
17879 | |||
17880 | usertype_metatable_core(const usertype_metatable_core&) = default; | ||
17881 | usertype_metatable_core(usertype_metatable_core&&) = default; | ||
17882 | usertype_metatable_core& operator=(const usertype_metatable_core&) = default; | ||
17883 | usertype_metatable_core& operator=(usertype_metatable_core&&) = default; | ||
17884 | }; | ||
17885 | |||
17886 | namespace usertype_detail { | ||
17887 | const lua_Integer toplevel_magic = static_cast<lua_Integer>(0xCCC2CCC1); | ||
17888 | |||
17889 | inline int is_indexer(string_view s) { | ||
17890 | if (s == to_string(meta_function::index)) { | ||
17891 | return 1; | ||
17892 | } | ||
17893 | else if (s == to_string(meta_function::new_index)) { | ||
17894 | return 2; | ||
17895 | } | ||
17896 | return 0; | ||
17897 | } | ||
17898 | |||
17899 | inline int is_indexer(meta_function mf) { | ||
17900 | if (mf == meta_function::index) { | ||
17901 | return 1; | ||
17902 | } | ||
17903 | else if (mf == meta_function::new_index) { | ||
17904 | return 2; | ||
17905 | } | ||
17906 | return 0; | ||
17907 | } | ||
17908 | |||
17909 | inline int is_indexer(call_construction) { | ||
17910 | return 0; | ||
17911 | } | ||
17912 | |||
17913 | inline int is_indexer(base_classes_tag) { | ||
17914 | return 0; | ||
17915 | } | ||
17916 | |||
17917 | inline auto make_string_view(string_view s) { | ||
17918 | return s; | ||
17919 | } | ||
17920 | |||
17921 | inline auto make_string_view(call_construction) { | ||
17922 | return string_view(to_string(meta_function::call_function)); | ||
17923 | } | ||
17924 | |||
17925 | inline auto make_string_view(meta_function mf) { | ||
17926 | return string_view(to_string(mf)); | ||
17927 | } | ||
17928 | |||
17929 | inline auto make_string_view(base_classes_tag) { | ||
17930 | return string_view(detail::base_class_cast_key()); | ||
17931 | } | ||
17932 | |||
17933 | template <typename Arg> | ||
17934 | inline std::string make_string(Arg&& arg) { | ||
17935 | string_view s = make_string_view(arg); | ||
17936 | return std::string(s.data(), s.size()); | ||
17937 | } | ||
17938 | |||
17939 | template <typename N> | ||
17940 | inline luaL_Reg make_reg(N&& n, lua_CFunction f) { | ||
17941 | luaL_Reg l{make_string_view(std::forward<N>(n)).data(), f}; | ||
17942 | return l; | ||
17943 | } | ||
17944 | |||
17945 | struct registrar { | ||
17946 | registrar() = default; | ||
17947 | registrar(const registrar&) = default; | ||
17948 | registrar(registrar&&) = default; | ||
17949 | registrar& operator=(const registrar&) = default; | ||
17950 | registrar& operator=(registrar&&) = default; | ||
17951 | virtual int push_um(lua_State* L) = 0; | ||
17952 | virtual ~registrar() { | ||
17953 | } | ||
17954 | }; | ||
17955 | |||
17956 | inline bool is_toplevel(lua_State* L, int index = magic_index) { | ||
17957 | int isnum = 0; | ||
17958 | lua_Integer magic = lua_tointegerx(L, upvalue_index(index), &isnum); | ||
17959 | return isnum != 0 && magic == toplevel_magic; | ||
17960 | } | ||
17961 | |||
17962 | inline int runtime_object_call(lua_State* L, void*, int runtimetarget) { | ||
17963 | usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index)); | ||
17964 | std::vector<object>& runtime = umc.runtime; | ||
17965 | object& runtimeobj = runtime[runtimetarget]; | ||
17966 | return stack::push(L, runtimeobj); | ||
17967 | } | ||
17968 | |||
17969 | template <typename T, bool is_index> | ||
17970 | inline int indexing_fail(lua_State* L) { | ||
17971 | if (is_index) { | ||
17972 | #if 0 //defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE | ||
17973 | auto maybeaccessor = stack::get<optional<string_view>>(L, is_index ? -1 : -2); | ||
17974 | string_view accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); | ||
17975 | return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data()); | ||
17976 | #else | ||
17977 | if (is_toplevel(L)) { | ||
17978 | if (lua_getmetatable(L, 1) == 1) { | ||
17979 | int metatarget = lua_gettop(L); | ||
17980 | stack::get_field(L, stack_reference(L, raw_index(2)), metatarget); | ||
17981 | return 1; | ||
17982 | } | ||
17983 | } | ||
17984 | // With runtime extensibility, we can't hard-error things. They have to return nil, like regular table types, unfortunately... | ||
17985 | return stack::push(L, lua_nil); | ||
17986 | #endif | ||
17987 | } | ||
17988 | else { | ||
17989 | auto maybeaccessor = stack::get<optional<string_view>>(L, is_index ? -1 : -2); | ||
17990 | string_view accessor = maybeaccessor.value_or(string_view("(unknown)")); | ||
17991 | return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data()); | ||
17992 | } | ||
17993 | } | ||
17994 | |||
17995 | int runtime_new_index(lua_State* L, void*, int runtimetarget); | ||
17996 | |||
17997 | template <typename T, bool is_simple> | ||
17998 | inline int metatable_newindex(lua_State* L) { | ||
17999 | if (is_toplevel(L)) { | ||
18000 | auto non_indexable = [&L]() { | ||
18001 | if (is_simple) { | ||
18002 | simple_map& sm = stack::get<user<simple_map>>(L, upvalue_index(simple_metatable_index)); | ||
18003 | function_map& functions = sm.functions; | ||
18004 | optional<string_view> maybeaccessor = stack::get<optional<string_view>>(L, 2); | ||
18005 | if (!maybeaccessor) { | ||
18006 | return; | ||
18007 | } | ||
18008 | string_view& accessor_view = maybeaccessor.value(); | ||
18009 | #if defined(SOL_UNORDERED_MAP_COMPATIBLE_HASH) && SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
18010 | auto preexistingit = functions.find(accessor_view, string_view_hash(), std::equal_to<string_view>()); | ||
18011 | #else | ||
18012 | std::string accessor(accessor_view.data(), accessor_view.size()); | ||
18013 | auto preexistingit = functions.find(accessor); | ||
18014 | #endif | ||
18015 | if (preexistingit == functions.cend()) { | ||
18016 | #if defined(SOL_UNORDERED_MAP_COMPATIBLE_HASH) && SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
18017 | std::string accessor(accessor_view.data(), accessor_view.size()); | ||
18018 | #endif | ||
18019 | functions.emplace_hint(preexistingit, std::move(accessor), object(L, 3)); | ||
18020 | } | ||
18021 | else { | ||
18022 | preexistingit->second = object(L, 3); | ||
18023 | } | ||
18024 | return; | ||
18025 | } | ||
18026 | usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index)); | ||
18027 | bool mustindex = umc.mustindex; | ||
18028 | if (!mustindex) | ||
18029 | return; | ||
18030 | optional<string_view> maybeaccessor = stack::get<optional<string_view>>(L, 2); | ||
18031 | if (!maybeaccessor) { | ||
18032 | return; | ||
18033 | } | ||
18034 | string_view& accessor_view = maybeaccessor.value(); | ||
18035 | mapping_t& mapping = umc.mapping; | ||
18036 | std::vector<object>& runtime = umc.runtime; | ||
18037 | int target = static_cast<int>(runtime.size()); | ||
18038 | #if defined(SOL_UNORDERED_MAP_COMPATIBLE_HASH) && SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
18039 | auto preexistingit = mapping.find(accessor_view, string_view_hash(), std::equal_to<string_view>()); | ||
18040 | #else | ||
18041 | std::string accessor(accessor_view.data(), accessor_view.size()); | ||
18042 | auto preexistingit = mapping.find(accessor); | ||
18043 | #endif | ||
18044 | if (preexistingit == mapping.cend()) { | ||
18045 | #if defined(SOL_UNORDERED_MAP_COMPATIBLE_HASH) && SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
18046 | std::string accessor(accessor_view.data(), accessor_view.size()); | ||
18047 | #endif | ||
18048 | runtime.emplace_back(L, 3); | ||
18049 | mapping.emplace_hint(mapping.cend(), std::move(accessor), call_information(&runtime_object_call, &runtime_new_index, target)); | ||
18050 | } | ||
18051 | else { | ||
18052 | target = preexistingit->second.runtime_target; | ||
18053 | runtime[target] = object(L, 3); | ||
18054 | preexistingit->second = call_information(&runtime_object_call, &runtime_new_index, target); | ||
18055 | } | ||
18056 | }; | ||
18057 | non_indexable(); | ||
18058 | for (std::size_t i = 0; i < 4; lua_settop(L, 3), ++i) { | ||
18059 | const char* metakey = nullptr; | ||
18060 | switch (i) { | ||
18061 | case 0: | ||
18062 | metakey = &usertype_traits<T*>::metatable()[0]; | ||
18063 | luaL_getmetatable(L, metakey); | ||
18064 | break; | ||
18065 | case 1: | ||
18066 | metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; | ||
18067 | luaL_getmetatable(L, metakey); | ||
18068 | break; | ||
18069 | case 2: | ||
18070 | metakey = &usertype_traits<T>::metatable()[0]; | ||
18071 | luaL_getmetatable(L, metakey); | ||
18072 | break; | ||
18073 | case 3: | ||
18074 | default: | ||
18075 | metakey = &usertype_traits<T>::user_metatable()[0]; | ||
18076 | { | ||
18077 | luaL_getmetatable(L, metakey); | ||
18078 | lua_getmetatable(L, -1); | ||
18079 | } | ||
18080 | break; | ||
18081 | } | ||
18082 | int tableindex = lua_gettop(L); | ||
18083 | if (type_of(L, tableindex) == type::lua_nil) { | ||
18084 | continue; | ||
18085 | } | ||
18086 | stack::set_field<false, true>(L, stack_reference(L, raw_index(2)), stack_reference(L, raw_index(3)), tableindex); | ||
18087 | } | ||
18088 | lua_settop(L, 0); | ||
18089 | return 0; | ||
18090 | } | ||
18091 | return indexing_fail<T, false>(L); | ||
18092 | } | ||
18093 | |||
18094 | inline int runtime_new_index(lua_State* L, void*, int runtimetarget) { | ||
18095 | usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index)); | ||
18096 | std::vector<object>& runtime = umc.runtime; | ||
18097 | object& runtimeobj = runtime[runtimetarget]; | ||
18098 | runtimeobj = object(L, 3); | ||
18099 | return 0; | ||
18100 | } | ||
18101 | |||
18102 | template <bool is_index, typename Base> | ||
18103 | static void walk_single_base(lua_State* L, bool& found, int& ret, string_view&) { | ||
18104 | if (found) | ||
18105 | return; | ||
18106 | const char* metakey = &usertype_traits<Base>::metatable()[0]; | ||
18107 | const char* gcmetakey = &usertype_traits<Base>::gc_table()[0]; | ||
18108 | const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key(); | ||
18109 | |||
18110 | luaL_getmetatable(L, metakey); | ||
18111 | if (type_of(L, -1) == type::lua_nil) { | ||
18112 | lua_pop(L, 1); | ||
18113 | return; | ||
18114 | } | ||
18115 | |||
18116 | stack::get_field(L, basewalkkey); | ||
18117 | if (type_of(L, -1) == type::lua_nil) { | ||
18118 | lua_pop(L, 2); | ||
18119 | return; | ||
18120 | } | ||
18121 | lua_CFunction basewalkfunc = stack::pop<lua_CFunction>(L); | ||
18122 | lua_pop(L, 1); | ||
18123 | |||
18124 | stack::get_field<true>(L, gcmetakey); | ||
18125 | int value = basewalkfunc(L); | ||
18126 | if (value > -1) { | ||
18127 | found = true; | ||
18128 | ret = value; | ||
18129 | } | ||
18130 | } | ||
18131 | |||
18132 | template <bool is_index, typename... Bases> | ||
18133 | static void walk_all_bases(lua_State* L, bool& found, int& ret, string_view& accessor) { | ||
18134 | (void)L; | ||
18135 | (void)found; | ||
18136 | (void)ret; | ||
18137 | (void)accessor; | ||
18138 | (void)detail::swallow{0, (walk_single_base<is_index, Bases>(L, found, ret, accessor), 0)...}; | ||
18139 | } | ||
18140 | } // namespace usertype_detail | ||
18141 | |||
18142 | template <typename T> | ||
18143 | struct clean_type { | ||
18144 | typedef std::conditional_t<std::is_array<meta::unqualified_t<T>>::value, T&, std::decay_t<T>> type; | ||
18145 | }; | ||
18146 | |||
18147 | template <typename T> | ||
18148 | using clean_type_t = typename clean_type<T>::type; | ||
18149 | |||
18150 | template <typename T, typename IndexSequence, typename... Tn> | ||
18151 | struct usertype_metatable : usertype_detail::registrar {}; | ||
18152 | |||
18153 | template <typename T, std::size_t... I, typename... Tn> | ||
18154 | struct usertype_metatable<T, std::index_sequence<I...>, Tn...> : usertype_metatable_core, usertype_detail::registrar { | ||
18155 | typedef std::make_index_sequence<sizeof...(I) * 2> indices; | ||
18156 | typedef std::index_sequence<I...> half_indices; | ||
18157 | typedef std::array<luaL_Reg, sizeof...(Tn) / 2 + 1 + 31> regs_t; | ||
18158 | typedef std::tuple<Tn...> RawTuple; | ||
18159 | typedef std::tuple<clean_type_t<Tn>...> Tuple; | ||
18160 | template <std::size_t Idx> | ||
18161 | struct check_binding : is_variable_binding<meta::unqualified_tuple_element_t<Idx, Tuple>> {}; | ||
18162 | Tuple functions; | ||
18163 | lua_CFunction destructfunc; | ||
18164 | lua_CFunction callconstructfunc; | ||
18165 | lua_CFunction indexbase; | ||
18166 | lua_CFunction newindexbase; | ||
18167 | usertype_detail::base_walk indexbaseclasspropogation; | ||
18168 | usertype_detail::base_walk newindexbaseclasspropogation; | ||
18169 | void* baseclasscheck; | ||
18170 | void* baseclasscast; | ||
18171 | bool secondarymeta; | ||
18172 | std::bitset<32> properties; | ||
18173 | |||
18174 | template <std::size_t Idx, meta::enable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler> | ||
18175 | lua_CFunction make_func() const { | ||
18176 | return std::get<Idx + 1>(functions); | ||
18177 | } | ||
18178 | |||
18179 | template <std::size_t Idx, meta::disable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler> | ||
18180 | lua_CFunction make_func() const { | ||
18181 | const auto& name = std::get<Idx>(functions); | ||
18182 | return (usertype_detail::make_string_view(name) == "__newindex") ? &call<Idx + 1, false> : &call<Idx + 1, true>; | ||
18183 | } | ||
18184 | |||
18185 | static bool contains_variable() { | ||
18186 | typedef meta::any<check_binding<(I * 2 + 1)>...> has_variables; | ||
18187 | return has_variables::value; | ||
18188 | } | ||
18189 | |||
18190 | bool contains_index() const { | ||
18191 | bool idx = false; | ||
18192 | (void)detail::swallow{0, ((idx |= (usertype_detail::is_indexer(std::get<I * 2>(functions)) != 0)), 0)...}; | ||
18193 | return idx; | ||
18194 | } | ||
18195 | |||
18196 | int finish_regs(regs_t& l, int& index) { | ||
18197 | auto prop_fx = [&](meta_function mf) { return !properties[static_cast<int>(mf)]; }; | ||
18198 | usertype_detail::insert_default_registrations<T>(l, index, prop_fx); | ||
18199 | if (destructfunc != nullptr) { | ||
18200 | l[index] = luaL_Reg{to_string(meta_function::garbage_collect).c_str(), destructfunc}; | ||
18201 | ++index; | ||
18202 | } | ||
18203 | return index; | ||
18204 | } | ||
18205 | |||
18206 | template <std::size_t Idx, typename F> | ||
18207 | void make_regs(regs_t&, int&, call_construction, F&&) { | ||
18208 | callconstructfunc = call<Idx + 1>; | ||
18209 | secondarymeta = true; | ||
18210 | } | ||
18211 | |||
18212 | template <std::size_t, typename... Bases> | ||
18213 | void make_regs(regs_t&, int&, base_classes_tag, bases<Bases...>) { | ||
18214 | static_assert(!meta::any_same<T, Bases...>::value, "base classes cannot list the original class as part of the bases"); | ||
18215 | if (sizeof...(Bases) < 1) { | ||
18216 | return; | ||
18217 | } | ||
18218 | mustindex = true; | ||
18219 | (void)detail::swallow{0, ((detail::has_derived<Bases>::value = true), 0)...}; | ||
18220 | |||
18221 | static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); | ||
18222 | static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); | ||
18223 | baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check; | ||
18224 | baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast; | ||
18225 | indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>; | ||
18226 | newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>; | ||
18227 | } | ||
18228 | |||
18229 | template <std::size_t Idx, typename N, typename F, typename = std::enable_if_t<!meta::any_same<meta::unqualified_t<N>, base_classes_tag, call_construction>::value>> | ||
18230 | void make_regs(regs_t& l, int& index, N&& n, F&&) { | ||
18231 | if (is_variable_binding<meta::unqualified_t<F>>::value) { | ||
18232 | return; | ||
18233 | } | ||
18234 | luaL_Reg reg = usertype_detail::make_reg(std::forward<N>(n), make_func<Idx>()); | ||
18235 | for (std::size_t i = 0; i < properties.size(); ++i) { | ||
18236 | meta_function mf = static_cast<meta_function>(i); | ||
18237 | const std::string& mfname = to_string(mf); | ||
18238 | if (mfname == reg.name) { | ||
18239 | switch (mf) { | ||
18240 | case meta_function::construct: | ||
18241 | if (properties[i]) { | ||
18242 | #if !(defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS) | ||
18243 | throw error("sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems"); | ||
18244 | #else | ||
18245 | assert(false && "sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems"); | ||
18246 | #endif | ||
18247 | } | ||
18248 | break; | ||
18249 | case meta_function::garbage_collect: | ||
18250 | if (destructfunc != nullptr) { | ||
18251 | #if !(defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS) | ||
18252 | throw error("sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems"); | ||
18253 | #else | ||
18254 | assert(false && "sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems"); | ||
18255 | #endif | ||
18256 | } | ||
18257 | destructfunc = reg.func; | ||
18258 | return; | ||
18259 | case meta_function::index: | ||
18260 | indexfunc = reg.func; | ||
18261 | mustindex = true; | ||
18262 | properties.set(i); | ||
18263 | return; | ||
18264 | case meta_function::new_index: | ||
18265 | newindexfunc = reg.func; | ||
18266 | mustindex = true; | ||
18267 | properties.set(i); | ||
18268 | return; | ||
18269 | default: | ||
18270 | break; | ||
18271 | } | ||
18272 | properties.set(i); | ||
18273 | break; | ||
18274 | } | ||
18275 | } | ||
18276 | l[index] = reg; | ||
18277 | ++index; | ||
18278 | } | ||
18279 | |||
18280 | template <typename... Args, typename = std::enable_if_t<sizeof...(Args) == sizeof...(Tn)>> | ||
18281 | usertype_metatable(Args&&... args) | ||
18282 | : usertype_metatable_core(&usertype_detail::indexing_fail<T, true>, &usertype_detail::metatable_newindex<T, false>), usertype_detail::registrar(), functions(std::forward<Args>(args)...), destructfunc(nullptr), callconstructfunc(nullptr), indexbase(&core_indexing_call<true>), newindexbase(&core_indexing_call<false>), indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(usertype_detail::walk_all_bases<false>), baseclasscheck(nullptr), baseclasscast(nullptr), secondarymeta(contains_variable()), properties() { | ||
18283 | properties.reset(); | ||
18284 | std::initializer_list<typename usertype_detail::mapping_t::value_type> ilist{{std::pair<std::string, usertype_detail::call_information>(usertype_detail::make_string(std::get<I * 2>(functions)), | ||
18285 | usertype_detail::call_information(&usertype_metatable::real_find_call<I * 2, I * 2 + 1, true>, | ||
18286 | &usertype_metatable::real_find_call<I * 2, I * 2 + 1, false>))}...}; | ||
18287 | this->mapping.insert(ilist); | ||
18288 | for (const auto& n : meta_function_names()) { | ||
18289 | this->mapping.erase(n); | ||
18290 | } | ||
18291 | this->mustindex = contains_variable() || contains_index(); | ||
18292 | } | ||
18293 | |||
18294 | usertype_metatable(const usertype_metatable&) = default; | ||
18295 | usertype_metatable(usertype_metatable&&) = default; | ||
18296 | usertype_metatable& operator=(const usertype_metatable&) = default; | ||
18297 | usertype_metatable& operator=(usertype_metatable&&) = default; | ||
18298 | |||
18299 | template <std::size_t I0, std::size_t I1, bool is_index> | ||
18300 | static int real_find_call(lua_State* L, void* um, int) { | ||
18301 | auto& f = *static_cast<usertype_metatable*>(um); | ||
18302 | if (is_variable_binding<decltype(std::get<I1>(f.functions))>::value) { | ||
18303 | return real_call_with<I1, is_index, true>(L, f); | ||
18304 | } | ||
18305 | // set up upvalues | ||
18306 | // for a chained call | ||
18307 | int upvalues = 0; | ||
18308 | upvalues += stack::push(L, nullptr); | ||
18309 | upvalues += stack::push(L, light<usertype_metatable>(f)); | ||
18310 | auto cfunc = &call<I1, is_index>; | ||
18311 | return stack::push(L, c_closure(cfunc, upvalues)); | ||
18312 | } | ||
18313 | |||
18314 | template <bool is_index> | ||
18315 | static int real_meta_call(lua_State* L, void* um, int) { | ||
18316 | auto& f = *static_cast<usertype_metatable*>(um); | ||
18317 | return is_index ? f.indexfunc(L) : f.newindexfunc(L); | ||
18318 | } | ||
18319 | |||
18320 | template <bool is_index, bool toplevel = false> | ||
18321 | static int core_indexing_call(lua_State* L) { | ||
18322 | usertype_metatable& f = toplevel | ||
18323 | ? stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index)) | ||
18324 | : stack::pop<light<usertype_metatable>>(L); | ||
18325 | static const int keyidx = -2 + static_cast<int>(is_index); | ||
18326 | if (toplevel && stack::get<type>(L, keyidx) != type::string) { | ||
18327 | return is_index ? f.indexfunc(L) : f.newindexfunc(L); | ||
18328 | } | ||
18329 | int runtime_target = 0; | ||
18330 | usertype_detail::member_search member = nullptr; | ||
18331 | { | ||
18332 | #if defined(SOL_UNORDERED_MAP_COMPATIBLE_HASH) && SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
18333 | string_view name = stack::get<string_view>(L, keyidx); | ||
18334 | auto memberit = f.mapping.find(name, string_view_hash(), std::equal_to<string_view>()); | ||
18335 | #else | ||
18336 | std::string name = stack::get<std::string>(L, keyidx); | ||
18337 | auto memberit = f.mapping.find(name); | ||
18338 | #endif | ||
18339 | if (memberit != f.mapping.cend()) { | ||
18340 | const usertype_detail::call_information& ci = memberit->second; | ||
18341 | member = is_index ? ci.index : ci.new_index; | ||
18342 | runtime_target = ci.runtime_target; | ||
18343 | } | ||
18344 | } | ||
18345 | if (member != nullptr) { | ||
18346 | return (member)(L, static_cast<void*>(&f), runtime_target); | ||
18347 | } | ||
18348 | string_view accessor = stack::get<string_view>(L, keyidx); | ||
18349 | int ret = 0; | ||
18350 | bool found = false; | ||
18351 | // Otherwise, we need to do propagating calls through the bases | ||
18352 | if (is_index) | ||
18353 | f.indexbaseclasspropogation(L, found, ret, accessor); | ||
18354 | else | ||
18355 | f.newindexbaseclasspropogation(L, found, ret, accessor); | ||
18356 | if (found) { | ||
18357 | return ret; | ||
18358 | } | ||
18359 | return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1; | ||
18360 | } | ||
18361 | |||
18362 | static int real_index_call(lua_State* L) { | ||
18363 | return core_indexing_call<true, true>(L); | ||
18364 | } | ||
18365 | |||
18366 | static int real_new_index_call(lua_State* L) { | ||
18367 | return core_indexing_call<false, true>(L); | ||
18368 | } | ||
18369 | |||
18370 | template <std::size_t Idx, bool is_index = true, bool is_variable = false> | ||
18371 | static int real_call(lua_State* L) { | ||
18372 | usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index)); | ||
18373 | return real_call_with<Idx, is_index, is_variable>(L, f); | ||
18374 | } | ||
18375 | |||
18376 | template <std::size_t Idx, bool is_index = true, bool is_variable = false> | ||
18377 | static int real_call_with(lua_State* L, usertype_metatable& um) { | ||
18378 | typedef meta::unqualified_tuple_element_t<Idx - 1, Tuple> K; | ||
18379 | typedef meta::unqualified_tuple_element_t<Idx, Tuple> F; | ||
18380 | static const int boost = !detail::is_non_factory_constructor<F>::value | ||
18381 | && std::is_same<K, call_construction>::value | ||
18382 | ? 1 | ||
18383 | : 0; | ||
18384 | auto& f = std::get<Idx>(um.functions); | ||
18385 | return call_detail::call_wrapped<T, is_index, is_variable, boost>(L, f); | ||
18386 | } | ||
18387 | |||
18388 | template <std::size_t Idx, bool is_index = true, bool is_variable = false> | ||
18389 | static int call(lua_State* L) { | ||
18390 | return detail::typed_static_trampoline<decltype(&real_call<Idx, is_index, is_variable>), (&real_call<Idx, is_index, is_variable>)>(L); | ||
18391 | } | ||
18392 | |||
18393 | template <std::size_t Idx, bool is_index = true, bool is_variable = false> | ||
18394 | static int call_with(lua_State* L) { | ||
18395 | return detail::typed_static_trampoline<decltype(&real_call_with<Idx, is_index, is_variable>), (&real_call_with<Idx, is_index, is_variable>)>(L); | ||
18396 | } | ||
18397 | |||
18398 | static int index_call(lua_State* L) { | ||
18399 | return detail::typed_static_trampoline<decltype(&real_index_call), (&real_index_call)>(L); | ||
18400 | } | ||
18401 | |||
18402 | static int new_index_call(lua_State* L) { | ||
18403 | return detail::typed_static_trampoline<decltype(&real_new_index_call), (&real_new_index_call)>(L); | ||
18404 | } | ||
18405 | |||
18406 | virtual int push_um(lua_State* L) override { | ||
18407 | return stack::push(L, std::move(*this)); | ||
18408 | } | ||
18409 | |||
18410 | ~usertype_metatable() override { | ||
18411 | } | ||
18412 | }; | ||
18413 | |||
18414 | namespace stack { | ||
18415 | |||
18416 | template <typename T, std::size_t... I, typename... Args> | ||
18417 | struct pusher<usertype_metatable<T, std::index_sequence<I...>, Args...>> { | ||
18418 | typedef usertype_metatable<T, std::index_sequence<I...>, Args...> umt_t; | ||
18419 | typedef typename umt_t::regs_t regs_t; | ||
18420 | |||
18421 | static umt_t& make_cleanup(lua_State* L, umt_t&& umx) { | ||
18422 | // ensure some sort of uniqueness | ||
18423 | static int uniqueness = 0; | ||
18424 | std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable(); | ||
18425 | // std::to_string doesn't exist in android still, with NDK, so this bullshit | ||
18426 | // is necessary | ||
18427 | // thanks, Android :v | ||
18428 | int appended = snprintf(nullptr, 0, "%d", uniqueness); | ||
18429 | std::size_t insertionpoint = uniquegcmetakey.length() - 1; | ||
18430 | uniquegcmetakey.append(appended, '\0'); | ||
18431 | char* uniquetarget = &uniquegcmetakey[insertionpoint]; | ||
18432 | snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); | ||
18433 | ++uniqueness; | ||
18434 | |||
18435 | const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; | ||
18436 | // Make sure userdata's memory is properly in lua first, | ||
18437 | // otherwise all the light userdata we make later will become invalid | ||
18438 | stack::push<user<umt_t>>(L, metatable_key, uniquegcmetakey, std::move(umx)); | ||
18439 | // Create the top level thing that will act as our deleter later on | ||
18440 | stack_reference umt(L, -1); | ||
18441 | stack::set_field<true>(L, gcmetakey, umt); | ||
18442 | umt.pop(); | ||
18443 | |||
18444 | stack::get_field<true>(L, gcmetakey); | ||
18445 | umt_t& target_umt = stack::pop<user<umt_t>>(L); | ||
18446 | return target_umt; | ||
18447 | } | ||
18448 | |||
18449 | static int push(lua_State* L, umt_t&& umx) { | ||
18450 | |||
18451 | umt_t& um = make_cleanup(L, std::move(umx)); | ||
18452 | usertype_metatable_core& umc = um; | ||
18453 | regs_t value_table{{}}; | ||
18454 | int lastreg = 0; | ||
18455 | (void)detail::swallow{0, (um.template make_regs<(I * 2)>(value_table, lastreg, std::get<(I * 2)>(um.functions), std::get<(I * 2 + 1)>(um.functions)), 0)...}; | ||
18456 | um.finish_regs(value_table, lastreg); | ||
18457 | value_table[lastreg] = {nullptr, nullptr}; | ||
18458 | regs_t ref_table = value_table; | ||
18459 | regs_t unique_table = value_table; | ||
18460 | bool hasdestructor = !value_table.empty() && to_string(meta_function::garbage_collect) == value_table[lastreg - 1].name; | ||
18461 | if (hasdestructor) { | ||
18462 | ref_table[lastreg - 1] = {nullptr, nullptr}; | ||
18463 | } | ||
18464 | unique_table[lastreg - 1] = {value_table[lastreg - 1].name, detail::unique_destruct<T>}; | ||
18465 | |||
18466 | lua_createtable(L, 0, 2); | ||
18467 | stack_reference type_table(L, -1); | ||
18468 | |||
18469 | stack::set_field(L, "name", detail::demangle<T>(), type_table.stack_index()); | ||
18470 | stack::set_field(L, "is", &usertype_detail::is_check<T>, type_table.stack_index()); | ||
18471 | |||
18472 | // Now use um | ||
18473 | const bool& mustindex = umc.mustindex; | ||
18474 | for (std::size_t i = 0; i < 3; ++i) { | ||
18475 | // Pointer types, AKA "references" from C++ | ||
18476 | const char* metakey = nullptr; | ||
18477 | luaL_Reg* metaregs = nullptr; | ||
18478 | switch (i) { | ||
18479 | case 0: | ||
18480 | metakey = &usertype_traits<T*>::metatable()[0]; | ||
18481 | metaregs = ref_table.data(); | ||
18482 | break; | ||
18483 | case 1: | ||
18484 | metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; | ||
18485 | metaregs = unique_table.data(); | ||
18486 | break; | ||
18487 | case 2: | ||
18488 | default: | ||
18489 | metakey = &usertype_traits<T>::metatable()[0]; | ||
18490 | metaregs = value_table.data(); | ||
18491 | break; | ||
18492 | } | ||
18493 | luaL_newmetatable(L, metakey); | ||
18494 | stack_reference t(L, -1); | ||
18495 | stack::set_field(L, meta_function::type, type_table, t.stack_index()); | ||
18496 | int upvalues = 0; | ||
18497 | upvalues += stack::push(L, nullptr); | ||
18498 | upvalues += stack::push(L, make_light(um)); | ||
18499 | luaL_setfuncs(L, metaregs, upvalues); | ||
18500 | |||
18501 | if (um.baseclasscheck != nullptr) { | ||
18502 | stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index()); | ||
18503 | } | ||
18504 | if (um.baseclasscast != nullptr) { | ||
18505 | stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index()); | ||
18506 | } | ||
18507 | |||
18508 | stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, nullptr, make_light(um), make_light(umc)), t.stack_index()); | ||
18509 | stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, nullptr, make_light(um), make_light(umc)), t.stack_index()); | ||
18510 | |||
18511 | if (mustindex) { | ||
18512 | // Basic index pushing: specialize | ||
18513 | // index and newindex to give variables and stuff | ||
18514 | stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), t.stack_index()); | ||
18515 | stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), t.stack_index()); | ||
18516 | } | ||
18517 | else { | ||
18518 | // If there's only functions, we can use the fast index version | ||
18519 | stack::set_field(L, meta_function::index, t, t.stack_index()); | ||
18520 | } | ||
18521 | // metatable on the metatable | ||
18522 | // for call constructor purposes and such | ||
18523 | lua_createtable(L, 0, 3); | ||
18524 | stack_reference metabehind(L, -1); | ||
18525 | stack::set_field(L, meta_function::type, type_table, metabehind.stack_index()); | ||
18526 | if (um.callconstructfunc != nullptr) { | ||
18527 | stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), metabehind.stack_index()); | ||
18528 | } | ||
18529 | if (um.secondarymeta) { | ||
18530 | stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index()); | ||
18531 | stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index()); | ||
18532 | } | ||
18533 | // type information needs to be present on the behind-tables too | ||
18534 | |||
18535 | stack::set_field(L, metatable_key, metabehind, t.stack_index()); | ||
18536 | metabehind.pop(); | ||
18537 | // We want to just leave the table | ||
18538 | // in the registry only, otherwise we return it | ||
18539 | t.pop(); | ||
18540 | } | ||
18541 | |||
18542 | // Now for the shim-table that actually gets assigned to the name | ||
18543 | luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]); | ||
18544 | stack_reference t(L, -1); | ||
18545 | stack::set_field(L, meta_function::type, type_table, t.stack_index()); | ||
18546 | int upvalues = 0; | ||
18547 | upvalues += stack::push(L, nullptr); | ||
18548 | upvalues += stack::push(L, make_light(um)); | ||
18549 | luaL_setfuncs(L, value_table.data(), upvalues); | ||
18550 | { | ||
18551 | lua_createtable(L, 0, 3); | ||
18552 | stack_reference metabehind(L, -1); | ||
18553 | // type information needs to be present on the behind-tables too | ||
18554 | stack::set_field(L, meta_function::type, type_table, metabehind.stack_index()); | ||
18555 | if (um.callconstructfunc != nullptr) { | ||
18556 | stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), metabehind.stack_index()); | ||
18557 | } | ||
18558 | |||
18559 | stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index()); | ||
18560 | stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index()); | ||
18561 | stack::set_field(L, metatable_key, metabehind, t.stack_index()); | ||
18562 | metabehind.pop(); | ||
18563 | } | ||
18564 | |||
18565 | lua_remove(L, type_table.stack_index()); | ||
18566 | |||
18567 | return 1; | ||
18568 | } | ||
18569 | }; | ||
18570 | |||
18571 | } // namespace stack | ||
18572 | |||
18573 | } // namespace sol | ||
18574 | |||
18575 | // end of sol/usertype_metatable.hpp | ||
18576 | |||
18577 | // beginning of sol/simple_usertype_metatable.hpp | ||
18578 | |||
18579 | namespace sol { | ||
18580 | |||
18581 | namespace usertype_detail { | ||
18582 | inline int call_indexing_object(lua_State* L, object& f) { | ||
18583 | int before = lua_gettop(L); | ||
18584 | f.push(); | ||
18585 | for (int i = 1; i <= before; ++i) { | ||
18586 | lua_pushvalue(L, i); | ||
18587 | } | ||
18588 | lua_call(L, before, LUA_MULTRET); | ||
18589 | int after = lua_gettop(L); | ||
18590 | return after - before; | ||
18591 | } | ||
18592 | |||
18593 | template <typename T, bool is_index, bool toplevel = false, bool has_indexing = false> | ||
18594 | inline int simple_core_indexing_call(lua_State* L) { | ||
18595 | simple_map& sm = toplevel | ||
18596 | ? stack::get<user<simple_map>>(L, upvalue_index(simple_metatable_index)) | ||
18597 | : stack::pop<user<simple_map>>(L); | ||
18598 | variable_map& variables = sm.variables; | ||
18599 | function_map& functions = sm.functions; | ||
18600 | static const int keyidx = -2 + static_cast<int>(is_index); | ||
18601 | if (toplevel) { | ||
18602 | if (type_of(L, keyidx) != type::string) { | ||
18603 | if (has_indexing) { | ||
18604 | object& indexingfunc = is_index | ||
18605 | ? sm.index | ||
18606 | : sm.newindex; | ||
18607 | return call_indexing_object(L, indexingfunc); | ||
18608 | } | ||
18609 | else { | ||
18610 | return is_index | ||
18611 | ? indexing_fail<T, is_index>(L) | ||
18612 | : metatable_newindex<T, true>(L); | ||
18613 | } | ||
18614 | } | ||
18615 | } | ||
18616 | string_view accessor = stack::get<string_view>(L, keyidx); | ||
18617 | variable_wrapper* varwrap = nullptr; | ||
18618 | { | ||
18619 | #if defined(SOL_UNORDERED_MAP_COMPATIBLE_HASH) && SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
18620 | string_view& accessorkey = accessor; | ||
18621 | auto vit = variables.find(accessorkey, string_view_hash(), std::equal_to<string_view>()); | ||
18622 | #else | ||
18623 | std::string accessorkey(accessor.data(), accessor.size()); | ||
18624 | auto vit = variables.find(accessorkey); | ||
18625 | #endif // Compatible Hash | ||
18626 | if (vit != variables.cend()) { | ||
18627 | varwrap = vit->second.get(); | ||
18628 | } | ||
18629 | } | ||
18630 | if (varwrap != nullptr) { | ||
18631 | return is_index ? varwrap->index(L) : varwrap->new_index(L); | ||
18632 | } | ||
18633 | bool function_failed = false; | ||
18634 | { | ||
18635 | #if defined(SOL_UNORDERED_MAP_COMPATIBLE_HASH) && SOL_UNORDERED_MAP_COMPATIBLE_HASH | ||
18636 | string_view& accessorkey = accessor; | ||
18637 | auto fit = functions.find(accessorkey, string_view_hash(), std::equal_to<string_view>()); | ||
18638 | #else | ||
18639 | std::string accessorkey(accessor.data(), accessor.size()); | ||
18640 | auto fit = functions.find(accessorkey); | ||
18641 | #endif // Compatible Hash | ||
18642 | if (fit != functions.cend()) { | ||
18643 | object& func = fit->second; | ||
18644 | if (is_index) { | ||
18645 | return stack::push(L, func); | ||
18646 | } | ||
18647 | else { | ||
18648 | function_failed = true; | ||
18649 | } | ||
18650 | } | ||
18651 | } | ||
18652 | if (function_failed) { | ||
18653 | if (has_indexing && !is_toplevel(L)) { | ||
18654 | object& indexingfunc = is_index | ||
18655 | ? sm.index | ||
18656 | : sm.newindex; | ||
18657 | return call_indexing_object(L, indexingfunc); | ||
18658 | } | ||
18659 | else { | ||
18660 | return is_index | ||
18661 | ? indexing_fail<T, is_index>(L) | ||
18662 | : metatable_newindex<T, true>(L); | ||
18663 | } | ||
18664 | } | ||
18665 | /* Check table storage first for a method that works | ||
18666 | luaL_getmetatable(L, sm.metakey); | ||
18667 | if (type_of(L, -1) != type::lua_nil) { | ||
18668 | stack::get_field<false, true>(L, accessor.c_str(), lua_gettop(L)); | ||
18669 | if (type_of(L, -1) != type::lua_nil) { | ||
18670 | // Woo, we found it? | ||
18671 | lua_remove(L, -2); | ||
18672 | return 1; | ||
18673 | } | ||
18674 | lua_pop(L, 1); | ||
18675 | } | ||
18676 | lua_pop(L, 1); | ||
18677 | */ | ||
18678 | |||
18679 | int ret = 0; | ||
18680 | bool found = false; | ||
18681 | // Otherwise, we need to do propagating calls through the bases | ||
18682 | if (is_index) { | ||
18683 | sm.indexbaseclasspropogation(L, found, ret, accessor); | ||
18684 | } | ||
18685 | else { | ||
18686 | sm.newindexbaseclasspropogation(L, found, ret, accessor); | ||
18687 | } | ||
18688 | if (found) { | ||
18689 | return ret; | ||
18690 | } | ||
18691 | if (toplevel) { | ||
18692 | if (has_indexing && !is_toplevel(L)) { | ||
18693 | object& indexingfunc = is_index | ||
18694 | ? sm.index | ||
18695 | : sm.newindex; | ||
18696 | return call_indexing_object(L, indexingfunc); | ||
18697 | } | ||
18698 | else { | ||
18699 | return is_index | ||
18700 | ? indexing_fail<T, is_index>(L) | ||
18701 | : metatable_newindex<T, true>(L); | ||
18702 | } | ||
18703 | } | ||
18704 | return -1; | ||
18705 | } | ||
18706 | |||
18707 | template <typename T, bool has_indexing = false> | ||
18708 | inline int simple_real_index_call(lua_State* L) { | ||
18709 | return simple_core_indexing_call<T, true, true, has_indexing>(L); | ||
18710 | } | ||
18711 | |||
18712 | template <typename T, bool has_indexing = false> | ||
18713 | inline int simple_real_new_index_call(lua_State* L) { | ||
18714 | return simple_core_indexing_call<T, false, true, has_indexing>(L); | ||
18715 | } | ||
18716 | |||
18717 | template <typename T, bool has_indexing = false> | ||
18718 | inline int simple_index_call(lua_State* L) { | ||
18719 | #if defined(__clang__) | ||
18720 | return detail::trampoline(L, &simple_real_index_call<T, has_indexing>); | ||
18721 | #else | ||
18722 | return detail::typed_static_trampoline<decltype(&simple_real_index_call<T, has_indexing>), (&simple_real_index_call<T, has_indexing>)>(L); | ||
18723 | #endif | ||
18724 | } | ||
18725 | |||
18726 | template <typename T, bool has_indexing = false> | ||
18727 | inline int simple_new_index_call(lua_State* L) { | ||
18728 | #if defined(__clang__) | ||
18729 | return detail::trampoline(L, &simple_real_new_index_call<T, has_indexing>); | ||
18730 | #else | ||
18731 | return detail::typed_static_trampoline<decltype(&simple_real_new_index_call<T, has_indexing>), (&simple_real_new_index_call<T, has_indexing>)>(L); | ||
18732 | #endif | ||
18733 | } | ||
18734 | } // namespace usertype_detail | ||
18735 | |||
18736 | struct simple_tag { | ||
18737 | } const simple{}; | ||
18738 | |||
18739 | template <typename T> | ||
18740 | struct simple_usertype_metatable : usertype_detail::registrar { | ||
18741 | public: | ||
18742 | usertype_detail::function_map registrations; | ||
18743 | usertype_detail::variable_map varmap; | ||
18744 | object callconstructfunc; | ||
18745 | object indexfunc; | ||
18746 | object newindexfunc; | ||
18747 | lua_CFunction indexbase; | ||
18748 | lua_CFunction newindexbase; | ||
18749 | usertype_detail::base_walk indexbaseclasspropogation; | ||
18750 | usertype_detail::base_walk newindexbaseclasspropogation; | ||
18751 | void* baseclasscheck; | ||
18752 | void* baseclasscast; | ||
18753 | bool mustindex; | ||
18754 | bool secondarymeta; | ||
18755 | std::array<bool, 32> properties; | ||
18756 | |||
18757 | template <typename N> | ||
18758 | void insert(N&& n, object&& o) { | ||
18759 | std::string key = usertype_detail::make_string(std::forward<N>(n)); | ||
18760 | int is_indexer = static_cast<int>(usertype_detail::is_indexer(n)); | ||
18761 | if (is_indexer == 1) { | ||
18762 | indexfunc = o; | ||
18763 | mustindex = true; | ||
18764 | } | ||
18765 | else if (is_indexer == 2) { | ||
18766 | newindexfunc = o; | ||
18767 | mustindex = true; | ||
18768 | } | ||
18769 | auto hint = registrations.find(key); | ||
18770 | if (hint == registrations.cend()) { | ||
18771 | registrations.emplace_hint(hint, std::move(key), std::move(o)); | ||
18772 | return; | ||
18773 | } | ||
18774 | hint->second = std::move(o); | ||
18775 | } | ||
18776 | |||
18777 | template <typename N, typename F, typename... Args> | ||
18778 | void insert_prepare(std::true_type, lua_State* L, N&&, F&& f, Args&&... args) { | ||
18779 | object o = make_object<F>(L, std::forward<F>(f), function_detail::call_indicator(), std::forward<Args>(args)...); | ||
18780 | callconstructfunc = std::move(o); | ||
18781 | } | ||
18782 | |||
18783 | template <typename N, typename F, typename... Args> | ||
18784 | void insert_prepare(std::false_type, lua_State* L, N&& n, F&& f, Args&&... args) { | ||
18785 | object o = make_object<F>(L, std::forward<F>(f), std::forward<Args>(args)...); | ||
18786 | insert(std::forward<N>(n), std::move(o)); | ||
18787 | } | ||
18788 | |||
18789 | template <typename N, typename F> | ||
18790 | void add_member_function(std::true_type, lua_State* L, N&& n, F&& f) { | ||
18791 | insert_prepare(std::is_same<meta::unqualified_t<N>, call_construction>(), L, std::forward<N>(n), std::forward<F>(f), function_detail::class_indicator<T>()); | ||
18792 | } | ||
18793 | |||
18794 | template <typename N, typename F> | ||
18795 | void add_member_function(std::false_type, lua_State* L, N&& n, F&& f) { | ||
18796 | insert_prepare(std::is_same<meta::unqualified_t<N>, call_construction>(), L, std::forward<N>(n), std::forward<F>(f)); | ||
18797 | } | ||
18798 | |||
18799 | template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler> | ||
18800 | void add_function(lua_State* L, N&& n, F&& f) { | ||
18801 | object o = make_object(L, as_function_reference(std::forward<F>(f))); | ||
18802 | if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { | ||
18803 | callconstructfunc = std::move(o); | ||
18804 | return; | ||
18805 | } | ||
18806 | insert(std::forward<N>(n), std::move(o)); | ||
18807 | } | ||
18808 | |||
18809 | template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler> | ||
18810 | void add_function(lua_State* L, N&& n, F&& f) { | ||
18811 | add_member_function(std::is_member_pointer<meta::unwrap_unqualified_t<F>>(), L, std::forward<N>(n), std::forward<F>(f)); | ||
18812 | } | ||
18813 | |||
18814 | template <typename N, typename F, meta::disable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler> | ||
18815 | void add(lua_State* L, N&& n, F&& f) { | ||
18816 | add_function(L, std::forward<N>(n), std::forward<F>(f)); | ||
18817 | } | ||
18818 | |||
18819 | template <typename N, typename F, meta::enable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler> | ||
18820 | void add(lua_State*, N&& n, F&& f) { | ||
18821 | mustindex = true; | ||
18822 | secondarymeta = true; | ||
18823 | std::string key = usertype_detail::make_string(std::forward<N>(n)); | ||
18824 | auto o = std::make_unique<usertype_detail::callable_binding<T, std::decay_t<F>>>(std::forward<F>(f)); | ||
18825 | auto hint = varmap.find(key); | ||
18826 | if (hint == varmap.cend()) { | ||
18827 | varmap.emplace_hint(hint, std::move(key), std::move(o)); | ||
18828 | return; | ||
18829 | } | ||
18830 | hint->second = std::move(o); | ||
18831 | } | ||
18832 | |||
18833 | template <typename N, typename... Fxs> | ||
18834 | void add(lua_State* L, N&& n, constructor_wrapper<Fxs...> c) { | ||
18835 | object o(L, in_place_type<detail::tagged<T, constructor_wrapper<Fxs...>>>, std::move(c)); | ||
18836 | if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { | ||
18837 | callconstructfunc = std::move(o); | ||
18838 | return; | ||
18839 | } | ||
18840 | insert(std::forward<N>(n), std::move(o)); | ||
18841 | } | ||
18842 | |||
18843 | template <typename N, typename... Lists> | ||
18844 | void add(lua_State* L, N&& n, constructor_list<Lists...> c) { | ||
18845 | object o(L, in_place_type<detail::tagged<T, constructor_list<Lists...>>>, std::move(c)); | ||
18846 | if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { | ||
18847 | callconstructfunc = std::move(o); | ||
18848 | return; | ||
18849 | } | ||
18850 | insert(std::forward<N>(n), std::move(o)); | ||
18851 | } | ||
18852 | |||
18853 | template <typename N> | ||
18854 | void add(lua_State* L, N&& n, destructor_wrapper<void> c) { | ||
18855 | object o(L, in_place_type<detail::tagged<T, destructor_wrapper<void>>>, std::move(c)); | ||
18856 | if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { | ||
18857 | callconstructfunc = std::move(o); | ||
18858 | return; | ||
18859 | } | ||
18860 | insert(std::forward<N>(n), std::move(o)); | ||
18861 | } | ||
18862 | |||
18863 | template <typename N, typename Fx> | ||
18864 | void add(lua_State* L, N&& n, destructor_wrapper<Fx> c) { | ||
18865 | object o(L, in_place_type<detail::tagged<T, destructor_wrapper<Fx>>>, std::move(c)); | ||
18866 | if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { | ||
18867 | callconstructfunc = std::move(o); | ||
18868 | return; | ||
18869 | } | ||
18870 | insert(std::forward<N>(n), std::move(o)); | ||
18871 | } | ||
18872 | |||
18873 | template <typename... Bases> | ||
18874 | void add(lua_State*, base_classes_tag, bases<Bases...>) { | ||
18875 | static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform. Please file a bug report."); | ||
18876 | static_assert(!meta::any_same<T, Bases...>::value, "base classes cannot list the original class as part of the bases"); | ||
18877 | if (sizeof...(Bases) < 1) { | ||
18878 | return; | ||
18879 | } | ||
18880 | mustindex = true; | ||
18881 | (void)detail::swallow{0, ((detail::has_derived<Bases>::value = true), 0)...}; | ||
18882 | |||
18883 | static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report."); | ||
18884 | static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report."); | ||
18885 | baseclasscheck = reinterpret_cast<void*>(&detail::inheritance<T, Bases...>::type_check); | ||
18886 | baseclasscast = reinterpret_cast<void*>(&detail::inheritance<T, Bases...>::type_cast); | ||
18887 | indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>; | ||
18888 | newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>; | ||
18889 | } | ||
18890 | |||
18891 | private: | ||
18892 | template <std::size_t... I, typename Tuple> | ||
18893 | simple_usertype_metatable(detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args) | ||
18894 | : callconstructfunc(lua_nil), indexfunc(lua_nil), newindexfunc(lua_nil), indexbase(&usertype_detail::simple_core_indexing_call<T, true>), newindexbase(&usertype_detail::simple_core_indexing_call<T, false>), indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>), baseclasscheck(nullptr), baseclasscast(nullptr), mustindex(false), secondarymeta(false), properties() { | ||
18895 | properties.fill(false); | ||
18896 | |||
18897 | (void)detail::swallow{0, | ||
18898 | (add(L, detail::forward_get<I * 2>(args), detail::forward_get<I * 2 + 1>(args)), 0)...}; | ||
18899 | } | ||
18900 | |||
18901 | template <typename... Args> | ||
18902 | simple_usertype_metatable(lua_State* L, detail::verified_tag v, Args&&... args) | ||
18903 | : simple_usertype_metatable(v, std::make_index_sequence<sizeof...(Args) / 2>(), L, std::forward_as_tuple(std::forward<Args>(args)...)) { | ||
18904 | } | ||
18905 | |||
18906 | template <typename... Args> | ||
18907 | simple_usertype_metatable(lua_State* L, detail::add_destructor_tag, Args&&... args) | ||
18908 | : simple_usertype_metatable(L, detail::verified, std::forward<Args>(args)..., "__gc", default_destructor) { | ||
18909 | } | ||
18910 | |||
18911 | template <typename... Args> | ||
18912 | simple_usertype_metatable(lua_State* L, detail::check_destructor_tag, Args&&... args) | ||
18913 | : simple_usertype_metatable(L, meta::condition<meta::all<std::is_destructible<T>, meta::neg<detail::has_destructor<Args...>>>, detail::add_destructor_tag, detail::verified_tag>(), std::forward<Args>(args)...) { | ||
18914 | } | ||
18915 | |||
18916 | public: | ||
18917 | simple_usertype_metatable(lua_State* L) | ||
18918 | : simple_usertype_metatable(L, meta::condition<meta::all<std::is_default_constructible<T>>, decltype(default_constructor), detail::check_destructor_tag>()) { | ||
18919 | } | ||
18920 | |||
18921 | template <typename Arg, typename... Args, meta::disable_any<meta::any_same<meta::unqualified_t<Arg>, detail::verified_tag, detail::add_destructor_tag, detail::check_destructor_tag>, meta::is_specialization_of<meta::unqualified_t<Arg>, constructors>, meta::is_specialization_of<meta::unqualified_t<Arg>, constructor_wrapper>> = meta::enabler> | ||
18922 | simple_usertype_metatable(lua_State* L, Arg&& arg, Args&&... args) | ||
18923 | : simple_usertype_metatable(L, meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<detail::has_constructor<Args...>>>, decltype(default_constructor), detail::check_destructor_tag>(), std::forward<Arg>(arg), std::forward<Args>(args)...) { | ||
18924 | } | ||
18925 | |||
18926 | template <typename... Args, typename... CArgs> | ||
18927 | simple_usertype_metatable(lua_State* L, constructors<CArgs...> constructorlist, Args&&... args) | ||
18928 | : simple_usertype_metatable(L, detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) { | ||
18929 | } | ||
18930 | |||
18931 | template <typename... Args, typename... Fxs> | ||
18932 | simple_usertype_metatable(lua_State* L, constructor_wrapper<Fxs...> constructorlist, Args&&... args) | ||
18933 | : simple_usertype_metatable(L, detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) { | ||
18934 | } | ||
18935 | |||
18936 | simple_usertype_metatable(const simple_usertype_metatable&) = default; | ||
18937 | simple_usertype_metatable(simple_usertype_metatable&&) = default; | ||
18938 | simple_usertype_metatable& operator=(const simple_usertype_metatable&) = default; | ||
18939 | simple_usertype_metatable& operator=(simple_usertype_metatable&&) = default; | ||
18940 | |||
18941 | virtual int push_um(lua_State* L) override { | ||
18942 | return stack::push(L, std::move(*this)); | ||
18943 | } | ||
18944 | }; | ||
18945 | |||
18946 | namespace stack { | ||
18947 | template <typename T> | ||
18948 | struct pusher<simple_usertype_metatable<T>> { | ||
18949 | typedef simple_usertype_metatable<T> umt_t; | ||
18950 | |||
18951 | static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) { | ||
18952 | static int uniqueness = 0; | ||
18953 | std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable(); | ||
18954 | // std::to_string doesn't exist in android still, with NDK, so this bullshit | ||
18955 | // is necessary | ||
18956 | // thanks, Android :v | ||
18957 | int appended = snprintf(nullptr, 0, "%d", uniqueness); | ||
18958 | std::size_t insertionpoint = uniquegcmetakey.length() - 1; | ||
18959 | uniquegcmetakey.append(appended, '\0'); | ||
18960 | char* uniquetarget = &uniquegcmetakey[insertionpoint]; | ||
18961 | snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); | ||
18962 | ++uniqueness; | ||
18963 | |||
18964 | const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; | ||
18965 | stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable()[0], | ||
18966 | umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, | ||
18967 | std::move(umx.indexfunc), std::move(umx.newindexfunc), | ||
18968 | std::move(umx.varmap), std::move(umx.registrations)); | ||
18969 | stack_reference stackvarmap(L, -1); | ||
18970 | stack::set_field<true>(L, gcmetakey, stackvarmap); | ||
18971 | stackvarmap.pop(); | ||
18972 | |||
18973 | stack::get_field<true>(L, gcmetakey); | ||
18974 | usertype_detail::simple_map& varmap = stack::pop<user<usertype_detail::simple_map>>(L); | ||
18975 | return varmap; | ||
18976 | } | ||
18977 | |||
18978 | static int push(lua_State* L, umt_t&& umx) { | ||
18979 | bool hasindex = umx.indexfunc.valid(); | ||
18980 | bool hasnewindex = umx.newindexfunc.valid(); | ||
18981 | auto& varmap = make_cleanup(L, umx); | ||
18982 | auto& properties = umx.properties; | ||
18983 | auto sic = hasindex ? &usertype_detail::simple_index_call<T, true> : &usertype_detail::simple_index_call<T, false>; | ||
18984 | auto snic = hasnewindex ? &usertype_detail::simple_new_index_call<T, true> : &usertype_detail::simple_new_index_call<T, false>; | ||
18985 | |||
18986 | lua_createtable(L, 0, 2); | ||
18987 | stack_reference type_table(L, -1); | ||
18988 | |||
18989 | stack::set_field(L, "name", detail::demangle<T>(), type_table.stack_index()); | ||
18990 | stack::set_field(L, "is", &usertype_detail::is_check<T>, type_table.stack_index()); | ||
18991 | |||
18992 | auto safety_check = [&](const std::string& first) { | ||
18993 | for (std::size_t j = 0; j < properties.size(); ++j) { | ||
18994 | meta_function mf = static_cast<meta_function>(j); | ||
18995 | const std::string& mfname = to_string(mf); | ||
18996 | bool& prop = properties[j]; | ||
18997 | if (mfname != first) | ||
18998 | continue; | ||
18999 | switch (mf) { | ||
19000 | case meta_function::construct: | ||
19001 | if (prop) { | ||
19002 | #if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS | ||
19003 | assert(false && "sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems"); | ||
19004 | #else | ||
19005 | throw error("sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems"); | ||
19006 | #endif | ||
19007 | } | ||
19008 | break; | ||
19009 | case meta_function::garbage_collect: | ||
19010 | if (prop) { | ||
19011 | #if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS | ||
19012 | assert(false && "sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems"); | ||
19013 | #else | ||
19014 | throw error("sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems"); | ||
19015 | #endif | ||
19016 | } | ||
19017 | return; | ||
19018 | default: | ||
19019 | break; | ||
19020 | } | ||
19021 | prop = true; | ||
19022 | break; | ||
19023 | } | ||
19024 | }; | ||
19025 | |||
19026 | for (auto& kvp : varmap.functions) { | ||
19027 | auto& first = std::get<0>(kvp); | ||
19028 | safety_check(first); | ||
19029 | } | ||
19030 | |||
19031 | auto register_kvp = [&](std::size_t meta_index, stack_reference& t, const std::string& first, object& second) { | ||
19032 | meta_function mf = meta_function::construct; | ||
19033 | for (std::size_t j = 0; j < properties.size(); ++j) { | ||
19034 | mf = static_cast<meta_function>(j); | ||
19035 | const std::string& mfname = to_string(mf); | ||
19036 | bool& prop = properties[j]; | ||
19037 | if (mfname != first) | ||
19038 | continue; | ||
19039 | switch (mf) { | ||
19040 | case meta_function::index: | ||
19041 | umx.indexfunc = second; | ||
19042 | break; | ||
19043 | case meta_function::new_index: | ||
19044 | umx.newindexfunc = second; | ||
19045 | break; | ||
19046 | default: | ||
19047 | break; | ||
19048 | } | ||
19049 | prop = true; | ||
19050 | break; | ||
19051 | } | ||
19052 | switch (meta_index) { | ||
19053 | case 0: | ||
19054 | if (mf == meta_function::garbage_collect) { | ||
19055 | return; | ||
19056 | } | ||
19057 | break; | ||
19058 | case 1: | ||
19059 | if (mf == meta_function::garbage_collect) { | ||
19060 | stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index()); | ||
19061 | return; | ||
19062 | } | ||
19063 | break; | ||
19064 | case 2: | ||
19065 | default: | ||
19066 | break; | ||
19067 | } | ||
19068 | stack::set_field(L, first, second, t.stack_index()); | ||
19069 | }; | ||
19070 | for (std::size_t i = 0; i < 3; ++i) { | ||
19071 | const char* metakey = nullptr; | ||
19072 | switch (i) { | ||
19073 | case 0: | ||
19074 | metakey = &usertype_traits<T*>::metatable()[0]; | ||
19075 | break; | ||
19076 | case 1: | ||
19077 | metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; | ||
19078 | break; | ||
19079 | case 2: | ||
19080 | default: | ||
19081 | metakey = &usertype_traits<T>::metatable()[0]; | ||
19082 | break; | ||
19083 | } | ||
19084 | luaL_newmetatable(L, metakey); | ||
19085 | stack_reference t(L, -1); | ||
19086 | stack::set_field(L, meta_function::type, type_table, t.stack_index()); | ||
19087 | |||
19088 | for (auto& kvp : varmap.functions) { | ||
19089 | auto& first = std::get<0>(kvp); | ||
19090 | auto& second = std::get<1>(kvp); | ||
19091 | register_kvp(i, t, first, second); | ||
19092 | } | ||
19093 | luaL_Reg opregs[34]{}; | ||
19094 | int opregsindex = 0; | ||
19095 | auto prop_fx = [&](meta_function mf) { return !properties[static_cast<int>(mf)]; }; | ||
19096 | usertype_detail::insert_default_registrations<T>(opregs, opregsindex, prop_fx); | ||
19097 | t.push(); | ||
19098 | luaL_setfuncs(L, opregs, 0); | ||
19099 | t.pop(); | ||
19100 | |||
19101 | if (umx.baseclasscheck != nullptr) { | ||
19102 | stack::set_field(L, detail::base_class_check_key(), umx.baseclasscheck, t.stack_index()); | ||
19103 | } | ||
19104 | if (umx.baseclasscast != nullptr) { | ||
19105 | stack::set_field(L, detail::base_class_cast_key(), umx.baseclasscast, t.stack_index()); | ||
19106 | } | ||
19107 | |||
19108 | // Base class propagation features | ||
19109 | stack::set_field(L, detail::base_class_index_propogation_key(), umx.indexbase, t.stack_index()); | ||
19110 | stack::set_field(L, detail::base_class_new_index_propogation_key(), umx.newindexbase, t.stack_index()); | ||
19111 | |||
19112 | if (umx.mustindex) { | ||
19113 | // use indexing function | ||
19114 | stack::set_field(L, meta_function::index, | ||
19115 | make_closure(sic, | ||
19116 | nullptr, | ||
19117 | make_light(varmap)), | ||
19118 | t.stack_index()); | ||
19119 | stack::set_field(L, meta_function::new_index, | ||
19120 | make_closure(snic, | ||
19121 | nullptr, | ||
19122 | make_light(varmap)), | ||
19123 | t.stack_index()); | ||
19124 | } | ||
19125 | else { | ||
19126 | // Metatable indexes itself | ||
19127 | stack::set_field(L, meta_function::index, t, t.stack_index()); | ||
19128 | } | ||
19129 | // metatable on the metatable | ||
19130 | // for call constructor purposes and such | ||
19131 | lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid())); | ||
19132 | stack_reference metabehind(L, -1); | ||
19133 | stack::set_field(L, meta_function::type, type_table, metabehind.stack_index()); | ||
19134 | if (umx.callconstructfunc.valid()) { | ||
19135 | stack::set_field(L, meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); | ||
19136 | } | ||
19137 | if (umx.secondarymeta) { | ||
19138 | stack::set_field(L, meta_function::index, | ||
19139 | make_closure(sic, | ||
19140 | nullptr, | ||
19141 | make_light(varmap)), | ||
19142 | metabehind.stack_index()); | ||
19143 | stack::set_field(L, meta_function::new_index, | ||
19144 | make_closure(snic, | ||
19145 | nullptr, | ||
19146 | make_light(varmap)), | ||
19147 | metabehind.stack_index()); | ||
19148 | } | ||
19149 | stack::set_field(L, metatable_key, metabehind, t.stack_index()); | ||
19150 | metabehind.pop(); | ||
19151 | |||
19152 | t.pop(); | ||
19153 | } | ||
19154 | |||
19155 | // Now for the shim-table that actually gets pushed | ||
19156 | luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]); | ||
19157 | stack_reference t(L, -1); | ||
19158 | stack::set_field(L, meta_function::type, type_table, t.stack_index()); | ||
19159 | |||
19160 | for (auto& kvp : varmap.functions) { | ||
19161 | auto& first = std::get<0>(kvp); | ||
19162 | auto& second = std::get<1>(kvp); | ||
19163 | register_kvp(2, t, first, second); | ||
19164 | } | ||
19165 | { | ||
19166 | lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid())); | ||
19167 | stack_reference metabehind(L, -1); | ||
19168 | stack::set_field(L, meta_function::type, type_table, metabehind.stack_index()); | ||
19169 | if (umx.callconstructfunc.valid()) { | ||
19170 | stack::set_field(L, meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); | ||
19171 | } | ||
19172 | // use indexing function | ||
19173 | stack::set_field(L, meta_function::index, | ||
19174 | make_closure(sic, | ||
19175 | nullptr, | ||
19176 | make_light(varmap), | ||
19177 | nullptr, | ||
19178 | nullptr, | ||
19179 | usertype_detail::toplevel_magic), | ||
19180 | metabehind.stack_index()); | ||
19181 | stack::set_field(L, meta_function::new_index, | ||
19182 | make_closure(snic, | ||
19183 | nullptr, | ||
19184 | make_light(varmap), | ||
19185 | nullptr, | ||
19186 | nullptr, | ||
19187 | usertype_detail::toplevel_magic), | ||
19188 | metabehind.stack_index()); | ||
19189 | stack::set_field(L, metatable_key, metabehind, t.stack_index()); | ||
19190 | metabehind.pop(); | ||
19191 | } | ||
19192 | |||
19193 | lua_remove(L, type_table.stack_index()); | ||
19194 | |||
19195 | // Don't pop the table when we're done; | ||
19196 | // return it | ||
19197 | return 1; | ||
19198 | } | ||
19199 | }; | ||
19200 | } // namespace stack | ||
19201 | } // namespace sol | ||
19202 | |||
19203 | // end of sol/simple_usertype_metatable.hpp | ||
19204 | |||
19205 | namespace sol { | ||
19206 | |||
19207 | template <typename T> | ||
19208 | class usertype { | ||
19209 | private: | ||
19210 | std::unique_ptr<usertype_detail::registrar, detail::deleter> metatableregister; | ||
19211 | |||
19212 | template <typename... Args> | ||
19213 | usertype(detail::verified_tag, Args&&... args) | ||
19214 | : metatableregister(detail::make_unique_deleter<usertype_metatable<T, std::make_index_sequence<sizeof...(Args) / 2>, Args...>, detail::deleter>(std::forward<Args>(args)...)) { | ||
19215 | static_assert(detail::has_destructor<Args...>::value, "this type does not have an explicit destructor declared; please pass a custom destructor function wrapped in sol::destruct, especially if the type does not have an accessible (private) destructor"); | ||
19216 | } | ||
19217 | |||
19218 | template <typename... Args> | ||
19219 | usertype(detail::add_destructor_tag, Args&&... args) | ||
19220 | : usertype(detail::verified, std::forward<Args>(args)..., "__gc", default_destructor) { | ||
19221 | } | ||
19222 | |||
19223 | template <typename... Args> | ||
19224 | usertype(detail::check_destructor_tag, Args&&... args) | ||
19225 | : usertype(meta::condition<meta::all<std::is_destructible<T>, meta::neg<detail::has_destructor<Args...>>>, detail::add_destructor_tag, detail::verified_tag>(), std::forward<Args>(args)...) { | ||
19226 | } | ||
19227 | |||
19228 | public: | ||
19229 | template <typename... Args> | ||
19230 | usertype(Args&&... args) | ||
19231 | : usertype(meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<detail::has_constructor<Args...>>>, decltype(default_constructor), detail::check_destructor_tag>(), std::forward<Args>(args)...) { | ||
19232 | } | ||
19233 | |||
19234 | template <typename... Args, typename... CArgs> | ||
19235 | usertype(constructors<CArgs...> constructorlist, Args&&... args) | ||
19236 | : usertype(detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) { | ||
19237 | } | ||
19238 | |||
19239 | template <typename... Args, typename... Fxs> | ||
19240 | usertype(constructor_wrapper<Fxs...> constructorlist, Args&&... args) | ||
19241 | : usertype(detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) { | ||
19242 | } | ||
19243 | |||
19244 | template <typename... Args> | ||
19245 | usertype(simple_tag, lua_State* L, Args&&... args) | ||
19246 | : metatableregister(detail::make_unique_deleter<simple_usertype_metatable<T>, detail::deleter>(L, std::forward<Args>(args)...)) { | ||
19247 | } | ||
19248 | |||
19249 | usertype_detail::registrar* registrar_data() { | ||
19250 | return metatableregister.get(); | ||
19251 | } | ||
19252 | |||
19253 | int push(lua_State* L) { | ||
19254 | int r = metatableregister->push_um(L); | ||
19255 | metatableregister = nullptr; | ||
19256 | return r; | ||
19257 | } | ||
19258 | }; | ||
19259 | |||
19260 | template <typename T> | ||
19261 | class simple_usertype : public usertype<T> { | ||
19262 | private: | ||
19263 | typedef usertype<T> base_t; | ||
19264 | lua_State* state; | ||
19265 | |||
19266 | public: | ||
19267 | template <typename... Args> | ||
19268 | simple_usertype(lua_State* L, Args&&... args) | ||
19269 | : base_t(simple, L, std::forward<Args>(args)...), state(L) { | ||
19270 | } | ||
19271 | |||
19272 | template <typename N, typename F> | ||
19273 | void set(N&& n, F&& f) { | ||
19274 | auto meta = static_cast<simple_usertype_metatable<T>*>(base_t::registrar_data()); | ||
19275 | meta->add(state, std::forward<N>(n), std::forward<F>(f)); | ||
19276 | } | ||
19277 | }; | ||
19278 | |||
19279 | namespace stack { | ||
19280 | template <typename T> | ||
19281 | struct pusher<usertype<T>> { | ||
19282 | static int push(lua_State* L, usertype<T>& user) { | ||
19283 | return user.push(L); | ||
19284 | } | ||
19285 | }; | ||
19286 | } // namespace stack | ||
19287 | } // namespace sol | ||
19288 | |||
19289 | // end of sol/usertype.hpp | ||
19290 | |||
19291 | // beginning of sol/table_iterator.hpp | ||
19292 | |||
19293 | namespace sol { | ||
19294 | |||
19295 | template <typename reference_type> | ||
19296 | class basic_table_iterator : public std::iterator<std::input_iterator_tag, std::pair<object, object>> { | ||
19297 | public: | ||
19298 | typedef object key_type; | ||
19299 | typedef object mapped_type; | ||
19300 | typedef std::pair<object, object> value_type; | ||
19301 | typedef std::input_iterator_tag iterator_category; | ||
19302 | typedef std::ptrdiff_t difference_type; | ||
19303 | typedef value_type* pointer; | ||
19304 | typedef value_type& reference; | ||
19305 | typedef const value_type& const_reference; | ||
19306 | |||
19307 | private: | ||
19308 | std::pair<object, object> kvp; | ||
19309 | reference_type ref; | ||
19310 | int tableidx = 0; | ||
19311 | int keyidx = 0; | ||
19312 | std::ptrdiff_t idx = 0; | ||
19313 | |||
19314 | public: | ||
19315 | basic_table_iterator() | ||
19316 | : keyidx(-1), idx(-1) { | ||
19317 | } | ||
19318 | |||
19319 | basic_table_iterator(reference_type x) | ||
19320 | : ref(std::move(x)) { | ||
19321 | ref.push(); | ||
19322 | tableidx = lua_gettop(ref.lua_state()); | ||
19323 | stack::push(ref.lua_state(), lua_nil); | ||
19324 | this->operator++(); | ||
19325 | if (idx == -1) { | ||
19326 | return; | ||
19327 | } | ||
19328 | --idx; | ||
19329 | } | ||
19330 | |||
19331 | basic_table_iterator& operator++() { | ||
19332 | if (idx == -1) | ||
19333 | return *this; | ||
19334 | |||
19335 | if (lua_next(ref.lua_state(), tableidx) == 0) { | ||
19336 | idx = -1; | ||
19337 | keyidx = -1; | ||
19338 | return *this; | ||
19339 | } | ||
19340 | ++idx; | ||
19341 | kvp.first = object(ref.lua_state(), -2); | ||
19342 | kvp.second = object(ref.lua_state(), -1); | ||
19343 | lua_pop(ref.lua_state(), 1); | ||
19344 | // leave key on the stack | ||
19345 | keyidx = lua_gettop(ref.lua_state()); | ||
19346 | return *this; | ||
19347 | } | ||
19348 | |||
19349 | basic_table_iterator operator++(int) { | ||
19350 | auto saved = *this; | ||
19351 | this->operator++(); | ||
19352 | return saved; | ||
19353 | } | ||
19354 | |||
19355 | reference operator*() { | ||
19356 | return kvp; | ||
19357 | } | ||
19358 | |||
19359 | const_reference operator*() const { | ||
19360 | return kvp; | ||
19361 | } | ||
19362 | |||
19363 | bool operator==(const basic_table_iterator& right) const { | ||
19364 | return idx == right.idx; | ||
19365 | } | ||
19366 | |||
19367 | bool operator!=(const basic_table_iterator& right) const { | ||
19368 | return idx != right.idx; | ||
19369 | } | ||
19370 | |||
19371 | ~basic_table_iterator() { | ||
19372 | if (keyidx != -1) { | ||
19373 | stack::remove(ref.lua_state(), keyidx, 1); | ||
19374 | } | ||
19375 | if (ref.valid()) { | ||
19376 | stack::remove(ref.lua_state(), tableidx, 1); | ||
19377 | } | ||
19378 | } | ||
19379 | }; | ||
19380 | |||
19381 | } // namespace sol | ||
19382 | |||
19383 | // end of sol/table_iterator.hpp | ||
19384 | |||
19385 | namespace sol { | ||
19386 | namespace detail { | ||
19387 | template <std::size_t n> | ||
19388 | struct clean { | ||
19389 | lua_State* L; | ||
19390 | clean(lua_State* luastate) | ||
19391 | : L(luastate) { | ||
19392 | } | ||
19393 | ~clean() { | ||
19394 | lua_pop(L, static_cast<int>(n)); | ||
19395 | } | ||
19396 | }; | ||
19397 | struct ref_clean { | ||
19398 | lua_State* L; | ||
19399 | int& n; | ||
19400 | ref_clean(lua_State* luastate, int& n) | ||
19401 | : L(luastate), n(n) { | ||
19402 | } | ||
19403 | ~ref_clean() { | ||
19404 | lua_pop(L, static_cast<int>(n)); | ||
19405 | } | ||
19406 | }; | ||
19407 | inline int fail_on_newindex(lua_State* L) { | ||
19408 | return luaL_error(L, "sol: cannot modify the elements of an enumeration table"); | ||
19409 | } | ||
19410 | } // namespace detail | ||
19411 | |||
19412 | const new_table create = new_table{}; | ||
19413 | |||
19414 | template <bool top_level, typename base_type> | ||
19415 | class basic_table_core : public basic_object_base<base_type> { | ||
19416 | typedef basic_object_base<base_type> base_t; | ||
19417 | friend class state; | ||
19418 | friend class state_view; | ||
19419 | |||
19420 | template <typename... Args> | ||
19421 | using is_global = meta::all<meta::boolean<top_level>, meta::is_c_str<Args>...>; | ||
19422 | |||
19423 | template <typename Fx> | ||
19424 | void for_each(std::true_type, Fx&& fx) const { | ||
19425 | auto pp = stack::push_pop(*this); | ||
19426 | stack::push(base_t::lua_state(), lua_nil); | ||
19427 | while (lua_next(base_t::lua_state(), -2)) { | ||
19428 | object key(base_t::lua_state(), -2); | ||
19429 | object value(base_t::lua_state(), -1); | ||
19430 | std::pair<object&, object&> keyvalue(key, value); | ||
19431 | auto pn = stack::pop_n(base_t::lua_state(), 1); | ||
19432 | fx(keyvalue); | ||
19433 | } | ||
19434 | } | ||
19435 | |||
19436 | template <typename Fx> | ||
19437 | void for_each(std::false_type, Fx&& fx) const { | ||
19438 | auto pp = stack::push_pop(*this); | ||
19439 | stack::push(base_t::lua_state(), lua_nil); | ||
19440 | while (lua_next(base_t::lua_state(), -2)) { | ||
19441 | object key(base_t::lua_state(), -2); | ||
19442 | object value(base_t::lua_state(), -1); | ||
19443 | auto pn = stack::pop_n(base_t::lua_state(), 1); | ||
19444 | fx(key, value); | ||
19445 | } | ||
19446 | } | ||
19447 | |||
19448 | template <bool raw, typename Ret0, typename Ret1, typename... Ret, std::size_t... I, typename Keys> | ||
19449 | auto tuple_get(types<Ret0, Ret1, Ret...>, std::index_sequence<0, 1, I...>, Keys&& keys) const | ||
19450 | -> decltype(stack::pop<std::tuple<Ret0, Ret1, Ret...>>(nullptr)) { | ||
19451 | typedef decltype(stack::pop<std::tuple<Ret0, Ret1, Ret...>>(nullptr)) Tup; | ||
19452 | return Tup( | ||
19453 | traverse_get_optional<top_level, raw, Ret0>(meta::is_optional<meta::unqualified_t<Ret0>>(), detail::forward_get<0>(keys)), | ||
19454 | traverse_get_optional<top_level, raw, Ret1>(meta::is_optional<meta::unqualified_t<Ret1>>(), detail::forward_get<1>(keys)), | ||
19455 | traverse_get_optional<top_level, raw, Ret>(meta::is_optional<meta::unqualified_t<Ret>>(), detail::forward_get<I>(keys))...); | ||
19456 | } | ||
19457 | |||
19458 | template <bool raw, typename Ret, std::size_t I, typename Keys> | ||
19459 | decltype(auto) tuple_get(types<Ret>, std::index_sequence<I>, Keys&& keys) const { | ||
19460 | return traverse_get_optional<top_level, raw, Ret>(meta::is_optional<meta::unqualified_t<Ret>>(), detail::forward_get<I>(keys)); | ||
19461 | } | ||
19462 | |||
19463 | template <bool raw, typename Pairs, std::size_t... I> | ||
19464 | void tuple_set(std::index_sequence<I...>, Pairs&& pairs) { | ||
19465 | auto pp = stack::push_pop < top_level && (is_global<decltype(detail::forward_get<I * 2>(pairs))...>::value) > (*this); | ||
19466 | void(detail::swallow{ (stack::set_field<top_level, raw>(base_t::lua_state(), | ||
19467 | detail::forward_get<I * 2>(pairs), | ||
19468 | detail::forward_get<I * 2 + 1>(pairs), | ||
19469 | lua_gettop(base_t::lua_state())), | ||
19470 | 0)... }); | ||
19471 | } | ||
19472 | |||
19473 | template <bool global, bool raw, typename T, typename Key> | ||
19474 | decltype(auto) traverse_get_deep(Key&& key) const { | ||
19475 | stack::get_field<global, raw>(base_t::lua_state(), std::forward<Key>(key)); | ||
19476 | return stack::get<T>(base_t::lua_state()); | ||
19477 | } | ||
19478 | |||
19479 | template <bool global, bool raw, typename T, typename Key, typename... Keys> | ||
19480 | decltype(auto) traverse_get_deep(Key&& key, Keys&&... keys) const { | ||
19481 | stack::get_field<global, raw>(base_t::lua_state(), std::forward<Key>(key)); | ||
19482 | return traverse_get_deep<false, raw, T>(std::forward<Keys>(keys)...); | ||
19483 | } | ||
19484 | |||
19485 | template <bool global, bool raw, typename T, std::size_t I, typename Key> | ||
19486 | decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key) const { | ||
19487 | typedef decltype(stack::get<T>(base_t::lua_state())) R; | ||
19488 | auto p = stack::probe_get_field<global, raw>(base_t::lua_state(), std::forward<Key>(key), lua_gettop(base_t::lua_state())); | ||
19489 | popcount += p.levels; | ||
19490 | if (!p.success) | ||
19491 | return R(nullopt); | ||
19492 | return stack::get<T>(base_t::lua_state()); | ||
19493 | } | ||
19494 | |||
19495 | template <bool global, bool raw, typename T, std::size_t I, typename Key, typename... Keys> | ||
19496 | decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key, Keys&&... keys) const { | ||
19497 | auto p = I > 0 ? stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), -1) : stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), lua_gettop(base_t::lua_state())); | ||
19498 | popcount += p.levels; | ||
19499 | if (!p.success) | ||
19500 | return T(nullopt); | ||
19501 | return traverse_get_deep_optional<false, raw, T, I + 1>(popcount, std::forward<Keys>(keys)...); | ||
19502 | } | ||
19503 | |||
19504 | template <bool global, bool raw, typename T, typename... Keys> | ||
19505 | decltype(auto) traverse_get_optional(std::false_type, Keys&&... keys) const { | ||
19506 | detail::clean<sizeof...(Keys)> c(base_t::lua_state()); | ||
19507 | return traverse_get_deep<global, raw, T>(std::forward<Keys>(keys)...); | ||
19508 | } | ||
19509 | |||
19510 | template <bool global, bool raw, typename T, typename... Keys> | ||
19511 | decltype(auto) traverse_get_optional(std::true_type, Keys&&... keys) const { | ||
19512 | int popcount = 0; | ||
19513 | detail::ref_clean c(base_t::lua_state(), popcount); | ||
19514 | return traverse_get_deep_optional<global, raw, T, 0>(popcount, std::forward<Keys>(keys)...); | ||
19515 | } | ||
19516 | |||
19517 | template <bool global, bool raw, typename Key, typename Value> | ||
19518 | void traverse_set_deep(Key&& key, Value&& value) const { | ||
19519 | stack::set_field<global, raw>(base_t::lua_state(), std::forward<Key>(key), std::forward<Value>(value)); | ||
19520 | } | ||
19521 | |||
19522 | template <bool global, bool raw, typename Key, typename... Keys> | ||
19523 | void traverse_set_deep(Key&& key, Keys&&... keys) const { | ||
19524 | stack::get_field<global, raw>(base_t::lua_state(), std::forward<Key>(key)); | ||
19525 | traverse_set_deep<false, raw>(std::forward<Keys>(keys)...); | ||
19526 | } | ||
19527 | |||
19528 | basic_table_core(lua_State* L, detail::global_tag t) noexcept | ||
19529 | : base_t(L, t) { | ||
19530 | } | ||
19531 | |||
19532 | protected: | ||
19533 | basic_table_core(detail::no_safety_tag, lua_nil_t n) | ||
19534 | : base_t(n) { | ||
19535 | } | ||
19536 | basic_table_core(detail::no_safety_tag, lua_State* L, int index) | ||
19537 | : base_t(L, index) { | ||
19538 | } | ||
19539 | basic_table_core(detail::no_safety_tag, lua_State* L, ref_index index) | ||
19540 | : base_t(L, index) { | ||
19541 | } | ||
19542 | template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
19543 | basic_table_core(detail::no_safety_tag, T&& r) noexcept | ||
19544 | : base_t(std::forward<T>(r)) { | ||
19545 | } | ||
19546 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
19547 | basic_table_core(detail::no_safety_tag, lua_State*L, T&& r) noexcept | ||
19548 | : base_t(L, std::forward<T>(r)) { | ||
19549 | } | ||
19550 | |||
19551 | public: | ||
19552 | typedef basic_table_iterator<base_type> iterator; | ||
19553 | typedef iterator const_iterator; | ||
19554 | |||
19555 | using base_t::lua_state; | ||
19556 | |||
19557 | basic_table_core() noexcept = default; | ||
19558 | basic_table_core(const basic_table_core&) = default; | ||
19559 | basic_table_core(basic_table_core&&) = default; | ||
19560 | basic_table_core& operator=(const basic_table_core&) = default; | ||
19561 | basic_table_core& operator=(basic_table_core&&) = default; | ||
19562 | basic_table_core(const stack_reference& r) | ||
19563 | : basic_table_core(r.lua_state(), r.stack_index()) { | ||
19564 | } | ||
19565 | basic_table_core(stack_reference&& r) | ||
19566 | : basic_table_core(r.lua_state(), r.stack_index()) { | ||
19567 | } | ||
19568 | template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
19569 | basic_table_core(lua_State* L, T&& r) | ||
19570 | : base_t(L, std::forward<T>(r)) { | ||
19571 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
19572 | auto pp = stack::push_pop(*this); | ||
19573 | constructor_handler handler{}; | ||
19574 | stack::check<basic_table_core>(lua_state(), -1, handler); | ||
19575 | #endif // Safety | ||
19576 | } | ||
19577 | basic_table_core(lua_State* L, const new_table& nt) | ||
19578 | : base_t(L, -stack::push(L, nt)) { | ||
19579 | if (!is_stack_based<meta::unqualified_t<base_type>>::value) { | ||
19580 | lua_pop(L, 1); | ||
19581 | } | ||
19582 | } | ||
19583 | basic_table_core(lua_State* L, int index = -1) | ||
19584 | : basic_table_core(detail::no_safety, L, index) { | ||
19585 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
19586 | constructor_handler handler{}; | ||
19587 | stack::check<basic_table_core>(L, index, handler); | ||
19588 | #endif // Safety | ||
19589 | } | ||
19590 | basic_table_core(lua_State* L, ref_index index) | ||
19591 | : basic_table_core(detail::no_safety, L, index) { | ||
19592 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
19593 | auto pp = stack::push_pop(*this); | ||
19594 | constructor_handler handler{}; | ||
19595 | stack::check<basic_table_core>(lua_state(), -1, handler); | ||
19596 | #endif // Safety | ||
19597 | } | ||
19598 | template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
19599 | basic_table_core(T&& r) noexcept | ||
19600 | : basic_table_core(detail::no_safety, std::forward<T>(r)) { | ||
19601 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
19602 | if (!is_table<meta::unqualified_t<T>>::value) { | ||
19603 | auto pp = stack::push_pop(*this); | ||
19604 | constructor_handler handler{}; | ||
19605 | stack::check<basic_table_core>(base_t::lua_state(), -1, handler); | ||
19606 | } | ||
19607 | #endif // Safety | ||
19608 | } | ||
19609 | basic_table_core(lua_nil_t r) noexcept | ||
19610 | : basic_table_core(detail::no_safety, r) { | ||
19611 | } | ||
19612 | |||
19613 | iterator begin() const { | ||
19614 | return iterator(*this); | ||
19615 | } | ||
19616 | |||
19617 | iterator end() const { | ||
19618 | return iterator(); | ||
19619 | } | ||
19620 | |||
19621 | const_iterator cbegin() const { | ||
19622 | return begin(); | ||
19623 | } | ||
19624 | |||
19625 | const_iterator cend() const { | ||
19626 | return end(); | ||
19627 | } | ||
19628 | |||
19629 | template <typename... Ret, typename... Keys> | ||
19630 | decltype(auto) get(Keys&&... keys) const { | ||
19631 | static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); | ||
19632 | auto pp = stack::push_pop<is_global<Keys...>::value>(*this); | ||
19633 | return tuple_get<false>(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), std::forward_as_tuple(std::forward<Keys>(keys)...)); | ||
19634 | } | ||
19635 | |||
19636 | template <typename T, typename Key> | ||
19637 | decltype(auto) get_or(Key&& key, T&& otherwise) const { | ||
19638 | typedef decltype(get<T>("")) U; | ||
19639 | optional<U> option = get<optional<U>>(std::forward<Key>(key)); | ||
19640 | if (option) { | ||
19641 | return static_cast<U>(option.value()); | ||
19642 | } | ||
19643 | return static_cast<U>(std::forward<T>(otherwise)); | ||
19644 | } | ||
19645 | |||
19646 | template <typename T, typename Key, typename D> | ||
19647 | decltype(auto) get_or(Key&& key, D&& otherwise) const { | ||
19648 | optional<T> option = get<optional<T>>(std::forward<Key>(key)); | ||
19649 | if (option) { | ||
19650 | return static_cast<T>(option.value()); | ||
19651 | } | ||
19652 | return static_cast<T>(std::forward<D>(otherwise)); | ||
19653 | } | ||
19654 | |||
19655 | template <typename T, typename... Keys> | ||
19656 | decltype(auto) traverse_get(Keys&&... keys) const { | ||
19657 | auto pp = stack::push_pop<is_global<Keys...>::value>(*this); | ||
19658 | return traverse_get_optional<top_level, false, T>(meta::is_optional<meta::unqualified_t<T>>(), std::forward<Keys>(keys)...); | ||
19659 | } | ||
19660 | |||
19661 | template <typename... Keys> | ||
19662 | basic_table_core& traverse_set(Keys&&... keys) { | ||
19663 | auto pp = stack::push_pop<is_global<Keys...>::value>(*this); | ||
19664 | auto pn = stack::pop_n(base_t::lua_state(), static_cast<int>(sizeof...(Keys) - 2)); | ||
19665 | traverse_set_deep<top_level, false>(std::forward<Keys>(keys)...); | ||
19666 | return *this; | ||
19667 | } | ||
19668 | |||
19669 | template <typename... Args> | ||
19670 | basic_table_core& set(Args&&... args) { | ||
19671 | tuple_set<false>(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...)); | ||
19672 | return *this; | ||
19673 | } | ||
19674 | |||
19675 | template <typename... Ret, typename... Keys> | ||
19676 | decltype(auto) raw_get(Keys&&... keys) const { | ||
19677 | static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); | ||
19678 | auto pp = stack::push_pop<is_global<Keys...>::value>(*this); | ||
19679 | return tuple_get<true>(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), std::forward_as_tuple(std::forward<Keys>(keys)...)); | ||
19680 | } | ||
19681 | |||
19682 | template <typename T, typename Key> | ||
19683 | decltype(auto) raw_get_or(Key&& key, T&& otherwise) const { | ||
19684 | typedef decltype(raw_get<T>("")) U; | ||
19685 | optional<U> option = raw_get<optional<U>>(std::forward<Key>(key)); | ||
19686 | if (option) { | ||
19687 | return static_cast<U>(option.value()); | ||
19688 | } | ||
19689 | return static_cast<U>(std::forward<T>(otherwise)); | ||
19690 | } | ||
19691 | |||
19692 | template <typename T, typename Key, typename D> | ||
19693 | decltype(auto) raw_get_or(Key&& key, D&& otherwise) const { | ||
19694 | optional<T> option = raw_get<optional<T>>(std::forward<Key>(key)); | ||
19695 | if (option) { | ||
19696 | return static_cast<T>(option.value()); | ||
19697 | } | ||
19698 | return static_cast<T>(std::forward<D>(otherwise)); | ||
19699 | } | ||
19700 | |||
19701 | template <typename T, typename... Keys> | ||
19702 | decltype(auto) traverse_raw_get(Keys&&... keys) const { | ||
19703 | auto pp = stack::push_pop<is_global<Keys...>::value>(*this); | ||
19704 | return traverse_get_optional<top_level, true, T>(meta::is_optional<meta::unqualified_t<T>>(), std::forward<Keys>(keys)...); | ||
19705 | } | ||
19706 | |||
19707 | template <typename... Keys> | ||
19708 | basic_table_core& traverse_raw_set(Keys&&... keys) { | ||
19709 | auto pp = stack::push_pop<is_global<Keys...>::value>(*this); | ||
19710 | auto pn = stack::pop_n(base_t::lua_state(), static_cast<int>(sizeof...(Keys) - 2)); | ||
19711 | traverse_set_deep<top_level, true>(std::forward<Keys>(keys)...); | ||
19712 | return *this; | ||
19713 | } | ||
19714 | |||
19715 | template <typename... Args> | ||
19716 | basic_table_core& raw_set(Args&&... args) { | ||
19717 | tuple_set<true>(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...)); | ||
19718 | return *this; | ||
19719 | } | ||
19720 | |||
19721 | template <typename T> | ||
19722 | basic_table_core& set_usertype(usertype<T>& user) { | ||
19723 | return set_usertype(usertype_traits<T>::name(), user); | ||
19724 | } | ||
19725 | |||
19726 | template <typename Key, typename T> | ||
19727 | basic_table_core& set_usertype(Key&& key, usertype<T>& user) { | ||
19728 | return set(std::forward<Key>(key), user); | ||
19729 | } | ||
19730 | |||
19731 | template <typename Class, typename... Args> | ||
19732 | basic_table_core& new_usertype(const std::string& name, Args&&... args) { | ||
19733 | usertype<Class> utype(std::forward<Args>(args)...); | ||
19734 | set_usertype(name, utype); | ||
19735 | return *this; | ||
19736 | } | ||
19737 | |||
19738 | template <typename Class, typename CTor0, typename... CTor, typename... Args> | ||
19739 | basic_table_core& new_usertype(const std::string& name, Args&&... args) { | ||
19740 | constructors<types<CTor0, CTor...>> ctor{}; | ||
19741 | return new_usertype<Class>(name, ctor, std::forward<Args>(args)...); | ||
19742 | } | ||
19743 | |||
19744 | template <typename Class, typename... CArgs, typename... Args> | ||
19745 | basic_table_core& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { | ||
19746 | usertype<Class> utype(ctor, std::forward<Args>(args)...); | ||
19747 | set_usertype(name, utype); | ||
19748 | return *this; | ||
19749 | } | ||
19750 | |||
19751 | template <typename Class, typename... Args> | ||
19752 | basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { | ||
19753 | simple_usertype<Class> utype(base_t::lua_state(), std::forward<Args>(args)...); | ||
19754 | set_usertype(name, utype); | ||
19755 | return *this; | ||
19756 | } | ||
19757 | |||
19758 | template <typename Class, typename CTor0, typename... CTor, typename... Args> | ||
19759 | basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { | ||
19760 | constructors<types<CTor0, CTor...>> ctor{}; | ||
19761 | return new_simple_usertype<Class>(name, ctor, std::forward<Args>(args)...); | ||
19762 | } | ||
19763 | |||
19764 | template <typename Class, typename... CArgs, typename... Args> | ||
19765 | basic_table_core& new_simple_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { | ||
19766 | simple_usertype<Class> utype(base_t::lua_state(), ctor, std::forward<Args>(args)...); | ||
19767 | set_usertype(name, utype); | ||
19768 | return *this; | ||
19769 | } | ||
19770 | |||
19771 | template <typename Class, typename... Args> | ||
19772 | simple_usertype<Class> create_simple_usertype(Args&&... args) { | ||
19773 | simple_usertype<Class> utype(base_t::lua_state(), std::forward<Args>(args)...); | ||
19774 | return utype; | ||
19775 | } | ||
19776 | |||
19777 | template <typename Class, typename CTor0, typename... CTor, typename... Args> | ||
19778 | simple_usertype<Class> create_simple_usertype(Args&&... args) { | ||
19779 | constructors<types<CTor0, CTor...>> ctor{}; | ||
19780 | return create_simple_usertype<Class>(ctor, std::forward<Args>(args)...); | ||
19781 | } | ||
19782 | |||
19783 | template <typename Class, typename... CArgs, typename... Args> | ||
19784 | simple_usertype<Class> create_simple_usertype(constructors<CArgs...> ctor, Args&&... args) { | ||
19785 | simple_usertype<Class> utype(base_t::lua_state(), ctor, std::forward<Args>(args)...); | ||
19786 | return utype; | ||
19787 | } | ||
19788 | |||
19789 | template <bool read_only = true, typename... Args> | ||
19790 | table new_enum(const string_view& name, Args&&... args) { | ||
19791 | table target = create_with(std::forward<Args>(args)...); | ||
19792 | if (read_only) { | ||
19793 | table x = create_with( | ||
19794 | meta_function::new_index, detail::fail_on_newindex, | ||
19795 | meta_function::index, target); | ||
19796 | table shim = create_named(name, metatable_key, x); | ||
19797 | return shim; | ||
19798 | } | ||
19799 | else { | ||
19800 | set(name, target); | ||
19801 | return target; | ||
19802 | } | ||
19803 | } | ||
19804 | |||
19805 | template <typename T, bool read_only = true> | ||
19806 | table new_enum(const string_view& name, std::initializer_list<std::pair<string_view, T>> items) { | ||
19807 | table target = create(static_cast<int>(items.size()), static_cast<int>(0)); | ||
19808 | for (const auto& kvp : items) { | ||
19809 | target.set(kvp.first, kvp.second); | ||
19810 | } | ||
19811 | if (read_only) { | ||
19812 | table x = create_with( | ||
19813 | meta_function::new_index, detail::fail_on_newindex, | ||
19814 | meta_function::index, target); | ||
19815 | table shim = create_named(name, metatable_key, x); | ||
19816 | return shim; | ||
19817 | } | ||
19818 | else { | ||
19819 | set(name, target); | ||
19820 | return target; | ||
19821 | } | ||
19822 | } | ||
19823 | |||
19824 | template <typename Fx> | ||
19825 | void for_each(Fx&& fx) const { | ||
19826 | typedef meta::is_invokable<Fx(std::pair<object, object>)> is_paired; | ||
19827 | for_each(is_paired(), std::forward<Fx>(fx)); | ||
19828 | } | ||
19829 | |||
19830 | size_t size() const { | ||
19831 | auto pp = stack::push_pop(*this); | ||
19832 | lua_len(base_t::lua_state(), -1); | ||
19833 | return stack::pop<size_t>(base_t::lua_state()); | ||
19834 | } | ||
19835 | |||
19836 | bool empty() const { | ||
19837 | return cbegin() == cend(); | ||
19838 | } | ||
19839 | |||
19840 | template <typename T> | ||
19841 | proxy<basic_table_core&, T> operator[](T&& key) & { | ||
19842 | return proxy<basic_table_core&, T>(*this, std::forward<T>(key)); | ||
19843 | } | ||
19844 | |||
19845 | template <typename T> | ||
19846 | proxy<const basic_table_core&, T> operator[](T&& key) const& { | ||
19847 | return proxy<const basic_table_core&, T>(*this, std::forward<T>(key)); | ||
19848 | } | ||
19849 | |||
19850 | template <typename T> | ||
19851 | proxy<basic_table_core, T> operator[](T&& key) && { | ||
19852 | return proxy<basic_table_core, T>(*this, std::forward<T>(key)); | ||
19853 | } | ||
19854 | |||
19855 | template <typename Sig, typename Key, typename... Args> | ||
19856 | basic_table_core& set_function(Key&& key, Args&&... args) { | ||
19857 | set_fx(types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...); | ||
19858 | return *this; | ||
19859 | } | ||
19860 | |||
19861 | template <typename Key, typename... Args> | ||
19862 | basic_table_core& set_function(Key&& key, Args&&... args) { | ||
19863 | set_fx(types<>(), std::forward<Key>(key), std::forward<Args>(args)...); | ||
19864 | return *this; | ||
19865 | } | ||
19866 | |||
19867 | template <typename... Args> | ||
19868 | basic_table_core& add(Args&&... args) { | ||
19869 | auto pp = stack::push_pop(*this); | ||
19870 | (void)detail::swallow{ 0, | ||
19871 | (stack::set_ref(base_t::lua_state(), std::forward<Args>(args)), 0)... }; | ||
19872 | return *this; | ||
19873 | } | ||
19874 | |||
19875 | private: | ||
19876 | template <typename R, typename... Args, typename Fx, typename Key, typename = std::result_of_t<Fx(Args...)>> | ||
19877 | void set_fx(types<R(Args...)>, Key&& key, Fx&& fx) { | ||
19878 | set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx)); | ||
19879 | } | ||
19880 | |||
19881 | template <typename Fx, typename Key, meta::enable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler> | ||
19882 | void set_fx(types<>, Key&& key, Fx&& fx) { | ||
19883 | set(std::forward<Key>(key), std::forward<Fx>(fx)); | ||
19884 | } | ||
19885 | |||
19886 | template <typename Fx, typename Key, typename... Args, meta::disable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler> | ||
19887 | void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { | ||
19888 | set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...)); | ||
19889 | } | ||
19890 | |||
19891 | template <typename... Sig, typename... Args, typename Key> | ||
19892 | void set_resolved_function(Key&& key, Args&&... args) { | ||
19893 | set(std::forward<Key>(key), as_function_reference<function_sig<Sig...>>(std::forward<Args>(args)...)); | ||
19894 | } | ||
19895 | |||
19896 | public: | ||
19897 | static inline table create(lua_State* L, int narr = 0, int nrec = 0) { | ||
19898 | lua_createtable(L, narr, nrec); | ||
19899 | table result(L); | ||
19900 | lua_pop(L, 1); | ||
19901 | return result; | ||
19902 | } | ||
19903 | |||
19904 | template <typename Key, typename Value, typename... Args> | ||
19905 | static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { | ||
19906 | lua_createtable(L, narr, nrec); | ||
19907 | table result(L); | ||
19908 | result.set(std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); | ||
19909 | lua_pop(L, 1); | ||
19910 | return result; | ||
19911 | } | ||
19912 | |||
19913 | template <typename... Args> | ||
19914 | static inline table create_with(lua_State* L, Args&&... args) { | ||
19915 | static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list."); | ||
19916 | static const int narr = static_cast<int>(meta::count_2_for_pack<std::is_integral, Args...>::value); | ||
19917 | return create(L, narr, static_cast<int>((sizeof...(Args) / 2) - narr), std::forward<Args>(args)...); | ||
19918 | } | ||
19919 | |||
19920 | table create(int narr = 0, int nrec = 0) { | ||
19921 | return create(base_t::lua_state(), narr, nrec); | ||
19922 | } | ||
19923 | |||
19924 | template <typename Key, typename Value, typename... Args> | ||
19925 | table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { | ||
19926 | return create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); | ||
19927 | } | ||
19928 | |||
19929 | template <typename Name> | ||
19930 | table create(Name&& name, int narr = 0, int nrec = 0) { | ||
19931 | table x = create(base_t::lua_state(), narr, nrec); | ||
19932 | this->set(std::forward<Name>(name), x); | ||
19933 | return x; | ||
19934 | } | ||
19935 | |||
19936 | template <typename Name, typename Key, typename Value, typename... Args> | ||
19937 | table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { | ||
19938 | table x = create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); | ||
19939 | this->set(std::forward<Name>(name), x); | ||
19940 | return x; | ||
19941 | } | ||
19942 | |||
19943 | template <typename... Args> | ||
19944 | table create_with(Args&&... args) { | ||
19945 | return create_with(base_t::lua_state(), std::forward<Args>(args)...); | ||
19946 | } | ||
19947 | |||
19948 | template <typename Name, typename... Args> | ||
19949 | table create_named(Name&& name, Args&&... args) { | ||
19950 | static const int narr = static_cast<int>(meta::count_2_for_pack<std::is_integral, Args...>::value); | ||
19951 | return create(std::forward<Name>(name), narr, (sizeof...(Args) / 2) - narr, std::forward<Args>(args)...); | ||
19952 | } | ||
19953 | }; | ||
19954 | } // namespace sol | ||
19955 | |||
19956 | // end of sol/table_core.hpp | ||
19957 | |||
19958 | namespace sol { | ||
19959 | typedef table_core<false> table; | ||
19960 | |||
19961 | namespace stack { | ||
19962 | template <> | ||
19963 | struct getter<metatable_t> { | ||
19964 | static table get(lua_State* L, int index = -1) { | ||
19965 | if (lua_getmetatable(L, index) == 0) { | ||
19966 | return table(L, ref_index(LUA_REFNIL)); | ||
19967 | } | ||
19968 | return table(L, -1); | ||
19969 | } | ||
19970 | }; | ||
19971 | } // namespace stack | ||
19972 | } // namespace sol | ||
19973 | |||
19974 | // end of sol/table.hpp | ||
19975 | |||
19976 | // beginning of sol/environment.hpp | ||
19977 | |||
19978 | namespace sol { | ||
19979 | |||
19980 | template <typename base_type> | ||
19981 | struct basic_environment : basic_table<base_type> { | ||
19982 | private: | ||
19983 | typedef basic_table<base_type> base_t; | ||
19984 | |||
19985 | public: | ||
19986 | using base_t::lua_state; | ||
19987 | |||
19988 | basic_environment() noexcept = default; | ||
19989 | basic_environment(const basic_environment&) = default; | ||
19990 | basic_environment(basic_environment&&) = default; | ||
19991 | basic_environment& operator=(const basic_environment&) = default; | ||
19992 | basic_environment& operator=(basic_environment&&) = default; | ||
19993 | basic_environment(const stack_reference& r) | ||
19994 | : basic_environment(r.lua_state(), r.stack_index()) { | ||
19995 | } | ||
19996 | basic_environment(stack_reference&& r) | ||
19997 | : basic_environment(r.lua_state(), r.stack_index()) { | ||
19998 | } | ||
19999 | |||
20000 | basic_environment(lua_State* L, new_table nt) | ||
20001 | : base_t(L, std::move(nt)) { | ||
20002 | } | ||
20003 | template <bool b> | ||
20004 | basic_environment(lua_State* L, new_table t, const basic_reference<b>& fallback) | ||
20005 | : basic_environment(L, std::move(t)) { | ||
20006 | stack_table mt(L, new_table(0, 1)); | ||
20007 | mt.set(meta_function::index, fallback); | ||
20008 | this->set(metatable_key, mt); | ||
20009 | mt.pop(); | ||
20010 | } | ||
20011 | |||
20012 | basic_environment(env_t, const stack_reference& extraction_target) | ||
20013 | : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { | ||
20014 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
20015 | constructor_handler handler{}; | ||
20016 | stack::check<env_t>(this->lua_state(), -1, handler); | ||
20017 | #endif // Safety | ||
20018 | lua_pop(this->lua_state(), 2); | ||
20019 | } | ||
20020 | template <bool b> | ||
20021 | basic_environment(env_t, const basic_reference<b>& extraction_target) | ||
20022 | : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { | ||
20023 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
20024 | constructor_handler handler{}; | ||
20025 | stack::check<env_t>(this->lua_state(), -1, handler); | ||
20026 | #endif // Safety | ||
20027 | lua_pop(this->lua_state(), 2); | ||
20028 | } | ||
20029 | basic_environment(lua_State* L, int index = -1) | ||
20030 | : base_t(detail::no_safety, L, index) { | ||
20031 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
20032 | constructor_handler handler{}; | ||
20033 | stack::check<basic_environment>(L, index, handler); | ||
20034 | #endif // Safety | ||
20035 | } | ||
20036 | basic_environment(lua_State* L, ref_index index) | ||
20037 | : base_t(detail::no_safety, L, index) { | ||
20038 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
20039 | auto pp = stack::push_pop(*this); | ||
20040 | constructor_handler handler{}; | ||
20041 | stack::check<basic_environment>(L, -1, handler); | ||
20042 | #endif // Safety | ||
20043 | } | ||
20044 | template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
20045 | basic_environment(T&& r) noexcept | ||
20046 | : base_t(detail::no_safety, std::forward<T>(r)) { | ||
20047 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
20048 | if (!is_environment<meta::unqualified_t<T>>::value) { | ||
20049 | auto pp = stack::push_pop(*this); | ||
20050 | constructor_handler handler{}; | ||
20051 | stack::check<basic_environment>(lua_state(), -1, handler); | ||
20052 | } | ||
20053 | #endif // Safety | ||
20054 | } | ||
20055 | basic_environment(lua_nil_t r) noexcept | ||
20056 | : base_t(detail::no_safety, r) { | ||
20057 | } | ||
20058 | |||
20059 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
20060 | basic_environment(lua_State* L, T&& r) noexcept | ||
20061 | : base_t(detail::no_safety, L, std::forward<T>(r)) { | ||
20062 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
20063 | if (!is_environment<meta::unqualified_t<T>>::value) { | ||
20064 | auto pp = stack::push_pop(*this); | ||
20065 | constructor_handler handler{}; | ||
20066 | stack::check<basic_environment>(lua_state(), -1, handler); | ||
20067 | } | ||
20068 | #endif // Safety | ||
20069 | } | ||
20070 | |||
20071 | template <typename T> | ||
20072 | void set_on(const T& target) const { | ||
20073 | lua_State* L = target.lua_state(); | ||
20074 | auto pp = stack::push_pop(target); | ||
20075 | #if SOL_LUA_VERSION < 502 | ||
20076 | // Use lua_setfenv | ||
20077 | this->push(); | ||
20078 | lua_setfenv(L, -2); | ||
20079 | #else | ||
20080 | // Use upvalues as explained in Lua 5.2 and beyond's manual | ||
20081 | this->push(); | ||
20082 | const char* name = lua_setupvalue(L, -2, 1); | ||
20083 | if (name == nullptr) { | ||
20084 | this->pop(); | ||
20085 | } | ||
20086 | #endif | ||
20087 | } | ||
20088 | }; | ||
20089 | |||
20090 | template <typename T, typename E> | ||
20091 | void set_environment(const basic_environment<E>& env, const T& target) { | ||
20092 | env.set_on(target); | ||
20093 | } | ||
20094 | |||
20095 | template <typename E = reference, typename T> | ||
20096 | basic_environment<E> get_environment(const T& target) { | ||
20097 | lua_State* L = target.lua_state(); | ||
20098 | auto pp = stack::pop_n(L, stack::push_environment_of(target)); | ||
20099 | return basic_environment<E>(L, -1); | ||
20100 | } | ||
20101 | |||
20102 | struct this_environment { | ||
20103 | optional<environment> env; | ||
20104 | |||
20105 | this_environment() | ||
20106 | : env(nullopt) { | ||
20107 | } | ||
20108 | this_environment(environment e) | ||
20109 | : env(std::move(e)) { | ||
20110 | } | ||
20111 | this_environment(const this_environment&) = default; | ||
20112 | this_environment(this_environment&&) = default; | ||
20113 | this_environment& operator=(const this_environment&) = default; | ||
20114 | this_environment& operator=(this_environment&&) = default; | ||
20115 | |||
20116 | explicit operator bool() const { | ||
20117 | return static_cast<bool>(env); | ||
20118 | } | ||
20119 | |||
20120 | operator optional<environment>&() { | ||
20121 | return env; | ||
20122 | } | ||
20123 | |||
20124 | operator const optional<environment>&() const { | ||
20125 | return env; | ||
20126 | } | ||
20127 | |||
20128 | operator environment&() { | ||
20129 | return env.value(); | ||
20130 | } | ||
20131 | |||
20132 | operator const environment&() const { | ||
20133 | return env.value(); | ||
20134 | } | ||
20135 | }; | ||
20136 | |||
20137 | namespace stack { | ||
20138 | template <> | ||
20139 | struct getter<env_t> { | ||
20140 | static environment get(lua_State* L, int index, record& tracking) { | ||
20141 | tracking.use(1); | ||
20142 | return get_environment(stack_reference(L, raw_index(index))); | ||
20143 | } | ||
20144 | }; | ||
20145 | |||
20146 | template <> | ||
20147 | struct getter<this_environment> { | ||
20148 | static this_environment get(lua_State* L, int, record& tracking) { | ||
20149 | tracking.use(0); | ||
20150 | lua_Debug info; | ||
20151 | // Level 0 means current function (this C function, which may or may not be useful for us?) | ||
20152 | // Level 1 means next call frame up the stack. (Can be nothing if function called directly from C++ with lua_p/call) | ||
20153 | int pre_stack_size = lua_gettop(L); | ||
20154 | if (lua_getstack(L, 1, &info) != 1) { | ||
20155 | if (lua_getstack(L, 0, &info) != 1) { | ||
20156 | lua_settop(L, pre_stack_size); | ||
20157 | return this_environment(); | ||
20158 | } | ||
20159 | } | ||
20160 | if (lua_getinfo(L, "f", &info) == 0) { | ||
20161 | lua_settop(L, pre_stack_size); | ||
20162 | return this_environment(); | ||
20163 | } | ||
20164 | |||
20165 | stack_reference f(L, -1); | ||
20166 | environment env(env_key, f); | ||
20167 | if (!env.valid()) { | ||
20168 | lua_settop(L, pre_stack_size); | ||
20169 | return this_environment(); | ||
20170 | } | ||
20171 | return this_environment(std::move(env)); | ||
20172 | } | ||
20173 | }; | ||
20174 | } // namespace stack | ||
20175 | } // namespace sol | ||
20176 | |||
20177 | // end of sol/environment.hpp | ||
20178 | |||
20179 | // beginning of sol/load_result.hpp | ||
20180 | |||
20181 | namespace sol { | ||
20182 | struct load_result : public proxy_base<load_result> { | ||
20183 | private: | ||
20184 | lua_State* L; | ||
20185 | int index; | ||
20186 | int returncount; | ||
20187 | int popcount; | ||
20188 | load_status err; | ||
20189 | |||
20190 | template <typename T> | ||
20191 | decltype(auto) tagged_get(types<optional<T>>) const { | ||
20192 | if (!valid()) { | ||
20193 | return optional<T>(nullopt); | ||
20194 | } | ||
20195 | return stack::get<optional<T>>(L, index); | ||
20196 | } | ||
20197 | |||
20198 | template <typename T> | ||
20199 | decltype(auto) tagged_get(types<T>) const { | ||
20200 | #if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES != 0 | ||
20201 | if (!valid()) { | ||
20202 | type_panic_c_str(L, index, type_of(L, index), type::none); | ||
20203 | } | ||
20204 | #endif // Check Argument Safety | ||
20205 | return stack::get<T>(L, index); | ||
20206 | } | ||
20207 | |||
20208 | optional<error> tagged_get(types<optional<error>>) const { | ||
20209 | if (valid()) { | ||
20210 | return nullopt; | ||
20211 | } | ||
20212 | return error(detail::direct_error, stack::get<std::string>(L, index)); | ||
20213 | } | ||
20214 | |||
20215 | error tagged_get(types<error>) const { | ||
20216 | #if defined(SOL_SAFE_PROXIES) && SOL_SAFE_PROXIES != 0 | ||
20217 | if (valid()) { | ||
20218 | type_panic_c_str(L, index, type_of(L, index), type::none, "expecting an error type (a string, from Lua)"); | ||
20219 | } | ||
20220 | #endif // Check Argument Safety | ||
20221 | return error(detail::direct_error, stack::get<std::string>(L, index)); | ||
20222 | } | ||
20223 | |||
20224 | public: | ||
20225 | load_result() = default; | ||
20226 | load_result(lua_State* Ls, int stackindex = -1, int retnum = 0, int popnum = 0, load_status lerr = load_status::ok) noexcept | ||
20227 | : L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) { | ||
20228 | } | ||
20229 | load_result(const load_result&) = default; | ||
20230 | load_result& operator=(const load_result&) = default; | ||
20231 | load_result(load_result&& o) noexcept | ||
20232 | : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { | ||
20233 | // Must be manual, otherwise destructor will screw us | ||
20234 | // return count being 0 is enough to keep things clean | ||
20235 | // but we will be thorough | ||
20236 | o.L = nullptr; | ||
20237 | o.index = 0; | ||
20238 | o.returncount = 0; | ||
20239 | o.popcount = 0; | ||
20240 | o.err = load_status::syntax; | ||
20241 | } | ||
20242 | load_result& operator=(load_result&& o) noexcept { | ||
20243 | L = o.L; | ||
20244 | index = o.index; | ||
20245 | returncount = o.returncount; | ||
20246 | popcount = o.popcount; | ||
20247 | err = o.err; | ||
20248 | // Must be manual, otherwise destructor will screw us | ||
20249 | // return count being 0 is enough to keep things clean | ||
20250 | // but we will be thorough | ||
20251 | o.L = nullptr; | ||
20252 | o.index = 0; | ||
20253 | o.returncount = 0; | ||
20254 | o.popcount = 0; | ||
20255 | o.err = load_status::syntax; | ||
20256 | return *this; | ||
20257 | } | ||
20258 | |||
20259 | load_status status() const noexcept { | ||
20260 | return err; | ||
20261 | } | ||
20262 | |||
20263 | bool valid() const noexcept { | ||
20264 | return status() == load_status::ok; | ||
20265 | } | ||
20266 | |||
20267 | template <typename T> | ||
20268 | T get() const { | ||
20269 | return tagged_get(types<meta::unqualified_t<T>>()); | ||
20270 | } | ||
20271 | |||
20272 | template <typename... Ret, typename... Args> | ||
20273 | decltype(auto) call(Args&&... args) { | ||
20274 | #if defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 191326131 && _MSC_FULL_VER >= 191200000 | ||
20275 | // MSVC is ass sometimes | ||
20276 | return get<protected_function>().call<Ret...>(std::forward<Args>(args)...); | ||
20277 | #else | ||
20278 | return get<protected_function>().template call<Ret...>(std::forward<Args>(args)...); | ||
20279 | #endif | ||
20280 | } | ||
20281 | |||
20282 | template <typename... Args> | ||
20283 | decltype(auto) operator()(Args&&... args) { | ||
20284 | return call<>(std::forward<Args>(args)...); | ||
20285 | } | ||
20286 | |||
20287 | lua_State* lua_state() const noexcept { | ||
20288 | return L; | ||
20289 | }; | ||
20290 | int stack_index() const noexcept { | ||
20291 | return index; | ||
20292 | }; | ||
20293 | |||
20294 | ~load_result() { | ||
20295 | stack::remove(L, index, popcount); | ||
20296 | } | ||
20297 | }; | ||
20298 | } // namespace sol | ||
20299 | |||
20300 | // end of sol/load_result.hpp | ||
20301 | |||
20302 | // beginning of sol/state_handling.hpp | ||
20303 | |||
20304 | #ifdef SOL_PRINT_ERRORS | ||
20305 | #endif | ||
20306 | |||
20307 | namespace sol { | ||
20308 | inline void register_main_thread(lua_State* L) { | ||
20309 | #if SOL_LUA_VERSION < 502 | ||
20310 | if (L == nullptr) { | ||
20311 | lua_pushnil(L); | ||
20312 | lua_setglobal(L, detail::default_main_thread_name()); | ||
20313 | return; | ||
20314 | } | ||
20315 | lua_pushthread(L); | ||
20316 | lua_setglobal(L, detail::default_main_thread_name()); | ||
20317 | #else | ||
20318 | (void)L; | ||
20319 | #endif | ||
20320 | } | ||
20321 | |||
20322 | inline int default_at_panic(lua_State* L) { | ||
20323 | #if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS | ||
20324 | (void)L; | ||
20325 | return -1; | ||
20326 | #else | ||
20327 | size_t messagesize; | ||
20328 | const char* message = lua_tolstring(L, -1, &messagesize); | ||
20329 | if (message) { | ||
20330 | std::string err(message, messagesize); | ||
20331 | lua_settop(L, 0); | ||
20332 | #if defined(SOL_PRINT_ERRORS) && SOL_PRINT_ERRORS | ||
20333 | std::cerr << "[sol2] An error occurred and panic has been invoked: "; | ||
20334 | std::cerr << err; | ||
20335 | std::cerr << std::endl; | ||
20336 | #endif | ||
20337 | throw error(err); | ||
20338 | } | ||
20339 | lua_settop(L, 0); | ||
20340 | throw error(std::string("An unexpected error occurred and panic has been invoked")); | ||
20341 | #endif // Printing Errors | ||
20342 | } | ||
20343 | |||
20344 | inline int default_traceback_error_handler(lua_State* L) { | ||
20345 | std::string msg = "An unknown error has triggered the default error handler"; | ||
20346 | optional<string_view> maybetopmsg = stack::check_get<string_view>(L, 1); | ||
20347 | if (maybetopmsg) { | ||
20348 | const string_view& topmsg = maybetopmsg.value(); | ||
20349 | msg.assign(topmsg.data(), topmsg.size()); | ||
20350 | } | ||
20351 | luaL_traceback(L, L, msg.c_str(), 1); | ||
20352 | optional<string_view> maybetraceback = stack::check_get<string_view>(L, -1); | ||
20353 | if (maybetraceback) { | ||
20354 | const string_view& traceback = maybetraceback.value(); | ||
20355 | msg.assign(traceback.data(), traceback.size()); | ||
20356 | } | ||
20357 | #if defined(SOL_PRINT_ERRORS) && SOL_PRINT_ERRORS | ||
20358 | //std::cerr << "[sol2] An error occurred and was caught in traceback: "; | ||
20359 | //std::cerr << msg; | ||
20360 | //std::cerr << std::endl; | ||
20361 | #endif // Printing | ||
20362 | return stack::push(L, msg); | ||
20363 | } | ||
20364 | |||
20365 | inline void set_default_state(lua_State* L, lua_CFunction panic_function = &default_at_panic, lua_CFunction traceback_function = c_call<decltype(&default_traceback_error_handler), &default_traceback_error_handler>, exception_handler_function exf = detail::default_exception_handler) { | ||
20366 | lua_atpanic(L, panic_function); | ||
20367 | protected_function::set_default_handler(object(L, in_place, traceback_function)); | ||
20368 | set_default_exception_handler(L, exf); | ||
20369 | register_main_thread(L); | ||
20370 | stack::luajit_exception_handler(L); | ||
20371 | } | ||
20372 | |||
20373 | inline std::size_t total_memory_used(lua_State* L) { | ||
20374 | std::size_t kb = lua_gc(L, LUA_GCCOUNT, 0); | ||
20375 | kb *= 1024; | ||
20376 | kb += lua_gc(L, LUA_GCCOUNTB, 0); | ||
20377 | return kb; | ||
20378 | } | ||
20379 | |||
20380 | inline protected_function_result script_pass_on_error(lua_State*, protected_function_result result) { | ||
20381 | return result; | ||
20382 | } | ||
20383 | |||
20384 | inline protected_function_result script_throw_on_error(lua_State*L, protected_function_result result) { | ||
20385 | type t = type_of(L, result.stack_index()); | ||
20386 | std::string err = "sol: "; | ||
20387 | err += to_string(result.status()); | ||
20388 | err += " error"; | ||
20389 | #if !(defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS) | ||
20390 | std::exception_ptr eptr = std::current_exception(); | ||
20391 | if (eptr) { | ||
20392 | err += " with a "; | ||
20393 | try { | ||
20394 | std::rethrow_exception(eptr); | ||
20395 | } | ||
20396 | catch (const std::exception& ex) { | ||
20397 | err += "std::exception -- "; | ||
20398 | err.append(ex.what()); | ||
20399 | } | ||
20400 | catch (const std::string& message) { | ||
20401 | err += "thrown message -- "; | ||
20402 | err.append(message); | ||
20403 | } | ||
20404 | catch (const char* message) { | ||
20405 | err += "thrown message -- "; | ||
20406 | err.append(message); | ||
20407 | } | ||
20408 | catch (...) { | ||
20409 | err.append("thrown but unknown type, cannot serialize into error message"); | ||
20410 | } | ||
20411 | } | ||
20412 | #endif // serialize exception information if possible | ||
20413 | if (t == type::string) { | ||
20414 | err += ": "; | ||
20415 | string_view serr = stack::get<string_view>(L, result.stack_index()); | ||
20416 | err.append(serr.data(), serr.size()); | ||
20417 | } | ||
20418 | #if defined(SOL_PRINT_ERRORS) && SOL_PRINT_ERRORS | ||
20419 | std::cerr << "[sol2] An error occurred and has been passed to an error handler: "; | ||
20420 | std::cerr << err; | ||
20421 | std::cerr << std::endl; | ||
20422 | #endif | ||
20423 | // replacing information of stack error into pfr | ||
20424 | int target = result.stack_index(); | ||
20425 | if (result.pop_count() > 0) { | ||
20426 | stack::remove(L, target, result.pop_count()); | ||
20427 | } | ||
20428 | stack::push(L, err); | ||
20429 | int top = lua_gettop(L); | ||
20430 | int towards = top - target; | ||
20431 | if (towards != 0) { | ||
20432 | lua_rotate(L, top, towards); | ||
20433 | } | ||
20434 | #if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS | ||
20435 | return result; | ||
20436 | #else | ||
20437 | // just throw our error | ||
20438 | throw error(detail::direct_error, err); | ||
20439 | #endif // If exceptions are allowed | ||
20440 | } | ||
20441 | |||
20442 | inline protected_function_result script_default_on_error(lua_State* L, protected_function_result pfr) { | ||
20443 | #if defined(SOL_DEFAULT_PASS_ON_ERROR) && SOL_DEFAULT_PASS_ON_ERROR | ||
20444 | return script_pass_on_error(L, std::move(pfr)); | ||
20445 | #else | ||
20446 | return script_throw_on_error(L, std::move(pfr)); | ||
20447 | #endif | ||
20448 | } | ||
20449 | } // namespace sol | ||
20450 | |||
20451 | // end of sol/state_handling.hpp | ||
20452 | |||
20453 | namespace sol { | ||
20454 | |||
20455 | class state_view { | ||
20456 | private: | ||
20457 | lua_State* L; | ||
20458 | table reg; | ||
20459 | global_table global; | ||
20460 | |||
20461 | optional<object> is_loaded_package(const std::string& key) { | ||
20462 | auto loaded = reg.traverse_get<optional<object>>("_LOADED", key); | ||
20463 | bool is53mod = loaded && !(loaded->is<bool>() && !loaded->as<bool>()); | ||
20464 | if (is53mod) | ||
20465 | return loaded; | ||
20466 | #if SOL_LUA_VERSION <= 501 | ||
20467 | auto loaded51 = global.traverse_get<optional<object>>("package", "loaded", key); | ||
20468 | bool is51mod = loaded51 && !(loaded51->is<bool>() && !loaded51->as<bool>()); | ||
20469 | if (is51mod) | ||
20470 | return loaded51; | ||
20471 | #endif | ||
20472 | return nullopt; | ||
20473 | } | ||
20474 | |||
20475 | template <typename T> | ||
20476 | void ensure_package(const std::string& key, T&& sr) { | ||
20477 | #if SOL_LUA_VERSION <= 501 | ||
20478 | auto pkg = global["package"]; | ||
20479 | if (!pkg.valid()) { | ||
20480 | pkg = create_table_with("loaded", create_table_with(key, sr)); | ||
20481 | } | ||
20482 | else { | ||
20483 | auto ld = pkg["loaded"]; | ||
20484 | if (!ld.valid()) { | ||
20485 | ld = create_table_with(key, sr); | ||
20486 | } | ||
20487 | else { | ||
20488 | ld[key] = sr; | ||
20489 | } | ||
20490 | } | ||
20491 | #endif | ||
20492 | auto loaded = reg["_LOADED"]; | ||
20493 | if (!loaded.valid()) { | ||
20494 | loaded = create_table_with(key, sr); | ||
20495 | } | ||
20496 | else { | ||
20497 | loaded[key] = sr; | ||
20498 | } | ||
20499 | } | ||
20500 | |||
20501 | template <typename Fx> | ||
20502 | object require_core(const std::string& key, Fx&& action, bool create_global = true) { | ||
20503 | optional<object> loaded = is_loaded_package(key); | ||
20504 | if (loaded && loaded->valid()) | ||
20505 | return std::move(*loaded); | ||
20506 | action(); | ||
20507 | stack_reference sr(L, -1); | ||
20508 | if (create_global) | ||
20509 | set(key, sr); | ||
20510 | ensure_package(key, sr); | ||
20511 | return stack::pop<object>(L); | ||
20512 | } | ||
20513 | |||
20514 | public: | ||
20515 | typedef global_table::iterator iterator; | ||
20516 | typedef global_table::const_iterator const_iterator; | ||
20517 | |||
20518 | state_view(lua_State* Ls) | ||
20519 | : L(Ls), reg(Ls, LUA_REGISTRYINDEX), global(Ls, detail::global_) { | ||
20520 | } | ||
20521 | |||
20522 | state_view(this_state Ls) | ||
20523 | : state_view(Ls.L) { | ||
20524 | } | ||
20525 | |||
20526 | lua_State* lua_state() const { | ||
20527 | return L; | ||
20528 | } | ||
20529 | |||
20530 | template <typename... Args> | ||
20531 | void open_libraries(Args&&... args) { | ||
20532 | static_assert(meta::all_same<lib, Args...>::value, "all types must be libraries"); | ||
20533 | if (sizeof...(args) == 0) { | ||
20534 | luaL_openlibs(L); | ||
20535 | return; | ||
20536 | } | ||
20537 | |||
20538 | lib libraries[1 + sizeof...(args)] = {lib::count, std::forward<Args>(args)...}; | ||
20539 | |||
20540 | for (auto&& library : libraries) { | ||
20541 | switch (library) { | ||
20542 | #if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) | ||
20543 | case lib::coroutine: | ||
20544 | #endif // luajit opens coroutine base stuff | ||
20545 | case lib::base: | ||
20546 | luaL_requiref(L, "base", luaopen_base, 1); | ||
20547 | lua_pop(L, 1); | ||
20548 | break; | ||
20549 | case lib::package: | ||
20550 | luaL_requiref(L, "package", luaopen_package, 1); | ||
20551 | lua_pop(L, 1); | ||
20552 | break; | ||
20553 | #if !defined(SOL_LUAJIT) | ||
20554 | case lib::coroutine: | ||
20555 | #if SOL_LUA_VERSION > 501 | ||
20556 | luaL_requiref(L, "coroutine", luaopen_coroutine, 1); | ||
20557 | lua_pop(L, 1); | ||
20558 | #endif // Lua 5.2+ only | ||
20559 | break; | ||
20560 | #endif // Not LuaJIT - comes builtin | ||
20561 | case lib::string: | ||
20562 | luaL_requiref(L, "string", luaopen_string, 1); | ||
20563 | lua_pop(L, 1); | ||
20564 | break; | ||
20565 | case lib::table: | ||
20566 | luaL_requiref(L, "table", luaopen_table, 1); | ||
20567 | lua_pop(L, 1); | ||
20568 | break; | ||
20569 | case lib::math: | ||
20570 | luaL_requiref(L, "math", luaopen_math, 1); | ||
20571 | lua_pop(L, 1); | ||
20572 | break; | ||
20573 | case lib::bit32: | ||
20574 | #ifdef SOL_LUAJIT | ||
20575 | luaL_requiref(L, "bit32", luaopen_bit, 1); | ||
20576 | lua_pop(L, 1); | ||
20577 | #elif (SOL_LUA_VERSION == 502) || defined(LUA_COMPAT_BITLIB) || defined(LUA_COMPAT_5_2) | ||
20578 | luaL_requiref(L, "bit32", luaopen_bit32, 1); | ||
20579 | lua_pop(L, 1); | ||
20580 | #else | ||
20581 | #endif // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) | ||
20582 | break; | ||
20583 | case lib::io: | ||
20584 | luaL_requiref(L, "io", luaopen_io, 1); | ||
20585 | lua_pop(L, 1); | ||
20586 | break; | ||
20587 | case lib::os: | ||
20588 | luaL_requiref(L, "os", luaopen_os, 1); | ||
20589 | lua_pop(L, 1); | ||
20590 | break; | ||
20591 | case lib::debug: | ||
20592 | luaL_requiref(L, "debug", luaopen_debug, 1); | ||
20593 | lua_pop(L, 1); | ||
20594 | break; | ||
20595 | case lib::utf8: | ||
20596 | #if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) | ||
20597 | luaL_requiref(L, "utf8", luaopen_utf8, 1); | ||
20598 | lua_pop(L, 1); | ||
20599 | #endif // Lua 5.3+ only | ||
20600 | break; | ||
20601 | case lib::ffi: | ||
20602 | #ifdef SOL_LUAJIT | ||
20603 | luaL_requiref(L, "ffi", luaopen_ffi, 1); | ||
20604 | lua_pop(L, 1); | ||
20605 | #endif // LuaJIT only | ||
20606 | break; | ||
20607 | case lib::jit: | ||
20608 | #ifdef SOL_LUAJIT | ||
20609 | luaL_requiref(L, "jit", luaopen_jit, 0); | ||
20610 | lua_pop(L, 1); | ||
20611 | #endif // LuaJIT Only | ||
20612 | break; | ||
20613 | case lib::count: | ||
20614 | default: | ||
20615 | break; | ||
20616 | } | ||
20617 | } | ||
20618 | } | ||
20619 | |||
20620 | object require(const std::string& key, lua_CFunction open_function, bool create_global = true) { | ||
20621 | luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0); | ||
20622 | return stack::pop<object>(L); | ||
20623 | } | ||
20624 | |||
20625 | object require_script(const std::string& key, const string_view& code, bool create_global = true, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20626 | auto action = [this, &code, &chunkname, &mode]() { | ||
20627 | stack::script(L, code, chunkname, mode); | ||
20628 | }; | ||
20629 | return require_core(key, action, create_global); | ||
20630 | } | ||
20631 | |||
20632 | object require_file(const std::string& key, const std::string& filename, bool create_global = true, load_mode mode = load_mode::any) { | ||
20633 | auto action = [this, &filename, &mode]() { | ||
20634 | stack::script_file(L, filename, mode); | ||
20635 | }; | ||
20636 | return require_core(key, action, create_global); | ||
20637 | } | ||
20638 | |||
20639 | template <typename E> | ||
20640 | protected_function_result do_string(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20641 | detail::typical_chunk_name_t basechunkname = {}; | ||
20642 | const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); | ||
20643 | load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())); | ||
20644 | if (x != load_status::ok) { | ||
20645 | return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); | ||
20646 | } | ||
20647 | stack_aligned_protected_function pf(L, -1); | ||
20648 | set_environment(env, pf); | ||
20649 | return pf(); | ||
20650 | } | ||
20651 | |||
20652 | template <typename E> | ||
20653 | protected_function_result do_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) { | ||
20654 | load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); | ||
20655 | if (x != load_status::ok) { | ||
20656 | return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); | ||
20657 | } | ||
20658 | stack_aligned_protected_function pf(L, -1); | ||
20659 | set_environment(env, pf); | ||
20660 | return pf(); | ||
20661 | } | ||
20662 | |||
20663 | protected_function_result do_string(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20664 | detail::typical_chunk_name_t basechunkname = {}; | ||
20665 | const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); | ||
20666 | load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())); | ||
20667 | if (x != load_status::ok) { | ||
20668 | return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); | ||
20669 | } | ||
20670 | stack_aligned_protected_function pf(L, -1); | ||
20671 | return pf(); | ||
20672 | } | ||
20673 | |||
20674 | protected_function_result do_file(const std::string& filename, load_mode mode = load_mode::any) { | ||
20675 | load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); | ||
20676 | if (x != load_status::ok) { | ||
20677 | return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); | ||
20678 | } | ||
20679 | stack_aligned_protected_function pf(L, -1); | ||
20680 | return pf(); | ||
20681 | } | ||
20682 | |||
20683 | template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler> | ||
20684 | protected_function_result safe_script(const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20685 | protected_function_result pfr = do_string(code, chunkname, mode); | ||
20686 | if (!pfr.valid()) { | ||
20687 | return on_error(L, std::move(pfr)); | ||
20688 | } | ||
20689 | return pfr; | ||
20690 | } | ||
20691 | |||
20692 | template <typename Fx, typename E> | ||
20693 | protected_function_result safe_script(const string_view& code, const basic_environment<E>& env, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20694 | protected_function_result pfr = do_string(code, env, chunkname, mode); | ||
20695 | if (!pfr.valid()) { | ||
20696 | return on_error(L, std::move(pfr)); | ||
20697 | } | ||
20698 | return pfr; | ||
20699 | } | ||
20700 | |||
20701 | template <typename E> | ||
20702 | protected_function_result safe_script(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20703 | return safe_script(code, env, script_default_on_error, chunkname, mode); | ||
20704 | } | ||
20705 | |||
20706 | protected_function_result safe_script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20707 | return safe_script(code, script_default_on_error, chunkname, mode); | ||
20708 | } | ||
20709 | |||
20710 | template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler> | ||
20711 | protected_function_result safe_script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) { | ||
20712 | protected_function_result pfr = do_file(filename, mode); | ||
20713 | if (!pfr.valid()) { | ||
20714 | return on_error(L, std::move(pfr)); | ||
20715 | } | ||
20716 | return pfr; | ||
20717 | } | ||
20718 | |||
20719 | template <typename Fx, typename E> | ||
20720 | protected_function_result safe_script_file(const std::string& filename, const basic_environment<E>& env, Fx&& on_error, load_mode mode = load_mode::any) { | ||
20721 | protected_function_result pfr = do_file(filename, env, mode); | ||
20722 | if (!pfr.valid()) { | ||
20723 | return on_error(L, std::move(pfr)); | ||
20724 | } | ||
20725 | return pfr; | ||
20726 | } | ||
20727 | |||
20728 | template <typename E> | ||
20729 | protected_function_result safe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) { | ||
20730 | return safe_script_file(filename, env, script_default_on_error, mode); | ||
20731 | } | ||
20732 | |||
20733 | protected_function_result safe_script_file(const std::string& filename, load_mode mode = load_mode::any) { | ||
20734 | return safe_script_file(filename, script_default_on_error, mode); | ||
20735 | } | ||
20736 | |||
20737 | template <typename E> | ||
20738 | unsafe_function_result unsafe_script(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20739 | detail::typical_chunk_name_t basechunkname = {}; | ||
20740 | const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); | ||
20741 | int index = lua_gettop(L); | ||
20742 | if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())) { | ||
20743 | lua_error(L); | ||
20744 | } | ||
20745 | set_environment(env, stack_reference(L, raw_index(index + 1))); | ||
20746 | if (lua_pcall(L, 0, LUA_MULTRET, 0)) { | ||
20747 | lua_error(L); | ||
20748 | } | ||
20749 | int postindex = lua_gettop(L); | ||
20750 | int returns = postindex - index; | ||
20751 | return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); | ||
20752 | } | ||
20753 | |||
20754 | unsafe_function_result unsafe_script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20755 | int index = lua_gettop(L); | ||
20756 | stack::script(L, code, chunkname, mode); | ||
20757 | int postindex = lua_gettop(L); | ||
20758 | int returns = postindex - index; | ||
20759 | return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); | ||
20760 | } | ||
20761 | |||
20762 | template <typename E> | ||
20763 | unsafe_function_result unsafe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) { | ||
20764 | int index = lua_gettop(L); | ||
20765 | if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) { | ||
20766 | lua_error(L); | ||
20767 | } | ||
20768 | set_environment(env, stack_reference(L, raw_index(index + 1))); | ||
20769 | if (lua_pcall(L, 0, LUA_MULTRET, 0)) { | ||
20770 | lua_error(L); | ||
20771 | } | ||
20772 | int postindex = lua_gettop(L); | ||
20773 | int returns = postindex - index; | ||
20774 | return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); | ||
20775 | } | ||
20776 | |||
20777 | unsafe_function_result unsafe_script_file(const std::string& filename, load_mode mode = load_mode::any) { | ||
20778 | int index = lua_gettop(L); | ||
20779 | stack::script_file(L, filename, mode); | ||
20780 | int postindex = lua_gettop(L); | ||
20781 | int returns = postindex - index; | ||
20782 | return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); | ||
20783 | } | ||
20784 | |||
20785 | template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler> | ||
20786 | protected_function_result script(const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20787 | return safe_script(code, std::forward<Fx>(on_error), chunkname, mode); | ||
20788 | } | ||
20789 | |||
20790 | template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler> | ||
20791 | protected_function_result script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) { | ||
20792 | return safe_script_file(filename, std::forward<Fx>(on_error), mode); | ||
20793 | } | ||
20794 | |||
20795 | template <typename Fx, typename E> | ||
20796 | protected_function_result script(const string_view& code, const basic_environment<E>& env, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20797 | return safe_script(code, env, std::forward<Fx>(on_error), chunkname, mode); | ||
20798 | } | ||
20799 | |||
20800 | template <typename Fx, typename E> | ||
20801 | protected_function_result script_file(const std::string& filename, const basic_environment<E>& env, Fx&& on_error, load_mode mode = load_mode::any) { | ||
20802 | return safe_script_file(filename, env, std::forward<Fx>(on_error), mode); | ||
20803 | } | ||
20804 | |||
20805 | protected_function_result script(const string_view& code, const environment& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20806 | return safe_script(code, env, script_default_on_error, chunkname, mode); | ||
20807 | } | ||
20808 | |||
20809 | protected_function_result script_file(const std::string& filename, const environment& env, load_mode mode = load_mode::any) { | ||
20810 | return safe_script_file(filename, env, script_default_on_error, mode); | ||
20811 | } | ||
20812 | |||
20813 | #if defined(SOL_SAFE_FUNCTION) && SOL_SAFE_FUNCTION | ||
20814 | protected_function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20815 | return safe_script(code, chunkname, mode); | ||
20816 | } | ||
20817 | |||
20818 | protected_function_result script_file(const std::string& filename, load_mode mode = load_mode::any) { | ||
20819 | return safe_script_file(filename, mode); | ||
20820 | } | ||
20821 | #else | ||
20822 | unsafe_function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20823 | return unsafe_script(code, chunkname, mode); | ||
20824 | } | ||
20825 | |||
20826 | unsafe_function_result script_file(const std::string& filename, load_mode mode = load_mode::any) { | ||
20827 | return unsafe_script_file(filename, mode); | ||
20828 | } | ||
20829 | #endif | ||
20830 | load_result load(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20831 | detail::typical_chunk_name_t basechunkname = {}; | ||
20832 | const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); | ||
20833 | load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())); | ||
20834 | return load_result(L, absolute_index(L, -1), 1, 1, x); | ||
20835 | } | ||
20836 | |||
20837 | load_result load_buffer(const char* buff, size_t size, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20838 | return load(string_view(buff, size), chunkname, mode); | ||
20839 | } | ||
20840 | |||
20841 | load_result load_file(const std::string& filename, load_mode mode = load_mode::any) { | ||
20842 | load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); | ||
20843 | return load_result(L, absolute_index(L, -1), 1, 1, x); | ||
20844 | } | ||
20845 | |||
20846 | load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { | ||
20847 | detail::typical_chunk_name_t basechunkname = {}; | ||
20848 | const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); | ||
20849 | load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())); | ||
20850 | return load_result(L, absolute_index(L, -1), 1, 1, x); | ||
20851 | } | ||
20852 | |||
20853 | iterator begin() const { | ||
20854 | return global.begin(); | ||
20855 | } | ||
20856 | |||
20857 | iterator end() const { | ||
20858 | return global.end(); | ||
20859 | } | ||
20860 | |||
20861 | const_iterator cbegin() const { | ||
20862 | return global.cbegin(); | ||
20863 | } | ||
20864 | |||
20865 | const_iterator cend() const { | ||
20866 | return global.cend(); | ||
20867 | } | ||
20868 | |||
20869 | global_table globals() const { | ||
20870 | return global; | ||
20871 | } | ||
20872 | |||
20873 | table registry() const { | ||
20874 | return reg; | ||
20875 | } | ||
20876 | |||
20877 | std::size_t memory_used() const { | ||
20878 | return total_memory_used(lua_state()); | ||
20879 | } | ||
20880 | |||
20881 | int stack_top() const { | ||
20882 | return stack::top(L); | ||
20883 | } | ||
20884 | |||
20885 | int stack_clear() { | ||
20886 | int s = stack_top(); | ||
20887 | lua_pop(L, s); | ||
20888 | return s; | ||
20889 | } | ||
20890 | |||
20891 | void collect_garbage() { | ||
20892 | lua_gc(lua_state(), LUA_GCCOLLECT, 0); | ||
20893 | } | ||
20894 | |||
20895 | operator lua_State*() const { | ||
20896 | return lua_state(); | ||
20897 | } | ||
20898 | |||
20899 | void set_panic(lua_CFunction panic) { | ||
20900 | lua_atpanic(lua_state(), panic); | ||
20901 | } | ||
20902 | |||
20903 | void set_exception_handler(exception_handler_function handler) { | ||
20904 | set_default_exception_handler(lua_state(), handler); | ||
20905 | } | ||
20906 | |||
20907 | template <typename... Args, typename... Keys> | ||
20908 | decltype(auto) get(Keys&&... keys) const { | ||
20909 | return global.get<Args...>(std::forward<Keys>(keys)...); | ||
20910 | } | ||
20911 | |||
20912 | template <typename T, typename Key> | ||
20913 | decltype(auto) get_or(Key&& key, T&& otherwise) const { | ||
20914 | return global.get_or(std::forward<Key>(key), std::forward<T>(otherwise)); | ||
20915 | } | ||
20916 | |||
20917 | template <typename T, typename Key, typename D> | ||
20918 | decltype(auto) get_or(Key&& key, D&& otherwise) const { | ||
20919 | return global.get_or<T>(std::forward<Key>(key), std::forward<D>(otherwise)); | ||
20920 | } | ||
20921 | |||
20922 | template <typename... Args> | ||
20923 | state_view& set(Args&&... args) { | ||
20924 | global.set(std::forward<Args>(args)...); | ||
20925 | return *this; | ||
20926 | } | ||
20927 | |||
20928 | template <typename T, typename... Keys> | ||
20929 | decltype(auto) traverse_get(Keys&&... keys) const { | ||
20930 | return global.traverse_get<T>(std::forward<Keys>(keys)...); | ||
20931 | } | ||
20932 | |||
20933 | template <typename... Args> | ||
20934 | state_view& traverse_set(Args&&... args) { | ||
20935 | global.traverse_set(std::forward<Args>(args)...); | ||
20936 | return *this; | ||
20937 | } | ||
20938 | |||
20939 | template <typename T> | ||
20940 | state_view& set_usertype(usertype<T>& user) { | ||
20941 | return set_usertype(usertype_traits<T>::name(), user); | ||
20942 | } | ||
20943 | |||
20944 | template <typename Key, typename T> | ||
20945 | state_view& set_usertype(Key&& key, usertype<T>& user) { | ||
20946 | global.set_usertype(std::forward<Key>(key), user); | ||
20947 | return *this; | ||
20948 | } | ||
20949 | |||
20950 | template <typename Class, typename... Args> | ||
20951 | state_view& new_usertype(const std::string& name, Args&&... args) { | ||
20952 | global.new_usertype<Class>(name, std::forward<Args>(args)...); | ||
20953 | return *this; | ||
20954 | } | ||
20955 | |||
20956 | template <typename Class, typename CTor0, typename... CTor, typename... Args> | ||
20957 | state_view& new_usertype(const std::string& name, Args&&... args) { | ||
20958 | global.new_usertype<Class, CTor0, CTor...>(name, std::forward<Args>(args)...); | ||
20959 | return *this; | ||
20960 | } | ||
20961 | |||
20962 | template <typename Class, typename... CArgs, typename... Args> | ||
20963 | state_view& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { | ||
20964 | global.new_usertype<Class>(name, ctor, std::forward<Args>(args)...); | ||
20965 | return *this; | ||
20966 | } | ||
20967 | |||
20968 | template <typename Class, typename... Args> | ||
20969 | state_view& new_simple_usertype(const std::string& name, Args&&... args) { | ||
20970 | global.new_simple_usertype<Class>(name, std::forward<Args>(args)...); | ||
20971 | return *this; | ||
20972 | } | ||
20973 | |||
20974 | template <typename Class, typename CTor0, typename... CTor, typename... Args> | ||
20975 | state_view& new_simple_usertype(const std::string& name, Args&&... args) { | ||
20976 | global.new_simple_usertype<Class, CTor0, CTor...>(name, std::forward<Args>(args)...); | ||
20977 | return *this; | ||
20978 | } | ||
20979 | |||
20980 | template <typename Class, typename... CArgs, typename... Args> | ||
20981 | state_view& new_simple_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { | ||
20982 | global.new_simple_usertype<Class>(name, ctor, std::forward<Args>(args)...); | ||
20983 | return *this; | ||
20984 | } | ||
20985 | |||
20986 | template <typename Class, typename... Args> | ||
20987 | simple_usertype<Class> create_simple_usertype(Args&&... args) { | ||
20988 | return global.create_simple_usertype<Class>(std::forward<Args>(args)...); | ||
20989 | } | ||
20990 | |||
20991 | template <typename Class, typename CTor0, typename... CTor, typename... Args> | ||
20992 | simple_usertype<Class> create_simple_usertype(Args&&... args) { | ||
20993 | return global.create_simple_usertype<Class, CTor0, CTor...>(std::forward<Args>(args)...); | ||
20994 | } | ||
20995 | |||
20996 | template <typename Class, typename... CArgs, typename... Args> | ||
20997 | simple_usertype<Class> create_simple_usertype(constructors<CArgs...> ctor, Args&&... args) { | ||
20998 | return global.create_simple_usertype<Class>(ctor, std::forward<Args>(args)...); | ||
20999 | } | ||
21000 | |||
21001 | template <bool read_only = true, typename... Args> | ||
21002 | state_view& new_enum(const string_view& name, Args&&... args) { | ||
21003 | global.new_enum<read_only>(name, std::forward<Args>(args)...); | ||
21004 | return *this; | ||
21005 | } | ||
21006 | |||
21007 | template <typename T, bool read_only = true> | ||
21008 | state_view& new_enum(const string_view& name, std::initializer_list<std::pair<string_view, T>> items) { | ||
21009 | global.new_enum<T, read_only>(name, std::move(items)); | ||
21010 | return *this; | ||
21011 | } | ||
21012 | |||
21013 | template <typename Fx> | ||
21014 | void for_each(Fx&& fx) { | ||
21015 | global.for_each(std::forward<Fx>(fx)); | ||
21016 | } | ||
21017 | |||
21018 | template <typename T> | ||
21019 | proxy<global_table&, T> operator[](T&& key) { | ||
21020 | return global[std::forward<T>(key)]; | ||
21021 | } | ||
21022 | |||
21023 | template <typename T> | ||
21024 | proxy<const global_table&, T> operator[](T&& key) const { | ||
21025 | return global[std::forward<T>(key)]; | ||
21026 | } | ||
21027 | |||
21028 | template <typename Sig, typename... Args, typename Key> | ||
21029 | state_view& set_function(Key&& key, Args&&... args) { | ||
21030 | global.set_function<Sig>(std::forward<Key>(key), std::forward<Args>(args)...); | ||
21031 | return *this; | ||
21032 | } | ||
21033 | |||
21034 | template <typename... Args, typename Key> | ||
21035 | state_view& set_function(Key&& key, Args&&... args) { | ||
21036 | global.set_function(std::forward<Key>(key), std::forward<Args>(args)...); | ||
21037 | return *this; | ||
21038 | } | ||
21039 | |||
21040 | template <typename Name> | ||
21041 | table create_table(Name&& name, int narr = 0, int nrec = 0) { | ||
21042 | return global.create(std::forward<Name>(name), narr, nrec); | ||
21043 | } | ||
21044 | |||
21045 | template <typename Name, typename Key, typename Value, typename... Args> | ||
21046 | table create_table(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { | ||
21047 | return global.create(std::forward<Name>(name), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); | ||
21048 | } | ||
21049 | |||
21050 | template <typename Name, typename... Args> | ||
21051 | table create_named_table(Name&& name, Args&&... args) { | ||
21052 | table x = global.create_with(std::forward<Args>(args)...); | ||
21053 | global.set(std::forward<Name>(name), x); | ||
21054 | return x; | ||
21055 | } | ||
21056 | |||
21057 | table create_table(int narr = 0, int nrec = 0) { | ||
21058 | return create_table(lua_state(), narr, nrec); | ||
21059 | } | ||
21060 | |||
21061 | template <typename Key, typename Value, typename... Args> | ||
21062 | table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { | ||
21063 | return create_table(lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); | ||
21064 | } | ||
21065 | |||
21066 | template <typename... Args> | ||
21067 | table create_table_with(Args&&... args) { | ||
21068 | return create_table_with(lua_state(), std::forward<Args>(args)...); | ||
21069 | } | ||
21070 | |||
21071 | static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) { | ||
21072 | return global_table::create(L, narr, nrec); | ||
21073 | } | ||
21074 | |||
21075 | template <typename Key, typename Value, typename... Args> | ||
21076 | static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { | ||
21077 | return global_table::create(L, narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); | ||
21078 | } | ||
21079 | |||
21080 | template <typename... Args> | ||
21081 | static inline table create_table_with(lua_State* L, Args&&... args) { | ||
21082 | return global_table::create_with(L, std::forward<Args>(args)...); | ||
21083 | } | ||
21084 | }; | ||
21085 | } // namespace sol | ||
21086 | |||
21087 | // end of sol/state_view.hpp | ||
21088 | |||
21089 | // beginning of sol/thread.hpp | ||
21090 | |||
21091 | namespace sol { | ||
21092 | struct lua_thread_state { | ||
21093 | lua_State* L; | ||
21094 | |||
21095 | lua_thread_state(lua_State* Ls) | ||
21096 | : L(Ls) { | ||
21097 | } | ||
21098 | |||
21099 | lua_State* lua_state() const noexcept { | ||
21100 | return L; | ||
21101 | } | ||
21102 | operator lua_State*() const noexcept { | ||
21103 | return lua_state(); | ||
21104 | } | ||
21105 | lua_State* operator->() const noexcept { | ||
21106 | return lua_state(); | ||
21107 | } | ||
21108 | }; | ||
21109 | |||
21110 | namespace stack { | ||
21111 | template <> | ||
21112 | struct pusher<lua_thread_state> { | ||
21113 | int push(lua_State*, lua_thread_state lts) { | ||
21114 | lua_pushthread(lts.L); | ||
21115 | return 1; | ||
21116 | } | ||
21117 | }; | ||
21118 | |||
21119 | template <> | ||
21120 | struct getter<lua_thread_state> { | ||
21121 | lua_thread_state get(lua_State* L, int index, record& tracking) { | ||
21122 | tracking.use(1); | ||
21123 | lua_thread_state lts( lua_tothread(L, index) ); | ||
21124 | return lts; | ||
21125 | } | ||
21126 | }; | ||
21127 | |||
21128 | template <> | ||
21129 | struct check_getter<lua_thread_state> { | ||
21130 | template <typename Handler> | ||
21131 | optional<lua_thread_state> get(lua_State* L, int index, Handler&& handler, record& tracking) { | ||
21132 | lua_thread_state lts( lua_tothread(L, index) ); | ||
21133 | if (lts.lua_state() == nullptr) { | ||
21134 | handler(L, index, type::thread, type_of(L, index), "value is not a valid thread type"); | ||
21135 | return nullopt; | ||
21136 | } | ||
21137 | tracking.use(1); | ||
21138 | return lts; | ||
21139 | } | ||
21140 | }; | ||
21141 | } // namespace stack | ||
21142 | |||
21143 | template <typename base_t> | ||
21144 | class basic_thread : public base_t { | ||
21145 | public: | ||
21146 | using base_t::lua_state; | ||
21147 | |||
21148 | basic_thread() noexcept = default; | ||
21149 | basic_thread(const basic_thread&) = default; | ||
21150 | basic_thread(basic_thread&&) = default; | ||
21151 | 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> | ||
21152 | basic_thread(T&& r) | ||
21153 | : base_t(std::forward<T>(r)) { | ||
21154 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21155 | auto pp = stack::push_pop(*this); | ||
21156 | constructor_handler handler{}; | ||
21157 | stack::check<basic_thread>(lua_state(), -1, handler); | ||
21158 | #endif // Safety | ||
21159 | } | ||
21160 | basic_thread(const stack_reference& r) | ||
21161 | : basic_thread(r.lua_state(), r.stack_index()){}; | ||
21162 | basic_thread(stack_reference&& r) | ||
21163 | : basic_thread(r.lua_state(), r.stack_index()){}; | ||
21164 | basic_thread& operator=(const basic_thread&) = default; | ||
21165 | basic_thread& operator=(basic_thread&&) = default; | ||
21166 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
21167 | basic_thread(lua_State* L, T&& r) | ||
21168 | : base_t(L, std::forward<T>(r)) { | ||
21169 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21170 | auto pp = stack::push_pop(*this); | ||
21171 | constructor_handler handler{}; | ||
21172 | stack::check<basic_thread>(lua_state(), -1, handler); | ||
21173 | #endif // Safety | ||
21174 | } | ||
21175 | basic_thread(lua_State* L, int index = -1) | ||
21176 | : base_t(L, index) { | ||
21177 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21178 | constructor_handler handler{}; | ||
21179 | stack::check<basic_thread>(L, index, handler); | ||
21180 | #endif // Safety | ||
21181 | } | ||
21182 | basic_thread(lua_State* L, ref_index index) | ||
21183 | : base_t(L, index) { | ||
21184 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21185 | auto pp = stack::push_pop(*this); | ||
21186 | constructor_handler handler{}; | ||
21187 | stack::check<basic_thread>(lua_state(), -1, handler); | ||
21188 | #endif // Safety | ||
21189 | } | ||
21190 | basic_thread(lua_State* L, lua_State* actualthread) | ||
21191 | : basic_thread(L, lua_thread_state{ actualthread }) { | ||
21192 | } | ||
21193 | basic_thread(lua_State* L, this_state actualthread) | ||
21194 | : basic_thread(L, lua_thread_state{ actualthread.L }) { | ||
21195 | } | ||
21196 | basic_thread(lua_State* L, lua_thread_state actualthread) | ||
21197 | : base_t(L, -stack::push(L, actualthread)) { | ||
21198 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21199 | constructor_handler handler{}; | ||
21200 | stack::check<basic_thread>(lua_state(), -1, handler); | ||
21201 | #endif // Safety | ||
21202 | if (!is_stack_based<base_t>::value) { | ||
21203 | lua_pop(lua_state(), 1); | ||
21204 | } | ||
21205 | } | ||
21206 | |||
21207 | state_view state() const { | ||
21208 | return state_view(this->thread_state()); | ||
21209 | } | ||
21210 | |||
21211 | bool is_main_thread() const { | ||
21212 | return stack::is_main_thread(this->thread_state()); | ||
21213 | } | ||
21214 | |||
21215 | lua_State* thread_state() const { | ||
21216 | auto pp = stack::push_pop(*this); | ||
21217 | lua_State* lthread = lua_tothread(lua_state(), -1); | ||
21218 | return lthread; | ||
21219 | } | ||
21220 | |||
21221 | thread_status status() const { | ||
21222 | lua_State* lthread = thread_state(); | ||
21223 | auto lstat = static_cast<thread_status>(lua_status(lthread)); | ||
21224 | if (lstat == thread_status::ok) { | ||
21225 | lua_Debug ar; | ||
21226 | if (lua_getstack(lthread, 0, &ar) > 0) | ||
21227 | return thread_status::ok; | ||
21228 | else if (lua_gettop(lthread) == 0) | ||
21229 | return thread_status::dead; | ||
21230 | else | ||
21231 | return thread_status::yielded; | ||
21232 | } | ||
21233 | return lstat; | ||
21234 | } | ||
21235 | |||
21236 | basic_thread create() { | ||
21237 | return create(lua_state()); | ||
21238 | } | ||
21239 | |||
21240 | static basic_thread create(lua_State* L) { | ||
21241 | lua_newthread(L); | ||
21242 | basic_thread result(L); | ||
21243 | if (!is_stack_based<base_t>::value) { | ||
21244 | lua_pop(L, 1); | ||
21245 | } | ||
21246 | return result; | ||
21247 | } | ||
21248 | }; | ||
21249 | |||
21250 | typedef basic_thread<reference> thread; | ||
21251 | typedef basic_thread<stack_reference> stack_thread; | ||
21252 | } // namespace sol | ||
21253 | |||
21254 | // end of sol/thread.hpp | ||
21255 | |||
21256 | namespace sol { | ||
21257 | |||
21258 | class state : private std::unique_ptr<lua_State, detail::state_deleter>, public state_view { | ||
21259 | private: | ||
21260 | typedef std::unique_ptr<lua_State, detail::state_deleter> unique_base; | ||
21261 | |||
21262 | public: | ||
21263 | state(lua_CFunction panic = default_at_panic) | ||
21264 | : unique_base(luaL_newstate()), state_view(unique_base::get()) { | ||
21265 | set_default_state(unique_base::get(), panic); | ||
21266 | } | ||
21267 | |||
21268 | state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) | ||
21269 | : unique_base(lua_newstate(alfunc, alpointer)), state_view(unique_base::get()) { | ||
21270 | set_default_state(unique_base::get(), panic); | ||
21271 | } | ||
21272 | |||
21273 | state(const state&) = delete; | ||
21274 | state(state&&) = default; | ||
21275 | state& operator=(const state&) = delete; | ||
21276 | state& operator=(state&& that) { | ||
21277 | state_view::operator=(std::move(that)); | ||
21278 | unique_base::operator=(std::move(that)); | ||
21279 | return *this; | ||
21280 | } | ||
21281 | |||
21282 | using state_view::get; | ||
21283 | |||
21284 | ~state() { | ||
21285 | } | ||
21286 | }; | ||
21287 | } // namespace sol | ||
21288 | |||
21289 | // end of sol/state.hpp | ||
21290 | |||
21291 | // beginning of sol/coroutine.hpp | ||
21292 | |||
21293 | namespace sol { | ||
21294 | template <typename base_t> | ||
21295 | class basic_coroutine : public base_t { | ||
21296 | public: | ||
21297 | typedef reference handler_t; | ||
21298 | handler_t error_handler; | ||
21299 | |||
21300 | private: | ||
21301 | call_status stats = call_status::yielded; | ||
21302 | |||
21303 | void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { | ||
21304 | stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount))); | ||
21305 | } | ||
21306 | |||
21307 | template <std::size_t... I, typename... Ret> | ||
21308 | auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) { | ||
21309 | luacall(n, sizeof...(Ret)); | ||
21310 | return stack::pop<std::tuple<Ret...>>(lua_state()); | ||
21311 | } | ||
21312 | |||
21313 | template <std::size_t I, typename Ret> | ||
21314 | Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) { | ||
21315 | luacall(n, 1); | ||
21316 | return stack::pop<Ret>(lua_state()); | ||
21317 | } | ||
21318 | |||
21319 | template <std::size_t I> | ||
21320 | void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) { | ||
21321 | luacall(n, 0); | ||
21322 | } | ||
21323 | |||
21324 | protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) { | ||
21325 | int firstreturn = 1; | ||
21326 | luacall(n, LUA_MULTRET); | ||
21327 | int poststacksize = lua_gettop(this->lua_state()); | ||
21328 | int returncount = poststacksize - (firstreturn - 1); | ||
21329 | if (error()) { | ||
21330 | if (error_handler.valid()) { | ||
21331 | string_view err = stack::get<string_view>(this->lua_state(), poststacksize); | ||
21332 | error_handler.push(); | ||
21333 | stack::push(this->lua_state(), err); | ||
21334 | lua_call(lua_state(), 1, 1); | ||
21335 | } | ||
21336 | return protected_function_result(this->lua_state(), lua_absindex(this->lua_state(), -1), 1, returncount, status()); | ||
21337 | } | ||
21338 | return protected_function_result(this->lua_state(), firstreturn, returncount, returncount, status()); | ||
21339 | } | ||
21340 | |||
21341 | public: | ||
21342 | using base_t::lua_state; | ||
21343 | |||
21344 | basic_coroutine() = default; | ||
21345 | template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_coroutine>>, 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> | ||
21346 | basic_coroutine(T&& r) noexcept | ||
21347 | : base_t(std::forward<T>(r)), error_handler(detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) { | ||
21348 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21349 | if (!is_function<meta::unqualified_t<T>>::value) { | ||
21350 | auto pp = stack::push_pop(*this); | ||
21351 | constructor_handler handler{}; | ||
21352 | stack::check<basic_coroutine>(lua_state(), -1, handler); | ||
21353 | } | ||
21354 | #endif // Safety | ||
21355 | } | ||
21356 | basic_coroutine(const basic_coroutine&) = default; | ||
21357 | basic_coroutine& operator=(const basic_coroutine&) = default; | ||
21358 | basic_coroutine(basic_coroutine&&) = default; | ||
21359 | basic_coroutine& operator=(basic_coroutine&&) = default; | ||
21360 | basic_coroutine(const basic_function<base_t>& b) | ||
21361 | : basic_coroutine(b, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(b.lua_state())) { | ||
21362 | } | ||
21363 | basic_coroutine(basic_function<base_t>&& b) | ||
21364 | : basic_coroutine(std::move(b), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(b.lua_state())) { | ||
21365 | } | ||
21366 | basic_coroutine(const basic_function<base_t>& b, handler_t eh) | ||
21367 | : base_t(b), error_handler(std::move(eh)) { | ||
21368 | } | ||
21369 | basic_coroutine(basic_function<base_t>&& b, handler_t eh) | ||
21370 | : base_t(std::move(b)), error_handler(std::move(eh)) { | ||
21371 | } | ||
21372 | basic_coroutine(const stack_reference& r) | ||
21373 | : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) { | ||
21374 | } | ||
21375 | basic_coroutine(stack_reference&& r) | ||
21376 | : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) { | ||
21377 | } | ||
21378 | basic_coroutine(const stack_reference& r, handler_t eh) | ||
21379 | : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) { | ||
21380 | } | ||
21381 | basic_coroutine(stack_reference&& r, handler_t eh) | ||
21382 | : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) { | ||
21383 | } | ||
21384 | |||
21385 | template <typename Super> | ||
21386 | basic_coroutine(const proxy_base<Super>& p) | ||
21387 | : basic_coroutine(p, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) { | ||
21388 | } | ||
21389 | template <typename Super> | ||
21390 | basic_coroutine(proxy_base<Super>&& p) | ||
21391 | : basic_coroutine(std::move(p), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) { | ||
21392 | } | ||
21393 | 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> | ||
21394 | basic_coroutine(Proxy&& p, Handler&& eh) | ||
21395 | : basic_coroutine(detail::force_cast<base_t>(p), std::forward<Handler>(eh)) { | ||
21396 | } | ||
21397 | |||
21398 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
21399 | basic_coroutine(lua_State* L, T&& r) | ||
21400 | : basic_coroutine(L, std::forward<T>(r), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { | ||
21401 | } | ||
21402 | template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> | ||
21403 | basic_coroutine(lua_State* L, T&& r, handler_t eh) | ||
21404 | : base_t(L, std::forward<T>(r)), error_handler(std::move(eh)) { | ||
21405 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21406 | auto pp = stack::push_pop(*this); | ||
21407 | constructor_handler handler{}; | ||
21408 | stack::check<basic_coroutine>(lua_state(), -1, handler); | ||
21409 | #endif // Safety | ||
21410 | } | ||
21411 | |||
21412 | basic_coroutine(lua_nil_t n) | ||
21413 | : base_t(n), error_handler(n) { | ||
21414 | } | ||
21415 | |||
21416 | basic_coroutine(lua_State* L, int index = -1) | ||
21417 | : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { | ||
21418 | } | ||
21419 | basic_coroutine(lua_State* L, int index, handler_t eh) | ||
21420 | : base_t(L, index), error_handler(std::move(eh)) { | ||
21421 | #ifdef SOL_SAFE_REFERENCES | ||
21422 | constructor_handler handler{}; | ||
21423 | stack::check<basic_coroutine>(L, index, handler); | ||
21424 | #endif // Safety | ||
21425 | } | ||
21426 | basic_coroutine(lua_State* L, absolute_index index) | ||
21427 | : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { | ||
21428 | } | ||
21429 | basic_coroutine(lua_State* L, absolute_index index, handler_t eh) | ||
21430 | : base_t(L, index), error_handler(std::move(eh)) { | ||
21431 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21432 | constructor_handler handler{}; | ||
21433 | stack::check<basic_coroutine>(L, index, handler); | ||
21434 | #endif // Safety | ||
21435 | } | ||
21436 | basic_coroutine(lua_State* L, raw_index index) | ||
21437 | : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { | ||
21438 | } | ||
21439 | basic_coroutine(lua_State* L, raw_index index, handler_t eh) | ||
21440 | : base_t(L, index), error_handler(std::move(eh)) { | ||
21441 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21442 | constructor_handler handler{}; | ||
21443 | stack::check<basic_coroutine>(L, index, handler); | ||
21444 | #endif // Safety | ||
21445 | } | ||
21446 | basic_coroutine(lua_State* L, ref_index index) | ||
21447 | : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { | ||
21448 | } | ||
21449 | basic_coroutine(lua_State* L, ref_index index, handler_t eh) | ||
21450 | : base_t(L, index), error_handler(std::move(eh)) { | ||
21451 | #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES | ||
21452 | auto pp = stack::push_pop(*this); | ||
21453 | constructor_handler handler{}; | ||
21454 | stack::check<basic_coroutine>(lua_state(), -1, handler); | ||
21455 | #endif // Safety | ||
21456 | } | ||
21457 | |||
21458 | call_status status() const noexcept { | ||
21459 | return stats; | ||
21460 | } | ||
21461 | |||
21462 | bool error() const noexcept { | ||
21463 | call_status cs = status(); | ||
21464 | return cs != call_status::ok && cs != call_status::yielded; | ||
21465 | } | ||
21466 | |||
21467 | bool runnable() const noexcept { | ||
21468 | return base_t::valid() | ||
21469 | && (status() == call_status::yielded); | ||
21470 | } | ||
21471 | |||
21472 | explicit operator bool() const noexcept { | ||
21473 | return runnable(); | ||
21474 | } | ||
21475 | |||
21476 | template <typename... Args> | ||
21477 | protected_function_result operator()(Args&&... args) { | ||
21478 | return call<>(std::forward<Args>(args)...); | ||
21479 | } | ||
21480 | |||
21481 | template <typename... Ret, typename... Args> | ||
21482 | decltype(auto) operator()(types<Ret...>, Args&&... args) { | ||
21483 | return call<Ret...>(std::forward<Args>(args)...); | ||
21484 | } | ||
21485 | |||
21486 | template <typename... Ret, typename... Args> | ||
21487 | decltype(auto) call(Args&&... args) { | ||
21488 | // some users screw up coroutine.create | ||
21489 | // and try to use it with sol::coroutine without ever calling the first resume in Lua | ||
21490 | // this makes the stack incompatible with other kinds of stacks: protect against this | ||
21491 | // make sure coroutines don't screw us over | ||
21492 | base_t::push(); | ||
21493 | int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); | ||
21494 | return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount); | ||
21495 | } | ||
21496 | }; | ||
21497 | } // namespace sol | ||
21498 | |||
21499 | // end of sol/coroutine.hpp | ||
21500 | |||
21501 | // beginning of sol/variadic_results.hpp | ||
21502 | |||
21503 | // beginning of sol/as_returns.hpp | ||
21504 | |||
21505 | namespace sol { | ||
21506 | template <typename T> | ||
21507 | struct as_returns_t { | ||
21508 | T src; | ||
21509 | }; | ||
21510 | |||
21511 | template <typename Source> | ||
21512 | auto as_returns(Source&& source) { | ||
21513 | return as_returns_t<std::decay_t<Source>>{ std::forward<Source>(source) }; | ||
21514 | } | ||
21515 | |||
21516 | namespace stack { | ||
21517 | template <typename T> | ||
21518 | struct pusher<as_returns_t<T>> { | ||
21519 | int push(lua_State* L, const as_returns_t<T>& e) { | ||
21520 | auto& src = detail::unwrap(e.src); | ||
21521 | int p = 0; | ||
21522 | for (const auto& i : src) { | ||
21523 | p += stack::push(L, i); | ||
21524 | } | ||
21525 | return p; | ||
21526 | } | ||
21527 | }; | ||
21528 | } // namespace stack | ||
21529 | } // namespace sol | ||
21530 | |||
21531 | // end of sol/as_returns.hpp | ||
21532 | |||
21533 | namespace sol { | ||
21534 | |||
21535 | struct variadic_results : public std::vector<object> { | ||
21536 | using std::vector<object>::vector; | ||
21537 | }; | ||
21538 | |||
21539 | namespace stack { | ||
21540 | template <> | ||
21541 | struct pusher<variadic_results> { | ||
21542 | int push(lua_State* L, const variadic_results& e) { | ||
21543 | int p = 0; | ||
21544 | for (const auto& i : e) { | ||
21545 | p += stack::push(L, i); | ||
21546 | } | ||
21547 | return p; | ||
21548 | } | ||
21549 | }; | ||
21550 | } // namespace stack | ||
21551 | |||
21552 | } // namespace sol | ||
21553 | |||
21554 | // end of sol/variadic_results.hpp | ||
21555 | |||
21556 | #if defined(__GNUC__) | ||
21557 | #pragma GCC diagnostic pop | ||
21558 | #elif defined _MSC_VER | ||
21559 | #pragma warning( push ) | ||
21560 | #endif // g++ | ||
21561 | |||
21562 | #if defined(SOL_INSIDE_UNREAL) && SOL_INSIDE_UNREAL | ||
21563 | #if defined(SOL_INSIDE_UNREAL_REMOVED_CHECK) && SOL_INSIDE_UNREAL_REMOVED_CHECK | ||
21564 | #if DO_CHECK | ||
21565 | #define check(expr) { if(UNLIKELY(!(expr))) { FDebug::LogAssertFailedMessage( #expr, __FILE__, __LINE__ ); _DebugBreakAndPromptForRemote(); FDebug::AssertFailed( #expr, __FILE__, __LINE__ ); CA_ASSUME(false); } } | ||
21566 | #else | ||
21567 | #define check(expr) { CA_ASSUME(expr); } | ||
21568 | #endif | ||
21569 | #endif | ||
21570 | #endif // Unreal Engine 4 Bullshit | ||
21571 | |||
21572 | #endif // SOL_HPP | ||
21573 | // end of sol.hpp | ||
21574 | |||
21575 | #endif // SOL_SINGLE_INCLUDE_HPP | ||