diff -r 3769ba002fd1 -r f04ab0420512 libidav/davqlexec.c --- a/libidav/davqlexec.c Thu Feb 01 16:31:24 2018 +0100 +++ b/libidav/davqlexec.c Thu Feb 01 18:25:23 2018 +0100 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2016 Olaf Wintermann. All rights reserved. + * Copyright 2018 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -39,6 +39,106 @@ #include "session.h" #include "resource.h" +DavQLArgList* dav_ql_get_args(DavQLStatement *st, va_list ap) { + DavQLArgList *args = malloc(sizeof(DavQLArgList)); + if(!args) { + return NULL; + } + args->first = NULL; + + DavQLArg *cur = NULL; + UCX_FOREACH(elm, st->args) { + intptr_t type = (intptr_t)elm->data; + DavQLArg *arg = calloc(1, sizeof(DavQLArg)); + if(!arg) { + dav_ql_free_arglist(args); + return NULL; + } + arg->type = type; + switch(type) { + case 'd': { + arg->value.d = va_arg(ap, int); + break; + } + case 'u': { + arg->value.u = va_arg(ap, unsigned int); + break; + } + case 's': { + arg->value.s = va_arg(ap, char*); + break; + } + case 't': { + arg->value.t = va_arg(ap, time_t); + break; + } + default: { + free(arg); + dav_ql_free_arglist(args); + return NULL; + } + } + if(cur) { + cur->next = arg; + } else { + args->first = arg; + } + cur = arg; + } + args->current = args->first; + return args; +} + +void dav_ql_free_arglist(DavQLArgList *args) { + DavQLArg *arg = args->first; + while(arg) { + DavQLArg *next = arg->next; + free(arg); + arg = next; + } +} + +static DavQLArg* arglist_get(DavQLArgList *args) { + DavQLArg *a = args->current; + if(a) { + args->current = a->next; + } + return a; +} + +int dav_ql_getarg_int(DavQLArgList *args) { + DavQLArg *a = arglist_get(args); + if(a && a->type == 'd') { + return a->value.d; + } + return 0; +} + +unsigned int dav_ql_getarg_uint(DavQLArgList *args) { + DavQLArg *a = arglist_get(args); + if(a && a->type == 'u') { + return a->value.u; + } + return 0; +} + +char* dav_ql_getarg_str(DavQLArgList *args) { + DavQLArg *a = arglist_get(args); + if(a && a->type == 's') { + return a->value.s; + } + return ""; +} + +time_t dav_ql_getarg_time(DavQLArgList *args) { + DavQLArg *a = arglist_get(args); + if(a && a->type == 't') { + return a->value.t; + } + return 0; +} + + DavResult dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) { va_list ap; va_start(ap, st); @@ -66,7 +166,7 @@ return result; } -sstr_t dav_format_string(UcxAllocator *a, sstr_t fstr, va_list ap, davqlerror_t *error) { +sstr_t dav_format_string(UcxAllocator *a, sstr_t fstr, DavQLArgList *ap, davqlerror_t *error) { UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); int placeholder = 0; @@ -81,17 +181,17 @@ int err = 0; switch(c) { case 's': { - char *arg = va_arg(ap, char*); + char *arg = dav_ql_getarg_str(ap); ucx_buffer_puts(buf, arg); break; } case 'd': { - int arg = va_arg(ap, int); + int arg = dav_ql_getarg_int(ap); ucx_bprintf(buf, "%d", arg); break; } case 'u': { - unsigned int arg = va_arg(ap, unsigned int); + unsigned int arg = dav_ql_getarg_uint(ap); ucx_bprintf(buf, "%u", arg); break; } @@ -338,6 +438,12 @@ result.result = NULL; result.status = 1; + DavQLArgList *args = dav_ql_get_args(st, ap); + if(!args) { + return result; + } + ucx_mempool_reg_destr(mp, args, (ucx_destructor)dav_ql_free_arglist); + int isallprop; UcxBuffer *rqbuf = fieldlist2propfindrequest(sn, mp, st->fields, &isallprop); if(!rqbuf) { @@ -356,7 +462,7 @@ sn->context, mp->allocator, field->expr, - ap); + args); if(!code) { // TODO: set error string return result; @@ -386,16 +492,17 @@ // get path string davqlerror_t error; - sstr_t path = dav_format_string(mp->allocator, st->path, ap, &error); + sstr_t path = dav_format_string(mp->allocator, st->path, args, &error); if(error) { // TODO: cleanup ucx_mempool_destroy(mp); return result; } - int depth = st->depth == DAV_DEPTH_PLACEHOLDER ? va_arg(ap, int) : st->depth; + int depth = st->depth == DAV_DEPTH_PLACEHOLDER ? + dav_ql_getarg_int(args) : st->depth; - UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, ap); + UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, args); if(st->where && !where) { // TODO: cleanup ucx_mempool_destroy(mp); @@ -627,7 +734,7 @@ return 1; } -static int add_cmd(DavContext *ctx, UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, va_list ap) { +static int add_cmd(DavContext *ctx, UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, DavQLArgList *ap) { if(!expr) { return 0; } @@ -643,7 +750,7 @@ case DAVQL_NUMBER: { cmd.type = DAVQL_CMD_INT; if(src.ptr[0] == '%') { - cmd.data.integer = va_arg(ap, int); + cmd.data.integer = dav_ql_getarg_int(ap); } else if(util_strtoint(src.ptr, &cmd.data.integer)) { ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); } else { @@ -662,7 +769,7 @@ case DAVQL_TIMESTAMP: { if(src.ptr[0] == '%') { cmd.type = DAVQL_CMD_TIMESTAMP; - cmd.data.timestamp = va_arg(ap, time_t); + cmd.data.timestamp = dav_ql_getarg_time(ap); ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); } else { // error @@ -886,7 +993,7 @@ return numcmd; } -UcxBuffer* dav_compile_expr(DavContext *ctx, UcxAllocator *a, DavQLExpression *lexpr, va_list ap) { +UcxBuffer* dav_compile_expr(DavContext *ctx, UcxAllocator *a, DavQLExpression *lexpr, DavQLArgList *ap) { UcxBuffer *bcode = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND); if(!bcode) { return NULL;