aboutsummaryrefslogtreecommitdiffstats
path: root/lib/LuaBridge/Source
diff options
context:
space:
mode:
Diffstat (limited to 'lib/LuaBridge/Source')
-rw-r--r--lib/LuaBridge/Source/CMakeLists.txt43
-rw-r--r--lib/LuaBridge/Source/LuaBridge/List.h50
-rw-r--r--lib/LuaBridge/Source/LuaBridge/LuaBridge.h59
-rw-r--r--lib/LuaBridge/Source/LuaBridge/Map.h50
-rw-r--r--lib/LuaBridge/Source/LuaBridge/RefCountedObject.h356
-rw-r--r--lib/LuaBridge/Source/LuaBridge/RefCountedPtr.h244
-rw-r--r--lib/LuaBridge/Source/LuaBridge/UnorderedMap.h50
-rw-r--r--lib/LuaBridge/Source/LuaBridge/Vector.h49
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/CFunctions.h495
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/ClassInfo.h169
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/Config.h10
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/Constructor.h205
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/FuncTraits.h942
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/Iterator.h154
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/LuaException.h122
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/LuaHelpers.h151
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/LuaRef.h1034
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/Namespace.h1224
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/Security.h72
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/Stack.h489
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/TypeList.h218
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/TypeTraits.h135
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/Userdata.h742
-rw-r--r--lib/LuaBridge/Source/LuaBridge/detail/dump.h143
24 files changed, 7206 insertions, 0 deletions
diff --git a/lib/LuaBridge/Source/CMakeLists.txt b/lib/LuaBridge/Source/CMakeLists.txt
new file mode 100644
index 0000000..e351990
--- /dev/null
+++ b/lib/LuaBridge/Source/CMakeLists.txt
@@ -0,0 +1,43 @@
+set (LUABRIDGE_HEADERS
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/List.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/LuaBridge.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/Map.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/RefCountedObject.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/RefCountedPtr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/UnorderedMap.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/Vector.h
+)
+source_group ("LuaBridge" FILES ${LUABRIDGE_HEADERS})
+
+set (LUABRIDGE_DETAIL_HEADERS
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/CFunctions.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/ClassInfo.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/Config.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/Constructor.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/dump.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/FuncTraits.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/Iterator.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/LuaException.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/LuaHelpers.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/LuaRef.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/Namespace.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/Stack.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/TypeList.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/TypeTraits.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaBridge/detail/Userdata.h
+)
+source_group ("LuaBridge\\detail" FILES ${LUABRIDGE_DETAIL_HEADERS})
+
+add_library (LuaBridge INTERFACE)
+target_sources (LuaBridge INTERFACE
+ ${LUABRIDGE_HEADERS}
+ ${LUABRIDGE_DETAIL_HEADERS}
+)
+target_include_directories (LuaBridge INTERFACE .)
+
+if (MSVC)
+ add_custom_target (LuaBridgeLibrary SOURCES
+ ${LUABRIDGE_HEADERS}
+ ${LUABRIDGE_DETAIL_HEADERS}
+ )
+endif ()
diff --git a/lib/LuaBridge/Source/LuaBridge/List.h b/lib/LuaBridge/Source/LuaBridge/List.h
new file mode 100644
index 0000000..3969f32
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/List.h
@@ -0,0 +1,50 @@
+// https://github.com/vinniefalco/LuaBridge
+//
+// Copyright 2018, Dmitry Tarakanov
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+#include <LuaBridge/detail/Stack.h>
+
+#include <list>
+
+namespace luabridge {
+
+template <class T>
+struct Stack <std::list <T> >
+{
+ static void push (lua_State* L, std::list <T> const& list)
+ {
+ lua_createtable (L, static_cast <int> (list.size ()), 0);
+ typename std::list <T>::const_iterator item = list.begin ();
+ for (std::size_t i = 1; i <= list.size (); ++i)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (i));
+ Stack <T>::push (L, *item);
+ lua_settable (L, -3);
+ ++item;
+ }
+ }
+
+ static std::list <T> get (lua_State* L, int index)
+ {
+ if (!lua_istable (L, index))
+ {
+ luaL_error (L, "#%d argments must be table", index);
+ }
+
+ std::list <T> list;
+
+ int const absindex = lua_absindex (L, index);
+ lua_pushnil (L);
+ while (lua_next (L, absindex) != 0)
+ {
+ list.push_back (Stack <T>::get (L, -1));
+ lua_pop (L, 1);
+ }
+ return list;
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/LuaBridge.h b/lib/LuaBridge/Source/LuaBridge/LuaBridge.h
new file mode 100644
index 0000000..866acc3
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/LuaBridge.h
@@ -0,0 +1,59 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2019, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+// All #include dependencies are listed here
+// instead of in the individual header files.
+//
+
+#define LUABRIDGE_MAJOR_VERSION 2
+#define LUABRIDGE_MINOR_VERSION 3
+#define LUABRIDGE_VERSION 203
+
+#ifndef LUA_VERSION_NUM
+#error "Lua headers must be included prior to LuaBridge ones"
+#endif
+
+
+#include <LuaBridge/detail/LuaHelpers.h>
+#include <LuaBridge/detail/TypeTraits.h>
+#include <LuaBridge/detail/TypeList.h>
+#include <LuaBridge/detail/FuncTraits.h>
+#include <LuaBridge/detail/Constructor.h>
+#include <LuaBridge/detail/ClassInfo.h>
+#include <LuaBridge/detail/LuaException.h>
+#include <LuaBridge/detail/LuaRef.h>
+#include <LuaBridge/detail/Iterator.h>
+#include <LuaBridge/detail/Userdata.h>
+#include <LuaBridge/detail/CFunctions.h>
+#include <LuaBridge/detail/Security.h>
+#include <LuaBridge/detail/Stack.h>
+#include <LuaBridge/detail/Namespace.h>
diff --git a/lib/LuaBridge/Source/LuaBridge/Map.h b/lib/LuaBridge/Source/LuaBridge/Map.h
new file mode 100644
index 0000000..890c87a
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/Map.h
@@ -0,0 +1,50 @@
+// https://github.com/vinniefalco/LuaBridge
+//
+// Copyright 2018, Dmitry Tarakanov
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+#include <LuaBridge/detail/Stack.h>
+
+#include <map>
+
+namespace luabridge {
+
+template <class K, class V>
+struct Stack <std::map <K, V> >
+{
+ typedef std::map <K, V> Map;
+
+ static void push (lua_State* L, const Map& map)
+ {
+ lua_createtable (L, 0, static_cast <int> (map.size ()));
+ typedef typename Map::const_iterator ConstIter;
+ for (ConstIter i = map.begin (); i != map.end (); ++i)
+ {
+ Stack <K>::push (L, i->first);
+ Stack <V>::push (L, i->second);
+ lua_settable (L, -3);
+ }
+ }
+
+ static Map get (lua_State* L, int index)
+ {
+ if (!lua_istable (L, index))
+ {
+ luaL_error (L, "#%d argments must be table", index);
+ }
+
+ Map map;
+ int const absindex = lua_absindex (L, index);
+ lua_pushnil (L);
+ while (lua_next (L, absindex) != 0)
+ {
+ map.emplace (Stack <K>::get (L, -2), Stack <V>::get (L, -1));
+ lua_pop (L, 1);
+ }
+ return map;
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/RefCountedObject.h b/lib/LuaBridge/Source/LuaBridge/RefCountedObject.h
new file mode 100644
index 0000000..ebc749e
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/RefCountedObject.h
@@ -0,0 +1,356 @@
+//==============================================================================
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2004-11 by Raw Material Software Ltd.
+
+ This is a derivative work used by permission from part of
+ JUCE, available at http://www.rawaterialsoftware.com
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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 incorporates work covered by the following copyright and
+ permission notice:
+
+ This file is part of the JUCE library - "Jules' Utility Class Extensions"
+ Copyright 2004-11 by Raw Material Software Ltd.
+*/
+//==============================================================================
+
+#pragma once
+
+//#define LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
+
+#include <LuaBridge/detail/TypeTraits.h>
+
+#include <cassert>
+
+namespace luabridge {
+
+//==============================================================================
+/**
+ Adds reference-counting to an object.
+
+ To add reference-counting to a class, derive it from this class, and
+ use the RefCountedObjectPtr class to point to it.
+
+ e.g. @code
+ class MyClass : public RefCountedObjectType
+ {
+ void foo();
+
+ // This is a neat way of declaring a typedef for a pointer class,
+ // rather than typing out the full templated name each time..
+ typedef RefCountedObjectPtr<MyClass> Ptr;
+ };
+
+ MyClass::Ptr p = new MyClass();
+ MyClass::Ptr p2 = p;
+ p = 0;
+ p2->foo();
+ @endcode
+
+ Once a new RefCountedObjectType has been assigned to a pointer, be
+ careful not to delete the object manually.
+*/
+template <class CounterType>
+class RefCountedObjectType
+{
+public:
+ //==============================================================================
+ /** Increments the object's reference count.
+
+ This is done automatically by the smart pointer, but is public just
+ in case it's needed for nefarious purposes.
+ */
+ inline void incReferenceCount() const
+ {
+ ++refCount;
+ }
+
+ /** Decreases the object's reference count.
+
+ If the count gets to zero, the object will be deleted.
+ */
+ inline void decReferenceCount() const
+ {
+ assert (getReferenceCount() > 0);
+
+ if (--refCount == 0)
+ delete this;
+ }
+
+ /** Returns the object's current reference count. */
+ inline int getReferenceCount() const
+ {
+ return static_cast <int> (refCount);
+ }
+
+protected:
+ //==============================================================================
+ /** Creates the reference-counted object (with an initial ref count of zero). */
+ RefCountedObjectType() : refCount ()
+ {
+ }
+
+ /** Destructor. */
+ virtual ~RefCountedObjectType()
+ {
+ // it's dangerous to delete an object that's still referenced by something else!
+ assert (getReferenceCount() == 0);
+ }
+
+private:
+ //==============================================================================
+ CounterType mutable refCount;
+};
+
+//==============================================================================
+
+/** Non thread-safe reference counted object.
+
+ This creates a RefCountedObjectType that uses a non-atomic integer
+ as the counter.
+*/
+typedef RefCountedObjectType <int> RefCountedObject;
+
+//==============================================================================
+/**
+ A smart-pointer class which points to a reference-counted object.
+
+ The template parameter specifies the class of the object you want to point
+ to - the easiest way to make a class reference-countable is to simply make
+ it inherit from RefCountedObjectType, but if you need to, you could roll
+ your own reference-countable class by implementing a pair of methods called
+ incReferenceCount() and decReferenceCount().
+
+ When using this class, you'll probably want to create a typedef to
+ abbreviate the full templated name - e.g.
+
+ @code
+
+ typedef RefCountedObjectPtr <MyClass> MyClassPtr;
+
+ @endcode
+*/
+template <class ReferenceCountedObjectClass>
+class RefCountedObjectPtr
+{
+public:
+ /** The class being referenced by this pointer. */
+ typedef ReferenceCountedObjectClass ReferencedType;
+
+ //==============================================================================
+ /** Creates a pointer to a null object. */
+ inline RefCountedObjectPtr() : referencedObject (0)
+ {
+ }
+
+ /** Creates a pointer to an object.
+
+ This will increment the object's reference-count if it is non-null.
+ */
+ inline RefCountedObjectPtr (ReferenceCountedObjectClass* const refCountedObject)
+ : referencedObject (refCountedObject)
+ {
+ if (refCountedObject != 0)
+ refCountedObject->incReferenceCount();
+ }
+
+ /** Copies another pointer.
+ This will increment the object's reference-count (if it is non-null).
+ */
+ inline RefCountedObjectPtr (const RefCountedObjectPtr& other)
+ : referencedObject (other.referencedObject)
+ {
+ if (referencedObject != 0)
+ referencedObject->incReferenceCount();
+ }
+
+#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ /** Takes-over the object from another pointer. */
+ inline RefCountedObjectPtr (RefCountedObjectPtr&& other)
+ : referencedObject (other.referencedObject)
+ {
+ other.referencedObject = 0;
+ }
+#endif
+
+ /** Copies another pointer.
+ This will increment the object's reference-count (if it is non-null).
+ */
+ template <class DerivedClass>
+ inline RefCountedObjectPtr (const RefCountedObjectPtr<DerivedClass>& other)
+ : referencedObject (static_cast <ReferenceCountedObjectClass*> (other.getObject()))
+ {
+ if (referencedObject != 0)
+ referencedObject->incReferenceCount();
+ }
+
+ /** Changes this pointer to point at a different object.
+
+ The reference count of the old object is decremented, and it might be
+ deleted if it hits zero. The new object's count is incremented.
+ */
+ RefCountedObjectPtr& operator= (const RefCountedObjectPtr& other)
+ {
+ return operator= (other.referencedObject);
+ }
+
+ /** Changes this pointer to point at a different object.
+
+ The reference count of the old object is decremented, and it might be
+ deleted if it hits zero. The new object's count is incremented.
+ */
+ template <class DerivedClass>
+ RefCountedObjectPtr& operator= (const RefCountedObjectPtr<DerivedClass>& other)
+ {
+ return operator= (static_cast <ReferenceCountedObjectClass*> (other.getObject()));
+ }
+
+#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ /** Takes-over the object from another pointer. */
+ RefCountedObjectPtr& operator= (RefCountedObjectPtr&& other)
+ {
+ std::swap (referencedObject, other.referencedObject);
+ return *this;
+ }
+#endif
+
+ /** Changes this pointer to point at a different object.
+
+ The reference count of the old object is decremented, and it might be
+ deleted if it hits zero. The new object's count is incremented.
+ */
+ RefCountedObjectPtr& operator= (ReferenceCountedObjectClass* const newObject)
+ {
+ if (referencedObject != newObject)
+ {
+ if (newObject != 0)
+ newObject->incReferenceCount();
+
+ ReferenceCountedObjectClass* const oldObject = referencedObject;
+ referencedObject = newObject;
+
+ if (oldObject != 0)
+ oldObject->decReferenceCount();
+ }
+
+ return *this;
+ }
+
+ /** Destructor.
+
+ This will decrement the object's reference-count, and may delete it if it
+ gets to zero.
+ */
+ inline ~RefCountedObjectPtr()
+ {
+ if (referencedObject != 0)
+ referencedObject->decReferenceCount();
+ }
+
+ /** Returns the object that this pointer references.
+ The pointer returned may be zero, of course.
+ */
+ inline operator ReferenceCountedObjectClass*() const
+ {
+ return referencedObject;
+ }
+
+ // the -> operator is called on the referenced object
+ inline ReferenceCountedObjectClass* operator->() const
+ {
+ return referencedObject;
+ }
+
+ /** Returns the object that this pointer references.
+ The pointer returned may be zero, of course.
+ */
+ inline ReferenceCountedObjectClass* getObject() const
+ {
+ return referencedObject;
+ }
+
+private:
+ //==============================================================================
+ ReferenceCountedObjectClass* referencedObject;
+};
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator== (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, ReferenceCountedObjectClass* const object2)
+{
+ return object1.getObject() == object2;
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator== (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, const RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
+{
+ return object1.getObject() == object2.getObject();
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator== (ReferenceCountedObjectClass* object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
+{
+ return object1 == object2.getObject();
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator!= (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectClass* object2)
+{
+ return object1.getObject() != object2;
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator!= (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
+{
+ return object1.getObject() != object2.getObject();
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator!= (ReferenceCountedObjectClass* object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
+{
+ return object1 != object2.getObject();
+}
+
+//==============================================================================
+
+template <class T>
+struct ContainerTraits <RefCountedObjectPtr <T> >
+{
+ typedef T Type;
+
+ static T* get (RefCountedObjectPtr <T> const& c)
+ {
+ return c.getObject ();
+ }
+};
+
+//==============================================================================
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/RefCountedPtr.h b/lib/LuaBridge/Source/LuaBridge/RefCountedPtr.h
new file mode 100644
index 0000000..4db103f
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/RefCountedPtr.h
@@ -0,0 +1,244 @@
+//==============================================================================
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2019, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <unordered_map>
+#include "RefCountedObject.h"
+
+namespace luabridge {
+
+//==============================================================================
+/**
+ Support for our RefCountedPtr.
+*/
+struct RefCountedPtrBase
+{
+ // Declaration of container for the refcounts
+ typedef std::unordered_map <const void *, int> RefCountsType;
+
+protected:
+ RefCountsType& getRefCounts () const
+ {
+ static RefCountsType refcounts;
+ return refcounts ;
+ }
+};
+
+//==============================================================================
+/**
+ A reference counted smart pointer.
+
+ The api is compatible with boost::RefCountedPtr and std::RefCountedPtr, in the
+ sense that it implements a strict subset of the functionality.
+
+ This implementation uses a hash table to look up the reference count
+ associated with a particular pointer.
+
+ @tparam T The class type.
+
+ @todo Decompose RefCountedPtr using a policy. At a minimum, the underlying
+ reference count should be policy based (to support atomic operations)
+ and the delete behavior should be policy based (to support custom
+ disposal methods).
+
+ @todo Provide an intrusive version of RefCountedPtr.
+*/
+template <class T>
+class RefCountedPtr : private RefCountedPtrBase
+{
+public:
+ template <typename Other>
+ struct rebind
+ {
+ typedef RefCountedPtr <Other> other;
+ };
+
+ /** Construct as nullptr or from existing pointer to T.
+
+ @param p The optional, existing pointer to assign from.
+ */
+ RefCountedPtr (T* p = 0) : m_p (p)
+ {
+ ++getRefCounts () [m_p];
+ }
+
+ /** Construct from another RefCountedPtr.
+
+ @param rhs The RefCountedPtr to assign from.
+ */
+ RefCountedPtr (RefCountedPtr <T> const& rhs) : m_p (rhs.get())
+ {
+ ++getRefCounts () [m_p];
+ }
+
+ /** Construct from a RefCountedPtr of a different type.
+
+ @invariant A pointer to U must be convertible to a pointer to T.
+
+ @param rhs The RefCountedPtr to assign from.
+ @tparam U The other object type.
+ */
+ template <typename U>
+ RefCountedPtr (RefCountedPtr <U> const& rhs) : m_p (static_cast <T*> (rhs.get()))
+ {
+ ++getRefCounts () [m_p];
+ }
+
+ /** Release the object.
+
+ If there are no more references then the object is deleted.
+ */
+ ~RefCountedPtr ()
+ {
+ reset();
+ }
+
+ /** Assign from another RefCountedPtr.
+
+ @param rhs The RefCountedPtr to assign from.
+ @return A reference to the RefCountedPtr.
+ */
+ RefCountedPtr <T>& operator= (RefCountedPtr <T> const& rhs)
+ {
+ if (m_p != rhs.m_p)
+ {
+ reset ();
+ m_p = rhs.m_p;
+ ++getRefCounts () [m_p];
+ }
+ return *this;
+ }
+
+ /** Assign from another RefCountedPtr of a different type.
+
+ @note A pointer to U must be convertible to a pointer to T.
+
+ @tparam U The other object type.
+ @param rhs The other RefCountedPtr to assign from.
+ @return A reference to the RefCountedPtr.
+ */
+ template <typename U>
+ RefCountedPtr <T>& operator= (RefCountedPtr <U> const& rhs)
+ {
+ reset ();
+ m_p = static_cast <T*> (rhs.get());
+ ++getRefCounts () [m_p];
+ return *this;
+ }
+
+ /** Retrieve the raw pointer.
+
+ @return A pointer to the object.
+ */
+ T* get () const
+ {
+ return m_p;
+ }
+
+ /** Retrieve the raw pointer.
+
+ @return A pointer to the object.
+ */
+ T* operator* () const
+ {
+ return m_p;
+ }
+
+ /** Retrieve the raw pointer.
+
+ @return A pointer to the object.
+ */
+ T* operator-> () const
+ {
+ return m_p;
+ }
+
+ /** Determine the number of references.
+
+ @note This is not thread-safe.
+
+ @return The number of active references.
+ */
+ long use_count () const
+ {
+ return getRefCounts () [m_p];
+ }
+
+ /** Release the pointer.
+
+ The reference count is decremented. If the reference count reaches
+ zero, the object is deleted.
+ */
+ void reset ()
+ {
+ if (m_p != 0)
+ {
+ if (--getRefCounts () [m_p] <= 0)
+ delete m_p;
+
+ m_p = 0;
+ }
+ }
+
+private:
+ T* m_p;
+};
+
+template <class T>
+bool operator== (const RefCountedPtr <T>& lhs, const RefCountedPtr <T>& rhs)
+{
+ return lhs.get () == rhs.get ();
+}
+
+template <class T>
+bool operator!= (const RefCountedPtr <T>& lhs, const RefCountedPtr <T>& rhs)
+{
+ return lhs.get() != rhs.get();
+}
+
+//==============================================================================
+
+// forward declaration
+template <class T>
+struct ContainerTraits;
+
+template <class T>
+struct ContainerTraits <RefCountedPtr <T> >
+{
+ typedef T Type;
+
+ static T* get (RefCountedPtr <T> const& c)
+ {
+ return c.get ();
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/UnorderedMap.h b/lib/LuaBridge/Source/LuaBridge/UnorderedMap.h
new file mode 100644
index 0000000..415996b
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/UnorderedMap.h
@@ -0,0 +1,50 @@
+// https://github.com/vinniefalco/LuaBridge
+//
+// Copyright 2019, Dmitry Tarakanov
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+#include <LuaBridge/detail/Stack.h>
+
+#include <unordered_map>
+
+namespace luabridge {
+
+template <class K, class V>
+struct Stack <std::unordered_map <K, V>>
+{
+ typedef std::unordered_map <K, V> Map;
+
+ static void push (lua_State* L, const Map& map)
+ {
+ lua_createtable (L, 0, static_cast <int> (map.size ()));
+ typedef typename Map::const_iterator ConstIter;
+ for (ConstIter i = map.begin (); i != map.end (); ++i)
+ {
+ Stack <K>::push (L, i->first);
+ Stack <V>::push (L, i->second);
+ lua_settable (L, -3);
+ }
+ }
+
+ static Map get (lua_State* L, int index)
+ {
+ if (!lua_istable (L, index))
+ {
+ luaL_error (L, "#%d argments must be table", index);
+ }
+
+ Map map;
+ int const absindex = lua_absindex (L, index);
+ lua_pushnil (L);
+ while (lua_next (L, absindex) != 0)
+ {
+ map.emplace (Stack <K>::get (L, -2), Stack <V>::get (L, -1));
+ lua_pop (L, 1);
+ }
+ return map;
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/Vector.h b/lib/LuaBridge/Source/LuaBridge/Vector.h
new file mode 100644
index 0000000..f1b711d
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/Vector.h
@@ -0,0 +1,49 @@
+// https://github.com/vinniefalco/LuaBridge
+//
+// Copyright 2018, Dmitry Tarakanov
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+#include <LuaBridge/detail/Stack.h>
+
+#include <vector>
+
+namespace luabridge {
+
+template <class T>
+struct Stack <std::vector <T> >
+{
+ static void push (lua_State* L, std::vector <T> const& vector)
+ {
+ lua_createtable (L, static_cast <int> (vector.size ()), 0);
+ for (std::size_t i = 0; i < vector.size (); ++i)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (i + 1));
+ Stack <T>::push (L, vector [i]);
+ lua_settable (L, -3);
+ }
+ }
+
+ static std::vector <T> get (lua_State* L, int index)
+ {
+ if (!lua_istable (L, index))
+ {
+ luaL_error (L, "#%d argments must be table", index);
+ }
+
+ std::vector <T> vector;
+ vector.reserve (static_cast <std::size_t> (get_length (L, index)));
+
+ int const absindex = lua_absindex (L, index);
+ lua_pushnil (L);
+ while (lua_next (L, absindex) != 0)
+ {
+ vector.push_back (Stack <T>::get (L, -1));
+ lua_pop (L, 1);
+ }
+ return vector;
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/CFunctions.h b/lib/LuaBridge/Source/LuaBridge/detail/CFunctions.h
new file mode 100644
index 0000000..d4ae0cc
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/CFunctions.h
@@ -0,0 +1,495 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2019, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <LuaBridge/detail/Config.h>
+#include <LuaBridge/detail/FuncTraits.h>
+
+#include <string>
+
+namespace luabridge {
+
+// We use a structure so we can define everything in the header.
+//
+struct CFunc
+{
+ static void addGetter (lua_State* L, const char* name, int tableIndex)
+ {
+ assert (lua_istable (L, tableIndex));
+ assert (lua_iscfunction (L, -1)); // Stack: getter
+
+ lua_rawgetp (L, tableIndex, getPropgetKey ()); // Stack: getter, propget table (pg)
+ lua_pushvalue (L, -2); // Stack: getter, pg, getter
+ rawsetfield (L, -2, name); // Stack: getter, pg
+ lua_pop (L, 2); // Stack: -
+ }
+
+ static void addSetter (lua_State* L, const char* name, int tableIndex)
+ {
+ assert (lua_istable (L, tableIndex));
+ assert (lua_iscfunction (L, -1)); // Stack: setter
+
+ lua_rawgetp (L, tableIndex, getPropsetKey ()); // Stack: setter, propset table (ps)
+ lua_pushvalue (L, -2); // Stack: setter, ps, setter
+ rawsetfield (L, -2, name); // Stack: setter, ps
+ lua_pop (L, 2); // Stack: -
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ __index metamethod for a namespace or class static and non-static members.
+ Retrieves functions from metatables and properties from propget tables.
+ Looks through the class hierarchy if inheritance is present.
+ */
+ static int indexMetaMethod (lua_State* L)
+ {
+ assert (lua_istable (L, 1) || lua_isuserdata (L, 1)); // Stack (further not shown): table | userdata, name
+
+ lua_getmetatable (L, 1); // Stack: class/const table (mt)
+ assert (lua_istable (L, -1));
+
+ for (;;)
+ {
+ lua_pushvalue (L, 2); // Stack: mt, field name
+ lua_rawget (L, -2); // Stack: mt, field | nil
+
+ if (lua_iscfunction (L, -1)) // Stack: mt, field
+ {
+ lua_remove (L, -2); // Stack: field
+ return 1;
+ }
+
+ assert (lua_isnil (L, -1)); // Stack: mt, nil
+ lua_pop (L, 1); // Stack: mt
+
+ lua_rawgetp (L, -1, getPropgetKey ()); // Stack: mt, propget table (pg)
+ assert (lua_istable (L, -1));
+
+ lua_pushvalue (L, 2); // Stack: mt, pg, field name
+ lua_rawget (L, -2); // Stack: mt, pg, getter | nil
+ lua_remove (L, -2); // Stack: mt, getter | nil
+
+ if (lua_iscfunction (L, -1)) // Stack: mt, getter
+ {
+ lua_remove (L, -2); // Stack: getter
+ lua_pushvalue (L, 1); // Stack: getter, table | userdata
+ lua_call (L, 1, 1); // Stack: value
+ return 1;
+ }
+
+ assert (lua_isnil (L, -1)); // Stack: mt, nil
+ lua_pop (L, 1); // Stack: mt
+
+ // It may mean that the field may be in const table and it's constness violation.
+ // Don't check that, just return nil
+
+ // Repeat the lookup in the parent metafield,
+ // or return nil if the field doesn't exist.
+ lua_rawgetp (L, -1, getParentKey ()); // Stack: mt, parent mt | nil
+
+ if (lua_isnil (L, -1)) // Stack: mt, nil
+ {
+ lua_remove (L, -2); // Stack: nil
+ return 1;
+ }
+
+ // Removethe metatable and repeat the search in the parent one.
+ assert (lua_istable (L, -1)); // Stack: mt, parent mt
+ lua_remove (L, -2); // Stack: parent mt
+ }
+
+ // no return
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ __newindex metamethod for namespace or class static members.
+ Retrieves properties from propset tables.
+ */
+ static int newindexStaticMetaMethod (lua_State* L)
+ {
+ return newindexMetaMethod (L, false);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ __newindex metamethod for non-static members.
+ Retrieves properties from propset tables.
+ */
+ static int newindexObjectMetaMethod (lua_State* L)
+ {
+ return newindexMetaMethod (L, true);
+ }
+
+ static int newindexMetaMethod (lua_State* L, bool pushSelf)
+ {
+ assert (lua_istable (L, 1) || lua_isuserdata (L, 1)); // Stack (further not shown): table | userdata, name, new value
+
+ lua_getmetatable (L, 1); // Stack: metatable (mt)
+ assert (lua_istable (L, -1));
+
+ for (;;)
+ {
+ lua_rawgetp (L, -1, getPropsetKey ()); // Stack: mt, propset table (ps) | nil
+
+ if (lua_isnil (L, -1)) // Stack: mt, nil
+ {
+ lua_pop (L, 2); // Stack: -
+ return luaL_error (L, "No member named '%s'", lua_tostring (L, 2));
+ }
+
+ assert (lua_istable (L, -1));
+
+ lua_pushvalue (L, 2); // Stack: mt, ps, field name
+ lua_rawget (L, -2); // Stack: mt, ps, setter | nil
+ lua_remove (L, -2); // Stack: mt, setter | nil
+
+ if (lua_iscfunction (L, -1)) // Stack: mt, setter
+ {
+ lua_remove (L, -2); // Stack: setter
+ if (pushSelf)
+ {
+ lua_pushvalue (L, 1); // Stack: setter, table | userdata
+ }
+ lua_pushvalue (L, 3); // Stack: setter, table | userdata, new value
+ lua_call (L, pushSelf ? 2 : 1, 0); // Stack: -
+ return 0;
+ }
+
+ assert (lua_isnil (L, -1)); // Stack: mt, nil
+ lua_pop (L, 1); // Stack: mt
+
+ lua_rawgetp (L, -1, getParentKey ()); // Stack: mt, parent mt | nil
+
+ if (lua_isnil (L, -1)) // Stack: mt, nil
+ {
+ lua_pop (L, 1); // Stack: -
+ return luaL_error (L, "No writable member '%s'", lua_tostring (L, 2));
+ }
+
+ assert (lua_istable (L, -1)); // Stack: mt, parent mt
+ lua_remove (L, -2); // Stack: parent mt
+ // Repeat the search in the parent
+ }
+
+ // no return
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to report an error writing to a read-only value.
+
+ The name of the variable is in the first upvalue.
+ */
+ static int readOnlyError (lua_State* L)
+ {
+ std::string s;
+
+ s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only";
+
+ return luaL_error (L, s.c_str ());
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to get a variable.
+
+ This is used for global variables or class static data members.
+
+ The pointer to the data is in the first upvalue.
+ */
+ template <class T>
+ static int getVariable (lua_State* L)
+ {
+ assert (lua_islightuserdata (L, lua_upvalueindex (1)));
+ T const* ptr = static_cast <T const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (ptr != 0);
+ Stack <T>::push (L, *ptr);
+ return 1;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to set a variable.
+
+ This is used for global variables or class static data members.
+
+ The pointer to the data is in the first upvalue.
+ */
+ template <class T>
+ static int setVariable (lua_State* L)
+ {
+ assert (lua_islightuserdata (L, lua_upvalueindex (1)));
+ T* ptr = static_cast <T*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (ptr != 0);
+ *ptr = Stack <T>::get (L, 1);
+ return 0;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a function with a return value.
+
+ This is used for global functions, global properties, class static methods,
+ and class static properties.
+
+ The function pointer (lightuserdata) in the first upvalue.
+ */
+ template <class FnPtr>
+ struct Call
+ {
+ typedef typename FuncTraits <FnPtr>::Params Params;
+ typedef typename FuncTraits <FnPtr>::ReturnType ReturnType;
+
+ static int f (lua_State* L)
+ {
+ assert (lua_islightuserdata (L, lua_upvalueindex (1)));
+ FnPtr fnptr = reinterpret_cast <FnPtr> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ return Invoke <ReturnType, Params, 1>::run (L, fnptr);
+ }
+ };
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a class member function with a return value.
+
+ The member function pointer is in the first upvalue.
+ The class userdata object is at the top of the Lua stack.
+ */
+ template <class MemFnPtr>
+ struct CallMember
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+ typedef typename FuncTraits <MemFnPtr>::ReturnType ReturnType;
+
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ T* const t = Userdata::get <T> (L, 1, false);
+ MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ return Invoke <ReturnType, Params, 2>::run (L, t, fnptr);
+ }
+ };
+
+ template <class MemFnPtr>
+ struct CallConstMember
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+ typedef typename FuncTraits <MemFnPtr>::ReturnType ReturnType;
+
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ T const* const t = Userdata::get <T> (L, 1, true);
+ MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ return Invoke <ReturnType, Params, 2>::run (L, t, fnptr);
+ }
+ };
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a class member lua_CFunction.
+
+ The member function pointer is in the first upvalue.
+ The object userdata ('this') value is at top ot the Lua stack.
+ */
+ template <class T>
+ struct CallMemberCFunction
+ {
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ typedef int (T::*MFP) (lua_State* L);
+ T* const t = Userdata::get <T> (L, 1, false);
+ MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ return (t->*fnptr) (L);
+ }
+ };
+
+ template <class T>
+ struct CallConstMemberCFunction
+ {
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ typedef int (T::*MFP) (lua_State* L);
+ T const* const t = Userdata::get <T> (L, 1, true);
+ MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ return (t->*fnptr) (L);
+ }
+ };
+
+#ifdef LUABRIDGE_CXX11
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to call on a object.
+
+ The proxy function pointer (lightuserdata) is in the first upvalue.
+ The class userdata object is at the top of the Lua stack.
+ */
+ template <class FnPtr>
+ struct CallProxyFunction
+ {
+ using Params = typename FuncTraits <FnPtr>::Params;
+ using ReturnType = typename FuncTraits <FnPtr>::ReturnType;
+
+ static int f (lua_State* L)
+ {
+ assert (lua_islightuserdata (L, lua_upvalueindex (1)));
+ auto fnptr = reinterpret_cast <FnPtr> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ return Invoke <ReturnType, Params, 1>::run (L, fnptr);
+ }
+ };
+
+ template <class Functor>
+ struct CallProxyFunctor
+ {
+ using Params = typename FuncTraits <Functor>::Params;
+ using ReturnType = typename FuncTraits <Functor>::ReturnType;
+
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ Functor& fn = *static_cast <Functor*> (lua_touserdata (L, lua_upvalueindex (1)));
+ return Invoke <ReturnType, Params, 1>::run (L, fn);
+ }
+ };
+
+#endif
+
+ //--------------------------------------------------------------------------
+
+ // SFINAE Helpers
+
+ template <class MemFnPtr, bool isConst>
+ struct CallMemberFunctionHelper
+ {
+ static void add (lua_State* L, char const* name, MemFnPtr mf)
+ {
+ new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
+ lua_pushcclosure (L, &CallConstMember <MemFnPtr>::f, 1);
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -5, name); // const table
+ rawsetfield (L, -3, name); // class table
+ }
+ };
+
+ template <class MemFnPtr>
+ struct CallMemberFunctionHelper <MemFnPtr, false>
+ {
+ static void add (lua_State* L, char const* name, MemFnPtr mf)
+ {
+ new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
+ lua_pushcclosure (L, &CallMember <MemFnPtr>::f, 1);
+ rawsetfield (L, -3, name); // class table
+ }
+ };
+
+ //--------------------------------------------------------------------------
+ /**
+ __gc metamethod for a class.
+ */
+ template <class C>
+ static int gcMetaMethod (lua_State* L)
+ {
+ Userdata* const ud = Userdata::getExact <C> (L, 1);
+ ud->~Userdata ();
+ return 0;
+ }
+
+ /**
+ __gc metamethod for an arbitrary class.
+ */
+ template <class T>
+ static int gcMetaMethodAny (lua_State* L)
+ {
+ assert (isfulluserdata (L, 1));
+ T* t = static_cast <T*> (lua_touserdata (L, 1));
+ t->~T ();
+ return 0;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to get a class data member.
+
+ The pointer-to-member is in the first upvalue.
+ The class userdata object is at the top of the Lua stack.
+ */
+ template <class C, typename T>
+ static int getProperty (lua_State* L)
+ {
+ C* const c = Userdata::get <C> (L, 1, true);
+ T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
+ try
+ {
+ Stack <T&>::push (L, c->**mp);
+ }
+ catch (const std::exception& e)
+ {
+ luaL_error (L, e.what ());
+ }
+ return 1;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to set a class data member.
+
+ The pointer-to-member is in the first upvalue.
+ The class userdata object is at the top of the Lua stack.
+ */
+ template <class C, typename T>
+ static int setProperty (lua_State* L)
+ {
+ C* const c = Userdata::get <C> (L, 1, false);
+ T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
+ try
+ {
+ c->**mp = Stack <T>::get (L, 2);
+ }
+ catch (const std::exception& e)
+ {
+ luaL_error (L, e.what ());
+ }
+ return 0;
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/ClassInfo.h b/lib/LuaBridge/Source/LuaBridge/detail/ClassInfo.h
new file mode 100644
index 0000000..ca83f93
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/ClassInfo.h
@@ -0,0 +1,169 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+namespace luabridge {
+
+/**
+ * A unique key for a type name in a metatable.
+ */
+inline const void* getTypeKey ()
+{
+#ifdef _NDEBUG
+ static char value;
+ return &value;
+#else
+ return reinterpret_cast <void*> (0x71);
+#endif
+}
+
+/**
+ * The key of a const table in another metatable.
+ */
+inline const void* getConstKey ()
+{
+#ifdef _NDEBUG
+ static char value;
+ return &value;
+#else
+ return reinterpret_cast <void*> (0xc07);
+#endif
+}
+
+/**
+ * The key of a class table in another metatable.
+ */
+inline const void* getClassKey ()
+{
+#ifdef _NDEBUG
+ static char value;
+ return &value;
+#else
+ return reinterpret_cast <void*> (0xc1a);
+#endif
+}
+
+/**
+ * The key of a propget table in another metatable.
+ */
+inline const void* getPropgetKey ()
+{
+#ifdef _NDEBUG
+ static char value;
+ return &value;
+#else
+ return reinterpret_cast <void*> (0x6e7);
+#endif
+}
+
+/**
+ * The key of a propset table in another metatable.
+ */
+inline const void* getPropsetKey ()
+{
+#ifdef _NDEBUG
+ static char value;
+ return &value;
+#else
+ return reinterpret_cast <void*> (0x5e7);
+#endif
+}
+
+/**
+ * The key of a static table in another metatable.
+ */
+inline const void* getStaticKey ()
+{
+#ifdef _NDEBUG
+ static char value;
+ return &value;
+#else
+ return reinterpret_cast <void*> (0x57a);
+#endif
+}
+
+/**
+ * The key of a parent table in another metatable.
+ */
+inline const void* getParentKey ()
+{
+#ifdef _NDEBUG
+ static char value;
+ return &value;
+#else
+ return reinterpret_cast <void*> (0xdad);
+#endif
+}
+
+/** Unique Lua registry keys for a class.
+
+ Each registered class inserts three keys into the registry, whose
+ values are the corresponding static, class, and const metatables. This
+ allows a quick and reliable lookup for a metatable from a template type.
+*/
+template <class T>
+class ClassInfo
+{
+public:
+ /** Get the key for the static table.
+
+ The static table holds the static data members, static properties, and
+ static member functions for a class.
+ */
+ static void const* getStaticKey ()
+ {
+ static char value;
+ return &value;
+ }
+
+ /** Get the key for the class table.
+
+ The class table holds the data members, properties, and member functions
+ of a class. Read-only data and properties, and const member functions are
+ also placed here (to save a lookup in the const table).
+ */
+ static void const* getClassKey ()
+ {
+ static char value;
+ return &value;
+ }
+
+ /** Get the key for the const table.
+
+ The const table holds read-only data members and properties, and const
+ member functions of a class.
+ */
+ static void const* getConstKey ()
+ {
+ static char value;
+ return &value;
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/Config.h b/lib/LuaBridge/Source/LuaBridge/detail/Config.h
new file mode 100644
index 0000000..76b3d42
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/Config.h
@@ -0,0 +1,10 @@
+// https://github.com/vinniefalco/LuaBridge
+//
+// Copyright 2019, Dmitry Tarakanov
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+#if !defined (LUABRIDGE_NO_CXX11) && (__cplusplus >= 201103L || (defined (_MSC_VER) && _MSC_VER >= 1900))
+#define LUABRIDGE_CXX11
+#endif
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/Constructor.h b/lib/LuaBridge/Source/LuaBridge/detail/Constructor.h
new file mode 100644
index 0000000..04b3dab
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/Constructor.h
@@ -0,0 +1,205 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+namespace luabridge {
+
+/*
+* Constructor generators. These templates allow you to call operator new and
+* pass the contents of a type/value list to the Constructor. Like the
+* function pointer containers, these are only defined up to 8 parameters.
+*/
+
+/** Constructor generators.
+
+ These templates call operator new with the contents of a type/value
+ list passed to the Constructor with up to 8 parameters. Two versions
+ of call() are provided. One performs a regular new, the other performs
+ a placement new.
+*/
+template <class T, typename List>
+struct Constructor {};
+
+template <class T>
+struct Constructor <T, None>
+{
+ static T* call (TypeListValues <None> const&)
+ {
+ return new T;
+ }
+ static T* call (void* mem, TypeListValues <None> const&)
+ {
+ return new (mem) T;
+ }
+};
+
+template <class T, class P1>
+struct Constructor <T, TypeList <P1> >
+{
+ static T* call (const TypeListValues<TypeList <P1> > &tvl)
+ {
+ return new T(tvl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1> > &tvl)
+ {
+ return new (mem) T(tvl.hd);
+ }
+};
+
+template <class T, class P1, class P2>
+struct Constructor <T, TypeList <P1, TypeList <P2> > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3> > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3> > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3> > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4> > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4> > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4> > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4,
+ class P5>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4, TypeList <P5> > > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4,
+ class P5, class P6>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4, TypeList <P5, TypeList <P6> > > > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4,
+ class P5, class P6, class P7>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
+ TypeList <P7> > > > > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
+ TypeList <P7> > > > > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4,
+ class P5, class P6, class P7, class P8>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7,
+ TypeList <P8> > > > > > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
+ TypeList <P7, TypeList <P8> > > > > > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
+ TypeList <P7, TypeList <P8> > > > > > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/FuncTraits.h b/lib/LuaBridge/Source/LuaBridge/detail/FuncTraits.h
new file mode 100644
index 0000000..a66e296
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/FuncTraits.h
@@ -0,0 +1,942 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2019, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <LuaBridge/detail/Config.h>
+
+#ifdef LUABRIDGE_CXX11
+#include <functional>
+#endif
+
+namespace luabridge {
+
+/**
+ Since the throw specification is part of a function signature, the FuncTraits
+ family of templates needs to be specialized for both types. The
+ LUABRIDGE_THROWSPEC macro controls whether we use the 'throw ()' form, or
+ 'noexcept' (if C++11 is available) to distinguish the functions.
+*/
+#if defined (__APPLE_CPP__) || defined (__APPLE_CC__) || defined (__clang__) || defined (__GNUC__) || \
+ (defined (_MSC_VER) && (_MSC_VER >= 1700))
+// Do not define LUABRIDGE_THROWSPEC since the Xcode and gcc compilers do not
+// distinguish the throw specification in the function signature.
+#define LUABRIDGE_THROWSPEC
+#else
+// Visual Studio 10 and earlier pay too much mind to useless throw () spec.
+//
+# define LUABRIDGE_THROWSPEC throw ()
+#endif
+
+//==============================================================================
+/**
+ * Traits class for unrolling the type list values into function arguments.
+ */
+template <class ReturnType, size_t NUM_PARAMS>
+struct Caller;
+
+template <class ReturnType>
+struct Caller <ReturnType, 0>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& params)
+ {
+ return fn ();
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>&)
+ {
+ return (obj->*fn) ();
+ }
+};
+
+template <class ReturnType>
+struct Caller <ReturnType, 1>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
+ {
+ return fn (tvl.hd);
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+ {
+ return (obj->*fn) (tvl.hd);
+ }
+};
+
+template <class ReturnType>
+struct Caller <ReturnType, 2>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
+ {
+ return fn (tvl.hd, tvl.tl.hd);
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+ {
+ return (obj->*fn) (tvl.hd, tvl.tl.hd);
+ }
+};
+
+template <class ReturnType>
+struct Caller <ReturnType, 3>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
+ {
+ return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+ {
+ return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+};
+
+template <class ReturnType>
+struct Caller <ReturnType, 4>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
+ {
+ return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+ {
+ return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+};
+
+template <class ReturnType>
+struct Caller <ReturnType, 5>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
+ {
+ return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+ {
+ return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class ReturnType>
+struct Caller <ReturnType, 6>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
+ {
+ return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.hd);
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+ {
+ return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class ReturnType>
+struct Caller <ReturnType, 7>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
+ {
+ return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+ {
+ return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class ReturnType>
+struct Caller <ReturnType, 8>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
+ {
+ return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+ {
+ return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class ReturnType>
+struct Caller <ReturnType, 9>
+{
+ template <class Fn, class Params>
+ static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
+ {
+ return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+
+ template <class T, class MemFn, class Params>
+ static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+ {
+ return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class ReturnType, class Fn, class Params>
+ReturnType doCall (Fn& fn, TypeListValues <Params>& tvl)
+{
+ return Caller <ReturnType, TypeListSize <Params>::value>::f (fn, tvl);
+}
+
+template <class ReturnType, class T, class MemFn, class Params>
+static ReturnType doCall(T* obj, MemFn& fn, TypeListValues <Params>& tvl)
+{
+ return Caller <ReturnType, TypeListSize <Params>::value>::f (obj, fn, tvl);
+}
+
+//==============================================================================
+/**
+ Traits for function pointers.
+
+ There are three types of functions: global, non-const member, and const
+ member. These templates determine the type of function, which class type it
+ belongs to if it is a class member, the const-ness if it is a member
+ function, and the type information for the return value and argument list.
+
+ Expansions are provided for functions with up to 8 parameters. This can be
+ manually extended, or expanded to an arbitrary amount using C++11 features.
+*/
+template <class MemFn, class D = MemFn>
+struct FuncTraits
+{
+};
+
+#ifndef LUABRIDGE_CXX11
+
+/* Ordinary function pointers. */
+
+template <class R, class D>
+struct FuncTraits <R (*) () LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class D>
+struct FuncTraits <R (*) (P1) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class D>
+struct FuncTraits <R (*) (P1, P2) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */
+
+#ifdef _M_IX86 // Windows 32bit only
+
+template <class R, class D>
+struct FuncTraits <R (__stdcall *) (), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class D>
+struct FuncTraits <R (__stdcall *) (P1), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class D>
+struct FuncTraits <R (__stdcall *) (P1, P2), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (__stdcall *) (P1, P2, P3), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5, P6), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5, P6, P7), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5, P6, P7, P8), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+#endif // _M_IX86
+
+/* Non-const member function pointers. */
+
+template <class T, class R, class D>
+struct FuncTraits <R (T::*) () LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class D>
+struct FuncTraits <R (T::*) (P1) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class D>
+struct FuncTraits <R (T::*) (P1, P2) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+/* Const member function pointers. */
+
+template <class T, class R, class D>
+struct FuncTraits <R (T::*) () const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class D>
+struct FuncTraits <R (T::*) (P1) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class D>
+struct FuncTraits <R (T::*) (P1, P2) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (T const* obj, R (T::*fp) (P1, P2) const, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+#else // ifndef LUABRIDGE_CXX11
+
+/* Ordinary function pointers. */
+
+template <class R, class... ParamList>
+struct FuncTraits <R (*) (ParamList...)>
+{
+ static bool const isMemberFunction = false;
+ using DeclType = R (*) (ParamList...);
+ using ReturnType = R;
+ using Params = typename MakeTypeList <ParamList...>::Result;
+
+ static R call (const DeclType& fp, TypeListValues <Params>& tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */
+
+#ifdef _M_IX86 // Windows 32bit only
+
+template <class R, class... ParamList>
+struct FuncTraits <R (__stdcall *) (ParamList...)>
+{
+ static bool const isMemberFunction = false;
+ using DeclType = R (__stdcall *) (ParamList...);
+ using ReturnType = R;
+ using Params = typename MakeTypeList <ParamList...>::Result;
+
+ static R call (const DeclType& fp, TypeListValues <Params>& tvl)
+ {
+ return doCall <R> (fp, tvl);
+ }
+};
+
+#endif // _M_IX86
+
+/* Non-const member function pointers. */
+
+template <class T, class R, class... ParamList>
+struct FuncTraits <R (T::*) (ParamList...)>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ using DeclType = R (T::*) (ParamList...);
+ using ClassType = T;
+ using ReturnType = R;
+ using Params = typename MakeTypeList <ParamList...>::Result;
+
+ static R call (ClassType* obj, const DeclType& fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+/* Const member function pointers. */
+
+template <class T, class R, class... ParamList>
+struct FuncTraits <R (T::*) (ParamList...) const>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ using DeclType = R (T::*) (ParamList...) const;
+ using ClassType = T;
+ using ReturnType = R;
+ using Params = typename MakeTypeList <ParamList...>::Result;
+
+ static R call (const ClassType* obj, const DeclType& fp, TypeListValues <Params> tvl)
+ {
+ return doCall <R> (obj, fp, tvl);
+ }
+};
+
+/* std::function */
+
+template <class R, class... ParamList>
+struct FuncTraits <std::function <R (ParamList...)>>
+{
+ static bool const isMemberFunction = false;
+ static bool const isConstMemberFunction = false;
+ using DeclType = std::function <R (ParamList...)>;
+ using ReturnType = R;
+ using Params = typename MakeTypeList <ParamList...>::Result;
+
+ static ReturnType call (DeclType& fn, TypeListValues <Params>& tvl)
+ {
+ return doCall <ReturnType> (fn, tvl);
+ }
+};
+
+#endif // ifndef LUABRIDGE_CXX11
+
+template <class ReturnType, class Params, int startParam>
+struct Invoke
+{
+ template <class Fn>
+ static int run (lua_State* L, Fn& fn)
+ {
+ try
+ {
+ ArgList <Params, startParam> args (L);
+ Stack <ReturnType>::push (L, FuncTraits <Fn>::call (fn, args));
+ return 1;
+ }
+ catch (const std::exception& e)
+ {
+ return luaL_error (L, e.what ());
+ }
+ }
+
+ template <class T, class MemFn>
+ static int run (lua_State* L, T* object, const MemFn& fn)
+ {
+ try
+ {
+ ArgList <Params, startParam> args (L);
+ Stack <ReturnType>::push (L, FuncTraits <MemFn>::call (object, fn, args));
+ return 1;
+ }
+ catch (const std::exception& e)
+ {
+ return luaL_error (L, e.what ());
+ }
+ }
+};
+
+template <class Params, int startParam>
+struct Invoke <void, Params, startParam>
+{
+ template <class Fn>
+ static int run (lua_State* L, Fn& fn)
+ {
+ try
+ {
+ ArgList <Params, startParam> args (L);
+ FuncTraits <Fn>::call (fn, args);
+ return 0;
+ }
+ catch (const std::exception& e)
+ {
+ return luaL_error (L, e.what ());
+ }
+ }
+
+ template <class T, class MemFn>
+ static int run (lua_State* L, T* object, const MemFn& fn)
+ {
+ try
+ {
+ ArgList <Params, startParam> args (L);
+ FuncTraits <MemFn>::call (object, fn, args);
+ return 0;
+ }
+ catch (const std::exception& e)
+ {
+ return luaL_error (L, e.what ());
+ }
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/Iterator.h b/lib/LuaBridge/Source/LuaBridge/detail/Iterator.h
new file mode 100644
index 0000000..6c17623
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/Iterator.h
@@ -0,0 +1,154 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2018, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <LuaBridge/detail/LuaRef.h>
+
+#include <utility>
+
+
+namespace luabridge {
+
+/** Allows table iteration.
+*/
+class Iterator
+{
+ lua_State* m_L;
+ LuaRef m_table;
+ LuaRef m_key;
+ LuaRef m_value;
+
+ void next ()
+ {
+ m_table.push ();
+ m_key.push ();
+ if (lua_next (m_L, -2))
+ {
+ m_value.pop ();
+ m_key.pop ();
+ }
+ else
+ {
+ m_key = Nil ();
+ m_value = Nil ();
+ }
+ lua_pop (m_L, 1);
+ }
+
+public:
+ explicit Iterator (const LuaRef& table, bool isEnd = false)
+ : m_L (table.state ())
+ , m_table (table)
+ , m_key (table.state ()) // m_key is nil
+ , m_value (table.state ()) // m_value is nil
+ {
+ if (!isEnd)
+ {
+ next (); // get the first (key, value) pair from table
+ }
+ }
+
+ lua_State* state () const
+ {
+ return m_L;
+ }
+
+ std::pair <LuaRef, LuaRef> operator* () const
+ {
+ return std::make_pair (m_key, m_value);
+ }
+
+ LuaRef operator-> () const
+ {
+ return m_value;
+ }
+
+ bool operator!= (const Iterator& rhs) const
+ {
+ assert (m_L == rhs.m_L);
+ return !m_table.rawequal (rhs.m_table) || !m_key.rawequal (rhs.m_key);
+ }
+
+ Iterator& operator++ ()
+ {
+ if (isNil ())
+ {
+ // if the iterator reaches the end, do nothing
+ return *this;
+ }
+ else
+ {
+ next ();
+ return *this;
+ }
+ }
+
+ bool isNil () const
+ {
+ return m_key.isNil ();
+ }
+
+ LuaRef key () const
+ {
+ return m_key;
+ }
+
+ LuaRef value () const
+ {
+ return m_value;
+ }
+
+private:
+ // Don't use postfix increment, it is less efficient
+ Iterator operator++ (int);
+};
+
+class Range
+{
+ Iterator m_begin;
+ Iterator m_end;
+
+public:
+ Range (const Iterator& begin, const Iterator& end)
+ : m_begin (begin)
+ , m_end (end)
+ {
+ }
+
+ const Iterator& begin () const { return m_begin; }
+ const Iterator& end () const { return m_end; }
+};
+
+inline Range pairs (const LuaRef& table)
+{
+ return Range (Iterator (table, false), Iterator (table, true));
+}
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/LuaException.h b/lib/LuaBridge/Source/LuaBridge/detail/LuaException.h
new file mode 100644
index 0000000..6ca9818
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/LuaException.h
@@ -0,0 +1,122 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <exception>
+#include <string>
+
+namespace luabridge {
+
+class LuaException : public std::exception
+{
+private:
+ lua_State* m_L;
+ std::string m_what;
+
+public:
+ //----------------------------------------------------------------------------
+ /**
+ Construct a LuaException after a lua_pcall().
+ */
+ LuaException (lua_State* L, int /*code*/)
+ : m_L (L)
+ {
+ whatFromStack ();
+ }
+
+ //----------------------------------------------------------------------------
+
+ LuaException (lua_State *L,
+ char const*,
+ char const*,
+ long)
+ : m_L (L)
+ {
+ whatFromStack ();
+ }
+
+ //----------------------------------------------------------------------------
+
+ ~LuaException() throw ()
+ {
+ }
+
+ //----------------------------------------------------------------------------
+
+ char const* what() const throw ()
+ {
+ return m_what.c_str();
+ }
+
+ //============================================================================
+ /**
+ Throw an exception.
+
+ This centralizes all the exceptions thrown, so that we can set
+ breakpoints before the stack is unwound, or otherwise customize the
+ behavior.
+ */
+ template <class Exception>
+ static void Throw (Exception e)
+ {
+ throw e;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Wrapper for lua_pcall that throws.
+ */
+ static void pcall (lua_State* L, int nargs = 0, int nresults = 0, int msgh = 0)
+ {
+ int code = lua_pcall (L, nargs, nresults, msgh);
+
+ if (code != LUABRIDGE_LUA_OK)
+ Throw (LuaException (L, code));
+ }
+
+ //----------------------------------------------------------------------------
+
+protected:
+ void whatFromStack ()
+ {
+ if (lua_gettop (m_L) > 0)
+ {
+ char const* s = lua_tostring (m_L, -1);
+ m_what = s ? s : "";
+ }
+ else
+ {
+ // stack is empty
+ m_what = "missing error";
+ }
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/LuaHelpers.h b/lib/LuaBridge/Source/LuaBridge/detail/LuaHelpers.h
new file mode 100644
index 0000000..e336cf2
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/LuaHelpers.h
@@ -0,0 +1,151 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <cassert>
+
+namespace luabridge {
+
+// These are for Lua versions prior to 5.2.0.
+//
+#if LUA_VERSION_NUM < 502
+inline int lua_absindex (lua_State* L, int idx)
+{
+ if (idx > LUA_REGISTRYINDEX && idx < 0)
+ return lua_gettop (L) + idx + 1;
+ else
+ return idx;
+}
+
+inline void lua_rawgetp (lua_State* L, int idx, void const* p)
+{
+ idx = lua_absindex (L, idx);
+ lua_pushlightuserdata (L, const_cast <void*> (p));
+ lua_rawget (L,idx);
+}
+
+inline void lua_rawsetp (lua_State* L, int idx, void const* p)
+{
+ idx = lua_absindex (L, idx);
+ lua_pushlightuserdata (L, const_cast <void*> (p));
+ // put key behind value
+ lua_insert (L, -2);
+ lua_rawset (L, idx);
+}
+
+#define LUA_OPEQ 1
+#define LUA_OPLT 2
+#define LUA_OPLE 3
+
+inline int lua_compare (lua_State* L, int idx1, int idx2, int op)
+{
+ switch (op)
+ {
+ case LUA_OPEQ:
+ return lua_equal (L, idx1, idx2);
+ break;
+
+ case LUA_OPLT:
+ return lua_lessthan (L, idx1, idx2);
+ break;
+
+ case LUA_OPLE:
+ return lua_equal (L, idx1, idx2) || lua_lessthan (L, idx1, idx2);
+ break;
+
+ default:
+ return 0;
+ };
+}
+
+inline int get_length (lua_State* L, int idx)
+{
+ return int (lua_objlen (L, idx));
+}
+
+#else
+inline int get_length (lua_State* L, int idx)
+{
+ lua_len (L, idx);
+ int len = int (luaL_checknumber (L, -1));
+ lua_pop (L, 1);
+ return len;
+}
+
+#endif
+
+#ifndef LUA_OK
+# define LUABRIDGE_LUA_OK 0
+#else
+# define LUABRIDGE_LUA_OK LUA_OK
+#endif
+
+/** Get a table value, bypassing metamethods.
+*/
+inline void rawgetfield (lua_State* L, int index, char const* key)
+{
+ assert (lua_istable (L, index));
+ index = lua_absindex (L, index);
+ lua_pushstring (L, key);
+ lua_rawget (L, index);
+}
+
+/** Set a table value, bypassing metamethods.
+*/
+inline void rawsetfield (lua_State* L, int index, char const* key)
+{
+ assert (lua_istable (L, index));
+ index = lua_absindex (L, index);
+ lua_pushstring (L, key);
+ lua_insert (L, -2);
+ lua_rawset (L, index);
+}
+
+/** Returns true if the value is a full userdata (not light).
+*/
+inline bool isfulluserdata (lua_State* L, int index)
+{
+ return lua_isuserdata (L, index) && !lua_islightuserdata (L, index);
+}
+
+/** Test lua_State objects for global equality.
+
+ This can determine if two different lua_State objects really point
+ to the same global state, such as when using coroutines.
+
+ @note This is used for assertions.
+*/
+inline bool equalstates (lua_State* L1, lua_State* L2)
+{
+ return lua_topointer (L1, LUA_REGISTRYINDEX) ==
+ lua_topointer (L2, LUA_REGISTRYINDEX);
+}
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/LuaRef.h b/lib/LuaBridge/Source/LuaBridge/detail/LuaRef.h
new file mode 100644
index 0000000..d7ec8f7
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/LuaRef.h
@@ -0,0 +1,1034 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2018, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <LuaBridge/detail/LuaException.h>
+#include <LuaBridge/detail/Stack.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace luabridge {
+
+//------------------------------------------------------------------------------
+/**
+ Type tag for representing LUA_TNIL.
+
+ Construct one of these using `Nil ()` to represent a Lua nil. This is faster
+ than creating a reference in the registry to nil. Example:
+
+ LuaRef t (LuaRef::createTable (L));
+ ...
+ t ["k"] = Nil (); // assign nil
+*/
+struct Nil
+{
+};
+
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for Nil.
+*/
+template <>
+struct Stack <Nil>
+{
+ static void push (lua_State* L, Nil)
+ {
+ lua_pushnil (L);
+ }
+};
+
+/**
+ * Base class for LuaRef and table value proxy classes.
+ */
+template <class Impl, class LuaRef>
+class LuaRefBase
+{
+protected:
+ //----------------------------------------------------------------------------
+ /**
+ Pop the Lua stack.
+
+ Pops the specified number of stack items on destruction. We use this
+ when returning objects, to avoid an explicit temporary variable, since
+ the destructor executes after the return statement. For example:
+
+ template <class U>
+ U cast (lua_State* L)
+ {
+ StackPop p (L, 1);
+ ...
+ return U (); // dtor called after this line
+ }
+
+ @note The `StackPop` object must always be a named local variable.
+ */
+ class StackPop
+ {
+ public:
+ /** Create a StackPop object.
+
+ @param count The number of stack entries to pop on destruction.
+ */
+ StackPop (lua_State* L, int count)
+ : m_L (L)
+ , m_count (count)
+ {
+ }
+
+ ~StackPop ()
+ {
+ lua_pop (m_L, m_count);
+ }
+
+ private:
+ lua_State* m_L;
+ int m_count;
+ };
+
+ friend struct Stack <LuaRef>;
+
+ //----------------------------------------------------------------------------
+ /**
+ Type tag for stack construction.
+ */
+ struct FromStack { };
+
+ LuaRefBase (lua_State* L)
+ : m_L (L)
+ {
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to this ref.
+
+ This is used internally.
+ */
+ int createRef () const
+ {
+ impl ().push ();
+ return luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+public:
+ //----------------------------------------------------------------------------
+ /**
+ converts to a string using luas tostring function
+ */
+ std::string tostring () const
+ {
+ lua_getglobal (m_L, "tostring");
+ impl ().push ();
+ lua_call (m_L, 1, 1);
+ const char* str = lua_tostring (m_L, -1);
+ lua_pop (m_L, 1);
+ return str;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Print a text description of the value to a stream.
+
+ This is used for diagnostics.
+ */
+ void print (std::ostream& os) const
+ {
+ switch (type ())
+ {
+ case LUA_TNIL:
+ os << "nil";
+ break;
+
+ case LUA_TNUMBER:
+ os << cast <lua_Number> ();
+ break;
+
+ case LUA_TBOOLEAN:
+ os << (cast <bool> () ? "true" : "false");
+ break;
+
+ case LUA_TSTRING:
+ os << '"' << cast <std::string> () << '"';
+ break;
+
+ case LUA_TTABLE:
+ os << "table: " << tostring ();
+ break;
+
+ case LUA_TFUNCTION:
+ os << "function: " << tostring ();
+ break;
+
+ case LUA_TUSERDATA:
+ os << "userdata: " << tostring ();
+ break;
+
+ case LUA_TTHREAD:
+ os << "thread: " << tostring ();
+ break;
+
+ case LUA_TLIGHTUSERDATA:
+ os << "lightuserdata: " << tostring ();
+ break;
+
+ default:
+ os << "unknown";
+ break;
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ /**
+ Write a LuaRef to a stream.
+
+ This allows LuaRef and table proxies to work with streams.
+ */
+ friend std::ostream& operator<< (std::ostream& os, LuaRefBase const& ref)
+ {
+ ref.print (os);
+ return os;
+ }
+
+ //============================================================================
+ //
+ // This group of member functions is mirrored in Proxy
+ //
+
+ /** Retrieve the lua_State associated with the reference.
+ */
+ lua_State* state () const
+ {
+ return m_L;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Place the object onto the Lua stack.
+ */
+ void push (lua_State* L) const
+ {
+ assert (equalstates (L, m_L));
+ (void) L;
+ impl ().push ();
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Pop the top of Lua stack and assign the ref to m_ref
+ */
+ void pop (lua_State* L)
+ {
+ assert (equalstates (L, m_L));
+ (void) L;
+ impl ().pop ();
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Determine the object type.
+
+ The return values are the same as for `lua_type`.
+ */
+ /** @{ */
+ int type () const
+ {
+ impl ().push ();
+ StackPop p (m_L, 1);
+ return lua_type (m_L, -1);
+ }
+
+ // should never happen
+ // bool isNone () const { return m_ref == LUA_NOREF; }
+
+ bool isNil () const { return type () == LUA_TNIL; }
+ bool isBool () const { return type () == LUA_TBOOLEAN; }
+ bool isNumber () const { return type () == LUA_TNUMBER; }
+ bool isString () const { return type () == LUA_TSTRING; }
+ bool isTable () const { return type () == LUA_TTABLE; }
+ bool isFunction () const { return type () == LUA_TFUNCTION; }
+ bool isUserdata () const { return type () == LUA_TUSERDATA; }
+ bool isThread () const { return type () == LUA_TTHREAD; }
+ bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; }
+
+ /** @} */
+
+ //----------------------------------------------------------------------------
+ /**
+ Perform an explicit conversion.
+ */
+ template <class T>
+ T cast () const
+ {
+ StackPop p (m_L, 1);
+ impl ().push ();
+ return Stack <T>::get (m_L, -1);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Universal implicit conversion operator.
+
+ NOTE: Visual Studio 2010 and 2012 have a bug where this function
+ is not used. See:
+
+ http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014
+ https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile
+
+ // This code snippet fails to compile in vs2010,vs2012
+ struct S {
+ template <class T> operator T () const { return T (); }
+ };
+ int main () {
+ S () || false;
+ return 0;
+ }
+ */
+ template <class T>
+ operator T () const
+ {
+ return cast <T> ();
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Universal comparison operators.
+ */
+ /** @{ */
+ template <class T>
+ bool operator== (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ impl ().push ();
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1;
+ }
+
+ template <class T>
+ bool operator< (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ impl ().push ();;
+ Stack <T>::push (m_L, rhs);
+ int lhsType = lua_type (m_L, -2);
+ int rhsType = lua_type (m_L, -1);
+ if (lhsType != rhsType)
+ {
+ return lhsType < rhsType;
+ }
+ return lua_compare (m_L, -2, -1, LUA_OPLT) == 1;
+ }
+
+ template <class T>
+ bool operator<= (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ impl ().push ();;
+ Stack <T>::push (m_L, rhs);
+ int lhsType = lua_type (m_L, -2);
+ int rhsType = lua_type (m_L, -1);
+ if (lhsType != rhsType)
+ {
+ return lhsType <= rhsType;
+ }
+ return lua_compare (m_L, -2, -1, LUA_OPLE) == 1;
+ }
+
+ template <class T>
+ bool operator> (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ impl ().push ();;
+ Stack <T>::push (m_L, rhs);
+ int lhsType = lua_type (m_L, -2);
+ int rhsType = lua_type (m_L, -1);
+ if (lhsType != rhsType)
+ {
+ return lhsType > rhsType;
+ }
+ return lua_compare (m_L, -1, -2, LUA_OPLT) == 1;
+ }
+
+ template <class T>
+ bool operator>= (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ impl ().push ();;
+ Stack <T>::push (m_L, rhs);
+ int lhsType = lua_type (m_L, -2);
+ int rhsType = lua_type (m_L, -1);
+ if (lhsType != rhsType)
+ {
+ return lhsType >= rhsType;
+ }
+ return lua_compare (m_L, -1, -2, LUA_OPLE) == 1;
+ }
+
+ template <class T>
+ bool rawequal (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ impl ().push ();;
+ Stack <T>::push (m_L, rhs);
+ return lua_rawequal (m_L, -1, -2) == 1;
+ }
+ /** @} */
+
+ //----------------------------------------------------------------------------
+ /**
+ Append a value to the table.
+
+ If the table is a sequence this will add another element to it.
+ */
+ template <class T>
+ void append (T v) const
+ {
+ impl ().push ();;
+ Stack <T>::push (m_L, v);
+ luaL_ref (m_L, -2);
+ lua_pop (m_L, 1);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Call the length operator.
+
+ This is identical to applying the Lua # operator.
+ */
+ int length () const
+ {
+ StackPop p (m_L, 1);
+ impl ().push ();;
+ return get_length (m_L, -1);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Call Lua code.
+
+ These overloads allow Lua code to be called with up to 8 parameters.
+ The return value is provided as a LuaRef (which may be LUA_REFNIL).
+ If an error occurs, a LuaException is thrown.
+ */
+ /** @{ */
+ LuaRef operator() () const
+ {
+ impl ().push ();;
+ LuaException::pcall (m_L, 0, 1);
+ return LuaRef::fromStack (m_L);
+ }
+
+ template <class P1>
+ LuaRef operator() (P1 p1) const
+ {
+ impl ().push ();;
+ Stack <P1>::push (m_L, p1);
+ LuaException::pcall (m_L, 1, 1);
+ return LuaRef::fromStack (m_L);
+ }
+
+ template <class P1, class P2>
+ LuaRef operator() (P1 p1, P2 p2) const
+ {
+ impl ().push ();;
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ LuaException::pcall (m_L, 2, 1);
+ return LuaRef::fromStack (m_L);
+ }
+
+ template <class P1, class P2, class P3>
+ LuaRef operator() (P1 p1, P2 p2, P3 p3) const
+ {
+ impl ().push ();;
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ LuaException::pcall (m_L, 3, 1);
+ return LuaRef::fromStack (m_L);
+ }
+
+ template <class P1, class P2, class P3, class P4>
+ LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4) const
+ {
+ impl ().push ();;
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ LuaException::pcall (m_L, 4, 1);
+ return LuaRef::fromStack (m_L);
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5>
+ LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const
+ {
+ impl ().push ();;
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ LuaException::pcall (m_L, 5, 1);
+ return LuaRef::fromStack (m_L);
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5, class P6>
+ LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const
+ {
+ impl ().push ();;
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ Stack <P6>::push (m_L, p6);
+ LuaException::pcall (m_L, 6, 1);
+ return LuaRef::fromStack (m_L);
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5, class P6, class P7>
+ LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const
+ {
+ impl ().push ();;
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ Stack <P6>::push (m_L, p6);
+ Stack <P7>::push (m_L, p7);
+ LuaException::pcall (m_L, 7, 1);
+ return LuaRef::fromStack (m_L);
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
+ LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const
+ {
+ impl ().push ();
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ Stack <P6>::push (m_L, p6);
+ Stack <P7>::push (m_L, p7);
+ Stack <P8>::push (m_L, p8);
+ LuaException::pcall (m_L, 8, 1);
+ return LuaRef::fromStack (m_L);
+ }
+ /** @} */
+
+ //============================================================================
+
+protected:
+ lua_State* m_L;
+
+private:
+ const Impl& impl () const
+ {
+ return static_cast <const Impl&> (*this);
+ }
+
+ Impl& impl ()
+ {
+ return static_cast <Impl&> (*this);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Lightweight reference to a Lua object.
+
+ The reference is maintained for the lifetime of the C++ object.
+*/
+class LuaRef : public LuaRefBase <LuaRef, LuaRef>
+{
+ //----------------------------------------------------------------------------
+ /**
+ A proxy for representing table values.
+ */
+ class Proxy : public LuaRefBase <Proxy, LuaRef>
+ {
+ friend class LuaRef;
+
+ public:
+ //--------------------------------------------------------------------------
+ /**
+ Construct a Proxy from a table value.
+
+ The table is in the registry, and the key is at the top of the stack.
+ The key is popped off the stack.
+ */
+ Proxy (lua_State* L, int tableRef)
+ : LuaRefBase (L)
+ , m_tableRef (LUA_NOREF)
+ , m_keyRef (luaL_ref (L, LUA_REGISTRYINDEX))
+ {
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, tableRef);
+ m_tableRef = luaL_ref (L, LUA_REGISTRYINDEX);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Create a Proxy via copy constructor.
+
+ It is best to avoid code paths that invoke this, because it creates
+ an extra temporary Lua reference. Typically this is done by passing
+ the Proxy parameter as a `const` reference.
+ */
+ Proxy (Proxy const& other)
+ : LuaRefBase (other.m_L)
+ , m_tableRef (LUA_NOREF)
+ , m_keyRef (LUA_NOREF)
+ {
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_tableRef);
+ m_tableRef = luaL_ref (m_L, LUA_REGISTRYINDEX);
+
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_keyRef);
+ m_keyRef = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Destroy the proxy.
+
+ This does not destroy the table value.
+ */
+ ~Proxy ()
+ {
+ luaL_unref (m_L, LUA_REGISTRYINDEX, m_keyRef);
+ luaL_unref (m_L, LUA_REGISTRYINDEX, m_tableRef);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Assign a new value to this table key.
+
+ This may invoke metamethods.
+ */
+ template <class T>
+ Proxy& operator= (T v)
+ {
+ StackPop p (m_L, 1);
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
+ Stack <T>::push (m_L, v);
+ lua_settable (m_L, -3);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Assign a new value to this table key.
+
+ The assignment is raw, no metamethods are invoked.
+ */
+ template <class T>
+ Proxy& rawset (T v)
+ {
+ StackPop p (m_L, 1);
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
+ Stack <T>::push (m_L, v);
+ lua_rawset (m_L, -3);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Push the value onto the Lua stack.
+ */
+ using LuaRefBase::push;
+
+ void push () const
+ {
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
+ lua_gettable (m_L, -2);
+ lua_remove (m_L, -2); // remove the table
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Access a table value using a key.
+
+ This invokes metamethods.
+ */
+ template <class T>
+ Proxy operator[] (T key) const
+ {
+ return LuaRef (*this) [key];
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Access a table value using a key.
+
+ The operation is raw, metamethods are not invoked. The result is
+ passed by value and may not be modified.
+ */
+ template <class T>
+ LuaRef rawget (T key) const
+ {
+ return LuaRef (*this).rawget (key);
+ }
+
+ private:
+ int m_tableRef;
+ int m_keyRef;
+ };
+
+ friend struct Stack <Proxy>;
+ friend struct Stack <Proxy&>;
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to an object at the top of the Lua stack and pop it.
+
+ This constructor is private and not invoked directly.
+ Instead, use the `fromStack` function.
+
+ @note The object is popped.
+ */
+ LuaRef (lua_State* L, FromStack)
+ : LuaRefBase (L)
+ , m_ref (luaL_ref (m_L, LUA_REGISTRYINDEX))
+ {
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to an object on the Lua stack.
+
+ This constructor is private and not invoked directly.
+ Instead, use the `fromStack` function.
+
+ @note The object is not popped.
+ */
+ LuaRef (lua_State* L, int index, FromStack)
+ : LuaRefBase (L)
+ , m_ref (LUA_NOREF)
+ {
+ lua_pushvalue (m_L, index);
+ m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+
+public:
+ //----------------------------------------------------------------------------
+ /**
+ Create a nil reference.
+
+ The LuaRef may be assigned later.
+ */
+ LuaRef (lua_State* L)
+ : LuaRefBase (L)
+ , m_ref (LUA_NOREF)
+ {
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to a value.
+ */
+ template <class T>
+ LuaRef (lua_State* L, T v)
+ : LuaRefBase (L)
+ , m_ref (LUA_NOREF)
+ {
+ Stack <T>::push (m_L, v);
+ m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to a table value.
+ */
+ LuaRef (Proxy const& v)
+ : LuaRefBase (v.state ())
+ , m_ref (v.createRef ())
+ {
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a new reference to an existing reference.
+ */
+ LuaRef (LuaRef const& other)
+ : LuaRefBase (other.m_L)
+ , m_ref (other.createRef ())
+ {
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Destroy a reference.
+
+ The corresponding Lua registry reference will be released.
+
+ @note If the state refers to a thread, it is the responsibility of the
+ caller to ensure that the thread still exists when the LuaRef
+ is destroyed.
+ */
+ ~LuaRef ()
+ {
+ luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Return a LuaRef from a top stack item.
+
+ The stack item is not popped.
+ */
+ static LuaRef fromStack (lua_State* L)
+ {
+ return LuaRef (L, FromStack ());
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Return a LuaRef from a stack item.
+
+ The stack item is not popped.
+ */
+ static LuaRef fromStack (lua_State* L, int index)
+ {
+ lua_pushvalue (L, index);
+ return LuaRef (L, FromStack ());
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a new empty table and return a reference to it.
+
+ It is also possible to use the free function `newTable`.
+
+ @see ::luabridge::newTable
+ */
+ static LuaRef newTable (lua_State* L)
+ {
+ lua_newtable (L);
+ return LuaRef (L, FromStack ());
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Return a reference to a named global.
+
+ It is also possible to use the free function `getGlobal`.
+
+ @see ::luabridge::getGlobal
+ */
+ static LuaRef getGlobal (lua_State *L, char const* name)
+ {
+ lua_getglobal (L, name);
+ return LuaRef (L, FromStack ());
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Assign another LuaRef to this LuaRef.
+ */
+ LuaRef& operator= (LuaRef const& rhs)
+ {
+ LuaRef ref (rhs);
+ swap (ref);
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Assign Proxy to this LuaRef.
+ */
+ LuaRef& operator= (LuaRef::Proxy const& rhs)
+ {
+ LuaRef ref (rhs);
+ swap (ref);
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Assign nil to this LuaRef.
+ */
+ LuaRef& operator= (Nil const&)
+ {
+ LuaRef ref (m_L);
+ swap (ref);
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Assign a different value to this LuaRef.
+ */
+ template <class T>
+ LuaRef& operator= (T rhs)
+ {
+ LuaRef ref (m_L, rhs);
+ swap (ref);
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Place the object onto the Lua stack.
+ */
+ using LuaRefBase::push;
+
+ void push () const
+ {
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_ref);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Pop the top of Lua stack and assign the ref to m_ref
+ */
+ void pop ()
+ {
+ luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
+ m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Access a table value using a key.
+
+ This invokes metamethods.
+ */
+ template <class T>
+ Proxy operator[] (T key) const
+ {
+ Stack <T>::push (m_L, key);
+ return Proxy (m_L, m_ref);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Access a table value using a key.
+
+ The operation is raw, metamethods are not invoked. The result is
+ passed by value and may not be modified.
+ */
+ template <class T>
+ LuaRef rawget (T key) const
+ {
+ StackPop (m_L, 1);
+ push (m_L);
+ Stack <T>::push (m_L, key);
+ lua_rawget (m_L, -2);
+ return LuaRef (m_L, FromStack ());
+ }
+
+private:
+ void swap (LuaRef& other)
+ {
+ std::swap (m_L, other.m_L);
+ std::swap (m_ref, other.m_ref);
+ }
+
+ int m_ref;
+};
+
+//------------------------------------------------------------------------------
+/**
+ * Stack specialization for `LuaRef`.
+ */
+template <>
+struct Stack <LuaRef>
+{
+ // The value is const& to prevent a copy construction.
+ //
+ static void push (lua_State* L, LuaRef const& v)
+ {
+ v.push (L);
+ }
+
+ static LuaRef get (lua_State* L, int index)
+ {
+ return LuaRef::fromStack (L, index);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ * Stack specialization for `Proxy`.
+ */
+template <>
+struct Stack <LuaRef::Proxy>
+{
+ // The value is const& to prevent a copy construction.
+ //
+ static void push (lua_State* L, LuaRef::Proxy const& v)
+ {
+ v.push (L);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Create a reference to a new, empty table.
+
+ This is a syntactic abbreviation for LuaRef::newTable ().
+*/
+inline LuaRef newTable (lua_State* L)
+{
+ return LuaRef::newTable (L);
+}
+
+//------------------------------------------------------------------------------
+/**
+ Create a reference to a value in the global table.
+
+ This is a syntactic abbreviation for LuaRef::getGlobal ().
+*/
+inline LuaRef getGlobal (lua_State *L, char const* name)
+{
+ return LuaRef::getGlobal (L, name);
+}
+
+//------------------------------------------------------------------------------
+
+// more C++-like cast syntax
+//
+template <class T>
+T LuaRef_cast (LuaRef const& lr)
+{
+ return lr.cast <T> ();
+}
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/Namespace.h b/lib/LuaBridge/Source/LuaBridge/detail/Namespace.h
new file mode 100644
index 0000000..870e6e6
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/Namespace.h
@@ -0,0 +1,1224 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2019, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <LuaBridge/detail/Config.h>
+#include <LuaBridge/detail/ClassInfo.h>
+#include <LuaBridge/detail/Security.h>
+#include <LuaBridge/detail/TypeTraits.h>
+
+#include <stdexcept>
+#include <string>
+
+namespace luabridge {
+
+namespace detail {
+
+/**
+ * Base for class and namespace registration.
+ * Maintains Lua stack in the proper state.
+ * Once beginNamespace, beginClass or deriveClass is called the parent
+ * object upon its destruction may no longer clear the Lua stack.
+ * Then endNamespace or endClass is called, a new parent is created
+ * and the child transfers the responsibility for clearing stack to it.
+ * So there can be maximum one "active" registrar object.
+ */
+class Registrar
+{
+protected:
+ lua_State* const L;
+ int mutable m_stackSize;
+
+ Registrar (lua_State* L)
+ : L (L)
+ , m_stackSize (0)
+ {
+ }
+
+ Registrar (const Registrar& rhs)
+ : L (rhs.L)
+ , m_stackSize (rhs.m_stackSize)
+ {
+ rhs.m_stackSize = 0;
+ }
+
+#ifndef _MSC_VER
+ // MS compiler thinks it's the 2nd copy ctor
+ Registrar(Registrar& rhs)
+ : L (rhs.L)
+ , m_stackSize (rhs.m_stackSize)
+ {
+ rhs.m_stackSize = 0;
+ }
+#endif // ifndef _MSC_VER
+
+ Registrar& operator= (const Registrar& rhs)
+ {
+ Registrar tmp (rhs);
+ std::swap (m_stackSize, tmp.m_stackSize);
+ return *this;
+ }
+
+ ~Registrar ()
+ {
+ if (m_stackSize > 0)
+ {
+ assert (m_stackSize <= lua_gettop (L));
+ lua_pop (L, m_stackSize);
+ }
+ }
+
+ void assertIsActive () const
+ {
+ if (m_stackSize == 0)
+ {
+ throw std::logic_error ("Unable to continue registration");
+ }
+ }
+};
+
+} // namespace detail
+
+/** Provides C++ to Lua registration capabilities.
+
+ This class is not instantiated directly, call `getGlobalNamespace` to start
+ the registration process.
+*/
+class Namespace : public detail::Registrar
+{
+ //============================================================================
+ /**
+ Error reporting.
+
+ VF: This function looks handy, why aren't we using it?
+ */
+#if 0
+ static int luaError (lua_State* L, std::string message)
+ {
+ assert (lua_isstring (L, lua_upvalueindex (1)));
+ std::string s;
+
+ // Get information on the caller's caller to format the message,
+ // so the error appears to originate from the Lua source.
+ lua_Debug ar;
+ int result = lua_getstack (L, 2, &ar);
+ if (result != 0)
+ {
+ lua_getinfo (L, "Sl", &ar);
+ s = ar.short_src;
+ if (ar.currentline != -1)
+ {
+ // poor mans int to string to avoid <strstrream>.
+ lua_pushnumber (L, ar.currentline);
+ s = s + ":" + lua_tostring (L, -1) + ": ";
+ lua_pop (L, 1);
+ }
+ }
+
+ s = s + message;
+
+ return luaL_error (L, s.c_str ());
+ }
+#endif
+
+ /**
+ Factored base to reduce template instantiations.
+ */
+ class ClassBase : public detail::Registrar
+ {
+ public:
+ explicit ClassBase (Namespace& parent)
+ : Registrar (parent)
+ {
+ }
+
+ using Registrar::operator=;
+
+ protected:
+ //--------------------------------------------------------------------------
+ /**
+ Create the const table.
+ */
+ void createConstTable (const char* name, bool trueConst = true)
+ {
+ std::string type_name = std::string (trueConst ? "const " : "") + name;
+
+ // Stack: namespace table (ns)
+ lua_newtable (L); // Stack: ns, const table (co)
+ lua_pushvalue (L, -1); // Stack: ns, co, co
+ lua_setmetatable (L, -2); // co.__metatable = co. Stack: ns, co
+
+ lua_pushstring (L, type_name.c_str ());
+ lua_rawsetp (L, -2, getTypeKey ()); // co [typeKey] = name. Stack: ns, co
+
+ lua_pushcfunction (L, &CFunc::indexMetaMethod);
+ rawsetfield (L, -2, "__index");
+
+ lua_pushcfunction (L, &CFunc::newindexObjectMetaMethod);
+ rawsetfield (L, -2, "__newindex");
+
+ lua_newtable (L);
+ lua_rawsetp (L, -2, getPropgetKey ());
+
+ if (Security::hideMetatables ())
+ {
+ lua_pushnil (L);
+ rawsetfield (L, -2, "__metatable");
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Create the class table.
+
+ The Lua stack should have the const table on top.
+ */
+ void createClassTable (char const* name)
+ {
+ // Stack: namespace table (ns), const table (co)
+
+ // Class table is the same as const table except the propset table
+ createConstTable (name, false); // Stack: ns, co, cl
+
+ lua_newtable (L); // Stack: ns, co, cl, propset table (ps)
+ lua_rawsetp (L, -2, getPropsetKey ()); // cl [propsetKey] = ps. Stack: ns, co, cl
+
+ lua_pushvalue (L, -2); // Stack: ns, co, cl, co
+ lua_rawsetp(L, -2, getConstKey ()); // cl [constKey] = co. Stack: ns, co, cl
+
+ lua_pushvalue (L, -1); // Stack: ns, co, cl, cl
+ lua_rawsetp (L, -3, getClassKey ()); // co [classKey] = cl. Stack: ns, co, cl
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Create the static table.
+ */
+ void createStaticTable (char const* name)
+ {
+ // Stack: namespace table (ns), const table (co), class table (cl)
+ lua_newtable (L); // Stack: ns, co, cl, visible static table (vst)
+ lua_newtable (L); // Stack: ns, co, cl, st, static metatable (st)
+ lua_pushvalue (L, -1); // Stack: ns, co, cl, vst, st, st
+ lua_setmetatable (L, -3); // st.__metatable = mt. Stack: ns, co, cl, vst, st
+ lua_insert (L, -2); // Stack: ns, co, cl, st, vst
+ rawsetfield (L, -5, name); // ns [name] = vst. Stack: ns, co, cl, st
+
+#if 0
+ lua_pushlightuserdata (L, this);
+ lua_pushcclosure (L, &tostringMetaMethod, 1);
+ rawsetfield (L, -2, "__tostring");
+#endif
+ lua_pushcfunction (L, &CFunc::indexMetaMethod);
+ rawsetfield (L, -2, "__index");
+
+ lua_pushcfunction (L, &CFunc::newindexStaticMetaMethod);
+ rawsetfield (L, -2, "__newindex");
+
+ lua_newtable (L); // Stack: ns, co, cl, st, proget table (pg)
+ lua_rawsetp (L, -2, getPropgetKey ()); // st [propgetKey] = pg. Stack: ns, co, cl, st
+
+ lua_newtable (L); // Stack: ns, co, cl, st, propset table (ps)
+ lua_rawsetp (L, -2, getPropsetKey ()); // st [propsetKey] = pg. Stack: ns, co, cl, st
+
+ lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl
+ lua_rawsetp(L, -2, getClassKey()); // st [classKey] = cl. Stack: ns, co, cl, st
+
+ if (Security::hideMetatables ())
+ {
+ lua_pushnil (L);
+ rawsetfield (L, -2, "__metatable");
+ }
+ }
+
+ //==========================================================================
+ /**
+ lua_CFunction to construct a class object wrapped in a container.
+ */
+ template <class Params, class C>
+ static int ctorContainerProxy (lua_State* L)
+ {
+ typedef typename ContainerTraits <C>::Type T;
+ ArgList <Params, 2> args (L);
+ T* const p = Constructor <T, Params>::call (args);
+ UserdataSharedHelper <C, false>::push (L, p);
+ return 1;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to construct a class object in-place in the userdata.
+ */
+ template <class Params, class T>
+ static int ctorPlacementProxy (lua_State* L)
+ {
+ ArgList <Params, 2> args (L);
+ Constructor <T, Params>::call (UserdataValue <T>::place (L), args);
+ return 1;
+ }
+
+ void assertStackState () const
+ {
+ // Stack: const table (co), class table (cl), static table (st)
+ assert (lua_istable (L, -3));
+ assert (lua_istable (L, -2));
+ assert (lua_istable (L, -1));
+ }
+ };
+
+ //============================================================================
+ //
+ // Class
+ //
+ //============================================================================
+ /**
+ Provides a class registration in a lua_State.
+
+ After construction the Lua stack holds these objects:
+ -1 static table
+ -2 class table
+ -3 const table
+ -4 enclosing namespace table
+ */
+ template <class T>
+ class Class : public ClassBase
+ {
+ public:
+ //==========================================================================
+ /**
+ Register a new class or add to an existing class registration.
+ */
+ Class (char const* name, Namespace& parent)
+ : ClassBase (parent)
+ {
+ assert (lua_istable (L, -1)); // Stack: namespace table (ns)
+ rawgetfield (L, -1, name); // Stack: ns, static table (st) | nil
+
+ if (lua_isnil (L, -1)) // Stack: ns, nil
+ {
+ lua_pop (L, 1); // Stack: ns
+
+ createConstTable (name); // Stack: ns, const table (co)
+ lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, function
+ rawsetfield (L, -2, "__gc"); // Stack: ns, co
+ ++m_stackSize;
+
+ createClassTable (name); // Stack: ns, co, class table (cl)
+ lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, cl, function
+ rawsetfield (L, -2, "__gc"); // Stack: ns, co, cl
+ ++m_stackSize;
+
+ createStaticTable (name); // Stack: ns, co, cl, st
+ ++m_stackSize;
+
+ // Map T back to its tables.
+ lua_pushvalue (L, -1); // Stack: ns, co, cl, st, st
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ()); // Stack: ns, co, cl, st
+ lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); // Stack: ns, co, cl, st
+ lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); // Stack: ns, co, cl, st
+ }
+ else
+ {
+ assert (lua_istable (L, -1)); // Stack: ns, st
+ ++m_stackSize;
+
+ // Map T back from its stored tables
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); // Stack: ns, st, co
+ lua_insert (L, -2); // Stack: ns, co, st
+ ++m_stackSize;
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); // Stack: ns, co, st, cl
+ lua_insert (L, -2); // Stack: ns, co, cl, st
+ ++m_stackSize;
+ }
+ }
+
+ //==========================================================================
+ /**
+ Derive a new class.
+ */
+ Class (char const* name, Namespace& parent, void const* const staticKey)
+ : ClassBase (parent)
+ {
+ assert (lua_istable (L, -1)); // Stack: namespace table (ns)
+
+ createConstTable (name); // Stack: ns, const table (co)
+ lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, function
+ rawsetfield (L, -2, "__gc"); // Stack: ns, co
+ ++m_stackSize;
+
+ createClassTable (name); // Stack: ns, co, class table (cl)
+ lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, cl, function
+ rawsetfield (L, -2, "__gc"); // Stack: ns, co, cl
+ ++m_stackSize;
+
+ createStaticTable (name); // Stack: ns, co, cl, st
+ ++m_stackSize;
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey); // Stack: ns, co, cl, st, parent st (pst) | nil
+ if (lua_isnil (L, -1)) // Stack: ns, co, cl, st, nil
+ {
+ ++m_stackSize;
+ throw std::runtime_error ("Base class is not registered");
+ }
+
+ assert (lua_istable (L, -1)); // Stack: ns, co, cl, st, pst
+
+ lua_rawgetp (L, -1, getClassKey ()); // Stack: ns, co, cl, st, pst, parent cl (pcl)
+ assert (lua_istable (L, -1));
+
+ lua_rawgetp (L, -1, getConstKey ()); // Stack: ns, co, cl, st, pst, pcl, parent co (pco)
+ assert (lua_istable (L, -1));
+
+ lua_rawsetp (L, -6, getParentKey ()); // co [parentKey] = pco. Stack: ns, co, cl, st, pst, pcl
+ lua_rawsetp (L, -4, getParentKey ()); // cl [parentKey] = pcl. Stack: ns, co, cl, st, pst
+ lua_rawsetp (L, -2, getParentKey ()); // st [parentKey] = pst. Stack: ns, co, cl, st
+
+ lua_pushvalue (L, -1); // Stack: ns, co, cl, st, st
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ()); // Stack: ns, co, cl, st
+ lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); // Stack: ns, co, cl, st
+ lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); // Stack: ns, co, cl, st
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Continue registration in the enclosing namespace.
+ */
+ Namespace endClass ()
+ {
+ assert (m_stackSize > 3);
+ m_stackSize -= 3;
+ lua_pop (L, 3);
+ return Namespace (*this);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a static data member.
+ */
+ template <class U>
+ Class <T>& addStaticProperty (char const* name, U* pu, bool isWritable = true)
+ {
+ return addStaticData (name, pu, isWritable);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a static data member.
+ */
+ template <class U>
+ Class <T>& addStaticData (char const* name, U* pu, bool isWritable = true)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ lua_pushlightuserdata (L, pu); // Stack: co, cl, st, pointer
+ lua_pushcclosure (L, &CFunc::getVariable <U>, 1); // Stack: co, cl, st, getter
+ CFunc::addGetter (L, name, -2); // Stack: co, cl, st
+
+ if (isWritable)
+ {
+ lua_pushlightuserdata (L, pu); // Stack: co, cl, st, ps, pointer
+ lua_pushcclosure (L, &CFunc::setVariable <U>, 1); // Stack: co, cl, st, ps, setter
+ }
+ else
+ {
+ lua_pushstring (L, name); // Stack: co, cl, st, name
+ lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: co, cl, st, error_fn
+ }
+ CFunc::addSetter (L, name, -2); // Stack: co, cl, st
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a static property member.
+
+ If the set function is null, the property is read-only.
+ */
+ template <class U>
+ Class <T>& addStaticProperty (char const* name, U (*get) (), void (*set) (U) = 0)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ lua_pushlightuserdata (L, reinterpret_cast <void*> (get)); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::Call <U (*) ()>::f, 1); // Stack: co, cl, st, getter
+ CFunc::addGetter (L, name, -2); // Stack: co, cl, st
+
+ if (set != 0)
+ {
+ lua_pushlightuserdata (L, reinterpret_cast <void*> (set)); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::Call <void (*) (U)>::f, 1); // Stack: co, cl, st, setter
+ }
+ else
+ {
+ lua_pushstring (L, name); // Stack: co, cl, st, ps, name
+ lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: co, cl, st, error_fn
+ }
+ CFunc::addSetter (L, name, -2); // Stack: co, cl, st
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a static member function.
+ */
+ template <class FP>
+ Class <T>& addStaticFunction (char const* name, FP const fp)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ lua_pushlightuserdata (L, reinterpret_cast <void*> (fp)); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::Call <FP>::f, 1); // co, cl, st, function
+ rawsetfield (L, -2, name); // co, cl, st
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a lua_CFunction.
+ */
+ Class <T>& addStaticFunction (char const* name, int (*const fp) (lua_State*))
+ {
+ return addStaticCFunction (name, fp);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a lua_CFunction.
+ */
+ Class <T>& addStaticCFunction (char const* name, int (*const fp) (lua_State*))
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ lua_pushcfunction (L, fp); // co, cl, st, function
+ rawsetfield (L, -2, name); // co, cl, st
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a data member.
+ */
+ template <class U>
+ Class <T>& addProperty (char const* name, U T::* mp, bool isWritable = true)
+ {
+ return addData (name, mp, isWritable);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a data member.
+ */
+ template <class U>
+ Class <T>& addData (char const* name, U T::* mp, bool isWritable = true)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ typedef const U T::*mp_t;
+ new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); // Stack: co, cl, st, field ptr
+ lua_pushcclosure (L, &CFunc::getProperty <T, U>, 1); // Stack: co, cl, st, getter
+ lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
+ CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
+ CFunc::addGetter (L, name, -3); // Stack: co, cl, st
+
+ if (isWritable)
+ {
+ new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); // Stack: co, cl, st, field ptr
+ lua_pushcclosure (L, &CFunc::setProperty <T, U>, 1); // Stack: co, cl, st, setter
+ CFunc::addSetter (L, name, -3); // Stack: co, cl, st
+ }
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a property member.
+ */
+ template <class TG, class TS = TG>
+ Class <T>& addProperty (char const* name, TG (T::* get) () const, void (T::* set) (TS) = 0)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ typedef TG (T::*get_t) () const;
+ new (lua_newuserdata (L, sizeof (get_t))) get_t (get); // Stack: co, cl, st, funcion ptr
+ lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1); // Stack: co, cl, st, getter
+ lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
+ CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
+ CFunc::addGetter (L, name, -3); // Stack: co, cl, st
+
+ if (set != 0)
+ {
+ typedef void (T::* set_t) (TS);
+ new (lua_newuserdata (L, sizeof (set_t))) set_t (set); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1); // Stack: co, cl, st, setter
+ CFunc::addSetter (L, name, -3); // Stack: co, cl, st
+ }
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a property member.
+ */
+ template <class TG, class TS = TG>
+ Class <T>& addProperty (char const* name, TG (T::* get) (lua_State*) const, void (T::* set) (TS, lua_State*) = 0)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ typedef TG (T::*get_t) (lua_State*) const;
+ new (lua_newuserdata (L, sizeof (get_t))) get_t (get); // Stack: co, cl, st, funcion ptr
+ lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1); // Stack: co, cl, st, getter
+ lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
+ CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
+ CFunc::addGetter (L, name, -3); // Stack: co, cl, st
+
+ if (set != 0)
+ {
+ typedef void (T::* set_t) (TS, lua_State*);
+ new (lua_newuserdata (L, sizeof (set_t))) set_t (set); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1); // Stack: co, cl, st, setter
+ CFunc::addSetter (L, name, -3); // Stack: co, cl, st
+ }
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a property member, by proxy.
+
+ When a class is closed for modification and does not provide (or cannot
+ provide) the function signatures necessary to implement get or set for
+ a property, this will allow non-member functions act as proxies.
+
+ Both the get and the set functions require a T const* and T* in the first
+ argument respectively.
+ */
+ template <class TG, class TS = TG>
+ Class <T>& addProperty (char const* name, TG (*get) (T const*), void (*set) (T*, TS) = 0)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ lua_pushlightuserdata (L, reinterpret_cast <void*> (get)); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::Call <TG (*) (const T*)>::f, 1); // Stack: co, cl, st, getter
+ lua_pushvalue (L, -1); // Stack: co, cl, st,, getter, getter
+ CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
+ CFunc::addGetter (L, name, -3); // Stack: co, cl, st
+
+ if (set != 0)
+ {
+ lua_pushlightuserdata (L, reinterpret_cast <void*> (set)); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::Call <void (*) (T*, TS)>::f, 1); // Stack: co, cl, st, setter
+ CFunc::addSetter (L, name, -3); // Stack: co, cl, st
+ }
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a property member, by proxy C-function.
+
+ When a class is closed for modification and does not provide (or cannot
+ provide) the function signatures necessary to implement get or set for
+ a property, this will allow non-member functions act as proxies.
+
+ The object userdata ('this') value is at the index 1.
+ The new value for set function is at the index 2.
+ */
+ Class <T>& addProperty (char const* name, int (*get) (lua_State*), int (*set) (lua_State*) = 0)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ lua_pushcfunction (L, get);
+ lua_pushvalue (L, -1); // Stack: co, cl, st,, getter, getter
+ CFunc::addGetter (L, name, -5); // Stack: co, cl, st,, getter
+ CFunc::addGetter (L, name, -3); // Stack: co, cl, st,
+
+ if (set != 0)
+ {
+ lua_pushcfunction (L, set);
+ CFunc::addSetter (L, name, -3); // Stack: co, cl, st,
+ }
+
+ return *this;
+ }
+
+#ifdef LUABRIDGE_CXX11
+ template <class TG, class TS = TG>
+ Class <T>& addProperty (char const* name,
+ std::function <TG (const T*)> get,
+ std::function <void (T*, TS)> set = nullptr)
+ {
+ using GetType = decltype (get);
+ new (lua_newuserdata (L, sizeof (get))) GetType (std::move (get)); // Stack: co, cl, st, function userdata (ud)
+ lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
+ lua_pushcfunction (L, &CFunc::gcMetaMethodAny <GetType>); // Stack: co, cl, st, ud, mt, gc function
+ rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
+ lua_setmetatable (L, -2); // Stack: co, cl, st, ud
+ lua_pushcclosure (L, &CFunc::CallProxyFunctor <GetType>::f, 1); // Stack: co, cl, st, getter
+ lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
+ CFunc::addGetter (L, name, -4); // Stack: co, cl, st, getter
+ CFunc::addGetter (L, name, -4); // Stack: co, cl, st
+
+ if (set != nullptr)
+ {
+ using SetType = decltype (set);
+ new (lua_newuserdata (L, sizeof (set))) SetType (std::move (set)); // Stack: co, cl, st, function userdata (ud)
+ lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
+ lua_pushcfunction (L, &CFunc::gcMetaMethodAny <SetType>); // Stack: co, cl, st, ud, mt, gc function
+ rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
+ lua_setmetatable (L, -2); // Stack: co, cl, st, ud
+ lua_pushcclosure (L, &CFunc::CallProxyFunctor <SetType>::f, 1); // Stack: co, cl, st, setter
+ CFunc::addSetter (L, name, -3); // Stack: co, cl, st
+ }
+
+ return *this;
+ }
+
+#endif // LUABRIDGE_CXX11
+
+#ifndef LUABRIDGE_CXX11
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a member function.
+ */
+ template <class MemFn>
+ Class <T>& addFunction (char const* name, MemFn mf)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ static const std::string GC = "__gc";
+ if (name == GC)
+ {
+ throw std::logic_error (GC + " metamethod registration is forbidden");
+ }
+ CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
+ return *this;
+ }
+
+#else // ifndef LUABRIDGE_CXX11
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a member function by std::function.
+ */
+ template <class ReturnType, class... Params>
+ Class <T>& addFunction (char const* name, std::function <ReturnType (T*, Params...)> function)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ using FnType = decltype (function);
+ new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: co, cl, st, function userdata (ud)
+ lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
+ lua_pushcfunction (L, &CFunc::gcMetaMethodAny <FnType>); // Stack: co, cl, st, ud, mt, gc function
+ rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
+ lua_setmetatable (L, -2); // Stack: co, cl, st, ud
+ lua_pushcclosure (L, &CFunc::CallProxyFunctor <FnType>::f, 1); // Stack: co, cl, st, function
+ rawsetfield (L, -3, name); // Stack: co, cl, st
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a const member function by std::function.
+ */
+ template <class ReturnType, class... Params>
+ Class <T>& addFunction (char const* name, std::function <ReturnType (const T*, Params...)> function)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ using FnType = decltype (function);
+ new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: co, cl, st, function userdata (ud)
+ lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
+ lua_pushcfunction (L, &CFunc::gcMetaMethodAny <FnType>); // Stack: co, cl, st, ud, mt, gc function
+ rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
+ lua_setmetatable (L, -2); // Stack: co, cl, st, ud
+ lua_pushcclosure (L, &CFunc::CallProxyFunctor <FnType>::f, 1); // Stack: co, cl, st, function
+ lua_pushvalue (L, -1); // Stack: co, cl, st, function, function
+ rawsetfield (L, -4, name); // Stack: co, cl, st, function
+ rawsetfield (L, -4, name); // Stack: co, cl, st
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a member function.
+ */
+ template <class ReturnType, class... Params>
+ Class <T>& addFunction (char const* name, ReturnType (T::* mf) (Params...))
+ {
+ using MemFn = ReturnType (T::*) (Params...);
+
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ static const std::string GC = "__gc";
+ if (name == GC)
+ {
+ throw std::logic_error (GC + " metamethod registration is forbidden");
+ }
+ CFunc::CallMemberFunctionHelper <MemFn, false>::add (L, name, mf);
+ return *this;
+ }
+
+ template <class ReturnType, class... Params>
+ Class <T>& addFunction (char const* name, ReturnType (T::* mf) (Params...) const)
+ {
+ using MemFn = ReturnType (T::*) (Params...) const;
+
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ static const std::string GC = "__gc";
+ if (name == GC)
+ {
+ throw std::logic_error (GC + " metamethod registration is forbidden");
+ }
+ CFunc::CallMemberFunctionHelper <MemFn, true>::add (L, name, mf);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a proxy function.
+ */
+ template <class ReturnType, class... Params>
+ Class <T>& addFunction (char const* name, ReturnType (*proxyFn) (T* object, Params...))
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ static const std::string GC = "__gc";
+ if (name == GC)
+ {
+ throw std::logic_error (GC + " metamethod registration is forbidden");
+ }
+ using FnType = decltype (proxyFn);
+ lua_pushlightuserdata (L, reinterpret_cast <void*> (proxyFn)); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::CallProxyFunction <FnType>::f, 1); // Stack: co, cl, st, function
+ rawsetfield (L, -3, name); // Stack: co, cl, st
+ return *this;
+ }
+
+ template <class ReturnType, class... Params>
+ Class <T>& addFunction (char const* name, ReturnType (*proxyFn) (const T* object, Params...))
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ static const std::string GC = "__gc";
+ if (name == GC)
+ {
+ throw std::logic_error (GC + " metamethod registration is forbidden");
+ }
+ using FnType = decltype (proxyFn);
+ lua_pushlightuserdata (L, reinterpret_cast <void*> (proxyFn)); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::CallProxyFunction <FnType>::f, 1); // Stack: co, cl, st, function
+ lua_pushvalue (L, -1); // Stack: co, cl, st, function, function
+ rawsetfield (L, -4, name); // Stack: co, cl, st, function
+ rawsetfield (L, -4, name); // Stack: co, cl, st
+ return *this;
+ }
+
+#endif
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a member lua_CFunction.
+ */
+ Class <T>& addFunction (char const* name, int (T::*mfp) (lua_State*))
+ {
+ return addCFunction (name, mfp);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a member lua_CFunction.
+ */
+ Class <T>& addCFunction (char const* name, int (T::*mfp) (lua_State*))
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ typedef int (T::*MFP) (lua_State*);
+ new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp); // Stack: co, cl, st, function ptr
+ lua_pushcclosure (L, &CFunc::CallMemberCFunction <T>::f, 1); // Stack: co, cl, st, function
+ rawsetfield (L, -3, name); // Stack: co, cl, st
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a const member lua_CFunction.
+ */
+ Class <T>& addFunction (char const* name, int (T::*mfp) (lua_State*) const)
+ {
+ return addCFunction (name, mfp);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a const member lua_CFunction.
+ */
+ Class <T>& addCFunction (char const* name, int (T::*mfp) (lua_State*) const)
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ typedef int (T::*MFP) (lua_State*) const;
+ new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
+ lua_pushcclosure (L, &CFunc::CallConstMemberCFunction <T>::f, 1);
+ lua_pushvalue (L, -1); // Stack: co, cl, st, function, function
+ rawsetfield (L, -4, name); // Stack: co, cl, st, function
+ rawsetfield (L, -4, name); // Stack: co, cl, st
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a primary Constructor.
+
+ The primary Constructor is invoked when calling the class type table
+ like a function.
+
+ The template parameter should be a function pointer type that matches
+ the desired Constructor (since you can't take the address of a Constructor
+ and pass it as an argument).
+ */
+ template <class MemFn, class C>
+ Class <T>& addConstructor ()
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ lua_pushcclosure (L, &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0);
+ rawsetfield (L, -2, "__call");
+
+ return *this;
+ }
+
+ template <class MemFn>
+ Class <T>& addConstructor ()
+ {
+ assertStackState (); // Stack: const table (co), class table (cl), static table (st)
+
+ lua_pushcclosure (L, &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0);
+ rawsetfield (L, -2, "__call");
+
+ return *this;
+ }
+ };
+
+private:
+ //----------------------------------------------------------------------------
+ /**
+ Open the global namespace for registrations.
+ */
+ explicit Namespace (lua_State* L)
+ : Registrar (L)
+ {
+ lua_getglobal (L, "_G");
+ ++m_stackSize;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Open a namespace for registrations.
+
+ The namespace is created if it doesn't already exist.
+ The parent namespace is at the top of the Lua stack.
+ */
+ Namespace (char const* name, Namespace& parent)
+ : Registrar (parent)
+ {
+ assert (lua_istable (L, -1)); // Stack: parent namespace (pns)
+
+ rawgetfield (L, -1, name); // Stack: pns, namespace (ns) | nil
+
+ if (lua_isnil (L, -1)) // Stack: pns, nil
+ {
+ lua_pop (L, 1); // Stack: pns
+
+ lua_newtable (L); // Stack: pns, ns
+ lua_pushvalue (L, -1); // Stack: pns, ns, ns
+
+ // na.__metatable = ns
+ lua_setmetatable (L, -2); // Stack: pns, ns
+
+ // ns.__index = indexMetaMethod
+ lua_pushcfunction (L, &CFunc::indexMetaMethod);
+ rawsetfield (L, -2, "__index"); // Stack: pns, ns
+
+ // ns.__newindex = newindexMetaMethod
+ lua_pushcfunction (L, &CFunc::newindexStaticMetaMethod);
+ rawsetfield (L, -2, "__newindex"); // Stack: pns, ns
+
+ lua_newtable (L); // Stack: pns, ns, propget table (pg)
+ lua_rawsetp (L, -2, getPropgetKey ()); // ns [propgetKey] = pg. Stack: pns, ns
+
+ lua_newtable (L); // Stack: pns, ns, propset table (ps)
+ lua_rawsetp (L, -2, getPropsetKey ()); // ns [propsetKey] = ps. Stack: pns, ns
+
+ // pns [name] = ns
+ lua_pushvalue (L, -1); // Stack: pns, ns, ns
+ rawsetfield (L, -3, name); // Stack: pns, ns
+#if 0
+ lua_pushcfunction (L, &tostringMetaMethod);
+ rawsetfield (L, -2, "__tostring");
+#endif
+ }
+
+ ++m_stackSize;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Close the class and continue the namespace registrations.
+ */
+ explicit Namespace (ClassBase& child)
+ : Registrar (child)
+ {
+ }
+
+ using Registrar::operator=;
+
+ static int throwAtPanic (lua_State* L)
+ {
+ throw std::runtime_error (lua_tostring (L, 1));
+ }
+
+public:
+ //----------------------------------------------------------------------------
+ /**
+ Open the global namespace.
+ */
+ static Namespace getGlobalNamespace (lua_State* L)
+ {
+ lua_atpanic (L, throwAtPanic);
+ return Namespace (L);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Open a new or existing namespace for registrations.
+ */
+ Namespace beginNamespace (char const* name)
+ {
+ assertIsActive ();
+ return Namespace (name, *this);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Continue namespace registration in the parent.
+
+ Do not use this on the global namespace.
+ */
+ Namespace endNamespace ()
+ {
+ if (m_stackSize == 1)
+ {
+ throw std::logic_error ("endNamespace () called on global namespace");
+ }
+
+ assert (m_stackSize > 1);
+ --m_stackSize;
+ lua_pop (L, 1);
+ return Namespace (*this);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a variable.
+ */
+ template <class T>
+ Namespace& addProperty (char const* name, T* pt, bool isWritable = true)
+ {
+ return addVariable (name, pt, isWritable);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a variable.
+ */
+ template <class T>
+ Namespace& addVariable (char const* name, T* pt, bool isWritable = true)
+ {
+ if (m_stackSize == 1)
+ {
+ throw std::logic_error ("addProperty () called on global namespace");
+ }
+
+ assert (lua_istable (L, -1)); // Stack: namespace table (ns)
+
+ lua_pushlightuserdata (L, pt); // Stack: ns, pointer
+ lua_pushcclosure (L, &CFunc::getVariable <T>, 1); // Stack: ns, getter
+ CFunc::addGetter (L, name, -2); // Stack: ns
+
+ if (isWritable)
+ {
+ lua_pushlightuserdata (L, pt); // Stack: ns, pointer
+ lua_pushcclosure (L, &CFunc::setVariable <T>, 1); // Stack: ns, setter
+ }
+ else
+ {
+ lua_pushstring (L, name); // Stack: ns, ps, name
+ lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: ns, error_fn
+ }
+ CFunc::addSetter (L, name, -2); // Stack: ns
+
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a property.
+
+ If the set function is omitted or null, the property is read-only.
+ */
+ template <class TG, class TS = TG>
+ Namespace& addProperty (char const* name, TG (*get) (), void (*set) (TS) = 0)
+ {
+ if (m_stackSize == 1)
+ {
+ throw std::logic_error ("addProperty () called on global namespace");
+ }
+
+ assert (lua_istable (L, -1)); // Stack: namespace table (ns)
+
+ lua_pushlightuserdata (L, reinterpret_cast <void*> (get)); // Stack: ns, function ptr
+ lua_pushcclosure (L, &CFunc::Call <TG (*) ()>::f, 1); // Stack: ns, getter
+ CFunc::addGetter (L, name, -2);
+
+ if (set != 0)
+ {
+ lua_pushlightuserdata(L, reinterpret_cast <void*> (set)); // Stack: ns, function ptr
+ lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1);
+ }
+ else
+ {
+ lua_pushstring (L, name);
+ lua_pushcclosure (L, &CFunc::readOnlyError, 1);
+ }
+ CFunc::addSetter (L, name, -2);
+
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a free function.
+ */
+ template <class FP>
+ Namespace& addFunction (char const* name, FP const fp)
+ {
+ assert (lua_istable (L, -1)); // Stack: namespace table (ns)
+
+ lua_pushlightuserdata (L, reinterpret_cast <void*> (fp)); // Stack: ns, function ptr
+ lua_pushcclosure (L, &CFunc::Call <FP>::f, 1); // Stack: ns, function
+ rawsetfield (L, -2, name); // Stack: ns
+
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a lua_CFunction.
+ */
+ Namespace& addFunction (char const* name, int (*const fp) (lua_State*))
+ {
+ return addCFunction (name, fp);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a lua_CFunction.
+ */
+ Namespace& addCFunction (char const* name, int (*const fp) (lua_State*))
+ {
+ assert (lua_istable (L, -1)); // Stack: namespace table (ns)
+
+ lua_pushcfunction (L, fp); // Stack: ns, function
+ rawsetfield (L, -2, name); // Stack: ns
+
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Open a new or existing class for registrations.
+ */
+ template <class T>
+ Class <T> beginClass (char const* name)
+ {
+ assertIsActive ();
+ return Class <T> (name, *this);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Derive a new class for registrations.
+
+ To continue registrations for the class later, use beginClass ().
+ Do not call deriveClass () again.
+ */
+ template <class Derived, class Base>
+ Class <Derived> deriveClass (char const* name)
+ {
+ assertIsActive ();
+ return Class <Derived> (name, *this, ClassInfo <Base>::getStaticKey ());
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Retrieve the global namespace.
+
+ It is recommended to put your namespace inside the global namespace, and
+ then add your classes and functions to it, rather than adding many classes
+ and functions directly to the global namespace.
+*/
+inline Namespace getGlobalNamespace (lua_State* L)
+{
+ return Namespace::getGlobalNamespace (L);
+}
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/Security.h b/lib/LuaBridge/Source/LuaBridge/detail/Security.h
new file mode 100644
index 0000000..ae5053e
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/Security.h
@@ -0,0 +1,72 @@
+#pragma once
+
+namespace luabridge {
+
+//------------------------------------------------------------------------------
+/**
+security options.
+*/
+class Security
+{
+public:
+ static bool hideMetatables()
+ {
+ return getSettings().hideMetatables;
+ }
+
+ static void setHideMetatables(bool shouldHide)
+ {
+ getSettings().hideMetatables = shouldHide;
+ }
+
+private:
+ struct Settings
+ {
+ Settings() : hideMetatables(true)
+ {
+ }
+
+ bool hideMetatables;
+ };
+
+ static Settings& getSettings()
+ {
+ static Settings settings;
+ return settings;
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+Push an object onto the Lua stack.
+*/
+template <class T>
+inline void push(lua_State* L, T t)
+{
+ Stack <T>::push(L, t);
+}
+
+//------------------------------------------------------------------------------
+/**
+Set a global value in the lua_State.
+
+@note This works on any type specialized by `Stack`, including `LuaRef` and
+its table proxies.
+*/
+template <class T>
+inline void setGlobal(lua_State* L, T t, char const* name)
+{
+ push(L, t);
+ lua_setglobal(L, name);
+}
+
+//------------------------------------------------------------------------------
+/**
+Change whether or not metatables are hidden (on by default).
+*/
+inline void setHideMetatables(bool shouldHide)
+{
+ Security::setHideMetatables(shouldHide);
+}
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/Stack.h b/lib/LuaBridge/Source/LuaBridge/detail/Stack.h
new file mode 100644
index 0000000..567f059
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/Stack.h
@@ -0,0 +1,489 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2019, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <LuaBridge/detail/LuaHelpers.h>
+#include <LuaBridge/detail/Userdata.h>
+
+#include <string>
+
+namespace luabridge {
+
+template <class T>
+struct Stack;
+
+template <>
+struct Stack <void>
+{
+ static void push ()
+ {
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Receive the lua_State* as an argument.
+*/
+template <>
+struct Stack <lua_State*>
+{
+ static lua_State* get (lua_State* L, int)
+ {
+ return L;
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Push a lua_CFunction.
+*/
+template <>
+struct Stack <lua_CFunction>
+{
+ static void push (lua_State* L, lua_CFunction f)
+ {
+ lua_pushcfunction (L, f);
+ }
+
+ static lua_CFunction get (lua_State* L, int index)
+ {
+ return lua_tocfunction (L, index);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `int`.
+*/
+template <>
+struct Stack <int>
+{
+ static void push (lua_State* L, int value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static int get (lua_State* L, int index)
+ {
+ return static_cast <int> (luaL_checkinteger (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `unsigned int`.
+*/
+template <>
+struct Stack <unsigned int>
+{
+ static void push (lua_State* L, unsigned int value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static unsigned int get (lua_State* L, int index)
+ {
+ return static_cast <unsigned int> (luaL_checkinteger (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `unsigned char`.
+*/
+template <>
+struct Stack <unsigned char>
+{
+ static void push (lua_State* L, unsigned char value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static unsigned char get (lua_State* L, int index)
+ {
+ return static_cast <unsigned char> (luaL_checkinteger (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `short`.
+*/
+template <>
+struct Stack <short>
+{
+ static void push (lua_State* L, short value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static short get (lua_State* L, int index)
+ {
+ return static_cast <short> (luaL_checkinteger (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `unsigned short`.
+*/
+template <>
+struct Stack <unsigned short>
+{
+ static void push (lua_State* L, unsigned short value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static unsigned short get (lua_State* L, int index)
+ {
+ return static_cast <unsigned short> (luaL_checkinteger (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `long`.
+*/
+template <>
+struct Stack <long>
+{
+ static void push (lua_State* L, long value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static long get (lua_State* L, int index)
+ {
+ return static_cast <long> (luaL_checkinteger (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `unsigned long`.
+*/
+template <>
+struct Stack <unsigned long>
+{
+ static void push (lua_State* L, unsigned long value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static unsigned long get (lua_State* L, int index)
+ {
+ return static_cast <unsigned long> (luaL_checkinteger (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ * Stack specialization for `long long`.
+ */
+template <>
+struct Stack <long long>
+{
+ static void push (lua_State* L, long long value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+ static long long get (lua_State* L, int index)
+ {
+ return static_cast <long long> (luaL_checkinteger (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ * Stack specialization for `unsigned long long`.
+ */
+template <>
+struct Stack <unsigned long long>
+{
+ static void push (lua_State* L, unsigned long long value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+ static unsigned long long get (lua_State* L, int index)
+ {
+ return static_cast <unsigned long long> (luaL_checkinteger (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `float`.
+*/
+template <>
+struct Stack <float>
+{
+ static void push (lua_State* L, float value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static float get (lua_State* L, int index)
+ {
+ return static_cast <float> (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `double`.
+*/
+template <>
+struct Stack <double>
+{
+ static void push (lua_State* L, double value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static double get (lua_State* L, int index)
+ {
+ return static_cast <double> (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `bool`.
+*/
+template <>
+struct Stack <bool>
+{
+ static void push (lua_State* L, bool value)
+ {
+ lua_pushboolean (L, value ? 1 : 0);
+ }
+
+ static bool get (lua_State* L, int index)
+ {
+ return lua_toboolean (L, index) ? true : false;
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `char`.
+*/
+template <>
+struct Stack <char>
+{
+ static void push (lua_State* L, char value)
+ {
+ lua_pushlstring (L, &value, 1);
+ }
+
+ static char get (lua_State* L, int index)
+ {
+ return luaL_checkstring (L, index) [0];
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `const char*`.
+*/
+template <>
+struct Stack <char const*>
+{
+ static void push (lua_State* L, char const* str)
+ {
+ if (str != 0)
+ lua_pushstring (L, str);
+ else
+ lua_pushnil (L);
+ }
+
+ static char const* get (lua_State* L, int index)
+ {
+ return lua_isnil (L, index) ? 0 : luaL_checkstring (L, index);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `std::string`.
+*/
+template <>
+struct Stack <std::string>
+{
+ static void push (lua_State* L, std::string const& str)
+ {
+ lua_pushlstring (L, str.data (), str.size ());
+ }
+
+ static std::string get (lua_State* L, int index)
+ {
+ size_t len;
+ const char *str = luaL_checklstring (L, index, &len);
+ return std::string (str, len);
+ }
+};
+
+
+template <class T>
+struct StackOpSelector <T&, false>
+{
+ typedef T ReturnType;
+
+ static void push (lua_State* L, T& value)
+ {
+ Stack <T>::push (L, value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Stack <T>::get (L, index);
+ }
+};
+
+template <class T>
+struct StackOpSelector <const T&, false>
+{
+ typedef T ReturnType;
+
+ static void push (lua_State* L, const T& value)
+ {
+ Stack <T>::push (L, value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Stack <T>::get (L, index);
+ }
+};
+
+template <class T>
+struct StackOpSelector <T*, false>
+{
+ typedef T ReturnType;
+
+ static void push (lua_State* L, T* value)
+ {
+ Stack <T>::push (L, *value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Stack <T>::get (L, index);
+ }
+};
+
+template <class T>
+struct StackOpSelector <const T*, false>
+{
+ typedef T ReturnType;
+
+ static void push (lua_State* L, const T* value)
+ {
+ Stack <T>::push (L, *value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Stack <T>::get (L, index);
+ }
+};
+
+
+template <class T>
+struct Stack <T&>
+{
+ typedef StackOpSelector <T&, IsUserdata <T>::value> Helper;
+ typedef typename Helper::ReturnType ReturnType;
+
+ static void push (lua_State* L, T& value)
+ {
+ Helper::push (L, value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Helper::get (L, index);
+ }
+};
+
+template <class T>
+struct Stack <const T&>
+{
+ typedef StackOpSelector <const T&, IsUserdata <T>::value> Helper;
+ typedef typename Helper::ReturnType ReturnType;
+
+ static void push (lua_State* L, const T& value)
+ {
+ Helper::push (L, value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Helper::get (L, index);
+ }
+};
+
+template <class T>
+struct Stack <T*>
+{
+ typedef StackOpSelector <T*, IsUserdata <T>::value> Helper;
+ typedef typename Helper::ReturnType ReturnType;
+
+ static void push (lua_State* L, T* value)
+ {
+ Helper::push (L, value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Helper::get (L, index);
+ }
+};
+
+template <class T>
+struct Stack <const T*>
+{
+ typedef StackOpSelector <const T*, IsUserdata <T>::value> Helper;
+ typedef typename Helper::ReturnType ReturnType;
+
+ static void push (lua_State* L, const T* value)
+ {
+ Helper::push (L, value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Helper::get (L, index);
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/TypeList.h b/lib/LuaBridge/Source/LuaBridge/detail/TypeList.h
new file mode 100644
index 0000000..d142f6e
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/TypeList.h
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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 incorporates work covered by the following copyright and
+ permission notice:
+
+ The Loki Library
+ Copyright (c) 2001 by Andrei Alexandrescu
+ This code accompanies the book:
+ Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+ Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+ Permission to use, copy, modify, distribute and sell this software for any
+ purpose is hereby granted without fee, provided that the above copyright
+ notice appear in all copies and that both that copyright notice and this
+ permission notice appear in supporting documentation.
+ The author or Addison-Welsey Longman make no representations about the
+ suitability of this software for any purpose. It is provided "as is"
+ without express or implied warranty.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <LuaBridge/detail/Config.h>
+#include <LuaBridge/detail/Stack.h>
+
+#include <string>
+#include <typeinfo>
+
+namespace luabridge {
+
+/**
+ None type means void parameters or return value.
+*/
+typedef void None;
+
+template <typename Head, typename Tail = None>
+struct TypeList
+{
+ typedef Tail TailType;
+};
+
+template <class List>
+struct TypeListSize
+{
+ static const size_t value = TypeListSize <typename List::TailType>::value + 1;
+};
+
+template <>
+struct TypeListSize <None>
+{
+ static const size_t value = 0;
+};
+
+#ifdef LUABRIDGE_CXX11
+
+template <class... Params>
+struct MakeTypeList;
+
+template <class Param, class... Params>
+struct MakeTypeList <Param, Params...>
+{
+ using Result = TypeList <Param, typename MakeTypeList <Params...>::Result>;
+};
+
+template <>
+struct MakeTypeList <>
+{
+ using Result = None;
+};
+
+#endif
+
+/**
+ A TypeList with actual values.
+*/
+template <typename List>
+struct TypeListValues
+{
+ static std::string const tostring (bool)
+ {
+ return "";
+ }
+};
+
+/**
+ TypeListValues recursive template definition.
+*/
+template <typename Head, typename Tail>
+struct TypeListValues <TypeList <Head, Tail> >
+{
+ Head hd;
+ TypeListValues <Tail> tl;
+
+ TypeListValues (Head hd_, TypeListValues <Tail> const& tl_)
+ : hd (hd_), tl (tl_)
+ {
+ }
+
+ static std::string tostring (bool comma = false)
+ {
+ std::string s;
+
+ if (comma)
+ s = ", ";
+
+ s = s + typeid (Head).name ();
+
+ return s + TypeListValues <Tail>::tostring (true);
+ }
+};
+
+// Specializations of type/value list for head types that are references and
+// const-references. We need to handle these specially since we can't count
+// on the referenced object hanging around for the lifetime of the list.
+
+template <typename Head, typename Tail>
+struct TypeListValues <TypeList <Head&, Tail> >
+{
+ Head hd;
+ TypeListValues <Tail> tl;
+
+ TypeListValues (Head& hd_, TypeListValues <Tail> const& tl_)
+ : hd (hd_), tl (tl_)
+ {
+ }
+
+ static std::string const tostring (bool comma = false)
+ {
+ std::string s;
+
+ if (comma)
+ s = ", ";
+
+ s = s + typeid (Head).name () + "&";
+
+ return s + TypeListValues <Tail>::tostring (true);
+ }
+};
+
+template <typename Head, typename Tail>
+struct TypeListValues <TypeList <Head const&, Tail> >
+{
+ Head hd;
+ TypeListValues <Tail> tl;
+
+ TypeListValues (Head const& hd_, const TypeListValues <Tail>& tl_)
+ : hd (hd_), tl (tl_)
+ {
+ }
+
+ static std::string const tostring (bool comma = false)
+ {
+ std::string s;
+
+ if (comma)
+ s = ", ";
+
+ s = s + typeid (Head).name () + " const&";
+
+ return s + TypeListValues <Tail>::tostring (true);
+ }
+};
+
+//==============================================================================
+/**
+ Subclass of a TypeListValues constructable from the Lua stack.
+*/
+
+template <typename List, int Start = 1>
+struct ArgList
+{
+};
+
+template <int Start>
+struct ArgList <None, Start> : public TypeListValues <None>
+{
+ ArgList (lua_State*)
+ {
+ }
+};
+
+template <typename Head, typename Tail, int Start>
+struct ArgList <TypeList <Head, Tail>, Start>
+ : public TypeListValues <TypeList <Head, Tail> >
+{
+ ArgList (lua_State* L)
+ : TypeListValues <TypeList <Head, Tail> > (Stack <Head>::get (L, Start),
+ ArgList <Tail, Start + 1> (L))
+ {
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/TypeTraits.h b/lib/LuaBridge/Source/LuaBridge/detail/TypeTraits.h
new file mode 100644
index 0000000..5fad375
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/TypeTraits.h
@@ -0,0 +1,135 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2019, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <string>
+
+
+namespace luabridge {
+
+//------------------------------------------------------------------------------
+/**
+ Container traits.
+
+ Unspecialized ContainerTraits has the isNotContainer typedef for SFINAE.
+ All user defined containers must supply an appropriate specialization for
+ ContinerTraits (without the typedef isNotContainer). The containers that
+ come with LuaBridge also come with the appropriate ContainerTraits
+ specialization. See the corresponding declaration for details.
+
+ A specialization of ContainerTraits for some generic type ContainerType
+ looks like this:
+
+ template <class T>
+ struct ContainerTraits <ContainerType <T> >
+ {
+ typedef typename T Type;
+
+ static T* get (ContainerType <T> const& c)
+ {
+ return c.get (); // Implementation-dependent on ContainerType
+ }
+ };
+*/
+template <class T>
+struct ContainerTraits
+{
+ typedef bool isNotContainer;
+ typedef T Type;
+};
+
+//------------------------------------------------------------------------------
+/**
+ Type traits.
+
+ Specializations return information about a type.
+*/
+struct TypeTraits
+{
+ /** Determine if type T is a container.
+
+ To be considered a container, there must be a specialization of
+ ContainerTraits with the required fields.
+ */
+ template <typename T>
+ class isContainer
+ {
+ private:
+ typedef char yes[1]; // sizeof (yes) == 1
+ typedef char no [2]; // sizeof (no) == 2
+
+ template <typename C>
+ static no& test (typename C::isNotContainer*);
+
+ template <typename>
+ static yes& test (...);
+
+ public:
+ static const bool value = sizeof (test <ContainerTraits <T> >(0)) == sizeof (yes);
+ };
+
+ /** Determine if T is const qualified.
+ */
+ /** @{ */
+ template <class T>
+ struct isConst
+ {
+ static bool const value = false;
+ };
+
+ template <class T>
+ struct isConst <T const>
+ {
+ static bool const value = true;
+ };
+ /** @} */
+
+ /** Remove the const qualifier from T.
+ */
+ /** @{ */
+ template <class T>
+ struct removeConst
+ {
+ typedef T Type;
+ };
+
+ template <class T>
+ struct removeConst <T const>
+ {
+ typedef T Type;
+ };
+ /**@}*/
+};
+
+
+template <class T>
+struct Stack;
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/Userdata.h b/lib/LuaBridge/Source/LuaBridge/detail/Userdata.h
new file mode 100644
index 0000000..2b82460
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/Userdata.h
@@ -0,0 +1,742 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2019, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include <LuaBridge/detail/ClassInfo.h>
+
+#include <cassert>
+#include <stdexcept>
+
+
+namespace luabridge {
+
+//==============================================================================
+/**
+ Return the identity pointer for our lightuserdata tokens.
+
+ Because of Lua's dynamic typing and our improvised system of imposing C++
+ class structure, there is the possibility that executing scripts may
+ knowingly or unknowingly cause invalid data to get passed to the C functions
+ created by LuaBridge. In particular, our security model addresses the
+ following:
+ 1. Scripts cannot create a userdata (ignoring the debug lib).
+ 2. Scripts cannot create a lightuserdata (ignoring the debug lib).
+ 3. Scripts cannot set the metatable on a userdata.
+*/
+
+/**
+ Interface to a class pointer retrievable from a userdata.
+*/
+class Userdata
+{
+protected:
+ void* m_p; // subclasses must set this
+
+ //--------------------------------------------------------------------------
+ /**
+ Get an untyped pointer to the contained class.
+ */
+ void* getPointer ()
+ {
+ return m_p;
+ }
+
+private:
+ //--------------------------------------------------------------------------
+ /**
+ Validate and retrieve a Userdata on the stack.
+
+ The Userdata must exactly match the corresponding class table or
+ const table, or else a Lua error is raised. This is used for the
+ __gc metamethod.
+ */
+ static Userdata* getExactClass (lua_State* L, int index, [[maybe_unused]]void const* classKey)
+ {
+ return static_cast <Userdata*> (lua_touserdata (L, lua_absindex (L, index)));
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Validate and retrieve a Userdata on the stack.
+
+ The Userdata must be derived from or the same as the given base class,
+ identified by the key. If canBeConst is false, generates an error if
+ the resulting Userdata represents to a const object. We do the type check
+ first so that the error message is informative.
+ */
+ static Userdata* getClass (lua_State* L,
+ int index,
+ void const* registryConstKey,
+ void const* registryClassKey,
+ bool canBeConst)
+ {
+ index = lua_absindex (L, index);
+
+ lua_getmetatable (L, index); // Stack: ot | nil
+ if (!lua_istable (L, -1))
+ {
+ lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: registry metatable (rt) | nil
+ return throwBadArg (L, index);
+ }
+
+ lua_rawgetp (L, -1, getConstKey ()); // Stack: ot | nil, const table (co) | nil
+ assert (lua_istable (L, -1) || lua_isnil (L, -1));
+
+ // If const table is NOT present, object is const. Use non-const registry table
+ // if object cannot be const, so constness validation is done automatically.
+ // E.g. nonConstFn (constObj)
+ // -> canBeConst = false, isConst = true
+ // -> 'Class' registry table, 'const Class' object table
+ // -> 'expected Class, got const Class'
+ bool isConst = lua_isnil (L, -1); // Stack: ot | nil, nil, rt
+ if (isConst && canBeConst)
+ {
+ lua_rawgetp (L, LUA_REGISTRYINDEX, registryConstKey); // Stack: ot, nil, rt
+ }
+ else
+ {
+ lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: ot, co, rt
+ }
+
+ lua_insert (L, -3); // Stack: rt, ot, co | nil
+ lua_pop (L, 1); // Stack: rt, ot
+
+ for (;;)
+ {
+ if (lua_rawequal (L, -1, -2))
+ {
+ lua_pop (L, 2); // Stack: -
+ return static_cast <Userdata*> (lua_touserdata (L, index));
+ }
+
+ // Replace current metatable with it's base class.
+ lua_rawgetp (L, -1, getParentKey ()); // Stack: rt, ot, parent ot (pot) | nil
+
+ if (lua_isnil (L, -1)) // Stack: rt, ot, nil
+ {
+ // Drop the object metatable because it may be some parent metatable
+ lua_pop (L, 2); // Stack: rt
+ return throwBadArg (L, index);
+ }
+
+ lua_remove (L, -2); // Stack: rt, pot
+ }
+
+ // no return
+ }
+
+ static Userdata* throwBadArg (lua_State* L, int index)
+ {
+ assert (lua_istable (L, -1) || lua_isnil (L, -1)); // Stack: rt | nil
+
+ const char* expected = 0;
+ if (lua_isnil (L, -1)) // Stack: nil
+ {
+ expected = "unregistered class";
+ }
+ else
+ {
+ lua_rawgetp (L, -1, getTypeKey ()); // Stack: rt, registry type
+ expected = lua_tostring (L, -1);
+ }
+
+ const char* got = 0;
+ if (lua_isuserdata (L, index))
+ {
+ lua_getmetatable (L, index); // Stack: ..., ot | nil
+ if (lua_istable (L, -1)) // Stack: ..., ot
+ {
+ lua_rawgetp (L, -1, getTypeKey ()); // Stack: ..., ot, object type | nil
+ if (lua_isstring (L, -1))
+ {
+ got = lua_tostring (L, -1);
+ }
+ }
+ }
+ if (!got)
+ {
+ got = lua_typename (L, lua_type (L, index));
+ }
+
+ luaL_argerror (L, index, lua_pushfstring (L, "%s expected, got %s", expected, got));
+ return 0;
+ }
+
+public:
+ virtual ~Userdata () { }
+
+ //--------------------------------------------------------------------------
+ /**
+ Returns the Userdata* if the class on the Lua stack matches.
+
+ If the class does not match, a Lua error is raised.
+ */
+ template <class T>
+ static inline Userdata* getExact (lua_State* L, int index)
+ {
+ return getExactClass (L, index, ClassInfo <T>::getClassKey ());
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Get a pointer to the class from the Lua stack.
+
+ If the object is not the class or a subclass, or it violates the
+ const-ness, a Lua error is raised.
+ */
+ template <class T>
+ static inline T* get (lua_State* L, int index, bool canBeConst)
+ {
+ if (lua_isnil (L, index))
+ return 0;
+
+ return static_cast <T*> (getClass (
+ L, index, ClassInfo <T>::getConstKey (),
+ ClassInfo <T>::getClassKey (),
+ canBeConst)->getPointer ());
+ }
+};
+
+//----------------------------------------------------------------------------
+/**
+ Wraps a class object stored in a Lua userdata.
+
+ The lifetime of the object is managed by Lua. The object is constructed
+ inside the userdata using placement new.
+*/
+template <class T>
+class UserdataValue : public Userdata
+{
+private:
+ UserdataValue <T> (UserdataValue <T> const&);
+ UserdataValue <T> operator= (UserdataValue <T> const&);
+
+ char m_storage [sizeof (T)];
+
+ inline T* getObject ()
+ {
+ // If this fails to compile it means you forgot to provide
+ // a Container specialization for your container!
+ //
+ return reinterpret_cast <T*> (&m_storage [0]);
+ }
+
+private:
+ /**
+ Used for placement construction.
+ */
+ UserdataValue ()
+ {
+ m_p = getObject ();
+ }
+
+ ~UserdataValue ()
+ {
+ getObject ()->~T ();
+ }
+
+public:
+ /**
+ Push a T via placement new.
+
+ The caller is responsible for calling placement new using the
+ returned uninitialized storage.
+ */
+ static void* place (lua_State* const L)
+ {
+ UserdataValue <T>* const ud = new (
+ lua_newuserdata (L, sizeof (UserdataValue <T>))) UserdataValue <T> ();
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+ if (!lua_istable (L, -1))
+ {
+ throw std::logic_error ("The class is not registered in LuaBridge");
+ }
+ lua_setmetatable (L, -2);
+ return ud->getPointer ();
+ }
+
+ /**
+ Push T via copy construction from U.
+ */
+ template <class U>
+ static inline void push (lua_State* const L, U const& u)
+ {
+ new (place (L)) U (u);
+ }
+};
+
+//----------------------------------------------------------------------------
+/**
+ Wraps a pointer to a class object inside a Lua userdata.
+
+ The lifetime of the object is managed by C++.
+*/
+class UserdataPtr : public Userdata
+{
+private:
+ UserdataPtr (UserdataPtr const&);
+ UserdataPtr operator= (UserdataPtr const&);
+
+private:
+ /** Push a pointer to object using metatable key.
+ */
+ static void push (lua_State* L, const void* p, void const* const key)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (const_cast <void*> (p));
+ lua_rawgetp (L, LUA_REGISTRYINDEX, key);
+ if (!lua_istable (L, -1))
+ {
+ throw std::logic_error ("The class is not registered in LuaBridge");
+ }
+ lua_setmetatable (L, -2);
+ }
+
+ explicit UserdataPtr (void* const p)
+ {
+ m_p = p;
+
+ // Can't construct with a null pointer!
+ //
+ assert (m_p != 0);
+ }
+
+public:
+ /** Push non-const pointer to object.
+ */
+ template <class T>
+ static void push (lua_State* const L, T* const p)
+ {
+ if (p)
+ push (L, p, ClassInfo <T>::getClassKey ());
+ else
+ lua_pushnil (L);
+ }
+
+ /** Push const pointer to object.
+ */
+ template <class T>
+ static void push (lua_State* const L, T const* const p)
+ {
+ if (p)
+ push (L, p, ClassInfo <T>::getConstKey ());
+ else
+ lua_pushnil (L);
+ }
+};
+
+//============================================================================
+/**
+ Wraps a container that references a class object.
+
+ The template argument C is the container type, ContainerTraits must be
+ specialized on C or else a compile error will result.
+*/
+template <class C>
+class UserdataShared : public Userdata
+{
+private:
+ UserdataShared (UserdataShared <C> const&);
+ UserdataShared <C>& operator= (UserdataShared <C> const&);
+
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ C m_c;
+
+private:
+ ~UserdataShared ()
+ {
+ }
+
+public:
+ /**
+ Construct from a container to the class or a derived class.
+ */
+ template <class U>
+ explicit UserdataShared (U const& u) : m_c (u)
+ {
+ m_p = const_cast <void*> (reinterpret_cast <void const*> (
+ (ContainerTraits <C>::get (m_c))));
+ }
+
+ /**
+ Construct from a pointer to the class or a derived class.
+ */
+ template <class U>
+ explicit UserdataShared (U* u) : m_c (u)
+ {
+ m_p = const_cast <void*> (reinterpret_cast <void const*> (
+ (ContainerTraits <C>::get (m_c))));
+ }
+};
+
+//----------------------------------------------------------------------------
+//
+// SFINAE helpers.
+//
+
+// non-const objects
+template <class C, bool makeObjectConst>
+struct UserdataSharedHelper
+{
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ static void push (lua_State* L, C const& c)
+ {
+ if (ContainerTraits <C>::get (c) != 0)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+ // If this goes off it means the class T is unregistered!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+
+ static void push (lua_State* L, T* const t)
+ {
+ if (t)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+ // If this goes off it means the class T is unregistered!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+};
+
+// const objects
+template <class C>
+struct UserdataSharedHelper <C, true>
+{
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ static void push (lua_State* L, C const& c)
+ {
+ if (ContainerTraits <C>::get (c) != 0)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
+ // If this goes off it means the class T is unregistered!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+
+ static void push (lua_State* L, T* const t)
+ {
+ if (t)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
+ // If this goes off it means the class T is unregistered!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+};
+
+/**
+ Pass by container.
+
+ The container controls the object lifetime. Typically this will be a
+ lifetime shared by C++ and Lua using a reference count. Because of type
+ erasure, containers like std::shared_ptr will not work. Containers must
+ either be of the intrusive variety, or in the style of the RefCountedPtr
+ type provided by LuaBridge (that uses a global hash table).
+*/
+template <class C, bool byContainer>
+struct StackHelper
+{
+ static void push (lua_State* L, C const& c)
+ {
+ UserdataSharedHelper <C,
+ TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, c);
+ }
+
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ static C get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, true);
+ }
+};
+
+/**
+ Pass by value.
+
+ Lifetime is managed by Lua. A C++ function which accesses a pointer or
+ reference to an object outside the activation record in which it was
+ retrieved may result in undefined behavior if Lua garbage collected it.
+*/
+template <class T>
+struct StackHelper <T, false>
+{
+ static inline void push (lua_State* L, T const& t)
+ {
+ UserdataValue <T>::push (L, t);
+ }
+
+ static inline T const& get (lua_State* L, int index)
+ {
+ return *Userdata::get <T> (L, index, true);
+ }
+};
+
+
+//------------------------------------------------------------------------------
+/**
+ Lua stack conversions for pointers and references to class objects.
+
+ Lifetime is managed by C++. Lua code which remembers a reference to the
+ value may result in undefined behavior if C++ destroys the object. The
+ handling of the const and volatile qualifiers happens in UserdataPtr.
+*/
+
+template <class C, bool byContainer>
+struct RefStackHelper
+{
+ typedef C return_type;
+
+ static inline void push (lua_State* L, C const& t)
+ {
+ UserdataSharedHelper <C,
+ TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, t);
+ }
+
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ static return_type get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, true);
+ }
+};
+
+template <class T>
+struct RefStackHelper <T, false>
+{
+ typedef T& return_type;
+
+ static void push (lua_State* L, T const& t)
+ {
+ UserdataPtr::push (L, &t);
+ }
+
+ static return_type get (lua_State* L, int index)
+ {
+ T* t = Userdata::get <T> (L, index, true);
+
+ if (!t)
+ luaL_error (L, "nil passed to reference");
+ return *t;
+ }
+};
+
+
+/**
+ * Voider class template. Used to force a comiler to instantiate
+ * an otherwise probably unused template parameter type T.
+ * See the C++20 std::void_t <> for details.
+ */
+template <class T>
+struct Void
+{
+ typedef void Type;
+};
+
+
+/**
+ * Trait class that selects whether to return a user registered
+ * class object by value or by reference.
+ */
+
+template <class T, class Enabler = void>
+struct UserdataGetter
+{
+ typedef T* ReturnType;
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, false);
+ }
+};
+
+template <class T>
+struct UserdataGetter <T, typename Void <T (*) ()>::Type>
+{
+ typedef T ReturnType;
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return StackHelper <T, TypeTraits::isContainer <T>::value>::get (L, index);
+ }
+};
+
+//==============================================================================
+
+/**
+ Lua stack conversions for class objects passed by value.
+*/
+template <class T>
+struct Stack
+{
+ typedef void IsUserdata;
+
+ typedef UserdataGetter <T> Getter;
+ typedef typename Getter::ReturnType ReturnType;
+
+ static void push (lua_State* L, T const& value)
+ {
+ StackHelper <T, TypeTraits::isContainer <T>::value>::push (L, value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Getter::get (L, index);
+ }
+};
+
+
+/**
+ * Trait class indicating whether the parameter type must be
+ * a user registered class. The trait checks the existence of
+ * member type Stack <T>::IsUserdata specialization for detection.
+ */
+template <class T, class Enable = void>
+struct IsUserdata
+{
+ static const bool value = false;
+};
+
+template <class T>
+struct IsUserdata <T, typename Void <typename Stack <T>::IsUserdata>::Type>
+{
+ static const bool value = true;
+};
+
+
+/**
+ * Trait class that selects a specific push/get implemenation.
+ */
+template <class T, bool isUserdata>
+struct StackOpSelector;
+
+// pointer
+template <class T>
+struct StackOpSelector <T*, true>
+{
+ typedef T* ReturnType;
+
+ static void push (lua_State* L, T* value)
+ {
+ UserdataPtr::push (L, value);
+ }
+
+ static T* get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, false);
+ }
+};
+
+// pointer to const
+template <class T>
+struct StackOpSelector <const T*, true>
+{
+ typedef const T* ReturnType;
+
+ static void push (lua_State* L, const T* value)
+ {
+ UserdataPtr::push (L, value);
+ }
+
+ static const T* get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, true);
+ }
+};
+
+// reference
+template <class T>
+struct StackOpSelector <T&, true>
+{
+ typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> Helper;
+ typedef typename Helper::return_type ReturnType;
+
+ static void push (lua_State* L, T& value)
+ {
+ UserdataPtr::push (L, &value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Helper::get (L, index);
+ }
+};
+
+// reference to const
+template <class T>
+struct StackOpSelector <const T&, true>
+{
+ typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> Helper;
+ typedef typename Helper::return_type ReturnType;
+
+ static void push (lua_State* L, const T& value)
+ {
+ Helper::push (L, value);
+ }
+
+ static ReturnType get (lua_State* L, int index)
+ {
+ return Helper::get (L, index);
+ }
+};
+
+} // namespace luabridge
diff --git a/lib/LuaBridge/Source/LuaBridge/detail/dump.h b/lib/LuaBridge/Source/LuaBridge/detail/dump.h
new file mode 100644
index 0000000..7e23f9f
--- /dev/null
+++ b/lib/LuaBridge/Source/LuaBridge/detail/dump.h
@@ -0,0 +1,143 @@
+//==============================================================================
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2019, Dmitry Tarakanov
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ 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.
+*/
+//==============================================================================
+
+#pragma once
+
+#include "LuaBridge/detail/ClassInfo.h"
+
+#include <iostream>
+#include <string>
+
+
+namespace luabridge {
+namespace debug {
+
+inline void putIndent (std::ostream& stream, unsigned level)
+{
+ for (unsigned i = 0; i < level; ++i)
+ {
+ stream << " ";
+ }
+}
+
+inline void dumpTable (lua_State* L, int index, std::ostream& stream, unsigned level);
+
+inline void dumpValue (lua_State* L, int index, std::ostream& stream, unsigned level = 0)
+{
+ const int type = lua_type (L, index);
+ switch (type)
+ {
+ case LUA_TNIL:
+ stream << "nil";
+ break;
+
+ case LUA_TBOOLEAN:
+ stream << (lua_toboolean (L, index) ? "true" : "false");
+ break;
+
+ case LUA_TNUMBER:
+ stream << lua_tonumber (L, index);
+ break;
+
+ case LUA_TSTRING:
+ stream << '"' << lua_tostring (L, index) << '"';
+ break;
+
+ case LUA_TFUNCTION:
+ if (lua_iscfunction (L, index))
+ {
+ stream << "cfunction@" << lua_topointer (L, index);
+ }
+ else
+ {
+ stream << "function@" << lua_topointer (L, index);
+ }
+ break;
+
+ case LUA_TTHREAD:
+ stream << "thread@" << lua_tothread (L, index);
+ break;
+
+ case LUA_TLIGHTUSERDATA:
+ stream << "lightuserdata@" << lua_touserdata (L, index);
+ break;
+
+ case LUA_TTABLE:
+ dumpTable (L, index, stream, level);
+ break;
+
+ case LUA_TUSERDATA:
+ stream << "userdata@" << lua_touserdata (L, index);
+ break;
+
+ default:
+ stream << lua_typename (L, type);;
+ break;
+ }
+}
+
+inline void dumpTable (lua_State* L, int index, std::ostream& stream, unsigned level)
+{
+ stream << "table@" << lua_topointer (L, index);
+
+ if (level > 0)
+ {
+ return;
+ }
+
+ index = lua_absindex (L, index);
+ stream << " {";
+ lua_pushnil (L); // Initial key
+ while (lua_next (L, index))
+ {
+ stream << "\n";
+ putIndent (stream, level + 1);
+ dumpValue (L, -2, stream, level + 1); // Key
+ stream << ": ";
+ dumpValue (L, -1, stream, level + 1); // Value
+ lua_pop (L, 1); // Value
+ }
+ putIndent (stream, level);
+ stream << "\n}";
+}
+
+inline void dumpState (lua_State *L, std::ostream& stream = std::cerr)
+{
+ int top = lua_gettop (L);
+ for (int i = 1; i <= top; ++i)
+ {
+ stream << "stack #" << i << ": ";
+ dumpValue (L, i, stream, 0);
+ stream << "\n";
+ }
+}
+
+} // namespace debug
+} // namespace luabridge