add LuaBridge
[ardour.git] / libs / lua / LuaBridge / detail / Userdata.h
1 //------------------------------------------------------------------------------
2 /*
3   https://github.com/vinniefalco/LuaBridge
4   
5   Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
6
7   License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
8
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:
15
16   The above copyright notice and this permission notice shall be included in all
17   copies or substantial portions of the Software.
18
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
25   SOFTWARE.
26 */
27 //==============================================================================
28
29 //==============================================================================
30 /**
31   Return the identity pointer for our lightuserdata tokens.
32
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
36   used.
37
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
42   following:
43
44   Notes:
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.
52 */
53 inline void* getIdentityKey ()
54 {
55   static char value;
56   return &value;
57 }
58
59 /**
60   Interface to a class pointer retrievable from a userdata.
61 */
62 class Userdata
63 {
64 protected:
65   void* m_p; // subclasses must set this
66
67   //--------------------------------------------------------------------------
68   /**
69     Get an untyped pointer to the contained class.
70   */
71   inline void* const getPointer ()
72   {
73     return m_p;
74   }
75
76 private:
77   //--------------------------------------------------------------------------
78   /**
79     Validate and retrieve a Userdata on the stack.
80
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
83     __gc metamethod.
84   */
85   static Userdata* getExactClass (lua_State* L,
86                                   int narg,
87                                   void const* classKey)
88   {
89     Userdata* ud = 0;
90     int const index = lua_absindex (L, narg);
91
92     bool mismatch = false;
93     char const* got = 0;
94
95     lua_rawgetp (L, LUA_REGISTRYINDEX, classKey);
96     assert (lua_istable (L, -1));
97
98     // Make sure we have a userdata.
99     if (!lua_isuserdata (L, index))
100       mismatch = true;
101
102     // Make sure it's metatable is ours.
103     if (!mismatch)
104     {
105       lua_getmetatable (L, index);
106       lua_rawgetp (L, -1, getIdentityKey ());
107       if (lua_isboolean (L, -1))
108       {
109         lua_pop (L, 1);
110       }
111       else
112       {
113         lua_pop (L, 2);
114         mismatch = true;
115       }      
116     }
117
118     if (!mismatch)
119     {
120       if (lua_rawequal (L, -1, -2))
121       {
122         // Matches class table.
123         lua_pop (L, 2);
124         ud = static_cast <Userdata*> (lua_touserdata (L, index));
125       }
126       else
127       {
128         rawgetfield (L, -2, "__const");
129         if (lua_rawequal (L, -1, -2))
130         {
131           // Matches const table
132           lua_pop (L, 3);
133           ud = static_cast <Userdata*> (lua_touserdata (L, index));
134         }
135         else
136         {
137           // Mismatch, but its one of ours so get a type name.
138           rawgetfield (L, -2, "__type");
139           lua_insert (L, -4);
140           lua_pop (L, 2);
141           got = lua_tostring (L, -2);
142           mismatch = true;
143         }
144       }
145     }
146
147     if (mismatch)
148     {
149       rawgetfield (L, -1, "__type");
150       assert (lua_type (L, -1) == LUA_TSTRING);
151       char const* const expected = lua_tostring (L, -1);
152
153       if (got == 0)
154         got = lua_typename (L, lua_type (L, index));
155
156       char const* const msg = lua_pushfstring (
157         L, "%s expected, got %s", expected, got);
158
159       if (narg > 0)
160         luaL_argerror (L, narg, msg);
161       else
162         lua_error (L);
163     }
164
165     return ud;
166   }
167
168   //--------------------------------------------------------------------------
169   /**
170     Validate and retrieve a Userdata on the stack.
171
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.
176   */
177   static Userdata* getClass (lua_State* L,
178                              int index,
179                              void const* baseClassKey,
180                              bool canBeConst)
181   {
182     assert (index > 0);
183     Userdata* ud = 0;
184
185     bool mismatch = false;
186     char const* got = 0;
187
188     lua_rawgetp (L, LUA_REGISTRYINDEX, baseClassKey);
189     assert (lua_istable (L, -1));
190
191     // Make sure we have a userdata.
192     if (lua_isuserdata (L, index))
193     {
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))
198       {
199         lua_pop (L, 1);
200
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);
205         lua_pop (L, 1);
206
207         // Replace the class table with the const table if needed.
208         if (isConst)
209         {
210           rawgetfield (L, -2, "__const");
211           assert (lua_istable (L, -1));
212           lua_replace (L, -3);
213         }
214
215         for (;;)
216         {
217           if (lua_rawequal (L, -1, -2))
218           {
219             lua_pop (L, 2);
220
221             // Match, now check const-ness.
222             if (isConst && !canBeConst)
223             {
224               luaL_argerror (L, index, "cannot be const");
225             }
226             else
227             {
228               ud = static_cast <Userdata*> (lua_touserdata (L, index));
229               break;
230             }
231           }
232           else
233           {
234             // Replace current metatable with it's base class.
235             rawgetfield (L, -1, "__parent");
236 /*
237 ud
238 class metatable
239 ud metatable
240 ud __parent (nil)
241 */
242
243             if (lua_isnil (L, -1))
244             {
245               lua_remove (L, -1);
246               // Mismatch, but its one of ours so get a type name.
247               rawgetfield (L, -1, "__type");
248               lua_insert (L, -3);
249               lua_pop (L, 1);
250               got = lua_tostring (L, -2);
251               mismatch = true;
252               break;
253             }
254             else
255             {
256               lua_remove (L, -2);
257             }
258           }
259         }
260       }
261       else
262       {
263         lua_pop (L, 2);
264         mismatch = true;
265       }      
266     }
267     else
268     {
269       mismatch = true;
270     }
271
272     if (mismatch)
273     {
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);
278
279       if (got == 0)
280         got = lua_typename (L, lua_type (L, index));
281
282       char const* const msg = lua_pushfstring (
283         L, "%s expected, got %s", expected, got);
284
285       luaL_argerror (L, index, msg);
286     }
287
288     return ud;
289   }
290
291 public:
292   virtual ~Userdata () { }
293
294   //--------------------------------------------------------------------------
295   /**
296     Returns the Userdata* if the class on the Lua stack matches.
297
298     If the class does not match, a Lua error is raised.
299   */
300   template <class T>
301   static inline Userdata* getExact (lua_State* L, int index)
302   {
303     return getExactClass (L, index, ClassInfo <T>::getClassKey ());
304   }
305
306   //--------------------------------------------------------------------------
307   /**
308     Get a pointer to the class from the Lua stack.
309
310     If the object is not the class or a subclass, or it violates the
311     const-ness, a Lua error is raised.
312   */
313   template <class T>
314   static inline T* get (lua_State* L, int index, bool canBeConst)
315   {
316     if (lua_isnil (L, index))
317       return 0;
318     else
319       return static_cast <T*> (getClass (L, index,
320         ClassInfo <T>::getClassKey (), canBeConst)->getPointer ());
321   }
322 };
323
324 //----------------------------------------------------------------------------
325 /**
326   Wraps a class object stored in a Lua userdata.
327
328   The lifetime of the object is managed by Lua. The object is constructed
329   inside the userdata using placement new.
330 */
331 template <class T>
332 class UserdataValue : public Userdata
333 {
334 private:
335   UserdataValue <T> (UserdataValue <T> const&);
336   UserdataValue <T> operator= (UserdataValue <T> const&);
337
338   char m_storage [sizeof (T)];
339
340   inline T* getObject ()
341   {
342     // If this fails to compile it means you forgot to provide
343     // a Container specialization for your container!
344     //
345     return reinterpret_cast <T*> (&m_storage [0]);
346   }
347
348 private:
349   /**
350     Used for placement construction.
351   */
352   UserdataValue ()
353   {
354     m_p = getObject ();
355   }
356
357   ~UserdataValue ()
358   {
359     getObject ()->~T ();
360   }
361
362 public:
363   /**
364     Push a T via placement new.
365
366     The caller is responsible for calling placement new using the
367     returned uninitialized storage.
368   */
369   static void* place (lua_State* const L)
370   {
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 ();
378   }
379
380   /**
381     Push T via copy construction from U.
382   */
383   template <class U>
384   static inline void push (lua_State* const L, U const& u)
385   {
386     new (place (L)) U (u);
387   }
388 };
389
390 //----------------------------------------------------------------------------
391 /**
392   Wraps a pointer to a class object inside a Lua userdata.
393
394   The lifetime of the object is managed by C++.
395 */
396 class UserdataPtr : public Userdata
397 {
398 private:
399   UserdataPtr (UserdataPtr const&);
400   UserdataPtr operator= (UserdataPtr const&);
401
402 private:
403   /** Push non-const pointer to object using metatable key.
404   */
405   static void push (lua_State* L, void* const p, void const* const key)
406   {
407     if (p)
408     {
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);
414     }
415     else
416     {
417       lua_pushnil (L);
418     }
419   }
420
421   /** Push const pointer to object using metatable key.
422   */
423   static void push (lua_State* L, void const* const p, void const* const key)
424   {
425     if (p)
426     {
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);
433     }
434     else
435     {
436       lua_pushnil (L);
437     }
438   }
439
440   explicit UserdataPtr (void* const p)
441   {
442     m_p = p;
443
444     // Can't construct with a null pointer!
445     //
446     assert (m_p != 0);
447   }
448
449 public:
450   /** Push non-const pointer to object.
451   */
452   template <class T>
453   static inline void push (lua_State* const L, T* const p)
454   {
455     if (p)
456       push (L, p, ClassInfo <T>::getClassKey ());
457     else
458       lua_pushnil (L);
459   }
460
461   /** Push const pointer to object.
462   */
463   template <class T>
464   static inline void push (lua_State* const L, T const* const p)
465   {
466     if (p)
467       push (L, p, ClassInfo <T>::getConstKey ());
468     else
469       lua_pushnil (L);
470   }
471 };
472
473 //============================================================================
474 /**
475   Wraps a container thet references a class object.
476
477   The template argument C is the container type, ContainerTraits must be
478   specialized on C or else a compile error will result.
479 */
480 template <class C>
481 class UserdataShared : public Userdata
482 {
483 private:
484   UserdataShared (UserdataShared <C> const&);
485   UserdataShared <C>& operator= (UserdataShared <C> const&);
486
487   typedef typename TypeTraits::removeConst <
488     typename ContainerTraits <C>::Type>::Type T;
489
490   C m_c;
491
492 private:
493   ~UserdataShared ()
494   {
495   }
496
497 public:
498   /**
499     Construct from a container to the class or a derived class.
500   */
501   template <class U>
502   explicit UserdataShared (U const& u) : m_c (u)
503   {
504     m_p = const_cast <void*> (reinterpret_cast <void const*> (
505         (ContainerTraits <C>::get (m_c))));
506   }
507
508   /**
509     Construct from a pointer to the class or a derived class.
510   */
511   template <class U>
512   explicit UserdataShared (U* u) : m_c (u)
513   {
514     m_p = const_cast <void*> (reinterpret_cast <void const*> (
515         (ContainerTraits <C>::get (m_c))));
516   }
517 };
518
519 //----------------------------------------------------------------------------
520 //
521 // SFINAE helpers.
522 //
523
524 // non-const objects
525 template <class C, bool makeObjectConst>
526 struct UserdataSharedHelper
527 {
528   typedef typename TypeTraits::removeConst <
529     typename ContainerTraits <C>::Type>::Type T;
530
531   static void push (lua_State* L, C const& c)
532   {
533     if (ContainerTraits <C>::get (c) != 0)
534     {
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);
540     }
541     else
542     {
543       lua_pushnil (L);
544     }
545   }
546
547   static void push (lua_State* L, T* const t)
548   {
549     if (t)
550     {
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);
556     }
557     else
558     {
559       lua_pushnil (L);
560     }
561   }
562 };
563
564 // const objects
565 template <class C>
566 struct UserdataSharedHelper <C, true>
567 {
568   typedef typename TypeTraits::removeConst <
569     typename ContainerTraits <C>::Type>::Type T;
570
571   static void push (lua_State* L, C const& c)
572   {
573     if (ContainerTraits <C>::get (c) != 0)
574     {
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);
580     }
581     else
582     {
583       lua_pushnil (L);
584     }
585   }
586
587   static void push (lua_State* L, T* const t)
588   {
589     if (t)
590     {
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);
596     }
597     else
598     {
599       lua_pushnil (L);
600     }
601   }
602 };
603
604 /**
605   Pass by container.
606
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).
612 */
613 template <class C, bool byContainer>
614 struct StackHelper
615 {
616   static inline void push (lua_State* L, C const& c)
617   {
618     UserdataSharedHelper <C,
619       TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, c);
620   }
621
622   typedef typename TypeTraits::removeConst <
623     typename ContainerTraits <C>::Type>::Type T;
624
625   static inline C get (lua_State* L, int index)
626   {
627     return Userdata::get <T> (L, index, true);
628   }
629 };
630
631 /**
632   Pass by value.
633
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.
637 */
638 template <class T>
639 struct StackHelper <T, false>
640 {
641   static inline void push (lua_State* L, T const& t)
642   {
643     UserdataValue <T>::push (L, t);
644   }
645
646   static inline T const& get (lua_State* L, int index)
647   {
648     return *Userdata::get <T> (L, index, true);
649   }
650 };
651
652 //==============================================================================
653
654 /**
655   Lua stack conversions for class objects passed by value.
656 */
657 template <class T>
658 struct Stack
659 {
660 public:
661   static inline void push (lua_State* L, T const& t)
662   {
663     StackHelper <T,
664       TypeTraits::isContainer <T>::value>::push (L, t);
665   }
666
667   static inline T get (lua_State* L, int index)
668   {
669     return StackHelper <T,
670       TypeTraits::isContainer <T>::value>::get (L, index);
671   }
672 };
673
674 //------------------------------------------------------------------------------
675 /**
676   Lua stack conversions for pointers and references to class objects.
677
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.
681 */
682
683 // pointer
684 template <class T>
685 struct Stack <T*>
686 {
687   static inline void push (lua_State* L, T* const p)
688   {
689     UserdataPtr::push (L, p);
690   }
691
692   static inline T* const get (lua_State* L, int index)
693   {
694     return Userdata::get <T> (L, index, false);
695   }
696 };
697
698 // Strips the const off the right side of *
699 template <class T>
700 struct Stack <T* const>
701 {
702   static inline void push (lua_State* L, T* const p)
703   {
704     UserdataPtr::push (L, p);
705   }
706
707   static inline T* const get (lua_State* L, int index)
708   {
709     return Userdata::get <T> (L, index, false);
710   }
711 };
712
713 // pointer to const
714 template <class T>
715 struct Stack <T const*>
716 {
717   static inline void push (lua_State* L, T const* const p)
718   {
719     UserdataPtr::push (L, p);
720   }
721
722   static inline T const* const get (lua_State* L, int index)
723   {
724     return Userdata::get <T> (L, index, true);
725   }
726 };
727
728 // Strips the const off the right side of *
729 template <class T>
730 struct Stack <T const* const>
731 {
732   static inline void push (lua_State* L, T const* const p)
733   {
734     UserdataPtr::push (L, p);
735   }
736
737   static inline T const* const get (lua_State* L, int index)
738   {
739     return Userdata::get <T> (L, index, true);
740   }
741 };
742
743 // reference
744 template <class T>
745 struct Stack <T&>
746 {
747   static inline void push (lua_State* L, T& t)
748   {
749     UserdataPtr::push (L, &t);
750   }
751
752   static T& get (lua_State* L, int index)
753   {
754     T* const t = Userdata::get <T> (L, index, false);
755     if (!t)
756       luaL_error (L, "nil passed to reference");
757     return *t;
758   }
759 };
760
761 template <class C, bool byContainer>
762 struct RefStackHelper
763 {
764   typedef C return_type;  
765         
766   static inline void push (lua_State* L, C const& t)
767   {
768     UserdataSharedHelper <C,
769       TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, t);
770   }
771
772   typedef typename TypeTraits::removeConst <
773     typename ContainerTraits <C>::Type>::Type T;
774
775   static return_type get (lua_State* L, int index)
776   {
777     return Userdata::get <T> (L, index, true);
778   }
779 };
780
781 template <class T>
782 struct RefStackHelper <T, false>
783 {
784   typedef T const& return_type;  
785         
786         static inline void push (lua_State* L, T const& t)
787         {
788           UserdataPtr::push (L, &t);
789         }
790
791   static return_type get (lua_State* L, int index)
792   {
793     T const* const t = Userdata::get <T> (L, index, true);
794
795     if (!t)
796       luaL_error (L, "nil passed to reference");
797     return *t;
798   }
799     
800 };
801
802 // reference to const
803 template <class T>
804 struct Stack <T const&>
805 {
806   typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> helper_t;
807   
808   static inline void push (lua_State* L, T const& t)
809   {
810     helper_t::push (L, t);
811   }
812
813   static typename helper_t::return_type get (lua_State* L, int index)
814   {
815     return helper_t::get (L, index);
816   }
817 };