2 * Copyright (c) 2007-2008 Mauro Iazzi
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
27 #include "lqt_common.hpp"
32 static void lqtL_getenumtable (lua_State
*L
) {
33 lua_getfield(L
, LUA_REGISTRYINDEX
, LQT_ENUMS
);
34 if (lua_isnil(L
, -1)) {
38 lua_setfield(L
, LUA_REGISTRYINDEX
, LQT_ENUMS
);
42 static void lqtL_getpointertable (lua_State
*L
) {
43 lua_getfield(L
, LUA_REGISTRYINDEX
, LQT_POINTERS
); // (1) get storage for pointers
44 if (lua_isnil(L
, -1)) { // (1) if there is not
45 lua_pop(L
, 1); // (0) pop the nil value
46 lua_newtable(L
); // (1) create a new one
47 lua_newtable(L
); // (2) create an empty metatable
48 lua_pushstring(L
, "v"); // (3) push the mode value: weak values are enough
49 lua_setfield(L
, -2, "__mode"); // (2) set the __mode field
50 lua_setmetatable(L
, -2); // (1) set it as the metatable
51 lua_pushvalue(L
, -1); // (2) duplicate the new pointer table
52 lua_setfield(L
, LUA_REGISTRYINDEX
, LQT_POINTERS
); // (1) put one copy as storage
56 static void lqtL_getreftable (lua_State
*L
) {
57 lua_getfield(L
, LUA_REGISTRYINDEX
, LQT_REFS
); // (1) get storage for pointers
58 if (lua_isnil(L
, -1)) { // (1) if there is not
59 lua_pop(L
, 1); // (0) pop the nil value
60 lua_newtable(L
); // (1) create a new one
61 lua_newtable(L
); // (2) create an empty metatable
62 lua_pushstring(L
, "kv"); // (3) push the mode value: weak values are enough
63 lua_setfield(L
, -2, "__mode"); // (2) set the __mode field
64 lua_setmetatable(L
, -2); // (1) set it as the metatable
65 lua_pushvalue(L
, -1); // (2) duplicate the new pointer table
66 lua_setfield(L
, LUA_REGISTRYINDEX
, LQT_REFS
); // (1) put one copy as storage
70 void * lqtL_getref (lua_State
*L
, size_t sz
) {
72 lqtL_getreftable(L
); // (1)
73 ret
= lua_newuserdata(L
, sz
); // (2)
74 lua_rawseti(L
, -2, 1+lua_objlen(L
, -2));
78 int * lqtL_tointref (lua_State
*L
, int index
) {
79 int *ret
= (int*)lqtL_getref(L
, sizeof(int));
80 *ret
= lua_tointeger(L
, index
);
84 void lqtL_pusharguments (lua_State
*L
, char **argv
) {
87 for (i
=0;*argv
/* fix the maximum number? */;argv
++,i
++) {
88 lua_pushstring(L
, *argv
);
89 lua_rawseti(L
, -2, i
+1);
94 char ** lqtL_toarguments (lua_State
*L
, int index
) {
95 char ** ret
= (char**)lqtL_getref(L
, sizeof(char*)*(lua_objlen(L
, index
)+1));
96 const char *str
= NULL
;
100 lua_rawgeti(L
, index
, i
+1);
101 if (!lua_isstring(L
, -1)) {
102 str
= NULL
; strlen
= 0;
107 str
= lua_tolstring(L
, -1, &strlen
);
108 ret
[i
] = (char*)lqtL_getref(L
, sizeof(char)*(strlen
+1));
109 strncpy(ret
[i
], str
, strlen
+1);
116 static int lqtL_createenum (lua_State
*L
, lqt_Enum e
[], const char *n
) {
117 lqtL_getenumtable(L
); // (1)
118 lua_newtable(L
); // (2)
119 lua_pushvalue(L
, -1); // (3)
120 lua_setfield(L
, -3, n
); // (2)
121 while ( (e
->name
!=0) ) { // (2)
122 lua_pushstring(L
, e
->name
); // (3)
123 lua_pushinteger(L
, e
->value
); // (4)
124 lua_settable(L
, -3); // (2)
125 lua_pushinteger(L
, e
->value
); // (3)
126 lua_pushstring(L
, e
->name
); // (4)
127 lua_settable(L
, -3); // (2)
130 lua_pop(L
, 2); // (0)
134 int lqtL_createenumlist (lua_State
*L
, lqt_Enumlist list
[]) {
135 while (list
->enums
!=0 && list
->name
!=0) {
136 lqtL_createenum(L
, list
->enums
, list
->name
); // (0)
142 static int lqtL_gcfunc (lua_State
*L
) {
143 if (!lua_isuserdata(L
, 1) || lua_islightuserdata(L
, 1)) return 0;
144 lua_getfenv(L
, 1); // (1)
145 if (!lua_istable(L
, -1)) {
146 lua_pop(L
, 1); // (0)
149 lua_getfield(L
, -1, "__gc"); // (2)
150 lua_remove(L
, -2); // (1)
151 if (!lua_isfunction(L
, -1)) {
152 lua_pop(L
, 1); // (0)
155 lua_pushvalue(L
, 1); // (2)
156 if (lua_pcall(L
, 1, 0, 0)) { // (-2;+1/+0)
163 static int lqtL_newindexfunc (lua_State
*L
) {
164 lua_settop(L
, 3); // (=3)
165 if (!lua_isuserdata(L
, 1) || lua_islightuserdata(L
, 1)) return 0;
166 lua_getfenv(L
, 1); // (+1)
167 if (!lua_istable(L
, -1)) {
168 lua_pop(L
, 1); // (+0)
171 lua_remove(L
, 1); // (+0)
172 lua_insert(L
, 1); // (+0)
173 lua_rawset(L
, 1); // (-2)
176 static int lqtL_indexfunc (lua_State
*L
) {
178 if (lua_isuserdata(L
, 1) || !lua_islightuserdata(L
, 1)) {
179 lua_getfenv(L
, 1); // (1)
180 lua_pushvalue(L
, 2); // (2)
181 lua_gettable(L
, -2); // (2)
182 if (!lua_isnil(L
, -1)) {
186 lua_pop(L
, 2); // (0)
188 lua_pushnil(L
); // (+1)
189 while (!lua_isnone(L
, lua_upvalueindex(i
))) { // (+1)
190 lua_pop(L
, 1); // (+0)
191 lua_pushvalue(L
, 2); // (+1)
193 lua_rawget(L
, lua_upvalueindex(i
)); // (+1)
195 lua_gettable(L
, lua_upvalueindex(i
)); // (+1)
197 if (!lua_isnil(L
, -1)) break;
203 static int lqtL_pushindexfunc (lua_State
*L
, const char *name
, lqt_Base
*bases
) {
205 luaL_newmetatable(L
, name
); // (1)
206 while (bases
->basename
!=NULL
) {
207 luaL_newmetatable(L
, bases
->basename
); // (upnum)
211 lua_pushcclosure(L
, lqtL_indexfunc
, upnum
); // (1)
215 int lqtL_createclasses (lua_State
*L
, lqt_Class
*list
) {
216 while (list
->name
!=0) { // (0)
217 luaL_newmetatable(L
, list
->name
); // (1)
218 luaL_register(L
, NULL
, list
->mt
); // (1)
219 lua_pushstring(L
, list
->name
); // (2)
220 lua_pushboolean(L
, 1); // (3)
221 lua_settable(L
, -3); // (1)
222 lqtL_pushindexfunc(L
, list
->name
, list
->bases
); // (2)
223 lua_setfield(L
, -2, "__index"); // (1)
224 lua_pushcfunction(L
, lqtL_newindexfunc
); // (2)
225 lua_setfield(L
, -2, "__newindex"); // (1)
226 lua_pushcfunction(L
, lqtL_gcfunc
); // (2)
227 lua_setfield(L
, -2, "__gc"); // (1)
228 lua_pushvalue(L
, -1); // (2)
229 lua_setmetatable(L
, -2); // (1)
230 lua_pop(L
, 1); // (0)
231 lua_pushlstring(L
, list
->name
, strlen(list
->name
)-1); // (1)
232 lua_newtable(L
); // (2)
233 luaL_register(L
, NULL
, list
->mt
); // (2)
234 lua_settable(L
, LUA_GLOBALSINDEX
); // (0)
240 bool lqtL_isinteger (lua_State
*L
, int i
) {
241 if (lua_type(L
, i
)==LUA_TNUMBER
)
242 return lua_tointeger(L
, i
)==lua_tonumber(L
, i
);
246 bool lqtL_isnumber (lua_State
*L
, int i
) {
247 return lua_type(L
, i
)==LUA_TNUMBER
;
249 bool lqtL_isstring (lua_State
*L
, int i
) {
250 return lua_type(L
, i
)==LUA_TSTRING
;
252 bool lqtL_isboolean (lua_State
*L
, int i
) {
253 return lua_type(L
, i
)==LUA_TBOOLEAN
;
255 bool lqtL_missarg (lua_State
*L
, int index
, int n
) {
258 for (i
=index
;i
<index
+n
;i
++) {
259 if (!lua_isnoneornil(L
, i
)) {
267 static void CS(lua_State
*L
) {
268 qDebug() << "++++++++++";
269 for (int i
=1;i
<=lua_gettop(L
);i
++) {
270 qDebug() << luaL_typename(L
, i
) << lua_touserdata(L
, i
);
272 qDebug() << "----------";
275 static void lqtL_ensurepointer (lua_State
*L
, const void *p
) { // (+1)
276 lqtL_getpointertable(L
); // (1)
277 lua_pushlightuserdata(L
, const_cast<void*>(p
)); // (2)
278 lua_gettable(L
, -2); // (2)
279 if (lua_isnil(L
, -1)) { // (2)
280 lua_pop(L
, 1); // (1)
281 const void **pp
= static_cast<const void**>(lua_newuserdata(L
, sizeof(void*))); // (2)
283 lua_newtable(L
); // (3)
284 lua_setfenv(L
, -2); // (2)
285 lua_pushlightuserdata(L
, const_cast<void*>(p
)); // (3)
286 lua_pushvalue(L
, -2); // (4)
287 lua_settable(L
, -4); // (2)
290 lua_remove(L
, -2); // (1)
293 void lqtL_register (lua_State
*L
, const void *p
) { // (+0)
294 lqtL_ensurepointer(L
, p
);
298 void lqtL_unregister (lua_State
*L
, const void *p
) {
299 lqtL_getpointertable(L
); // (1)
300 lua_pushlightuserdata(L
, const_cast<void*>(p
)); // (2)
301 lua_gettable(L
, -2); // (2)
302 if (lua_isuserdata(L
, -1)) {
303 const void **pp
= static_cast<const void**>(lua_touserdata(L
, -1)); // (2)
306 lua_pop(L
, 1); // (1)
307 lua_pushlightuserdata(L
, const_cast<void*>(p
)); // (2)
308 lua_pushnil(L
); // (3)
309 lua_settable(L
, -3); // (1)
310 lua_pop(L
, 1); // (0)
313 void lqtL_passudata (lua_State
*L
, const void *p
, const char *name
) {
314 bool already
= false;
315 lqtL_ensurepointer(L
, p
); // (1)
316 if (lua_getmetatable(L
, -1)) {
318 lua_pop(L
, 1); // (1)
319 lua_getfield(L
, -1, name
); // (2)
320 already
= lua_toboolean(L
, -1); // (2)
321 lua_pop(L
, 1); // (1)
326 luaL_newmetatable(L
, name
); // (2)
327 lua_setmetatable(L
, -2); // (1)
332 void lqtL_pushudata (lua_State
*L
, const void *p
, const char *name
) {
333 bool already
= false;
334 lqtL_ensurepointer(L
, p
); // (1)
335 lua_getmetatable(L
, -1); // (2)
336 if (!lua_isnil(L
, -1)) {
337 lua_pop(L
, 1); // (1)
338 lua_getfield(L
, -1, name
); // (2)
339 already
= lua_toboolean(L
, -1); // (2)
341 lua_pop(L
, 1); // (1)
343 luaL_newmetatable(L
, name
); // (2)
344 lua_setmetatable(L
, -2); // (1)
349 void *lqtL_toudata (lua_State
*L
, int index
, const char *name
) {
351 if (!lqtL_testudata(L
, index
, name
)) return 0;
352 void **pp
= static_cast<void**>(lua_touserdata(L
, index
));
357 bool lqtL_testudata (lua_State
*L
, int index
, const char *name
) {
358 if (!lua_isuserdata(L
, index
) || lua_islightuserdata(L
, index
)) return false;
359 lua_getfield(L
, index
, name
);
360 if (!lua_isboolean(L
, -1) || !lua_toboolean(L
, -1)) {
368 void lqtL_pushenum (lua_State
*L
, int value
, const char *name
) {
369 lqtL_getenumtable(L
);
370 lua_getfield(L
, -1, name
);
372 if (!lua_istable(L
, -1)) {
377 lua_pushnumber(L
, value
);
382 bool lqtL_isenum (lua_State
*L
, int index
, const char *name
) {
384 if (!lua_isstring(L
, index
)) return false;
385 lqtL_getenumtable(L
);
386 lua_getfield(L
, -1, name
);
387 if (!lua_istable(L
, -1)) {
392 lua_pushvalue(L
, index
);
394 ret
= lua_isnumber(L
, -1);
399 int lqtL_toenum (lua_State
*L
, int index
, const char *name
) {
401 lqtL_getenumtable(L
); // (1)
402 lua_getfield(L
, -1, name
); // (2)
403 if (lua_isnil(L
, -1)) {
407 lua_pushvalue(L
, index
); // (3)
408 lua_gettable(L
, -2); // (3)
409 ret
= lua_tointeger(L
, -1); // (3)
410 lua_pop(L
, 3); // (0)
414 int lqtL_getflags (lua_State
*L
, int index
, const char *name
) {
416 lqtL_getenumtable(L
);
417 lua_getfield(L
, -1, name
);
421 void lqtL_pushflags (lua_State
*L
, int index
, const char *name
) {