X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=libextl%2Fluaextl.c;fp=libextl%2Fluaextl.c;h=b58545d74937fe32808c0f391a819b58f8cacef5;hb=ae4260bb64817c11f9a7140324cd3e3ba113e297;hp=a2cc2b92759133a4d31fb7f87225a79bc52a3f69;hpb=de22e45179cb3bafa490294d31d47f361047a30a;p=ion3.git diff --git a/libextl/luaextl.c b/libextl/luaextl.c index a2cc2b9..b58545d 100644 --- a/libextl/luaextl.c +++ b/libextl/luaextl.c @@ -637,7 +637,7 @@ void extl_deinit() /*}}}*/ -/*{{{ StackĀ get/push -- all unsafe */ +/*{{{ Stack get/push -- all unsafe */ static bool extl_stack_get(lua_State *st, int pos, char type, @@ -649,11 +649,18 @@ 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'){ @@ -661,21 +668,23 @@ static bool extl_stack_get(lua_State *st, int pos, char type, 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'){ @@ -688,10 +697,9 @@ static bool extl_stack_get(lua_State *st, int pos, char type, 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); @@ -700,95 +708,141 @@ static bool extl_stack_get(lua_State *st, int pos, char type, 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; } @@ -802,21 +856,29 @@ static bool extl_stack_push_vararg(lua_State *st, char spec, va_list *argsp) 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); +} + + /*}}}*/ @@ -1019,6 +1081,11 @@ static bool extl_table_do_gets(ExtlTab ref, const char *entry, 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); @@ -1060,6 +1127,11 @@ static bool extl_table_do_geti(ExtlTab ref, int entry, char type, void *valret) 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); @@ -1165,6 +1237,10 @@ bool extl_table_set(ExtlTab ref, char itype, char type, ...) 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) { @@ -1202,6 +1278,11 @@ bool extl_table_sets_t(ExtlTab ref, const char *entry, ExtlTab 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); @@ -1290,6 +1371,58 @@ bool extl_table_cleari(ExtlTab ref, int entry) +/*}}}*/ + + +/*{{{ 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); +} + + /*}}}*/