2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
11 #ifndef LUAAPI__GENERICWRAPPER_H
12 #define LUAAPI__GENERICWRAPPER_H
24 namespace Loader
{ class Context
; }
28 #define WRAP_0(func, selftype, restype) \
29 static int func(lua_State* l) { \
30 selftype* self = retrieve(l, 1); \
31 CAT0(lua_push, restype)(l, self->func()); \
35 #define PROPERTY_RW(PROP, GET, SET, restype) \
36 static int get_##PROP(lua_State* l) { \
37 lua_push##restype(l, retrieve(l, 1, DontCheck)->GET()); \
41 static int set_##PROP(lua_State* l) { \
42 retrieve(l, 1, DontCheck)->SET( lua_to##restype(l, 2) ); \
46 #define PROPERTY_RW_TYPE(PROP, GET, SET, restype, TYPE) \
47 static int get_##PROP(lua_State* l) { \
48 lua_push##restype(l, retrieve(l, 1, DontCheck)->GET()); \
52 static int set_##PROP(lua_State* l) { \
53 retrieve(l, 1, DontCheck)->SET( TYPE(lua_to##restype(l, 2)) ); \
57 #define PROPERTY_RW_CLASS(PROP, GET, SET, CLASS) \
58 static int get_##PROP(lua_State* l) { \
59 Wrapper<CLASS>::allocate(l, new CLASS(retrieve(l, 1, DontCheck)->GET())); \
63 static int set_##PROP(lua_State* l) { \
64 retrieve(l, 1, DontCheck)->SET( *Wrapper<CLASS>::retrieve(l, 2, AssertOk) ); \
68 #define PROPERTY_RO(PROP, GET, restype) \
69 static int get_##PROP(lua_State* l) { \
70 lua_push##restype(l, retrieve(l, 1, DontCheck)->GET()); \
74 #define P_PROPERTY_RW(PROP, GET, SET, restype) \
75 static int get_##PROP(lua_State* l) { \
76 lua_push##restype(l, (*retrieve(l, 1, DontCheck))->GET()); \
80 static int set_##PROP(lua_State* l) { \
81 (*retrieve(l, 1, DontCheck))->SET( lua_to##restype(l, 2) ); \
85 #define P_PROPERTY_RW_TYPE(PROP, GET, SET, restype, TYPE) \
86 static int get_##PROP(lua_State* l) { \
87 lua_push##restype(l, (*retrieve(l, 1, DontCheck))->GET()); \
91 static int set_##PROP(lua_State* l) { \
92 (*retrieve(l, 1, DontCheck))->SET( TYPE(lua_to##restype(l, 2)) ); \
96 #define P_PROPERTY_RO_TYPE(PROP, GET, restype, TYPE) \
97 static int get_##PROP(lua_State* l) { \
98 lua_push##restype(l, (*retrieve(l, 1, DontCheck))->GET()); \
102 #define P_PROPERTY_RW_CLASS(PROP, GET, SET, CLASS) \
103 static int get_##PROP(lua_State* l) { \
104 Wrapper<CLASS>::allocate(l, new CLASS((*retrieve(l, 1, DontCheck))->GET())); \
108 static int set_##PROP(lua_State* l) { \
109 (*retrieve(l, 1, DontCheck))->SET( *Wrapper<CLASS>::retrieve(l, 2, AssertOk) ); \
113 #define P_PROPERTY_RO_CLASS(PROP, GET, CLASS) \
114 static int get_##PROP(lua_State* l) { \
115 Wrapper<CLASS>::allocate(l, new CLASS((*retrieve(l, 1, DontCheck))->GET())); \
119 #define P_PROPERTY_RW_P_CLASS(PROP, GET, SET, CLASS) \
120 static int get_##PROP(lua_State* l) { \
121 Wrapper<CLASS>::allocate(l, (*retrieve(l, 1, DontCheck))->GET()); \
125 static int set_##PROP(lua_State* l) { \
126 (*retrieve(l, 1, DontCheck))->SET( *Wrapper<CLASS>::retrieve(l, 2, AssertOk) ); \
130 #define P_PROPERTY_RO_P_CLASS(PROP, GET, CLASS) \
131 static int get_##PROP(lua_State* l) { \
132 Wrapper<CLASS>::allocate(l, (*retrieve(l, 1, DontCheck))->GET()); \
136 #define P_PROPERTY_RO(PROP, GET, restype) \
137 static int get_##PROP(lua_State* l) { \
138 lua_push##restype(l, (*retrieve(l, 1, DontCheck))->GET()); \
142 #define P_PROPERTY_RO_QSTRING(PROP, GET) \
143 static int get_##PROP(lua_State* l) { \
144 QString s = (*retrieve(l, 1, DontCheck))->GET(); \
145 lua_pushstring(l, s.toAscii().constData()); \
149 #define P_PROPERTY_RW_QSTRING(PROP, GET, SET) \
150 static int get_##PROP(lua_State* l) { \
151 QString s = (*retrieve(l, 1, DontCheck))->GET(); \
152 lua_pushstring(l, s.toAscii().constData()); \
156 static int set_##PROP(lua_State* l) { \
157 (*retrieve(l, 1, DontCheck))->SET( QString(lua_tostring(l, 2)) ); \
161 #define SET_PROPERTY_RW(LUA, PROP) \
162 set_property(LUA, #PROP, get_##PROP, set_##PROP);
164 #define SET_PROPERTY_RO(LUA, PROP) \
165 set_property(LUA, #PROP, get_##PROP, NULL);
168 #define LOADING_CONTEXT "kboard_loading_context"
169 #define CURRENT_DIRECTORY "kboard_script_curr_dir"
170 #define API_LOADER "kboard_api_loader"
179 StackCheck(lua_State
* l
, int expect
= 0) : l(l
) {
180 top
= lua_gettop(l
) + expect
;
184 if (lua_gettop(l
) != top
) {
185 std::cout
<< "Wrong stack size!\n\texpected = " << top
<<
186 "\n\tactual = " << lua_gettop(l
) << std::endl
;
200 template <typename T
>
204 //BEGIN GenericWrappeBase------------------------------------------------------
206 class GenericWrapperBase
{
208 static QString
file_path(lua_State
* l
, const QString
& f
);
210 static Loader::Context
* retrieve_context(lua_State
* l
);
213 * Add property f to the table at @a index.
215 static void set_property(lua_State
* l
, const char* name
, lua_CFunction get
,
216 lua_CFunction set
= NULL
, int index
= -1);
219 * Add method f to the table at @a index.
221 static void set_method(lua_State
* l
, lua_CFunction f
, const char* name
, int index
= -1);
224 * Add meta method f to the table at @a index.
226 static void set_meta_method(lua_State
* l
, lua_CFunction f
, const char* name
, int index
= -1);
229 * Object index read event
231 static int object_meta_index_event(lua_State
* l
);
234 * Object index write event
236 static int object_meta_newindex_event(lua_State
* l
);
239 //END GenericWrapperBase-------------------------------------------------------
242 //BEGIN GenericWrapper---------------------------------------------------------
244 template <typename T
>
245 class GenericWrapper
: public GenericWrapperBase
{
248 static void register_class(lua_State
* l
);
251 * Retrieve a wrapped object on the stack.
253 static T
* retrieve(lua_State
* l
, int index
= -1, CheckStrenght check
= Check
);
256 * Destroy a wrapped object of type T.
258 static int deallocate(lua_State
* l
);
261 * Wrap an object of type T in a Lua userdatum.
262 * Lua takes ownership of the object, so that it is
263 * automatically disposed by the Lua garbage collector.
265 static void allocate(lua_State
* l
, T
* x
);
268 * Create the factory class and static metatable.
270 static void create_prototype(lua_State
* l
, const char* prototype_name
);
273 * Calls the Wrapper<T> constructor
275 static int constructor_wrapper(lua_State
* l
);
278 * Pushes this object's meta table.
280 static void push_meta_table(lua_State
* l
);
284 void GenericWrapper
<T
>::register_class(lua_State
* l
) {
285 create_prototype(l
, Wrapper
<T
>::class_name());
289 T
* GenericWrapper
<T
>::retrieve(lua_State
* l
, int index
, CheckStrenght check
) {
292 if(check
!= DontCheck
) {
293 if(!lua_getmetatable(l
,index
)) {
294 if(check
== AssertOk
)
295 luaL_error(l
, "Mismatch, got object of unknown type expecting %s",
296 Wrapper
<T
>::class_name());
299 GenericWrapper
<T
>::push_meta_table(l
);
301 if(!lua_rawequal(l
, -2, -1)) {
302 if(check
== AssertOk
) {
303 if(lua_istable(l
, -2)) {
304 lua_getfield(l
, -2, ".type");
305 if(lua_isstring(l
, -1))
306 luaL_error(l
, "Mismatch, got object of type %s expecting %s",
307 wrap_cptr(lua_tostring(l
,-1)), Wrapper
<T
>::class_name());
310 luaL_error(l
, "Mismatch, got object of unknown type expecting %s",
311 Wrapper
<T
>::class_name());
319 T
** data
= reinterpret_cast<T
**>(
320 lua_touserdata(l
, index
));
321 return data
? *data
: NULL
;
325 int GenericWrapper
<T
>::deallocate(lua_State
* l
) {
328 T
* data
= retrieve(l
);
335 void GenericWrapper
<T
>::allocate(lua_State
* l
, T
* x
) {
339 T
** data
= reinterpret_cast<T
**>(
340 lua_newuserdata(l
, sizeof(T
*)));
345 lua_setmetatable(l
, -2);
349 void GenericWrapper
<T
>::create_prototype(lua_State
* l
, const char* prototype_name
) {
352 lua_newtable(l
); // factory class
354 lua_newtable(l
); // metatable
355 lua_pushcfunction(l
, &constructor_wrapper
);
356 lua_setfield(l
, -2, "__call");
357 lua_setmetatable(l
, -2);
359 lua_newtable(l
); // object metatable
361 lua_pushcfunction(l
, &deallocate
);
362 lua_setfield(l
, -2, "__gc");
364 // add index metamethod
365 lua_pushcfunction(l
, &object_meta_index_event
);
366 lua_setfield(l
, -2, "__index");
368 // add newindex metamethod
369 lua_pushcfunction(l
, &object_meta_newindex_event
);
370 lua_setfield(l
, -2, "__newindex");
373 lua_setfield(l
, -2, ".methods");
376 lua_setfield(l
, -2, ".get");
379 lua_setfield(l
, -2, ".set");
381 lua_pushstring(l
, prototype_name
);
382 lua_setfield(l
, -2, ".type");
384 Wrapper
<T
>::create_index_table(l
);
385 lua_setfield(l
, -2, "object_meta_table");
387 lua_setglobal(l
, prototype_name
);
391 int GenericWrapper
<T
>::constructor_wrapper(lua_State
* l
) {
393 return Wrapper
<T
>::constructor(l
);
397 void GenericWrapper
<T
>::push_meta_table(lua_State
* l
) {
400 lua_getglobal(l
, Wrapper
<T
>::class_name());
401 lua_pushstring(l
, "object_meta_table");
406 //END GenericWrapper-----------------------------------------------------------
408 //BEGIN GenericWrapperByValue---------------------------------------------------------
410 template <typename T
>
411 class GenericWrapperByValue
: public GenericWrapperBase
{
414 static void register_class(lua_State
* l
);
417 * Retrieve a wrapped object on the stack.
419 static T
* retrieve(lua_State
* l
, int index
= -1, CheckStrenght check
= Check
);
422 * Destroy a wrapped object of type T.
424 static int deallocate(lua_State
* l
);
427 * Wrap an object of type T in a Lua userdatum.
428 * Lua takes ownership of the object, so that it is
429 * automatically disposed by the Lua garbage collector.
431 static void allocate(lua_State
* l
, const T x
);
433 static void create(lua_State
* l
);
434 template<typename A1
>
435 static void create(lua_State
* l
, const A1
&);
436 template<typename A1
, typename A2
>
437 static void create(lua_State
* l
, const A1
&, const A2
&);
438 template<typename A1
, typename A2
, typename A3
>
439 static void create(lua_State
* l
, const A1
&, const A2
&, const A3
&);
440 template<typename A1
, typename A2
, typename A3
, typename A4
>
441 static void create(lua_State
* l
, const A1
&, const A2
&, const A3
&, const A4
&);
442 template<typename A1
, typename A2
, typename A3
, typename A4
, typename A5
>
443 static void create(lua_State
* l
, const A1
&, const A2
&, const A3
&, const A4
&, const A5
&);
446 * Create the factory class and static metatable.
448 static void create_prototype(lua_State
* l
, const char* prototype_name
);
451 * Calls the Wrapper<T> constructor
453 static int constructor_wrapper(lua_State
* l
);
456 * Pushes this object's meta table.
458 static void push_meta_table(lua_State
* l
);
462 void GenericWrapperByValue
<T
>::register_class(lua_State
* l
) {
463 create_prototype(l
, Wrapper
<T
>::class_name());
467 T
* GenericWrapperByValue
<T
>::retrieve(lua_State
* l
, int index
, CheckStrenght check
) {
470 if(check
!= DontCheck
) {
471 if(!lua_getmetatable(l
,index
)) {
472 if(check
== AssertOk
)
473 luaL_error(l
, "Mismatch, got object of unknown type expecting %s",
474 Wrapper
<T
>::class_name());
477 GenericWrapperByValue
<T
>::push_meta_table(l
);
479 if(!lua_rawequal(l
, -2, -1)) {
480 if(check
== AssertOk
) {
481 if(lua_istable(l
, -2)) {
482 lua_getfield(l
, -2, ".type");
483 if(lua_isstring(l
, -1))
484 luaL_error(l
, "Mismatch, got object of type %s expecting %s",
485 wrap_cptr(lua_tostring(l
,-1)), Wrapper
<T
>::class_name());
488 luaL_error(l
, "Mismatch, got object of unknown type expecting %s",
489 Wrapper
<T
>::class_name());
497 T
* data
= reinterpret_cast<T
*>(
498 lua_touserdata(l
, index
));
503 int GenericWrapperByValue
<T
>::deallocate(lua_State
* l
) {
506 T
* data
= retrieve(l
);
508 data
->~T(); //placement delete
513 void GenericWrapperByValue
<T
>::allocate(lua_State
* l
, T x
) {
517 T
* data
= reinterpret_cast<T
*>(
518 lua_newuserdata(l
, sizeof(T
)));
519 new(data
) T(x
); //placement new
525 lua_setmetatable(l
, -2);
529 void GenericWrapperByValue
<T
>::create(lua_State
* l
) {
532 T
* data
= reinterpret_cast<T
*>(lua_newuserdata(l
, sizeof(T
)));
533 new(data
) T(); //placement new
535 lua_setmetatable(l
, -2);
539 template<typename A1
>
540 void GenericWrapperByValue
<T
>::create(lua_State
* l
, const A1
& a1
) {
543 T
* data
= reinterpret_cast<T
*>(lua_newuserdata(l
, sizeof(T
)));
544 new(data
) T(a1
); //placement new
546 lua_setmetatable(l
, -2);
550 template<typename A1
, typename A2
>
551 void GenericWrapperByValue
<T
>::create(lua_State
* l
, const A1
& a1
, const A2
& a2
) {
554 T
* data
= reinterpret_cast<T
*>(lua_newuserdata(l
, sizeof(T
)));
555 new(data
) T(a1
, a2
); //placement new
557 lua_setmetatable(l
, -2);
561 template<typename A1
, typename A2
, typename A3
>
562 void GenericWrapperByValue
<T
>::create(lua_State
* l
, const A1
& a1
, const A2
& a2
, const A3
& a3
) {
565 T
* data
= reinterpret_cast<T
*>(lua_newuserdata(l
, sizeof(T
)));
566 new(data
) T(a1
, a2
, a3
); //placement new
568 lua_setmetatable(l
, -2);
572 template<typename A1
, typename A2
, typename A3
, typename A4
>
573 void GenericWrapperByValue
<T
>::create(lua_State
* l
, const A1
& a1
, const A2
& a2
,
574 const A3
& a3
, const A4
& a4
) {
577 T
* data
= reinterpret_cast<T
*>(lua_newuserdata(l
, sizeof(T
)));
578 new(data
) T(a1
, a2
, a3
, a4
); //placement new
580 lua_setmetatable(l
, -2);
584 template<typename A1
, typename A2
, typename A3
, typename A4
, typename A5
>
585 void GenericWrapperByValue
<T
>::create(lua_State
* l
, const A1
& a1
, const A2
& a2
, const A3
& a3
,
586 const A4
& a4
, const A5
& a5
) {
589 T
* data
= reinterpret_cast<T
*>(lua_newuserdata(l
, sizeof(T
)));
590 new(data
) T(a1
, a2
, a3
, a4
, a5
); //placement new
592 lua_setmetatable(l
, -2);
596 void GenericWrapperByValue
<T
>::create_prototype(lua_State
* l
, const char* prototype_name
) {
599 lua_newtable(l
); // factory class
601 lua_newtable(l
); // metatable
602 lua_pushcfunction(l
, &constructor_wrapper
);
603 lua_setfield(l
, -2, "__call");
604 lua_setmetatable(l
, -2);
606 lua_newtable(l
); // object metatable
608 lua_pushcfunction(l
, &deallocate
);
609 lua_setfield(l
, -2, "__gc");
611 // add index metamethod
612 lua_pushcfunction(l
, &object_meta_index_event
);
613 lua_setfield(l
, -2, "__index");
615 // add newindex metamethod
616 lua_pushcfunction(l
, &object_meta_newindex_event
);
617 lua_setfield(l
, -2, "__newindex");
620 lua_setfield(l
, -2, ".methods");
623 lua_setfield(l
, -2, ".get");
626 lua_setfield(l
, -2, ".set");
628 lua_pushstring(l
, prototype_name
);
629 lua_setfield(l
, -2, ".type");
631 Wrapper
<T
>::create_index_table(l
);
632 lua_setfield(l
, -2, "object_meta_table");
634 lua_setglobal(l
, prototype_name
);
638 int GenericWrapperByValue
<T
>::constructor_wrapper(lua_State
* l
) {
640 return Wrapper
<T
>::constructor(l
);
644 void GenericWrapperByValue
<T
>::push_meta_table(lua_State
* l
) {
647 lua_getglobal(l
, Wrapper
<T
>::class_name());
648 lua_pushstring(l
, "object_meta_table");
653 //END GenericWrapperByValue-----------------------------------------------------------
659 static void register_in_index_table(lua_State
* l
);
660 static int eq_event(lua_State
* l
);
664 void Comparable
<T
>::register_in_index_table(lua_State
* l
) {
665 Wrapper
<T
>::set_meta_method(l
, &eq_event
, "__eq");
669 int Comparable
<T
>::eq_event(lua_State
* l
) {
670 int n
= lua_gettop(l
);
672 luaL_error(l
, "Wrong argument count %d for __eq", n
);
673 T
*p1
= Wrapper
<T
>::retrieve(l
, 1, AssertOk
);
674 T
*p2
= Wrapper
<T
>::retrieve(l
, 2, AssertOk
);
676 lua_pushboolean(l
, *p1
== *p2
);
683 static void register_in_index_table(lua_State
* l
);
684 static int add_event(lua_State
* l
);
685 static int sub_event(lua_State
* l
);
686 static int unm_event(lua_State
* l
);
690 void Summable
<T
>::register_in_index_table(lua_State
* l
) {
691 Wrapper
<T
>::set_meta_method(l
, &add_event
, "__add");
692 Wrapper
<T
>::set_meta_method(l
, &sub_event
, "__sub");
693 Wrapper
<T
>::set_meta_method(l
, &unm_event
, "__unm");
697 int Summable
<T
>::add_event(lua_State
* l
) {
698 int n
= lua_gettop(l
);
700 luaL_error(l
, "Wrong argument count %d for __add", n
);
701 T
*p1
= Wrapper
<T
>::retrieve(l
, 1, AssertOk
);
702 T
*p2
= Wrapper
<T
>::retrieve(l
, 2, AssertOk
);
705 Wrapper
<T
>::allocate(l
, new T(*p1
+ *p2
));
711 int Summable
<T
>::sub_event(lua_State
* l
) {
712 int n
= lua_gettop(l
);
714 luaL_error(l
, "Wrong argument count %d for __sub", n
);
715 T
*p1
= Wrapper
<T
>::retrieve(l
, 1, AssertOk
);
716 T
*p2
= Wrapper
<T
>::retrieve(l
, 2, AssertOk
);
719 Wrapper
<T
>::allocate(l
, new T(*p1
- *p2
));
725 int Summable
<T
>::unm_event(lua_State
* l
) {
726 int n
= lua_gettop(l
);
728 /* for some strange reason unm gets 2 copies of the same argument */
730 luaL_error(l
, "Wrong argument count %d for __unm", n
);
731 T
*p1
= Wrapper
<T
>::retrieve(l
, 1, AssertOk
);
734 Wrapper
<T
>::allocate(l
, new T(-*p1
));
739 } //end namespace LuaApi
742 #endif //LUAAPI__GENERICWRAPPER_H