Sat, 30 May 2015 21:43:36 +0200
added expression executor prototype
dav/main.c | file | annotate | diff | comparison | revisions | |
libidav/davqlexec.c | file | annotate | diff | comparison | revisions | |
libidav/davqlexec.h | file | annotate | diff | comparison | revisions |
--- a/dav/main.c Sat May 30 14:14:36 2015 +0200 +++ b/dav/main.c Sat May 30 21:43:36 2015 +0200 @@ -55,11 +55,12 @@ #include <libidav/davqlexec.h> void test() { DavQLStatement *stmt = dav_parse_statement(S( - "get * from / where name unlike '%d.%s'")); + "get * from / where lastmodified > 12")); DavSession *sn = dav_session_new(ctx, "http://test/"); dav_statement_exec(sn, stmt, 123, "txt"); - dav_debug_statement(stmt); + + //dav_debug_statement(stmt); dav_free_statement(stmt); }
--- 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: {
--- a/libidav/davqlexec.h Sat May 30 14:14:36 2015 +0200 +++ b/libidav/davqlexec.h Sat May 30 21:43:36 2015 +0200 @@ -123,6 +123,7 @@ UcxBuffer* dav_compile_expr(UcxAllocator *a, DavQLExpression *lexpr, va_list ap); +int dav_exec_expr(UcxBuffer *bcode, DavResource *res, DavQLStackObj *result); void print_bytecode(UcxBuffer *bcode);