Lua Array Documentation
[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 Member 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,
1055           std::string(), type_name <T>() + "*")
1056       PRINTDOC ("Ext C Function", _name << "array",
1057           std::string(""), "int (*)(lua_State*)")
1058       PRINTDOC ("Ext C Function", _name << "get_table",
1059           std::string(""), "int (*)(lua_State*)")
1060       PRINTDOC ("Ext C Function", _name << "set_table",
1061           std::string(""), "int (*)(lua_State*)")
1062
1063       m_stackSize = parent->m_stackSize + 3;
1064       parent->m_stackSize = 0;
1065
1066 #if 0 // don't allow to duplicates handlers for same array-type
1067       assert (lua_istable (L, -1));
1068       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1069       if (lua_istable (L, -1)) {
1070         lua_pushnil (L);
1071         lua_pushnil (L);
1072         return;
1073       }
1074       lua_pop (L, 1);
1075 #endif
1076
1077       assert (lua_istable (L, -1));
1078       rawgetfield (L, -1, name);
1079
1080       if (lua_isnil (L, -1))
1081       {
1082         lua_pop (L, 1);
1083
1084         // register array access in global namespace
1085         luaL_newmetatable (L, typeid(T).name());
1086         lua_pushcclosure (L, CFunc::array_index<T>, 0);
1087         lua_setfield(L, -2, "__index");
1088         lua_pushcclosure (L, CFunc::array_newindex<T>, 0);
1089         lua_setfield(L, -2, "__newindex");
1090         lua_pop (L, 1);
1091
1092         createConstTable (name);
1093         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1094         rawsetfield (L, -2, "__gc");
1095
1096         createClassTable (name);
1097         lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1098         rawsetfield (L, -2, "__gc");
1099
1100         createStaticTable (name);
1101
1102         // Map T back to its tables.
1103         lua_pushvalue (L, -1);
1104         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
1105         lua_pushvalue (L, -2);
1106         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1107         lua_pushvalue (L, -3);
1108         lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
1109
1110         assert (lua_istable (L, -1));
1111         lua_pushcclosure (L, &CFunc::getArray <T>, 0);
1112         rawsetfield (L, -3, "array"); // class table
1113
1114         lua_pushcclosure (L, &CFunc::getTable <T>, 0);
1115         rawsetfield (L, -3, "get_table"); // class table
1116
1117         lua_pushcclosure (L, &CFunc::setTable <T>, 0);
1118         rawsetfield (L, -3, "set_table"); // class table
1119       }
1120       else
1121       {
1122         lua_pushnil (L);
1123         lua_pushnil (L);
1124       }
1125     }
1126
1127     Namespace endArray ()
1128     {
1129       return Namespace (this);
1130     }
1131   };
1132
1133   /** Boost Weak & Shared Pointer Class Wrapper */
1134   template <class T>
1135   class WSPtrClass : virtual public ClassBase
1136   {
1137   public:
1138     WSPtrClass (char const* name, Namespace const* parent)
1139       : ClassBase (parent->L)
1140       , weak (name, parent)
1141       , shared (name, parent)
1142     {
1143 #ifdef LUABINDINGDOC
1144       _parent = parent;
1145       _name = parent->_name + name + ":";
1146 #endif
1147       PRINTDOC ("[C] Weak/Shared Pointer Class",
1148           parent->_name + name,
1149           std::string(), type_name <T>())
1150       m_stackSize = weak.m_stackSize;
1151       parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1152       lua_pop (L, 3);
1153     }
1154
1155     WSPtrClass (char const* name, Namespace const* parent, void const* const sharedkey, void const* const weakkey)
1156       : ClassBase (parent->L)
1157       , weak (name, parent, weakkey)
1158       , shared (name, parent, sharedkey)
1159     {
1160 #ifdef LUABINDINGDOC
1161       _parent = parent;
1162       _name = parent->_name + name + ":";
1163 #endif
1164       m_stackSize = weak.m_stackSize;
1165       parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1166       lua_pop (L, 3);
1167     }
1168
1169     template <class MemFn>
1170     WSPtrClass <T>& addFunction (char const* name, MemFn mf)
1171     {
1172       FUNDOC ("Weak/Shared Pointer Function", name, MemFn)
1173       set_weak_class ();
1174       CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
1175
1176       set_shared_class ();
1177       CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
1178       return *this;
1179     }
1180
1181     template <class MemFn>
1182     WSPtrClass <T>& addRefFunction (char const* name, MemFn mf)
1183     {
1184       FUNDOC ("Weak/Shared Pointer Function RefReturn", name, MemFn)
1185       set_weak_class ();
1186       CFunc::CallMemberRefWPtrFunctionHelper <MemFn>::add (L, name, mf);
1187
1188       set_shared_class ();
1189       CFunc::CallMemberRefPtrFunctionHelper <MemFn>::add (L, name, mf);
1190       return *this;
1191     }
1192
1193     template <class MemFn>
1194     WSPtrClass <T>& addConstructor ()
1195     {
1196       FUNDOC ("Weak/Shared Pointer Constructor", "", MemFn)
1197       set_weak_class ();
1198       lua_pushcclosure (L,
1199           &weak. template ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::weak_ptr<T> >, 0);
1200       rawsetfield(L, -2, "__call");
1201
1202       set_shared_class ();
1203       lua_pushcclosure (L,
1204           &shared. template ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::shared_ptr<T> >, 0);
1205       rawsetfield(L, -2, "__call");
1206       return *this;
1207     }
1208
1209     WSPtrClass <T>& addVoidConstructor ()
1210     {
1211       return addConstructor <void (*) ()> ();
1212     }
1213
1214     WSPtrClass <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
1215     {
1216       DATADOC ("Weak/Shared Ext C Function", name, fp)
1217       set_weak_class ();
1218       assert (lua_istable (L, -1));
1219       lua_pushcclosure (L, fp, 0);
1220       rawsetfield (L, -3, name); // class table
1221
1222       set_shared_class ();
1223       assert (lua_istable (L, -1));
1224       lua_pushcclosure (L, fp, 0);
1225       rawsetfield (L, -3, name); // class table
1226
1227       return *this;
1228     }
1229
1230     template <class U>
1231     WSPtrClass <T>& addCast (char const* name)
1232     {
1233       PRINTDOC("Weak/Shared Pointer Cast", _name << name,
1234           type_name< U >(),
1235           type_name< U >() << " (" << type_name< T >() << "::*)()")
1236
1237       // TODO weak ptr
1238       set_shared_class ();
1239       assert (lua_istable (L, -1));
1240       lua_pushcclosure (L, &CFunc::CastMemberPtr <T, U>::f, 0);
1241       rawsetfield (L, -3, name); // class table
1242       return *this;
1243     }
1244
1245     WSPtrClass <T>& addNullCheck ()
1246     {
1247       PRINTDOC("Weak/Shared Null Check", _name << "isnil", std::string("bool"), std::string("void (*)()"))
1248       set_weak_class ();
1249       assert (lua_istable (L, -1));
1250       lua_pushcclosure (L, &CFunc::WPtrNullCheck <T>::f, 0);
1251       rawsetfield (L, -3, "isnil"); // class table
1252
1253       set_shared_class ();
1254       assert (lua_istable (L, -1));
1255       lua_pushcclosure (L, &CFunc::PtrNullCheck <T>::f, 0);
1256       rawsetfield (L, -3, "isnil"); // class table
1257
1258       return *this;
1259     }
1260
1261
1262     Namespace endClass ()
1263     {
1264       return Namespace (this);
1265     }
1266
1267   private:
1268     void set_weak_class () {
1269       lua_pop (L, 3);
1270       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::weak_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     void set_shared_class () {
1277       lua_pop (L, 3);
1278       lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::shared_ptr<T> >::getStaticKey ());
1279       rawgetfield (L, -1, "__class");
1280       rawgetfield (L, -1, "__const");
1281       lua_insert (L, -3);
1282       lua_insert (L, -2);
1283     }
1284     Class<boost::weak_ptr<T> > weak;
1285     Class<boost::shared_ptr<T> > shared;
1286   };
1287
1288
1289 private:
1290   //----------------------------------------------------------------------------
1291   /**
1292       Open the global namespace for registrations.
1293   */
1294   explicit Namespace (lua_State* L_)
1295     : L (L_)
1296     , m_stackSize (0)
1297 #ifdef LUABINDINGDOC
1298     , _name ("")
1299     , _parent (0)
1300 #endif
1301   {
1302     lua_getglobal (L, "_G");
1303     ++m_stackSize;
1304   }
1305
1306 #ifdef LUABINDINGDOC
1307   std::string _name;
1308   Namespace const * _parent;
1309 #endif
1310
1311   //----------------------------------------------------------------------------
1312   /**
1313       Open a namespace for registrations.
1314
1315       The namespace is created if it doesn't already exist.
1316       The parent namespace is at the top of the Lua stack.
1317   */
1318   Namespace (char const* name, Namespace const* parent)
1319     : L (parent->L)
1320     , m_stackSize (0)
1321 #ifdef LUABINDINGDOC
1322     , _name (parent->_name + name + ":")
1323     , _parent (parent)
1324 #endif
1325   {
1326     m_stackSize = parent->m_stackSize + 1;
1327     parent->m_stackSize = 0;
1328
1329     assert (lua_istable (L, -1));
1330     rawgetfield (L, -1, name);
1331     if (lua_isnil (L, -1))
1332     {
1333       lua_pop (L, 1);
1334
1335       lua_newtable (L);
1336       lua_pushvalue (L, -1);
1337       lua_setmetatable (L, -2);
1338       lua_pushcfunction (L, &CFunc::indexMetaMethod);
1339       rawsetfield (L, -2, "__index");
1340       lua_pushcfunction (L, &CFunc::newindexMetaMethod);
1341       rawsetfield (L, -2, "__newindex");
1342       lua_newtable (L);
1343       rawsetfield (L, -2, "__propget");
1344       lua_newtable (L);
1345       rawsetfield (L, -2, "__propset");
1346       lua_pushvalue (L, -1);
1347       rawsetfield (L, -3, name);
1348 #if 0
1349       lua_pushcfunction (L, &tostringMetaMethod);
1350       rawsetfield (L, -2, "__tostring");
1351 #endif
1352     }
1353   }
1354
1355   //----------------------------------------------------------------------------
1356   /**
1357       Creates a continued registration from a child namespace.
1358   */
1359   explicit Namespace (Namespace const* child)
1360     : L (child->L)
1361     , m_stackSize (0)
1362 #ifdef LUABINDINGDOC
1363     , _name (child->_parent ? child->_parent->_name : "")
1364     , _parent (child->_parent ? child->_parent->_parent : NULL)
1365 #endif
1366   {
1367     m_stackSize = child->m_stackSize - 1;
1368     child->m_stackSize = 1;
1369     child->pop (1);
1370
1371     // It is not necessary or valid to call
1372     // endNamespace() for the global namespace!
1373     //
1374     assert (m_stackSize != 0);
1375   }
1376
1377   //----------------------------------------------------------------------------
1378   /**
1379       Creates a continued registration from a child class.
1380   */
1381   explicit Namespace (ClassBase const* child)
1382     : L (child->L)
1383     , m_stackSize (0)
1384 #ifdef LUABINDINGDOC
1385     , _name (child->_parent ? child->_parent->_name : "")
1386     , _parent (child->_parent ? child->_parent->_parent : NULL)
1387 #endif
1388   {
1389     m_stackSize = child->m_stackSize - 3;
1390     child->m_stackSize = 3;
1391     child->pop (3);
1392   }
1393
1394 public:
1395   //----------------------------------------------------------------------------
1396   /**
1397       Copy Constructor.
1398
1399       Ownership of the stack is transferred to the new object. This happens
1400       when the compiler emits temporaries to hold these objects while chaining
1401       registrations across namespaces.
1402   */
1403   Namespace (Namespace const& other) : L (other.L)
1404   {
1405     m_stackSize = other.m_stackSize;
1406     other.m_stackSize = 0;
1407 #ifdef LUABINDINGDOC
1408     _name = other._name;
1409     _parent = other._parent;
1410 #endif
1411   }
1412
1413   //----------------------------------------------------------------------------
1414   /**
1415       Closes this namespace registration.
1416   */
1417   ~Namespace ()
1418   {
1419     pop (m_stackSize);
1420   }
1421
1422   //----------------------------------------------------------------------------
1423   /**
1424       Open the global namespace.
1425   */
1426   static Namespace getGlobalNamespace (lua_State* L)
1427   {
1428     return Namespace (L);
1429   }
1430
1431   //----------------------------------------------------------------------------
1432   /**
1433       Open a new or existing namespace for registrations.
1434   */
1435   Namespace beginNamespace (char const* name)
1436   {
1437     return Namespace (name, this);
1438   }
1439
1440   //----------------------------------------------------------------------------
1441   /**
1442       Continue namespace registration in the parent.
1443
1444       Do not use this on the global namespace.
1445   */
1446   Namespace endNamespace ()
1447   {
1448     return Namespace (this);
1449   }
1450
1451   //----------------------------------------------------------------------------
1452   /**
1453       Add or replace a variable.
1454   */
1455   template <class T>
1456   Namespace& addVariable (char const* name, T* pt, bool isWritable = true)
1457   {
1458     assert (lua_istable (L, -1));
1459
1460     rawgetfield (L, -1, "__propget");
1461     assert (lua_istable (L, -1));
1462     lua_pushlightuserdata (L, pt);
1463     lua_pushcclosure (L, &CFunc::getVariable <T>, 1);
1464     rawsetfield (L, -2, name);
1465     lua_pop (L, 1);
1466
1467     rawgetfield (L, -1, "__propset");
1468     assert (lua_istable (L, -1));
1469     if (isWritable)
1470     {
1471       lua_pushlightuserdata (L, pt);
1472       lua_pushcclosure (L, &CFunc::setVariable <T>, 1);
1473     }
1474     else
1475     {
1476       lua_pushstring (L, name);
1477       lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1478     }
1479     rawsetfield (L, -2, name);
1480     lua_pop (L, 1);
1481
1482     return *this;
1483   }
1484
1485   template <typename U>
1486   Namespace& addConst (char const* name, const U val)
1487   {
1488     DATADOC ("Constant/Enum", name, val)
1489     assert (lua_istable (L, -1));
1490     rawgetfield (L, -1, "__propget");
1491     new (lua_newuserdata (L, sizeof (val))) U (val);
1492     lua_pushcclosure (L, &CFunc::getConst <U>, 1);
1493     rawsetfield (L, -2, name);
1494     lua_pop (L, 1);
1495
1496     rawgetfield (L, -1, "__propset");
1497     assert (lua_istable (L, -1));
1498     lua_pushstring (L, name);
1499     lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1500     rawsetfield (L, -2, name);
1501     lua_pop (L, 1);
1502     return *this;
1503   }
1504
1505   //----------------------------------------------------------------------------
1506   /**
1507       Add or replace a property.
1508
1509       If the set function is omitted or null, the property is read-only.
1510   */
1511   template <class TG, class TS>
1512   Namespace& addProperty (char const* name, TG (*get) (), void (*set)(TS) = 0)
1513   {
1514     assert (lua_istable (L, -1));
1515
1516     rawgetfield (L, -1, "__propget");
1517     assert (lua_istable (L, -1));
1518     typedef TG (*get_t) ();
1519     new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
1520     lua_pushcclosure (L, &CFunc::Call <TG (*) (void)>::f, 1);
1521     rawsetfield (L, -2, name);
1522     lua_pop (L, 1);
1523
1524     rawgetfield (L, -1, "__propset");
1525     assert (lua_istable (L, -1));
1526     if (set != 0)
1527     {
1528       typedef void (*set_t) (TS);
1529       new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
1530       lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1);
1531     }
1532     else
1533     {
1534       lua_pushstring (L, name);
1535       lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1536     }
1537     rawsetfield (L, -2, name);
1538     lua_pop (L, 1);
1539
1540     return *this;
1541   }
1542
1543   //----------------------------------------------------------------------------
1544   /**
1545       Add or replace a free function.
1546   */
1547   template <class FP>
1548   Namespace& addFunction (char const* name, FP const fp)
1549   {
1550     FUNDOC ("Free Function", name, FP)
1551     assert (lua_istable (L, -1));
1552
1553     new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1554     lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
1555     rawsetfield (L, -2, name);
1556
1557     return *this;
1558   }
1559
1560   template <class FP>
1561   Namespace& addRefFunction (char const* name, FP const fp)
1562   {
1563     FUNDOC ("Free Function RefReturn", name, FP)
1564     assert (lua_istable (L, -1));
1565
1566     new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1567     lua_pushcclosure (L, &CFunc::CallRef <FP>::f, 1);
1568     rawsetfield (L, -2, name);
1569
1570     return *this;
1571   }
1572
1573   //----------------------------------------------------------------------------
1574   /**
1575       Add or replace a array type
1576   */
1577
1578   template <typename T>
1579   Namespace registerArray (char const* name)
1580   {
1581     return Array <T> (name, this).endArray();
1582   }
1583
1584
1585   //----------------------------------------------------------------------------
1586   /**
1587       Add or replace a lua_CFunction.
1588   */
1589   Namespace& addCFunction (char const* name, int (*const fp)(lua_State*))
1590   {
1591     lua_pushcfunction (L, fp);
1592     rawsetfield (L, -2, name);
1593
1594     return *this;
1595   }
1596
1597   //----------------------------------------------------------------------------
1598   /**
1599       Open a new or existing class for registrations.
1600   */
1601   template <class T>
1602   Class <T> beginClass (char const* name)
1603   {
1604     return Class <T> (name, this);
1605   }
1606
1607   /** weak & shared pointer class */
1608   template <class T>
1609   WSPtrClass <T> beginWSPtrClass (char const* name)
1610   {
1611     return WSPtrClass <T> (name, this)
1612       .addNullCheck();
1613   }
1614
1615   //----------------------------------------------------------------------------
1616
1617   template <class K, class V>
1618   Class<std::map<K, V> > beginStdMap (char const* name)
1619   {
1620     typedef std::map<K, V> LT;
1621     typedef std::pair<const K, V> T;
1622
1623     return beginClass<LT> (name)
1624       .addVoidConstructor ()
1625       .addFunction ("empty", &LT::empty)
1626       .addFunction ("size", &LT::size)
1627       .addFunction ("clear", (void (LT::*)())&LT::clear)
1628       .addFunction ("count", (void (LT::*)())&LT::count)
1629       .addExtCFunction ("add", &CFunc::tableToMap<K, V>)
1630       .addExtCFunction ("iter", &CFunc::mapIter<K, V>)
1631       .addExtCFunction ("table", &CFunc::mapToTable<K, V>);
1632   }
1633
1634   template <class T>
1635   Class<std::set<T> > beginStdSet (char const* name)
1636   {
1637     typedef std::set<T> LT;
1638     return beginClass<LT> (name)
1639       .addVoidConstructor ()
1640       .addFunction ("clear", (void (LT::*)())&LT::clear)
1641       .addFunction ("empty", &LT::empty)
1642       .addFunction ("size", &LT::size)
1643       .addExtCFunction ("add", &CFunc::tableToSet<T>)
1644       .addExtCFunction ("iter", &CFunc::setIter<T>)
1645       .addExtCFunction ("table", &CFunc::setToTable<T>);
1646   }
1647
1648   template <unsigned int T>
1649   Class<std::bitset<T> > beginStdBitSet (char const* name)
1650   {
1651     typedef std::bitset<T> BS;
1652     return beginClass<BS> (name)
1653       .addVoidConstructor ()
1654       .addFunction ("reset", (BS& (BS::*)())&BS::reset)
1655       .addFunction ("set", (BS& (BS::*)(size_t, bool))&BS::set)
1656       .addFunction ("count", &BS::count)
1657       .addFunction ("any", &BS::any)
1658       .addFunction ("none", &BS::none)
1659       .addFunction ("test", &BS::test)
1660       .addFunction ("size", &BS::size)
1661       .addExtCFunction ("add", &CFunc::tableToBitSet<T>)
1662       .addExtCFunction ("table", &CFunc::bitSetToTable<T>);
1663   }
1664
1665   template <class T>
1666   Class<std::list<T> > beginConstStdList (char const* name)
1667   {
1668     typedef std::list<T> LT;
1669     return beginClass<LT> (name)
1670       .addVoidConstructor ()
1671       .addFunction ("empty", &LT::empty)
1672       .addFunction ("size", &LT::size)
1673       .addFunction ("reverse", &LT::reverse)
1674       .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1675       .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1676   }
1677
1678   template <class T>
1679   Class<std::list<T> > beginStdList (char const* name)
1680   {
1681     typedef std::list<T> LT;
1682     return beginConstStdList<T> (name)
1683       .addFunction ("unique", (void (LT::*)())&LT::unique)
1684       .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1685       .addExtCFunction ("add", &CFunc::tableToList<T, LT>);
1686   }
1687
1688   template <class T>
1689   Class<std::vector<T> > beginStdVector (char const* name)
1690   {
1691     typedef std::vector<T> LT;
1692     typedef typename std::vector<T>::reference T_REF;
1693     typedef typename std::vector<T>::size_type T_SIZE;
1694
1695     return beginClass<LT> (name)
1696       .addVoidConstructor ()
1697       .addFunction ("empty", &LT::empty)
1698       .addFunction ("size", &LT::size)
1699       .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1700       .addFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
1701       .addExtCFunction ("add", &CFunc::tableToList<T, LT>)
1702       .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1703       .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1704   }
1705
1706   //----------------------------------------------------------------------------
1707
1708   template <class T>
1709   Class<boost::shared_ptr<std::list<T> > > beginPtrStdList (char const* name)
1710   {
1711     typedef std::list<T> LT;
1712
1713     return beginClass<boost::shared_ptr<LT> > (name)
1714       .addVoidConstructor ()
1715       .addPtrFunction ("empty", &LT::empty)
1716       .addPtrFunction ("size", &LT::size)
1717       .addPtrFunction ("reverse", &LT::reverse)
1718       .addPtrFunction ("unique", (void (LT::*)())&LT::unique)
1719       .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1720       .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
1721       .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
1722       .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
1723   }
1724
1725   template <class T>
1726   Class<boost::shared_ptr<std::vector<T> > > beginPtrStdVector (char const* name)
1727   {
1728     typedef std::vector<T> LT;
1729     typedef typename std::vector<T>::reference T_REF;
1730     typedef typename std::vector<T>::size_type T_SIZE;
1731
1732     return beginClass<boost::shared_ptr<LT> > (name)
1733       .addVoidConstructor ()
1734       .addPtrFunction ("empty", &LT::empty)
1735       .addPtrFunction ("empty", &LT::empty)
1736       .addPtrFunction ("size", &LT::size)
1737       .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
1738       .addPtrFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
1739       .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
1740       .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
1741       .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
1742   }
1743
1744   //----------------------------------------------------------------------------
1745   /**
1746       Derive a new class for registrations.
1747
1748       To continue registrations for the class later, use beginClass().
1749       Do not call deriveClass() again.
1750   */
1751   template <class T, class U>
1752   Class <T> deriveClass (char const* name)
1753   {
1754     CLASSDOC ("[C] Derived Class", _name << name, type_name <T>(), type_name <U>())
1755     return Class <T> (name, this, ClassInfo <U>::getStaticKey ());
1756   }
1757
1758   template <class T, class U>
1759   WSPtrClass <T> deriveWSPtrClass (char const* name)
1760   {
1761
1762     CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::shared_ptr<T> >(), type_name <boost::shared_ptr<U> >())
1763     CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::weak_ptr<T> >(), type_name <boost::weak_ptr<U> >())
1764     CLASSDOC ("[C] Derived Pointer Class", _name << name, type_name <T>(), type_name <U>())
1765     return WSPtrClass <T> (name, this,
1766         ClassInfo <boost::shared_ptr<U> >::getStaticKey (),
1767         ClassInfo <boost::weak_ptr<U> >::getStaticKey ())
1768       .addNullCheck();
1769   }
1770
1771 };
1772
1773 //------------------------------------------------------------------------------
1774 /**
1775     Retrieve the global namespace.
1776
1777     It is recommended to put your namespace inside the global namespace, and
1778     then add your classes and functions to it, rather than adding many classes
1779     and functions directly to the global namespace.
1780 */
1781 inline Namespace getGlobalNamespace (lua_State* L)
1782 {
1783   return Namespace::getGlobalNamespace (L);
1784 }
1785
1786
1787 #undef KEYSTA
1788 #undef KEYEND
1789 #undef CLASSDOC
1790 #undef PRINTDOC
1791 #undef FUNDOC
1792 #undef DATADOC
1793
1794 /* vim: set et sw=2: */