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