libidav/davqlparser.c

changeset 747
efbd59642577
parent 374
38ae05d46f9a
--- a/libidav/davqlparser.c	Sun Apr 16 14:12:24 2023 +0200
+++ b/libidav/davqlparser.c	Fri Apr 21 21:25:32 2023 +0200
@@ -27,7 +27,9 @@
  */
 
 #include "davqlparser.h"
-#include <ucx/utils.h>
+#include <cx/utils.h>
+#include <cx/linked_list.h>
+#include <cx/printf.h>
 #include <string.h>
 #include <stdio.h>
 #include <ctype.h>
@@ -93,9 +95,9 @@
 static void dav_debug_ql_fnames_print(DavQLStatement *stmt) {
     if (stmt->fields) {
         printf("Field names: ");
-        UCX_FOREACH(field, stmt->fields) {
-            DavQLField *f = field->data;
-            printf("%.*s, ", sfmtarg(f->name));
+        CxIterator i = cxListIterator(stmt->fields);
+        cx_foreach(DavQLField *, f, i) {
+            printf("%.*s, ", (int)f->name.length, f->name.ptr);
         }
         printf("\b\b  \b\b\n");
     }
@@ -103,10 +105,10 @@
 
 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) {
     // Basic information
-    size_t fieldcount = ucx_list_size(stmt->fields);
+    size_t fieldcount = stmt->fields ? stmt->fields->size : 0;
     int specialfield = 0;
-    if (stmt->fields) {
-        DavQLField* firstfield = (DavQLField*)stmt->fields->data;
+    if (stmt->fields && stmt->fields->size > 0) {
+        DavQLField* firstfield = (DavQLField*)cxListAt(stmt->fields, 0);
         if (firstfield->expr->type == DAVQL_IDENTIFIER) {
             switch (firstfield->expr->srctext.ptr[0]) {
             case '*': specialfield = 1; break;
@@ -118,14 +120,14 @@
         fieldcount--;
     }
     printf("Statement: %.*s\nType: %s\nField count: %zu %s\n",
-        sfmtarg(stmt->srctext),
+        (int)stmt->srctext.length, stmt->srctext.ptr,
         _map_querytype(stmt->type),
         fieldcount,
         _map_specialfield(specialfield));
     
     dav_debug_ql_fnames_print(stmt);
     printf("Path: %.*s\nHas where clause: %s\n",
-        sfmtarg(stmt->path),
+        (int)stmt->path.length, stmt->path.ptr,
         stmt->where ? "yes" : "no");
     
     // WITH attributes
@@ -140,11 +142,11 @@
     // order by clause
     printf("Order by: ");
     if (stmt->orderby) {
-        UCX_FOREACH(crit, stmt->orderby) {
-            DavQLOrderCriterion *critdata = crit->data;
-            printf("%.*s %s%s", sfmtarg(critdata->column->srctext),
+        CxIterator i = cxListIterator(stmt->orderby);
+        cx_foreach(DavQLOrderCriterion*, critdata, i) {
+            printf("%.*s %s%s", (int)critdata->column->srctext.length, critdata->column->srctext.ptr,
                 critdata->descending ? "desc" : "asc",
-                crit->next ? ", " : "\n");
+                i.index+1 < stmt->orderby->size ? ", " : "\n");
         }
     } else {
         printf("nothing\n");
@@ -168,7 +170,7 @@
 
 static void dav_debug_ql_expr_print(DavQLExpression *expr) {
     if (dav_debug_ql_expr_selected(expr)) {
-        sstr_t empty = ST("(empty)");
+        cxstring empty = CX_STR("(empty)");
         printf(
             "Text: %.*s\nType: %s\nOperator: %s\n",
             sfmtarg(expr->srctext),
@@ -280,7 +282,7 @@
     }
     
     DavQLExpression *examineexpr = NULL;
-    UcxList *examineelem = NULL;
+    CxList *examineelem = NULL;
     int examineclause = 0;
     
     while(1) {
@@ -294,8 +296,8 @@
         case DQLD_CMD_F:
             examineclause = DQLD_CMD_F;
             examineelem = stmt->fields;
-            if (stmt->fields) {
-                DavQLField* field = ((DavQLField*)stmt->fields->data);
+            if (stmt->fields && stmt->fields->size > 0) {
+                DavQLField* field = cxListAt(stmt->fields, 0);
                 examineexpr = field->expr;
                 dav_debug_ql_field_print(field);
             } else {
@@ -310,14 +312,16 @@
         case DQLD_CMD_O:
             examineclause = DQLD_CMD_O;
             examineelem = stmt->orderby;
-            examineexpr = stmt->orderby ?
-                ((DavQLOrderCriterion*)stmt->orderby->data)->column : NULL;
+            examineexpr = stmt->orderby && stmt->orderby->size > 0 ?
+                ((DavQLOrderCriterion*)cxListAt(stmt->orderby, 0))->column : NULL;
             dav_debug_ql_expr_print(examineexpr);
             break;
         case DQLD_CMD_N:
         case DQLD_CMD_P:
+            printf("TODO: port code to ucx 3\n");
+            /*
             if (examineelem) {
-                UcxList *newelem = (cmd == DQLD_CMD_N ?
+                CxList *newelem = (cmd == DQLD_CMD_N ?
                     examineelem->next : examineelem->prev);
                 if (newelem) {
                     examineelem = newelem;
@@ -338,6 +342,7 @@
             } else {
                 printf("Currently not examining an expression list.\n");
             }
+            */
             break;
         case DQLD_CMD_L:
             if (dav_debug_ql_expr_selected(examineexpr)) {
@@ -411,28 +416,28 @@
 #define _error_invalid_string "string expected " _error_context
 #define _error_invalid_order_criterion "invalid order criterion " _error_context
 
-#define token_sstr(token) (((DavQLToken*)(token)->data)->value)
+#define token_sstr(token) ((token)->value)
 
 static void dav_error_in_context(int errorcode, const char *errormsg,
-        DavQLStatement *stmt, UcxList *token) {
+        DavQLStatement *stmt, DavQLToken *token) {
     
     // we try to achieve two things: get as many information as possible
     // and recover the concrete source string (and not the token strings)
-    sstr_t emptystring = ST("");
-    sstr_t prev = token->prev ? (token->prev->prev ?
+    cxstring emptystring = CX_STR("");
+    cxstring prev = token->prev ? (token->prev->prev ?
         token_sstr(token->prev->prev) : token_sstr(token->prev))
         : emptystring;
-    sstr_t tokenstr = token_sstr(token);
-    sstr_t next = token->next ? (token->next->next ?
+    cxstring tokenstr = token_sstr(token);
+    cxstring next = token->next ? (token->next->next ?
         token_sstr(token->next->next) : token_sstr(token->next))
         : emptystring;
     
     int lp = prev.length == 0 ? 0 : tokenstr.ptr-prev.ptr;
-    char *pn = tokenstr.ptr + tokenstr.length;
+    const char *pn = tokenstr.ptr + tokenstr.length;
     int ln = next.ptr+next.length - pn;
     
     stmt->errorcode = errorcode;
-    stmt->errormessage = ucx_sprintf(errormsg,
+    stmt->errormessage = cx_asprintf(errormsg,
         lp, prev.ptr,
         sfmtarg(tokenstr),
         ln, pn).ptr;
@@ -448,30 +453,18 @@
 #define dqlsec_mallocz(stmt, ptr, type) \
         dqlsec_alloc_failed(ptr = calloc(1, sizeof(type)), stmt)
 
-#define dqlsec_list_append_or_free(stmt, list, data)            \
-    do {                                                        \
-        UcxList *_dqlsecbak_ = list;                            \
-        list = ucx_list_append(list, data);                     \
-        if (!list) {                                            \
-            free(data);                                         \
-            data = NULL;                                        \
-            (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;      \
-            list = _dqlsecbak_;                                 \
-            return 0;                                           \
-        }                                                       \
-    } while(0)
 
 // special symbols are single tokens - the % sign MUST NOT be a special symbol
 static const char *special_token_symbols = ",()+-*/&|^~=!<>";
 
 static _Bool iskeyword(DavQLToken *token) {
-    sstr_t keywords[] ={ST("select"), ST("set"), ST("from"), ST("at"), ST("as"),
-        ST("where"), ST("anywhere"), ST("like"), ST("unlike"), ST("and"),
-        ST("or"), ST("not"), ST("xor"), ST("with"), ST("infinity"),
-        ST("order"), ST("by"), ST("asc"), ST("desc")
+    cxstring keywords[] ={CX_STR("select"), CX_STR("set"), CX_STR("from"), CX_STR("at"), CX_STR("as"),
+        CX_STR("where"), CX_STR("anywhere"), CX_STR("like"), CX_STR("unlike"), CX_STR("and"),
+        CX_STR("or"), CX_STR("not"), CX_STR("xor"), CX_STR("with"), CX_STR("infinity"),
+        CX_STR("order"), CX_STR("by"), CX_STR("asc"), CX_STR("desc")
     };
-    for (int i = 0 ; i < sizeof(keywords)/sizeof(sstr_t) ; i++) {
-        if (!sstrcasecmp(token->value, keywords[i])) {
+    for (int i = 0 ; i < sizeof(keywords)/sizeof(cxstring) ; i++) {
+        if (!cx_strcasecmp(token->value, keywords[i])) {
             return 1;
         }
     }
@@ -479,18 +472,45 @@
 }
 
 static _Bool islongoperator(DavQLToken *token) {
-    sstr_t operators[] = {ST("and"), ST("or"), ST("not"), ST("xor"),
-        ST("like"), ST("unlike")
+    cxstring operators[] = {CX_STR("and"), CX_STR("or"), CX_STR("not"), CX_STR("xor"),
+        CX_STR("like"), CX_STR("unlike")
     };
-    for (int i = 0 ; i < sizeof(operators)/sizeof(sstr_t) ; i++) {
-        if (!sstrcasecmp(token->value, operators[i])) {
+    for (int i = 0 ; i < sizeof(operators)/sizeof(cxstring) ; i++) {
+        if (!cx_strcasecmp(token->value, operators[i])) {
             return 1;
         }
     }
     return 0;
 }
 
-static UcxList* dav_parse_add_token(UcxList *tokenlist, DavQLToken *token) {
+static int dav_stmt_add_field(DavQLStatement *stmt, DavQLField *field) {
+    if(!stmt->fields) {
+        stmt->fields = cxLinkedListCreateSimple(CX_STORE_POINTERS);
+        if(!stmt->fields) {
+            stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
+            return 1;
+        }
+    }
+    
+    if(cxListAdd(stmt->fields, field)) {
+        stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
+            return 1;
+    }
+    
+    return 0;
+}
+    
+
+static void tokenlist_free(DavQLToken *tokenlist) {
+    DavQLToken *token = tokenlist;
+    while(token) {
+        DavQLToken *next = token->next;
+        free(token);
+        token = next;
+    }
+}
+
+static int dav_parse_add_token(DavQLToken **begin, DavQLToken **end, DavQLToken *token) {
     
     // determine token class (order of if-statements is very important!)
     char firstchar = token->value.ptr[0];
@@ -541,24 +561,22 @@
         }
     }
     
-    
-    UcxList *ret = ucx_list_append(tokenlist, token);
-    if (ret) {
-        return ret;
-    } else {
-        ucx_list_free(tokenlist);
-        return NULL;
-    }
+    cx_linked_list_add((void**)begin, (void**)end, offsetof(DavQLToken, prev), offsetof(DavQLToken, next), token);
+    return 0;
 }
 
-static UcxList* dav_parse_tokenize(sstr_t src) {
-#define alloc_token() do {token = malloc(sizeof(DavQLToken));\
-        if(!token) {ucx_list_free(tokens); return NULL;}} while(0)
-#define add_token() do {tokens = dav_parse_add_token(tokens, token); \
-        if(!tokens) {return NULL;}} while(0)
-    UcxList *tokens = NULL;
+
+
+static DavQLToken* dav_parse_tokenize(cxstring src) {
+#define alloc_token() do {token = calloc(1, sizeof(DavQLToken));\
+        if(!token) {tokenlist_free(tokens_begin); return NULL;}} while(0)
+#define add_token() if(dav_parse_add_token(&tokens_begin, &tokens_end, token)) return NULL;
+    
+    DavQLToken *tokens_begin = NULL;
+    DavQLToken *tokens_end = NULL;
     
     DavQLToken *token = NULL;
+    
     char insequence = '\0';
     for (size_t i = 0 ; i < src.length ; i++) {
         // quoted strings / identifiers are a single token
@@ -628,14 +646,10 @@
     
     alloc_token();
     token->tokenclass = DAVQL_TOKEN_END;
-    token->value = S("");
-    UcxList *ret = ucx_list_append(tokens, token);
-    if (ret) {
-        return ret;
-    } else {
-        ucx_list_free(tokens);
-        return NULL;
-    }
+    token->value = CX_STR("");
+    
+    cx_linked_list_add((void**)&tokens_begin, (void**)&tokens_end, offsetof(DavQLToken, prev), offsetof(DavQLToken, next), token);
+    return tokens_begin;
 #undef alloc_token
 #undef add_token
 }
@@ -661,18 +675,17 @@
     if (crit->column) { // do it null-safe though column is expected to be set
         dav_free_expression(crit->column);
     }
-    free(crit);
 }
 
 #define token_is(token, expectedclass) (token && \
-    (((DavQLToken*)(token)->data)->tokenclass == expectedclass))
+    (token->tokenclass == expectedclass))
 
 #define tokenvalue_is(token, expectedvalue) (token && \
-    !sstrcasecmp(((DavQLToken*)(token)->data)->value, S(expectedvalue)))
+    !cx_strcasecmp(token->value, cx_str(expectedvalue)))
 
-typedef int(*exprparser_f)(DavQLStatement*,UcxList*,DavQLExpression*);
+typedef int(*exprparser_f)(DavQLStatement*,DavQLToken*,DavQLExpression*);
 
-static int dav_parse_binary_expr(DavQLStatement* stmt, UcxList* token,
+static int dav_parse_binary_expr(DavQLStatement* stmt, DavQLToken* token,
         DavQLExpression* expr, exprparser_f parseL, char* opc, int* opv,
         exprparser_f parseR) {
     
@@ -692,7 +705,7 @@
         return 0;
     }
     total_consumed += consumed;
-    token = ucx_list_get(token, consumed);
+    token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
 
     char *op;
     if (token_is(token, DAVQL_TOKEN_OPERATOR) &&
@@ -731,15 +744,20 @@
     return total_consumed;
 }
 
-static void dav_add_fmt_args(DavQLStatement *stmt, sstr_t str) {
+static void fmt_args_add(DavQLStatement *stmt, void *data) {
+    if(!stmt->args) {
+        stmt->args = cxLinkedListCreateSimple(CX_STORE_POINTERS);
+    }
+    cxListAdd(stmt->args, data);
+}
+
+static void dav_add_fmt_args(DavQLStatement *stmt, cxstring str) {
     int placeholder = 0;
     for (size_t i=0;i<str.length;i++) {
         char c = str.ptr[i];
         if (placeholder) {
             if (c != '%') {
-                stmt->args = ucx_list_append(
-                        stmt->args,
-                        (void*)(intptr_t)c);
+                fmt_args_add(stmt, (void*)(intptr_t)c);
             }
             placeholder = 0;
         } else if (c == '%') {
@@ -748,7 +766,7 @@
     }
 }
 
-static int dav_parse_literal(DavQLStatement* stmt, UcxList* token,
+static int dav_parse_literal(DavQLStatement* stmt, DavQLToken* token,
         DavQLExpression* expr) {
     
     expr->srctext = token_sstr(token);
@@ -772,7 +790,7 @@
             return 0;
         }
         // add fmtspec type to query arg list
-        stmt->args = ucx_list_append(stmt->args, (void*)(intptr_t)expr->srctext.ptr[1]);
+        fmt_args_add(stmt, (void*)(intptr_t)expr->srctext.ptr[1]);
     } else {
         return 0;
     }
@@ -781,10 +799,10 @@
 }
 
 // forward declaration
-static int dav_parse_expression(DavQLStatement* stmt, UcxList* token,
+static int dav_parse_expression(DavQLStatement* stmt, DavQLToken* token,
         DavQLExpression* expr);
 
-static int dav_parse_arglist(DavQLStatement* stmt, UcxList* token,
+static int dav_parse_arglist(DavQLStatement* stmt, DavQLToken* token,
         DavQLExpression* expr) {
     
     expr->srctext.ptr = token_sstr(token).ptr;
@@ -796,7 +814,7 @@
     // RULE:    Expression, {",", Expression};
     DavQLExpression *arglist = expr;
     DavQLExpression arg;
-    char *lastchar = expr->srctext.ptr;
+    const char *lastchar = expr->srctext.ptr;
     int consumed;
     do {
         memset(&arg, 0, sizeof(DavQLExpression));
@@ -804,7 +822,7 @@
         if (consumed) {
             lastchar = arg.srctext.ptr + arg.srctext.length;
             total_consumed += consumed;
-            token = ucx_list_get(token, consumed);
+            token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
             // look ahead for a comma
             if (token_is(token, DAVQL_TOKEN_COMMA)) {
                 total_consumed++;
@@ -837,7 +855,7 @@
     return total_consumed;
 }
 
-static int dav_parse_funccall(DavQLStatement* stmt, UcxList* token,
+static int dav_parse_funccall(DavQLStatement* stmt, DavQLToken* token,
         DavQLExpression* expr) {
     
     // RULE:    Identifier, "(", ArgumentList, ")";
@@ -861,7 +879,7 @@
             return 2;
         }
         if (argtokens) {
-            token = ucx_list_get(token, argtokens);
+            token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), argtokens);
             dqlsec_malloc(stmt, expr->right, DavQLExpression);
             memcpy(expr->right, &arg, sizeof(DavQLExpression));
         } else {
@@ -881,10 +899,10 @@
     }
 }
 
-static int dav_parse_unary_expr(DavQLStatement* stmt, UcxList* token,
+static int dav_parse_unary_expr(DavQLStatement* stmt, DavQLToken* token,
         DavQLExpression* expr) {
     
-    UcxList *firsttoken = token; // save for srctext recovery
+    DavQLToken *firsttoken = token; // save for srctext recovery
     
     DavQLExpression* atom = expr;
     int total_consumed = 0;
@@ -923,7 +941,7 @@
                 _error_invalid_expr, stmt, token);
             return 0;
         }
-        token = ucx_list_get(token, consumed);
+        token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
         total_consumed += consumed;
         if (token_is(token, DAVQL_TOKEN_CLOSEP)) {
             token = token->next; total_consumed++;
@@ -951,8 +969,8 @@
     // recover source text
     expr->srctext.ptr = token_sstr(firsttoken).ptr;
     if (total_consumed > 0) {
-        sstr_t lasttoken =
-            token_sstr(ucx_list_get(firsttoken, total_consumed-1));
+        cxstring lasttoken =
+            token_sstr((DavQLToken*)cx_linked_list_at(token, 0, offsetof(DavQLToken, next), total_consumed-1));
         expr->srctext.length =
             lasttoken.ptr - expr->srctext.ptr + lasttoken.length;
     } else {
@@ -964,7 +982,7 @@
     return total_consumed;
 }
 
-static int dav_parse_bitexpr(DavQLStatement* stmt, UcxList* token,
+static int dav_parse_bitexpr(DavQLStatement* stmt, DavQLToken* token,
         DavQLExpression* expr) {
     
     return dav_parse_binary_expr(stmt, token, expr,
@@ -973,7 +991,7 @@
         dav_parse_bitexpr);
 }
 
-static int dav_parse_multexpr(DavQLStatement* stmt, UcxList* token,
+static int dav_parse_multexpr(DavQLStatement* stmt, DavQLToken* token,
         DavQLExpression* expr) {
     
     return dav_parse_binary_expr(stmt, token, expr,
@@ -982,7 +1000,7 @@
         dav_parse_multexpr);
 }
 
-static int dav_parse_expression(DavQLStatement* stmt, UcxList* token,
+static int dav_parse_expression(DavQLStatement* stmt, DavQLToken* token,
         DavQLExpression* expr) {
     
     return dav_parse_binary_expr(stmt, token, expr,
@@ -991,7 +1009,7 @@
         dav_parse_expression);
 }
 
-static int dav_parse_named_field(DavQLStatement *stmt, UcxList *token,
+static int dav_parse_named_field(DavQLStatement *stmt, DavQLToken *token,
         DavQLField *field) {
     int total_consumed = 0, consumed;
     
@@ -1010,7 +1028,7 @@
         return 0;
     }
 
-    token = ucx_list_get(token, consumed);
+    token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
     total_consumed += consumed;    
     
     if (token_is(token, DAVQL_TOKEN_KEYWORD) && tokenvalue_is(token, "as")) {
@@ -1034,13 +1052,16 @@
     }
 }
 
-static int dav_parse_fieldlist(DavQLStatement *stmt, UcxList *token) {
+static int dav_parse_fieldlist(DavQLStatement *stmt, DavQLToken *token) {
     
     // RULE:    "-"
     if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "-")) {
         DavQLField *field;
         dqlsec_malloc(stmt, field, DavQLField);
-        dqlsec_list_append_or_free(stmt, stmt->fields, field);
+        if(dav_stmt_add_field(stmt, field)) {
+            free(field);
+            return 0;
+        }
         dqlsec_mallocz(stmt, field->expr, DavQLExpression);
         field->expr->type = DAVQL_IDENTIFIER;
         field->expr->srctext = field->name = token_sstr(token);
@@ -1051,7 +1072,10 @@
     if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) {
         DavQLField *field;
         dqlsec_malloc(stmt, field, DavQLField);
-        dqlsec_list_append_or_free(stmt, stmt->fields, field);
+        if(dav_stmt_add_field(stmt, field)) {
+            free(field);
+            return 0;
+        }
         dqlsec_mallocz(stmt, field->expr, DavQLExpression);
         field->expr->type = DAVQL_IDENTIFIER;
         field->expr->srctext = field->name = token_sstr(token);
@@ -1060,7 +1084,7 @@
         int consumed = 1;
         
         do {
-            token = ucx_list_get(token, consumed);
+            token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
             total_consumed += consumed;
             
             if (token_is(token, DAVQL_TOKEN_COMMA)) {
@@ -1071,7 +1095,10 @@
                     DavQLField *field;
                     dqlsec_malloc(stmt, field, DavQLField);
                     memcpy(field, &localfield, sizeof(DavQLField));
-                    dqlsec_list_append_or_free(stmt, stmt->fields, field);
+                    if(dav_stmt_add_field(stmt, field)) {
+                        free(field);
+                        return 0;
+                    }
                 }                
             } else {
                 consumed = 0;
@@ -1092,8 +1119,11 @@
                 DavQLField *field;
                 dqlsec_malloc(stmt, field, DavQLField);
                 memcpy(field, &localfield, sizeof(DavQLField));
-                dqlsec_list_append_or_free(stmt, stmt->fields, field);
-                token = ucx_list_get(token, consumed);
+                if(dav_stmt_add_field(stmt, field)) {
+                    free(field);
+                    return 0;
+                }
+                token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
                 total_consumed += consumed;
             } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER)
                 // look ahead, if the field is JUST the identifier
@@ -1105,7 +1135,10 @@
                 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
                 field->expr->type = DAVQL_IDENTIFIER;
                 field->expr->srctext = field->name = token_sstr(token);
-                dqlsec_list_append_or_free(stmt, stmt->fields, field);
+                if(dav_stmt_add_field(stmt, field)) {
+                    free(field);
+                    return 0;
+                }
 
                 consumed = 1;
                 total_consumed++;
@@ -1137,10 +1170,10 @@
 }
 
 // forward declaration
-static int dav_parse_logical_expr(DavQLStatement *stmt, UcxList *token,
+static int dav_parse_logical_expr(DavQLStatement *stmt, DavQLToken *token,
         DavQLExpression *expr);
 
-static int dav_parse_bool_prim(DavQLStatement *stmt, UcxList *token,
+static int dav_parse_bool_prim(DavQLStatement *stmt, DavQLToken *token,
         DavQLExpression *expr) {
     
     expr->type = DAVQL_LOGICAL;
@@ -1154,9 +1187,9 @@
     if (!total_consumed || stmt->errorcode) {
         return 0;
     }
-    token = ucx_list_get(token, total_consumed);
+    token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), total_consumed);
 
-    UcxList* optok = token;
+    DavQLToken* optok = token;
     // RULE:    Expression, (" like " | " unlike "), String
     if (token_is(optok, DAVQL_TOKEN_OPERATOR) && (tokenvalue_is(optok,
             "like") || tokenvalue_is(optok, "unlike"))) {
@@ -1248,7 +1281,7 @@
     }
 }
 
-static int dav_parse_bool_expr(DavQLStatement *stmt, UcxList *token,
+static int dav_parse_bool_expr(DavQLStatement *stmt, DavQLToken *token,
         DavQLExpression *expr) {
     
     // RULE:    "not ", LogicalExpression
@@ -1264,7 +1297,7 @@
             return 0;
         }
         if (consumed) {
-            sstr_t lasttok = token_sstr(ucx_list_get(token, consumed-1));
+            cxstring lasttok = token_sstr((DavQLToken*)cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed-1));
             expr->srctext.length =
                 lasttok.ptr - expr->srctext.ptr + lasttok.length;
             return consumed + 1;
@@ -1278,7 +1311,7 @@
     else if (token_is(token, DAVQL_TOKEN_OPENP)) {
         int consumed = dav_parse_logical_expr(stmt, token->next, expr);
         if (consumed) {
-            token = ucx_list_get(token->next, consumed);
+            token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
 
             if (token_is(token, DAVQL_TOKEN_CLOSEP)) {
                 token = token->next;
@@ -1301,10 +1334,10 @@
     return dav_parse_bool_prim(stmt, token, expr);
 }
 
-static int dav_parse_logical_expr(DavQLStatement *stmt, UcxList *token,
+static int dav_parse_logical_expr(DavQLStatement *stmt, DavQLToken *token,
         DavQLExpression *expr) {
     
-    UcxList *firsttoken = token;
+    DavQLToken *firsttoken = token;
     int total_consumed = 0;
     
     // RULE:    BooleanLiteral, [LogicalOperator, LogicalExpression];
@@ -1320,7 +1353,7 @@
         return 0;
     }
     total_consumed += consumed;
-    token = ucx_list_get(token, consumed);
+    token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
 
     if (token_is(token, DAVQL_TOKEN_OPERATOR)) {
         expr->type = DAVQL_LOGICAL;
@@ -1354,7 +1387,7 @@
                 return 0;
             }
             total_consumed += consumed;
-            token = ucx_list_get(token, consumed);
+            token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
 
             dqlsec_malloc(stmt, expr->left, DavQLExpression);
             memcpy(expr->left, &left, sizeof(DavQLExpression));
@@ -1368,20 +1401,20 @@
     // set type and recover source text
     if (total_consumed > 0) {        
         expr->srctext.ptr = token_sstr(firsttoken).ptr;
-        sstr_t lasttok = token_sstr(ucx_list_get(firsttoken, total_consumed-1));
+        cxstring lasttok = token_sstr((DavQLToken*)cx_linked_list_at(firsttoken, 0, offsetof(DavQLToken, next), total_consumed-1));
         expr->srctext.length = lasttok.ptr-expr->srctext.ptr+lasttok.length;
     }
     
     return total_consumed;
 }
 
-static int dav_parse_where_clause(DavQLStatement *stmt, UcxList *token) {
+static int dav_parse_where_clause(DavQLStatement *stmt, DavQLToken *token) {
     dqlsec_mallocz(stmt, stmt->where, DavQLExpression);
     
     return dav_parse_logical_expr(stmt, token, stmt->where);
 }
 
-static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) {
+static int dav_parse_with_clause(DavQLStatement *stmt, DavQLToken *token) {
 
     int total_consumed = 0;
     
@@ -1404,7 +1437,7 @@
                         if (depthexpr->srctext.ptr[0] == '%') {
                             stmt->depth = DAV_DEPTH_PLACEHOLDER;
                         } else {
-                            sstr_t depthstr = depthexpr->srctext;
+                            cxstring depthstr = depthexpr->srctext;
                             char *conv = malloc(depthstr.length+1);
                             if (!conv) {
                                 dav_free_expression(depthexpr);
@@ -1436,7 +1469,7 @@
     return total_consumed;
 }
 
-static int dav_parse_order_crit(DavQLStatement *stmt, UcxList *token,
+static int dav_parse_order_crit(DavQLStatement *stmt, DavQLToken *token,
     DavQLOrderCriterion *crit) {
     
     // RULE:    (Identifier | Number), [" asc"|" desc"];
@@ -1456,7 +1489,7 @@
     dqlsec_malloc(stmt, crit->column, DavQLExpression);
     memcpy(crit->column, &expr, sizeof(DavQLExpression));
     
-    token = ucx_list_get(token, consumed);
+    token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
     if (token_is(token, DAVQL_TOKEN_KEYWORD) && (
             tokenvalue_is(token, "asc") || tokenvalue_is(token, "desc"))) {
         
@@ -1469,12 +1502,19 @@
     }
 }
 
-static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token) {
+static int dav_parse_orderby_clause(DavQLStatement *stmt, DavQLToken *token) {
     
     int total_consumed = 0, consumed;
     
     DavQLOrderCriterion crit;
     
+    if(!stmt->orderby) {
+        stmt->orderby = cxLinkedListCreateSimple(sizeof(DavQLOrderCriterion));
+        if(!stmt->orderby) {
+            return 0;
+        }
+    }
+    
     // RULE:    OrderByCriterion, {",", OrderByCriterion};
     do {
         consumed = dav_parse_order_crit(stmt, token, &crit);
@@ -1486,13 +1526,13 @@
                 stmt, token);
             return 0;
         }
-        token = ucx_list_get(token, consumed);
+        token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
         total_consumed += consumed;
         
-        DavQLOrderCriterion *criterion;
-        dqlsec_malloc(stmt, criterion, DavQLOrderCriterion);
-        memcpy(criterion, &crit, sizeof(DavQLOrderCriterion));
-        dqlsec_list_append_or_free(stmt, stmt->orderby, criterion);
+        if(cxListAdd(stmt->orderby, &crit)) {
+            stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
+            return 0;
+        }
         
         if (token_is(token, DAVQL_TOKEN_COMMA)) {
             total_consumed++;
@@ -1506,7 +1546,7 @@
 }
 
 
-static int dav_parse_assignments(DavQLStatement *stmt, UcxList *token) {
+static int dav_parse_assignments(DavQLStatement *stmt, DavQLToken *token) {
     
     // RULE:    Assignment, {",", Assignment}
     int total_consumed = 0, consumed;
@@ -1540,11 +1580,14 @@
                 dav_free_field(field);
                 return total_consumed;
             }
-            token = ucx_list_get(token, consumed);
+            token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
             total_consumed += consumed;
             
             // Add assignment to list and check if there's another one
-            dqlsec_list_append_or_free(stmt, stmt->fields, field);
+            if(dav_stmt_add_field(stmt, field)) {
+                free(field);
+                return 0;
+            }
             consumed = token_is(token, DAVQL_TOKEN_COMMA) ? 1 : 0;
             if (consumed) {
                 token = token->next;
@@ -1560,7 +1603,7 @@
     return total_consumed;
 }
 
-static int dav_parse_path(DavQLStatement *stmt, UcxList *tokens) {
+static int dav_parse_path(DavQLStatement *stmt, DavQLToken *tokens) {
     if (token_is(tokens, DAVQL_TOKEN_STRING)) {
         stmt->path = token_sstr(tokens);
         tokens = tokens->next;
@@ -1572,7 +1615,7 @@
         int consumed = 1;
         while (!token_is(tokens, DAVQL_TOKEN_KEYWORD) &&
                 !token_is(tokens, DAVQL_TOKEN_END)) {
-            sstr_t toksstr = token_sstr(tokens);
+            cxstring toksstr = token_sstr(tokens);
             stmt->path.length = toksstr.ptr-stmt->path.ptr+toksstr.length;
             tokens = tokens->next;
             consumed++;
@@ -1582,7 +1625,7 @@
             tokenvalue_is(tokens, "%s")) {
         stmt->path = token_sstr(tokens);
         tokens = tokens->next;
-        stmt->args = ucx_list_append(stmt->args, (void*)(intptr_t)'s');
+        fmt_args_add(stmt, (void*)(intptr_t)'s');
         return 1;
     } else {
         dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
@@ -1596,11 +1639,11 @@
  * @param stmt the statement object that shall contain the syntax tree
  * @param tokens the token list
  */
-static void dav_parse_select_statement(DavQLStatement *stmt, UcxList *tokens) {
+static void dav_parse_select_statement(DavQLStatement *stmt, DavQLToken *tokens) {
     stmt->type = DAVQL_SELECT;
 
     // Consume field list
-    tokens = ucx_list_get(tokens, dav_parse_fieldlist(stmt, tokens));
+    tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), dav_parse_fieldlist(stmt, tokens));
     if (stmt->errorcode) {
         return;
     }
@@ -1616,7 +1659,7 @@
     }
     
     // Consume path
-    tokens = ucx_list_get(tokens, dav_parse_path(stmt, tokens));
+    tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), dav_parse_path(stmt, tokens));
     if (stmt->errorcode) {
         return;
     }
@@ -1626,7 +1669,7 @@
     if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
             && tokenvalue_is(tokens, "with")) {
         tokens = tokens->next;
-        tokens = ucx_list_get(tokens,
+        tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next),
             dav_parse_with_clause(stmt, tokens));
     }
     if (stmt->errorcode) {
@@ -1637,7 +1680,7 @@
     if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
             && tokenvalue_is(tokens, "where")) {
         tokens = tokens->next;
-        tokens = ucx_list_get(tokens,
+        tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next),
             dav_parse_where_clause(stmt, tokens));
     } else if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
             && tokenvalue_is(tokens, "anywhere")) {
@@ -1656,7 +1699,7 @@
         if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
                 && tokenvalue_is(tokens, "by")) {
             tokens = tokens->next;
-            tokens = ucx_list_get(tokens,
+            tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next),
                 dav_parse_orderby_clause(stmt, tokens));
         } else {
             dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
@@ -1680,11 +1723,11 @@
     }
 }
 
-static void dav_parse_set_statement(DavQLStatement *stmt, UcxList *tokens) {
+static void dav_parse_set_statement(DavQLStatement *stmt, DavQLToken *tokens) {
     stmt->type = DAVQL_SET;
     
     // Consume assignments
-    tokens = ucx_list_get(tokens, dav_parse_assignments(stmt, tokens));
+    tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), dav_parse_assignments(stmt, tokens));
     if (stmt->errorcode) {
         return;
     }
@@ -1700,7 +1743,7 @@
     }
 
     // Consume path
-    tokens = ucx_list_get(tokens, dav_parse_path(stmt, tokens));
+    tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), dav_parse_path(stmt, tokens));
     if (stmt->errorcode) {
         return;
     }
@@ -1709,7 +1752,7 @@
     if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
             && tokenvalue_is(tokens, "with")) {
         tokens = tokens->next;
-        tokens = ucx_list_get(tokens,
+        tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), 
             dav_parse_with_clause(stmt, tokens));
     }
     if (stmt->errorcode) {
@@ -1720,7 +1763,7 @@
     if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
             && tokenvalue_is(tokens, "where")) {
         tokens = tokens->next;
-        tokens = ucx_list_get(tokens,
+        tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), 
             dav_parse_where_clause(stmt, tokens));
     } else if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
             && tokenvalue_is(tokens, "anywhere")) {
@@ -1734,7 +1777,7 @@
     }
 }
 
-DavQLStatement* dav_parse_statement(sstr_t srctext) {
+DavQLStatement* dav_parse_statement(cxstring srctext) {
     DavQLStatement *stmt = calloc(1, sizeof(DavQLStatement));
     
     // if we can't even get enough memory for the statement object or an error
@@ -1753,11 +1796,11 @@
     stmt->depth = 1;
     
     // save trimmed source text
-    stmt->srctext = sstrtrim(srctext);
+    stmt->srctext = cx_strtrim(srctext);
     
     if (stmt->srctext.length) {   
         // tokenization
-        UcxList* tokens = dav_parse_tokenize(stmt->srctext);
+        DavQLToken* tokens = dav_parse_tokenize(stmt->srctext);
 
         if (tokens) {
             // use first token to determine query type
@@ -1773,10 +1816,7 @@
             }
 
             // free token data
-            UCX_FOREACH(token, tokens) {
-                free(token->data);
-            }
-            ucx_list_free(tokens);
+            tokenlist_free(tokens);
         } else {
             stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
         }
@@ -1797,10 +1837,10 @@
 }
 
 void dav_free_statement(DavQLStatement *stmt) {
-    UCX_FOREACH(expr, stmt->fields) {
-        dav_free_field(expr->data);
+    if(stmt->fields) {
+        stmt->fields->simple_destructor = (cx_destructor_func)dav_free_field;
+        cxListDestroy(stmt->fields);
     }
-    ucx_list_free(stmt->fields);
     
     if (stmt->where) {
         dav_free_expression(stmt->where);
@@ -1808,10 +1848,13 @@
     if (stmt->errormessage) {
         free(stmt->errormessage);
     }
-    UCX_FOREACH(crit, stmt->orderby) {
-        dav_free_order_criterion(crit->data);
+    
+    if(stmt->orderby) {
+        stmt->orderby->simple_destructor = (cx_destructor_func)dav_free_order_criterion;
+        cxListDestroy(stmt->orderby);
     }
-    ucx_list_free(stmt->orderby);
-    ucx_list_free(stmt->args);
+    if(stmt->args) {
+        cxListDestroy(stmt->args);
+    }
     free(stmt);
 }

mercurial