]> git.decadent.org.uk Git - ion3.git/blobdiff - libextl/luaextl.c
[svn-upgrade] Integrating new upstream version, ion3 (20070506)
[ion3.git] / libextl / luaextl.c
index a2cc2b92759133a4d31fb7f87225a79bc52a3f69..b58545d74937fe32808c0f391a819b58f8cacef5 100644 (file)
@@ -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);
+}
+
+
 /*}}}*/