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