static bool extl_init_obj_info(lua_State *st)
{
static ExtlExportedFnSpec dummy[]={
- {NULL, NULL, NULL, NULL, NULL, FALSE, FALSE}
+ {NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE}
};
extl_register_class("Obj", dummy, NULL);
/*}}}*/
-/*{{{ Stack get/push -- all unsafe */
+/*{{{ Stack get/push -- all unsafe */
static bool extl_stack_get(lua_State *st, int pos, char type,
if(wasdeadobject!=NULL)
*wasdeadobject=FALSE;
+
+ if(type=='b'){
+ if(valret)
+ *((bool*)valret)=lua_toboolean(st, pos);
+ return TRUE;
+ }
- if(type=='i' || type=='d'){
- if(lua_type(st, pos)!=LUA_TNUMBER)
+ switch(lua_type(st, pos)){
+ case LUA_TNUMBER:
+ if(type!='i' && type!='d' && type!='a')
return FALSE;
-
+
d=lua_tonumber(st, pos);
if(type=='i'){
return FALSE;
if(valret)
*((int*)valret)=d;
+ }else if(type=='a'){
+ if(valret){
+ ((ExtlAny*)valret)->type='d';
+ ((ExtlAny*)valret)->value.d=d;
+ }
}else{
if(valret)
*((double*)valret)=d;
}
return TRUE;
- }
-
- if(type=='b'){
- if(valret)
- *((bool*)valret)=lua_toboolean(st, pos);
- return TRUE;
- }
-
- if(lua_type(st, pos)==LUA_TNIL || lua_type(st, pos)==LUA_TNONE){
- if(type=='t' || type=='f'){
+
+ case LUA_TNIL:
+ case LUA_TNONE:
+ if(type=='a'){
+ if(valret)
+ ((ExtlAny*)valret)->type='v';
+ }else if(type=='t' || type=='f'){
if(valret)
*((int*)valret)=LUA_NOREF;
}else if(type=='s' || type=='S'){
return FALSE;
}
return TRUE;
- }
- if(type=='s' || type=='S'){
- if(lua_type(st, pos)!=LUA_TSTRING)
+ case LUA_TSTRING:
+ if(type!='s' && type!='S' && type!='a')
return FALSE;
if(valret){
str=lua_tostring(st, pos);
if(str==NULL)
return FALSE;
}
- *((const char**)valret)=str;
+ if(type=='a'){
+ ((ExtlAny*)valret)->type=(copystring ? 's' : 'S');
+ ((ExtlAny*)valret)->value.s=str;
+ }else{
+ *((const char**)valret)=str;
+ }
}
return TRUE;
- }
- if(type=='f'){
- if(!lua_isfunction(st, pos))
+ case LUA_TFUNCTION:
+ if(type!='f' && type!='a')
return FALSE;
if(valret){
lua_pushvalue(st, pos);
- *((int*)valret)=lua_ref(st, 1);
+ if(type=='a'){
+ ((ExtlAny*)valret)->type='f';
+ ((ExtlAny*)valret)->value.f=lua_ref(st, 1);
+ }else{
+ *((int*)valret)=lua_ref(st, 1);
+ }
}
return TRUE;
- }
-
- if(type=='t'){
- if(!lua_istable(st, pos))
+
+ case LUA_TTABLE:
+ if(type!='t' && type!='a')
return FALSE;
if(valret){
lua_pushvalue(st, pos);
- *((int*)valret)=lua_ref(st, 1);
+ if(type=='a'){
+ ((ExtlAny*)valret)->type='t';
+ ((ExtlAny*)valret)->value.f=lua_ref(st, 1);
+ }else{
+ *((int*)valret)=lua_ref(st, 1);
+ }
}
return TRUE;
- }
-
- if(type=='o'){
- bool invalid=FALSE, dead=FALSE;
- Obj *obj=extl_get_obj(st, pos, &invalid, &dead);
- if(wasdeadobject!=NULL)
- *wasdeadobject=dead;
- if(valret){
- *((Obj**)valret)=obj;
- D(fprintf(stderr, "Got obj %p, ", obj);
- fprintf(stderr, "%s\n", OBJ_TYPESTR(obj)));
+
+ case LUA_TUSERDATA:
+ if(type=='o'|| type=='a'){
+ bool invalid=FALSE, dead=FALSE;
+ Obj *obj=extl_get_obj(st, pos, &invalid, &dead);
+ if(wasdeadobject!=NULL)
+ *wasdeadobject=dead;
+ if(valret){
+ if(type=='a'){
+ ((ExtlAny*)valret)->type='o';
+ ((ExtlAny*)valret)->value.o=obj;
+ }else{
+ *((Obj**)valret)=obj;
+ }
+ }
+ return !invalid;
}
- return !invalid;
}
return FALSE;
}
-static void extl_stack_push(lua_State *st, char spec, void *ptr)
+static void extl_to_any(ExtlAny *a, char type, void *ptr)
{
- if(spec=='i'){
- lua_pushnumber(st, *(int*)ptr);
- }else if(spec=='d'){
- lua_pushnumber(st, *(double*)ptr);
- }else if(spec=='b'){
- lua_pushboolean(st, *(bool*)ptr);
- }else if(spec=='o'){
- extl_push_obj(st, *(Obj**)ptr);
- }else if(spec=='s' || spec=='S'){
- lua_pushstring(st, *(char**)ptr);
- }else if(spec=='t' || spec=='f'){
- lua_rawgeti(st, LUA_REGISTRYINDEX, *(int*)ptr);
- }else{
- lua_pushnil(st);
+ if(type=='a'){
+ *a=*(ExtlAny*)ptr;
+ return;
+ }
+
+ a->type=type;
+
+ switch(type){
+ case 'i': a->value.i=*(int*)ptr; break;
+ case 'd': a->value.d=*(double*)ptr; break;
+ case 'b': a->value.b=*(bool*)ptr; break;
+ case 'o': a->value.o=*(Obj**)ptr; break;
+ case 's':
+ case 'S': a->value.s=*(char**)ptr; break;
+ case 't': a->value.t=*(ExtlTab*)ptr; break;
+ case 'f': a->value.f=*(ExtlFn*)ptr; break;
}
}
-static bool extl_stack_push_vararg(lua_State *st, char spec, va_list *argsp)
+static void extl_to_any_vararg(ExtlAny *a, char type, va_list *argsp)
{
- switch(spec){
- case 'i':
- lua_pushnumber(st, (double)va_arg(*argsp, int));
- break;
- case 'd':
- lua_pushnumber(st, va_arg(*argsp, double));
- break;
- case 'b':
- lua_pushboolean(st, va_arg(*argsp, bool));
- break;
- case 'o':
- extl_push_obj(st, va_arg(*argsp, Obj*));
- break;
- case 'S':
- case 's':
- lua_pushstring(st, va_arg(*argsp, char*));
- break;
- case 'f':
- case 't':
- lua_rawgeti(st, LUA_REGISTRYINDEX, va_arg(*argsp, int));
- break;
- default:
- return FALSE;
+ if(type=='a'){
+ *a=va_arg(*argsp, ExtlAny);
+ return;
+ }
+
+ a->type=type;
+
+ switch(type){
+ case 'i': a->value.i=va_arg(*argsp, int); break;
+ case 'd': a->value.d=va_arg(*argsp, double); break;
+ case 'b': a->value.b=va_arg(*argsp, bool); break;
+ case 'o': a->value.o=va_arg(*argsp, Obj*); break;
+ case 's':
+ case 'S': a->value.s=va_arg(*argsp, char*); break;
+ case 't': a->value.t=va_arg(*argsp, ExtlTab); break;
+ case 'f': a->value.f=va_arg(*argsp, ExtlFn); break;
}
+}
+
+
+static void extl_stack_pusha(lua_State *st, ExtlAny *a)
+{
+ switch(a->type){
+ case 'i': lua_pushnumber(st, a->value.i); break;
+ case 'd': lua_pushnumber(st, a->value.d); break;
+ case 'b': lua_pushboolean(st, a->value.b); break;
+ case 'o': extl_push_obj(st, a->value.o); break;
+ case 's':
+ case 'S': lua_pushstring(st, a->value.s); break;
+ case 't': lua_rawgeti(st, LUA_REGISTRYINDEX, a->value.t); break;
+ case 'f': lua_rawgeti(st, LUA_REGISTRYINDEX, a->value.f); break;
+ default: lua_pushnil(st);
+ }
+}
+
+
+static void extl_stack_push(lua_State *st, char spec, void *ptr)
+{
+ ExtlAny a;
+
+ extl_to_any(&a, spec, ptr);
+ extl_stack_pusha(st, &a);
+}
+
+
+static bool extl_stack_push_vararg(lua_State *st, char spec, va_list *argsp)
+{
+ ExtlAny a;
+
+ extl_to_any_vararg(&a, spec, argsp);
+ extl_stack_pusha(st, &a);
return TRUE;
}
enum{STRINGS_NONE, STRINGS_NONCONST, STRINGS_ALL};
-static void extl_free(void *ptr, char spec, int strings)
+static void extl_any_free(ExtlAny *a, int strings)
{
- if(((spec=='s' && strings!=STRINGS_NONE) ||
- (spec=='S' && strings==STRINGS_ALL)) && *(char**)ptr!=NULL){
- if(*(char**)ptr!=NULL)
- free(*(char**)ptr);
- *(char**)ptr=NULL;
- }else if(spec=='t'){
- extl_unref_table(*(ExtlTab*)ptr);
- }else if(spec=='f'){
- extl_unref_fn(*(ExtlFn*)ptr);
+ if((a->type=='s' && strings!=STRINGS_NONE) ||
+ (a->type=='S' && strings==STRINGS_ALL)){
+ if(a->value.s!=NULL)
+ free((char*)a->value.s);
+ }else if(a->type=='t'){
+ extl_unref_table(a->value.t);
+ }else if(a->type=='f'){
+ extl_unref_fn(a->value.f);
}
}
+static void extl_free(void *ptr, char spec, int strings)
+{
+ ExtlAny a;
+
+ extl_to_any(&a, spec, ptr);
+ extl_any_free(&a, strings);
+}
+
+
/*}}}*/
return extl_table_get(ref, 's', type, entry, valret);
}
+bool extl_table_gets_a(ExtlTab ref, const char *entry, ExtlAny *ret)
+{
+ return extl_table_do_gets(ref, entry, 'a', (void*)ret);
+}
+
bool extl_table_gets_o(ExtlTab ref, const char *entry, Obj **ret)
{
return extl_table_do_gets(ref, entry, 'o', (void*)ret);
return extl_table_get(ref, 'i', type, entry, valret);
}
+bool extl_table_geti_a(ExtlTab ref, int entry, ExtlAny *ret)
+{
+ return extl_table_do_geti(ref, entry, 'a', (void*)ret);
+}
+
bool extl_table_geti_o(ExtlTab ref, int entry, Obj **ret)
{
return extl_table_do_geti(ref, entry, 'o', (void*)ret);
return retval;
}
+bool extl_table_sets_a(ExtlTab ref, const char *entry, const ExtlAny *val)
+{
+ return extl_table_set(ref, 's', 'a', entry, val);
+}
bool extl_table_sets_o(ExtlTab ref, const char *entry, Obj *val)
{
}
+bool extl_table_seti_a(ExtlTab ref, int entry, const ExtlAny *val)
+{
+ return extl_table_set(ref, 'i', 'a', entry, val);
+}
+
bool extl_table_seti_o(ExtlTab ref, int entry, Obj *val)
{
return extl_table_set(ref, 'i', 'o', entry, val);
+/*}}}*/
+
+
+/*{{{ Table iteration */
+
+
+typedef struct{
+ ExtlTab ref;
+ ExtlIterFn *fn;
+ void *d;
+} IterP;
+
+
+int extl_table_iter_do(lua_State *st, IterP *par)
+{
+ lua_rawgeti(st, LUA_REGISTRYINDEX, par->ref);
+
+ lua_pushnil(st);
+
+ while(lua_next(st, -2)!=0){
+ ExtlAny k, v;
+
+ if(extl_stack_get(st, -2, 'a', FALSE, NULL, &k)){
+ bool ret=TRUE;
+ if(extl_stack_get(st, -1, 'a', FALSE, NULL, &v)){
+ ret=par->fn(k, v, par->d);
+ extl_any_free(&v, STRINGS_NONE);
+ }
+ extl_any_free(&k, STRINGS_NONE);
+ if(!ret)
+ return 0;
+ }
+
+ lua_pop(st, 1);
+ }
+
+ return 0;
+}
+
+
+void extl_table_iter(ExtlTab ref, ExtlIterFn *fn, void *d)
+{
+ IterP par;
+
+ par.ref=ref;
+ par.fn=fn;
+ par.d=d;
+
+ extl_cpcall(l_st, (ExtlCPCallFn*)extl_table_iter_do, &par);
+}
+
+
/*}}}*/
D(fprintf(stderr, "%s called\n", spec->name));
- if(!lua_checkstack(st, MAX_PARAMS+1)){
+ if(!lua_checkstack(st, MAX_PARAMS+1)){
extl_warn(TR("Stack full."));
return 0;
}
return 0;
}
- if(param.spec->fn==NULL){
+ if(!param.spec->registered){
extl_warn(TR("Called function has been unregistered."));
return 0;
}
lua_rawgeti(st, LUA_REGISTRYINDEX, data->table);
ind=-3;
}
-
- lua_pushstring(st, spec->name);
-
- spec2=lua_newuserdata(st, sizeof(ExtlExportedFnSpec));
- memcpy(spec2, spec, sizeof(ExtlExportedFnSpec));
+ lua_pushstring(st, spec->name);
- lua_getregistry(st);
- lua_pushvalue(st, -2); /* Get spec2 */
- lua_pushfstring(st, "luaextl_%s_%s_upvalue",
- data->cls, spec->name);
- lua_rawset_check(st, -3); /* Set registry.luaextl_fn_upvalue=spec2 */
- lua_pop(st, 1); /* Pop registry */
+ lua_pushlightuserdata(st, spec);
lua_pushcclosure(st, extl_l1_call_handler, 1);
+
lua_rawset_check(st, ind);
-
+
return TRUE;
}
®data)){
return FALSE;
}
+ spec[i].registered=TRUE;
}
return TRUE;
static bool extl_do_unregister_function(lua_State *st, RegData *data)
{
- ExtlExportedFnSpec *spec=data->spec, *spec2;
+ ExtlExportedFnSpec *spec=data->spec;
int ind=LUA_GLOBALSINDEX;
-
- lua_getregistry(st);
- lua_pushfstring(st, "luaextl_%s_%s_upvalue",
- data->cls, spec->name);
- lua_pushvalue(st, -1);
- lua_gettable(st, -3); /* Get registry.luaextl_fn_upvalue */
- spec2=lua_touserdata(st, -1);
-
- if(spec2==NULL)
- return FALSE;
-
- spec2->ispec=NULL;
- spec2->ospec=NULL;
- spec2->fn=NULL;
- spec2->name=NULL;
- spec2->l2handler=NULL;
-
- lua_pop(st, 1); /* Pop the upvalue */
- lua_pushnil(st);
- lua_rawset_check(st, -3); /* Clear registry.luaextl_fn_upvalue */
if(data->table!=LUA_NOREF){
lua_rawgeti(st, LUA_REGISTRYINDEX, data->table);
regdata.spec=&(spec[i]);
extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_unregister_function,
®data);
+ spec[i].registered=FALSE;
}
}