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