allow lua binding functions with up to 9 parameters
[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 #if 0 // unused
787     //--------------------------------------------------------------------------
788     /**
789       Add or replace a property member.
790     */
791     template <class TG, class TS>
792     Class <T>& addProperty (char const* name, TG (T::* get) () const, void (T::* set) (TS))
793     {
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 void (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     // read-only
822     template <class TG>
823     Class <T>& addProperty (char const* name, TG (T::* get) () const)
824     {
825       // Add to __propget in class and const tables.
826       rawgetfield (L, -2, "__propget");
827       rawgetfield (L, -4, "__propget");
828       typedef TG (T::*get_t) () const;
829       new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
830       lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1);
831       lua_pushvalue (L, -1);
832       rawsetfield (L, -4, name);
833       rawsetfield (L, -2, name);
834       lua_pop (L, 2);
835
836       return *this;
837     }
838
839     //--------------------------------------------------------------------------
840     /**
841       Add or replace a property member, by proxy.
842
843       When a class is closed for modification and does not provide (or cannot
844       provide) the function signatures necessary to implement get or set for
845       a property, this will allow non-member functions act as proxies.
846
847       Both the get and the set functions require a T const* and T* in the first
848       argument respectively.
849     */
850     template <class TG, class TS>
851     Class <T>& addProperty (char const* name, TG (*get) (T const*), void (*set) (T*, TS))
852     {
853       // Add to __propget in class and const tables.
854       {
855         rawgetfield (L, -2, "__propget");
856         rawgetfield (L, -4, "__propget");
857         typedef TG (*get_t) (T const*);
858         new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
859         lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
860         lua_pushvalue (L, -1);
861         rawsetfield (L, -4, name);
862         rawsetfield (L, -2, name);
863         lua_pop (L, 2);
864       }
865
866       if (set != 0)
867       {
868         // Add to __propset in class table.
869         rawgetfield (L, -2, "__propset");
870         assert (lua_istable (L, -1));
871         typedef void (*set_t) (T*, TS);
872         new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
873         lua_pushcclosure (L, &CFunc::Call <set_t>::f, 1);
874         rawsetfield (L, -2, name);
875         lua_pop (L, 1);
876       }
877
878       return *this;
879     }
880
881     // read-only
882     template <class TG, class TS>
883     Class <T>& addProperty (char const* name, TG (*get) (T const*))
884     {
885       // Add to __propget in class and const tables.
886       rawgetfield (L, -2, "__propget");
887       rawgetfield (L, -4, "__propget");
888       typedef TG (*get_t) (T const*);
889       new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
890       lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
891       lua_pushvalue (L, -1);
892       rawsetfield (L, -4, name);
893       rawsetfield (L, -2, name);
894       lua_pop (L, 2);
895
896       return *this;
897     }
898 #endif
899     //--------------------------------------------------------------------------
900     /**
901         Add or replace a member function.
902     */
903     template <class MemFn>
904     Class <T>& addFunction (char const* name, MemFn mf)
905     {
906       FUNDOC("Member Function", name, MemFn)
907       CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
908       return *this;
909     }
910
911     template <class MemFn>
912     Class <T>& addPtrFunction (char const* name, MemFn mf)
913     {
914       FUNDOC("Member Pointer Function", name, MemFn)
915       CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
916       return *this;
917     }
918
919     template <class MemFn>
920     Class <T>& addWPtrFunction (char const* name, MemFn mf)
921     {
922       FUNDOC("Member Weak Pointer Function", name, MemFn)
923       CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
924       return *this;
925     }
926
927     template <class MemFn>
928     Class <T>& addRefFunction (char const* name, MemFn mf)
929     {
930       FUNDOC("Member Function RefReturn", name, MemFn)
931       CFunc::CallMemberRefFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
932       return *this;
933     }
934
935
936     //--------------------------------------------------------------------------
937     /**
938         Add or replace a member lua_CFunction.
939     */
940     Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*))
941     {
942       DATADOC ("C Function", name, mfp)
943       typedef int (T::*MFP)(lua_State*);
944       assert (lua_istable (L, -1));
945       new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
946       lua_pushcclosure (L, &CFunc::CallMemberCFunction <T>::f, 1);
947       rawsetfield (L, -3, name); // class table
948
949       return *this;
950     }
951
952     // custom callback - extend existing classes
953     // with non-class member functions (e.g STL iterator)
954     Class <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
955     {
956       DATADOC ("Ext C Function", name, fp)
957       assert (lua_istable (L, -1));
958       lua_pushcclosure (L, fp, 0);
959       rawsetfield (L, -3, name); // class table
960       return *this;
961     }
962
963     //--------------------------------------------------------------------------
964     /**
965         Add or replace a const member lua_CFunction.
966     */
967     Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*) const)
968     {
969       DATADOC ("Const C Member Function", name, mfp)
970       typedef int (T::*MFP)(lua_State*) const;
971       assert (lua_istable (L, -1));
972       new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
973       lua_pushcclosure (L, &CFunc::CallConstMemberCFunction <T>::f, 1);
974       lua_pushvalue (L, -1);
975       rawsetfield (L, -5, name); // const table
976       rawsetfield (L, -3, name); // class table
977
978       return *this;
979     }
980
981     /**
982         Add or replace a static const data
983     */
984     template <typename U>
985       Class <T>& addConst (char const* name, const U val)
986       {
987         DATADOC ("Constant/Enum Member", name, val)
988         assert (lua_istable (L, -1));
989
990         rawgetfield (L, -1, "__propget"); // static
991         new (lua_newuserdata (L, sizeof (val))) U (val);
992         lua_pushcclosure (L, &CFunc::getConst <U>, 1);
993         rawsetfield (L, -2, name);
994         lua_pop (L, 1);
995
996         rawgetfield (L, -1, "__propset"); // static
997         lua_pushstring (L, name);
998         lua_pushcclosure (L, &CFunc::readOnlyError, 1);
999         rawsetfield (L, -2, name);
1000         lua_pop (L, 1);
1001         return *this;
1002       }
1003
1004     //--------------------------------------------------------------------------
1005     /**
1006       Add or replace a primary Constructor.
1007
1008       The primary Constructor is invoked when calling the class type table
1009       like a function.
1010
1011       The template parameter should be a function pointer type that matches
1012       the desired Constructor (since you can't take the address of a Constructor
1013       and pass it as an argument).
1014     */
1015     template <class MemFn, class C>
1016     Class <T>& addConstructor ()
1017     {
1018       FUNDOC("Constructor", "", MemFn)
1019       lua_pushcclosure (L,
1020         &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0);
1021       rawsetfield(L, -2, "__call");
1022
1023       return *this;
1024     }
1025
1026     template <class MemFn>
1027     Class <T>& addConstructor ()
1028     {
1029       FUNDOC("Constructor", "", MemFn)
1030       lua_pushcclosure (L,
1031         &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0);
1032       rawsetfield(L, -2, "__call");
1033
1034       return *this;
1035     }
1036
1037     Class <T>& addVoidConstructor ()
1038     {
1039       return addConstructor <void (*) ()> ();
1040     }
1041
1042     Class <T>& addEqualCheck ()
1043     {
1044       PRINTDOC("Member Function", _name << "sameinstance", std::string("bool"), std::string("void (*)(" + type_name <T>() + ")"))
1045       assert (lua_istable (L, -1));
1046       lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1047       rawsetfield (L, -3, "sameinstance");
1048       return *this;
1049     }
1050
1051   };
1052
1053   /** C Array to/from table */
1054   template <typename T>
1055   class Array : virtual public ClassBase
1056   {
1057   public:
1058     Array (char const* name, Namespace const* parent) : ClassBase (parent->L)
1059     {
1060 #ifdef LUABINDINGDOC
1061       _parent = parent;
1062       _name = parent->_name + name + ":";
1063 #endif
1064       PRINTDOC ("[C] Array", parent->_name << name,
1065           std::string(), type_name <T>() + "*")
1066       PRINTDOC ("Ext C Function", _name << "array",
1067           std::string(""), "int (*)(lua_State*)")
1068       PRINTDOC ("Ext C Function", _name << "get_table",
1069           std::string(""), "int (*)(lua_State*)")
1070       PRINTDOC ("Ext C Function", _name << "set_table",
1071           std::string(""), "int (*)(lua_State*)")
1072       PRINTDOC("Member Function", _name << "sameinstance",
1073           std::string("bool"), std::string("bool (*)(" + type_name <T>() + "*)"))
1074       PRINTDOC("Member Function", _name << "offset",
1075           std::string(type_name <T>() + "*"), std::string(type_name <T>() + "* (*)(unsigned int)"))
1076
1077       m_stackSize = parent->m_stackSize + 3;
1078       parent->m_stackSize = 0;
1079
1080 #if 0 // don't allow to duplicates handlers for same array-type
1081       assert (lua_istable (L, -1));
1082       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1083       if (lua_istable (L, -1)) {
1084         lua_pushnil (L);
1085         lua_pushnil (L);
1086         return;
1087       }
1088       lua_pop (L, 1);
1089 #endif
1090
1091       assert (lua_istable (L, -1));
1092       rawgetfield (L, -1, name);
1093
1094       if (lua_isnil (L, -1))
1095       {
1096         lua_pop (L, 1);
1097
1098         // register array access in global namespace
1099         luaL_newmetatable (L, typeid(T).name());
1100         lua_pushcclosure (L, CFunc::array_index<T>, 0);
1101         lua_setfield(L, -2, "__index");
1102         lua_pushcclosure (L, CFunc::array_newindex<T>, 0);
1103         lua_setfield(L, -2, "__newindex");
1104         lua_pop (L, 1);
1105
1106         createConstTable (name);
1107         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1108         rawsetfield (L, -2, "__gc");
1109
1110         createClassTable (name);
1111         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1112         rawsetfield (L, -2, "__gc");
1113
1114         createStaticTable (name);
1115
1116         // Map T back to its tables.
1117         lua_pushvalue (L, -1);
1118         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
1119         lua_pushvalue (L, -2);
1120         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1121         lua_pushvalue (L, -3);
1122         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
1123
1124         assert (lua_istable (L, -1));
1125         lua_pushcclosure (L, &CFunc::getArray <T>, 0);
1126         rawsetfield (L, -3, "array"); // class table
1127
1128         lua_pushcclosure (L, &CFunc::getTable <T>, 0);
1129         rawsetfield (L, -3, "get_table"); // class table
1130
1131         lua_pushcclosure (L, &CFunc::setTable <T>, 0);
1132         rawsetfield (L, -3, "set_table"); // class table
1133
1134         lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1135         rawsetfield (L, -3, "sameinstance");
1136
1137         lua_pushcclosure (L, &CFunc::offsetArray <T>, 0);
1138         rawsetfield (L, -3, "offset"); // class table
1139
1140       }
1141       else
1142       {
1143         lua_pushnil (L);
1144         lua_pushnil (L);
1145       }
1146     }
1147
1148     Namespace endArray ()
1149     {
1150       return Namespace (this);
1151     }
1152   };
1153
1154   /** Boost Weak & Shared Pointer Class Wrapper */
1155   template <class T>
1156   class WSPtrClass : virtual public ClassBase
1157   {
1158   public:
1159     WSPtrClass (char const* name, Namespace const* parent)
1160       : ClassBase (parent->L)
1161       , weak (name, parent)
1162       , shared (name, parent)
1163     {
1164 #ifdef LUABINDINGDOC
1165       _parent = parent;
1166       _name = parent->_name + name + ":";
1167 #endif
1168       PRINTDOC ("[C] Weak/Shared Pointer Class",
1169           parent->_name + name,
1170           std::string(), type_name <T>())
1171       m_stackSize = weak.m_stackSize;
1172       parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1173       lua_pop (L, 3);
1174     }
1175
1176     WSPtrClass (char const* name, Namespace const* parent, void const* const sharedkey, void const* const weakkey)
1177       : ClassBase (parent->L)
1178       , weak (name, parent, weakkey)
1179       , shared (name, parent, sharedkey)
1180     {
1181 #ifdef LUABINDINGDOC
1182       _parent = parent;
1183       _name = parent->_name + name + ":";
1184 #endif
1185       m_stackSize = weak.m_stackSize;
1186       parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1187       lua_pop (L, 3);
1188     }
1189
1190     template <class MemFn>
1191     WSPtrClass <T>& addFunction (char const* name, MemFn mf)
1192     {
1193       FUNDOC ("Weak/Shared Pointer Function", name, MemFn)
1194       set_weak_class ();
1195       CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
1196
1197       set_shared_class ();
1198       CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
1199       return *this;
1200     }
1201
1202     template <class MemFn>
1203     WSPtrClass <T>& addRefFunction (char const* name, MemFn mf)
1204     {
1205       FUNDOC ("Weak/Shared Pointer Function RefReturn", name, MemFn)
1206       set_weak_class ();
1207       CFunc::CallMemberRefWPtrFunctionHelper <MemFn>::add (L, name, mf);
1208
1209       set_shared_class ();
1210       CFunc::CallMemberRefPtrFunctionHelper <MemFn>::add (L, name, mf);
1211       return *this;
1212     }
1213
1214     template <class MemFn>
1215     WSPtrClass <T>& addConstructor ()
1216     {
1217       FUNDOC ("Weak/Shared Pointer Constructor", "", MemFn)
1218       set_weak_class ();
1219       lua_pushcclosure (L,
1220           &weak. template ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::weak_ptr<T> >, 0);
1221       rawsetfield(L, -2, "__call");
1222
1223       set_shared_class ();
1224       lua_pushcclosure (L,
1225           &shared. template ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::shared_ptr<T> >, 0);
1226       rawsetfield(L, -2, "__call");
1227       return *this;
1228     }
1229
1230     WSPtrClass <T>& addVoidConstructor ()
1231     {
1232       return addConstructor <void (*) ()> ();
1233     }
1234
1235     WSPtrClass <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
1236     {
1237       DATADOC ("Weak/Shared Ext C Function", name, fp)
1238       set_weak_class ();
1239       assert (lua_istable (L, -1));
1240       lua_pushcclosure (L, fp, 0);
1241       rawsetfield (L, -3, name); // class table
1242
1243       set_shared_class ();
1244       assert (lua_istable (L, -1));
1245       lua_pushcclosure (L, fp, 0);
1246       rawsetfield (L, -3, name); // class table
1247
1248       return *this;
1249     }
1250
1251     template <class U>
1252     WSPtrClass <T>& addCast (char const* name)
1253     {
1254       PRINTDOC("Weak/Shared Pointer Cast", _name << name,
1255           type_name< U >(),
1256           type_name< U >() << " (" << type_name< T >() << "::*)()")
1257
1258       // TODO weak ptr
1259       set_shared_class ();
1260       assert (lua_istable (L, -1));
1261       lua_pushcclosure (L, &CFunc::CastMemberPtr <T, U>::f, 0);
1262       rawsetfield (L, -3, name); // class table
1263       return *this;
1264     }
1265
1266     WSPtrClass <T>& addNullCheck ()
1267     {
1268       PRINTDOC("Weak/Shared Null Check", _name << "isnil", std::string("bool"), std::string("void (*)()"))
1269       set_weak_class ();
1270       assert (lua_istable (L, -1));
1271       lua_pushcclosure (L, &CFunc::WPtrNullCheck <T>::f, 0);
1272       rawsetfield (L, -3, "isnil"); // class table
1273
1274       set_shared_class ();
1275       assert (lua_istable (L, -1));
1276       lua_pushcclosure (L, &CFunc::PtrNullCheck <T>::f, 0);
1277       rawsetfield (L, -3, "isnil"); // class table
1278
1279       return *this;
1280     }
1281
1282
1283     Namespace endClass ()
1284     {
1285       return Namespace (this);
1286     }
1287
1288   private:
1289     void set_weak_class () {
1290       lua_pop (L, 3);
1291       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::weak_ptr<T> >::getStaticKey ());
1292       rawgetfield (L, -1, "__class");
1293       rawgetfield (L, -1, "__const");
1294       lua_insert (L, -3);
1295       lua_insert (L, -2);
1296     }
1297     void set_shared_class () {
1298       lua_pop (L, 3);
1299       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::shared_ptr<T> >::getStaticKey ());
1300       rawgetfield (L, -1, "__class");
1301       rawgetfield (L, -1, "__const");
1302       lua_insert (L, -3);
1303       lua_insert (L, -2);
1304     }
1305     Class<boost::weak_ptr<T> > weak;
1306     Class<boost::shared_ptr<T> > shared;
1307   };
1308
1309
1310 private:
1311   //----------------------------------------------------------------------------
1312   /**
1313       Open the global namespace for registrations.
1314   */
1315   explicit Namespace (lua_State* L_)
1316     : L (L_)
1317     , m_stackSize (0)
1318 #ifdef LUABINDINGDOC
1319     , _name ("")
1320     , _parent (0)
1321 #endif
1322   {
1323     lua_getglobal (L, "_G");
1324     ++m_stackSize;
1325   }
1326
1327 #ifdef LUABINDINGDOC
1328   std::string _name;
1329   Namespace const * _parent;
1330 #endif
1331
1332   //----------------------------------------------------------------------------
1333   /**
1334       Open a namespace for registrations.
1335
1336       The namespace is created if it doesn't already exist.
1337       The parent namespace is at the top of the Lua stack.
1338   */
1339   Namespace (char const* name, Namespace const* parent)
1340     : L (parent->L)
1341     , m_stackSize (0)
1342 #ifdef LUABINDINGDOC
1343     , _name (parent->_name + name + ":")
1344     , _parent (parent)
1345 #endif
1346   {
1347     m_stackSize = parent->m_stackSize + 1;
1348     parent->m_stackSize = 0;
1349
1350     assert (lua_istable (L, -1));
1351     rawgetfield (L, -1, name);
1352     if (lua_isnil (L, -1))
1353     {
1354       lua_pop (L, 1);
1355
1356       lua_newtable (L);
1357       lua_pushvalue (L, -1);
1358       lua_setmetatable (L, -2);
1359       lua_pushcfunction (L, &CFunc::indexMetaMethod);
1360       rawsetfield (L, -2, "__index");
1361       lua_pushcfunction (L, &CFunc::newindexMetaMethod);
1362       rawsetfield (L, -2, "__newindex");
1363       lua_newtable (L);
1364       rawsetfield (L, -2, "__propget");
1365       lua_newtable (L);
1366       rawsetfield (L, -2, "__propset");
1367       lua_pushvalue (L, -1);
1368       rawsetfield (L, -3, name);
1369 #if 0
1370       lua_pushcfunction (L, &tostringMetaMethod);
1371       rawsetfield (L, -2, "__tostring");
1372 #endif
1373     }
1374   }
1375
1376   //----------------------------------------------------------------------------
1377   /**
1378       Creates a continued registration from a child namespace.
1379   */
1380   explicit Namespace (Namespace const* child)
1381     : L (child->L)
1382     , m_stackSize (0)
1383 #ifdef LUABINDINGDOC
1384     , _name (child->_parent ? child->_parent->_name : "")
1385     , _parent (child->_parent ? child->_parent->_parent : NULL)
1386 #endif
1387   {
1388     m_stackSize = child->m_stackSize - 1;
1389     child->m_stackSize = 1;
1390     child->pop (1);
1391
1392     // It is not necessary or valid to call
1393     // endNamespace() for the global namespace!
1394     //
1395     assert (m_stackSize != 0);
1396   }
1397
1398   //----------------------------------------------------------------------------
1399   /**
1400       Creates a continued registration from a child class.
1401   */
1402   explicit Namespace (ClassBase const* child)
1403     : L (child->L)
1404     , m_stackSize (0)
1405 #ifdef LUABINDINGDOC
1406     , _name (child->_parent ? child->_parent->_name : "")
1407     , _parent (child->_parent ? child->_parent->_parent : NULL)
1408 #endif
1409   {
1410     m_stackSize = child->m_stackSize - 3;
1411     child->m_stackSize = 3;
1412     child->pop (3);
1413   }
1414
1415 public:
1416   //----------------------------------------------------------------------------
1417   /**
1418       Copy Constructor.
1419
1420       Ownership of the stack is transferred to the new object. This happens
1421       when the compiler emits temporaries to hold these objects while chaining
1422       registrations across namespaces.
1423   */
1424   Namespace (Namespace const& other) : L (other.L)
1425   {
1426     m_stackSize = other.m_stackSize;
1427     other.m_stackSize = 0;
1428 #ifdef LUABINDINGDOC
1429     _name = other._name;
1430     _parent = other._parent;
1431 #endif
1432   }
1433
1434   //----------------------------------------------------------------------------
1435   /**
1436       Closes this namespace registration.
1437   */
1438   ~Namespace ()
1439   {
1440     pop (m_stackSize);
1441   }
1442
1443   //----------------------------------------------------------------------------
1444   /**
1445       Open the global namespace.
1446   */
1447   static Namespace getGlobalNamespace (lua_State* L)
1448   {
1449     return Namespace (L);
1450   }
1451
1452   //----------------------------------------------------------------------------
1453   /**
1454       Open a new or existing namespace for registrations.
1455   */
1456   Namespace beginNamespace (char const* name)
1457   {
1458     return Namespace (name, this);
1459   }
1460
1461   //----------------------------------------------------------------------------
1462   /**
1463       Continue namespace registration in the parent.
1464
1465       Do not use this on the global namespace.
1466   */
1467   Namespace endNamespace ()
1468   {
1469     return Namespace (this);
1470   }
1471
1472   //----------------------------------------------------------------------------
1473   /**
1474       Add or replace a variable.
1475   */
1476   template <class T>
1477   Namespace& addVariable (char const* name, T* pt, bool isWritable = true)
1478   {
1479     assert (lua_istable (L, -1));
1480
1481     rawgetfield (L, -1, "__propget");
1482     assert (lua_istable (L, -1));
1483     lua_pushlightuserdata (L, pt);
1484     lua_pushcclosure (L, &CFunc::getVariable <T>, 1);
1485     rawsetfield (L, -2, name);
1486     lua_pop (L, 1);
1487
1488     rawgetfield (L, -1, "__propset");
1489     assert (lua_istable (L, -1));
1490     if (isWritable)
1491     {
1492       lua_pushlightuserdata (L, pt);
1493       lua_pushcclosure (L, &CFunc::setVariable <T>, 1);
1494     }
1495     else
1496     {
1497       lua_pushstring (L, name);
1498       lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1499     }
1500     rawsetfield (L, -2, name);
1501     lua_pop (L, 1);
1502
1503     return *this;
1504   }
1505
1506   template <typename U>
1507   Namespace& addConst (char const* name, const U val)
1508   {
1509     DATADOC ("Constant/Enum", name, val)
1510     assert (lua_istable (L, -1));
1511     rawgetfield (L, -1, "__propget");
1512     new (lua_newuserdata (L, sizeof (val))) U (val);
1513     lua_pushcclosure (L, &CFunc::getConst <U>, 1);
1514     rawsetfield (L, -2, name);
1515     lua_pop (L, 1);
1516
1517     rawgetfield (L, -1, "__propset");
1518     assert (lua_istable (L, -1));
1519     lua_pushstring (L, name);
1520     lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1521     rawsetfield (L, -2, name);
1522     lua_pop (L, 1);
1523     return *this;
1524   }
1525
1526   //----------------------------------------------------------------------------
1527   /**
1528       Add or replace a property.
1529
1530       If the set function is omitted or null, the property is read-only.
1531   */
1532   template <class TG, class TS>
1533   Namespace& addProperty (char const* name, TG (*get) (), void (*set)(TS) = 0)
1534   {
1535     assert (lua_istable (L, -1));
1536
1537     rawgetfield (L, -1, "__propget");
1538     assert (lua_istable (L, -1));
1539     typedef TG (*get_t) ();
1540     new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
1541     lua_pushcclosure (L, &CFunc::Call <TG (*) (void)>::f, 1);
1542     rawsetfield (L, -2, name);
1543     lua_pop (L, 1);
1544
1545     rawgetfield (L, -1, "__propset");
1546     assert (lua_istable (L, -1));
1547     if (set != 0)
1548     {
1549       typedef void (*set_t) (TS);
1550       new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
1551       lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1);
1552     }
1553     else
1554     {
1555       lua_pushstring (L, name);
1556       lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1557     }
1558     rawsetfield (L, -2, name);
1559     lua_pop (L, 1);
1560
1561     return *this;
1562   }
1563
1564   //----------------------------------------------------------------------------
1565   /**
1566       Add or replace a free function.
1567   */
1568   template <class FP>
1569   Namespace& addFunction (char const* name, FP const fp)
1570   {
1571     FUNDOC ("Free Function", name, FP)
1572     assert (lua_istable (L, -1));
1573
1574     new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1575     lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
1576     rawsetfield (L, -2, name);
1577
1578     return *this;
1579   }
1580
1581   template <class FP>
1582   Namespace& addRefFunction (char const* name, FP const fp)
1583   {
1584     FUNDOC ("Free Function RefReturn", name, FP)
1585     assert (lua_istable (L, -1));
1586
1587     new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1588     lua_pushcclosure (L, &CFunc::CallRef <FP>::f, 1);
1589     rawsetfield (L, -2, name);
1590
1591     return *this;
1592   }
1593
1594   //----------------------------------------------------------------------------
1595   /**
1596       Add or replace a array type
1597   */
1598
1599   template <typename T>
1600   Namespace registerArray (char const* name)
1601   {
1602     return Array <T> (name, this).endArray();
1603   }
1604
1605
1606   //----------------------------------------------------------------------------
1607   /**
1608       Add or replace a lua_CFunction.
1609   */
1610   Namespace& addCFunction (char const* name, int (*const fp)(lua_State*))
1611   {
1612     DATADOC ("Free C Function", name, fp)
1613     lua_pushcfunction (L, fp);
1614     rawsetfield (L, -2, name);
1615
1616     return *this;
1617   }
1618
1619   //----------------------------------------------------------------------------
1620   /**
1621       Open a new or existing class for registrations.
1622   */
1623   template <class T>
1624   Class <T> beginClass (char const* name)
1625   {
1626     return Class <T> (name, this);
1627   }
1628
1629   /** weak & shared pointer class */
1630   template <class T>
1631   WSPtrClass <T> beginWSPtrClass (char const* name)
1632   {
1633     return WSPtrClass <T> (name, this)
1634       .addNullCheck();
1635   }
1636
1637   //----------------------------------------------------------------------------
1638
1639   template <class K, class V>
1640   Class<std::map<K, V> > beginStdMap (char const* name)
1641   {
1642     typedef std::map<K, V> LT;
1643     typedef std::pair<const K, V> T;
1644
1645     return beginClass<LT> (name)
1646       .addVoidConstructor ()
1647       .addFunction ("empty", &LT::empty)
1648       .addFunction ("size", &LT::size)
1649       .addFunction ("clear", (void (LT::*)())&LT::clear)
1650       .addFunction ("count", (void (LT::*)())&LT::count)
1651       .addExtCFunction ("add", &CFunc::tableToMap<K, V>)
1652       .addExtCFunction ("iter", &CFunc::mapIter<K, V>)
1653       .addExtCFunction ("table", &CFunc::mapToTable<K, V>);
1654   }
1655
1656   template <class T>
1657   Class<std::set<T> > beginStdSet (char const* name)
1658   {
1659     typedef std::set<T> LT;
1660     return beginClass<LT> (name)
1661       .addVoidConstructor ()
1662       .addFunction ("clear", (void (LT::*)())&LT::clear)
1663       .addFunction ("empty", &LT::empty)
1664       .addFunction ("size", &LT::size)
1665       .addExtCFunction ("add", &CFunc::tableToSet<T>)
1666       .addExtCFunction ("iter", &CFunc::setIter<T>)
1667       .addExtCFunction ("table", &CFunc::setToTable<T>);
1668   }
1669
1670   template <unsigned int T>
1671   Class<std::bitset<T> > beginStdBitSet (char const* name)
1672   {
1673     typedef std::bitset<T> BS;
1674     return beginClass<BS> (name)
1675       .addVoidConstructor ()
1676       .addFunction ("reset", (BS& (BS::*)())&BS::reset)
1677       .addFunction ("set", (BS& (BS::*)(size_t, bool))&BS::set)
1678       .addFunction ("count", &BS::count)
1679       .addFunction ("any", &BS::any)
1680       .addFunction ("none", &BS::none)
1681       .addFunction ("test", &BS::test)
1682       .addFunction ("size", &BS::size)
1683       .addExtCFunction ("add", &CFunc::tableToBitSet<T>)
1684       .addExtCFunction ("table", &CFunc::bitSetToTable<T>);
1685   }
1686
1687   template <class T>
1688   Class<std::list<T> > beginConstStdList (char const* name)
1689   {
1690     typedef std::list<T> LT;
1691     return beginClass<LT> (name)
1692       .addVoidConstructor ()
1693       .addFunction ("empty", &LT::empty)
1694       .addFunction ("size", &LT::size)
1695       .addFunction ("reverse", &LT::reverse)
1696       .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1697       .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1698   }
1699
1700   template <class T>
1701   Class<std::list<T> > beginStdList (char const* name)
1702   {
1703     typedef std::list<T> LT;
1704     return beginConstStdList<T> (name)
1705       .addFunction ("unique", (void (LT::*)())&LT::unique)
1706       .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1707       .addExtCFunction ("add", &CFunc::tableToList<T, LT>);
1708   }
1709
1710   template <class T>
1711   Class<std::vector<T> > beginStdVector (char const* name)
1712   {
1713     typedef std::vector<T> LT;
1714     typedef typename std::vector<T>::reference T_REF;
1715     typedef typename std::vector<T>::size_type T_SIZE;
1716
1717     return beginClass<LT> (name)
1718       .addVoidConstructor ()
1719       .addFunction ("empty", &LT::empty)
1720       .addFunction ("size", &LT::size)
1721       .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1722       .addFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
1723       .addExtCFunction ("add", &CFunc::tableToList<T, LT>)
1724       .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1725       .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1726   }
1727
1728   //----------------------------------------------------------------------------
1729
1730   template <class T>
1731   Class<boost::shared_ptr<std::list<T> > > beginPtrStdList (char const* name)
1732   {
1733     typedef std::list<T> LT;
1734
1735     return beginClass<boost::shared_ptr<LT> > (name)
1736       .addVoidConstructor ()
1737       .addPtrFunction ("empty", &LT::empty)
1738       .addPtrFunction ("size", &LT::size)
1739       .addPtrFunction ("reverse", &LT::reverse)
1740       .addPtrFunction ("unique", (void (LT::*)())&LT::unique)
1741       .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1742       .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
1743       .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
1744       .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
1745   }
1746
1747   template <class T>
1748   Class<boost::shared_ptr<std::vector<T> > > beginPtrStdVector (char const* name)
1749   {
1750     typedef std::vector<T> LT;
1751     typedef typename std::vector<T>::reference T_REF;
1752     typedef typename std::vector<T>::size_type T_SIZE;
1753
1754     return beginClass<boost::shared_ptr<LT> > (name)
1755       .addVoidConstructor ()
1756       .addPtrFunction ("empty", &LT::empty)
1757       .addPtrFunction ("empty", &LT::empty)
1758       .addPtrFunction ("size", &LT::size)
1759       .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1760       .addPtrFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
1761       .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
1762       .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
1763       .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
1764   }
1765
1766   //----------------------------------------------------------------------------
1767   /**
1768       Derive a new class for registrations.
1769
1770       To continue registrations for the class later, use beginClass().
1771       Do not call deriveClass() again.
1772   */
1773   template <class T, class U>
1774   Class <T> deriveClass (char const* name)
1775   {
1776     CLASSDOC ("[C] Derived Class", _name << name, type_name <T>(), type_name <U>())
1777     return Class <T> (name, this, ClassInfo <U>::getStaticKey ());
1778   }
1779
1780   template <class T, class U>
1781   WSPtrClass <T> deriveWSPtrClass (char const* name)
1782   {
1783
1784     CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::shared_ptr<T> >(), type_name <boost::shared_ptr<U> >())
1785     CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::weak_ptr<T> >(), type_name <boost::weak_ptr<U> >())
1786     CLASSDOC ("[C] Derived Pointer Class", _name << name, type_name <T>(), type_name <U>())
1787     return WSPtrClass <T> (name, this,
1788         ClassInfo <boost::shared_ptr<U> >::getStaticKey (),
1789         ClassInfo <boost::weak_ptr<U> >::getStaticKey ())
1790       .addNullCheck();
1791   }
1792
1793 };
1794
1795 //------------------------------------------------------------------------------
1796 /**
1797     Retrieve the global namespace.
1798
1799     It is recommended to put your namespace inside the global namespace, and
1800     then add your classes and functions to it, rather than adding many classes
1801     and functions directly to the global namespace.
1802 */
1803 inline Namespace getGlobalNamespace (lua_State* L)
1804 {
1805   return Namespace::getGlobalNamespace (L);
1806 }
1807
1808
1809 #undef KEYSTA
1810 #undef KEYEND
1811 #undef CLASSDOC
1812 #undef PRINTDOC
1813 #undef FUNDOC
1814 #undef DATADOC
1815
1816 /* vim: set et sw=2: */