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);
151 /** Add a signal to an object.
152 * \param L The Lua VM state.
153 * \param oud The object index on the stack.
154 * \param name The name of the signal.
155 * \param ud The index of function to call when signal is emitted.
158 luaA_object_add_signal(lua_State
*L
, int oud
,
159 const char *name
, int ud
)
161 luaA_checkfunction(L
, ud
);
162 lua_object_t
*obj
= lua_touserdata(L
, oud
);
163 signal_add(&obj
->signals
, name
, luaA_object_ref_item(L
, oud
, ud
));
166 /** Remove a signal to an object.
167 * \param L The Lua VM state.
168 * \param oud The object index on the stack.
169 * \param name The name of the signal.
170 * \param ud The index of function to call when signal is emitted.
173 luaA_object_remove_signal(lua_State
*L
, int oud
,
174 const char *name
, int ud
)
176 luaA_checkfunction(L
, ud
);
177 lua_object_t
*obj
= lua_touserdata(L
, oud
);
178 void *ref
= (void *) lua_topointer(L
, ud
);
179 signal_remove(&obj
->signals
, name
, ref
);
180 luaA_object_unref_item(L
, oud
, ref
);
185 signal_object_emit(lua_State
*L
, signal_array_t
*arr
, const char *name
, int nargs
)
187 signal_t
*sigfound
= signal_array_getbyid(arr
,
188 a_strhash((const unsigned char *) name
));
192 int nbfunc
= sigfound
->sigfuncs
.len
;
193 luaL_checkstack(L
, lua_gettop(L
) + nbfunc
+ nargs
+ 1, "too much signal");
194 /* Push all functions and then execute, because this list can change
195 * while executing funcs. */
196 foreach(func
, sigfound
->sigfuncs
)
197 luaA_object_push(L
, (void *) *func
);
199 for(int i
= 0; i
< nbfunc
; i
++)
202 for(int j
= 0; j
< nargs
; j
++)
203 lua_pushvalue(L
, - nargs
- nbfunc
+ i
);
204 /* push first function */
205 lua_pushvalue(L
, - nargs
- nbfunc
+ i
);
206 /* remove this first function */
207 lua_remove(L
, - nargs
- nbfunc
- 1 + i
);
208 luaA_dofunction(L
, nargs
, 0);
215 /** Emit a signal to an object.
216 * \param L The Lua VM state.
217 * \param oud The object index on the stack.
218 * \param name The name of the signal.
219 * \param nargs The number of arguments to pass to the called functions.
222 luaA_object_emit_signal(lua_State
*L
, int oud
,
223 const char *name
, int nargs
)
225 int oud_abs
= luaA_absindex(L
, oud
);
226 lua_object_t
*obj
= lua_touserdata(L
, oud
);
228 luaL_error(L
, "trying to emit signal on non-object");
229 signal_t
*sigfound
= signal_array_getbyid(&obj
->signals
,
230 a_strhash((const unsigned char *) name
));
233 int nbfunc
= sigfound
->sigfuncs
.len
;
234 luaL_checkstack(L
, lua_gettop(L
) + nbfunc
+ nargs
+ 2, "too much signal");
235 /* Push all functions and then execute, because this list can change
236 * while executing funcs. */
237 foreach(func
, sigfound
->sigfuncs
)
238 luaA_object_push_item(L
, oud_abs
, (void *) *func
);
240 for(int i
= 0; i
< nbfunc
; i
++)
243 lua_pushvalue(L
, oud_abs
);
245 for(int j
= 0; j
< nargs
; j
++)
246 lua_pushvalue(L
, - nargs
- nbfunc
- 1 + i
);
247 /* push first function */
248 lua_pushvalue(L
, - nargs
- nbfunc
- 1 + i
);
249 /* remove this first function */
250 lua_remove(L
, - nargs
- nbfunc
- 2 + i
);
251 luaA_dofunction(L
, nargs
+ 1, 0);
258 luaA_object_add_signal_simple(lua_State
*L
)
260 luaA_object_add_signal(L
, 1, luaL_checkstring(L
, 2), 3);
265 luaA_object_remove_signal_simple(lua_State
*L
)
267 luaA_object_remove_signal(L
, 1, luaL_checkstring(L
, 2), 3);
272 luaA_object_emit_signal_simple(lua_State
*L
)
274 luaA_object_emit_signal(L
, 1, luaL_checkstring(L
, 2), lua_gettop(L
) - 2);
279 luaA_object_tostring(lua_State
*L
)
281 lua_class_t
*lua_class
= luaA_class_get(L
, 1);
282 lua_pushfstring(L
, "%s: %p", lua_class
->name
, luaA_checkudata(L
, 1, lua_class
));
286 /** Garbage collect a Lua object.
287 * \param L The Lua VM state.
288 * \return The number of elements pushed on stack.
291 luaA_object_gc(lua_State
*L
)
293 lua_object_t
*item
= lua_touserdata(L
, 1);
294 signal_array_wipe(&item
->signals
);
298 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80