From 4bbfeae42a1245b1b84e8847787d7643e6a6f2cf Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 10 May 2018 19:27:59 -0400 Subject: 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. --- CMakeLists.txt | 5 +- res/platform.lua | 27 + src/components/automatable.h | 81 +- src/components/realizable.h | 3 + src/systems/automating.cpp | 99 +- src/systems/automating.h | 3 + src/systems/realizing.cpp | 153 +- src/vector.h | 10 +- vendor/sol.hpp | 21575 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 21688 insertions(+), 268 deletions(-) create mode 100644 res/platform.lua create mode 100644 vendor/sol.hpp 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) find_package(portaudio REQUIRED) find_package(libsndfile REQUIRED) find_package(libxml2 REQUIRED) +find_package(lua REQUIRED) IF(APPLE) FIND_LIBRARY(COCOA_LIBRARY Cocoa) @@ -32,6 +33,7 @@ set(ALL_LIBS ${PORTAUDIO_LIBRARIES} ${LIBSNDFILE_LIBRARY} ${LIBXML2_LIBRARIES} + ${LUA_LIBRARIES} ${EXTRA_LIBS} ) @@ -40,6 +42,7 @@ include_directories( ${GLFW_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} + ${LUA_INCLUDE_DIRS} src vendor ) @@ -71,6 +74,6 @@ add_executable(Aromatherapy vendor/stb_image.cpp ) -set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 11) +set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 17) set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD_REQUIRED ON) target_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 @@ +function moveLeft(entity, len, speed) + local remaining = len / speed + + while (remaining > 0) do + print("no") + --entity:ponderable().vel:x(-speed) + remaining = remaining - coroutine.yield() + end +end + +function moveRight(entity, len, speed) + local remaining = len / speed + + while (remaining > 0) do + print("no2") + --entity:ponderable().vel:x(speed) + remaining = remaining - coroutine.yield() + end +end + +function run(entity) + print("yes") + while true do + moveRight(entity, 90, 30) + moveLeft(entity, 90, 30) + end +end \ 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 @@ #define AUTOMATABLE_H_3D519131 #include "component.h" -#include -#include -#include "vector.h" +#include +#include class AutomatableComponent : public Component { public: - /** - * Helper class that defines an automatable action. - */ - class Action { - public: - - /** - * The horizontal and vertical speed, in pixels/sec, that the entity should - * move at. - */ - vec2d speed; - - /** - * The duration of the action in seconds. - */ - double dur; - }; - - /** - * Helper type that defines a behavior that an entity can exhibit, which is a - * list of actions that are stepped through in sequence. - */ - using Behavior = std::vector; - - /** - * A group of behaviors that the entity can exhibit, which are picked at - * random at the start of automation and whenever a behavior completes. - * - * @managed_by RealizingSystem - */ - std::vector behaviors; - - /** - * A random distribution over the above behaviors. - * - * @managed_by RealizingSystem - */ - std::discrete_distribution behaviorDist; - - /** - * A flag indicating whether a behavior is currently executing. - * - * @managed_by AutomatingSystem - */ - bool behaviorRunning = false; - - /** - * A flag indicating whether an action is currently executing. - * - * @managed_by AutomatingSystem - */ - bool actionRunning = false; - - /** - * The index of the currently executing behavior, if there is one. - * - * @managed_by AutomatingSystem - */ - size_t currentBehavior; + std::unique_ptr runner; + std::unique_ptr behavior; - /** - * The index of the currently executing action, if there is one. - * - * @managed_by AutomatingSystem - */ - size_t currentAction; - - /** - * The amount of time remaining, in seconds, of the currently executing - * action. - * - * @managed_by AutomatingSystem - */ - double remaining; + sol::environment origBehavior; /** * 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 @@ #include "component.h" #include #include +#include #include "entity_manager.h" #include "vector.h" @@ -69,6 +70,8 @@ public: * The entity ID of the currently active player. */ id_type activePlayer; + + sol::state scriptEngine; }; #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 @@ #include "game.h" #include "components/automatable.h" #include "components/ponderable.h" -#include "systems/pondering.h" +#include "components/realizable.h" +#include "systems/realizing.h" +#include "vector.h" + +struct script_entity { + using id_type = EntityManager::id_type; + + id_type id; + + script_entity(id_type id) : id(id) + { + } +}; void AutomatingSystem::tick(double dt) { auto entities = game_.getEntityManager().getEntitiesWithComponents< - AutomatableComponent, - PonderableComponent>(); + AutomatableComponent>(); for (id_type entity : entities) { @@ -20,43 +31,7 @@ void AutomatingSystem::tick(double dt) continue; } - if (automatable.behaviorRunning && - (automatable.remaining <= 0.0)) - { - automatable.currentAction++; - automatable.actionRunning = false; - - if (automatable.currentAction == - automatable.behaviors[automatable.currentBehavior].size()) - { - automatable.behaviorRunning = false; - } - } - - if (!automatable.behaviorRunning) - { - automatable.currentBehavior = automatable.behaviorDist(game_.getRng()); - automatable.currentAction = 0; - automatable.behaviorRunning = true; - } - - AutomatableComponent::Action& curAction = - automatable.behaviors - [automatable.currentBehavior] - [automatable.currentAction]; - - if (!automatable.actionRunning) - { - automatable.remaining = curAction.dur; - automatable.actionRunning = true; - } - - auto& ponderable = game_.getEntityManager(). - getComponent(entity); - - ponderable.vel = curAction.speed; - - automatable.remaining -= dt; + (*automatable.behavior)(dt); } } @@ -65,6 +40,46 @@ void AutomatingSystem::initPrototype(id_type prototype) auto& automatable = game_.getEntityManager(). getComponent(prototype); - automatable.behaviorRunning = false; - automatable.actionRunning = false; + auto& realizable = game_.getEntityManager(). + getComponent( + game_.getSystemManager().getSystem().getSingleton()); + automatable.behavior.reset(); + automatable.runner = std::unique_ptr(new sol::thread(sol::thread::create(realizable.scriptEngine.lua_state()))); + automatable.behavior = std::unique_ptr(new sol::coroutine(automatable.runner->state()["run"])); + (*automatable.behavior)(script_entity(prototype)); +} + +void AutomatingSystem::initScriptEngine(sol::state& scriptEngine) +{ + scriptEngine.open_libraries(sol::lib::base, sol::lib::coroutine); + scriptEngine.new_usertype( + "vec2d", + sol::constructors(), + "x", sol::property( + [] (vec2d& v) -> double { return v.x(); }, + [] (vec2d& v, double x) { v.x() = x; }), + "y", sol::property( + [] (vec2d& v) -> double { return v.y(); }, + [] (vec2d& v, double y) { v.y() = y; })); + + scriptEngine.new_usertype( + "vec2i", + sol::constructors(), + "x", [] (vec2i& v) -> int& { return v.x(); }, + "y", [] (vec2i& v) -> int& { return v.y(); }); + + scriptEngine.new_usertype( + "entity", + sol::constructors(), + "id", &script_entity::id, + "ponderable", + [&] (script_entity& entity) -> PonderableComponent& { + return game_.getEntityManager(). + getComponent(entity.id); + }); + + scriptEngine.new_usertype( + "ponderable", + "vel", &PonderableComponent::vel, + "accel", &PonderableComponent::accel); } 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 @@ #define AUTOMATING_H_E6E5D76E #include "system.h" +#include class AutomatingSystem : public System { public: @@ -14,6 +15,8 @@ public: void initPrototype(id_type prototype); + void initScriptEngine(sol::state& scriptEngine); + }; #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) return key; } -void parseAI( - xmlNodePtr node, - std::vector& behavior, - const std::map& items) -{ - xmlChar* key = nullptr; - - if (!xmlStrcmp( - node->name, - reinterpret_cast("switch"))) - { - key = getProp(node, "item"); - std::string switchItem = reinterpret_cast(key); - xmlFree(key); - - for (xmlNodePtr switchNode = node->xmlChildrenNode; - switchNode != nullptr; - switchNode = switchNode->next) - { - if (!xmlStrcmp( - switchNode->name, - reinterpret_cast("case"))) - { - key = getProp(switchNode, "value"); - int caseValue = atoi(reinterpret_cast(key)); - xmlFree(key); - - if (items.at(switchItem) == caseValue) - { - for (xmlNodePtr caseNode = switchNode->xmlChildrenNode; - caseNode != nullptr; - caseNode = caseNode->next) - { - parseAI( - caseNode, - behavior, - items); - } - } - } - } - } else if (!xmlStrcmp( - node->name, - reinterpret_cast("move"))) - { - key = getProp(node, "direction"); - std::string direction = reinterpret_cast(key); - xmlFree(key); - - key = getProp(node, "length-var"); - std::string lengthVar = reinterpret_cast(key); - xmlFree(key); - - key = getProp(node, "speed-var"); - std::string speedVar = reinterpret_cast(key); - xmlFree(key); - - double length = items.at(lengthVar); - double speed = items.at(speedVar); - - AutomatableComponent::Action action; - - if (direction == "left") - { - action.speed.x() = -speed; - action.speed.y() = 0; - } else if (direction == "right") - { - action.speed.x() = speed; - action.speed.y() = 0; - } else if (direction == "up") - { - action.speed.x() = 0; - action.speed.y() = -speed; - } else if (direction == "down") - { - action.speed.x() = 0; - action.speed.y() = speed; - } - - action.dur = length / speed; - - behavior.push_back(std::move(action)); - } -} - // TODO: neither the XML doc nor any of the emplaced entities are properly // destroyed if this method throws an exception. EntityManager::id_type RealizingSystem::initSingleton( @@ -126,6 +40,9 @@ EntityManager::id_type RealizingSystem::initSingleton( auto& realizable = game_.getEntityManager(). emplaceComponent(world); + game_.getSystemManager().getSystem(). + initScriptEngine(realizable.scriptEngine); + realizable.worldFile = worldFile; realizable.prototypeFile = prototypeFile; @@ -299,68 +216,14 @@ EntityManager::id_type RealizingSystem::initSingleton( game_.getSystemManager().getSystem(). initializeBody(mapObject, PonderableComponent::Type::vacuumed); - // Look for any object configuration. - std::map items; - - for (xmlNodePtr objectNode = mapNode->xmlChildrenNode; - objectNode != nullptr; - objectNode = objectNode->next) + if (prototypeId == "movplat") { - if (!xmlStrcmp( - objectNode->name, - reinterpret_cast("item"))) - { - key = getProp(objectNode, "id"); - std::string itemName = reinterpret_cast(key); - xmlFree(key); - - key = xmlNodeGetContent(objectNode); - int itemVal = atoi(reinterpret_cast(key)); - xmlFree(key); - - items[itemName] = itemVal; - } - } + auto& automatable = game_.getEntityManager(). + emplaceComponent(mapObject); - // Add any AI behaviors. - std::vector behaviorWeights; - for (xmlNodePtr protoSubNode = prototypeNode->xmlChildrenNode; - protoSubNode != nullptr; - protoSubNode = protoSubNode->next) - { - if (!xmlStrcmp( - protoSubNode->name, - reinterpret_cast("ai"))) - { - if (!game_.getEntityManager(). - hasComponent(mapObject)) - { - game_.getEntityManager(). - emplaceComponent(mapObject); - } - - auto& automatable = game_.getEntityManager(). - getComponent(mapObject); - - key = getProp(protoSubNode, "chance"); - behaviorWeights.push_back(atof(reinterpret_cast(key))); - xmlFree(key); - - std::vector behavior; - - for (xmlNodePtr aiNode = protoSubNode->xmlChildrenNode; - aiNode != nullptr; - aiNode = aiNode->next) - { - parseAI( - aiNode, - behavior, - items); - } - - automatable.behaviors.push_back(std::move(behavior)); - } + realizable.scriptEngine.script_file( + "res/platform.lua");//, } 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: T coords[2]; - vec2() = default; + vec2() : coords{0, 0} + { + } - vec2(double x, double y) : coords{x, y} + vec2(T x, T y) : coords{x, y} { } @@ -90,12 +92,12 @@ public: return vec2(-x(), -y()); } - vec2 operator*(double s) const + vec2 operator*(T s) const { return vec2(x() * s, y() * s); } - vec2& operator*=(double s) + vec2& operator*=(T s) { x() *= s; 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 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2018-04-18 00:12:41.772355 UTC +// This header was generated with sol v2.20.0 (revision 8b77411) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_HPP +#define SOL_SINGLE_INCLUDE_HPP + +// beginning of sol.hpp + +#ifndef SOL_HPP +#define SOL_HPP + +#if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) +#define SOL_INSIDE_UNREAL 1 +#endif // Unreal Engine 4 bullshit + +#if defined(SOL_INSIDE_UNREAL) && SOL_INSIDE_UNREAL +#ifdef check +#define SOL_INSIDE_UNREAL_REMOVED_CHECK +#undef check +#endif +#endif // Unreal Engine 4 Bullshit + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wconversion" +#if __GNUC__ > 6 +#pragma GCC diagnostic ignored "-Wnoexcept-type" +#endif +#elif defined(__clang__) +#elif defined _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4324 ) // structure was padded due to alignment specifier +#pragma warning( disable : 4503 ) // decorated name horse shit +#pragma warning( disable : 4702 ) // unreachable code +#pragma warning( disable: 4127 ) // 'conditional expression is constant' yeah that's the point your old compilers don't have `if constexpr` you jerk +#pragma warning( disable: 4505 ) // some other nonsense warning +#endif // clang++ vs. g++ vs. VC++ + +// beginning of sol/forward.hpp + +// beginning of sol/feature_test.hpp + +#if (defined(__cplusplus) && __cplusplus == 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && ((defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201402L)))) +#ifndef SOL_CXX17_FEATURES +#define SOL_CXX17_FEATURES 1 +#endif // C++17 features macro +#endif // C++17 features check + +#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES +#if defined(__cpp_noexcept_function_type) || ((defined(_MSC_VER) && _MSC_VER > 1911) && (defined(_MSVC_LANG) && ((_MSVC_LANG >= 201403L)))) +#ifndef SOL_NOEXCEPT_FUNCTION_TYPE +#define SOL_NOEXCEPT_FUNCTION_TYPE 1 +#endif // noexcept is part of a function's type +#endif // compiler-specific checks +#if defined(__clang__) && defined(__APPLE__) +#if defined(__has_include) +#if __has_include() +#define SOL_STD_VARIANT 1 +#endif // has include nonsense +#endif // __has_include +#else +#define SOL_STD_VARIANT 1 +#endif // Clang screws up variant +#endif // C++17 only + +// beginning of sol/config.hpp + +#ifdef _MSC_VER + #if defined(_DEBUG) && !defined(NDEBUG) + + #ifndef SOL_IN_DEBUG_DETECTED + #define SOL_IN_DEBUG_DETECTED 1 + #endif + + #endif // VC++ Debug macros + + #ifndef _CPPUNWIND + #ifndef SOL_NO_EXCEPTIONS + #define SOL_NO_EXCEPTIONS 1 + #endif + #endif // Automatic Exceptions + + #ifndef _CPPRTTI + #ifndef SOL_NO_RTTI + #define SOL_NO_RTTI 1 + #endif + #endif // Automatic RTTI +#elif defined(__GNUC__) || defined(__clang__) + + #if !defined(NDEBUG) && !defined(__OPTIMIZE__) + + #ifndef SOL_IN_DEBUG_DETECTED + #define SOL_IN_DEBUG_DETECTED 1 + #endif + + #endif // Not Debug && g++ optimizer flag + + #ifndef __EXCEPTIONS + #ifndef SOL_NO_EXCEPTIONS + #define SOL_NO_EXCEPTIONS 1 + #endif + #endif // No Exceptions + + #ifndef __GXX_RTTI + #ifndef SOL_NO_RTII + #define SOL_NO_RTTI 1 + #endif + #endif // No RTTI + +#endif // vc++ || clang++/g++ + +#if defined(SOL_CHECK_ARGUMENTS) && SOL_CHECK_ARGUMENTS + + // Checks low-level getter function + // (and thusly, affects nearly entire framework) + #if !defined(SOL_SAFE_GETTER) + #define SOL_SAFE_GETTER 1 + #endif + + // Checks access on usertype functions + // local my_obj = my_type.new() + // my_obj.my_member_function() + // -- bad syntax and crash + #if !defined(SOL_SAFE_USERTYPE) + #define SOL_SAFE_USERTYPE 1 + #endif + + // Checks sol::reference derived boundaries + // sol::function ref(L, 1); + // sol::userdata sref(L, 2); + #if !defined(SOL_SAFE_REFERENCES) + #define SOL_SAFE_REFERENCES 1 + #endif + + // Changes all typedefs of sol::function to point to the + // protected_function version, instead of unsafe_function + #if !defined(SOL_SAFE_FUNCTION) + #define SOL_SAFE_FUNCTION 1 + #endif + + // Checks function parameters and + // returns upon call into/from Lua + // local a = 1 + // local b = "woof" + // my_c_function(a, b) + #if !defined(SOL_SAFE_FUNCTION_CALLS) + #define SOL_SAFE_FUNCTION_CALLS 1 + #endif + + // Checks conversions + // int v = lua["bark"]; + // int v2 = my_sol_function(); + #if !defined(SOL_SAFE_PROXIES) + #define SOL_SAFE_PROXIES 1 + #endif + + // Check overflowing number conversions + // for things like 64 bit integers that don't fit in a typical lua_Number + // for Lua 5.1 and 5.2 + #if !defined(SOL_SAFE_NUMERICS) + #define SOL_SAFE_NUMERICS 1 + #endif + + // Turn off Number Precision Checks + // if this is defined, we do not do range + // checks on integers / unsigned integers that might + // be bigger than what Lua can represent + #if !defined(SOL_NO_CHECK_NUMBER_PRECISION) + // off by default + #define SOL_NO_CHECK_NUMBER_PRECISION 0 + #endif + +#endif // Turn on Safety for all if top-level macro is defined + +#if defined(SOL_IN_DEBUG_DETECTED) && SOL_IN_DEBUG_DETECTED + + #if !defined(SOL_SAFE_REFERENCES) + // Ensure that references are forcefully type-checked upon construction + #define SOL_SAFE_REFERENCES 1 + #endif + + // Safe usertypes checks for errors such as + // obj = my_type.new() + // obj.f() -- note the '.' instead of ':' + // usertypes should be safe no matter what + #if !defined(SOL_SAFE_USERTYPE) + #define SOL_SAFE_USERTYPE 1 + #endif + + #if !defined(SOL_SAFE_FUNCTION_CALLS) + // Function calls from Lua should be automatically safe in debug mode + #define SOL_SAFE_FUNCTION_CALLS 1 + #endif + + // Print any exceptions / errors that occur + // in debug mode to the default error stream / console + #if !defined(SOL_PRINT_ERRORS) + #define SOL_PRINT_ERRORS 1 + #endif + +#endif // DEBUG: Turn on all debug safety features for VC++ / g++ / clang++ and similar + +#if !defined(SOL_PRINT_ERRORS) +#define SOL_PRINT_ERRORS 0 +#endif + +#if !defined(SOL_DEFAULT_PASS_ON_ERROR) +#define SOL_DEFAULT_PASS_ON_ERROR 0 +#endif + +#if !defined(SOL_ENABLE_INTEROP) +#define SOL_ENABLE_INTEROP 0 +#endif + +#if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) +#if !defined(SOL_NO_NIL) +#define SOL_NO_NIL 1 +#endif +#endif // avoiding nil defines / keywords + +#if defined(SOL_USE_BOOST) && SOL_USE_BOOST +#ifndef SOL_UNORDERED_MAP_COMPATIBLE_HASH +#define SOL_UNORDERED_MAP_COMPATIBLE_HASH 1 +#endif // SOL_UNORDERED_MAP_COMPATIBLE_HASH +#endif + +#ifndef SOL_STACK_STRING_OPTIMIZATION_SIZE +#define SOL_STACK_STRING_OPTIMIZATION_SIZE 1024 +#endif // Optimized conversion routines using a KB or so off the stack + +// end of sol/config.hpp + +// end of sol/feature_test.hpp + +namespace sol { + + template + class basic_reference; + using reference = basic_reference; + using main_reference = basic_reference; + class stack_reference; + + struct proxy_base_tag; + template + struct proxy_base; + template + struct proxy; + + template + class usertype; + template + class simple_usertype; + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using main_table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + template + using basic_table = basic_table_core; + typedef table_core table; + typedef table_core global_table; + typedef main_table_core main_table; + typedef main_table_core main_global_table; + typedef stack_table_core stack_table; + typedef stack_table_core stack_global_table; + template + struct basic_environment; + using environment = basic_environment; + using main_environment = basic_environment; + using stack_environment = basic_environment; + template + class basic_function; + template + class basic_protected_function; + using unsafe_function = basic_function; + using safe_function = basic_protected_function; + using main_unsafe_function = basic_function; + using main_safe_function = basic_protected_function; + using stack_unsafe_function = basic_function; + using stack_safe_function = basic_protected_function; + using stack_aligned_unsafe_function = basic_function; + using stack_aligned_safe_function = basic_protected_function; + using protected_function = safe_function; + using main_protected_function = main_safe_function; + using stack_protected_function = stack_safe_function; + using stack_aligned_protected_function = stack_aligned_safe_function; +#if defined(SOL_SAFE_FUNCTION) && SOL_SAFE_FUNCTION + using function = protected_function; + using main_function = main_protected_function; + using stack_function = stack_protected_function; +#else + using function = unsafe_function; + using main_function = main_unsafe_function; + using stack_function = stack_unsafe_function; +#endif + using stack_aligned_function = stack_aligned_unsafe_function; + using stack_aligned_stack_handler_function = basic_protected_function; + + struct unsafe_function_result; + struct protected_function_result; + using safe_function_result = protected_function_result; +#if defined(SOL_SAFE_FUNCTION) && SOL_SAFE_FUNCTION + using function_result = safe_function_result; +#else + using function_result = unsafe_function_result; +#endif + + template + class basic_object; + template + class basic_userdata; + template + class basic_lightuserdata; + template + class basic_coroutine; + template + class basic_thread; + + using object = basic_object; + using userdata = basic_userdata; + using lightuserdata = basic_lightuserdata; + using thread = basic_thread; + using coroutine = basic_coroutine; + using main_object = basic_object; + using main_userdata = basic_userdata; + using main_lightuserdata = basic_lightuserdata; + using main_coroutine = basic_coroutine; + using stack_object = basic_object; + using stack_userdata = basic_userdata; + using stack_lightuserdata = basic_lightuserdata; + using stack_thread = basic_thread; + using stack_coroutine = basic_coroutine; + + struct stack_proxy_base; + struct stack_proxy; + struct variadic_args; + struct variadic_results; + struct stack_count; + struct this_state; + struct this_main_state; + struct this_environment; + + template + struct as_table_t; + template + struct as_container_t; + template + struct nested; + template + struct light; + template + struct user; + template + struct as_args_t; + template + struct protect_t; + template + struct filter_wrapper; +} // namespace sol + +// end of sol/forward.hpp + +// beginning of sol/state.hpp + +// beginning of sol/state_view.hpp + +// beginning of sol/error.hpp + +#include +#include + +namespace sol { + namespace detail { + struct direct_error_tag {}; + const auto direct_error = direct_error_tag{}; + } // namespace detail + + class error : public std::runtime_error { + private: + // Because VC++ is upsetting, most of the time! + std::string w; + + public: + error(const std::string& str) + : error(detail::direct_error, "lua: error: " + str) { + } + error(std::string&& str) + : error(detail::direct_error, "lua: error: " + std::move(str)) { + } + error(detail::direct_error_tag, const std::string& str) + : std::runtime_error(""), w(str) { + } + error(detail::direct_error_tag, std::string&& str) + : std::runtime_error(""), w(std::move(str)) { + } + + error(const error& e) = default; + error(error&& e) = default; + error& operator=(const error& e) = default; + error& operator=(error&& e) = default; + + virtual const char* what() const noexcept override { + return w.c_str(); + } + }; + +} // namespace sol + +// end of sol/error.hpp + +// beginning of sol/table.hpp + +// beginning of sol/table_core.hpp + +// beginning of sol/proxy.hpp + +// beginning of sol/traits.hpp + +// beginning of sol/tuple.hpp + +#include +#include + +namespace sol { + namespace detail { + using swallow = std::initializer_list; + } // namespace detail + + template + struct types { + typedef std::make_index_sequence indices; + static constexpr std::size_t size() { + return sizeof...(Args); + } + }; + namespace meta { + namespace detail { + template + struct tuple_types_ { typedef types type; }; + + template + struct tuple_types_> { typedef types type; }; + } // namespace detail + + template + using unqualified = std::remove_cv>; + + template + using unqualified_t = typename unqualified::type; + + template + using tuple_types = typename detail::tuple_types_::type; + + template + struct pop_front_type; + + template + using pop_front_type_t = typename pop_front_type::type; + + template + struct pop_front_type> { + typedef void front_type; + typedef types type; + }; + + template + struct pop_front_type> { + typedef Arg front_type; + typedef types type; + }; + + template + using tuple_element = std::tuple_element>; + + template + using tuple_element_t = std::tuple_element_t>; + + template + using unqualified_tuple_element = unqualified>; + + template + using unqualified_tuple_element_t = unqualified_t>; + + } // namespace meta +} // namespace sol + +// end of sol/tuple.hpp + +// beginning of sol/bind_traits.hpp + +namespace sol { +namespace meta { + namespace meta_detail { + + template + struct check_deducible_signature { + struct nat {}; + template + static auto test(int) -> decltype(&G::operator(), void()); + template + static auto test(...) -> nat; + + using type = std::is_void(0))>; + }; + } // namespace meta_detail + + template + struct has_deducible_signature : meta_detail::check_deducible_signature::type {}; + + namespace meta_detail { + + template + struct void_tuple_element : meta::tuple_element {}; + + template + struct void_tuple_element> { typedef void type; }; + + template + using void_tuple_element_t = typename void_tuple_element::type; + + template + struct basic_traits { + private: + typedef std::conditional_t::value, int, T>& first_type; + + public: + static const bool is_noexcept = it_is_noexcept; + static const bool is_member_function = std::is_void::value; + static const bool has_c_var_arg = has_c_variadic; + static const std::size_t arity = sizeof...(Args); + static const std::size_t free_arity = sizeof...(Args) + static_cast(!std::is_void::value); + typedef types args_list; + typedef std::tuple args_tuple; + typedef T object_type; + typedef R return_type; + typedef tuple_types returns_list; + typedef R(function_type)(Args...); + typedef std::conditional_t::value, args_list, types> free_args_list; + typedef std::conditional_t::value, R(Args...), R(first_type, Args...)> free_function_type; + typedef std::conditional_t::value, R (*)(Args...), R (*)(first_type, Args...)> free_function_pointer_type; + typedef std::remove_pointer_t signature_type; + template + using arg_at = void_tuple_element_t; + }; + + template ::value> + struct fx_traits : basic_traits {}; + + // Free Functions + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args..., ...); + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args..., ...); + }; + + // Member Functions + /* C-Style Variadics */ + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...); + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile; + }; + + /* Member Function Qualifiers */ + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) &&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) &&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const&&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const&&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile&&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile&&; + }; + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args..., ...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args..., ...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) noexcept; + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) && noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) && noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const&& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const&& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile&& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; + }; + +#endif // noexcept is part of a function's type + +#if defined(_MSC_VER) && defined(_M_IX86) + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...); + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile; + }; + + /* Member Function Qualifiers */ + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const&; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) &&; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const&&; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&&; + }; + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE + + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args...) noexcept; + }; + + /* __stdcall cannot be applied to functions with varargs*/ + /*template + struct fx_traits<__stdcall R(Args..., ...) noexcept, false> : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) noexcept; + };*/ + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) & noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) & noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const& noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile& noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) && noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) && noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const&& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const&& noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; + };*/ +#endif // noexcept is part of a function's type +#endif // __stdcall x86 VC++ bug + + template + struct fx_traits : fx_traits::function_type, false> {}; + + template ::value> + struct callable_traits : fx_traits> { + }; + + template + struct callable_traits { + typedef std::conditional_t::value, std::add_lvalue_reference_t, R> return_type; + typedef return_type Arg; + typedef T object_type; + using signature_type = R(T::*); + static const bool is_noexcept = false; + static const bool is_member_function = false; + static const std::size_t arity = 1; + static const std::size_t free_arity = 2; + typedef std::tuple args_tuple; + typedef types args_list; + typedef types free_args_list; + typedef meta::tuple_types returns_list; + typedef return_type(function_type)(T&, return_type); + typedef return_type(*function_pointer_type)(T&, Arg); + typedef return_type(*free_function_pointer_type)(T&, Arg); + template + using arg_at = void_tuple_element_t; + }; + + } // namespace meta_detail + + template + struct bind_traits : meta_detail::callable_traits {}; + + template + using function_args_t = typename bind_traits::args_list; + + template + using function_signature_t = typename bind_traits::signature_type; + + template + using function_return_t = typename bind_traits::return_type; +} +} // namespace sol::meta + +// end of sol/bind_traits.hpp + +// beginning of sol/string_view.hpp + +#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES +#include +#endif // C++17 features +#include +#if defined(SOL_USE_BOOST) && SOL_USE_BOOST +#include +#endif + +namespace sol { +#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES + template > + using basic_string_view = std::basic_string_view; + typedef std::string_view string_view; + typedef std::wstring_view wstring_view; + typedef std::u16string_view u16string_view; + typedef std::u32string_view u32string_view; + typedef std::hash string_view_hash; +#else + template > + struct basic_string_view { + std::size_t s; + const Char* p; + + basic_string_view(const std::string& r) + : basic_string_view(r.data(), r.size()) { + } + basic_string_view(const Char* ptr) + : basic_string_view(ptr, Traits::length(ptr)) { + } + basic_string_view(const Char* ptr, std::size_t sz) + : s(sz), p(ptr) { + } + + static int compare(const Char* lhs_p, std::size_t lhs_sz, const Char* rhs_p, std::size_t rhs_sz) { + int result = Traits::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); + if (result != 0) + return result; + if (lhs_sz < rhs_sz) + return -1; + if (lhs_sz > rhs_sz) + return 1; + return 0; + } + + const Char* begin() const { + return p; + } + + const Char* end() const { + return p + s; + } + + const Char* cbegin() const { + return p; + } + + const Char* cend() const { + return p + s; + } + + const Char* data() const { + return p; + } + + std::size_t size() const { + return s; + } + + std::size_t length() const { + return size(); + } + + operator std::basic_string() const { + return std::basic_string(data(), size()); + } + + bool operator==(const basic_string_view& r) const { + return compare(p, s, r.data(), r.size()) == 0; + } + + bool operator==(const Char* r) const { + return compare(r, Traits::length(r), p, s) == 0; + } + + bool operator==(const std::basic_string& r) const { + return compare(r.data(), r.size(), p, s) == 0; + } + + bool operator!=(const basic_string_view& r) const { + return !(*this == r); + } + + bool operator!=(const char* r) const { + return !(*this == r); + } + + bool operator!=(const std::basic_string& r) const { + return !(*this == r); + } + }; + + template > + struct basic_string_view_hash { + typedef basic_string_view argument_type; + typedef std::size_t result_type; + + template + result_type operator()(const std::basic_string& r) const { + return (*this)(argument_type(r.c_str(), r.size())); + } + + result_type operator()(const argument_type& r) const { +#if defined(SOL_USE_BOOST) && SOL_USE_BOOST + return boost::hash_range(r.begin(), r.end()); +#else + // Modified, from libstdc++ + // An implementation attempt at Fowler No Voll, 1a. + // Supposedly, used in MSVC, + // GCC (libstdc++) uses MurmurHash of some sort for 64-bit though...? + // But, well. Can't win them all, right? + // This should normally only apply when NOT using boost, + // so this should almost never be tapped into... + std::size_t hash = 0; + const unsigned char* cptr = reinterpret_cast(r.data()); + for (std::size_t sz = r.size(); sz != 0; --sz) { + hash ^= static_cast(*cptr++); + hash *= static_cast(1099511628211ULL); + } + return hash; +#endif + } + }; +} // namespace sol + +namespace std { + template + struct hash< ::sol::basic_string_view > : ::sol::basic_string_view_hash {}; +} // namespace std + +namespace sol { + using string_view = basic_string_view; + using wstring_view = basic_string_view; + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + using string_view_hash = std::hash; +#endif // C++17 Support +} // namespace sol + +// end of sol/string_view.hpp + +#include +#include +#include +#include +#include + +namespace sol { + template + using index_value = std::integral_constant; + + namespace meta { + template + struct identity { typedef T type; }; + + template + using identity_t = typename identity::type; + + template + struct is_tuple : std::false_type {}; + + template + struct is_tuple> : std::true_type {}; + + template + struct is_builtin_type : std::integral_constant::value || std::is_pointer::value || std::is_array::value> {}; + + template + struct unwrapped { + typedef T type; + }; + + template + struct unwrapped> { + typedef T type; + }; + + template + using unwrapped_t = typename unwrapped::type; + + template + struct unwrap_unqualified : unwrapped> {}; + + template + using unwrap_unqualified_t = typename unwrap_unqualified::type; + + template + struct remove_member_pointer; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + using remove_member_pointer_t = remove_member_pointer; + + namespace meta_detail { + template class Templ> + struct is_specialization_of : std::false_type {}; + template class Templ> + struct is_specialization_of, Templ> : std::true_type {}; + } + + template class Templ> + using is_specialization_of = meta_detail::is_specialization_of, Templ>; + + template + struct all_same : std::true_type {}; + + template + struct all_same : std::integral_constant::value && all_same::value> {}; + + template + struct any_same : std::false_type {}; + + template + struct any_same : std::integral_constant::value || any_same::value> {}; + + template + using boolean = std::integral_constant; + + template + using invoke_t = typename T::type; + + template + using invoke_b = boolean; + + template + using neg = boolean; + + template + using condition = std::conditional_t; + + template + struct all : boolean {}; + + template + struct all : condition, boolean> {}; + + template + struct any : boolean {}; + + template + struct any : condition, any> {}; + + enum class enable_t { + _ + }; + + constexpr const auto enabler = enable_t::_; + + template + using disable_if_t = std::enable_if_t; + + template + using enable = std::enable_if_t::value, enable_t>; + + template + using disable = std::enable_if_t>::value, enable_t>; + + template + using enable_any = std::enable_if_t::value, enable_t>; + + template + using disable_any = std::enable_if_t>::value, enable_t>; + + template + struct find_in_pack_v : boolean {}; + + template + struct find_in_pack_v : any, find_in_pack_v> {}; + + namespace meta_detail { + template + struct index_in_pack : std::integral_constant {}; + + template + struct index_in_pack : std::conditional_t::value, std::integral_constant, index_in_pack> {}; + } // namespace meta_detail + + template + struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> {}; + + template + struct index_in : meta_detail::index_in_pack<0, T, List> {}; + + template + struct index_in> : meta_detail::index_in_pack<0, T, Args...> {}; + + template + struct at_in_pack {}; + + template + using at_in_pack_t = typename at_in_pack::type; + + template + struct at_in_pack : std::conditional> {}; + + template + struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; + + namespace meta_detail { + template class Pred, typename... Ts> + struct count_for_pack : std::integral_constant {}; + template class Pred, typename T, typename... Ts> + struct count_for_pack : std::conditional_t < sizeof...(Ts) + == 0 + || Limit<2, + std::integral_constant(Limit != 0 && Pred::value)>, + count_for_pack(Pred::value), Pred, Ts...>> {}; + template class Pred, typename... Ts> + struct count_2_for_pack : std::integral_constant {}; + template class Pred, typename T, typename U, typename... Ts> + struct count_2_for_pack : std::conditional_t(Pred::value)>, + count_2_for_pack(Pred::value), Pred, Ts...>> {}; + } // namespace meta_detail + + template