29b361b69085730662e04c708966c40ae9e16136
[ardour.git] / libs / lua / LuaBridge / detail / CFunctions.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
8   License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
9
10   Permission is hereby granted, free of charge, to any person obtaining a copy
11   of this software and associated documentation files (the "Software"), to deal
12   in the Software without restriction, including without limitation the rights
13   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14   copies of the Software, and to permit persons to whom the Software is
15   furnished to do so, subject to the following conditions:
16
17   The above copyright notice and this permission notice shall be included in all
18   copies or substantial portions of the Software.
19
20   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26   SOFTWARE.
27 */
28 //==============================================================================
29
30 // We use a structure so we can define everything in the header.
31 //
32 struct CFunc
33 {
34   //----------------------------------------------------------------------------
35   /**
36       __index metamethod for a namespace or class static members.
37
38       This handles:
39         Retrieving functions and class static methods, stored in the metatable.
40         Reading global and class static data, stored in the __propget table.
41         Reading global and class properties, stored in the __propget table.
42   */
43   static int indexMetaMethod (lua_State* L)
44   {
45     int result = 0;
46     lua_getmetatable (L, 1);                // push metatable of arg1
47     for (;;)
48     {
49       lua_pushvalue (L, 2);                 // push key arg2
50       lua_rawget (L, -2);                   // lookup key in metatable
51       if (lua_isnil (L, -1))                // not found
52       {
53         lua_pop (L, 1);                     // discard nil
54         rawgetfield (L, -1, "__propget");   // lookup __propget in metatable
55         lua_pushvalue (L, 2);               // push key arg2
56         lua_rawget (L, -2);                 // lookup key in __propget
57         lua_remove (L, -2);                 // discard __propget
58         if (lua_iscfunction (L, -1))
59         {
60           lua_remove (L, -2);               // discard metatable
61           lua_pushvalue (L, 1);             // push arg1
62           lua_call (L, 1, 1);               // call cfunction
63           result = 1;
64           break;
65         }
66         else
67         {
68           assert (lua_isnil (L, -1));
69           lua_pop (L, 1);                   // discard nil and fall through
70         }
71       }
72       else
73       {
74         assert (lua_istable (L, -1) || lua_iscfunction (L, -1));
75         lua_remove (L, -2);
76         result = 1;
77         break;
78       }
79
80       rawgetfield (L, -1, "__parent");
81       if (lua_istable (L, -1))
82       {
83         // Remove metatable and repeat the search in __parent.
84         lua_remove (L, -2);
85       }
86       else
87       {
88         // Discard metatable and return nil.
89         assert (lua_isnil (L, -1));
90         lua_remove (L, -2);
91         result = 1;
92         break;
93       }
94     }
95
96     return result;
97   }
98
99   //----------------------------------------------------------------------------
100   /**
101       __newindex metamethod for a namespace or class static members.
102
103       The __propset table stores proxy functions for assignment to:
104         Global and class static data.
105         Global and class properties.
106   */
107   static int newindexMetaMethod (lua_State* L)
108   {
109     int result = 0;
110     lua_getmetatable (L, 1);                // push metatable of arg1
111     for (;;)
112     {
113       rawgetfield (L, -1, "__propset");     // lookup __propset in metatable
114       assert (lua_istable (L, -1));
115       lua_pushvalue (L, 2);                 // push key arg2
116       lua_rawget (L, -2);                   // lookup key in __propset
117       lua_remove (L, -2);                   // discard __propset
118       if (lua_iscfunction (L, -1))          // ensure value is a cfunction
119       {
120         lua_remove (L, -2);                 // discard metatable
121         lua_pushvalue (L, 3);               // push new value arg3
122         lua_call (L, 1, 0);                 // call cfunction
123         result = 0;
124         break;
125       }
126       else
127       {
128         assert (lua_isnil (L, -1));
129         lua_pop (L, 1);
130       }
131
132       rawgetfield (L, -1, "__parent");
133       if (lua_istable (L, -1))
134       {
135         // Remove metatable and repeat the search in __parent.
136         lua_remove (L, -2);
137       }
138       else
139       {
140         assert (lua_isnil (L, -1));
141         lua_pop (L, 2);
142         result = luaL_error (L,"no writable variable '%s'", lua_tostring (L, 2));
143       }
144     }
145
146     return result;
147   }
148
149   //----------------------------------------------------------------------------
150   /**
151       lua_CFunction to report an error writing to a read-only value.
152
153       The name of the variable is in the first upvalue.
154   */
155   static int readOnlyError (lua_State* L)
156   {
157     std::string s;
158
159     s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only";
160
161     return luaL_error (L, s.c_str ());
162   }
163
164   //----------------------------------------------------------------------------
165   /**
166       lua_CFunction to get a variable.
167
168       This is used for global variables or class static data members.
169
170       The pointer to the data is in the first upvalue.
171   */
172   template <class T>
173   static int getVariable (lua_State* L)
174   {
175     assert (lua_islightuserdata (L, lua_upvalueindex (1)));
176     T const* ptr = static_cast <T const*> (lua_touserdata (L, lua_upvalueindex (1)));
177     assert (ptr != 0);
178     Stack <T>::push (L, *ptr);
179     return 1;
180   }
181
182   //----------------------------------------------------------------------------
183   /**
184       lua_CFunction to set a variable.
185
186       This is used for global variables or class static data members.
187
188       The pointer to the data is in the first upvalue.
189   */
190   template <class T>
191   static int setVariable (lua_State* L)
192   {
193     assert (lua_islightuserdata (L, lua_upvalueindex (1)));
194     T* ptr = static_cast <T*> (lua_touserdata (L, lua_upvalueindex (1)));
195     assert (ptr != 0);
196     *ptr = Stack <T>::get (L, 1);
197     return 0;
198   }
199
200   //----------------------------------------------------------------------------
201   /**
202       lua_CFunction to call a function with a return value.
203
204       This is used for global functions, global properties, class static methods,
205       and class static properties.
206
207       The function pointer is in the first upvalue.
208   */
209   template <class FnPtr,
210             class ReturnType = typename FuncTraits <FnPtr>::ReturnType>
211   struct Call
212   {
213     typedef typename FuncTraits <FnPtr>::Params Params;
214     static int f (lua_State* L)
215     {
216       assert (isfulluserdata (L, lua_upvalueindex (1)));
217       FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
218       assert (fnptr != 0);
219       ArgList <Params> args (L);
220       Stack <typename FuncTraits <FnPtr>::ReturnType>::push (L, FuncTraits <FnPtr>::call (fnptr, args));
221       return 1;
222     }
223   };
224
225   //----------------------------------------------------------------------------
226   /**
227       lua_CFunction to call a function with no return value.
228
229       This is used for global functions, global properties, class static methods,
230       and class static properties.
231
232       The function pointer is in the first upvalue.
233   */
234   template <class FnPtr>
235   struct Call <FnPtr, void>
236   {
237     typedef typename FuncTraits <FnPtr>::Params Params;
238     static int f (lua_State* L)
239     {
240       assert (isfulluserdata (L, lua_upvalueindex (1)));
241       FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
242       assert (fnptr != 0);
243       ArgList <Params> args (L);
244       FuncTraits <FnPtr>::call (fnptr, args);
245       return 0;
246     }
247   };
248
249   //----------------------------------------------------------------------------
250   /**
251       lua_CFunction to call a function with references as arguments.
252   */
253   template <class FnPtr,
254             class ReturnType = typename FuncTraits <FnPtr>::ReturnType>
255   struct CallRef
256   {
257     typedef typename FuncTraits <FnPtr>::Params Params;
258     static int f (lua_State* L)
259     {
260       assert (isfulluserdata (L, lua_upvalueindex (1)));
261       FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
262       assert (fnptr != 0);
263       ArgList <Params, 1> args (L);
264       Stack <typename FuncTraits <FnPtr>::ReturnType>::push (L, FuncTraits <FnPtr>::call (fnptr, args));
265       LuaRef v (newTable (L));
266       FuncArgs <Params, 0>::refs (v, args);
267       v.push(L);
268       return 2;
269     }
270   };
271
272   template <class FnPtr>
273   struct CallRef <FnPtr, void>
274   {
275     typedef typename FuncTraits <FnPtr>::Params Params;
276     static int f (lua_State* L)
277     {
278       assert (isfulluserdata (L, lua_upvalueindex (1)));
279       FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
280       assert (fnptr != 0);
281       ArgList <Params, 1> args (L);
282       FuncTraits <FnPtr>::call (fnptr, args);
283       LuaRef v (newTable (L));
284       FuncArgs <Params, 0>::refs (v, args);
285       v.push(L);
286       return 1;
287     }
288   };
289
290
291   //----------------------------------------------------------------------------
292   /**
293       lua_CFunction to call a class member function with a return value.
294
295       The member function pointer is in the first upvalue.
296       The class userdata object is at the top of the Lua stack.
297   */
298   template <class MemFnPtr,
299             class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
300   struct CallMember
301   {
302     typedef typename FuncTraits <MemFnPtr>::ClassType T;
303     typedef typename FuncTraits <MemFnPtr>::Params Params;
304
305     static int f (lua_State* L)
306     {
307       assert (isfulluserdata (L, lua_upvalueindex (1)));
308       T* const t = Userdata::get <T> (L, 1, false);
309       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
310       assert (fnptr != 0);
311       ArgList <Params, 2> args (L);
312       Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
313       return 1;
314     }
315   };
316
317   template <class MemFnPtr,
318             class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
319   struct CallConstMember
320   {
321     typedef typename FuncTraits <MemFnPtr>::ClassType T;
322     typedef typename FuncTraits <MemFnPtr>::Params Params;
323
324     static int f (lua_State* L)
325     {
326       assert (isfulluserdata (L, lua_upvalueindex (1)));
327       T const* const t = Userdata::get <T> (L, 1, true);
328       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
329       assert (fnptr != 0);
330       ArgList <Params, 2> args(L);
331       Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
332       return 1;
333     }
334   };
335
336   template <class MemFnPtr, class T,
337            class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
338   struct CallMemberPtr
339   {
340     typedef typename FuncTraits <MemFnPtr>::Params Params;
341
342     static int f (lua_State* L)
343     {
344       assert (isfulluserdata (L, lua_upvalueindex (1)));
345       boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
346       T* const tt = t->get();
347       if (!tt) {
348         return luaL_error (L, "shared_ptr is nil");
349       }
350       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
351       assert (fnptr != 0);
352       ArgList <Params, 2> args (L);
353       Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
354       return 1;
355     }
356   };
357
358   template <class T, class R>
359   struct CastMemberPtr
360   {
361     static int f (lua_State* L)
362     {
363       boost::shared_ptr<T> t = luabridge::Stack<boost::shared_ptr<T> >::get (L, 1);
364       Stack <boost::shared_ptr<R> >::push (L, boost::dynamic_pointer_cast<R> (t));
365       return 1;
366     }
367   };
368
369   template <class T>
370   struct PtrNullCheck
371   {
372     static int f (lua_State* L)
373     {
374       boost::shared_ptr<T> t = luabridge::Stack<boost::shared_ptr<T> >::get (L, 1);
375       Stack <bool>::push (L, t == 0);
376       return 1;
377     }
378   };
379
380   template <class T>
381   struct WPtrNullCheck
382   {
383     static int f (lua_State* L)
384     {
385       bool rv = true;
386       boost::weak_ptr<T> tw = luabridge::Stack<boost::weak_ptr<T> >::get (L, 1);
387       boost::shared_ptr<T> const t = tw.lock();
388       if (t) {
389         T* const tt = t.get();
390         rv = (tt == 0);
391       }
392       Stack <bool>::push (L, rv);
393       return 1;
394     }
395   };
396
397   template <class MemFnPtr, class T,
398            class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
399   struct CallMemberWPtr
400   {
401     typedef typename FuncTraits <MemFnPtr>::Params Params;
402
403     static int f (lua_State* L)
404     {
405       assert (isfulluserdata (L, lua_upvalueindex (1)));
406       boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
407       boost::shared_ptr<T> const t = tw->lock();
408       if (!t) {
409         return luaL_error (L, "cannot lock weak_ptr");
410       }
411       T* const tt = t.get();
412       if (!tt) {
413         return luaL_error (L, "weak_ptr is nil");
414       }
415       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
416       assert (fnptr != 0);
417       ArgList <Params, 2> args (L);
418       Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
419       return 1;
420     }
421   };
422
423   /**
424       lua_CFunction to calls for function references.
425   */
426   template <class MemFnPtr,
427             class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
428   struct CallMemberRef
429   {
430     typedef typename FuncTraits <MemFnPtr>::ClassType T;
431     typedef typename FuncTraits <MemFnPtr>::Params Params;
432
433     static int f (lua_State* L)
434     {
435       assert (isfulluserdata (L, lua_upvalueindex (1)));
436       T* const t = Userdata::get <T> (L, 1, false);
437       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
438       assert (fnptr != 0);
439       ArgList <Params, 2> args (L);
440       Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
441       LuaRef v (newTable (L));
442       FuncArgs <Params, 0>::refs (v, args);
443       v.push(L);
444       return 2;
445     }
446   };
447
448   template <class MemFnPtr,
449             class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
450   struct CallConstMemberRef
451   {
452     typedef typename FuncTraits <MemFnPtr>::ClassType T;
453     typedef typename FuncTraits <MemFnPtr>::Params Params;
454
455     static int f (lua_State* L)
456     {
457       assert (isfulluserdata (L, lua_upvalueindex (1)));
458       T const* const t = Userdata::get <T> (L, 1, true);
459       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
460       assert (fnptr != 0);
461       ArgList <Params, 2> args(L);
462       Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
463       LuaRef v (newTable (L));
464       FuncArgs <Params, 0>::refs (v, args);
465       v.push(L);
466       return 2;
467     }
468   };
469
470   template <class MemFnPtr, class T,
471             class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
472   struct CallMemberRefPtr
473   {
474     typedef typename FuncTraits <MemFnPtr>::Params Params;
475
476     static int f (lua_State* L)
477     {
478       assert (isfulluserdata (L, lua_upvalueindex (1)));
479       boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
480       T* const tt = t->get();
481       if (!tt) {
482         return luaL_error (L, "shared_ptr is nil");
483       }
484       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
485       assert (fnptr != 0);
486       ArgList <Params, 2> args (L);
487       Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
488       LuaRef v (newTable (L));
489       FuncArgs <Params, 0>::refs (v, args);
490       v.push(L);
491       return 2;
492     }
493   };
494
495   template <class MemFnPtr, class T,
496             class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
497   struct CallMemberRefWPtr
498   {
499     typedef typename FuncTraits <MemFnPtr>::Params Params;
500
501     static int f (lua_State* L)
502     {
503       assert (isfulluserdata (L, lua_upvalueindex (1)));
504       boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
505       boost::shared_ptr<T> const t = tw->lock();
506       if (!t) {
507         return luaL_error (L, "cannot lock weak_ptr");
508       }
509       T* const tt = t.get();
510       if (!tt) {
511         return luaL_error (L, "weak_ptr is nil");
512       }
513       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
514       assert (fnptr != 0);
515       ArgList <Params, 2> args (L);
516       Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
517       LuaRef v (newTable (L));
518       FuncArgs <Params, 0>::refs (v, args);
519       v.push(L);
520       return 2;
521     }
522   };
523
524   //----------------------------------------------------------------------------
525   /**
526       lua_CFunction to call a class member function with no return value.
527
528       The member function pointer is in the first upvalue.
529       The class userdata object is at the top of the Lua stack.
530   */
531   template <class MemFnPtr>
532   struct CallMember <MemFnPtr, void>
533   {
534     typedef typename FuncTraits <MemFnPtr>::ClassType T;
535     typedef typename FuncTraits <MemFnPtr>::Params Params;
536
537     static int f (lua_State* L)
538     {
539       assert (isfulluserdata (L, lua_upvalueindex (1)));
540       T* const t = Userdata::get <T> (L, 1, false);
541       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
542       assert (fnptr != 0);
543       ArgList <Params, 2> args (L);
544       FuncTraits <MemFnPtr>::call (t, fnptr, args);
545       return 0;
546     }
547   };
548
549   template <class MemFnPtr>
550   struct CallConstMember <MemFnPtr, void>
551   {
552     typedef typename FuncTraits <MemFnPtr>::ClassType T;
553     typedef typename FuncTraits <MemFnPtr>::Params Params;
554
555     static int f (lua_State* L)
556     {
557       assert (isfulluserdata (L, lua_upvalueindex (1)));
558       T const* const t = Userdata::get <T> (L, 1, true);
559       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
560       assert (fnptr != 0);
561       ArgList <Params, 2> args (L);
562       FuncTraits <MemFnPtr>::call (t, fnptr, args);
563       return 0;
564     }
565   };
566
567   template <class MemFnPtr, class T>
568   struct CallMemberPtr <MemFnPtr, T, void>
569   {
570     typedef typename FuncTraits <MemFnPtr>::Params Params;
571
572     static int f (lua_State* L)
573     {
574       assert (isfulluserdata (L, lua_upvalueindex (1)));
575       boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
576       T* const tt = t->get();
577       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
578       assert (fnptr != 0);
579       ArgList <Params, 2> args (L);
580       FuncTraits <MemFnPtr>::call (tt, fnptr, args);
581       return 0;
582     }
583   };
584
585   template <class MemFnPtr, class T>
586   struct CallMemberWPtr <MemFnPtr, T, void>
587   {
588     typedef typename FuncTraits <MemFnPtr>::Params Params;
589
590     static int f (lua_State* L)
591     {
592       assert (isfulluserdata (L, lua_upvalueindex (1)));
593       boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
594       boost::shared_ptr<T> const t = tw->lock();
595       if (!t) {
596         return luaL_error (L, "cannot lock weak_ptr");
597       }
598       T* const tt = t.get();
599       if (!tt) {
600         return luaL_error (L, "weak_ptr is nil");
601       }
602       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
603       assert (fnptr != 0);
604       ArgList <Params, 2> args (L);
605       FuncTraits <MemFnPtr>::call (tt, fnptr, args);
606       return 0;
607     }
608   };
609
610   template <class MemFnPtr>
611   struct CallMemberRef <MemFnPtr, void>
612   {
613     typedef typename FuncTraits <MemFnPtr>::ClassType T;
614     typedef typename FuncTraits <MemFnPtr>::Params Params;
615
616     static int f (lua_State* L)
617     {
618       assert (isfulluserdata (L, lua_upvalueindex (1)));
619       T* const t = Userdata::get <T> (L, 1, false);
620       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
621       assert (fnptr != 0);
622       ArgList <Params, 2> args (L);
623       FuncTraits <MemFnPtr>::call (t, fnptr, args);
624       LuaRef v (newTable (L));
625       FuncArgs <Params, 0>::refs (v, args);
626       v.push(L);
627       return 1;
628     }
629   };
630
631   template <class MemFnPtr>
632   struct CallConstMemberRef <MemFnPtr, void>
633   {
634     typedef typename FuncTraits <MemFnPtr>::ClassType T;
635     typedef typename FuncTraits <MemFnPtr>::Params Params;
636
637     static int f (lua_State* L)
638     {
639       assert (isfulluserdata (L, lua_upvalueindex (1)));
640       T const* const t = Userdata::get <T> (L, 1, true);
641       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
642       assert (fnptr != 0);
643       ArgList <Params, 2> args (L);
644       FuncTraits <MemFnPtr>::call (t, fnptr, args);
645       LuaRef v (newTable (L));
646       FuncArgs <Params, 0>::refs (v, args);
647       v.push(L);
648       return 1;
649     }
650   };
651
652   template <class MemFnPtr, class T>
653   struct CallMemberRefPtr <MemFnPtr, T, void>
654   {
655     typedef typename FuncTraits <MemFnPtr>::Params Params;
656
657     static int f (lua_State* L)
658     {
659       assert (isfulluserdata (L, lua_upvalueindex (1)));
660       boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
661       T* const tt = t->get();
662       if (!tt) {
663         return luaL_error (L, "shared_ptr is nil");
664       }
665       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
666       assert (fnptr != 0);
667       ArgList <Params, 2> args (L);
668       FuncTraits <MemFnPtr>::call (tt, fnptr, args);
669       LuaRef v (newTable (L));
670       FuncArgs <Params, 0>::refs (v, args);
671       v.push(L);
672       return 1;
673     }
674   };
675
676   template <class MemFnPtr, class T>
677   struct CallMemberRefWPtr <MemFnPtr, T, void>
678   {
679     typedef typename FuncTraits <MemFnPtr>::Params Params;
680
681     static int f (lua_State* L)
682     {
683       assert (isfulluserdata (L, lua_upvalueindex (1)));
684       boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
685       boost::shared_ptr<T> const t = tw->lock();
686       if (!t) {
687         return luaL_error (L, "cannot lock weak_ptr");
688       }
689       T* const tt = t.get();
690       if (!tt) {
691         return luaL_error (L, "weak_ptr is nil");
692       }
693       MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
694       assert (fnptr != 0);
695       ArgList <Params, 2> args (L);
696       FuncTraits <MemFnPtr>::call (tt, fnptr, args);
697       LuaRef v (newTable (L));
698       FuncArgs <Params, 0>::refs (v, args);
699       v.push(L);
700       return 1;
701     }
702   };
703
704   //--------------------------------------------------------------------------
705   /**
706       lua_CFunction to call a class member lua_CFunction.
707
708       The member function pointer is in the first upvalue.
709       The class userdata object is at the top of the Lua stack.
710   */
711   template <class T>
712   struct CallMemberCFunction
713   {
714     static int f (lua_State* L)
715     {
716       assert (isfulluserdata (L, lua_upvalueindex (1)));
717       typedef int (T::*MFP)(lua_State* L);
718       T* const t = Userdata::get <T> (L, 1, false);
719       MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
720       assert (fnptr != 0);
721       return (t->*fnptr) (L);
722     }
723   };
724
725   template <class T>
726   struct CallConstMemberCFunction
727   {
728     static int f (lua_State* L)
729     {
730       assert (isfulluserdata (L, lua_upvalueindex (1)));
731       typedef int (T::*MFP)(lua_State* L);
732       T const* const t = Userdata::get <T> (L, 1, true);
733       MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
734       assert (fnptr != 0);
735       return (t->*fnptr) (L);
736     }
737   };
738
739   //--------------------------------------------------------------------------
740
741   // SFINAE Helpers
742
743   template <class MemFnPtr, bool isConst>
744   struct CallMemberFunctionHelper
745   {
746     static void add (lua_State* L, char const* name, MemFnPtr mf)
747     {
748       new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
749       lua_pushcclosure (L, &CallConstMember <MemFnPtr>::f, 1);
750       lua_pushvalue (L, -1);
751       rawsetfield (L, -5, name); // const table
752       rawsetfield (L, -3, name); // class table
753     }
754   };
755
756   template <class MemFnPtr>
757   struct CallMemberFunctionHelper <MemFnPtr, false>
758   {
759     static void add (lua_State* L, char const* name, MemFnPtr mf)
760     {
761       new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
762       lua_pushcclosure (L, &CallMember <MemFnPtr>::f, 1);
763       rawsetfield (L, -3, name); // class table
764     }
765   };
766
767   template <class MemFnPtr>
768   struct CallMemberPtrFunctionHelper
769   {
770     typedef typename FuncTraits <MemFnPtr>::ClassType T;
771     static void add (lua_State* L, char const* name, MemFnPtr mf)
772     {
773       new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
774       lua_pushcclosure (L, &CallMemberPtr <MemFnPtr, T>::f, 1);
775       rawsetfield (L, -3, name); // class table
776     }
777   };
778
779   template <class MemFnPtr>
780   struct CallMemberRefPtrFunctionHelper
781   {
782     typedef typename FuncTraits <MemFnPtr>::ClassType T;
783     static void add (lua_State* L, char const* name, MemFnPtr mf)
784     {
785       new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
786       lua_pushcclosure (L, &CallMemberRefPtr <MemFnPtr, T>::f, 1);
787       rawsetfield (L, -3, name); // class table
788     }
789   };
790
791   template <class MemFnPtr>
792   struct CallMemberWPtrFunctionHelper
793   {
794     typedef typename FuncTraits <MemFnPtr>::ClassType T;
795     static void add (lua_State* L, char const* name, MemFnPtr mf)
796     {
797       new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
798       lua_pushcclosure (L, &CallMemberWPtr <MemFnPtr, T>::f, 1);
799       rawsetfield (L, -3, name); // class table
800     }
801   };
802
803   template <class MemFnPtr>
804   struct CallMemberRefWPtrFunctionHelper
805   {
806     typedef typename FuncTraits <MemFnPtr>::ClassType T;
807     static void add (lua_State* L, char const* name, MemFnPtr mf)
808     {
809       new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
810       lua_pushcclosure (L, &CallMemberRefWPtr <MemFnPtr, T>::f, 1);
811       rawsetfield (L, -3, name); // class table
812     }
813   };
814
815   template <class MemFnPtr, bool isConst>
816   struct CallMemberRefFunctionHelper
817   {
818     static void add (lua_State* L, char const* name, MemFnPtr mf)
819     {
820       new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
821       lua_pushcclosure (L, &CallConstMemberRef <MemFnPtr>::f, 1);
822       lua_pushvalue (L, -1);
823       rawsetfield (L, -5, name); // const table
824       rawsetfield (L, -3, name); // class table
825     }
826   };
827
828   template <class MemFnPtr>
829   struct CallMemberRefFunctionHelper <MemFnPtr, false>
830   {
831     static void add (lua_State* L, char const* name, MemFnPtr mf)
832     {
833       new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
834       lua_pushcclosure (L, &CallMemberRef <MemFnPtr>::f, 1);
835       rawsetfield (L, -3, name); // class table
836     }
837   };
838
839   //--------------------------------------------------------------------------
840   /**
841       __gc metamethod for a class.
842   */
843   template <class C>
844   static int gcMetaMethod (lua_State* L)
845   {
846     Userdata* const ud = Userdata::getExact <C> (L, 1);
847     ud->~Userdata ();
848     return 0;
849   }
850
851   static int gcNOOPMethod (lua_State* L)
852   {
853     return 0;
854   }
855
856   //--------------------------------------------------------------------------
857   /**
858       lua_CFunction to get a class data member.
859
860       The pointer-to-member is in the first upvalue.
861       The class userdata object is at the top of the Lua stack.
862   */
863   template <class C, typename T>
864   static int getProperty (lua_State* L)
865   {
866     C const* const c = Userdata::get <C> (L, 1, true);
867     T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
868     Stack <T>::push (L, c->**mp);
869     return 1;
870   }
871
872   //--------------------------------------------------------------------------
873
874   /**
875       lua_CFunction to get a constant (enum)
876   */
877   template <typename U>
878   static int getConst (lua_State* L)
879   {
880     U *v = static_cast <U *> (lua_touserdata (L, lua_upvalueindex (1)));
881     assert (v);
882     Stack <U>::push (L, *v);
883     return 1;
884   }
885
886   //--------------------------------------------------------------------------
887   /**
888       lua_CFunction to set a class data member.
889
890       The pointer-to-member is in the first upvalue.
891       The class userdata object is at the top of the Lua stack.
892   */
893   template <class C, typename T>
894   static int setProperty (lua_State* L)
895   {
896     C* const c = Userdata::get <C> (L, 1, false);
897     T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
898     c->**mp = Stack <T>::get (L, 2);
899     return 0;
900   }
901
902   //--------------------------------------------------------------------------
903
904   // metatable callback for "array[index]"
905   template <typename T>
906   static int array_index (lua_State* L) {
907     T** parray = (T**) luaL_checkudata (L, 1, typeid(T).name());
908     int const index = luabridge::Stack<int>::get (L, 2);
909     luabridge::Stack<T>::push (L, (*parray)[index-1]);
910     return 1;
911   }
912
913   // metatable callback for "array[index] = value"
914   template <typename T>
915   static int array_newindex (lua_State* L) {
916     T** parray = (T**) luaL_checkudata (L, 1, typeid(T).name());
917     int const index = luabridge::Stack<int>::get (L, 2);
918     T const value = luabridge::Stack<T>::get (L, 3);
919     (*parray)[index-1] = value;
920     return 0;
921   }
922
923   template <typename T>
924   static int getArray (lua_State* L) {
925     T *v = luabridge::Stack<T*>::get (L, 1);
926     T** parray = (T**) lua_newuserdata(L, sizeof(T**));
927     *parray = v;
928     luaL_getmetatable(L, typeid(T).name());
929     lua_setmetatable(L, -2);
930     return 1;
931   }
932
933   // copy complete c array to lua table
934   template <typename T>
935   static int getTable (lua_State* L) {
936     T *v = luabridge::Stack<T*>::get (L, 1);
937     const int cnt = luabridge::Stack<int>::get (L, 2);
938     LuaRef t (L);
939     t = newTable (L);
940     for (int i = 0; i < cnt; ++i) {
941       t[i + 1] = v[i];
942     }
943     t.push(L);
944     return 1;
945   }
946
947   // copy lua table to c array
948   template <typename T>
949   static int setTable (lua_State* L) {
950     T *v = luabridge::Stack<T*>::get (L, 1);
951     LuaRef t (LuaRef::fromStack(L, 2));
952     const int cnt = luabridge::Stack<int>::get (L, 3);
953     for (int i = 0; i < cnt; ++i) {
954       v[i] = t[i + 1];
955     }
956     return 0;
957   }
958
959
960   //--------------------------------------------------------------------------
961   /**
962     C++ STL iterators
963    */
964
965   // read lua table into C++ std::list
966   template <class T, class C>
967   static int tableToListHelper (lua_State *L, C * const t)
968   {
969     if (!t) { return luaL_error (L, "invalid pointer to std::list<>/std::vector"); }
970     if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
971     lua_pushvalue (L, -1);
972     lua_pushnil (L);
973     while (lua_next (L, -2)) {
974       lua_pushvalue (L, -2);
975       T const value = Stack<T>::get (L, -2);
976       t->push_back (value);
977       lua_pop (L, 2);
978     }
979     lua_pop (L, 1);
980     lua_pop (L, 2);
981     Stack<C>::push (L, *t);
982     return 1;
983   }
984
985   template <class T, class C>
986   static int tableToList (lua_State *L)
987   {
988     C * const t = Userdata::get<C> (L, 1, false);
989     return tableToListHelper<T, C> (L, t);
990   }
991
992   template <class T, class C>
993   static int ptrTableToList (lua_State *L)
994   {
995     boost::shared_ptr<C> const* const t = Userdata::get<boost::shared_ptr<C> > (L, 1, true);
996     if (!t) { return luaL_error (L, "cannot derefencee shared_ptr"); }
997     return tableToListHelper<T, C> (L, t->get());
998   }
999
1000   //--------------------------------------------------------------------------
1001   template <class T, class C>
1002   static int listIterIter (lua_State *L) {
1003     typedef typename C::const_iterator IterType;
1004     IterType * const end = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (2)));
1005     IterType * const iter = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (1)));
1006     assert (end);
1007     assert (iter);
1008     if ((*iter) == (*end)) {
1009       return 0;
1010     }
1011     Stack <T>::push (L, **iter);
1012     ++(*iter);
1013     return 1;
1014   }
1015
1016   // generate an iterator
1017   template <class T, class C>
1018   static int listIterHelper (lua_State *L, C * const t)
1019   {
1020     if (!t) { return luaL_error (L, "invalid pointer to std::list<>/std::vector"); }
1021     typedef typename C::const_iterator IterType;
1022     new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->begin());
1023     new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->end());
1024     lua_pushcclosure (L, listIterIter<T, C>, 2);
1025     return 1;
1026   }
1027
1028   template <class T, class C>
1029   static int listIter (lua_State *L)
1030   {
1031     C * const t = Userdata::get <C> (L, 1, false);
1032     return listIterHelper<T, C> (L, t);
1033   }
1034
1035   template <class T, class C>
1036   static int ptrListIter (lua_State *L)
1037   {
1038     boost::shared_ptr<C> const* const t = Userdata::get <boost::shared_ptr<C> >(L, 1, true);
1039     if (!t) { return luaL_error (L, "cannot derefencee shared_ptr"); }
1040     return listIterHelper<T, C> (L, t->get());
1041   }
1042
1043   //--------------------------------------------------------------------------
1044   // generate table from std::list
1045   template <class T, class C>
1046   static int listToTableHelper (lua_State *L, C const* const t)
1047   {
1048     if (!t) { return luaL_error (L, "invalid pointer to std::list<>/std::vector"); }
1049 #if 0 // direct lua api
1050     lua_createtable(L, t->size(), 0);
1051     int newTable = lua_gettop(L);
1052     int index = 1;
1053     for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter, ++index) {
1054       Stack<T>::push(L, (*iter));
1055       lua_rawseti (L, newTable, index);
1056     }
1057 #else // luabridge way
1058     LuaRef v (L);
1059     v = newTable (L);
1060     int index = 1;
1061     for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter, ++index) {
1062       v[index] = (*iter);
1063     }
1064     v.push(L);
1065 #endif
1066     return 1;
1067   }
1068
1069   template <class T, class C>
1070   static int listToTable (lua_State *L)
1071   {
1072     C const* const t = Userdata::get <C> (L, 1, true);
1073     return listToTableHelper<T, C> (L, t);
1074   }
1075
1076   template <class T, class C>
1077   static int ptrListToTable (lua_State *L)
1078   {
1079     boost::shared_ptr<C> const* const t = Userdata::get <boost::shared_ptr<C> > (L, 1, true);
1080     if (!t) { return luaL_error (L, "cannot derefencee shared_ptr"); }
1081     return listToTableHelper<T, C> (L, t->get());
1082   }
1083
1084   //--------------------------------------------------------------------------
1085   // generate std::map from table
1086
1087   template <class K, class V>
1088   static int tableToMap (lua_State *L)
1089   {
1090     typedef std::map<K, V> C;
1091     C * const t = Userdata::get <C> (L, 1, true);
1092     if (!t) { return luaL_error (L, "invalid pointer to std::map"); }
1093     if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
1094
1095     lua_pushvalue (L, -1);
1096     lua_pushnil (L);
1097     while (lua_next (L, -2)) {
1098       lua_pushvalue (L, -2);
1099       K const key = Stack<K>::get (L, -1);
1100       V const value = Stack<V>::get (L, -2);
1101       t->insert (std::pair<K,V> (key, value));
1102       //(*t)[key] = value;
1103       lua_pop (L, 2);
1104     }
1105     lua_pop (L, 1);
1106     lua_pop (L, 2);
1107     Stack<C>::push (L, *t);
1108     return 1;
1109   }
1110
1111   // iterate over a std::map
1112   template <class K, class V>
1113   static int mapIterIter (lua_State *L)
1114   {
1115     typedef std::map<K, V> C;
1116     typedef typename C::const_iterator IterType;
1117     IterType * const end = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (2)));
1118     IterType * const iter = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (1)));
1119     assert (end);
1120     assert (iter);
1121     if ((*iter) == (*end)) {
1122       return 0;
1123     }
1124     Stack <K>::push (L, (*iter)->first);
1125     Stack <V>::push (L, (*iter)->second);
1126     ++(*iter);
1127     return 2;
1128   }
1129
1130   // generate iterator
1131   template <class K, class V>
1132   static int mapIter (lua_State *L)
1133   {
1134     typedef std::map<K, V> C;
1135     C * const t = Userdata::get <C> (L, 1, false);
1136     if (!t) { return luaL_error (L, "invalid pointer to std::map"); }
1137     typedef typename C::const_iterator IterType;
1138     new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->begin());
1139     new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->end());
1140     lua_pushcclosure (L, mapIterIter<K, V>, 2);
1141     return 1;
1142   }
1143
1144   // generate table from std::map
1145   template <class K, class V>
1146   static int mapToTable (lua_State *L)
1147   {
1148     typedef std::map<K, V> C;
1149     C const* const t = Userdata::get <C> (L, 1, true);
1150     if (!t) { return luaL_error (L, "invalid pointer to std::map"); }
1151
1152     LuaRef v (L);
1153     v = newTable (L);
1154     for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter) {
1155       v[(*iter).first] = (*iter).second;
1156     }
1157     v.push(L);
1158     return 1;
1159   }
1160
1161   //--------------------------------------------------------------------------
1162   // generate std::set from table keys ( table[member] = true )
1163   // http://www.lua.org/pil/11.5.html
1164
1165   template <class T>
1166   static int tableToSet (lua_State *L)
1167   {
1168     typedef std::set<T> C;
1169     C * const t = Userdata::get <C> (L, 1, true);
1170     if (!t) { return luaL_error (L, "invalid pointer to std::set"); }
1171     if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
1172
1173     lua_pushvalue (L, -1);
1174     lua_pushnil (L);
1175     while (lua_next (L, -2)) {
1176       lua_pushvalue (L, -2);
1177       T const member = Stack<T>::get (L, -1);
1178       bool const v = Stack<bool>::get (L, -2);
1179       if (v) {
1180         t->insert (member);
1181       }
1182       lua_pop (L, 2);
1183     }
1184     lua_pop (L, 1);
1185     lua_pop (L, 2);
1186     Stack<C>::push (L, *t);
1187     return 1;
1188   }
1189
1190   // iterate over a std::set, explicit "true" value.
1191   // compare to http://www.lua.org/pil/11.5.html
1192   template <class T>
1193   static int setIterIter (lua_State *L)
1194   {
1195     typedef std::set<T> C;
1196     typedef typename C::const_iterator IterType;
1197     IterType * const end = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (2)));
1198     IterType * const iter = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (1)));
1199     assert (end);
1200     assert (iter);
1201     if ((*iter) == (*end)) {
1202       return 0;
1203     }
1204     Stack <T>::push (L, **iter);
1205     Stack <bool>::push (L, true);
1206     ++(*iter);
1207     return 2;
1208   }
1209
1210   // generate iterator
1211   template <class T>
1212   static int setIter (lua_State *L)
1213   {
1214     typedef std::set<T> C;
1215     C * const t = Userdata::get <C> (L, 1, false);
1216     if (!t) { return luaL_error (L, "invalid pointer to std::set"); }
1217     typedef typename C::const_iterator IterType;
1218     new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->begin());
1219     new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->end());
1220     lua_pushcclosure (L, setIterIter<T>, 2);
1221     return 1;
1222   }
1223
1224   // generate table from std::set
1225   template <class T>
1226   static int setToTable (lua_State *L)
1227   {
1228     typedef std::set<T> C;
1229     C const* const t = Userdata::get <C> (L, 1, true);
1230     if (!t) { return luaL_error (L, "invalid pointer to std::set"); }
1231
1232     LuaRef v (L);
1233     v = newTable (L);
1234     for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter) {
1235       v[(*iter)] = true;
1236     }
1237     v.push(L);
1238     return 1;
1239   }
1240
1241   //--------------------------------------------------------------------------
1242   // bitset { num = true }
1243   // compare to http://www.lua.org/pil/11.5.html
1244   template <unsigned int T>
1245   static int tableToBitSet (lua_State *L)
1246   {
1247     typedef std::bitset<T> C;
1248     C * const t = Userdata::get <C> (L, 1, true);
1249     if (!t) { return luaL_error (L, "invalid pointer to std::bitset"); }
1250     if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
1251
1252     lua_pushvalue (L, -1);
1253     lua_pushnil (L);
1254     while (lua_next (L, -2)) {
1255       lua_pushvalue (L, -2);
1256       unsigned int const member = Stack<unsigned int>::get (L, -1);
1257       bool const v = Stack<bool>::get (L, -2);
1258       if (member < T && v) {
1259         t->set (member);
1260       }
1261       lua_pop (L, 2);
1262     }
1263     lua_pop (L, 1);
1264     lua_pop (L, 2);
1265     Stack<C>::push (L, *t);
1266     return 1;
1267   }
1268
1269   // generate table from std::bitset
1270   template <unsigned int T>
1271   static int bitSetToTable (lua_State *L)
1272   {
1273     typedef std::bitset<T> C;
1274     C const* const t = Userdata::get <C> (L, 1, true);
1275     if (!t) { return luaL_error (L, "invalid pointer to std::bitset"); }
1276
1277     LuaRef v (L);
1278     v = newTable (L);
1279     for (unsigned int i = 0; i < T; ++i) {
1280       if (t->test (i)) {
1281         v[i] = true;
1282       }
1283     }
1284     v.push(L);
1285     return 1;
1286   }
1287
1288 };
1289
1290 /* vim: set et sw=2: */