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   Copyright 2007, Nathan Reed
8 
9   License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
10 
11   Permission is hereby granted, free of charge, to any person obtaining a copy
12   of this software and associated documentation files (the "Software"), to deal
13   in the Software without restriction, including without limitation the rights
14   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15   copies of the Software, and to permit persons to whom the Software is
16   furnished to do so, subject to the following conditions:
17 
18   The above copyright notice and this permission notice shall be included in all
19   copies or substantial portions of the Software.
20 
21   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27   SOFTWARE.
28 */
29 //==============================================================================
30 
31 #ifdef LUABINDINGDOC
32 #include <iostream>
33 #include <typeinfo>
34 #include <execinfo.h>
35 #include <type_traits>
36 #include <cxxabi.h>
37 #include <memory>
38 #include <string>
39 #include <cstdlib>
40 
41 template <class T>
type_name()42 std::string type_name()
43 {
44 	typedef typename std::remove_reference<T>::type TR;
45 	std::unique_ptr<char, void(*)(void*)> own
46 		(
47 		 abi::__cxa_demangle(typeid(TR).name(), nullptr,
48 			 nullptr, nullptr),
49 		 std::free
50 		);
51 	std::string r = own != nullptr ? own.get() : typeid(TR).name();
52 	if (std::is_const<TR>::value)
53 		r += " const";
54 	if (std::is_volatile<TR>::value)
55 		r += " volatile";
56 	if (std::is_lvalue_reference<T>::value)
57 		r += "&";
58 	else if (std::is_rvalue_reference<T>::value)
59 		r += "&&";
60 	return r;
61 }
62 
63 //#define LUADOCOUT
64 
65 #ifdef LUADOCOUT // lua
66 #define KEYSTA "[\""
67 #define KEYEND "\"] = "
68 #else // JSON
69 #define KEYSTA "\""
70 #define KEYEND "\" : "
71 #endif
72 
73 #define CLASSDOC(TYPE, LUANAME, DECL, PARENTDECL) \
74   if (LuaBindingDoc::printBindings ()) { \
75     std::cout <<   "{ " << KEYSTA << "type"   << KEYEND << "  \""  << TYPE << "\",\n"; \
76     std::cout <<   "  " << KEYSTA << "lua"    << KEYEND << "   \"" << LUANAME << "\",\n"; \
77     std::cout <<   "  " << KEYSTA << "decl"   << KEYEND << "  \"" << DECL << "\",\n"; \
78     std::cout <<   "  " << KEYSTA << "parent" << KEYEND << "\""  << PARENTDECL << "\"\n"; \
79     std::cout <<   "},\n"; \
80   }
81 
82 #define PRINTDOC(TYPE, LUANAME, RETVAL, DECL) \
83   if (LuaBindingDoc::printBindings ()) { \
84     std::cout <<   "{ " << KEYSTA << "type"   << KEYEND << "  \""  << TYPE << "\",\n"; \
85     std::cout <<   "  " << KEYSTA << "lua"    << KEYEND << "   \"" << LUANAME << "\",\n"; \
86     if (!(RETVAL).empty()) { \
87       std::cout << "  " << KEYSTA << "ret"    << KEYEND << "   \"" << (RETVAL) << "\",\n"; \
88     } \
89     std::cout <<   "  " << KEYSTA << "decl"   << KEYEND << "  \""  << DECL << "\"\n"; \
90     std::cout <<   "},\n"; \
91   }
92 
93 #define FUNDOC(TYPE, NAME, FUNCTOR) \
94   PRINTDOC(TYPE, _name << NAME, \
95       type_name< typename FuncTraits <FUNCTOR>::ReturnType >(), \
96       type_name< typename FuncTraits <FUNCTOR>::DeclType >())
97 
98 #define DATADOC(TYPE, NAME, FUNCTOR) \
99   PRINTDOC(TYPE, _name << NAME, \
100       std::string(), \
101       type_name< decltype(FUNCTOR) >())\
102 
103 
104 #else
105 
106 #define CLASSDOC(TYPE, LUANAME, DECL, PARENTDECL)
107 #define PRINTDOC(TYPE, LUANAME, RETVAL, DECL)
108 #define FUNDOC(TYPE, NAME, FUNCTOR)
109 #define DATADOC(TYPE, NAME, FUNCTOR)
110 
111 #endif
112 
113 /** Provides C++ to Lua registration capabilities.
114 
115     This class is not instantiated directly, call `getGlobalNamespace` to start
116     the registration process.
117 */
118 class Namespace
119 {
120 private:
121   Namespace& operator= (Namespace const& other);
122 
123   lua_State* const L;
124   int mutable m_stackSize;
125 
126 private:
127   //============================================================================
128   /**
129     Error reporting.
130 
131     VF: This function looks handy, why aren't we using it?
132   */
133 #if 0
134   static int luaError (lua_State* L, std::string message)
135   {
136     assert (lua_isstring (L, lua_upvalueindex (1)));
137     std::string s;
138 
139     // Get information on the caller's caller to format the message,
140     // so the error appears to originate from the Lua source.
141     lua_Debug ar;
142     int result = lua_getstack (L, 2, &ar);
143     if (result != 0)
144     {
145       lua_getinfo (L, "Sl", &ar);
146       s = ar.short_src;
147       if (ar.currentline != -1)
148       {
149         // poor mans int to string to avoid <strstrream>.
150         lua_pushnumber (L, ar.currentline);
151         s = s + ":" + lua_tostring (L, -1) + ": ";
152         lua_pop (L, 1);
153       }
154     }
155 
156     s = s + message;
157 
158     return luaL_error (L, s.c_str ());
159   }
160 #endif
161 
162   //----------------------------------------------------------------------------
163   /**
164     Pop the Lua stack.
165   */
pop(int n)166   void pop (int n) const
167   {
168     if (m_stackSize >= n && lua_gettop (L) >= n)
169     {
170       lua_pop (L, n);
171       m_stackSize -= n;
172     }
173     else
174     {
175       throw std::logic_error ("invalid stack");
176     }
177   }
178 
179 private:
180   /**
181     Factored base to reduce template instantiations.
182   */
183   class ClassBase
184   {
185   private:
186     ClassBase& operator= (ClassBase const& other);
187 
188   protected:
189     friend class Namespace;
190 
191     lua_State* const L;
192     int mutable m_stackSize;
193 
194 #ifdef LUABINDINGDOC
195     std::string _name;
196     const Namespace* _parent;
197 #endif
198 
199   protected:
200     //--------------------------------------------------------------------------
201     /**
202       __index metamethod for a class.
203 
204       This implements member functions, data members, and property members.
205       Functions are stored in the metatable and const metatable. Data members
206       and property members are in the __propget table.
207 
208       If the key is not found, the search proceeds up the hierarchy of base
209       classes.
210     */
indexMetaMethod(lua_State * L)211     static int indexMetaMethod (lua_State* L)
212     {
213       int result = 0;
214 
215       assert (lua_isuserdata (L, 1));               // warn on security bypass
216       lua_getmetatable (L, 1);                      // get metatable for object
217       for (;;)
218       {
219         lua_pushvalue (L, 2);                       // push key arg2
220         lua_rawget (L, -2);                         // lookup key in metatable
221         if (lua_iscfunction (L, -1))                // ensure its a cfunction
222         {
223           lua_remove (L, -2);                       // remove metatable
224           result = 1;
225           break;
226         }
227         else if (lua_isnil (L, -1))
228         {
229           lua_pop (L, 1);
230         }
231         else
232         {
233           lua_pop (L, 2);
234           throw std::logic_error ("not a cfunction");
235         }
236 
237         rawgetfield (L, -1, "__propget");           // get __propget table
238         if (lua_istable (L, -1))                    // ensure it is a table
239         {
240           lua_pushvalue (L, 2);                     // push key arg2
241           lua_rawget (L, -2);                       // lookup key in __propget
242           lua_remove (L, -2);                       // remove __propget
243           if (lua_iscfunction (L, -1))              // ensure its a cfunction
244           {
245             lua_remove (L, -2);                     // remove metatable
246             lua_pushvalue (L, 1);                   // push class arg1
247             lua_call (L, 1, 1);
248             result = 1;
249             break;
250           }
251           else if (lua_isnil (L, -1))
252           {
253             lua_pop (L, 1);
254           }
255           else
256           {
257             lua_pop (L, 2);
258 
259             // We only put cfunctions into __propget.
260             throw std::logic_error ("not a cfunction");
261           }
262         }
263         else
264         {
265           lua_pop (L, 2);
266 
267           // __propget is missing, or not a table.
268           throw std::logic_error ("missing __propget table");
269         }
270 
271         // Repeat the lookup in the __parent metafield,
272         // or return nil if the field doesn't exist.
273         rawgetfield (L, -1, "__parent");
274         if (lua_istable (L, -1))
275         {
276           // Remove metatable and repeat the search in __parent.
277           lua_remove (L, -2);
278         }
279         else if (lua_isnil (L, -1))
280         {
281           result = 1;
282           break;
283         }
284         else
285         {
286           lua_pop (L, 2);
287 
288           throw std::logic_error ("__parent is not a table");
289         }
290       }
291 
292       return result;
293     }
294 
295     //--------------------------------------------------------------------------
296     /**
297       __newindex metamethod for classes.
298 
299       This supports writable variables and properties on class objects. The
300       corresponding object is passed in the first parameter to the set function.
301     */
newindexMetaMethod(lua_State * L)302     static int newindexMetaMethod (lua_State* L)
303     {
304       int result = 0;
305 
306       lua_getmetatable (L, 1);
307 
308       for (;;)
309       {
310         // Check __propset
311         rawgetfield (L, -1, "__propset");
312         if (!lua_isnil (L, -1))
313         {
314           lua_pushvalue (L, 2);
315           lua_rawget (L, -2);
316           if (!lua_isnil (L, -1))
317           {
318             // found it, call the setFunction.
319             assert (lua_isfunction (L, -1));
320             lua_pushvalue (L, 1);
321             lua_pushvalue (L, 3);
322             lua_call (L, 2, 0);
323             result = 0;
324             break;
325           }
326           lua_pop (L, 1);
327         }
328         lua_pop (L, 1);
329 
330         // Repeat the lookup in the __parent metafield.
331         rawgetfield (L, -1, "__parent");
332         if (lua_isnil (L, -1))
333         {
334           // Either the property or __parent must exist.
335           result = luaL_error (L,
336             "no member named '%s'", lua_tostring (L, 2));
337         }
338         lua_remove (L, -2);
339       }
340 
341       return result;
342     }
343 
344     //--------------------------------------------------------------------------
345     /**
346       Create the const table.
347     */
createConstTable(char const * name)348     void createConstTable (char const* name)
349     {
350       lua_newtable (L);
351       lua_pushvalue (L, -1);
352       lua_setmetatable (L, -2);
353       lua_pushboolean (L, 1);
354       lua_rawsetp (L, -2, getIdentityKey ());
355       lua_pushstring (L, (std::string ("const ") + name).c_str ());
356       rawsetfield (L, -2, "__type");
357       lua_pushcfunction (L, &indexMetaMethod);
358       rawsetfield (L, -2, "__index");
359       lua_pushcfunction (L, &newindexMetaMethod);
360       rawsetfield (L, -2, "__newindex");
361       lua_newtable (L);
362       rawsetfield (L, -2, "__propget");
363 
364       if (Security::hideMetatables ())
365       {
366         lua_pushboolean (L, false);
367         rawsetfield (L, -2, "__metatable");
368       }
369     }
370 
371     //--------------------------------------------------------------------------
372     /**
373       Create the class table.
374 
375       The Lua stack should have the const table on top.
376     */
createClassTable(char const * name)377     void createClassTable (char const* name)
378     {
379       lua_newtable (L);
380       lua_pushvalue (L, -1);
381       lua_setmetatable (L, -2);
382       lua_pushboolean (L, 1);
383       lua_rawsetp (L, -2, getIdentityKey ());
384       lua_pushstring (L, name);
385       rawsetfield (L, -2, "__type");
386       lua_pushcfunction (L, &indexMetaMethod);
387       rawsetfield (L, -2, "__index");
388       lua_pushcfunction (L, &newindexMetaMethod);
389       rawsetfield (L, -2, "__newindex");
390       lua_newtable (L);
391       rawsetfield (L, -2, "__propget");
392       lua_newtable (L);
393       rawsetfield (L, -2, "__propset");
394 
395       lua_pushvalue (L, -2);
396       rawsetfield (L, -2, "__const"); // point to const table
397 
398       lua_pushvalue (L, -1);
399       rawsetfield (L, -3, "__class"); // point const table to class table
400 
401       if (Security::hideMetatables ())
402       {
403         lua_pushboolean (L, false);
404         rawsetfield (L, -2, "__metatable");
405       }
406     }
407 
408     //--------------------------------------------------------------------------
409     /**
410       Create the static table.
411 
412       The Lua stack should have:
413         -1 class table
414         -2 const table
415         -3 enclosing namespace
416     */
createStaticTable(char const * name)417     void createStaticTable (char const* name)
418     {
419       lua_newtable (L);
420       lua_newtable (L);
421       lua_pushvalue (L, -1);
422       lua_setmetatable (L, -3);
423       lua_insert (L, -2);
424       rawsetfield (L, -5, name);
425 
426 #if 0
427       lua_pushlightuserdata (L, this);
428       lua_pushcclosure (L, &tostringMetaMethod, 1);
429       rawsetfield (L, -2, "__tostring");
430 #endif
431       lua_pushcfunction (L, &CFunc::indexMetaMethod);
432       rawsetfield (L, -2, "__index");
433       lua_pushcfunction (L, &CFunc::newindexMetaMethod);
434       rawsetfield (L, -2, "__newindex");
435       lua_newtable (L);
436       rawsetfield (L, -2, "__propget");
437       lua_newtable (L);
438       rawsetfield (L, -2, "__propset");
439 
440       lua_pushvalue (L, -2);
441       rawsetfield (L, -2, "__class"); // point to class table
442 
443       if (Security::hideMetatables ())
444       {
445         lua_pushboolean (L, false);
446         rawsetfield (L, -2, "__metatable");
447       }
448     }
449 
450     //==========================================================================
451     /**
452       lua_CFunction to construct a class object wrapped in a container.
453     */
454     template <class Params, class C>
ctorContainerProxy(lua_State * L)455     static int ctorContainerProxy (lua_State* L)
456     {
457       typedef typename ContainerTraits <C>::Type T;
458       ArgList <Params, 2> args (L);
459       T* const p = Constructor <T, Params>::call (args);
460       UserdataSharedHelper <C, false>::push (L, p);
461       return 1;
462     }
463 
464     //--------------------------------------------------------------------------
465     /**
466       lua_CFunction to construct a class object in-place in the userdata.
467     */
468     template <class Params, class T>
ctorPlacementProxy(lua_State * L)469     static int ctorPlacementProxy (lua_State* L)
470     {
471       ArgList <Params, 2> args (L);
472       Constructor <T, Params>::call (UserdataValue <T>::place (L), args);
473       return 1;
474     }
475 
476     template <class Params, class T, class C>
ctorPtrPlacementProxy(lua_State * L)477     static int ctorPtrPlacementProxy (lua_State* L)
478     {
479       ArgList <Params, 2> args (L);
480       T newobject (Constructor <C, Params>::call (args));
481       Stack<T>::push (L, newobject);
482       return 1;
483     }
484 
485     template <class T>
ctorNilPtrPlacementProxy(lua_State * L)486     static int ctorNilPtrPlacementProxy (lua_State* L)
487     {
488       const T* newobject = new T ();
489       Stack<T>::push (L, *newobject);
490       return 1;
491     }
492 
493     //--------------------------------------------------------------------------
494     /**
495       Pop the Lua stack.
496     */
pop(int n)497     void pop (int n) const
498     {
499       if (m_stackSize >= n && lua_gettop (L) >= n)
500       {
501         lua_pop (L, n);
502         m_stackSize -= n;
503       }
504       else
505       {
506         throw std::logic_error ("invalid stack");
507       }
508     }
509 
510   public:
511     //--------------------------------------------------------------------------
ClassBase(lua_State * L_)512     explicit ClassBase (lua_State* L_)
513       : L (L_)
514       , m_stackSize (0)
515     {
516     }
517 
518     //--------------------------------------------------------------------------
519     /**
520       Copy Constructor.
521     */
ClassBase(ClassBase const & other)522     ClassBase (ClassBase const& other)
523       : L (other.L)
524       , m_stackSize (0)
525 #ifdef LUABINDINGDOC
526       , _name (other._name)
527       , _parent (other._parent)
528 #endif
529     {
530       m_stackSize = other.m_stackSize;
531       other.m_stackSize = 0;
532     }
533 
~ClassBase()534     ~ClassBase ()
535     {
536       pop (m_stackSize);
537     }
538   };
539 
540   //============================================================================
541   //
542   // Class
543   //
544   //============================================================================
545   /**
546     Provides a class registration in a lua_State.
547 
548     After contstruction the Lua stack holds these objects:
549       -1 static table
550       -2 class table
551       -3 const table
552       -4 (enclosing namespace)
553   */
554   template <class T>
555   class Class : virtual public ClassBase
556   {
557   public:
558     //==========================================================================
559     /**
560       Register a new class or add to an existing class registration.
561     */
Class(char const * name,Namespace const * parent)562     Class (char const* name, Namespace const* parent) : ClassBase (parent->L)
563     {
564 #ifdef LUABINDINGDOC
565       _parent = parent;
566       _name = parent->_name + name + ":";
567 #endif
568       PRINTDOC ("[C] Class", parent->_name << name, std::string(), type_name <T>())
569       m_stackSize = parent->m_stackSize + 3;
570       parent->m_stackSize = 0;
571 
572       assert (lua_istable (L, -1));
573       rawgetfield (L, -1, name);
574 
575       if (lua_isnil (L, -1))
576       {
577         lua_pop (L, 1);
578 
579         createConstTable (name);
580         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
581         rawsetfield (L, -2, "__gc");
582         lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
583         rawsetfield (L, -2, "__eq");
584 
585         createClassTable (name);
586         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
587         rawsetfield (L, -2, "__gc");
588         lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
589         rawsetfield (L, -2, "__eq");
590 
591         createStaticTable (name);
592 
593         // Map T back to its tables.
594         lua_pushvalue (L, -1);
595         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
596         lua_pushvalue (L, -2);
597         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
598         lua_pushvalue (L, -3);
599         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
600       }
601       else
602       {
603         lua_pop (L, 1);
604         lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
605         rawgetfield (L, -1, "__class");
606         rawgetfield (L, -1, "__const");
607 
608         // Reverse the top 3 stack elements
609         lua_insert (L, -3);
610         lua_insert (L, -2);
611       }
612     }
613 
614     //==========================================================================
615     /**
616       Derive a new class.
617     */
Class(char const * name,Namespace const * parent,void const * const staticKey)618     Class (char const* name, Namespace const* parent, void const* const staticKey)
619       : ClassBase (parent->L)
620     {
621 #ifdef LUABINDINGDOC
622       _parent = parent;
623       _name = parent->_name + name + ":";
624 #endif
625       m_stackSize = parent->m_stackSize + 3;
626       parent->m_stackSize = 0;
627 
628       assert (lua_istable (L, -1));
629 
630       createConstTable (name);
631       lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
632       rawsetfield (L, -2, "__gc");
633       lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
634       rawsetfield (L, -2, "__eq");
635 
636       createClassTable (name);
637       lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
638       rawsetfield (L, -2, "__gc");
639       lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
640       rawsetfield (L, -2, "__eq");
641 
642       createStaticTable (name);
643 
644       lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey);
645       assert (lua_istable (L, -1));
646       rawgetfield (L, -1, "__class");
647       assert (lua_istable (L, -1));
648       rawgetfield (L, -1, "__const");
649       assert (lua_istable (L, -1));
650 
651       rawsetfield (L, -6, "__parent");
652       rawsetfield (L, -4, "__parent");
653       rawsetfield (L, -2, "__parent");
654 
655       lua_pushvalue (L, -1);
656       lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
657       lua_pushvalue (L, -2);
658       lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
659       lua_pushvalue (L, -3);
660       lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
661     }
662 
663     //--------------------------------------------------------------------------
664     /**
665       Continue registration in the enclosing namespace.
666     */
endClass()667     Namespace endClass ()
668     {
669       return Namespace (this);
670     }
671 
672     //--------------------------------------------------------------------------
673     /**
674       Add or replace a static data member.
675     */
676     template <class U>
677     Class <T>& addStaticData (char const* name, U* pu, bool isWritable = true)
678     {
679       DATADOC ("Static Data Member", name, pu)
680       assert (lua_istable (L, -1));
681 
682       rawgetfield (L, -1, "__propget");
683       assert (lua_istable (L, -1));
684       lua_pushlightuserdata (L, pu);
685       lua_pushcclosure (L, &CFunc::getVariable <U>, 1);
686       rawsetfield (L, -2, name);
687       lua_pop (L, 1);
688 
689       rawgetfield (L, -1, "__propset");
690       assert (lua_istable (L, -1));
691       if (isWritable)
692       {
693         lua_pushlightuserdata (L, pu);
694         lua_pushcclosure (L, &CFunc::setVariable <U>, 1);
695       }
696       else
697       {
698         lua_pushstring (L, name);
699         lua_pushcclosure (L, &CFunc::readOnlyError, 1);
700       }
701       rawsetfield (L, -2, name);
702       lua_pop (L, 1);
703 
704       return *this;
705     }
706 
707     //--------------------------------------------------------------------------
708 #if 0 // unused
709     /**
710       Add or replace a static property member.
711 
712       If the set function is null, the property is read-only.
713     */
714     template <class U>
715     Class <T>& addStaticProperty (char const* name, U (*get)(), void (*set)(U) = 0)
716     {
717       typedef U (*get_t)();
718       typedef void (*set_t)(U);
719 
720       assert (lua_istable (L, -1));
721 
722       rawgetfield (L, -1, "__propget");
723       assert (lua_istable (L, -1));
724       new (lua_newuserdata (L, sizeof (get))) get_t (get);
725       lua_pushcclosure (L, &CFunc::Call <U (*) (void)>::f, 1);
726       rawsetfield (L, -2, name);
727       lua_pop (L, 1);
728 
729       rawgetfield (L, -1, "__propset");
730       assert (lua_istable (L, -1));
731       if (set != 0)
732       {
733         new (lua_newuserdata (L, sizeof (set))) set_t (set);
734         lua_pushcclosure (L, &CFunc::Call <void (*) (U)>::f, 1);
735       }
736       else
737       {
738         lua_pushstring (L, name);
739         lua_pushcclosure (L, &CFunc::readOnlyError, 1);
740       }
741       rawsetfield (L, -2, name);
742       lua_pop (L, 1);
743 
744       return *this;
745     }
746 #endif
747 
748     //--------------------------------------------------------------------------
749     /**
750       Add or replace a static member function.
751     */
752     template <class FP>
addStaticFunction(char const * name,FP const fp)753     Class <T>& addStaticFunction (char const* name, FP const fp)
754     {
755       FUNDOC ("Static Member Function", name, FP)
756       new (lua_newuserdata (L, sizeof (fp))) FP (fp);
757       lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
758       rawsetfield (L, -2, name);
759 
760       return *this;
761     }
762 
763     //--------------------------------------------------------------------------
764     /**
765       Add or replace a lua_CFunction.
766     */
addStaticCFunction(char const * name,int (* const fp)(lua_State *))767     Class <T>& addStaticCFunction (char const* name, int (*const fp)(lua_State*))
768     {
769       DATADOC ("Static C Function", name, fp)
770       lua_pushcfunction (L, fp);
771       rawsetfield (L, -2, name);
772       return *this;
773     }
774 
775     //--------------------------------------------------------------------------
776     /**
777       Add or replace a data member.
778     */
779     template <class U>
780     Class <T>& addData (char const* name, const U T::* mp, bool isWritable = true)
781     {
782       DATADOC ("Data Member", name, mp)
783       typedef const U T::*mp_t;
784 
785       // Add to __propget in class and const tables.
786       {
787         rawgetfield (L, -2, "__propget");
788         rawgetfield (L, -4, "__propget");
789         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
790         lua_pushcclosure (L, &CFunc::getProperty <T,U>, 1);
791         lua_pushvalue (L, -1);
792         rawsetfield (L, -4, name);
793         rawsetfield (L, -2, name);
794         lua_pop (L, 2);
795       }
796 
797       if (isWritable)
798       {
799         // Add to __propset in class table.
800         rawgetfield (L, -2, "__propset");
801         assert (lua_istable (L, -1));
802         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
803         lua_pushcclosure (L, &CFunc::setProperty <T,U>, 1);
804         rawsetfield (L, -2, name);
805         lua_pop (L, 1);
806       }
807 
808       return *this;
809     }
810 
811     //--------------------------------------------------------------------------
812     /**
813       Add or replace a property member.
814     */
815     template <class TG, class TS>
addProperty(char const * name,TG (T::* get)()const,bool (T::* set)(TS))816     Class <T>& addProperty (char const* name, TG (T::* get) () const, bool (T::* set) (TS))
817     {
818       DATADOC ("Property", name, get)
819       // Add to __propget in class and const tables.
820       {
821         rawgetfield (L, -2, "__propget");
822         rawgetfield (L, -4, "__propget");
823         typedef TG (T::*get_t) () const;
824         new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
825         lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1);
826         lua_pushvalue (L, -1);
827         rawsetfield (L, -4, name);
828         rawsetfield (L, -2, name);
829         lua_pop (L, 2);
830       }
831 
832       {
833         // Add to __propset in class table.
834         rawgetfield (L, -2, "__propset");
835         assert (lua_istable (L, -1));
836         typedef bool (T::* set_t) (TS);
837         new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
838         lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1);
839         rawsetfield (L, -2, name);
840         lua_pop (L, 1);
841       }
842 
843       return *this;
844     }
845 
846 #if 0 // unused
847     // read-only
848     template <class TG>
849     Class <T>& addProperty (char const* name, TG (T::* get) () const)
850     {
851       // Add to __propget in class and const tables.
852       rawgetfield (L, -2, "__propget");
853       rawgetfield (L, -4, "__propget");
854       typedef TG (T::*get_t) () const;
855       new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
856       lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1);
857       lua_pushvalue (L, -1);
858       rawsetfield (L, -4, name);
859       rawsetfield (L, -2, name);
860       lua_pop (L, 2);
861 
862       return *this;
863     }
864 #endif
865 
866     //--------------------------------------------------------------------------
867     /**
868       Add or replace a property member, by proxy.
869 
870       When a class is closed for modification and does not provide (or cannot
871       provide) the function signatures necessary to implement get or set for
872       a property, this will allow non-member functions act as proxies.
873 
874       Both the get and the set functions require a T const* and T* in the first
875       argument respectively.
876     */
877     template <class TG, class TS>
addProperty(char const * name,TG (* get)(T const *),bool (* set)(T *,TS))878     Class <T>& addProperty (char const* name, TG (*get) (T const*), bool (*set) (T*, TS))
879     {
880       // Add to __propget in class and const tables.
881       {
882         rawgetfield (L, -2, "__propget");
883         rawgetfield (L, -4, "__propget");
884         typedef TG (*get_t) (T const*);
885         new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
886         lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
887         lua_pushvalue (L, -1);
888         rawsetfield (L, -4, name);
889         rawsetfield (L, -2, name);
890         lua_pop (L, 2);
891       }
892 
893       if (set != 0)
894       {
895         // Add to __propset in class table.
896         rawgetfield (L, -2, "__propset");
897         assert (lua_istable (L, -1));
898         typedef void (*set_t) (T*, TS);
899         new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
900         lua_pushcclosure (L, &CFunc::Call <set_t>::f, 1);
901         rawsetfield (L, -2, name);
902         lua_pop (L, 1);
903       }
904 
905       return *this;
906     }
907 
908 #if 0 // unused
909     // read-only
910     template <class TG, class TS>
911     Class <T>& addProperty (char const* name, TG (*get) (T const*))
912     {
913       // Add to __propget in class and const tables.
914       rawgetfield (L, -2, "__propget");
915       rawgetfield (L, -4, "__propget");
916       typedef TG (*get_t) (T const*);
917       new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
918       lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
919       lua_pushvalue (L, -1);
920       rawsetfield (L, -4, name);
921       rawsetfield (L, -2, name);
922       lua_pop (L, 2);
923 
924       return *this;
925     }
926 #endif
927     //--------------------------------------------------------------------------
928     /**
929         Add or replace a member function.
930     */
931     template <class MemFn>
addFunction(char const * name,MemFn mf)932     Class <T>& addFunction (char const* name, MemFn mf)
933     {
934       FUNDOC("Member Function", name, MemFn)
935       CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
936       return *this;
937     }
938 
939     template <class MemFn>
addPtrFunction(char const * name,MemFn mf)940     Class <T>& addPtrFunction (char const* name, MemFn mf)
941     {
942       FUNDOC("Member Pointer Function", name, MemFn)
943       CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
944       return *this;
945     }
946 
947     template <class MemFn>
addWPtrFunction(char const * name,MemFn mf)948     Class <T>& addWPtrFunction (char const* name, MemFn mf)
949     {
950       FUNDOC("Member Weak Pointer Function", name, MemFn)
951       CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
952       return *this;
953     }
954 
955     template <class MemFn>
addRefFunction(char const * name,MemFn mf)956     Class <T>& addRefFunction (char const* name, MemFn mf)
957     {
958       FUNDOC("Member Function RefReturn", name, MemFn)
959       CFunc::CallMemberRefFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
960       return *this;
961     }
962 
963 
964     //--------------------------------------------------------------------------
965     /**
966         Add or replace a member lua_CFunction.
967     */
addCFunction(char const * name,int (T::* mfp)(lua_State *))968     Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*))
969     {
970       DATADOC ("C Function", name, mfp)
971       typedef int (T::*MFP)(lua_State*);
972       assert (lua_istable (L, -1));
973       new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
974       lua_pushcclosure (L, &CFunc::CallMemberCFunction <T>::f, 1);
975       rawsetfield (L, -3, name); // class table
976 
977       return *this;
978     }
979 
980     // custom callback - extend existing classes
981     // with non-class member functions (e.g STL iterator)
addExtCFunction(char const * name,int (* const fp)(lua_State *))982     Class <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
983     {
984       DATADOC ("Ext C Function", name, fp)
985       assert (lua_istable (L, -1));
986       lua_pushcclosure (L, fp, 0);
987       lua_pushvalue (L, -1);
988       rawsetfield (L, -5, name); // const table
989       rawsetfield (L, -3, name); // class table
990       return *this;
991     }
992 
993     //--------------------------------------------------------------------------
994     /**
995         Add or replace a const member lua_CFunction.
996     */
addCFunction(char const * name,int (T::* mfp)(lua_State *)const)997     Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*) const)
998     {
999       DATADOC ("Const C Member Function", name, mfp)
1000       typedef int (T::*MFP)(lua_State*) const;
1001       assert (lua_istable (L, -1));
1002       new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
1003       lua_pushcclosure (L, &CFunc::CallConstMemberCFunction <T>::f, 1);
1004       lua_pushvalue (L, -1);
1005       rawsetfield (L, -5, name); // const table
1006       rawsetfield (L, -3, name); // class table
1007 
1008       return *this;
1009     }
1010 
1011     /**
1012         Add or replace a static const data
1013     */
1014     template <typename U>
addConst(char const * name,const U val)1015       Class <T>& addConst (char const* name, const U val)
1016       {
1017         DATADOC ("Constant/Enum Member", name, val)
1018         assert (lua_istable (L, -1));
1019 
1020         rawgetfield (L, -1, "__propget"); // static
1021         new (lua_newuserdata (L, sizeof (val))) U (val);
1022         lua_pushcclosure (L, &CFunc::getConst <U>, 1);
1023         rawsetfield (L, -2, name);
1024         lua_pop (L, 1);
1025 
1026         rawgetfield (L, -1, "__propset"); // static
1027         lua_pushstring (L, name);
1028         lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1029         rawsetfield (L, -2, name);
1030         lua_pop (L, 1);
1031         return *this;
1032       }
1033 
1034     //--------------------------------------------------------------------------
1035     /**
1036       Add or replace a primary Constructor.
1037 
1038       The primary Constructor is invoked when calling the class type table
1039       like a function.
1040 
1041       The template parameter should be a function pointer type that matches
1042       the desired Constructor (since you can't take the address of a Constructor
1043       and pass it as an argument).
1044     */
1045     template <class MemFn, class C>
addConstructor()1046     Class <T>& addConstructor ()
1047     {
1048       FUNDOC("Constructor", "", MemFn)
1049       lua_pushcclosure (L,
1050         &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0);
1051       rawsetfield(L, -2, "__call");
1052 
1053       return *this;
1054     }
1055 
1056     template <class MemFn>
addConstructor()1057     Class <T>& addConstructor ()
1058     {
1059       FUNDOC("Constructor", "", MemFn)
1060       lua_pushcclosure (L,
1061         &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0);
1062       rawsetfield(L, -2, "__call");
1063 
1064       return *this;
1065     }
1066 
1067     template <class MemFn, class PT>
addPtrConstructor()1068     Class <T>& addPtrConstructor ()
1069     {
1070       FUNDOC("Constructor", "", MemFn)
1071       lua_pushcclosure (L,
1072         &ctorPtrPlacementProxy <typename FuncTraits <MemFn>::Params, T, PT>, 0);
1073       rawsetfield(L, -2, "__call");
1074 
1075       return *this;
1076     }
1077 
addVoidConstructor()1078     Class <T>& addVoidConstructor ()
1079     {
1080       return addConstructor <void (*) ()> ();
1081     }
1082 
1083     template <class PT>
addVoidPtrConstructor()1084     Class <T>& addVoidPtrConstructor ()
1085     {
1086       return addPtrConstructor <void (*) (), PT> ();
1087     }
1088 
addEqualCheck()1089     Class <T>& addEqualCheck ()
1090     {
1091       assert (lua_istable (L, -1));
1092       lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1093       rawsetfield (L, -3, "sameinstance");
1094       return *this;
1095     }
1096 
1097     template <class U>
addCast(char const * name)1098     Class <T>& addCast (char const* name)
1099     {
1100       PRINTDOC("Cast", _name << name,
1101           type_name< U >(),
1102           type_name< U >() << " (" << type_name< T >() << "::*)()")
1103 
1104       assert (lua_istable (L, -1));
1105       lua_pushcclosure (L, &CFunc::CastClass <T, U>::f, 0);
1106       rawsetfield (L, -3, name); // class table
1107 
1108       lua_pushcclosure (L, &CFunc::CastConstClass <T, U>::f, 0);
1109       rawsetfield (L, -4, name); // const table
1110       return *this;
1111     }
1112 
1113   };
1114 
1115   /** C Array to/from table */
1116   template <typename T>
1117   class Array : virtual public ClassBase
1118   {
1119   public:
Array(char const * name,Namespace const * parent)1120     Array (char const* name, Namespace const* parent) : ClassBase (parent->L)
1121     {
1122 #ifdef LUABINDINGDOC
1123       _parent = parent;
1124       _name = parent->_name + name + ":";
1125 #endif
1126       PRINTDOC ("[C] Array", parent->_name << name,
1127           std::string(), type_name <T>() + "*")
1128       PRINTDOC ("Ext C Function", _name << "array",
1129           std::string(""), "int (*)(lua_State*)")
1130       PRINTDOC ("Ext C Function", _name << "get_table",
1131           std::string(""), "int (*)(lua_State*)")
1132       PRINTDOC ("Ext C Function", _name << "set_table",
1133           std::string(""), "int (*)(lua_State*)")
1134       PRINTDOC("Member Function", _name << "offset",
1135           std::string(type_name <T>() + "*"), std::string(type_name <T>() + "* (*)(unsigned int)"))
1136 
1137       m_stackSize = parent->m_stackSize + 3;
1138       parent->m_stackSize = 0;
1139 
1140 #if 0 // don't allow to duplicates handlers for same array-type
1141       assert (lua_istable (L, -1));
1142       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1143       if (lua_istable (L, -1)) {
1144         lua_pushnil (L);
1145         lua_pushnil (L);
1146         return;
1147       }
1148       lua_pop (L, 1);
1149 #endif
1150 
1151       assert (lua_istable (L, -1));
1152       rawgetfield (L, -1, name);
1153 
1154       if (lua_isnil (L, -1))
1155       {
1156         lua_pop (L, 1);
1157 
1158         // register array access in global namespace
1159         luaL_newmetatable (L, typeid(T).name());
1160         lua_pushcclosure (L, CFunc::array_index<T>, 0);
1161         lua_setfield(L, -2, "__index");
1162         lua_pushcclosure (L, CFunc::array_newindex<T>, 0);
1163         lua_setfield(L, -2, "__newindex");
1164         if (Security::hideMetatables ())
1165         {
1166           lua_pushboolean (L, false);
1167           rawsetfield (L, -2, "__metatable");
1168         }
1169         lua_pop (L, 1);
1170 
1171 
1172         createConstTable (name);
1173         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1174         rawsetfield (L, -2, "__gc");
1175         lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1176         rawsetfield (L, -2, "__eq");
1177 
1178         createClassTable (name);
1179         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1180         rawsetfield (L, -2, "__gc");
1181         lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1182         rawsetfield (L, -2, "__eq");
1183 
1184         createStaticTable (name);
1185 
1186         // Map T back to its tables.
1187         lua_pushvalue (L, -1);
1188         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
1189         lua_pushvalue (L, -2);
1190         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1191         lua_pushvalue (L, -3);
1192         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
1193 
1194         assert (lua_istable (L, -1));
1195         lua_pushcclosure (L, &CFunc::getArray <T>, 0);
1196         rawsetfield (L, -3, "array"); // class table
1197 
1198         lua_pushcclosure (L, &CFunc::getTable <T>, 0);
1199         rawsetfield (L, -3, "get_table"); // class table
1200 
1201         lua_pushcclosure (L, &CFunc::setTable <T>, 0);
1202         rawsetfield (L, -3, "set_table"); // class table
1203 
1204         lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1205         rawsetfield (L, -3, "sameinstance");
1206 
1207         lua_pushcclosure (L, &CFunc::offsetArray <T>, 0);
1208         rawsetfield (L, -3, "offset"); // class table
1209 
1210       }
1211       else
1212       {
1213         lua_pushnil (L);
1214         lua_pushnil (L);
1215       }
1216     }
1217 
endArray()1218     Namespace endArray ()
1219     {
1220       return Namespace (this);
1221     }
1222   };
1223 
1224   /** Boost Weak & Shared Pointer Class Wrapper */
1225   template <class T>
1226   class WSPtrClass : virtual public ClassBase
1227   {
1228   public:
WSPtrClass(char const * name,Namespace const * parent)1229     WSPtrClass (char const* name, Namespace const* parent)
1230       : ClassBase (parent->L)
1231       , shared (name, parent)
1232       , weak (name, parent)
1233     {
1234 #ifdef LUABINDINGDOC
1235       _parent = parent;
1236       _name = parent->_name + name + ":";
1237 #endif
1238       PRINTDOC ("[C] Weak/Shared Pointer Class",
1239           parent->_name + name,
1240           std::string(), type_name <T>())
1241       m_stackSize = shared.m_stackSize;
1242       parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1243       lua_pop (L, 3);
1244     }
1245 
WSPtrClass(char const * name,Namespace const * parent,void const * const sharedkey,void const * const weakkey)1246     WSPtrClass (char const* name, Namespace const* parent, void const* const sharedkey, void const* const weakkey)
1247       : ClassBase (parent->L)
1248       , shared (name, parent, sharedkey)
1249       , weak (name, parent, weakkey)
1250     {
1251 #ifdef LUABINDINGDOC
1252       _parent = parent;
1253       _name = parent->_name + name + ":";
1254 #endif
1255       m_stackSize = shared.m_stackSize;
1256       parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1257       lua_pop (L, 3);
1258     }
1259 
1260     template <class MemFn>
addFunction(char const * name,MemFn mf)1261     WSPtrClass <T>& addFunction (char const* name, MemFn mf)
1262     {
1263       FUNDOC ("Weak/Shared Pointer Function", name, MemFn)
1264       set_shared_class ();
1265       CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
1266 
1267       set_weak_class ();
1268       CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
1269       return *this;
1270     }
1271 
1272     template <class MemFn>
addRefFunction(char const * name,MemFn mf)1273     WSPtrClass <T>& addRefFunction (char const* name, MemFn mf)
1274     {
1275       FUNDOC ("Weak/Shared Pointer Function RefReturn", name, MemFn)
1276       set_shared_class ();
1277       CFunc::CallMemberRefPtrFunctionHelper <MemFn>::add (L, name, mf);
1278 
1279       set_weak_class ();
1280       CFunc::CallMemberRefWPtrFunctionHelper <MemFn>::add (L, name, mf);
1281       return *this;
1282     }
1283 
1284     template <class MemFn>
addConstructor()1285     WSPtrClass <T>& addConstructor ()
1286     {
1287       FUNDOC ("Weak/Shared Pointer Constructor", "", MemFn)
1288       set_shared_class ();
1289       lua_pushcclosure (L,
1290           &shared. template ctorPtrPlacementProxy <typename FuncTraits <MemFn>::Params, boost::shared_ptr<T>, T >, 0);
1291       rawsetfield(L, -2, "__call");
1292 
1293       set_weak_class ();
1294       // NOTE: this constructs an empty weak-ptr,
1295       // ideally we'd construct a weak-ptr from a referenced shared-ptr
1296       lua_pushcclosure (L,
1297           &weak. template ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::weak_ptr<T> >, 0);
1298       rawsetfield(L, -2, "__call");
1299       return *this;
1300     }
1301 
addVoidConstructor()1302     WSPtrClass <T>& addVoidConstructor ()
1303     {
1304       return addConstructor <void (*) ()> ();
1305     }
1306 
1307     template <class FP>
addStaticFunction(char const * name,FP const fp)1308     WSPtrClass <T>& addStaticFunction (char const* name, FP const fp)
1309     {
1310       FUNDOC ("Static Member Function", name, FP)
1311       set_shared_class ();
1312       new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1313       lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
1314       rawsetfield (L, -2, name);
1315 
1316       set_weak_class ();
1317       new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1318       lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
1319       rawsetfield (L, -2, name);
1320       return *this;
1321     }
1322 
addNilPtrConstructor()1323     WSPtrClass <T>& addNilPtrConstructor ()
1324     {
1325       FUNDOC ("Weak/Shared Pointer NIL Constructor", "", void (*) ())
1326       set_shared_class ();
1327       lua_pushcclosure (L,
1328           &shared. template ctorNilPtrPlacementProxy <boost::shared_ptr<T> >, 0);
1329       rawsetfield(L, -2, "__call");
1330 
1331       set_weak_class ();
1332       // NOTE: this constructs an empty weak-ptr,
1333       // ideally we'd construct a weak-ptr from a referenced shared-ptr
1334       lua_pushcclosure (L,
1335           &weak. template ctorNilPtrPlacementProxy <boost::weak_ptr<T> >, 0);
1336       rawsetfield(L, -2, "__call");
1337 
1338       return *this;
1339     }
1340 
addExtCFunction(char const * name,int (* const fp)(lua_State *))1341     WSPtrClass <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
1342     {
1343       DATADOC ("Weak/Shared Ext C Function", name, fp)
1344       set_shared_class ();
1345       assert (lua_istable (L, -1));
1346       lua_pushcclosure (L, fp, 0);
1347       lua_pushvalue (L, -1);
1348       rawsetfield (L, -5, name); // const table
1349       rawsetfield (L, -3, name); // class table
1350 
1351       set_weak_class ();
1352       assert (lua_istable (L, -1));
1353       lua_pushcclosure (L, fp, 0);
1354       lua_pushvalue (L, -1);
1355       rawsetfield (L, -5, name); // const table
1356       rawsetfield (L, -3, name); // class table
1357 
1358       return *this;
1359     }
1360 
1361     template <class U>
addCast(char const * name)1362     WSPtrClass <T>& addCast (char const* name)
1363     {
1364       PRINTDOC("Weak/Shared Pointer Cast", _name << name,
1365           type_name< U >(),
1366           type_name< U >() << " (" << type_name< T >() << "::*)()")
1367 
1368       // TODO weak ptr
1369       set_shared_class ();
1370       assert (lua_istable (L, -1));
1371       lua_pushcclosure (L, &CFunc::CastMemberPtr <T, U>::f, 0);
1372       rawsetfield (L, -3, name); // class table
1373       return *this;
1374     }
1375 
addNullCheck()1376     WSPtrClass <T>& addNullCheck ()
1377     {
1378       PRINTDOC("Weak/Shared Null Check", _name << "isnil", std::string("bool"), std::string("void (*)()"))
1379       set_shared_class ();
1380       assert (lua_istable (L, -1));
1381       lua_pushcclosure (L, &CFunc::PtrNullCheck <T>::f, 0);
1382       rawsetfield (L, -3, "isnil"); // class table
1383 
1384       set_weak_class ();
1385       assert (lua_istable (L, -1));
1386       lua_pushcclosure (L, &CFunc::WPtrNullCheck <T>::f, 0);
1387       rawsetfield (L, -3, "isnil"); // class table
1388 
1389       return *this;
1390     }
1391 
addEqualCheck()1392     WSPtrClass <T>& addEqualCheck ()
1393     {
1394       set_shared_class ();
1395       assert (lua_istable (L, -1));
1396       lua_pushcclosure (L, &CFunc::PtrEqualCheck <T>::f, 0);
1397       rawsetfield (L, -3, "sameinstance"); // class table
1398 
1399       set_weak_class ();
1400       assert (lua_istable (L, -1));
1401       lua_pushcclosure (L, &CFunc::WPtrEqualCheck <T>::f, 0);
1402       rawsetfield (L, -3, "sameinstance"); // class table
1403 
1404       return *this;
1405     }
1406 
1407     template <class U>
1408     WSPtrClass <T>& addData (char const* name, const U T::* mp, bool isWritable = true)
1409     {
1410       DATADOC ("Data Member", name, mp)
1411       typedef const U T::*mp_t;
1412 
1413       set_weak_class ();
1414       assert (lua_istable (L, -1));
1415       // Add to __propget in class and const tables.
1416       {
1417         rawgetfield (L, -2, "__propget");
1418         rawgetfield (L, -4, "__propget");
1419         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1420         lua_pushcclosure (L, &CFunc::getWPtrProperty <T,U>, 1);
1421         lua_pushvalue (L, -1);
1422         rawsetfield (L, -4, name);
1423         rawsetfield (L, -2, name);
1424         lua_pop (L, 2);
1425       }
1426 
1427       if (isWritable)
1428       {
1429         // Add to __propset in class table.
1430         rawgetfield (L, -2, "__propset");
1431         assert (lua_istable (L, -1));
1432         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1433         lua_pushcclosure (L, &CFunc::setWPtrProperty <T,U>, 1);
1434         rawsetfield (L, -2, name);
1435         lua_pop (L, 1);
1436       }
1437 
1438       set_shared_class ();
1439       assert (lua_istable (L, -1));
1440       // Add to __propget in class and const tables.
1441       {
1442         rawgetfield (L, -2, "__propget");
1443         rawgetfield (L, -4, "__propget");
1444         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1445         lua_pushcclosure (L, &CFunc::getPtrProperty <T,U>, 1);
1446         lua_pushvalue (L, -1);
1447         rawsetfield (L, -4, name);
1448         rawsetfield (L, -2, name);
1449         lua_pop (L, 2);
1450       }
1451 
1452       if (isWritable)
1453       {
1454         // Add to __propset in class table.
1455         rawgetfield (L, -2, "__propset");
1456         assert (lua_istable (L, -1));
1457         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1458         lua_pushcclosure (L, &CFunc::setPtrProperty <T,U>, 1);
1459         rawsetfield (L, -2, name);
1460         lua_pop (L, 1);
1461       }
1462 
1463       return *this;
1464     }
1465 
1466 
endClass()1467     Namespace endClass ()
1468     {
1469       return Namespace (this);
1470     }
1471 
1472   private:
set_weak_class()1473     void set_weak_class () {
1474       lua_pop (L, 3);
1475       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::weak_ptr<T> >::getStaticKey ());
1476       rawgetfield (L, -1, "__class");
1477       rawgetfield (L, -1, "__const");
1478       lua_insert (L, -3);
1479       lua_insert (L, -2);
1480     }
set_shared_class()1481     void set_shared_class () {
1482       lua_pop (L, 3);
1483       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::shared_ptr<T> >::getStaticKey ());
1484       rawgetfield (L, -1, "__class");
1485       rawgetfield (L, -1, "__const");
1486       lua_insert (L, -3);
1487       lua_insert (L, -2);
1488     }
1489     Class<boost::shared_ptr<T> > shared;
1490     Class<boost::weak_ptr<T> > weak;
1491   };
1492 
1493 
1494 private:
1495   //----------------------------------------------------------------------------
1496   /**
1497       Open the global namespace for registrations.
1498   */
Namespace(lua_State * L_)1499   explicit Namespace (lua_State* L_)
1500     : L (L_)
1501     , m_stackSize (0)
1502 #ifdef LUABINDINGDOC
1503     , _name ("")
1504     , _parent (0)
1505 #endif
1506   {
1507     lua_getglobal (L, "_G");
1508     ++m_stackSize;
1509   }
1510 
1511 #ifdef LUABINDINGDOC
1512   std::string _name;
1513   Namespace const * _parent;
1514 #endif
1515 
1516   //----------------------------------------------------------------------------
1517   /**
1518       Open a namespace for registrations.
1519 
1520       The namespace is created if it doesn't already exist.
1521       The parent namespace is at the top of the Lua stack.
1522   */
Namespace(char const * name,Namespace const * parent)1523   Namespace (char const* name, Namespace const* parent)
1524     : L (parent->L)
1525     , m_stackSize (0)
1526 #ifdef LUABINDINGDOC
1527     , _name (parent->_name + name + ":")
1528     , _parent (parent)
1529 #endif
1530   {
1531     m_stackSize = parent->m_stackSize + 1;
1532     parent->m_stackSize = 0;
1533 
1534     assert (lua_istable (L, -1));
1535     rawgetfield (L, -1, name);
1536     if (lua_isnil (L, -1))
1537     {
1538       lua_pop (L, 1);
1539 
1540       lua_newtable (L);
1541       lua_pushvalue (L, -1);
1542       lua_setmetatable (L, -2);
1543       lua_pushcfunction (L, &CFunc::indexMetaMethod);
1544       rawsetfield (L, -2, "__index");
1545       lua_pushcfunction (L, &CFunc::newindexMetaMethod);
1546       rawsetfield (L, -2, "__newindex");
1547       lua_newtable (L);
1548       rawsetfield (L, -2, "__propget");
1549       lua_newtable (L);
1550       rawsetfield (L, -2, "__propset");
1551       lua_pushvalue (L, -1);
1552       rawsetfield (L, -3, name);
1553 #if 0
1554       lua_pushcfunction (L, &tostringMetaMethod);
1555       rawsetfield (L, -2, "__tostring");
1556 #endif
1557       if (Security::hideMetatables ())
1558       {
1559         lua_pushboolean (L, false);
1560         rawsetfield (L, -2, "__metatable");
1561       }
1562 
1563     }
1564   }
1565 
1566   //----------------------------------------------------------------------------
1567   /**
1568       Creates a continued registration from a child namespace.
1569   */
Namespace(Namespace const * child)1570   explicit Namespace (Namespace const* child)
1571     : L (child->L)
1572     , m_stackSize (0)
1573 #ifdef LUABINDINGDOC
1574     , _name (child->_parent ? child->_parent->_name : "")
1575     , _parent (child->_parent ? child->_parent->_parent : NULL)
1576 #endif
1577   {
1578     m_stackSize = child->m_stackSize - 1;
1579     child->m_stackSize = 1;
1580     child->pop (1);
1581 
1582     // It is not necessary or valid to call
1583     // endNamespace() for the global namespace!
1584     //
1585     assert (m_stackSize != 0);
1586   }
1587 
1588   //----------------------------------------------------------------------------
1589   /**
1590       Creates a continued registration from a child class.
1591   */
Namespace(ClassBase const * child)1592   explicit Namespace (ClassBase const* child)
1593     : L (child->L)
1594     , m_stackSize (0)
1595 #ifdef LUABINDINGDOC
1596     , _name (child->_parent ? child->_parent->_name : "")
1597     , _parent (child->_parent ? child->_parent->_parent : NULL)
1598 #endif
1599   {
1600     m_stackSize = child->m_stackSize - 3;
1601     child->m_stackSize = 3;
1602     child->pop (3);
1603   }
1604 
1605 public:
1606   //----------------------------------------------------------------------------
1607   /**
1608       Copy Constructor.
1609 
1610       Ownership of the stack is transferred to the new object. This happens
1611       when the compiler emits temporaries to hold these objects while chaining
1612       registrations across namespaces.
1613   */
Namespace(Namespace const & other)1614   Namespace (Namespace const& other) : L (other.L)
1615   {
1616     m_stackSize = other.m_stackSize;
1617     other.m_stackSize = 0;
1618 #ifdef LUABINDINGDOC
1619     _name = other._name;
1620     _parent = other._parent;
1621 #endif
1622   }
1623 
1624   //----------------------------------------------------------------------------
1625   /**
1626       Closes this namespace registration.
1627   */
~Namespace()1628   ~Namespace ()
1629   {
1630     pop (m_stackSize);
1631   }
1632 
1633   //----------------------------------------------------------------------------
1634   /**
1635       Open the global namespace.
1636   */
getGlobalNamespace(lua_State * L)1637   static Namespace getGlobalNamespace (lua_State* L)
1638   {
1639     return Namespace (L);
1640   }
1641 
1642   //----------------------------------------------------------------------------
1643   /**
1644       Open a new or existing namespace for registrations.
1645   */
beginNamespace(char const * name)1646   Namespace beginNamespace (char const* name)
1647   {
1648     return Namespace (name, this);
1649   }
1650 
1651   //----------------------------------------------------------------------------
1652   /**
1653       Continue namespace registration in the parent.
1654 
1655       Do not use this on the global namespace.
1656   */
endNamespace()1657   Namespace endNamespace ()
1658   {
1659     return Namespace (this);
1660   }
1661 
1662   //----------------------------------------------------------------------------
1663   /**
1664       Add or replace a variable.
1665   */
1666   template <class T>
1667   Namespace& addVariable (char const* name, T* pt, bool isWritable = true)
1668   {
1669     assert (lua_istable (L, -1));
1670 
1671     rawgetfield (L, -1, "__propget");
1672     assert (lua_istable (L, -1));
1673     lua_pushlightuserdata (L, pt);
1674     lua_pushcclosure (L, &CFunc::getVariable <T>, 1);
1675     rawsetfield (L, -2, name);
1676     lua_pop (L, 1);
1677 
1678     rawgetfield (L, -1, "__propset");
1679     assert (lua_istable (L, -1));
1680     if (isWritable)
1681     {
1682       lua_pushlightuserdata (L, pt);
1683       lua_pushcclosure (L, &CFunc::setVariable <T>, 1);
1684     }
1685     else
1686     {
1687       lua_pushstring (L, name);
1688       lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1689     }
1690     rawsetfield (L, -2, name);
1691     lua_pop (L, 1);
1692 
1693     return *this;
1694   }
1695 
1696   template <typename U>
addConst(char const * name,const U val)1697   Namespace& addConst (char const* name, const U val)
1698   {
1699     DATADOC ("Constant/Enum", name, val)
1700     assert (lua_istable (L, -1));
1701     rawgetfield (L, -1, "__propget");
1702     new (lua_newuserdata (L, sizeof (val))) U (val);
1703     lua_pushcclosure (L, &CFunc::getConst <U>, 1);
1704     rawsetfield (L, -2, name);
1705     lua_pop (L, 1);
1706 
1707     rawgetfield (L, -1, "__propset");
1708     assert (lua_istable (L, -1));
1709     lua_pushstring (L, name);
1710     lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1711     rawsetfield (L, -2, name);
1712     lua_pop (L, 1);
1713     return *this;
1714   }
1715 
1716   //----------------------------------------------------------------------------
1717   /**
1718       Add or replace a property.
1719 
1720       If the set function is omitted or null, the property is read-only.
1721   */
1722 #if 0 // unused
1723   template <class TG, class TS>
1724   Namespace& addProperty (char const* name, TG (*get) (), void (*set)(TS) = 0)
1725   {
1726     assert (lua_istable (L, -1));
1727 
1728     rawgetfield (L, -1, "__propget");
1729     assert (lua_istable (L, -1));
1730     typedef TG (*get_t) ();
1731     new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
1732     lua_pushcclosure (L, &CFunc::Call <TG (*) (void)>::f, 1);
1733     rawsetfield (L, -2, name);
1734     lua_pop (L, 1);
1735 
1736     rawgetfield (L, -1, "__propset");
1737     assert (lua_istable (L, -1));
1738     if (set != 0)
1739     {
1740       typedef void (*set_t) (TS);
1741       new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
1742       lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1);
1743     }
1744     else
1745     {
1746       lua_pushstring (L, name);
1747       lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1748     }
1749     rawsetfield (L, -2, name);
1750     lua_pop (L, 1);
1751 
1752     return *this;
1753   }
1754 #endif
1755 
1756   //----------------------------------------------------------------------------
1757   /**
1758       Add or replace a free function.
1759   */
1760   template <class FP>
addFunction(char const * name,FP const fp)1761   Namespace& addFunction (char const* name, FP const fp)
1762   {
1763     FUNDOC ("Free Function", name, FP)
1764     assert (lua_istable (L, -1));
1765 
1766     new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1767     lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
1768     rawsetfield (L, -2, name);
1769 
1770     return *this;
1771   }
1772 
1773   template <class FP>
addRefFunction(char const * name,FP const fp)1774   Namespace& addRefFunction (char const* name, FP const fp)
1775   {
1776     FUNDOC ("Free Function RefReturn", name, FP)
1777     assert (lua_istable (L, -1));
1778 
1779     new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1780     lua_pushcclosure (L, &CFunc::CallRef <FP>::f, 1);
1781     rawsetfield (L, -2, name);
1782 
1783     return *this;
1784   }
1785 
1786   //----------------------------------------------------------------------------
1787   /**
1788       Add or replace a array type
1789   */
1790 
1791   template <typename T>
registerArray(char const * name)1792   Namespace registerArray (char const* name)
1793   {
1794     return Array <T> (name, this).endArray();
1795   }
1796 
1797 
1798   //----------------------------------------------------------------------------
1799   /**
1800       Add or replace a lua_CFunction.
1801   */
addCFunction(char const * name,int (* const fp)(lua_State *))1802   Namespace& addCFunction (char const* name, int (*const fp)(lua_State*))
1803   {
1804     DATADOC ("Free C Function", name, fp)
1805     lua_pushcfunction (L, fp);
1806     rawsetfield (L, -2, name);
1807 
1808     return *this;
1809   }
1810 
1811   //----------------------------------------------------------------------------
1812   /**
1813       Open a new or existing class for registrations.
1814   */
1815   template <class T>
beginClass(char const * name)1816   Class <T> beginClass (char const* name)
1817   {
1818     return Class <T> (name, this);
1819   }
1820 
1821   /** weak & shared pointer class */
1822   template <class T>
beginWSPtrClass(char const * name)1823   WSPtrClass <T> beginWSPtrClass (char const* name)
1824   {
1825     return WSPtrClass <T> (name, this)
1826       .addNullCheck()
1827       .addEqualCheck();
1828   }
1829 
1830   //----------------------------------------------------------------------------
1831 
1832   template <class K, class V>
beginStdMap(char const * name)1833   Class<std::map<K, V> > beginStdMap (char const* name)
1834   {
1835     typedef std::map<K, V> LT;
1836     typedef std::pair<const K, V> T;
1837 
1838     typedef typename std::map<K, V>::size_type T_SIZE;
1839 
1840     return beginClass<LT> (name)
1841       .addVoidConstructor ()
1842       .addFunction ("empty", (bool (LT::*)()const)&LT::empty)
1843       .addFunction ("size", (T_SIZE (LT::*)()const)&LT::size)
1844       .addFunction ("clear", (void (LT::*)())&LT::clear)
1845       .addFunction ("count", (T_SIZE (LT::*)(const K&) const)&LT::count)
1846       .addExtCFunction ("add", &CFunc::tableToMap<K, V>)
1847       .addExtCFunction ("iter", &CFunc::mapIter<K, V>)
1848       .addExtCFunction ("table", &CFunc::mapToTable<K, V>)
1849       .addExtCFunction ("at", &CFunc::mapAt<K, V>);
1850   }
1851 
1852   template <class T>
beginStdSet(char const * name)1853   Class<std::set<T> > beginStdSet (char const* name)
1854   {
1855     typedef std::set<T> LT;
1856     return beginClass<LT> (name)
1857       .addVoidConstructor ()
1858       .addFunction ("clear", (void (LT::*)())&LT::clear)
1859       .addFunction ("empty", &LT::empty)
1860       .addFunction ("size", &LT::size)
1861       .addExtCFunction ("iter", &CFunc::setIter<T, LT>)
1862       .addExtCFunction ("table", &CFunc::setToTable<T, LT>);
1863   }
1864 
1865   template <unsigned int T>
beginStdBitSet(char const * name)1866   Class<std::bitset<T> > beginStdBitSet (char const* name)
1867   {
1868     typedef std::bitset<T> BS;
1869     return beginClass<BS> (name)
1870       .addVoidConstructor ()
1871       .addFunction ("reset", (BS& (BS::*)())&BS::reset)
1872       .addFunction ("set", (BS& (BS::*)(size_t, bool))&BS::set)
1873       .addFunction ("count", (size_t (BS::*)()const)&BS::count)
1874       .addFunction ("size", (size_t (BS::*)()const)&BS::size)
1875       .addFunction ("any", (bool (BS::*)()const)&BS::any)
1876       .addFunction ("none", (bool (BS::*)()const)&BS::none)
1877       .addFunction ("test", &BS::test)
1878       .addExtCFunction ("add", &CFunc::tableToBitSet<T>)
1879       .addExtCFunction ("table", &CFunc::bitSetToTable<T>);
1880   }
1881 
1882   template <class T>
beginConstStdList(char const * name)1883   Class<std::list<T> > beginConstStdList (char const* name)
1884   {
1885     typedef std::list<T> LT;
1886     typedef typename LT::size_type T_SIZE;
1887     return beginClass<LT> (name)
1888       .addVoidConstructor ()
1889       .addFunction ("empty", static_cast<bool (LT::*)() const>(&LT::empty))
1890       .addFunction ("size", static_cast<T_SIZE (LT::*)() const>(&LT::size))
1891       .addFunction ("reverse", static_cast<void (LT::*)()>(&LT::reverse))
1892       .addFunction ("front", static_cast<T& (LT::*)()>(&LT::front))
1893       .addFunction ("back", static_cast<T& (LT::*)()>(&LT::back))
1894       .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1895       .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1896   }
1897 
1898   template <class T>
beginStdList(char const * name)1899   Class<std::list<T> > beginStdList (char const* name)
1900   {
1901     typedef std::list<T> LT;
1902     typedef typename LT::size_type T_SIZE;
1903     return beginConstStdList<T> (name)
1904 #if !defined(_MSC_VER) || (_MSC_VER < 1900)
1905 	  /* std::list::unique() got broken in later versions of MSVC */
1906 # if (defined(__cplusplus) &&  __cplusplus >= 201709L)
1907       .addFunction ("unique", (T_SIZE (LT::*)())&LT::unique)
1908 # else
1909       .addFunction ("unique", (void (LT::*)())&LT::unique)
1910 # endif
1911 #endif
1912       .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1913       .addExtCFunction ("add", &CFunc::tableToList<T, LT>);
1914   }
1915 
1916   template <class T>
beginConstStdCPtrList(char const * name)1917   Class<std::list<T*> > beginConstStdCPtrList (char const* name)
1918   {
1919     typedef T* TP;
1920     typedef std::list<TP> LT;
1921     typedef typename LT::size_type T_SIZE;
1922     return beginClass<LT> (name)
1923       .addVoidConstructor ()
1924       .addFunction ("empty", static_cast<bool (LT::*)() const>(&LT::empty))
1925       .addFunction ("size", static_cast<T_SIZE (LT::*)() const>(&LT::size))
1926       .addFunction ("reverse", static_cast<void (LT::*)()>(&LT::reverse))
1927       .addFunction ("front", static_cast<const TP& (LT::*)() const>(&LT::front))
1928       .addFunction ("back", static_cast<const TP& (LT::*)() const>(&LT::back))
1929       .addExtCFunction ("iter", &CFunc::listIter<T*, LT>)
1930       .addExtCFunction ("table", &CFunc::listToTable<T*, LT>);
1931   }
1932 
1933   template <class T>
beginStdCPtrList(char const * name)1934   Class<std::list<T*> > beginStdCPtrList (char const* name)
1935   {
1936     typedef T* TP;
1937     typedef std::list<TP> LT;
1938     typedef typename LT::size_type T_SIZE;
1939     return beginConstStdCPtrList<T> (name)
1940 #if !defined(_MSC_VER) || (_MSC_VER < 1900)
1941 	  /* std::list::unique() got broken in later versions of MSVC */
1942 # if (defined(__cplusplus) &&  __cplusplus >= 201709L)
1943       .addFunction ("unique", (T_SIZE (LT::*)())&LT::unique)
1944 # else
1945       .addFunction ("unique", (void (LT::*)())&LT::unique)
1946 # endif
1947 #endif
1948       .addExtCFunction ("push_back", &CFunc::pushbackptr<T, LT>);
1949   }
1950 
1951 
1952   template <class T>
beginConstStdVector(char const * name)1953   Class<std::vector<T> > beginConstStdVector (char const* name)
1954   {
1955     typedef std::vector<T> LT;
1956     typedef typename std::vector<T>::reference T_REF;
1957     typedef typename std::vector<T>::size_type T_SIZE;
1958 
1959     return beginClass<LT> (name)
1960       .addVoidConstructor ()
1961       .addFunction ("empty", (bool (LT::*)()const)&LT::empty)
1962       .addFunction ("size", (T_SIZE (LT::*)()const)&LT::size)
1963       .addFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
1964       .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1965       .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1966   }
1967 
1968   template <class T>
beginStdVector(char const * name)1969   Class<std::vector<T> > beginStdVector (char const* name)
1970   {
1971     typedef std::vector<T> LT;
1972     return beginConstStdVector<T> (name)
1973       .addVoidConstructor ()
1974       .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1975       .addFunction ("clear", (void (LT::*)())&LT::clear)
1976       .addExtCFunction ("to_array", &CFunc::vectorToArray<T, LT>)
1977       .addExtCFunction ("add", &CFunc::tableToList<T, LT>);
1978   }
1979 
1980   //----------------------------------------------------------------------------
1981 
1982   template <class T>
beginPtrStdList(char const * name)1983   Class<boost::shared_ptr<std::list<T> > > beginPtrStdList (char const* name)
1984   {
1985     typedef std::list<T> LT;
1986     typedef typename LT::size_type T_SIZE;
1987     return beginClass<boost::shared_ptr<LT> > (name)
1988       //.addVoidPtrConstructor<LT> ()
1989       .addPtrFunction ("empty", (bool (LT::*)()const)&LT::empty)
1990       .addPtrFunction ("size", (T_SIZE (LT::*)()const)&LT::size)
1991       .addPtrFunction ("reverse", (void (LT::*)())&LT::reverse)
1992 #if !defined(_MSC_VER) || (_MSC_VER < 1900)
1993 	  /* std::list::unique() got broken in later versions of MSVC */
1994 # if (defined(__cplusplus) &&  __cplusplus >= 201709L)
1995       .addPtrFunction ("unique", (T_SIZE (LT::*)())&LT::unique)
1996 # else
1997       .addPtrFunction ("unique", (void (LT::*)())&LT::unique)
1998 # endif
1999 #endif
2000       .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
2001       .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
2002       .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
2003       .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
2004   }
2005 
2006   template <class T>
beginPtrStdVector(char const * name)2007   Class<boost::shared_ptr<std::vector<T> > > beginPtrStdVector (char const* name)
2008   {
2009     typedef std::vector<T> LT;
2010     typedef typename std::vector<T>::reference T_REF;
2011     typedef typename std::vector<T>::size_type T_SIZE;
2012 
2013     return beginClass<boost::shared_ptr<LT> > (name)
2014       //.addVoidPtrConstructor<LT> ()
2015       .addPtrFunction ("empty", (bool (LT::*)()const)&LT::empty)
2016       .addPtrFunction ("size", (T_SIZE (LT::*)()const)&LT::size)
2017       .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
2018       .addPtrFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
2019       .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
2020       .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
2021       .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
2022   }
2023 
2024   //----------------------------------------------------------------------------
2025   /**
2026       Derive a new class for registrations.
2027 
2028       To continue registrations for the class later, use beginClass().
2029       Do not call deriveClass() again.
2030   */
2031   template <class T, class U>
deriveClass(char const * name)2032   Class <T> deriveClass (char const* name)
2033   {
2034     CLASSDOC ("[C] Derived Class", _name << name, type_name <T>(), type_name <U>())
2035     return Class <T> (name, this, ClassInfo <U>::getStaticKey ());
2036   }
2037 
2038   template <class T, class U>
deriveWSPtrClass(char const * name)2039   WSPtrClass <T> deriveWSPtrClass (char const* name)
2040   {
2041 
2042     CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::shared_ptr<T> >(), type_name <boost::shared_ptr<U> >())
2043     CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::weak_ptr<T> >(), type_name <boost::weak_ptr<U> >())
2044     CLASSDOC ("[C] Derived Pointer Class", _name << name, type_name <T>(), type_name <U>())
2045     return WSPtrClass <T> (name, this,
2046         ClassInfo <boost::shared_ptr<U> >::getStaticKey (),
2047         ClassInfo <boost::weak_ptr<U> >::getStaticKey ())
2048       .addNullCheck()
2049       .addEqualCheck();
2050   }
2051 
2052 };
2053 
2054 //------------------------------------------------------------------------------
2055 /**
2056     Retrieve the global namespace.
2057 
2058     It is recommended to put your namespace inside the global namespace, and
2059     then add your classes and functions to it, rather than adding many classes
2060     and functions directly to the global namespace.
2061 */
getGlobalNamespace(lua_State * L)2062 inline Namespace getGlobalNamespace (lua_State* L)
2063 {
2064   return Namespace::getGlobalNamespace (L);
2065 }
2066 
2067 
2068 #undef KEYSTA
2069 #undef KEYEND
2070 #undef CLASSDOC
2071 #undef PRINTDOC
2072 #undef FUNDOC
2073 #undef DATADOC
2074 
2075 /* vim: set et sw=2: */
2076