f4f2ae21352711f3e307fc2ec4fb3b4dd6990f58
[ardour.git] / libs / lua / LuaBridge / detail / Namespace.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   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>
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   */
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     */
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     */
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     */
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_pushnil (L);
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     */
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_pushnil (L);
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     */
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_pushnil (L);
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>
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>
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>
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>
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     */
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     //--------------------------------------------------------------------------
512     explicit ClassBase (lua_State* L_)
513       : L (L_)
514       , m_stackSize (0)
515     {
516     }
517
518     //--------------------------------------------------------------------------
519     /**
520       Copy Constructor.
521     */
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
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     */
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
583         createClassTable (name);
584         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
585         rawsetfield (L, -2, "__gc");
586
587         createStaticTable (name);
588
589         // Map T back to its tables.
590         lua_pushvalue (L, -1);
591         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
592         lua_pushvalue (L, -2);
593         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
594         lua_pushvalue (L, -3);
595         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
596       }
597       else
598       {
599         lua_pop (L, 1);
600         lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
601         rawgetfield (L, -1, "__class");
602         rawgetfield (L, -1, "__const");
603
604         // Reverse the top 3 stack elements
605         lua_insert (L, -3);
606         lua_insert (L, -2);
607       }
608     }
609
610     //==========================================================================
611     /**
612       Derive a new class.
613     */
614     Class (char const* name, Namespace const* parent, void const* const staticKey)
615       : ClassBase (parent->L)
616     {
617 #ifdef LUABINDINGDOC
618       _parent = parent;
619       _name = parent->_name + name + ":";
620 #endif
621       m_stackSize = parent->m_stackSize + 3;
622       parent->m_stackSize = 0;
623
624       assert (lua_istable (L, -1));
625
626       createConstTable (name);
627       lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
628       rawsetfield (L, -2, "__gc");
629
630       createClassTable (name);
631       lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
632       rawsetfield (L, -2, "__gc");
633
634       createStaticTable (name);
635
636       lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey);
637       assert (lua_istable (L, -1));
638       rawgetfield (L, -1, "__class");
639       assert (lua_istable (L, -1));
640       rawgetfield (L, -1, "__const");
641       assert (lua_istable (L, -1));
642
643       rawsetfield (L, -6, "__parent");
644       rawsetfield (L, -4, "__parent");
645       rawsetfield (L, -2, "__parent");
646
647       lua_pushvalue (L, -1);
648       lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
649       lua_pushvalue (L, -2);
650       lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
651       lua_pushvalue (L, -3);
652       lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
653     }
654
655     //--------------------------------------------------------------------------
656     /**
657       Continue registration in the enclosing namespace.
658     */
659     Namespace endClass ()
660     {
661       return Namespace (this);
662     }
663
664     //--------------------------------------------------------------------------
665     /**
666       Add or replace a static data member.
667     */
668     template <class U>
669     Class <T>& addStaticData (char const* name, U* pu, bool isWritable = true)
670     {
671       DATADOC ("Static Data Member", name, pu)
672       assert (lua_istable (L, -1));
673
674       rawgetfield (L, -1, "__propget");
675       assert (lua_istable (L, -1));
676       lua_pushlightuserdata (L, pu);
677       lua_pushcclosure (L, &CFunc::getVariable <U>, 1);
678       rawsetfield (L, -2, name);
679       lua_pop (L, 1);
680
681       rawgetfield (L, -1, "__propset");
682       assert (lua_istable (L, -1));
683       if (isWritable)
684       {
685         lua_pushlightuserdata (L, pu);
686         lua_pushcclosure (L, &CFunc::setVariable <U>, 1);
687       }
688       else
689       {
690         lua_pushstring (L, name);
691         lua_pushcclosure (L, &CFunc::readOnlyError, 1);
692       }
693       rawsetfield (L, -2, name);
694       lua_pop (L, 1);
695
696       return *this;
697     }
698
699     //--------------------------------------------------------------------------
700 #if 0 // unused
701     /**
702       Add or replace a static property member.
703
704       If the set function is null, the property is read-only.
705     */
706     template <class U>
707     Class <T>& addStaticProperty (char const* name, U (*get)(), void (*set)(U) = 0)
708     {
709       typedef U (*get_t)();
710       typedef void (*set_t)(U);
711
712       assert (lua_istable (L, -1));
713
714       rawgetfield (L, -1, "__propget");
715       assert (lua_istable (L, -1));
716       new (lua_newuserdata (L, sizeof (get))) get_t (get);
717       lua_pushcclosure (L, &CFunc::Call <U (*) (void)>::f, 1);
718       rawsetfield (L, -2, name);
719       lua_pop (L, 1);
720
721       rawgetfield (L, -1, "__propset");
722       assert (lua_istable (L, -1));
723       if (set != 0)
724       {
725         new (lua_newuserdata (L, sizeof (set))) set_t (set);
726         lua_pushcclosure (L, &CFunc::Call <void (*) (U)>::f, 1);
727       }
728       else
729       {
730         lua_pushstring (L, name);
731         lua_pushcclosure (L, &CFunc::readOnlyError, 1);
732       }
733       rawsetfield (L, -2, name);
734       lua_pop (L, 1);
735
736       return *this;
737     }
738 #endif
739
740     //--------------------------------------------------------------------------
741     /**
742       Add or replace a static member function.
743     */
744     template <class FP>
745     Class <T>& addStaticFunction (char const* name, FP const fp)
746     {
747       FUNDOC ("Static Member Function", name, FP)
748       new (lua_newuserdata (L, sizeof (fp))) FP (fp);
749       lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
750       rawsetfield (L, -2, name);
751
752       return *this;
753     }
754
755     //--------------------------------------------------------------------------
756     /**
757       Add or replace a lua_CFunction.
758     */
759     Class <T>& addStaticCFunction (char const* name, int (*const fp)(lua_State*))
760     {
761       DATADOC ("Static C Function", name, fp)
762       lua_pushcfunction (L, fp);
763       rawsetfield (L, -2, name);
764       return *this;
765     }
766
767     //--------------------------------------------------------------------------
768     /**
769       Add or replace a data member.
770     */
771     template <class U>
772     Class <T>& addData (char const* name, const U T::* mp, bool isWritable = true)
773     {
774       DATADOC ("Data Member", name, mp)
775       typedef const U T::*mp_t;
776
777       // Add to __propget in class and const tables.
778       {
779         rawgetfield (L, -2, "__propget");
780         rawgetfield (L, -4, "__propget");
781         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
782         lua_pushcclosure (L, &CFunc::getProperty <T,U>, 1);
783         lua_pushvalue (L, -1);
784         rawsetfield (L, -4, name);
785         rawsetfield (L, -2, name);
786         lua_pop (L, 2);
787       }
788
789       if (isWritable)
790       {
791         // Add to __propset in class table.
792         rawgetfield (L, -2, "__propset");
793         assert (lua_istable (L, -1));
794         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
795         lua_pushcclosure (L, &CFunc::setProperty <T,U>, 1);
796         rawsetfield (L, -2, name);
797         lua_pop (L, 1);
798       }
799
800       return *this;
801     }
802
803     //--------------------------------------------------------------------------
804     /**
805       Add or replace a property member.
806     */
807     template <class TG, class TS>
808     Class <T>& addProperty (char const* name, TG (T::* get) () const, bool (T::* set) (TS))
809     {
810       DATADOC ("Property", name, get)
811       // Add to __propget in class and const tables.
812       {
813         rawgetfield (L, -2, "__propget");
814         rawgetfield (L, -4, "__propget");
815         typedef TG (T::*get_t) () const;
816         new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
817         lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1);
818         lua_pushvalue (L, -1);
819         rawsetfield (L, -4, name);
820         rawsetfield (L, -2, name);
821         lua_pop (L, 2);
822       }
823
824       {
825         // Add to __propset in class table.
826         rawgetfield (L, -2, "__propset");
827         assert (lua_istable (L, -1));
828         typedef bool (T::* set_t) (TS);
829         new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
830         lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1);
831         rawsetfield (L, -2, name);
832         lua_pop (L, 1);
833       }
834
835       return *this;
836     }
837
838 #if 0 // unused
839     // read-only
840     template <class TG>
841     Class <T>& addProperty (char const* name, TG (T::* get) () const)
842     {
843       // Add to __propget in class and const tables.
844       rawgetfield (L, -2, "__propget");
845       rawgetfield (L, -4, "__propget");
846       typedef TG (T::*get_t) () const;
847       new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
848       lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1);
849       lua_pushvalue (L, -1);
850       rawsetfield (L, -4, name);
851       rawsetfield (L, -2, name);
852       lua_pop (L, 2);
853
854       return *this;
855     }
856 #endif
857
858     //--------------------------------------------------------------------------
859     /**
860       Add or replace a property member, by proxy.
861
862       When a class is closed for modification and does not provide (or cannot
863       provide) the function signatures necessary to implement get or set for
864       a property, this will allow non-member functions act as proxies.
865
866       Both the get and the set functions require a T const* and T* in the first
867       argument respectively.
868     */
869     template <class TG, class TS>
870     Class <T>& addProperty (char const* name, TG (*get) (T const*), bool (*set) (T*, TS))
871     {
872       // Add to __propget in class and const tables.
873       {
874         rawgetfield (L, -2, "__propget");
875         rawgetfield (L, -4, "__propget");
876         typedef TG (*get_t) (T const*);
877         new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
878         lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
879         lua_pushvalue (L, -1);
880         rawsetfield (L, -4, name);
881         rawsetfield (L, -2, name);
882         lua_pop (L, 2);
883       }
884
885       if (set != 0)
886       {
887         // Add to __propset in class table.
888         rawgetfield (L, -2, "__propset");
889         assert (lua_istable (L, -1));
890         typedef void (*set_t) (T*, TS);
891         new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
892         lua_pushcclosure (L, &CFunc::Call <set_t>::f, 1);
893         rawsetfield (L, -2, name);
894         lua_pop (L, 1);
895       }
896
897       return *this;
898     }
899
900 #if 0 // unused
901     // read-only
902     template <class TG, class TS>
903     Class <T>& addProperty (char const* name, TG (*get) (T const*))
904     {
905       // Add to __propget in class and const tables.
906       rawgetfield (L, -2, "__propget");
907       rawgetfield (L, -4, "__propget");
908       typedef TG (*get_t) (T const*);
909       new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
910       lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
911       lua_pushvalue (L, -1);
912       rawsetfield (L, -4, name);
913       rawsetfield (L, -2, name);
914       lua_pop (L, 2);
915
916       return *this;
917     }
918 #endif
919     //--------------------------------------------------------------------------
920     /**
921         Add or replace a member function.
922     */
923     template <class MemFn>
924     Class <T>& addFunction (char const* name, MemFn mf)
925     {
926       FUNDOC("Member Function", name, MemFn)
927       CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
928       return *this;
929     }
930
931     template <class MemFn>
932     Class <T>& addPtrFunction (char const* name, MemFn mf)
933     {
934       FUNDOC("Member Pointer Function", name, MemFn)
935       CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
936       return *this;
937     }
938
939     template <class MemFn>
940     Class <T>& addWPtrFunction (char const* name, MemFn mf)
941     {
942       FUNDOC("Member Weak Pointer Function", name, MemFn)
943       CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
944       return *this;
945     }
946
947     template <class MemFn>
948     Class <T>& addRefFunction (char const* name, MemFn mf)
949     {
950       FUNDOC("Member Function RefReturn", name, MemFn)
951       CFunc::CallMemberRefFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
952       return *this;
953     }
954
955
956     //--------------------------------------------------------------------------
957     /**
958         Add or replace a member lua_CFunction.
959     */
960     Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*))
961     {
962       DATADOC ("C Function", name, mfp)
963       typedef int (T::*MFP)(lua_State*);
964       assert (lua_istable (L, -1));
965       new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
966       lua_pushcclosure (L, &CFunc::CallMemberCFunction <T>::f, 1);
967       rawsetfield (L, -3, name); // class table
968
969       return *this;
970     }
971
972     // custom callback - extend existing classes
973     // with non-class member functions (e.g STL iterator)
974     Class <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
975     {
976       DATADOC ("Ext C Function", name, fp)
977       assert (lua_istable (L, -1));
978       lua_pushcclosure (L, fp, 0);
979       rawsetfield (L, -3, name); // class table
980       return *this;
981     }
982
983     //--------------------------------------------------------------------------
984     /**
985         Add or replace a const member lua_CFunction.
986     */
987     Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*) const)
988     {
989       DATADOC ("Const C Member Function", name, mfp)
990       typedef int (T::*MFP)(lua_State*) const;
991       assert (lua_istable (L, -1));
992       new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
993       lua_pushcclosure (L, &CFunc::CallConstMemberCFunction <T>::f, 1);
994       lua_pushvalue (L, -1);
995       rawsetfield (L, -5, name); // const table
996       rawsetfield (L, -3, name); // class table
997
998       return *this;
999     }
1000
1001     /**
1002         Add or replace a static const data
1003     */
1004     template <typename U>
1005       Class <T>& addConst (char const* name, const U val)
1006       {
1007         DATADOC ("Constant/Enum Member", name, val)
1008         assert (lua_istable (L, -1));
1009
1010         rawgetfield (L, -1, "__propget"); // static
1011         new (lua_newuserdata (L, sizeof (val))) U (val);
1012         lua_pushcclosure (L, &CFunc::getConst <U>, 1);
1013         rawsetfield (L, -2, name);
1014         lua_pop (L, 1);
1015
1016         rawgetfield (L, -1, "__propset"); // static
1017         lua_pushstring (L, name);
1018         lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1019         rawsetfield (L, -2, name);
1020         lua_pop (L, 1);
1021         return *this;
1022       }
1023
1024     //--------------------------------------------------------------------------
1025     /**
1026       Add or replace a primary Constructor.
1027
1028       The primary Constructor is invoked when calling the class type table
1029       like a function.
1030
1031       The template parameter should be a function pointer type that matches
1032       the desired Constructor (since you can't take the address of a Constructor
1033       and pass it as an argument).
1034     */
1035     template <class MemFn, class C>
1036     Class <T>& addConstructor ()
1037     {
1038       FUNDOC("Constructor", "", MemFn)
1039       lua_pushcclosure (L,
1040         &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0);
1041       rawsetfield(L, -2, "__call");
1042
1043       return *this;
1044     }
1045
1046     template <class MemFn>
1047     Class <T>& addConstructor ()
1048     {
1049       FUNDOC("Constructor", "", MemFn)
1050       lua_pushcclosure (L,
1051         &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0);
1052       rawsetfield(L, -2, "__call");
1053
1054       return *this;
1055     }
1056
1057     template <class MemFn, class PT>
1058     Class <T>& addPtrConstructor ()
1059     {
1060       FUNDOC("Constructor", "", MemFn)
1061       lua_pushcclosure (L,
1062         &ctorPtrPlacementProxy <typename FuncTraits <MemFn>::Params, T, PT>, 0);
1063       rawsetfield(L, -2, "__call");
1064
1065       return *this;
1066     }
1067
1068     Class <T>& addVoidConstructor ()
1069     {
1070       return addConstructor <void (*) ()> ();
1071     }
1072
1073     template <class PT>
1074     Class <T>& addVoidPtrConstructor ()
1075     {
1076       return addPtrConstructor <void (*) (), PT> ();
1077     }
1078
1079     Class <T>& addEqualCheck ()
1080     {
1081       PRINTDOC("Member Function", _name << "sameinstance", std::string("bool"), std::string("void (*)(" + type_name <T>() + ")"))
1082       assert (lua_istable (L, -1));
1083       lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1084       rawsetfield (L, -3, "sameinstance");
1085       return *this;
1086     }
1087
1088     template <class U>
1089     Class <T>& addCast (char const* name)
1090     {
1091       PRINTDOC("Cast", _name << name,
1092           type_name< U >(),
1093           type_name< U >() << " (" << type_name< T >() << "::*)()")
1094
1095       assert (lua_istable (L, -1));
1096       lua_pushcclosure (L, &CFunc::CastClass <T, U>::f, 0);
1097       rawsetfield (L, -3, name); // class table
1098
1099       lua_pushcclosure (L, &CFunc::CastConstClass <T, U>::f, 0);
1100       rawsetfield (L, -4, name); // const table
1101       return *this;
1102     }
1103
1104   };
1105
1106   /** C Array to/from table */
1107   template <typename T>
1108   class Array : virtual public ClassBase
1109   {
1110   public:
1111     Array (char const* name, Namespace const* parent) : ClassBase (parent->L)
1112     {
1113 #ifdef LUABINDINGDOC
1114       _parent = parent;
1115       _name = parent->_name + name + ":";
1116 #endif
1117       PRINTDOC ("[C] Array", parent->_name << name,
1118           std::string(), type_name <T>() + "*")
1119       PRINTDOC ("Ext C Function", _name << "array",
1120           std::string(""), "int (*)(lua_State*)")
1121       PRINTDOC ("Ext C Function", _name << "get_table",
1122           std::string(""), "int (*)(lua_State*)")
1123       PRINTDOC ("Ext C Function", _name << "set_table",
1124           std::string(""), "int (*)(lua_State*)")
1125       PRINTDOC("Member Function", _name << "sameinstance",
1126           std::string("bool"), std::string("bool (*)(" + type_name <T>() + "*)"))
1127       PRINTDOC("Member Function", _name << "offset",
1128           std::string(type_name <T>() + "*"), std::string(type_name <T>() + "* (*)(unsigned int)"))
1129
1130       m_stackSize = parent->m_stackSize + 3;
1131       parent->m_stackSize = 0;
1132
1133 #if 0 // don't allow to duplicates handlers for same array-type
1134       assert (lua_istable (L, -1));
1135       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1136       if (lua_istable (L, -1)) {
1137         lua_pushnil (L);
1138         lua_pushnil (L);
1139         return;
1140       }
1141       lua_pop (L, 1);
1142 #endif
1143
1144       assert (lua_istable (L, -1));
1145       rawgetfield (L, -1, name);
1146
1147       if (lua_isnil (L, -1))
1148       {
1149         lua_pop (L, 1);
1150
1151         // register array access in global namespace
1152         luaL_newmetatable (L, typeid(T).name());
1153         lua_pushcclosure (L, CFunc::array_index<T>, 0);
1154         lua_setfield(L, -2, "__index");
1155         lua_pushcclosure (L, CFunc::array_newindex<T>, 0);
1156         lua_setfield(L, -2, "__newindex");
1157         lua_pop (L, 1);
1158
1159         createConstTable (name);
1160         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1161         rawsetfield (L, -2, "__gc");
1162
1163         createClassTable (name);
1164         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1165         rawsetfield (L, -2, "__gc");
1166
1167         createStaticTable (name);
1168
1169         // Map T back to its tables.
1170         lua_pushvalue (L, -1);
1171         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
1172         lua_pushvalue (L, -2);
1173         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1174         lua_pushvalue (L, -3);
1175         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
1176
1177         assert (lua_istable (L, -1));
1178         lua_pushcclosure (L, &CFunc::getArray <T>, 0);
1179         rawsetfield (L, -3, "array"); // class table
1180
1181         lua_pushcclosure (L, &CFunc::getTable <T>, 0);
1182         rawsetfield (L, -3, "get_table"); // class table
1183
1184         lua_pushcclosure (L, &CFunc::setTable <T>, 0);
1185         rawsetfield (L, -3, "set_table"); // class table
1186
1187         lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1188         rawsetfield (L, -3, "sameinstance");
1189
1190         lua_pushcclosure (L, &CFunc::offsetArray <T>, 0);
1191         rawsetfield (L, -3, "offset"); // class table
1192
1193       }
1194       else
1195       {
1196         lua_pushnil (L);
1197         lua_pushnil (L);
1198       }
1199     }
1200
1201     Namespace endArray ()
1202     {
1203       return Namespace (this);
1204     }
1205   };
1206
1207   /** Boost Weak & Shared Pointer Class Wrapper */
1208   template <class T>
1209   class WSPtrClass : virtual public ClassBase
1210   {
1211   public:
1212     WSPtrClass (char const* name, Namespace const* parent)
1213       : ClassBase (parent->L)
1214       , shared (name, parent)
1215       , weak (name, parent)
1216     {
1217 #ifdef LUABINDINGDOC
1218       _parent = parent;
1219       _name = parent->_name + name + ":";
1220 #endif
1221       PRINTDOC ("[C] Weak/Shared Pointer Class",
1222           parent->_name + name,
1223           std::string(), type_name <T>())
1224       m_stackSize = shared.m_stackSize;
1225       parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1226       lua_pop (L, 3);
1227     }
1228
1229     WSPtrClass (char const* name, Namespace const* parent, void const* const sharedkey, void const* const weakkey)
1230       : ClassBase (parent->L)
1231       , shared (name, parent, sharedkey)
1232       , weak (name, parent, weakkey)
1233     {
1234 #ifdef LUABINDINGDOC
1235       _parent = parent;
1236       _name = parent->_name + name + ":";
1237 #endif
1238       m_stackSize = shared.m_stackSize;
1239       parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1240       lua_pop (L, 3);
1241     }
1242
1243     template <class MemFn>
1244     WSPtrClass <T>& addFunction (char const* name, MemFn mf)
1245     {
1246       FUNDOC ("Weak/Shared Pointer Function", name, MemFn)
1247       set_shared_class ();
1248       CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
1249
1250       set_weak_class ();
1251       CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
1252       return *this;
1253     }
1254
1255     template <class MemFn>
1256     WSPtrClass <T>& addRefFunction (char const* name, MemFn mf)
1257     {
1258       FUNDOC ("Weak/Shared Pointer Function RefReturn", name, MemFn)
1259       set_shared_class ();
1260       CFunc::CallMemberRefPtrFunctionHelper <MemFn>::add (L, name, mf);
1261
1262       set_weak_class ();
1263       CFunc::CallMemberRefWPtrFunctionHelper <MemFn>::add (L, name, mf);
1264       return *this;
1265     }
1266
1267     template <class MemFn>
1268     WSPtrClass <T>& addConstructor ()
1269     {
1270       FUNDOC ("Weak/Shared Pointer Constructor", "", MemFn)
1271       set_shared_class ();
1272       lua_pushcclosure (L,
1273           &shared. template ctorPtrPlacementProxy <typename FuncTraits <MemFn>::Params, boost::shared_ptr<T>, T >, 0);
1274       rawsetfield(L, -2, "__call");
1275
1276       set_weak_class ();
1277       // NOTE: this constructs an empty weak-ptr,
1278       // ideally we'd construct a weak-ptr from a referenced shared-ptr
1279       lua_pushcclosure (L,
1280           &weak. template ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::weak_ptr<T> >, 0);
1281       rawsetfield(L, -2, "__call");
1282       return *this;
1283     }
1284
1285     WSPtrClass <T>& addVoidConstructor ()
1286     {
1287       return addConstructor <void (*) ()> ();
1288     }
1289
1290     WSPtrClass <T>& addNilPtrConstructor ()
1291     {
1292       FUNDOC ("Weak/Shared Pointer NIL Constructor", "", void (*) ())
1293       set_shared_class ();
1294       lua_pushcclosure (L,
1295           &shared. template ctorNilPtrPlacementProxy <boost::shared_ptr<T> >, 0);
1296       rawsetfield(L, -2, "__call");
1297
1298       set_weak_class ();
1299       // NOTE: this constructs an empty weak-ptr,
1300       // ideally we'd construct a weak-ptr from a referenced shared-ptr
1301       lua_pushcclosure (L,
1302           &weak. template ctorNilPtrPlacementProxy <boost::weak_ptr<T> >, 0);
1303       rawsetfield(L, -2, "__call");
1304
1305       return *this;
1306     }
1307
1308     WSPtrClass <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
1309     {
1310       DATADOC ("Weak/Shared Ext C Function", name, fp)
1311       set_shared_class ();
1312       assert (lua_istable (L, -1));
1313       lua_pushcclosure (L, fp, 0);
1314       rawsetfield (L, -3, name); // class table
1315
1316       set_weak_class ();
1317       assert (lua_istable (L, -1));
1318       lua_pushcclosure (L, fp, 0);
1319       rawsetfield (L, -3, name); // class table
1320
1321       return *this;
1322     }
1323
1324     template <class U>
1325     WSPtrClass <T>& addCast (char const* name)
1326     {
1327       PRINTDOC("Weak/Shared Pointer Cast", _name << name,
1328           type_name< U >(),
1329           type_name< U >() << " (" << type_name< T >() << "::*)()")
1330
1331       // TODO weak ptr
1332       set_shared_class ();
1333       assert (lua_istable (L, -1));
1334       lua_pushcclosure (L, &CFunc::CastMemberPtr <T, U>::f, 0);
1335       rawsetfield (L, -3, name); // class table
1336       return *this;
1337     }
1338
1339     WSPtrClass <T>& addNullCheck ()
1340     {
1341       PRINTDOC("Weak/Shared Null Check", _name << "isnil", std::string("bool"), std::string("void (*)()"))
1342       set_shared_class ();
1343       assert (lua_istable (L, -1));
1344       lua_pushcclosure (L, &CFunc::PtrNullCheck <T>::f, 0);
1345       rawsetfield (L, -3, "isnil"); // class table
1346
1347       set_weak_class ();
1348       assert (lua_istable (L, -1));
1349       lua_pushcclosure (L, &CFunc::WPtrNullCheck <T>::f, 0);
1350       rawsetfield (L, -3, "isnil"); // class table
1351
1352       return *this;
1353     }
1354
1355     WSPtrClass <T>& addEqualCheck ()
1356     {
1357       PRINTDOC("Member Function", _name << "sameinstance", std::string("bool"), std::string("void (*)(" + type_name <T>() + ")"))
1358       set_shared_class ();
1359       assert (lua_istable (L, -1));
1360       lua_pushcclosure (L, &CFunc::PtrEqualCheck <T>::f, 0);
1361       rawsetfield (L, -3, "sameinstance"); // class table
1362
1363       set_weak_class ();
1364       assert (lua_istable (L, -1));
1365       lua_pushcclosure (L, &CFunc::WPtrEqualCheck <T>::f, 0);
1366       rawsetfield (L, -3, "sameinstance"); // class table
1367
1368       return *this;
1369     }
1370
1371     template <class U>
1372     WSPtrClass <T>& addData (char const* name, const U T::* mp, bool isWritable = true)
1373     {
1374       DATADOC ("Data Member", name, mp)
1375       typedef const U T::*mp_t;
1376
1377       set_weak_class ();
1378       assert (lua_istable (L, -1));
1379       // Add to __propget in class and const tables.
1380       {
1381         rawgetfield (L, -2, "__propget");
1382         rawgetfield (L, -4, "__propget");
1383         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1384         lua_pushcclosure (L, &CFunc::getWPtrProperty <T,U>, 1);
1385         lua_pushvalue (L, -1);
1386         rawsetfield (L, -4, name);
1387         rawsetfield (L, -2, name);
1388         lua_pop (L, 2);
1389       }
1390
1391       if (isWritable)
1392       {
1393         // Add to __propset in class table.
1394         rawgetfield (L, -2, "__propset");
1395         assert (lua_istable (L, -1));
1396         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1397         lua_pushcclosure (L, &CFunc::setWPtrProperty <T,U>, 1);
1398         rawsetfield (L, -2, name);
1399         lua_pop (L, 1);
1400       }
1401
1402       set_shared_class ();
1403       assert (lua_istable (L, -1));
1404       // Add to __propget in class and const tables.
1405       {
1406         rawgetfield (L, -2, "__propget");
1407         rawgetfield (L, -4, "__propget");
1408         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1409         lua_pushcclosure (L, &CFunc::getPtrProperty <T,U>, 1);
1410         lua_pushvalue (L, -1);
1411         rawsetfield (L, -4, name);
1412         rawsetfield (L, -2, name);
1413         lua_pop (L, 2);
1414       }
1415
1416       if (isWritable)
1417       {
1418         // Add to __propset in class table.
1419         rawgetfield (L, -2, "__propset");
1420         assert (lua_istable (L, -1));
1421         new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1422         lua_pushcclosure (L, &CFunc::setPtrProperty <T,U>, 1);
1423         rawsetfield (L, -2, name);
1424         lua_pop (L, 1);
1425       }
1426
1427       return *this;
1428     }
1429
1430
1431     Namespace endClass ()
1432     {
1433       return Namespace (this);
1434     }
1435
1436   private:
1437     void set_weak_class () {
1438       lua_pop (L, 3);
1439       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::weak_ptr<T> >::getStaticKey ());
1440       rawgetfield (L, -1, "__class");
1441       rawgetfield (L, -1, "__const");
1442       lua_insert (L, -3);
1443       lua_insert (L, -2);
1444     }
1445     void set_shared_class () {
1446       lua_pop (L, 3);
1447       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::shared_ptr<T> >::getStaticKey ());
1448       rawgetfield (L, -1, "__class");
1449       rawgetfield (L, -1, "__const");
1450       lua_insert (L, -3);
1451       lua_insert (L, -2);
1452     }
1453     Class<boost::shared_ptr<T> > shared;
1454     Class<boost::weak_ptr<T> > weak;
1455   };
1456
1457
1458 private:
1459   //----------------------------------------------------------------------------
1460   /**
1461       Open the global namespace for registrations.
1462   */
1463   explicit Namespace (lua_State* L_)
1464     : L (L_)
1465     , m_stackSize (0)
1466 #ifdef LUABINDINGDOC
1467     , _name ("")
1468     , _parent (0)
1469 #endif
1470   {
1471     lua_getglobal (L, "_G");
1472     ++m_stackSize;
1473   }
1474
1475 #ifdef LUABINDINGDOC
1476   std::string _name;
1477   Namespace const * _parent;
1478 #endif
1479
1480   //----------------------------------------------------------------------------
1481   /**
1482       Open a namespace for registrations.
1483
1484       The namespace is created if it doesn't already exist.
1485       The parent namespace is at the top of the Lua stack.
1486   */
1487   Namespace (char const* name, Namespace const* parent)
1488     : L (parent->L)
1489     , m_stackSize (0)
1490 #ifdef LUABINDINGDOC
1491     , _name (parent->_name + name + ":")
1492     , _parent (parent)
1493 #endif
1494   {
1495     m_stackSize = parent->m_stackSize + 1;
1496     parent->m_stackSize = 0;
1497
1498     assert (lua_istable (L, -1));
1499     rawgetfield (L, -1, name);
1500     if (lua_isnil (L, -1))
1501     {
1502       lua_pop (L, 1);
1503
1504       lua_newtable (L);
1505       lua_pushvalue (L, -1);
1506       lua_setmetatable (L, -2);
1507       lua_pushcfunction (L, &CFunc::indexMetaMethod);
1508       rawsetfield (L, -2, "__index");
1509       lua_pushcfunction (L, &CFunc::newindexMetaMethod);
1510       rawsetfield (L, -2, "__newindex");
1511       lua_newtable (L);
1512       rawsetfield (L, -2, "__propget");
1513       lua_newtable (L);
1514       rawsetfield (L, -2, "__propset");
1515       lua_pushvalue (L, -1);
1516       rawsetfield (L, -3, name);
1517 #if 0
1518       lua_pushcfunction (L, &tostringMetaMethod);
1519       rawsetfield (L, -2, "__tostring");
1520 #endif
1521     }
1522   }
1523
1524   //----------------------------------------------------------------------------
1525   /**
1526       Creates a continued registration from a child namespace.
1527   */
1528   explicit Namespace (Namespace const* child)
1529     : L (child->L)
1530     , m_stackSize (0)
1531 #ifdef LUABINDINGDOC
1532     , _name (child->_parent ? child->_parent->_name : "")
1533     , _parent (child->_parent ? child->_parent->_parent : NULL)
1534 #endif
1535   {
1536     m_stackSize = child->m_stackSize - 1;
1537     child->m_stackSize = 1;
1538     child->pop (1);
1539
1540     // It is not necessary or valid to call
1541     // endNamespace() for the global namespace!
1542     //
1543     assert (m_stackSize != 0);
1544   }
1545
1546   //----------------------------------------------------------------------------
1547   /**
1548       Creates a continued registration from a child class.
1549   */
1550   explicit Namespace (ClassBase const* child)
1551     : L (child->L)
1552     , m_stackSize (0)
1553 #ifdef LUABINDINGDOC
1554     , _name (child->_parent ? child->_parent->_name : "")
1555     , _parent (child->_parent ? child->_parent->_parent : NULL)
1556 #endif
1557   {
1558     m_stackSize = child->m_stackSize - 3;
1559     child->m_stackSize = 3;
1560     child->pop (3);
1561   }
1562
1563 public:
1564   //----------------------------------------------------------------------------
1565   /**
1566       Copy Constructor.
1567
1568       Ownership of the stack is transferred to the new object. This happens
1569       when the compiler emits temporaries to hold these objects while chaining
1570       registrations across namespaces.
1571   */
1572   Namespace (Namespace const& other) : L (other.L)
1573   {
1574     m_stackSize = other.m_stackSize;
1575     other.m_stackSize = 0;
1576 #ifdef LUABINDINGDOC
1577     _name = other._name;
1578     _parent = other._parent;
1579 #endif
1580   }
1581
1582   //----------------------------------------------------------------------------
1583   /**
1584       Closes this namespace registration.
1585   */
1586   ~Namespace ()
1587   {
1588     pop (m_stackSize);
1589   }
1590
1591   //----------------------------------------------------------------------------
1592   /**
1593       Open the global namespace.
1594   */
1595   static Namespace getGlobalNamespace (lua_State* L)
1596   {
1597     return Namespace (L);
1598   }
1599
1600   //----------------------------------------------------------------------------
1601   /**
1602       Open a new or existing namespace for registrations.
1603   */
1604   Namespace beginNamespace (char const* name)
1605   {
1606     return Namespace (name, this);
1607   }
1608
1609   //----------------------------------------------------------------------------
1610   /**
1611       Continue namespace registration in the parent.
1612
1613       Do not use this on the global namespace.
1614   */
1615   Namespace endNamespace ()
1616   {
1617     return Namespace (this);
1618   }
1619
1620   //----------------------------------------------------------------------------
1621   /**
1622       Add or replace a variable.
1623   */
1624   template <class T>
1625   Namespace& addVariable (char const* name, T* pt, bool isWritable = true)
1626   {
1627     assert (lua_istable (L, -1));
1628
1629     rawgetfield (L, -1, "__propget");
1630     assert (lua_istable (L, -1));
1631     lua_pushlightuserdata (L, pt);
1632     lua_pushcclosure (L, &CFunc::getVariable <T>, 1);
1633     rawsetfield (L, -2, name);
1634     lua_pop (L, 1);
1635
1636     rawgetfield (L, -1, "__propset");
1637     assert (lua_istable (L, -1));
1638     if (isWritable)
1639     {
1640       lua_pushlightuserdata (L, pt);
1641       lua_pushcclosure (L, &CFunc::setVariable <T>, 1);
1642     }
1643     else
1644     {
1645       lua_pushstring (L, name);
1646       lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1647     }
1648     rawsetfield (L, -2, name);
1649     lua_pop (L, 1);
1650
1651     return *this;
1652   }
1653
1654   template <typename U>
1655   Namespace& addConst (char const* name, const U val)
1656   {
1657     DATADOC ("Constant/Enum", name, val)
1658     assert (lua_istable (L, -1));
1659     rawgetfield (L, -1, "__propget");
1660     new (lua_newuserdata (L, sizeof (val))) U (val);
1661     lua_pushcclosure (L, &CFunc::getConst <U>, 1);
1662     rawsetfield (L, -2, name);
1663     lua_pop (L, 1);
1664
1665     rawgetfield (L, -1, "__propset");
1666     assert (lua_istable (L, -1));
1667     lua_pushstring (L, name);
1668     lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1669     rawsetfield (L, -2, name);
1670     lua_pop (L, 1);
1671     return *this;
1672   }
1673
1674   //----------------------------------------------------------------------------
1675   /**
1676       Add or replace a property.
1677
1678       If the set function is omitted or null, the property is read-only.
1679   */
1680 #if 0 // unused
1681   template <class TG, class TS>
1682   Namespace& addProperty (char const* name, TG (*get) (), void (*set)(TS) = 0)
1683   {
1684     assert (lua_istable (L, -1));
1685
1686     rawgetfield (L, -1, "__propget");
1687     assert (lua_istable (L, -1));
1688     typedef TG (*get_t) ();
1689     new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
1690     lua_pushcclosure (L, &CFunc::Call <TG (*) (void)>::f, 1);
1691     rawsetfield (L, -2, name);
1692     lua_pop (L, 1);
1693
1694     rawgetfield (L, -1, "__propset");
1695     assert (lua_istable (L, -1));
1696     if (set != 0)
1697     {
1698       typedef void (*set_t) (TS);
1699       new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
1700       lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1);
1701     }
1702     else
1703     {
1704       lua_pushstring (L, name);
1705       lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1706     }
1707     rawsetfield (L, -2, name);
1708     lua_pop (L, 1);
1709
1710     return *this;
1711   }
1712 #endif
1713
1714   //----------------------------------------------------------------------------
1715   /**
1716       Add or replace a free function.
1717   */
1718   template <class FP>
1719   Namespace& addFunction (char const* name, FP const fp)
1720   {
1721     FUNDOC ("Free Function", name, FP)
1722     assert (lua_istable (L, -1));
1723
1724     new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1725     lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
1726     rawsetfield (L, -2, name);
1727
1728     return *this;
1729   }
1730
1731   template <class FP>
1732   Namespace& addRefFunction (char const* name, FP const fp)
1733   {
1734     FUNDOC ("Free Function RefReturn", name, FP)
1735     assert (lua_istable (L, -1));
1736
1737     new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1738     lua_pushcclosure (L, &CFunc::CallRef <FP>::f, 1);
1739     rawsetfield (L, -2, name);
1740
1741     return *this;
1742   }
1743
1744   //----------------------------------------------------------------------------
1745   /**
1746       Add or replace a array type
1747   */
1748
1749   template <typename T>
1750   Namespace registerArray (char const* name)
1751   {
1752     return Array <T> (name, this).endArray();
1753   }
1754
1755
1756   //----------------------------------------------------------------------------
1757   /**
1758       Add or replace a lua_CFunction.
1759   */
1760   Namespace& addCFunction (char const* name, int (*const fp)(lua_State*))
1761   {
1762     DATADOC ("Free C Function", name, fp)
1763     lua_pushcfunction (L, fp);
1764     rawsetfield (L, -2, name);
1765
1766     return *this;
1767   }
1768
1769   //----------------------------------------------------------------------------
1770   /**
1771       Open a new or existing class for registrations.
1772   */
1773   template <class T>
1774   Class <T> beginClass (char const* name)
1775   {
1776     return Class <T> (name, this);
1777   }
1778
1779   /** weak & shared pointer class */
1780   template <class T>
1781   WSPtrClass <T> beginWSPtrClass (char const* name)
1782   {
1783     return WSPtrClass <T> (name, this)
1784       .addNullCheck()
1785       .addEqualCheck();
1786   }
1787
1788   //----------------------------------------------------------------------------
1789
1790   template <class K, class V>
1791   Class<std::map<K, V> > beginStdMap (char const* name)
1792   {
1793     typedef std::map<K, V> LT;
1794     typedef std::pair<const K, V> T;
1795
1796     typedef typename std::map<K, V>::size_type T_SIZE;
1797
1798     return beginClass<LT> (name)
1799       .addVoidConstructor ()
1800       .addFunction ("empty", &LT::empty)
1801       .addFunction ("size", &LT::size)
1802       .addFunction ("clear", (void (LT::*)())&LT::clear)
1803       .addFunction ("count", (T_SIZE (LT::*)(const K&) const)&LT::count)
1804       .addExtCFunction ("add", &CFunc::tableToMap<K, V>)
1805       .addExtCFunction ("iter", &CFunc::mapIter<K, V>)
1806       .addExtCFunction ("table", &CFunc::mapToTable<K, V>)
1807       .addExtCFunction ("at", &CFunc::mapAt<K, V>);
1808   }
1809
1810   template <class T>
1811   Class<std::set<T> > beginStdSet (char const* name)
1812   {
1813     typedef std::set<T> LT;
1814     return beginClass<LT> (name)
1815       .addVoidConstructor ()
1816       .addFunction ("clear", (void (LT::*)())&LT::clear)
1817       .addFunction ("empty", &LT::empty)
1818       .addFunction ("size", &LT::size)
1819       .addExtCFunction ("add", &CFunc::tableToSet<T>)
1820       .addExtCFunction ("iter", &CFunc::setIter<T>)
1821       .addExtCFunction ("table", &CFunc::setToTable<T>);
1822   }
1823
1824   template <unsigned int T>
1825   Class<std::bitset<T> > beginStdBitSet (char const* name)
1826   {
1827     typedef std::bitset<T> BS;
1828     return beginClass<BS> (name)
1829       .addVoidConstructor ()
1830       .addFunction ("reset", (BS& (BS::*)())&BS::reset)
1831       .addFunction ("set", (BS& (BS::*)(size_t, bool))&BS::set)
1832       .addFunction ("count", &BS::count)
1833       .addFunction ("any", &BS::any)
1834       .addFunction ("none", &BS::none)
1835       .addFunction ("test", &BS::test)
1836       .addFunction ("size", &BS::size)
1837       .addExtCFunction ("add", &CFunc::tableToBitSet<T>)
1838       .addExtCFunction ("table", &CFunc::bitSetToTable<T>);
1839   }
1840
1841   template <class T>
1842   Class<std::list<T> > beginConstStdList (char const* name)
1843   {
1844     typedef std::list<T> LT;
1845     return beginClass<LT> (name)
1846       .addVoidConstructor ()
1847       .addFunction ("empty", &LT::empty)
1848       .addFunction ("size", &LT::size)
1849       .addFunction ("reverse", &LT::reverse)
1850       .addFunction ("front", static_cast<const T& (LT::*)() const>(&LT::front))
1851       .addFunction ("back", static_cast<const T& (LT::*)() const>(&LT::back))
1852       .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1853       .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1854   }
1855
1856   template <class T>
1857   Class<std::list<T> > beginStdList (char const* name)
1858   {
1859     typedef std::list<T> LT;
1860     return beginConstStdList<T> (name)
1861       .addFunction ("unique", (void (LT::*)())&LT::unique)
1862       .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1863       .addExtCFunction ("add", &CFunc::tableToList<T, LT>);
1864   }
1865
1866   template <class T>
1867   Class<std::vector<T> > beginStdVector (char const* name)
1868   {
1869     typedef std::vector<T> LT;
1870     typedef typename std::vector<T>::reference T_REF;
1871     typedef typename std::vector<T>::size_type T_SIZE;
1872
1873     return beginClass<LT> (name)
1874       .addVoidConstructor ()
1875       .addFunction ("empty", &LT::empty)
1876       .addFunction ("size", &LT::size)
1877       .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1878       .addFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
1879       .addExtCFunction ("add", &CFunc::tableToList<T, LT>)
1880       .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1881       .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1882   }
1883
1884   //----------------------------------------------------------------------------
1885
1886   template <class T>
1887   Class<boost::shared_ptr<std::list<T> > > beginPtrStdList (char const* name)
1888   {
1889     typedef std::list<T> LT;
1890     return beginClass<boost::shared_ptr<LT> > (name)
1891       //.addVoidPtrConstructor<LT> ()
1892       .addPtrFunction ("empty", &LT::empty)
1893       .addPtrFunction ("size", &LT::size)
1894       .addPtrFunction ("reverse", &LT::reverse)
1895       .addPtrFunction ("unique", (void (LT::*)())&LT::unique)
1896       .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1897       .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
1898       .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
1899       .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
1900   }
1901
1902   template <class T>
1903   Class<boost::shared_ptr<std::vector<T> > > beginPtrStdVector (char const* name)
1904   {
1905     typedef std::vector<T> LT;
1906     typedef typename std::vector<T>::reference T_REF;
1907     typedef typename std::vector<T>::size_type T_SIZE;
1908
1909     return beginClass<boost::shared_ptr<LT> > (name)
1910       //.addVoidPtrConstructor<LT> ()
1911       .addPtrFunction ("empty", &LT::empty)
1912       .addPtrFunction ("empty", &LT::empty)
1913       .addPtrFunction ("size", &LT::size)
1914       .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1915       .addPtrFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
1916       .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
1917       .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
1918       .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
1919   }
1920
1921   //----------------------------------------------------------------------------
1922   /**
1923       Derive a new class for registrations.
1924
1925       To continue registrations for the class later, use beginClass().
1926       Do not call deriveClass() again.
1927   */
1928   template <class T, class U>
1929   Class <T> deriveClass (char const* name)
1930   {
1931     CLASSDOC ("[C] Derived Class", _name << name, type_name <T>(), type_name <U>())
1932     return Class <T> (name, this, ClassInfo <U>::getStaticKey ());
1933   }
1934
1935   template <class T, class U>
1936   WSPtrClass <T> deriveWSPtrClass (char const* name)
1937   {
1938
1939     CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::shared_ptr<T> >(), type_name <boost::shared_ptr<U> >())
1940     CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::weak_ptr<T> >(), type_name <boost::weak_ptr<U> >())
1941     CLASSDOC ("[C] Derived Pointer Class", _name << name, type_name <T>(), type_name <U>())
1942     return WSPtrClass <T> (name, this,
1943         ClassInfo <boost::shared_ptr<U> >::getStaticKey (),
1944         ClassInfo <boost::weak_ptr<U> >::getStaticKey ())
1945       .addNullCheck()
1946       .addEqualCheck();
1947   }
1948
1949 };
1950
1951 //------------------------------------------------------------------------------
1952 /**
1953     Retrieve the global namespace.
1954
1955     It is recommended to put your namespace inside the global namespace, and
1956     then add your classes and functions to it, rather than adding many classes
1957     and functions directly to the global namespace.
1958 */
1959 inline Namespace getGlobalNamespace (lua_State* L)
1960 {
1961   return Namespace::getGlobalNamespace (L);
1962 }
1963
1964
1965 #undef KEYSTA
1966 #undef KEYEND
1967 #undef CLASSDOC
1968 #undef PRINTDOC
1969 #undef FUNDOC
1970 #undef DATADOC
1971
1972 /* vim: set et sw=2: */