summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-05-10 19:27:59 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-05-17 15:39:39 -0400
commit4bbfeae42a1245b1b84e8847787d7643e6a6f2cf (patch)
tree8dd65d9ab0cfffd0e79f670c94b035c5eebfa934
parent67b24a8ddd89371cfb944c5b441c852f0edc23b1 (diff)
downloadtherapy-4bbfeae42a1245b1b84e8847787d7643e6a6f2cf.tar.gz
therapy-4bbfeae42a1245b1b84e8847787d7643e6a6f2cf.tar.bz2
therapy-4bbfeae42a1245b1b84e8847787d7643e6a6f2cf.zip
Started integrating Lua as a scripting engine
Currently moving platforms are able to have their movement controlled by a script rather than by XML, which is probably a better implementation and scales better to other things. The scripts, instead of using the components as state, use the stack as state. In this way, they pretend to be multithreaded. For instance, the moving platform calls moveRight and then moveLeft. Both of those functions internally make calls that say to wait until the next tick. When the AutomatingSystem ticks, it continues execution of all scripts (sequentially, of course) until they ask for the next tick again. This is implemented using coroutines.
-rw-r--r--CMakeLists.txt5
-rw-r--r--res/platform.lua27
-rw-r--r--src/components/automatable.h81
-rw-r--r--src/components/realizable.h3
-rw-r--r--src/systems/automating.cpp99
-rw-r--r--src/systems/automating.h3
-rw-r--r--src/systems/realizing.cpp153
-rw-r--r--src/vector.h10
-rw-r--r--vendor/sol.hpp21575
9 files changed, 21688 insertions, 268 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 04ca668..fbc843c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -16,6 +16,7 @@ find_package(GLEW REQUIRED)
16find_package(portaudio REQUIRED) 16find_package(portaudio REQUIRED)
17find_package(libsndfile REQUIRED) 17find_package(libsndfile REQUIRED)
18find_package(libxml2 REQUIRED) 18find_package(libxml2 REQUIRED)
19find_package(lua REQUIRED)
19 20
20IF(APPLE) 21IF(APPLE)
21 FIND_LIBRARY(COCOA_LIBRARY Cocoa) 22 FIND_LIBRARY(COCOA_LIBRARY Cocoa)
@@ -32,6 +33,7 @@ set(ALL_LIBS
32 ${PORTAUDIO_LIBRARIES} 33 ${PORTAUDIO_LIBRARIES}
33 ${LIBSNDFILE_LIBRARY} 34 ${LIBSNDFILE_LIBRARY}
34 ${LIBXML2_LIBRARIES} 35 ${LIBXML2_LIBRARIES}
36 ${LUA_LIBRARIES}
35 ${EXTRA_LIBS} 37 ${EXTRA_LIBS}
36) 38)
37 39
@@ -40,6 +42,7 @@ include_directories(
40 ${GLFW_INCLUDE_DIRS} 42 ${GLFW_INCLUDE_DIRS}
41 ${OPENGL_INCLUDE_DIRS} 43 ${OPENGL_INCLUDE_DIRS}
42 ${GLEW_INCLUDE_DIRS} 44 ${GLEW_INCLUDE_DIRS}
45 ${LUA_INCLUDE_DIRS}
43 src 46 src
44 vendor 47 vendor
45) 48)
@@ -71,6 +74,6 @@ add_executable(Aromatherapy
71 vendor/stb_image.cpp 74 vendor/stb_image.cpp
72) 75)
73 76
74set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 11) 77set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 17)
75set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD_REQUIRED ON) 78set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD_REQUIRED ON)
76target_link_libraries(Aromatherapy ${ALL_LIBS}) 79target_link_libraries(Aromatherapy ${ALL_LIBS})
diff --git a/res/platform.lua b/res/platform.lua new file mode 100644 index 0000000..31a7cba --- /dev/null +++ b/res/platform.lua
@@ -0,0 +1,27 @@
1function moveLeft(entity, len, speed)
2 local remaining = len / speed
3
4 while (remaining > 0) do
5 print("no")
6 --entity:ponderable().vel:x(-speed)
7 remaining = remaining - coroutine.yield()
8 end
9end
10
11function moveRight(entity, len, speed)
12 local remaining = len / speed
13
14 while (remaining > 0) do
15 print("no2")
16 --entity:ponderable().vel:x(speed)
17 remaining = remaining - coroutine.yield()
18 end
19end
20
21function run(entity)
22 print("yes")
23 while true do
24 moveRight(entity, 90, 30)
25 moveLeft(entity, 90, 30)
26 end
27end \ No newline at end of file
diff --git a/src/components/automatable.h b/src/components/automatable.h index c1fd1a3..d30340a 100644 --- a/src/components/automatable.h +++ b/src/components/automatable.h
@@ -2,87 +2,16 @@
2#define AUTOMATABLE_H_3D519131 2#define AUTOMATABLE_H_3D519131
3 3
4#include "component.h" 4#include "component.h"
5#include <vector> 5#include <sol.hpp>
6#include <random> 6#include <memory>
7#include "vector.h"
8 7
9class AutomatableComponent : public Component { 8class AutomatableComponent : public Component {
10public: 9public:
11 10
12 /** 11 std::unique_ptr<sol::thread> runner;
13 * Helper class that defines an automatable action. 12 std::unique_ptr<sol::coroutine> behavior;
14 */
15 class Action {
16 public:
17
18 /**
19 * The horizontal and vertical speed, in pixels/sec, that the entity should
20 * move at.
21 */
22 vec2d speed;
23
24 /**
25 * The duration of the action in seconds.
26 */
27 double dur;
28 };
29
30 /**
31 * Helper type that defines a behavior that an entity can exhibit, which is a
32 * list of actions that are stepped through in sequence.
33 */
34 using Behavior = std::vector<Action>;
35
36 /**
37 * A group of behaviors that the entity can exhibit, which are picked at
38 * random at the start of automation and whenever a behavior completes.
39 *
40 * @managed_by RealizingSystem
41 */
42 std::vector<Behavior> behaviors;
43
44 /**
45 * A random distribution over the above behaviors.
46 *
47 * @managed_by RealizingSystem
48 */
49 std::discrete_distribution<size_t> behaviorDist;
50
51 /**
52 * A flag indicating whether a behavior is currently executing.
53 *
54 * @managed_by AutomatingSystem
55 */
56 bool behaviorRunning = false;
57
58 /**
59 * A flag indicating whether an action is currently executing.
60 *
61 * @managed_by AutomatingSystem
62 */
63 bool actionRunning = false;
64
65 /**
66 * The index of the currently executing behavior, if there is one.
67 *
68 * @managed_by AutomatingSystem
69 */
70 size_t currentBehavior;
71 13
72 /** 14 sol::environment origBehavior;
73 * The index of the currently executing action, if there is one.
74 *
75 * @managed_by AutomatingSystem
76 */
77 size_t currentAction;
78
79 /**
80 * The amount of time remaining, in seconds, of the currently executing
81 * action.
82 *
83 * @managed_by AutomatingSystem
84 */
85 double remaining;
86 15
87 /** 16 /**
88 * If this flag is disabled, the entity will be ignored by the automating 17 * If this flag is disabled, the entity will be ignored by the automating
diff --git a/src/components/realizable.h b/src/components/realizable.h index b749aeb..bc834a2 100644 --- a/src/components/realizable.h +++ b/src/components/realizable.h
@@ -4,6 +4,7 @@
4#include "component.h" 4#include "component.h"
5#include <set> 5#include <set>
6#include <map> 6#include <map>
7#include <sol.hpp>
7#include "entity_manager.h" 8#include "entity_manager.h"
8#include "vector.h" 9#include "vector.h"
9 10
@@ -69,6 +70,8 @@ public:
69 * The entity ID of the currently active player. 70 * The entity ID of the currently active player.
70 */ 71 */
71 id_type activePlayer; 72 id_type activePlayer;
73
74 sol::state scriptEngine;
72}; 75};
73 76
74#endif /* end of include guard: REALIZABLE_H_36D8D71E */ 77#endif /* end of include guard: REALIZABLE_H_36D8D71E */
diff --git a/src/systems/automating.cpp b/src/systems/automating.cpp index 61b97d9..6cec3bf 100644 --- a/src/systems/automating.cpp +++ b/src/systems/automating.cpp
@@ -2,13 +2,24 @@
2#include "game.h" 2#include "game.h"
3#include "components/automatable.h" 3#include "components/automatable.h"
4#include "components/ponderable.h" 4#include "components/ponderable.h"
5#include "systems/pondering.h" 5#include "components/realizable.h"
6#include "systems/realizing.h"
7#include "vector.h"
8
9struct script_entity {
10 using id_type = EntityManager::id_type;
11
12 id_type id;
13
14 script_entity(id_type id) : id(id)
15 {
16 }
17};
6 18
7void AutomatingSystem::tick(double dt) 19void AutomatingSystem::tick(double dt)
8{ 20{
9 auto entities = game_.getEntityManager().getEntitiesWithComponents< 21 auto entities = game_.getEntityManager().getEntitiesWithComponents<
10 AutomatableComponent, 22 AutomatableComponent>();
11 PonderableComponent>();
12 23
13 for (id_type entity : entities) 24 for (id_type entity : entities)
14 { 25 {
@@ -20,43 +31,7 @@ void AutomatingSystem::tick(double dt)
20 continue; 31 continue;
21 } 32 }
22 33
23 if (automatable.behaviorRunning && 34 (*automatable.behavior)(dt);
24 (automatable.remaining <= 0.0))
25 {
26 automatable.currentAction++;
27 automatable.actionRunning = false;
28
29 if (automatable.currentAction ==
30 automatable.behaviors[automatable.currentBehavior].size())
31 {
32 automatable.behaviorRunning = false;
33 }
34 }
35
36 if (!automatable.behaviorRunning)
37 {
38 automatable.currentBehavior = automatable.behaviorDist(game_.getRng());
39 automatable.currentAction = 0;
40 automatable.behaviorRunning = true;
41 }
42
43 AutomatableComponent::Action& curAction =
44 automatable.behaviors
45 [automatable.currentBehavior]
46 [automatable.currentAction];
47
48 if (!automatable.actionRunning)
49 {
50 automatable.remaining = curAction.dur;
51 automatable.actionRunning = true;
52 }
53
54 auto& ponderable = game_.getEntityManager().
55 getComponent<PonderableComponent>(entity);
56
57 ponderable.vel = curAction.speed;
58
59 automatable.remaining -= dt;
60 } 35 }
61} 36}
62 37
@@ -65,6 +40,46 @@ void AutomatingSystem::initPrototype(id_type prototype)
65 auto& automatable = game_.getEntityManager(). 40 auto& automatable = game_.getEntityManager().
66 getComponent<AutomatableComponent>(prototype); 41 getComponent<AutomatableComponent>(prototype);
67 42
68 automatable.behaviorRunning = false; 43 auto& realizable = game_.getEntityManager().
69 automatable.actionRunning = false; 44 getComponent<RealizableComponent>(
45 game_.getSystemManager().getSystem<RealizingSystem>().getSingleton());
46 automatable.behavior.reset();
47 automatable.runner = std::unique_ptr<sol::thread>(new sol::thread(sol::thread::create(realizable.scriptEngine.lua_state())));
48 automatable.behavior = std::unique_ptr<sol::coroutine>(new sol::coroutine(automatable.runner->state()["run"]));
49 (*automatable.behavior)(script_entity(prototype));
50}
51
52void AutomatingSystem::initScriptEngine(sol::state& scriptEngine)
53{
54 scriptEngine.open_libraries(sol::lib::base, sol::lib::coroutine);
55 scriptEngine.new_usertype<vec2d>(
56 "vec2d",
57 sol::constructors<vec2d(), vec2d(double, double)>(),
58 "x", sol::property(
59 [] (vec2d& v) -> double { return v.x(); },
60 [] (vec2d& v, double x) { v.x() = x; }),
61 "y", sol::property(
62 [] (vec2d& v) -> double { return v.y(); },
63 [] (vec2d& v, double y) { v.y() = y; }));
64
65 scriptEngine.new_usertype<vec2i>(
66 "vec2i",
67 sol::constructors<vec2i(), vec2i(int, int)>(),
68 "x", [] (vec2i& v) -> int& { return v.x(); },
69 "y", [] (vec2i& v) -> int& { return v.y(); });
70
71 scriptEngine.new_usertype<script_entity>(
72 "entity",
73 sol::constructors<script_entity(id_type)>(),
74 "id", &script_entity::id,
75 "ponderable",
76 [&] (script_entity& entity) -> PonderableComponent& {
77 return game_.getEntityManager().
78 getComponent<PonderableComponent>(entity.id);
79 });
80
81 scriptEngine.new_usertype<PonderableComponent>(
82 "ponderable",
83 "vel", &PonderableComponent::vel,
84 "accel", &PonderableComponent::accel);
70} 85}
diff --git a/src/systems/automating.h b/src/systems/automating.h index c78b7cf..117b622 100644 --- a/src/systems/automating.h +++ b/src/systems/automating.h
@@ -2,6 +2,7 @@
2#define AUTOMATING_H_E6E5D76E 2#define AUTOMATING_H_E6E5D76E
3 3
4#include "system.h" 4#include "system.h"
5#include <sol.hpp>
5 6
6class AutomatingSystem : public System { 7class AutomatingSystem : public System {
7public: 8public:
@@ -14,6 +15,8 @@ public:
14 15
15 void initPrototype(id_type prototype); 16 void initPrototype(id_type prototype);
16 17
18 void initScriptEngine(sol::state& scriptEngine);
19
17}; 20};
18 21
19#endif /* end of include guard: AUTOMATING_H_E6E5D76E */ 22#endif /* end of include guard: AUTOMATING_H_E6E5D76E */
diff --git a/src/systems/realizing.cpp b/src/systems/realizing.cpp index f9285ad..28e2279 100644 --- a/src/systems/realizing.cpp +++ b/src/systems/realizing.cpp
@@ -29,92 +29,6 @@ inline xmlChar* getProp(xmlNodePtr node, const char* attr)
29 return key; 29 return key;
30} 30}
31 31
32void parseAI(
33 xmlNodePtr node,
34 std::vector<AutomatableComponent::Action>& behavior,
35 const std::map<std::string, int>& items)
36{
37 xmlChar* key = nullptr;
38
39 if (!xmlStrcmp(
40 node->name,
41 reinterpret_cast<const xmlChar*>("switch")))
42 {
43 key = getProp(node, "item");
44 std::string switchItem = reinterpret_cast<char*>(key);
45 xmlFree(key);
46
47 for (xmlNodePtr switchNode = node->xmlChildrenNode;
48 switchNode != nullptr;
49 switchNode = switchNode->next)
50 {
51 if (!xmlStrcmp(
52 switchNode->name,
53 reinterpret_cast<const xmlChar*>("case")))
54 {
55 key = getProp(switchNode, "value");
56 int caseValue = atoi(reinterpret_cast<char*>(key));
57 xmlFree(key);
58
59 if (items.at(switchItem) == caseValue)
60 {
61 for (xmlNodePtr caseNode = switchNode->xmlChildrenNode;
62 caseNode != nullptr;
63 caseNode = caseNode->next)
64 {
65 parseAI(
66 caseNode,
67 behavior,
68 items);
69 }
70 }
71 }
72 }
73 } else if (!xmlStrcmp(
74 node->name,
75 reinterpret_cast<const xmlChar*>("move")))
76 {
77 key = getProp(node, "direction");
78 std::string direction = reinterpret_cast<char*>(key);
79 xmlFree(key);
80
81 key = getProp(node, "length-var");
82 std::string lengthVar = reinterpret_cast<char*>(key);
83 xmlFree(key);
84
85 key = getProp(node, "speed-var");
86 std::string speedVar = reinterpret_cast<char*>(key);
87 xmlFree(key);
88
89 double length = items.at(lengthVar);
90 double speed = items.at(speedVar);
91
92 AutomatableComponent::Action action;
93
94 if (direction == "left")
95 {
96 action.speed.x() = -speed;
97 action.speed.y() = 0;
98 } else if (direction == "right")
99 {
100 action.speed.x() = speed;
101 action.speed.y() = 0;
102 } else if (direction == "up")
103 {
104 action.speed.x() = 0;
105 action.speed.y() = -speed;
106 } else if (direction == "down")
107 {
108 action.speed.x() = 0;
109 action.speed.y() = speed;
110 }
111
112 action.dur = length / speed;
113
114 behavior.push_back(std::move(action));
115 }
116}
117
118// TODO: neither the XML doc nor any of the emplaced entities are properly 32// TODO: neither the XML doc nor any of the emplaced entities are properly
119// destroyed if this method throws an exception. 33// destroyed if this method throws an exception.
120EntityManager::id_type RealizingSystem::initSingleton( 34EntityManager::id_type RealizingSystem::initSingleton(
@@ -126,6 +40,9 @@ EntityManager::id_type RealizingSystem::initSingleton(
126 auto& realizable = game_.getEntityManager(). 40 auto& realizable = game_.getEntityManager().
127 emplaceComponent<RealizableComponent>(world); 41 emplaceComponent<RealizableComponent>(world);
128 42
43 game_.getSystemManager().getSystem<AutomatingSystem>().
44 initScriptEngine(realizable.scriptEngine);
45
129 realizable.worldFile = worldFile; 46 realizable.worldFile = worldFile;
130 realizable.prototypeFile = prototypeFile; 47 realizable.prototypeFile = prototypeFile;
131 48
@@ -299,68 +216,14 @@ EntityManager::id_type RealizingSystem::initSingleton(
299 game_.getSystemManager().getSystem<PonderingSystem>(). 216 game_.getSystemManager().getSystem<PonderingSystem>().
300 initializeBody(mapObject, PonderableComponent::Type::vacuumed); 217 initializeBody(mapObject, PonderableComponent::Type::vacuumed);
301 218
302 // Look for any object configuration. 219 if (prototypeId == "movplat")
303 std::map<std::string, int> items;
304
305 for (xmlNodePtr objectNode = mapNode->xmlChildrenNode;
306 objectNode != nullptr;
307 objectNode = objectNode->next)
308 { 220 {
309 if (!xmlStrcmp( 221 auto& automatable = game_.getEntityManager().
310 objectNode->name, 222 emplaceComponent<AutomatableComponent>(mapObject);
311 reinterpret_cast<const xmlChar*>("item")))
312 {
313 key = getProp(objectNode, "id");
314 std::string itemName = reinterpret_cast<char*>(key);
315 xmlFree(key);
316
317 key = xmlNodeGetContent(objectNode);
318 int itemVal = atoi(reinterpret_cast<char*>(key));
319 xmlFree(key);
320
321 items[itemName] = itemVal;
322 }
323 }
324 223
325 // Add any AI behaviors.
326 std::vector<double> behaviorWeights;
327 224
328 for (xmlNodePtr protoSubNode = prototypeNode->xmlChildrenNode; 225 realizable.scriptEngine.script_file(
329 protoSubNode != nullptr; 226 "res/platform.lua");//,
330 protoSubNode = protoSubNode->next)
331 {
332 if (!xmlStrcmp(
333 protoSubNode->name,
334 reinterpret_cast<const xmlChar*>("ai")))
335 {
336 if (!game_.getEntityManager().
337 hasComponent<AutomatableComponent>(mapObject))
338 {
339 game_.getEntityManager().
340 emplaceComponent<AutomatableComponent>(mapObject);
341 }
342
343 auto& automatable = game_.getEntityManager().
344 getComponent<AutomatableComponent>(mapObject);
345
346 key = getProp(protoSubNode, "chance");
347 behaviorWeights.push_back(atof(reinterpret_cast<char*>(key)));
348 xmlFree(key);
349
350 std::vector<AutomatableComponent::Action> behavior;
351
352 for (xmlNodePtr aiNode = protoSubNode->xmlChildrenNode;
353 aiNode != nullptr;
354 aiNode = aiNode->next)
355 {
356 parseAI(
357 aiNode,
358 behavior,
359 items);
360 }
361
362 automatable.behaviors.push_back(std::move(behavior));
363 }
364 } 227 }
365 228
366 mappable.objects.push_back(mapObject); 229 mappable.objects.push_back(mapObject);
diff --git a/src/vector.h b/src/vector.h index 3abd98a..9355dd5 100644 --- a/src/vector.h +++ b/src/vector.h
@@ -7,9 +7,11 @@ public:
7 7
8 T coords[2]; 8 T coords[2];
9 9
10 vec2() = default; 10 vec2() : coords{0, 0}
11 {
12 }
11 13
12 vec2(double x, double y) : coords{x, y} 14 vec2(T x, T y) : coords{x, y}
13 { 15 {
14 } 16 }
15 17
@@ -90,12 +92,12 @@ public:
90 return vec2(-x(), -y()); 92 return vec2(-x(), -y());
91 } 93 }
92 94
93 vec2 operator*(double s) const 95 vec2 operator*(T s) const
94 { 96 {
95 return vec2(x() * s, y() * s); 97 return vec2(x() * s, y() * s);
96 } 98 }
97 99
98 vec2& operator*=(double s) 100 vec2& operator*=(T s)
99 { 101 {
100 x() *= s; 102 x() *= s;
101 y() *= s; 103 y() *= s;
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
259namespace 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
399namespace 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
451namespace 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
518namespace sol {
519namespace 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
1045namespace 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
1171namespace 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
1176namespace 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
1193namespace 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)
1926extern "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
2014typedef size_t lua_Unsigned;
2015
2016typedef 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*/
2029typedef struct luaL_Stream {
2030 FILE *f;
2031} luaL_Stream;
2032
2033#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
2034COMPAT53_API int lua_absindex(lua_State *L, int i);
2035
2036#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith)
2037COMPAT53_API void lua_arith(lua_State *L, int op);
2038
2039#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare)
2040COMPAT53_API int lua_compare(lua_State *L, int idx1, int idx2, int op);
2041
2042#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy)
2043COMPAT53_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)
2051COMPAT53_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)
2072COMPAT53_API int lua_rawgetp(lua_State *L, int i, const void *p);
2073
2074#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp)
2075COMPAT53_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)
2082COMPAT53_API lua_Number lua_tonumberx(lua_State *L, int i, int *isnum);
2083
2084#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
2085COMPAT53_API void luaL_checkversion(lua_State *L);
2086
2087#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
2088COMPAT53_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)
2091COMPAT53_API int luaL_loadfilex(lua_State *L, const char *filename, const char *mode);
2092
2093#define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx)
2094COMPAT53_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)
2097COMPAT53_API void luaL_checkstack(lua_State *L, int sp, const char *msg);
2098
2099#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable)
2100COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char *name);
2101
2102#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len)
2103COMPAT53_API lua_Integer luaL_len(lua_State *L, int i);
2104
2105#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs)
2106COMPAT53_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup);
2107
2108#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable)
2109COMPAT53_API void luaL_setmetatable(lua_State *L, const char *tname);
2110
2111#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata)
2112COMPAT53_API void *luaL_testudata(lua_State *L, int i, const char *tname);
2113
2114#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback)
2115COMPAT53_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)
2118COMPAT53_API int luaL_fileresult(lua_State *L, int stat, const char *fname);
2119
2120#define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult)
2121COMPAT53_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)
2132COMPAT53_API void luaL_buffinit(lua_State *L, luaL_Buffer_53 *B);
2133
2134#define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53)
2135COMPAT53_API char *luaL_prepbuffsize(luaL_Buffer_53 *B, size_t s);
2136
2137#define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53)
2138COMPAT53_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)
2141COMPAT53_API void luaL_addvalue(luaL_Buffer_53 *B);
2142
2143#define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53)
2144COMPAT53_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
2189typedef int lua_KContext;
2190
2191typedef 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)
2203COMPAT53_API int lua_geti(lua_State *L, int index, lua_Integer i);
2204
2205#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger)
2206COMPAT53_API int lua_isinteger(lua_State *L, int index);
2207
2208#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53)
2209COMPAT53_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)
2221COMPAT53_API void lua_rotate(lua_State *L, int idx, int n);
2222
2223#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti)
2224COMPAT53_API void lua_seti(lua_State *L, int index, lua_Integer i);
2225
2226#define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber)
2227COMPAT53_API size_t lua_stringtonumber(lua_State *L, const char *s);
2228
2229#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring)
2230COMPAT53_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)
2239COMPAT53_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
2367static 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
2401COMPAT53_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
2407static 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
2421static 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
2432COMPAT53_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
2444static const char compat53_compare_code[] =
2445"local a,b=...\n"
2446"return a<=b\n";
2447
2448COMPAT53_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
2472COMPAT53_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
2479COMPAT53_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
2498COMPAT53_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
2505COMPAT53_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
2513COMPAT53_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
2521COMPAT53_API void luaL_checkversion(lua_State *L) {
2522 (void)L;
2523}
2524
2525COMPAT53_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
2536COMPAT53_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
2551COMPAT53_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
2563COMPAT53_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
2576COMPAT53_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
2582COMPAT53_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
2598static 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
2612static 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
2635static 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
2650static 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
2670COMPAT53_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
2696COMPAT53_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
2716static 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
2724typedef 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
2732static 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
2743COMPAT53_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
2760typedef 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
2766static 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
2783static 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
2792static 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*/
2812static 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
2824COMPAT53_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
2884COMPAT53_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
2918COMPAT53_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
2934COMPAT53_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
2946COMPAT53_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
2964COMPAT53_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
2969COMPAT53_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
2980void 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
2991COMPAT53_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
2998COMPAT53_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
3008COMPAT53_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
3023static 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
3032COMPAT53_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
3047COMPAT53_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
3059COMPAT53_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
3073COMPAT53_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
3107COMPAT53_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
3172namespace 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
3333namespace 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
4321namespace 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
4354namespace 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
4375namespace 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
4412namespace 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
4537namespace 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
4611namespace 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
5785namespace 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)
5975extern "C" {
5976}
5977#endif // MinGW is on some stuff
5978#include <locale>
5979
5980namespace sol {
5981namespace 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
6117namespace 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
6241namespace 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
6370namespace 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
6824namespace 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
6899namespace 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
6943namespace 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
7800namespace 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
7836namespace 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
7920namespace sol {
7921namespace 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
8514namespace 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
8538namespace 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
8845namespace sol {
8846namespace 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
9690namespace sol {
9691namespace 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
9859namespace sol {
9860namespace 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
10843namespace sol {
10844namespace 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
10870namespace sol {
10871namespace 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
11118namespace sol {
11119namespace 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
11178namespace 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
11412namespace 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
11445namespace 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
11575namespace 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
11645namespace 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
11683namespace 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
11877namespace 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
12019namespace 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
12073namespace 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
12341namespace sol {
12342namespace 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
12365namespace 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
12393namespace 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
12507namespace 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
13238namespace 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
13364namespace sol {
13365namespace 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
13604namespace sol {
13605namespace 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
13711namespace sol {
13712namespace 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
13745namespace 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
13892namespace 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
14400namespace 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
14514namespace 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
14591namespace 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
14869namespace 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
14961namespace 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
15191namespace sol {
15192namespace 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
15206namespace 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
15265namespace 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
15380namespace 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
15409namespace 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
15562namespace 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
15688namespace 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
17125namespace 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
17546namespace 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
17798namespace 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
18579namespace 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
19205namespace 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
19293namespace 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
19385namespace 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
19958namespace 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
19978namespace 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
20181namespace 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
20307namespace 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
20453namespace 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
21091namespace 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
21256namespace 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
21293namespace 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
21505namespace 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
21533namespace 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