2 * luaobject.c - useful functions for handling Lua objects
4 * Copyright © 2009 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "common/luaobject.h"
24 /** Setup the object system at startup.
25 * \param L The Lua VM state.
28 luaA_object_setup(lua_State
*L
)
30 /* Push identification string */
31 lua_pushliteral(L
, LUAA_OBJECT_REGISTRY_KEY
);
32 /* Create an empty table */
34 /* Create an empty metatable */
36 /* Set this empty table as the registry metatable.
37 * It's used to store the number of reference on stored objects. */
38 lua_setmetatable(L
, -2);
39 /* Register table inside registry */
40 lua_rawset(L
, LUA_REGISTRYINDEX
);
43 /** Increment a object reference in its store table.
44 * \param L The Lua VM state.
45 * \param tud The table index on the stack.
46 * \param oud The object index on the stack.
47 * \return A pointer to the object.
50 luaA_object_incref(lua_State
*L
, int tud
, int oud
)
52 /* Get pointer value of the item */
53 void *pointer
= (void *) lua_topointer(L
, oud
);
55 /* Not reference able. */
62 /* Push the pointer (key) */
63 lua_pushlightuserdata(L
, pointer
);
64 /* Push the data (value) */
65 lua_pushvalue(L
, oud
< 0 ? oud
- 1 : oud
);
66 /* table.lightudata = data */
67 lua_rawset(L
, tud
< 0 ? tud
- 2 : tud
);
71 /* Get the metatable */
72 lua_getmetatable(L
, tud
);
73 /* Push the pointer (key) */
74 lua_pushlightuserdata(L
, pointer
);
75 /* Get the number of references */
77 /* Get the number of references and increment it */
78 int count
= lua_tonumber(L
, -1) + 1;
80 /* Push the pointer (key) */
81 lua_pushlightuserdata(L
, pointer
);
82 /* Push count (value) */
83 lua_pushinteger(L
, count
);
84 /* Set metatable[pointer] = count */
89 /* Remove referenced item */
95 /** Decrement a object reference in its store table.
96 * \param L The Lua VM state.
97 * \param tud The table index on the stack.
98 * \param oud The object index on the stack.
99 * \return A pointer to the object.
102 luaA_object_decref(lua_State
*L
, int tud
, void *pointer
)
107 /* First, refcount-- */
108 /* Get the metatable */
109 lua_getmetatable(L
, tud
);
110 /* Push the pointer (key) */
111 lua_pushlightuserdata(L
, pointer
);
112 /* Get the number of references */
114 /* Get the number of references and decrement it */
115 int count
= lua_tonumber(L
, -1) - 1;
117 /* Push the pointer (key) */
118 lua_pushlightuserdata(L
, pointer
);
119 /* Hasn't the ref reached 0? */
121 lua_pushinteger(L
, count
);
123 /* Yup, delete it, set nil as value */
125 /* Set meta[pointer] = count/nil */
130 /* Wait, no more ref? */
133 /* Yes? So remove it from table */
134 lua_pushlightuserdata(L
, pointer
);
135 /* Push nil as value */
137 /* table[pointer] = nil */
138 lua_rawset(L
, tud
< 0 ? tud
- 2 : tud
);
143 luaA_settype(lua_State
*L
, lua_class_t
*lua_class
)
145 lua_pushlightuserdata(L
, lua_class
);
146 lua_rawget(L
, LUA_REGISTRYINDEX
);
147 lua_setmetatable(L
, -2);
152 luaA_object_connect_signal(lua_State
*L
, int oud
,
153 const char *name
, lua_CFunction fn
)
155 lua_pushcfunction(L
, fn
);
156 luaA_object_connect_signal_from_stack(L
, oud
, name
, -1);
160 luaA_object_disconnect_signal(lua_State
*L
, int oud
,
161 const char *name
, lua_CFunction fn
)
163 lua_pushcfunction(L
, fn
);
164 luaA_object_disconnect_signal_from_stack(L
, oud
, name
, -1);
167 /** Add a signal to an object.
168 * \param L The Lua VM state.
169 * \param oud The object index on the stack.
170 * \param name The name of the signal.
171 * \param ud The index of function to call when signal is emitted.
174 luaA_object_connect_signal_from_stack(lua_State
*L
, int oud
,
175 const char *name
, int ud
)
177 luaA_checkfunction(L
, ud
);
178 lua_object_t
*obj
= lua_touserdata(L
, oud
);
179 signal_connect(&obj
->signals
, name
, luaA_object_ref_item(L
, oud
, ud
));
182 /** Remove a signal to an object.
183 * \param L The Lua VM state.
184 * \param oud The object index on the stack.
185 * \param name The name of the signal.
186 * \param ud The index of function to call when signal is emitted.
189 luaA_object_disconnect_signal_from_stack(lua_State
*L
, int oud
,
190 const char *name
, int ud
)
192 luaA_checkfunction(L
, ud
);
193 lua_object_t
*obj
= lua_touserdata(L
, oud
);
194 void *ref
= (void *) lua_topointer(L
, ud
);
195 signal_disconnect(&obj
->signals
, name
, ref
);
196 luaA_object_unref_item(L
, oud
, ref
);
201 signal_object_emit(lua_State
*L
, signal_array_t
*arr
, const char *name
, int nargs
)
203 signal_t
*sigfound
= signal_array_getbyid(arr
,
204 a_strhash((const unsigned char *) name
));
208 int nbfunc
= sigfound
->sigfuncs
.len
;
209 luaL_checkstack(L
, lua_gettop(L
) + nbfunc
+ nargs
+ 1, "too much signal");
210 /* Push all functions and then execute, because this list can change
211 * while executing funcs. */
212 foreach(func
, sigfound
->sigfuncs
)
213 luaA_object_push(L
, (void *) *func
);
215 for(int i
= 0; i
< nbfunc
; i
++)
218 for(int j
= 0; j
< nargs
; j
++)
219 lua_pushvalue(L
, - nargs
- nbfunc
+ i
);
220 /* push first function */
221 lua_pushvalue(L
, - nargs
- nbfunc
+ i
);
222 /* remove this first function */
223 lua_remove(L
, - nargs
- nbfunc
- 1 + i
);
224 luaA_dofunction(L
, nargs
, 0);
227 warn("Trying to emit unknown signal '%s'", name
);
233 /** Emit a signal to an object.
234 * \param L The Lua VM state.
235 * \param oud The object index on the stack.
236 * \param name The name of the signal.
237 * \param nargs The number of arguments to pass to the called functions.
240 luaA_object_emit_signal(lua_State
*L
, int oud
,
241 const char *name
, int nargs
)
243 int oud_abs
= luaA_absindex(L
, oud
);
244 lua_object_t
*obj
= lua_touserdata(L
, oud
);
246 luaL_error(L
, "trying to emit signal on non-object");
247 signal_t
*sigfound
= signal_array_getbyid(&obj
->signals
,
248 a_strhash((const unsigned char *) name
));
251 int nbfunc
= sigfound
->sigfuncs
.len
;
252 luaL_checkstack(L
, lua_gettop(L
) + nbfunc
+ nargs
+ 2, "too much signal");
253 /* Push all functions and then execute, because this list can change
254 * while executing funcs. */
255 foreach(func
, sigfound
->sigfuncs
)
256 luaA_object_push_item(L
, oud_abs
, (void *) *func
);
258 for(int i
= 0; i
< nbfunc
; i
++)
261 lua_pushvalue(L
, oud_abs
);
263 for(int j
= 0; j
< nargs
; j
++)
264 lua_pushvalue(L
, - nargs
- nbfunc
- 1 + i
);
265 /* push first function */
266 lua_pushvalue(L
, - nargs
- nbfunc
- 1 + i
);
267 /* remove this first function */
268 lua_remove(L
, - nargs
- nbfunc
- 2 + i
);
269 luaA_dofunction(L
, nargs
+ 1, 0);
272 warn("Trying to emit unknown signal '%s'", name
);
274 /* Then emit signal on the class */
275 lua_pushvalue(L
, oud
);
276 lua_insert(L
, - nargs
- 1);
277 luaA_class_emit_signal(L
, luaA_class_get(L
, - nargs
- 1), name
, nargs
+ 1);
281 luaA_object_connect_signal_simple(lua_State
*L
)
283 luaA_object_connect_signal_from_stack(L
, 1, luaL_checkstring(L
, 2), 3);
288 luaA_object_disconnect_signal_simple(lua_State
*L
)
290 luaA_object_disconnect_signal_from_stack(L
, 1, luaL_checkstring(L
, 2), 3);
295 luaA_object_emit_signal_simple(lua_State
*L
)
297 luaA_object_emit_signal(L
, 1, luaL_checkstring(L
, 2), lua_gettop(L
) - 2);
302 luaA_object_tostring(lua_State
*L
)
304 lua_class_t
*lua_class
= luaA_class_get(L
, 1);
305 lua_object_t
*object
= luaA_checkudata(L
, 1, lua_class
);
308 for(; lua_class
; lua_class
= lua_class
->parent
, i
++)
312 lua_pushliteral(L
, "/");
313 lua_insert(L
, - (i
* 2));
315 lua_pushstring(L
, NONULL(lua_class
->name
));
316 lua_insert(L
, - (i
* 2) - 1);
319 lua_pushfstring(L
, ": %p", object
);
321 lua_concat(L
, i
* 2);
326 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80