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