libidav/davqlexec.c

changeset 126
b156cae29e65
parent 124
41939c8f3f9c
child 127
7072a2b4ae35
--- a/libidav/davqlexec.c	Sat May 30 14:14:36 2015 +0200
+++ b/libidav/davqlexec.c	Sat May 30 21:43:36 2015 +0200
@@ -134,7 +134,15 @@
     
     UcxBuffer *bcode = dav_compile_expr(mp->allocator, st->where, ap);
     
-    print_bytecode(bcode);
+    //print_bytecode(bcode);
+    
+    DavResource *res = dav_resource_new(sn, "/test.txt");
+    dav_set_property_ns(res, "DAV:", "string", "value");
+    dav_set_property_ns(res, "DAV:", "integer", "1337");
+    res->lastmodified = 100;
+    
+    DavQLStackObj result;
+    dav_exec_expr(bcode, res, &result);
 }
 
 static int count_func_args(DavQLExpression *expr) {
@@ -151,6 +159,20 @@
     return count;
 }
 
+static int identifier2propname(UcxAllocator *a, sstr_t id, DavPropName *propname) {
+    ssize_t count;
+    sstr_t *s = sstrsplit_a(a, id, S(":"), &count);
+    if(count == 2) {
+        sstr_t ns = s[0];
+        sstr_t name = s[1];
+        propname->ns = ns.ptr;
+        propname->name = name.ptr;
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
 static int add_cmd(UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, va_list ap) {
     if(!expr) {
         return 0;
@@ -197,8 +219,10 @@
             cmd.type = DAVQL_CMD_RES_IDENTIFIER;
             if(propertyname.length > 0) {
                 cmd.type = DAVQL_CMD_PROP_IDENTIFIER;
-                
-                // TODO
+                if(identifier2propname(a, src, &cmd.data.property)) {
+                    // error
+                    return -1;
+                }
             } else if(!sstrcmp(src, S("name"))) {
                 cmd.data.resprop = DAVQL_RES_NAME;
             } else if(!sstrcmp(src, S("path"))) {
@@ -215,6 +239,15 @@
                 cmd.data.resprop = DAVQL_RES_LASTMODIFIED;
             } else if(!sstrcmp(src, S("iscollection"))) {
                 cmd.data.resprop = DAVQL_RES_ISCOLLECTION;
+            } else if(!sstrcmp(src, S("true"))) {
+                cmd.type = DAVQL_CMD_INT;
+                cmd.data.integer = 1;
+            } else if(!sstrcmp(src, S("false"))) {
+                cmd.type = DAVQL_CMD_INT;
+                cmd.data.integer = 0;
+            } else {
+                // error, unknown identifier
+                return -1;
             }
             ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
             break;
@@ -288,7 +321,7 @@
                     break;
                 }
                 case DAVQL_LAND: {
-                    cmd.type = DAVQL_CMD_OP_LOGICAL_NOT;
+                    cmd.type = DAVQL_CMD_OP_LOGICAL_AND;
                     ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
@@ -409,6 +442,253 @@
     return bcode;
 }
 
+int dav_exec_expr(UcxBuffer *bcode, DavResource *res, DavQLStackObj *result) {
+    size_t count = bcode->pos / sizeof(DavQLCmd);
+    DavQLCmd *cmds = (DavQLCmd*)bcode->space;
+    
+    // create execution stack
+    size_t stsize = 64;
+    size_t stpos = 0;
+    DavQLStackObj *stack = calloc(stsize, sizeof(DavQLStackObj));
+#define DAVQL_PUSH(obj) \
+        if(stpos == stsize) { \
+            stsize += 64; \
+            stack = realloc(stack, stsize * sizeof(DavQLStackObj)); \
+        } \
+        stack[stpos++] = obj;
+#define DAVQL_POP() stack[--stpos]
+    
+    DavQLStackObj obj;
+    for(size_t i=0;i<count;i++) {
+        DavQLCmd cmd = cmds[i];
+        switch(cmd.type) {
+            case DAVQL_CMD_INT: {
+                printf("int %lld\n", cmd.data.integer);
+                obj.type = 0;
+                obj.length = 0;
+                obj.data.integer = cmd.data.integer;
+                DAVQL_PUSH(obj);
+                break;
+            }
+            case DAVQL_CMD_STRING: {
+                printf("string \"%.*s\"\n", cmd.data.string.length, cmd.data.string.ptr);
+                obj.type = 1;
+                obj.length = cmd.data.string.length;
+                obj.data.string = cmd.data.string.ptr;
+                DAVQL_PUSH(obj);
+                break;
+            }
+            case DAVQL_CMD_TIMESTAMP: {
+                printf("timestamp %d\n", cmd.data.timestamp);
+                obj.type = 0;
+                obj.length = 0;
+                obj.data.integer = cmd.data.timestamp;
+                DAVQL_PUSH(obj);
+                break;
+            }
+            case DAVQL_CMD_RES_IDENTIFIER: {
+                char *rid[8] = {"name", "path", "href", "contentlength", "contenttype", "creationdate", "lastmodified", "iscollection"};
+                printf("resprop %s\n", rid[cmd.data.resprop]);
+                switch(cmd.data.resprop) {
+                    case DAVQL_RES_NAME: {
+                        obj.type = 1;
+                        obj.length = strlen(res->name);
+                        obj.data.string = res->name;
+                        break;
+                    }
+                    case DAVQL_RES_PATH: {
+                        obj.type = 1;
+                        obj.length = strlen(res->path);
+                        obj.data.string = res->path;
+                        break;
+                    }
+                    case DAVQL_RES_HREF: {
+                        obj.type = 1;
+                        obj.length = strlen(res->href);
+                        obj.data.string = res->href;
+                        break;
+                    }
+                    case DAVQL_RES_CONTENTLENGTH: {
+                        obj.type = 0;
+                        obj.length = 0;
+                        obj.data.integer = res->contentlength;
+                        break;
+                    }
+                    case DAVQL_RES_CONTENTTYPE: {
+                        obj.type = 1;
+                        obj.length = strlen(res->contenttype);
+                        obj.data.string = res->contenttype;
+                        break;
+                    }
+                    case DAVQL_RES_CREATIONDATE: {
+                        obj.type = 0;
+                        obj.length = 0;
+                        obj.data.integer = res->creationdate;
+                        break;
+                    }
+                    case DAVQL_RES_LASTMODIFIED: {
+                        obj.type = 0;
+                        obj.length = 0;
+                        obj.data.integer = res->lastmodified;
+                        break;
+                    }
+                    case DAVQL_RES_ISCOLLECTION: {
+                        obj.type = 0;
+                        obj.length = 0;
+                        obj.data.integer = res->iscollection;
+                        break;
+                    }
+                }
+                DAVQL_PUSH(obj);
+                break;
+            }
+            case DAVQL_CMD_PROP_IDENTIFIER: {
+                printf("property %s:%s\n", cmd.data.property.ns, cmd.data.property.name);
+                char *value = dav_get_property_ns(res, cmd.data.property.ns, cmd.data.property.name);
+                obj.type = 1;
+                obj.length = value ? strlen(value) : 0;
+                obj.data.string = value;
+                DAVQL_PUSH(obj);
+                break;
+            }
+            case DAVQL_CMD_OP_UNARY_ADD: {
+                printf("uadd\n");
+                break;
+            }
+            case DAVQL_CMD_OP_UNARY_SUB: {
+                printf("usub\n");
+                break;
+            }
+            case DAVQL_CMD_OP_UNARY_NEG: {
+                printf("uneg\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_ADD: {
+                printf("add\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_SUB: {
+                printf("sub\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_MUL: {
+                printf("mul\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_DIV: {
+                printf("div\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_AND: {
+                printf("and\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_OR: {
+                printf("or\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_XOR: {
+                printf("xor\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_NOT: {
+                printf("not\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_AND: {
+                printf("land\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_OR_L: {
+                printf("or_l %d\n", cmd.data.integer);
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_OR: {
+                printf("or\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_XOR: {
+                printf("lxor\n");
+                break;
+            }
+            case DAVQL_CMD_OP_EQ: {
+                printf("eq\n");
+                break;
+            }
+            case DAVQL_CMD_OP_NEQ: {
+                printf("neq\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LT: {
+                printf("lt\n");
+                break;
+            }
+            case DAVQL_CMD_OP_GT: {
+                printf("gt\n");
+                DavQLStackObj obj2 = DAVQL_POP();
+                DavQLStackObj obj1 = DAVQL_POP();
+                // result
+                obj.type = 0;
+                obj.length = 0;
+                
+                int64_t int1;
+                int64_t int2;
+                int isint = 1;
+                if(obj1.type == 0) {
+                    int1 = obj1.data.integer;
+                } else {
+                    isint = util_strtoint(obj1.data.string, &int1);
+                }
+                if(isint) {
+                    if(obj2.type == 0) {
+                        int2 = obj2.data.integer;
+                    } else {
+                        isint = util_strtoint(obj2.data.string, &int2);
+                    }
+                    if(isint) {
+                        obj.data.integer = int1 > int2;
+                    }
+                }
+                
+                // string compare
+                // TODO
+                DAVQL_PUSH(obj);
+                break;
+            }
+            case DAVQL_CMD_OP_LE: {
+                printf("le\n");
+                break;
+            }
+            case DAVQL_CMD_OP_GE: {
+                printf("ge\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LIKE: {
+                printf("like\n");
+                break;
+            }
+            case DAVQL_CMD_OP_UNLIKE: {
+                printf("unlike\n");
+                break;
+            }
+            case DAVQL_CMD_CALL: {
+                printf("call %x\n", cmd.data.func);
+                break;
+            }
+        }
+    }
+    
+    for(int i=0;i<stpos;i++) {
+        DavQLStackObj obj = stack[i];
+        if(obj.type == 0) {
+            printf("stack: int=%lld\n", obj.data.integer);
+        } else {
+            printf("stack: string=\"%.*s\"\n", obj.length, obj.data.string);
+        }
+    }
+    return 0;
+}
+
 
 void print_bytecode(UcxBuffer *bcode) {
     bcode->pos = 0;
@@ -416,7 +696,7 @@
     while(ucx_buffer_read(&cmd, sizeof(DavQLCmd), 1, bcode) == 1) {
         switch(cmd.type) {
             case DAVQL_CMD_INT: {
-                printf("int %ll\n", cmd.data.integer);
+                printf("int %lld\n", cmd.data.integer);
                 break;
             }
             case DAVQL_CMD_STRING: {

mercurial