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.
54 inline void* getIdentityKey ()
61 Interface to a class pointer retrievable from a userdata.
66 void* m_p; // subclasses must set this
68 //--------------------------------------------------------------------------
70 Get an untyped pointer to the contained class.
72 inline void* getPointer () const
78 //--------------------------------------------------------------------------
80 Validate and retrieve a Userdata on the stack.
82 The Userdata must exactly match the corresponding class table or
83 const table, or else a Lua error is raised. This is used for the
86 static Userdata* getExactClass (lua_State* L,
91 int const index = lua_absindex (L, narg);
93 bool mismatch = false;
96 lua_rawgetp (L, LUA_REGISTRYINDEX, classKey);
97 assert (lua_istable (L, -1));
99 // Make sure we have a userdata.
100 if (!lua_isuserdata (L, index))
103 // Make sure it's metatable is ours.
106 lua_getmetatable (L, index);
107 lua_rawgetp (L, -1, getIdentityKey ());
108 if (lua_isboolean (L, -1))
121 if (lua_rawequal (L, -1, -2))
123 // Matches class table.
125 ud = static_cast <Userdata*> (lua_touserdata (L, index));
129 rawgetfield (L, -2, "__const");
130 if (lua_rawequal (L, -1, -2))
132 // Matches const table
134 ud = static_cast <Userdata*> (lua_touserdata (L, index));
138 // Mismatch, but its one of ours so get a type name.
139 rawgetfield (L, -2, "__type");
142 got = lua_tostring (L, -2);
150 rawgetfield (L, -1, "__type");
151 assert (lua_type (L, -1) == LUA_TSTRING);
152 char const* const expected = lua_tostring (L, -1);
155 got = lua_typename (L, lua_type (L, index));
157 char const* const msg = lua_pushfstring (
158 L, "%s expected, got %s", expected, got);
161 luaL_argerror (L, narg, msg);
169 //--------------------------------------------------------------------------
171 Validate and retrieve a Userdata on the stack.
173 The Userdata must be derived from or the same as the given base class,
174 identified by the key. If canBeConst is false, generates an error if
175 the resulting Userdata represents to a const object. We do the type check
176 first so that the error message is informative.
178 static Userdata* getClass (lua_State* L,
180 void const* baseClassKey,
186 bool mismatch = false;
189 lua_rawgetp (L, LUA_REGISTRYINDEX, baseClassKey);
190 assert (lua_istable (L, -1));
192 // Make sure we have a userdata.
193 if (lua_isuserdata (L, index))
195 // Make sure it's metatable is ours.
196 lua_getmetatable (L, index);
197 lua_rawgetp (L, -1, getIdentityKey ());
198 if (lua_isboolean (L, -1))
202 // If __const is present, object is NOT const.
203 rawgetfield (L, -1, "__const");
204 assert (lua_istable (L, -1) || lua_isnil (L, -1));
205 bool const isConst = lua_isnil (L, -1);
208 // Replace the class table with the const table if needed.
211 rawgetfield (L, -2, "__const");
212 assert (lua_istable (L, -1));
218 if (lua_rawequal (L, -1, -2))
222 // Match, now check const-ness.
223 if (isConst && !canBeConst)
225 luaL_argerror (L, index, "cannot be const");
229 ud = static_cast <Userdata*> (lua_touserdata (L, index));
235 // Replace current metatable with it's base class.
236 rawgetfield (L, -1, "__parent");
244 if (lua_isnil (L, -1))
247 // Mismatch, but its one of ours so get a type name.
248 rawgetfield (L, -1, "__type");
251 got = lua_tostring (L, -2);
275 assert (lua_type (L, -1) == LUA_TTABLE);
276 rawgetfield (L, -1, "__type");
277 assert (lua_type (L, -1) == LUA_TSTRING);
278 char const* const expected = lua_tostring (L, -1);
281 got = lua_typename (L, lua_type (L, index));
283 char const* const msg = lua_pushfstring (
284 L, "%s expected, got %s", expected, got);
286 luaL_argerror (L, index, msg);
293 virtual ~Userdata () { }
295 //--------------------------------------------------------------------------
297 Returns the Userdata* if the class on the Lua stack matches.
299 If the class does not match, a Lua error is raised.
302 static inline Userdata* getExact (lua_State* L, int index)
304 return getExactClass (L, index, ClassInfo <T>::getClassKey ());
307 //--------------------------------------------------------------------------
309 Get a pointer to the class from the Lua stack.
311 If the object is not the class or a subclass, or it violates the
312 const-ness, a Lua error is raised.
315 static inline T* get (lua_State* L, int index, bool canBeConst)
317 if (lua_isnil (L, index))
320 return static_cast <T*> (getClass (L, index,
321 ClassInfo <T>::getClassKey (), canBeConst)->getPointer ());
325 //----------------------------------------------------------------------------
327 Wraps a class object stored in a Lua userdata.
329 The lifetime of the object is managed by Lua. The object is constructed
330 inside the userdata using placement new.
333 class UserdataValue : public Userdata
336 UserdataValue <T> (UserdataValue <T> const&);
337 UserdataValue <T> operator= (UserdataValue <T> const&);
339 char m_storage [sizeof (T)];
341 inline T* getObject ()
343 // If this fails to compile it means you forgot to provide
344 // a Container specialization for your container!
346 return reinterpret_cast <T*> (&m_storage [0]);
351 Used for placement construction.
365 Push a T via placement new.
367 The caller is responsible for calling placement new using the
368 returned uninitialized storage.
370 static void* place (lua_State* const L)
372 UserdataValue <T>* const ud = new (
373 lua_newuserdata (L, sizeof (UserdataValue <T>))) UserdataValue <T> ();
374 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
375 // If this goes off it means you forgot to register the class!
376 assert (lua_istable (L, -1));
377 lua_setmetatable (L, -2);
378 return ud->getPointer ();
382 Push T via copy construction from U.
385 static inline void push (lua_State* const L, U const& u)
387 new (place (L)) U (u);
391 //----------------------------------------------------------------------------
393 Wraps a pointer to a class object inside a Lua userdata.
395 The lifetime of the object is managed by C++.
397 class UserdataPtr : public Userdata
400 UserdataPtr (UserdataPtr const&);
401 UserdataPtr operator= (UserdataPtr const&);
404 /** Push non-const pointer to object using metatable key.
406 static void push (lua_State* L, void* const p, void const* const key)
410 new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (p);
411 lua_rawgetp (L, LUA_REGISTRYINDEX, key);
412 // If this goes off it means you forgot to register the class!
413 assert (lua_istable (L, -1));
414 lua_setmetatable (L, -2);
422 /** Push const pointer to object using metatable key.
424 static void push (lua_State* L, void const* const p, void const* const key)
428 new (lua_newuserdata (L, sizeof (UserdataPtr)))
429 UserdataPtr (const_cast <void*> (p));
430 lua_rawgetp (L, LUA_REGISTRYINDEX, key);
431 // If this goes off it means you forgot to register the class!
432 assert (lua_istable (L, -1));
433 lua_setmetatable (L, -2);
441 explicit UserdataPtr (void* const p)
445 // Can't construct with a null pointer!
451 /** Push non-const pointer to object.
454 static inline void push (lua_State* const L, T* const p)
457 push (L, p, ClassInfo <T>::getClassKey ());
462 /** Push const pointer to object.
465 static inline void push (lua_State* const L, T const* const p)
468 push (L, p, ClassInfo <T>::getConstKey ());
474 //============================================================================
476 Wraps a container thet references a class object.
478 The template argument C is the container type, ContainerTraits must be
479 specialized on C or else a compile error will result.
482 class UserdataShared : public Userdata
485 UserdataShared (UserdataShared <C> const&);
486 UserdataShared <C>& operator= (UserdataShared <C> const&);
488 typedef typename TypeTraits::removeConst <
489 typename ContainerTraits <C>::Type>::Type T;
500 Construct from a container to the class or a derived class.
503 explicit UserdataShared (U const& u) : m_c (u)
505 m_p = const_cast <void*> (reinterpret_cast <void const*> (
506 (ContainerTraits <C>::get (m_c))));
510 Construct from a pointer to the class or a derived class.
513 explicit UserdataShared (U* u) : m_c (u)
515 m_p = const_cast <void*> (reinterpret_cast <void const*> (
516 (ContainerTraits <C>::get (m_c))));
520 //----------------------------------------------------------------------------
526 template <class C, bool makeObjectConst>
527 struct UserdataSharedHelper
529 typedef typename TypeTraits::removeConst <
530 typename ContainerTraits <C>::Type>::Type T;
532 static void push (lua_State* L, C const& c)
534 if (ContainerTraits <C>::get (c) != 0)
536 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
537 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
538 // If this goes off it means the class T is unregistered!
539 assert (lua_istable (L, -1));
540 lua_setmetatable (L, -2);
548 static void push (lua_State* L, T* const t)
552 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
553 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
554 // If this goes off it means the class T is unregistered!
555 assert (lua_istable (L, -1));
556 lua_setmetatable (L, -2);
567 struct UserdataSharedHelper <C, true>
569 typedef typename TypeTraits::removeConst <
570 typename ContainerTraits <C>::Type>::Type T;
572 static void push (lua_State* L, C const& c)
574 if (ContainerTraits <C>::get (c) != 0)
576 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
577 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
578 // If this goes off it means the class T is unregistered!
579 assert (lua_istable (L, -1));
580 lua_setmetatable (L, -2);
588 static void push (lua_State* L, T* const t)
592 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
593 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
594 // If this goes off it means the class T is unregistered!
595 assert (lua_istable (L, -1));
596 lua_setmetatable (L, -2);
608 The container controls the object lifetime. Typically this will be a
609 lifetime shared by C++ and Lua using a reference count. Because of type
610 erasure, containers like std::shared_ptr will not work. Containers must
611 either be of the intrusive variety, or in the style of the RefCountedPtr
612 type provided by LuaBridge (that uses a global hash table).
614 template <class C, bool byContainer, bool isEnum>
617 static inline void push (lua_State* L, C const& c)
619 UserdataSharedHelper <C,
620 TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, c);
623 typedef typename TypeTraits::removeConst <
624 typename ContainerTraits <C>::Type>::Type T;
626 static inline C get (lua_State* L, int index)
628 return Userdata::get <T> (L, index, true);
635 Lifetime is managed by Lua. A C++ function which accesses a pointer or
636 reference to an object outside the activation record in which it was
637 retrieved may result in undefined behavior if Lua garbage collected it.
640 struct StackHelper <T, false, false>
642 static inline void push (lua_State* L, T const& t)
644 UserdataValue <T>::push (L, t);
647 static inline T const& get (lua_State* L, int index)
649 return *Userdata::get <T> (L, index, true);
654 struct StackHelper <T, false, true>
656 static inline void push (lua_State* L, T const& t)
658 int v = static_cast <int> (t);
659 lua_pushinteger (L, static_cast <lua_Integer> (v));
662 static inline T get (lua_State* L, int index)
664 int v = static_cast <int> (luaL_checkinteger (L, index));
669 //==============================================================================
672 Lua stack conversions for class objects passed by value.
678 static inline void push (lua_State* L, T const& t)
681 TypeTraits::isContainer <T>::value,
682 TypeTraits::isEnum<T>::value>::push (L, t);
685 static inline T get (lua_State* L, int index)
687 return StackHelper <T,
688 TypeTraits::isContainer <T>::value,
689 TypeTraits::isEnum<T>::value>::get (L, index);
693 //------------------------------------------------------------------------------
695 Lua stack conversions for pointers and references to class objects.
697 Lifetime is managed by C++. Lua code which remembers a reference to the
698 value may result in undefined behavior if C++ destroys the object. The
699 handling of the const and volatile qualifiers happens in UserdataPtr.
706 static inline void push (lua_State* L, T* const p)
708 UserdataPtr::push (L, p);
711 static inline T* get (lua_State* L, int index)
713 return Userdata::get <T> (L, index, false);
717 // Strips the const off the right side of *
719 struct Stack <T* const>
721 static inline void push (lua_State* L, T* const p)
723 UserdataPtr::push (L, p);
726 static inline T* get (lua_State* L, int index)
728 return Userdata::get <T> (L, index, false);
734 struct Stack <T const*>
736 static inline void push (lua_State* L, T const* const p)
738 UserdataPtr::push (L, p);
741 static inline T const* get (lua_State* L, int index)
743 return Userdata::get <T> (L, index, true);
747 // Strips the const off the right side of *
749 struct Stack <T const* const>
751 static inline void push (lua_State* L, T const* const p)
753 UserdataPtr::push (L, p);
756 static inline T const* get (lua_State* L, int index)
758 return Userdata::get <T> (L, index, true);
766 static inline void push (lua_State* L, T& t)
768 UserdataPtr::push (L, &t);
771 static T& get (lua_State* L, int index)
773 T* const t = Userdata::get <T> (L, index, false);
775 luaL_error (L, "nil passed to reference");
780 template <class C, bool byContainer>
781 struct RefStackHelper
783 typedef C return_type;
785 static inline void push (lua_State* L, C const& t)
787 UserdataSharedHelper <C,
788 TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, t);
791 typedef typename TypeTraits::removeConst <
792 typename ContainerTraits <C>::Type>::Type T;
794 static return_type get (lua_State* L, int index)
796 return Userdata::get <T> (L, index, true);
801 struct RefStackHelper <T, false>
803 typedef T const& return_type;
805 static inline void push (lua_State* L, T const& t)
807 UserdataPtr::push (L, &t);
810 static return_type get (lua_State* L, int index)
812 T const* const t = Userdata::get <T> (L, index, true);
815 luaL_error (L, "nil passed to reference");
821 // reference to const
823 struct Stack <T const&>
825 typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> helper_t;
827 static inline void push (lua_State* L, T const& t)
829 helper_t::push (L, t);
832 static typename helper_t::return_type get (lua_State* L, int index)
834 return helper_t::get (L, index);