1 //------------------------------------------------------------------------------
3 https://github.com/vinniefalco/LuaBridge
5 Copyright 2016, Robin Gareus <robin@gareus.org>
6 Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
8 License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 //==============================================================================
30 //==============================================================================
32 Return the identity pointer for our lightuserdata tokens.
34 LuaBridge metatables are tagged with a security "token." The token is a
35 lightuserdata created from the identity pointer, used as a key in the
36 metatable. The value is a boolean = true, although any value could have been
39 Because of Lua's dynamic typing and our improvised system of imposing C++
40 class structure, there is the possibility that executing scripts may
41 knowingly or unknowingly cause invalid data to get passed to the C functions
42 created by LuaBridge. In particular, our security model addresses the
46 1. Scripts cannot create a userdata (ignoring the debug lib).
47 2. Scripts cannot create a lightuserdata (ignoring the debug lib).
48 3. Scripts cannot set the metatable on a userdata.
49 4. Our identity key is a unique pointer in the process.
50 5. Our metatables have a lightuserdata identity key / value pair.
51 6. Our metatables have "__metatable" set to a boolean = false.
52 7. Our lightuserdata is unique.
55 #ifdef PLATFORM_WINDOWS
57 #include "LuaBridge/LuaBridge.h" /* Needed for LuaBridge_API */
58 LuaBridge_API void* getIdentityKey ();
60 extern void* getIdentityKey ();
63 inline void* getIdentityKey ()
71 Interface to a class pointer retrievable from a userdata.
76 void* m_p; // subclasses must set this
78 //--------------------------------------------------------------------------
80 Get an untyped pointer to the contained class.
82 inline void* getPointer () const
88 //--------------------------------------------------------------------------
90 Validate and retrieve a Userdata on the stack.
92 The Userdata must exactly match the corresponding class table or
93 const table, or else a Lua error is raised. This is used for the
96 static Userdata* getExactClass (lua_State* L,
101 int const index = lua_absindex (L, narg);
103 bool mismatch = false;
106 lua_rawgetp (L, LUA_REGISTRYINDEX, classKey);
107 assert (lua_istable (L, -1));
109 // Make sure we have a userdata.
110 if (!lua_isuserdata (L, index))
113 // Make sure it's metatable is ours.
116 lua_getmetatable (L, index);
117 lua_rawgetp (L, -1, getIdentityKey ());
118 if (lua_isboolean (L, -1))
131 if (lua_rawequal (L, -1, -2))
133 // Matches class table.
135 ud = static_cast <Userdata*> (lua_touserdata (L, index));
139 rawgetfield (L, -2, "__const");
140 if (lua_rawequal (L, -1, -2))
142 // Matches const table
144 ud = static_cast <Userdata*> (lua_touserdata (L, index));
148 // Mismatch, but its one of ours so get a type name.
149 rawgetfield (L, -2, "__type");
152 got = lua_tostring (L, -2);
160 rawgetfield (L, -1, "__type");
161 assert (lua_type (L, -1) == LUA_TSTRING);
162 char const* const expected = lua_tostring (L, -1);
165 got = lua_typename (L, lua_type (L, index));
167 char const* const msg = lua_pushfstring (
168 L, "%s expected, got %s", expected, got);
171 luaL_argerror (L, narg, msg);
179 //--------------------------------------------------------------------------
181 Validate and retrieve a Userdata on the stack.
183 The Userdata must be derived from or the same as the given base class,
184 identified by the key. If canBeConst is false, generates an error if
185 the resulting Userdata represents to a const object. We do the type check
186 first so that the error message is informative.
188 static Userdata* getClass (lua_State* L,
190 void const* baseClassKey,
196 bool mismatch = false;
199 lua_rawgetp (L, LUA_REGISTRYINDEX, baseClassKey);
200 assert (lua_istable (L, -1));
202 // Make sure we have a userdata.
203 if (lua_isuserdata (L, index))
205 // Make sure it's metatable is ours.
206 lua_getmetatable (L, index);
207 lua_rawgetp (L, -1, getIdentityKey ());
208 if (lua_isboolean (L, -1))
212 // If __const is present, object is NOT const.
213 rawgetfield (L, -1, "__const");
214 assert (lua_istable (L, -1) || lua_isnil (L, -1));
215 bool const isConst = lua_isnil (L, -1);
218 // Replace the class table with the const table if needed.
221 rawgetfield (L, -2, "__const");
222 assert (lua_istable (L, -1));
228 if (lua_rawequal (L, -1, -2))
232 // Match, now check const-ness.
233 if (isConst && !canBeConst)
235 luaL_argerror (L, index, "cannot be const");
239 ud = static_cast <Userdata*> (lua_touserdata (L, index));
245 // Replace current metatable with it's base class.
246 rawgetfield (L, -1, "__parent");
254 if (lua_isnil (L, -1))
257 // Mismatch, but its one of ours so get a type name.
258 rawgetfield (L, -1, "__type");
261 got = lua_tostring (L, -2);
285 assert (lua_type (L, -1) == LUA_TTABLE);
286 rawgetfield (L, -1, "__type");
287 assert (lua_type (L, -1) == LUA_TSTRING);
288 char const* const expected = lua_tostring (L, -1);
291 got = lua_typename (L, lua_type (L, index));
293 char const* const msg = lua_pushfstring (
294 L, "%s expected, got %s", expected, got);
296 luaL_argerror (L, index, msg);
303 virtual ~Userdata () { }
305 static void* get_ptr (lua_State* L, int index) {
306 Userdata* ud = static_cast <Userdata*> (lua_touserdata (L, index));
310 //--------------------------------------------------------------------------
312 Returns the Userdata* if the class on the Lua stack matches.
314 If the class does not match, a Lua error is raised.
317 static inline Userdata* getExact (lua_State* L, int index)
319 return getExactClass (L, index, ClassInfo <T>::getClassKey ());
322 //--------------------------------------------------------------------------
324 Get a pointer to the class from the Lua stack.
326 If the object is not the class or a subclass, or it violates the
327 const-ness, a Lua error is raised.
330 static inline T* get (lua_State* L, int index, bool canBeConst)
332 if (lua_isnil (L, index))
335 return static_cast <T*> (getClass (L, index,
336 ClassInfo <T>::getClassKey (), canBeConst)->getPointer ());
340 //----------------------------------------------------------------------------
342 Wraps a class object stored in a Lua userdata.
344 The lifetime of the object is managed by Lua. The object is constructed
345 inside the userdata using placement new.
348 class UserdataValue : public Userdata
351 UserdataValue <T> (UserdataValue <T> const&);
352 UserdataValue <T> operator= (UserdataValue <T> const&);
354 char m_storage [sizeof (T)];
356 inline T* getObject ()
358 // If this fails to compile it means you forgot to provide
359 // a Container specialization for your container!
361 return reinterpret_cast <T*> (&m_storage [0]);
366 Used for placement construction.
380 Push a T via placement new.
382 The caller is responsible for calling placement new using the
383 returned uninitialized storage.
385 static void* place (lua_State* const L)
387 UserdataValue <T>* const ud = new (
388 lua_newuserdata (L, sizeof (UserdataValue <T>))) UserdataValue <T> ();
389 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
390 // If this goes off it means you forgot to register the class!
391 assert (lua_istable (L, -1));
392 lua_setmetatable (L, -2);
393 return ud->getPointer ();
397 Push T via copy construction from U.
400 static inline void push (lua_State* const L, U const& u)
402 new (place (L)) U (u);
406 //----------------------------------------------------------------------------
408 Wraps a pointer to a class object inside a Lua userdata.
410 The lifetime of the object is managed by C++.
412 class UserdataPtr : public Userdata
415 UserdataPtr (UserdataPtr const&);
416 UserdataPtr operator= (UserdataPtr const&);
419 /** Push non-const pointer to object using metatable key.
421 static void push (lua_State* L, void* const p, void const* const key)
425 new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (p);
426 lua_rawgetp (L, LUA_REGISTRYINDEX, key);
427 // If this goes off it means you forgot to register the class!
428 assert (lua_istable (L, -1));
429 lua_setmetatable (L, -2);
437 /** Push const pointer to object using metatable key.
439 static void push (lua_State* L, void const* const p, void const* const key)
443 new (lua_newuserdata (L, sizeof (UserdataPtr)))
444 UserdataPtr (const_cast <void*> (p));
445 lua_rawgetp (L, LUA_REGISTRYINDEX, key);
446 // If this goes off it means you forgot to register the class!
447 assert (lua_istable (L, -1));
448 lua_setmetatable (L, -2);
456 explicit UserdataPtr (void* const p)
460 // Can't construct with a null pointer!
466 static inline void push_raw (lua_State* const L, void* p, const void* classkey)
468 new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (p);
469 lua_rawgetp (L, LUA_REGISTRYINDEX, classkey);
470 assert (lua_istable (L, -1));
471 lua_setmetatable (L, -2);
475 /** Push non-const pointer to object.
478 static inline void push (lua_State* const L, T* const p)
481 push (L, p, ClassInfo <T>::getClassKey ());
486 /** Push const pointer to object.
489 static inline void push (lua_State* const L, T const* const p)
492 push (L, p, ClassInfo <T>::getConstKey ());
498 //============================================================================
500 Wraps a container thet references a class object.
502 The template argument C is the container type, ContainerTraits must be
503 specialized on C or else a compile error will result.
506 class UserdataShared : public Userdata
509 UserdataShared (UserdataShared <C> const&);
510 UserdataShared <C>& operator= (UserdataShared <C> const&);
512 typedef typename TypeTraits::removeConst <
513 typename ContainerTraits <C>::Type>::Type T;
524 Construct from a container to the class or a derived class.
527 explicit UserdataShared (U const& u) : m_c (u)
529 m_p = const_cast <void*> (reinterpret_cast <void const*> (
530 (ContainerTraits <C>::get (m_c))));
534 Construct from a pointer to the class or a derived class.
537 explicit UserdataShared (U* u) : m_c (u)
539 m_p = const_cast <void*> (reinterpret_cast <void const*> (
540 (ContainerTraits <C>::get (m_c))));
544 //----------------------------------------------------------------------------
550 template <class C, bool makeObjectConst>
551 struct UserdataSharedHelper
553 typedef typename TypeTraits::removeConst <
554 typename ContainerTraits <C>::Type>::Type T;
556 static void push (lua_State* L, C const& c)
558 if (ContainerTraits <C>::get (c) != 0)
560 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
561 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
562 // If this goes off it means the class T is unregistered!
563 assert (lua_istable (L, -1));
564 lua_setmetatable (L, -2);
572 static void push (lua_State* L, T* const t)
576 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
577 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
578 // If this goes off it means the class T is unregistered!
579 assert (lua_istable (L, -1));
580 lua_setmetatable (L, -2);
591 struct UserdataSharedHelper <C, true>
593 typedef typename TypeTraits::removeConst <
594 typename ContainerTraits <C>::Type>::Type T;
596 static void push (lua_State* L, C const& c)
598 if (ContainerTraits <C>::get (c) != 0)
600 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
601 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
602 // If this goes off it means the class T is unregistered!
603 assert (lua_istable (L, -1));
604 lua_setmetatable (L, -2);
612 static void push (lua_State* L, T* const t)
616 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
617 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
618 // If this goes off it means the class T is unregistered!
619 assert (lua_istable (L, -1));
620 lua_setmetatable (L, -2);
632 The container controls the object lifetime. Typically this will be a
633 lifetime shared by C++ and Lua using a reference count. Because of type
634 erasure, containers like std::shared_ptr will not work. Containers must
635 either be of the intrusive variety, or in the style of the RefCountedPtr
636 type provided by LuaBridge (that uses a global hash table).
638 template <class C, bool byContainer, bool isEnum>
641 static inline void push (lua_State* L, C const& c)
643 UserdataSharedHelper <C,
644 TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, c);
647 typedef typename TypeTraits::removeConst <
648 typename ContainerTraits <C>::Type>::Type T;
650 static inline C get (lua_State* L, int index)
652 return Userdata::get <T> (L, index, true);
659 Lifetime is managed by Lua. A C++ function which accesses a pointer or
660 reference to an object outside the activation record in which it was
661 retrieved may result in undefined behavior if Lua garbage collected it.
664 struct StackHelper <T, false, false>
666 static inline void push (lua_State* L, T const& t)
668 UserdataValue <T>::push (L, t);
671 static inline T const& get (lua_State* L, int index)
673 return *Userdata::get <T> (L, index, true);
678 struct StackHelper <T, false, true>
680 static inline void push (lua_State* L, T const& t)
682 int v = static_cast <int> (t);
683 lua_pushinteger (L, static_cast <lua_Integer> (v));
686 static inline T get (lua_State* L, int index)
688 int v = static_cast <int> (luaL_checkinteger (L, index));
693 //==============================================================================
696 Lua stack conversions for class objects passed by value.
702 static inline void push (lua_State* L, T const& t)
705 TypeTraits::isContainer <T>::value,
706 TypeTraits::isEnum<T>::value>::push (L, t);
709 static inline T get (lua_State* L, int index)
711 return StackHelper <T,
712 TypeTraits::isContainer <T>::value,
713 TypeTraits::isEnum<T>::value>::get (L, index);
717 //------------------------------------------------------------------------------
719 Lua stack conversions for pointers and references to class objects.
721 Lifetime is managed by C++. Lua code which remembers a reference to the
722 value may result in undefined behavior if C++ destroys the object. The
723 handling of the const and volatile qualifiers happens in UserdataPtr.
730 static inline void push (lua_State* L, T* const p)
732 UserdataPtr::push (L, p);
735 static inline T* get (lua_State* L, int index)
737 return Userdata::get <T> (L, index, false);
741 // Strips the const off the right side of *
743 struct Stack <T* const>
745 static inline void push (lua_State* L, T* const p)
747 UserdataPtr::push (L, p);
750 static inline T* get (lua_State* L, int index)
752 return Userdata::get <T> (L, index, false);
758 struct Stack <T const*>
760 static inline void push (lua_State* L, T const* const p)
762 UserdataPtr::push (L, p);
765 static inline T const* get (lua_State* L, int index)
767 return Userdata::get <T> (L, index, true);
771 // Strips the const off the right side of *
773 struct Stack <T const* const>
775 static inline void push (lua_State* L, T const* const p)
777 UserdataPtr::push (L, p);
780 static inline T const* get (lua_State* L, int index)
782 return Userdata::get <T> (L, index, true);
790 static inline void push (lua_State* L, T& t)
792 UserdataPtr::push (L, &t);
795 static T& get (lua_State* L, int index)
797 T* const t = Userdata::get <T> (L, index, false);
799 luaL_error (L, "nil passed to reference");
804 template <class C, bool byContainer>
805 struct RefStackHelper
807 typedef C return_type;
809 static inline void push (lua_State* L, C const& t)
811 UserdataSharedHelper <C,
812 TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, t);
815 typedef typename TypeTraits::removeConst <
816 typename ContainerTraits <C>::Type>::Type T;
818 static return_type get (lua_State* L, int index)
820 return Userdata::get <T> (L, index, true);
825 struct RefStackHelper <T, false>
827 typedef T const& return_type;
829 static inline void push (lua_State* L, T const& t)
831 UserdataPtr::push (L, &t);
834 static return_type get (lua_State* L, int index)
836 T const* const t = Userdata::get <T> (L, index, true);
839 luaL_error (L, "nil passed to reference");
845 // reference to const
847 struct Stack <T const&>
849 typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> helper_t;
851 static inline void push (lua_State* L, T const& t)
853 helper_t::push (L, t);
856 static typename helper_t::return_type get (lua_State* L, int index)
858 return helper_t::get (L, index);