diff options
Diffstat (limited to 'vendor')
| -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 | ||
