summaryrefslogtreecommitdiff
path: root/libs/lua/LuaBridge/detail/CFunctions.h
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-01-11 11:50:50 +0100
committerRobin Gareus <robin@gareus.org>2016-02-22 22:06:47 +0100
commite98f21dd297819fcb4931bd5a87474736c7a450e (patch)
tree018a17a9f67c206cea1394c3f4012c58a1a2f6d4 /libs/lua/LuaBridge/detail/CFunctions.h
parentc8973f67a65d911d1b08e1121d1c7da57c58b182 (diff)
add LuaBridge
https://github.com/vinniefalco/LuaBridge
Diffstat (limited to 'libs/lua/LuaBridge/detail/CFunctions.h')
-rw-r--r--libs/lua/LuaBridge/detail/CFunctions.h442
1 files changed, 442 insertions, 0 deletions
diff --git a/libs/lua/LuaBridge/detail/CFunctions.h b/libs/lua/LuaBridge/detail/CFunctions.h
new file mode 100644
index 0000000000..0497b6bb4b
--- /dev/null
+++ b/libs/lua/LuaBridge/detail/CFunctions.h
@@ -0,0 +1,442 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+// We use a structure so we can define everything in the header.
+//
+struct CFunc
+{
+ //----------------------------------------------------------------------------
+ /**
+ __index metamethod for a namespace or class static members.
+
+ This handles:
+ Retrieving functions and class static methods, stored in the metatable.
+ Reading global and class static data, stored in the __propget table.
+ Reading global and class properties, stored in the __propget table.
+ */
+ static int indexMetaMethod (lua_State* L)
+ {
+ int result = 0;
+ lua_getmetatable (L, 1); // push metatable of arg1
+ for (;;)
+ {
+ lua_pushvalue (L, 2); // push key arg2
+ lua_rawget (L, -2); // lookup key in metatable
+ if (lua_isnil (L, -1)) // not found
+ {
+ lua_pop (L, 1); // discard nil
+ rawgetfield (L, -1, "__propget"); // lookup __propget in metatable
+ lua_pushvalue (L, 2); // push key arg2
+ lua_rawget (L, -2); // lookup key in __propget
+ lua_remove (L, -2); // discard __propget
+ if (lua_iscfunction (L, -1))
+ {
+ lua_remove (L, -2); // discard metatable
+ lua_pushvalue (L, 1); // push arg1
+ lua_call (L, 1, 1); // call cfunction
+ result = 1;
+ break;
+ }
+ else
+ {
+ assert (lua_isnil (L, -1));
+ lua_pop (L, 1); // discard nil and fall through
+ }
+ }
+ else
+ {
+ assert (lua_istable (L, -1) || lua_iscfunction (L, -1));
+ lua_remove (L, -2);
+ result = 1;
+ break;
+ }
+
+ rawgetfield (L, -1, "__parent");
+ if (lua_istable (L, -1))
+ {
+ // Remove metatable and repeat the search in __parent.
+ lua_remove (L, -2);
+ }
+ else
+ {
+ // Discard metatable and return nil.
+ assert (lua_isnil (L, -1));
+ lua_remove (L, -2);
+ result = 1;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ __newindex metamethod for a namespace or class static members.
+
+ The __propset table stores proxy functions for assignment to:
+ Global and class static data.
+ Global and class properties.
+ */
+ static int newindexMetaMethod (lua_State* L)
+ {
+ int result = 0;
+ lua_getmetatable (L, 1); // push metatable of arg1
+ for (;;)
+ {
+ rawgetfield (L, -1, "__propset"); // lookup __propset in metatable
+ assert (lua_istable (L, -1));
+ lua_pushvalue (L, 2); // push key arg2
+ lua_rawget (L, -2); // lookup key in __propset
+ lua_remove (L, -2); // discard __propset
+ if (lua_iscfunction (L, -1)) // ensure value is a cfunction
+ {
+ lua_remove (L, -2); // discard metatable
+ lua_pushvalue (L, 3); // push new value arg3
+ lua_call (L, 1, 0); // call cfunction
+ result = 0;
+ break;
+ }
+ else
+ {
+ assert (lua_isnil (L, -1));
+ lua_pop (L, 1);
+ }
+
+ rawgetfield (L, -1, "__parent");
+ if (lua_istable (L, -1))
+ {
+ // Remove metatable and repeat the search in __parent.
+ lua_remove (L, -2);
+ }
+ else
+ {
+ assert (lua_isnil (L, -1));
+ lua_pop (L, 2);
+ result = luaL_error (L,"no writable variable '%s'", lua_tostring (L, 2));
+ }
+ }
+
+ return result;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ 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 is in the first upvalue.
+ */
+ template <class FnPtr,
+ class ReturnType = typename FuncTraits <FnPtr>::ReturnType>
+ struct Call
+ {
+ typedef typename FuncTraits <FnPtr>::Params Params;
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ ArgList <Params> args (L);
+ Stack <typename FuncTraits <FnPtr>::ReturnType>::push (L, FuncTraits <FnPtr>::call (fnptr, args));
+ return 1;
+ }
+ };
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a function with no return value.
+
+ This is used for global functions, global properties, class static methods,
+ and class static properties.
+
+ The function pointer is in the first upvalue.
+ */
+ template <class FnPtr>
+ struct Call <FnPtr, void>
+ {
+ typedef typename FuncTraits <FnPtr>::Params Params;
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ ArgList <Params> args (L);
+ FuncTraits <FnPtr>::call (fnptr, args);
+ return 0;
+ }
+ };
+
+ //----------------------------------------------------------------------------
+ /**
+ 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,
+ class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
+ struct CallMember
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+
+ 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);
+ ArgList <Params, 2> args (L);
+ Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
+ return 1;
+ }
+ };
+
+ template <class MemFnPtr,
+ class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
+ struct CallConstMember
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+
+ 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);
+ ArgList <Params, 2> args(L);
+ Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
+ return 1;
+ }
+ };
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a class member function with no 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 <MemFnPtr, void>
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+
+ 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);
+ ArgList <Params, 2> args (L);
+ FuncTraits <MemFnPtr>::call (t, fnptr, args);
+ return 0;
+ }
+ };
+
+ template <class MemFnPtr>
+ struct CallConstMember <MemFnPtr, void>
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+
+ 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);
+ ArgList <Params, 2> args (L);
+ FuncTraits <MemFnPtr>::call (t, fnptr, args);
+ return 0;
+ }
+ };
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a class member lua_CFunction.
+
+ The member function pointer is in the first upvalue.
+ The class userdata object is at the top of 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);
+ }
+ };
+
+ //--------------------------------------------------------------------------
+
+ // 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;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ 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* const c = Userdata::get <C> (L, 1, true);
+ T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
+ Stack <T>::push (L, c->**mp);
+ 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)));
+ c->**mp = Stack <T>::get (L, 2);
+ return 0;
+ }
+};