libidav/davqlexec.c

changeset 365
f04ab0420512
parent 361
b6f2462ee055
child 387
92f8a2a243fc
--- 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;

mercurial