1 //------------------------------------------------------------------------------
3 https://github.com/vinniefalco/LuaBridge
5 Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
7 License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
16 The above copyright notice and this permission notice shall be included in all
17 copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 //==============================================================================
29 //==============================================================================
31 Return the identity pointer for our lightuserdata tokens.
33 LuaBridge metatables are tagged with a security "token." The token is a
34 lightuserdata created from the identity pointer, used as a key in the
35 metatable. The value is a boolean = true, although any value could have been
38 Because of Lua's dynamic typing and our improvised system of imposing C++
39 class structure, there is the possibility that executing scripts may
40 knowingly or unknowingly cause invalid data to get passed to the C functions
41 created by LuaBridge. In particular, our security model addresses the
45 1. Scripts cannot create a userdata (ignoring the debug lib).
46 2. Scripts cannot create a lightuserdata (ignoring the debug lib).
47 3. Scripts cannot set the metatable on a userdata.
48 4. Our identity key is a unique pointer in the process.
49 5. Our metatables have a lightuserdata identity key / value pair.
50 6. Our metatables have "__metatable" set to a boolean = false.
51 7. Our lightuserdata is unique.
53 inline void* getIdentityKey ()
60 Interface to a class pointer retrievable from a userdata.
65 void* m_p; // subclasses must set this
67 //--------------------------------------------------------------------------
69 Get an untyped pointer to the contained class.
71 inline void* const getPointer ()
77 //--------------------------------------------------------------------------
79 Validate and retrieve a Userdata on the stack.
81 The Userdata must exactly match the corresponding class table or
82 const table, or else a Lua error is raised. This is used for the
85 static Userdata* getExactClass (lua_State* L,
90 int const index = lua_absindex (L, narg);
92 bool mismatch = false;
95 lua_rawgetp (L, LUA_REGISTRYINDEX, classKey);
96 assert (lua_istable (L, -1));
98 // Make sure we have a userdata.
99 if (!lua_isuserdata (L, index))
102 // Make sure it's metatable is ours.
105 lua_getmetatable (L, index);
106 lua_rawgetp (L, -1, getIdentityKey ());
107 if (lua_isboolean (L, -1))
120 if (lua_rawequal (L, -1, -2))
122 // Matches class table.
124 ud = static_cast <Userdata*> (lua_touserdata (L, index));
128 rawgetfield (L, -2, "__const");
129 if (lua_rawequal (L, -1, -2))
131 // Matches const table
133 ud = static_cast <Userdata*> (lua_touserdata (L, index));
137 // Mismatch, but its one of ours so get a type name.
138 rawgetfield (L, -2, "__type");
141 got = lua_tostring (L, -2);
149 rawgetfield (L, -1, "__type");
150 assert (lua_type (L, -1) == LUA_TSTRING);
151 char const* const expected = lua_tostring (L, -1);
154 got = lua_typename (L, lua_type (L, index));
156 char const* const msg = lua_pushfstring (
157 L, "%s expected, got %s", expected, got);
160 luaL_argerror (L, narg, msg);
168 //--------------------------------------------------------------------------
170 Validate and retrieve a Userdata on the stack.
172 The Userdata must be derived from or the same as the given base class,
173 identified by the key. If canBeConst is false, generates an error if
174 the resulting Userdata represents to a const object. We do the type check
175 first so that the error message is informative.
177 static Userdata* getClass (lua_State* L,
179 void const* baseClassKey,
185 bool mismatch = false;
188 lua_rawgetp (L, LUA_REGISTRYINDEX, baseClassKey);
189 assert (lua_istable (L, -1));
191 // Make sure we have a userdata.
192 if (lua_isuserdata (L, index))
194 // Make sure it's metatable is ours.
195 lua_getmetatable (L, index);
196 lua_rawgetp (L, -1, getIdentityKey ());
197 if (lua_isboolean (L, -1))
201 // If __const is present, object is NOT const.
202 rawgetfield (L, -1, "__const");
203 assert (lua_istable (L, -1) || lua_isnil (L, -1));
204 bool const isConst = lua_isnil (L, -1);
207 // Replace the class table with the const table if needed.
210 rawgetfield (L, -2, "__const");
211 assert (lua_istable (L, -1));
217 if (lua_rawequal (L, -1, -2))
221 // Match, now check const-ness.
222 if (isConst && !canBeConst)
224 luaL_argerror (L, index, "cannot be const");
228 ud = static_cast <Userdata*> (lua_touserdata (L, index));
234 // Replace current metatable with it's base class.
235 rawgetfield (L, -1, "__parent");
243 if (lua_isnil (L, -1))
246 // Mismatch, but its one of ours so get a type name.
247 rawgetfield (L, -1, "__type");
250 got = lua_tostring (L, -2);
274 assert (lua_type (L, -1) == LUA_TTABLE);
275 rawgetfield (L, -1, "__type");
276 assert (lua_type (L, -1) == LUA_TSTRING);
277 char const* const expected = lua_tostring (L, -1);
280 got = lua_typename (L, lua_type (L, index));
282 char const* const msg = lua_pushfstring (
283 L, "%s expected, got %s", expected, got);
285 luaL_argerror (L, index, msg);
292 virtual ~Userdata () { }
294 //--------------------------------------------------------------------------
296 Returns the Userdata* if the class on the Lua stack matches.
298 If the class does not match, a Lua error is raised.
301 static inline Userdata* getExact (lua_State* L, int index)
303 return getExactClass (L, index, ClassInfo <T>::getClassKey ());
306 //--------------------------------------------------------------------------
308 Get a pointer to the class from the Lua stack.
310 If the object is not the class or a subclass, or it violates the
311 const-ness, a Lua error is raised.
314 static inline T* get (lua_State* L, int index, bool canBeConst)
316 if (lua_isnil (L, index))
319 return static_cast <T*> (getClass (L, index,
320 ClassInfo <T>::getClassKey (), canBeConst)->getPointer ());
324 //----------------------------------------------------------------------------
326 Wraps a class object stored in a Lua userdata.
328 The lifetime of the object is managed by Lua. The object is constructed
329 inside the userdata using placement new.
332 class UserdataValue : public Userdata
335 UserdataValue <T> (UserdataValue <T> const&);
336 UserdataValue <T> operator= (UserdataValue <T> const&);
338 char m_storage [sizeof (T)];
340 inline T* getObject ()
342 // If this fails to compile it means you forgot to provide
343 // a Container specialization for your container!
345 return reinterpret_cast <T*> (&m_storage [0]);
350 Used for placement construction.
364 Push a T via placement new.
366 The caller is responsible for calling placement new using the
367 returned uninitialized storage.
369 static void* place (lua_State* const L)
371 UserdataValue <T>* const ud = new (
372 lua_newuserdata (L, sizeof (UserdataValue <T>))) UserdataValue <T> ();
373 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
374 // If this goes off it means you forgot to register the class!
375 assert (lua_istable (L, -1));
376 lua_setmetatable (L, -2);
377 return ud->getPointer ();
381 Push T via copy construction from U.
384 static inline void push (lua_State* const L, U const& u)
386 new (place (L)) U (u);
390 //----------------------------------------------------------------------------
392 Wraps a pointer to a class object inside a Lua userdata.
394 The lifetime of the object is managed by C++.
396 class UserdataPtr : public Userdata
399 UserdataPtr (UserdataPtr const&);
400 UserdataPtr operator= (UserdataPtr const&);
403 /** Push non-const pointer to object using metatable key.
405 static void push (lua_State* L, void* const p, void const* const key)
409 new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (p);
410 lua_rawgetp (L, LUA_REGISTRYINDEX, key);
411 // If this goes off it means you forgot to register the class!
412 assert (lua_istable (L, -1));
413 lua_setmetatable (L, -2);
421 /** Push const pointer to object using metatable key.
423 static void push (lua_State* L, void const* const p, void const* const key)
427 new (lua_newuserdata (L, sizeof (UserdataPtr)))
428 UserdataPtr (const_cast <void*> (p));
429 lua_rawgetp (L, LUA_REGISTRYINDEX, key);
430 // If this goes off it means you forgot to register the class!
431 assert (lua_istable (L, -1));
432 lua_setmetatable (L, -2);
440 explicit UserdataPtr (void* const p)
444 // Can't construct with a null pointer!
450 /** Push non-const pointer to object.
453 static inline void push (lua_State* const L, T* const p)
456 push (L, p, ClassInfo <T>::getClassKey ());
461 /** Push const pointer to object.
464 static inline void push (lua_State* const L, T const* const p)
467 push (L, p, ClassInfo <T>::getConstKey ());
473 //============================================================================
475 Wraps a container thet references a class object.
477 The template argument C is the container type, ContainerTraits must be
478 specialized on C or else a compile error will result.
481 class UserdataShared : public Userdata
484 UserdataShared (UserdataShared <C> const&);
485 UserdataShared <C>& operator= (UserdataShared <C> const&);
487 typedef typename TypeTraits::removeConst <
488 typename ContainerTraits <C>::Type>::Type T;
499 Construct from a container to the class or a derived class.
502 explicit UserdataShared (U const& u) : m_c (u)
504 m_p = const_cast <void*> (reinterpret_cast <void const*> (
505 (ContainerTraits <C>::get (m_c))));
509 Construct from a pointer to the class or a derived class.
512 explicit UserdataShared (U* u) : m_c (u)
514 m_p = const_cast <void*> (reinterpret_cast <void const*> (
515 (ContainerTraits <C>::get (m_c))));
519 //----------------------------------------------------------------------------
525 template <class C, bool makeObjectConst>
526 struct UserdataSharedHelper
528 typedef typename TypeTraits::removeConst <
529 typename ContainerTraits <C>::Type>::Type T;
531 static void push (lua_State* L, C const& c)
533 if (ContainerTraits <C>::get (c) != 0)
535 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
536 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
537 // If this goes off it means the class T is unregistered!
538 assert (lua_istable (L, -1));
539 lua_setmetatable (L, -2);
547 static void push (lua_State* L, T* const t)
551 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
552 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
553 // If this goes off it means the class T is unregistered!
554 assert (lua_istable (L, -1));
555 lua_setmetatable (L, -2);
566 struct UserdataSharedHelper <C, true>
568 typedef typename TypeTraits::removeConst <
569 typename ContainerTraits <C>::Type>::Type T;
571 static void push (lua_State* L, C const& c)
573 if (ContainerTraits <C>::get (c) != 0)
575 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
576 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
577 // If this goes off it means the class T is unregistered!
578 assert (lua_istable (L, -1));
579 lua_setmetatable (L, -2);
587 static void push (lua_State* L, T* const t)
591 new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
592 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
593 // If this goes off it means the class T is unregistered!
594 assert (lua_istable (L, -1));
595 lua_setmetatable (L, -2);
607 The container controls the object lifetime. Typically this will be a
608 lifetime shared by C++ and Lua using a reference count. Because of type
609 erasure, containers like std::shared_ptr will not work. Containers must
610 either be of the intrusive variety, or in the style of the RefCountedPtr
611 type provided by LuaBridge (that uses a global hash table).
613 template <class C, bool byContainer>
616 static inline void push (lua_State* L, C const& c)
618 UserdataSharedHelper <C,
619 TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, c);
622 typedef typename TypeTraits::removeConst <
623 typename ContainerTraits <C>::Type>::Type T;
625 static inline C get (lua_State* L, int index)
627 return Userdata::get <T> (L, index, true);
634 Lifetime is managed by Lua. A C++ function which accesses a pointer or
635 reference to an object outside the activation record in which it was
636 retrieved may result in undefined behavior if Lua garbage collected it.
639 struct StackHelper <T, false>
641 static inline void push (lua_State* L, T const& t)
643 UserdataValue <T>::push (L, t);
646 static inline T const& get (lua_State* L, int index)
648 return *Userdata::get <T> (L, index, true);
652 //==============================================================================
655 Lua stack conversions for class objects passed by value.
661 static inline void push (lua_State* L, T const& t)
664 TypeTraits::isContainer <T>::value>::push (L, t);
667 static inline T get (lua_State* L, int index)
669 return StackHelper <T,
670 TypeTraits::isContainer <T>::value>::get (L, index);
674 //------------------------------------------------------------------------------
676 Lua stack conversions for pointers and references to class objects.
678 Lifetime is managed by C++. Lua code which remembers a reference to the
679 value may result in undefined behavior if C++ destroys the object. The
680 handling of the const and volatile qualifiers happens in UserdataPtr.
687 static inline void push (lua_State* L, T* const p)
689 UserdataPtr::push (L, p);
692 static inline T* const get (lua_State* L, int index)
694 return Userdata::get <T> (L, index, false);
698 // Strips the const off the right side of *
700 struct Stack <T* const>
702 static inline void push (lua_State* L, T* const p)
704 UserdataPtr::push (L, p);
707 static inline T* const get (lua_State* L, int index)
709 return Userdata::get <T> (L, index, false);
715 struct Stack <T const*>
717 static inline void push (lua_State* L, T const* const p)
719 UserdataPtr::push (L, p);
722 static inline T const* const get (lua_State* L, int index)
724 return Userdata::get <T> (L, index, true);
728 // Strips the const off the right side of *
730 struct Stack <T const* const>
732 static inline void push (lua_State* L, T const* const p)
734 UserdataPtr::push (L, p);
737 static inline T const* const get (lua_State* L, int index)
739 return Userdata::get <T> (L, index, true);
747 static inline void push (lua_State* L, T& t)
749 UserdataPtr::push (L, &t);
752 static T& get (lua_State* L, int index)
754 T* const t = Userdata::get <T> (L, index, false);
756 luaL_error (L, "nil passed to reference");
761 template <class C, bool byContainer>
762 struct RefStackHelper
764 typedef C return_type;
766 static inline void push (lua_State* L, C const& t)
768 UserdataSharedHelper <C,
769 TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, t);
772 typedef typename TypeTraits::removeConst <
773 typename ContainerTraits <C>::Type>::Type T;
775 static return_type get (lua_State* L, int index)
777 return Userdata::get <T> (L, index, true);
782 struct RefStackHelper <T, false>
784 typedef T const& return_type;
786 static inline void push (lua_State* L, T const& t)
788 UserdataPtr::push (L, &t);
791 static return_type get (lua_State* L, int index)
793 T const* const t = Userdata::get <T> (L, index, true);
796 luaL_error (L, "nil passed to reference");
802 // reference to const
804 struct Stack <T const&>
806 typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> helper_t;
808 static inline void push (lua_State* L, T const& t)
810 helper_t::push (L, t);
813 static typename helper_t::return_type get (lua_State* L, int index)
815 return helper_t::get (L, index);