libidav/davqlexec.c

changeset 747
efbd59642577
parent 739
bba6a6e221b4
child 755
283d3d7a657a
equal deleted inserted replaced
746:a569148841ff 747:efbd59642577
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <string.h> 31 #include <string.h>
32 #include <inttypes.h> 32 #include <inttypes.h>
33 33
34 #include <ucx/utils.h> 34 #include <cx/utils.h>
35 #include <ucx/map.h> 35 #include <cx/map.h>
36 #include <cx/hash_map.h>
37 #include <cx/printf.h>
38 #include <cx/basic_mempool.h>
39
36 #include "davqlexec.h" 40 #include "davqlexec.h"
37 #include "utils.h" 41 #include "utils.h"
38 #include "methods.h" 42 #include "methods.h"
39 #include "session.h" 43 #include "session.h"
40 #include "resource.h" 44 #include "resource.h"
44 if(!args) { 48 if(!args) {
45 return NULL; 49 return NULL;
46 } 50 }
47 args->first = NULL; 51 args->first = NULL;
48 52
53 if(!st->args) {
54 args->first = NULL;
55 args->current = NULL;
56 return args;
57 }
58
49 DavQLArg *cur = NULL; 59 DavQLArg *cur = NULL;
50 UCX_FOREACH(elm, st->args) { 60 CxIterator i = cxListIterator(st->args);
51 intptr_t type = (intptr_t)elm->data; 61 cx_foreach(void*, data, i) {
62 intptr_t type = (intptr_t)data;
52 DavQLArg *arg = calloc(1, sizeof(DavQLArg)); 63 DavQLArg *arg = calloc(1, sizeof(DavQLArg));
53 if(!arg) { 64 if(!arg) {
54 dav_ql_free_arglist(args); 65 dav_ql_free_arglist(args);
55 return NULL; 66 return NULL;
56 } 67 }
165 } 176 }
166 177
167 return result; 178 return result;
168 } 179 }
169 180
170 sstr_t dav_format_string(UcxAllocator *a, sstr_t fstr, DavQLArgList *ap, davqlerror_t *error) { 181 cxmutstr dav_format_string(const CxAllocator *a, cxstring fstr, DavQLArgList *ap, davqlerror_t *error) {
171 UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); 182 CxBuffer buf;
183 cxBufferInit(&buf, NULL, 128, a, CX_BUFFER_AUTO_EXTEND);
172 184
173 int placeholder = 0; 185 int placeholder = 0;
174 for(int i=0;i<fstr.length;i++) { 186 for(int i=0;i<fstr.length;i++) {
175 char c = fstr.ptr[i]; 187 char c = fstr.ptr[i];
176 if(placeholder) { 188 if(placeholder) {
177 if(c == '%') { 189 if(c == '%') {
178 // no placeholder, %% transposes to % 190 // no placeholder, %% transposes to %
179 ucx_buffer_putc(buf, c); 191 cxBufferPut(&buf, c);
180 } else { 192 } else {
181 // detect placeholder type and insert arg 193 // detect placeholder type and insert arg
182 int err = 0; 194 int err = 0;
183 switch(c) { 195 switch(c) {
184 case 's': { 196 case 's': {
185 char *arg = dav_ql_getarg_str(ap); 197 char *arg = dav_ql_getarg_str(ap);
186 ucx_buffer_puts(buf, arg); 198 cxBufferPutString(&buf, arg);
187 break; 199 break;
188 } 200 }
189 case 'd': { 201 case 'd': {
190 int arg = dav_ql_getarg_int(ap); 202 int arg = dav_ql_getarg_int(ap);
191 ucx_bprintf(buf, "%d", arg); 203 cx_bprintf(&buf, "%d", arg);
192 break; 204 break;
193 } 205 }
194 case 'u': { 206 case 'u': {
195 unsigned int arg = dav_ql_getarg_uint(ap); 207 unsigned int arg = dav_ql_getarg_uint(ap);
196 ucx_bprintf(buf, "%u", arg); 208 cx_bprintf(&buf, "%u", arg);
197 break; 209 break;
198 } 210 }
199 case 't': { 211 case 't': {
200 // time arguments not supported for strings 212 // time arguments not supported for strings
201 err = 1; 213 err = 1;
205 *error = DAVQL_UNKNOWN_FORMATCHAR; 217 *error = DAVQL_UNKNOWN_FORMATCHAR;
206 err = 1; 218 err = 1;
207 } 219 }
208 } 220 }
209 if(err) { 221 if(err) {
210 ucx_buffer_free(buf); 222 cxBufferDestroy(&buf);
211 sstr_t n; 223 return (cxmutstr){NULL,0};
212 n.ptr = NULL;
213 n.length = 0;
214 return n;
215 } 224 }
216 } 225 }
217 placeholder = 0; 226 placeholder = 0;
218 } else { 227 } else {
219 if(c == '%') { 228 if(c == '%') {
220 placeholder = 1; 229 placeholder = 1;
221 } else { 230 } else {
222 ucx_buffer_putc(buf, c); 231 cxBufferPut(&buf, c);
223 } 232 }
224 } 233 }
234 }
235 if(cxBufferPut(&buf, '\0')) {
236 *error = DAVQL_OOM;
237 cxBufferDestroy(&buf);
238 return (cxmutstr){NULL, 0};
225 } 239 }
226 *error = DAVQL_OK; 240 *error = DAVQL_OK;
227 241
228 sstr_t ret = sstrdup_a(a, sstrn(buf->space, buf->size)); 242 return cx_mutstrn(buf.space, buf.size-1);
229 ucx_buffer_free(buf); 243 }
230 return ret; 244
231 } 245 static int fl_add_properties(DavSession *sn, const CxAllocator *a, CxMap *map, DavQLExpression *expression) {
232
233 static int fl_add_properties(DavSession *sn, UcxMempool *mp, UcxMap *map, DavQLExpression *expression) {
234 if(!expression) { 246 if(!expression) {
235 return 0; 247 return 0;
236 } 248 }
237 249
238 if(expression->type == DAVQL_IDENTIFIER) { 250 if(expression->type == DAVQL_IDENTIFIER) {
239 DavProperty *property = ucx_mempool_malloc(mp, sizeof(DavProperty)); 251 DavProperty *property = cxMalloc(a, sizeof(DavProperty));
240 252
241 char *name; 253 char *name;
242 DavNamespace *ns = dav_get_property_namespace( 254 DavNamespace *ns = dav_get_property_namespace(
243 sn->context, 255 sn->context,
244 sstrdup_a(mp->allocator, expression->srctext).ptr, 256 cx_strdup_a(a, expression->srctext).ptr,
245 &name); 257 &name);
246 if(!ns) { 258 if(!ns) {
247 return -1; 259 return -1;
248 } 260 }
249 261
250 property->ns = ns; 262 property->ns = ns;
251 property->name = name; 263 property->name = name;
252 property->value = NULL; 264 property->value = NULL;
253 265
254 ucx_map_sstr_put(map, expression->srctext, property); 266 cxMapPut(map, cx_hash_key(expression->srctext.ptr, expression->srctext.length), property);
255 } 267 }
256 268
257 if(expression->left) { 269 if(expression->left) {
258 if(fl_add_properties(sn, mp, map, expression->left)) { 270 if(fl_add_properties(sn, a, map, expression->left)) {
259 return -1; 271 return -1;
260 } 272 }
261 } 273 }
262 if(expression->right) { 274 if(expression->right) {
263 if(fl_add_properties(sn, mp, map, expression->right)) { 275 if(fl_add_properties(sn, a, map, expression->right)) {
264 return -1; 276 return -1;
265 } 277 }
266 } 278 }
267 279
268 return 0; 280 return 0;
269 } 281 }
270 282
271 static UcxBuffer* fieldlist2propfindrequest(DavSession *sn, UcxMempool *mp, UcxList *fields, int *isallprop) { 283 static CxBuffer* fieldlist2propfindrequest(DavSession *sn, const CxAllocator *a, CxList *fields, int *isallprop) {
272 UcxMap *properties = ucx_map_new(32); 284 CxMap *properties = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 32);
273 *isallprop = 0; 285 *isallprop = 0;
274 286
275 UCX_FOREACH(elm, fields) { 287 CxIterator i = cxListIterator(fields);
276 DavQLField *field = elm->data; 288 cx_foreach(DavQLField*, field, i) {
277 if(!sstrcmp(field->name, S("*"))) { 289 if(!cx_strcmp(field->name, CX_STR("*"))) {
278 ucx_map_free(properties); 290 cxMapDestroy(properties);
279 *isallprop = 1; 291 *isallprop = 1;
280 return create_allprop_propfind_request(); 292 return create_allprop_propfind_request();
281 } else if(!sstrcmp(field->name, S("-"))) { 293 } else if(!cx_strcmp(field->name, CX_STR("-"))) {
282 ucx_map_free(properties); 294 cxMapDestroy(properties);
283 return create_propfind_request(sn, NULL, "propfind", 0); 295 return create_propfind_request(sn, NULL, "propfind", 0);
284 } else { 296 } else {
285 if(fl_add_properties(sn, mp, properties, field->expr)) { 297 if(fl_add_properties(sn, a, properties, field->expr)) {
286 // TODO: set error 298 // TODO: set error
287 ucx_map_free(properties); 299 cxMapDestroy(properties);
288 return NULL; 300 return NULL;
289 } 301 }
290 } 302 }
291 } 303 }
292 304
293 UcxMapIterator i = ucx_map_iterator(properties); 305 i = cxMapIteratorValues(properties);
294 UcxKey key; 306 CxList *list = cxLinkedListCreateSimple(CX_STORE_POINTERS);
295 DavProperty *value; 307 cx_foreach(DavProperty*, value, i) {
296 UcxList *list = NULL; 308 cxListAdd(list, value);
297 UCX_MAP_FOREACH(key, value, i) { 309 }
298 list = ucx_list_append(list, value); 310
299 } 311 CxBuffer *reqbuf = create_propfind_request(sn, list, "propfind", 0);
300 312 cxListDestroy(list);
301 UcxBuffer *reqbuf = create_propfind_request(sn, list, "propfind", 0); 313 cxMapDestroy(properties);
302 ucx_list_free(list);
303 ucx_map_free(properties);
304 return reqbuf; 314 return reqbuf;
305 } 315 }
306 316
307 static int reset_properties(DavSession *sn, DavResult *result, DavResource *res, UcxList *fields) { 317 static int reset_properties(DavSession *sn, DavResult *result, DavResource *res, CxList *fields) {
308 UcxMap *new_properties = ucx_map_new_a(sn->mp->allocator, 32); 318 CxMap *new_properties = cxHashMapCreate(sn->mp->allocator, CX_STORE_POINTERS, 32);
309 DavResourceData *data = (DavResourceData*)res->data; 319 DavResourceData *data = (DavResourceData*)res->data;
310 320
311 // add basic properties 321 // add basic properties
312 void *value; 322 void *value;
313 323
314 sstr_t cl_keystr = dav_property_key("DAV:", "getcontentlength"); 324 cxmutstr cl_keystr = dav_property_key("DAV:", "getcontentlength");
315 UcxKey cl_key = ucx_key(cl_keystr.ptr, cl_keystr.length); 325 CxHashKey cl_key = cx_hash_key(cl_keystr.ptr, cl_keystr.length);
316 value = ucx_map_get(data->properties, cl_key); 326 value = cxMapGet(data->properties, cl_key);
317 if(value) { 327 if(value) {
318 ucx_map_put(new_properties, cl_key, value); 328 cxMapPut(new_properties, cl_key, value);
319 } 329 }
320 330
321 sstr_t cd_keystr = dav_property_key("DAV:", "creationdate"); 331 cxmutstr cd_keystr = dav_property_key("DAV:", "creationdate");
322 UcxKey cd_key = ucx_key(cd_keystr.ptr, cd_keystr.length); 332 CxHashKey cd_key = cx_hash_key(cd_keystr.ptr, cd_keystr.length);
323 value = ucx_map_get(data->properties, cd_key); 333 value = cxMapGet(data->properties, cd_key);
324 if(value) { 334 if(value) {
325 ucx_map_put(new_properties, cd_key, value); 335 cxMapPut(new_properties, cd_key, value);
326 } 336 }
327 337
328 sstr_t lm_keystr = dav_property_key("DAV:", "getlastmodified"); 338 cxmutstr lm_keystr = dav_property_key("DAV:", "getlastmodified");
329 UcxKey lm_key = ucx_key(lm_keystr.ptr, lm_keystr.length); 339 CxHashKey lm_key = cx_hash_key(lm_keystr.ptr, lm_keystr.length);
330 value = ucx_map_get(data->properties, lm_key); 340 value = cxMapGet(data->properties, lm_key);
331 if(value) { 341 if(value) {
332 ucx_map_put(new_properties, lm_key, value); 342 cxMapPut(new_properties, lm_key, value);
333 } 343 }
334 344
335 sstr_t ct_keystr = dav_property_key("DAV:", "getcontenttype"); 345 cxmutstr ct_keystr = dav_property_key("DAV:", "getcontenttype");
336 UcxKey ct_key = ucx_key(ct_keystr.ptr, ct_keystr.length); 346 CxHashKey ct_key = cx_hash_key(ct_keystr.ptr, ct_keystr.length);
337 value = ucx_map_get(data->properties, ct_key); 347 value = cxMapGet(data->properties, ct_key);
338 if(value) { 348 if(value) {
339 ucx_map_put(new_properties, ct_key, value); 349 cxMapPut(new_properties, ct_key, value);
340 } 350 }
341 351
342 sstr_t rt_keystr = dav_property_key("DAV:", "resourcetype"); 352 cxmutstr rt_keystr = dav_property_key("DAV:", "resourcetype");
343 UcxKey rt_key = ucx_key(rt_keystr.ptr, rt_keystr.length); 353 CxHashKey rt_key = cx_hash_key(rt_keystr.ptr, rt_keystr.length);
344 value = ucx_map_get(data->properties, rt_key); 354 value = cxMapGet(data->properties, rt_key);
345 if(value) { 355 if(value) {
346 ucx_map_put(new_properties, rt_key, value); 356 cxMapPut(new_properties, rt_key, value);
347 } 357 }
348 358
349 sstr_t cn_keystr = dav_property_key(DAV_NS, "crypto-name"); 359 cxmutstr cn_keystr = dav_property_key(DAV_NS, "crypto-name");
350 UcxKey cn_key = ucx_key(cn_keystr.ptr, cn_keystr.length); 360 CxHashKey cn_key = cx_hash_key(cn_keystr.ptr, cn_keystr.length);
351 value = ucx_map_get(data->properties, cn_key); 361 value = cxMapGet(data->properties, cn_key);
352 if(value) { 362 if(value) {
353 ucx_map_put(new_properties, cn_key, value); 363 cxMapPut(new_properties, cn_key, value);
354 } 364 }
355 365
356 sstr_t ck_keystr = dav_property_key(DAV_NS, "crypto-key"); 366 cxmutstr ck_keystr = dav_property_key(DAV_NS, "crypto-key");
357 UcxKey ck_key = ucx_key(ck_keystr.ptr, ck_keystr.length); 367 CxHashKey ck_key = cx_hash_key(ck_keystr.ptr, ck_keystr.length);
358 value = ucx_map_get(data->properties, ck_key); 368 value = cxMapGet(data->properties, ck_key);
359 if(value) { 369 if(value) {
360 ucx_map_put(new_properties, ck_key, value); 370 cxMapPut(new_properties, ck_key, value);
361 } 371 }
362 372
363 sstr_t ch_keystr = dav_property_key(DAV_NS, "crypto-hash"); 373 cxmutstr ch_keystr = dav_property_key(DAV_NS, "crypto-hash");
364 UcxKey ch_key = ucx_key(ch_keystr.ptr, ch_keystr.length); 374 CxHashKey ch_key = cx_hash_key(ch_keystr.ptr, ch_keystr.length);
365 value = ucx_map_get(data->properties, ch_key); 375 value = cxMapGet(data->properties, ch_key);
366 if(value) { 376 if(value) {
367 ucx_map_put(new_properties, ch_key, value); 377 cxMapPut(new_properties, ch_key, value);
368 } 378 }
369 379
370 // add properties from field list 380 // add properties from field list
371 UCX_FOREACH(elm, fields) { 381 if(fields) {
372 DavCompiledField *field = elm->data; 382 CxIterator i = cxListIterator(fields);
373 DavQLStackObj field_result; 383 cx_foreach(DavCompiledField*, field, i) {
374 if(!dav_exec_expr(field->code, res, &field_result)) { 384 DavQLStackObj field_result;
375 sstr_t str; 385 if(!dav_exec_expr(field->code, res, &field_result)) {
376 str.ptr = NULL; 386 cxmutstr str;
377 str.length = 0; 387 str.ptr = NULL;
378 DavXmlNode *node = NULL; 388 str.length = 0;
379 if(field_result.type == 0) { 389 DavXmlNode *node = NULL;
380 str = ucx_asprintf( 390 if(field_result.type == 0) {
381 sn->mp->allocator, 391 str = cx_asprintf_a(
382 "%d", 392 sn->mp->allocator,
383 field_result.data.integer); 393 "%" PRId64,
384 } else if(field_result.type == 1) { 394 field_result.data.integer);
385 if(field_result.data.string) { 395 } else if(field_result.type == 1) {
386 str = sstrdup_a(sn->mp->allocator, sstrn( 396 if(field_result.data.string) {
387 field_result.data.string, 397 str = cx_strdup_a(sn->mp->allocator, cx_strn(
388 field_result.length)); 398 field_result.data.string,
389 } 399 field_result.length));
390 } else if(field_result.type == 2) { 400 }
391 node = dav_copy_node(field_result.data.node); 401 } else if(field_result.type == 2) {
402 node = dav_copy_node(field_result.data.node);
403 } else {
404 // unknown type
405 // TODO: error
406 resource_free_properties(sn, new_properties);
407 return -1;
408 }
409 if(str.ptr) {
410 node = dav_session_malloc(sn, sizeof(DavXmlNode));
411 memset(node, 0, sizeof(DavXmlNode));
412 node->type = DAV_XML_TEXT;
413 node->content = str.ptr;
414 node->contentlength = str.length;
415 }
416 if(node) {
417 cxmutstr key = dav_property_key(field->ns, field->name);
418
419 DavNamespace *namespace = dav_session_malloc(sn, sizeof(DavNamespace));
420 namespace->prefix = NULL;
421 namespace->name = dav_session_strdup(sn, field->ns);
422
423 DavProperty *prop = dav_session_malloc(sn, sizeof(DavProperty));
424 prop->name = dav_session_strdup(sn, field->name);
425 prop->ns = namespace;
426 prop->value = node;
427
428 cxMapPut(new_properties, cx_hash_key(key.ptr, key.length), prop);
429 free(key.ptr);
430 }
392 } else { 431 } else {
393 // unknown type
394 // TODO: error 432 // TODO: error
395 resource_free_properties(sn, new_properties); 433 resource_free_properties(sn, new_properties);
396 return -1; 434 return -1;
397 } 435 }
398 if(str.ptr) { 436 }
399 node = dav_session_malloc(sn, sizeof(DavXmlNode)); 437 }
400 memset(node, 0, sizeof(DavXmlNode)); 438
401 node->type = DAV_XML_TEXT; 439 cxMapRemove(data->properties, cl_key);
402 node->content = str.ptr; 440 cxMapRemove(data->properties, cd_key);
403 node->contentlength = str.length; 441 cxMapRemove(data->properties, lm_key);
404 } 442 cxMapRemove(data->properties, ct_key);
405 if(node) { 443 cxMapRemove(data->properties, rt_key);
406 sstr_t key = dav_property_key(field->ns, field->name); 444 cxMapRemove(data->properties, cn_key);
407 445 cxMapRemove(data->properties, ck_key);
408 DavNamespace *namespace = dav_session_malloc(sn, sizeof(DavNamespace)); 446 cxMapRemove(data->properties, ch_key);
409 namespace->prefix = NULL;
410 namespace->name = dav_session_strdup(sn, field->ns);
411
412 DavProperty *prop = dav_session_malloc(sn, sizeof(DavProperty));
413 prop->name = dav_session_strdup(sn, field->name);
414 prop->ns = namespace;
415 prop->value = node;
416
417 ucx_map_sstr_put(new_properties, key, prop);
418 free(key.ptr);
419 }
420 } else {
421 // TODO: error
422 resource_free_properties(sn, new_properties);
423 return -1;
424 }
425 }
426
427 ucx_map_remove(data->properties, cl_key);
428 ucx_map_remove(data->properties, cd_key);
429 ucx_map_remove(data->properties, lm_key);
430 ucx_map_remove(data->properties, ct_key);
431 ucx_map_remove(data->properties, rt_key);
432 ucx_map_remove(data->properties, cn_key);
433 ucx_map_remove(data->properties, ck_key);
434 ucx_map_remove(data->properties, ch_key);
435 447
436 resource_free_properties(sn, data->properties); 448 resource_free_properties(sn, data->properties);
437 data->properties = new_properties; 449 data->properties = new_properties;
438 450
439 free(cl_keystr.ptr); 451 free(cl_keystr.ptr);
450 462
451 /* 463 /*
452 * execute a davql select statement 464 * execute a davql select statement
453 */ 465 */
454 DavResult dav_exec_select(DavSession *sn, DavQLStatement *st, va_list ap) { 466 DavResult dav_exec_select(DavSession *sn, DavQLStatement *st, va_list ap) {
455 UcxMempool *mp = ucx_mempool_new(128); 467 CxMempool *mp = cxBasicMempoolCreate(128);
456 DavResult result; 468 DavResult result;
457 result.result = NULL; 469 result.result = NULL;
458 result.status = 1; 470 result.status = 1;
459 471
460 DavQLArgList *args = dav_ql_get_args(st, ap); 472 DavQLArgList *args = dav_ql_get_args(st, ap);
461 if(!args) { 473 if(!args) {
462 return result; 474 return result;
463 } 475 }
464 ucx_mempool_reg_destr(mp, args, (ucx_destructor)dav_ql_free_arglist); 476 util_regdestr(mp, args, (cx_destructor_func)dav_ql_free_arglist);
465 477
466 int isallprop; 478 int isallprop;
467 UcxBuffer *rqbuf = fieldlist2propfindrequest(sn, mp, st->fields, &isallprop); 479 CxBuffer *rqbuf = fieldlist2propfindrequest(sn, mp->allocator, st->fields, &isallprop);
468 if(!rqbuf) { 480 if(!rqbuf) {
469 ucx_mempool_destroy(mp); 481 cxMempoolDestroy(mp);
470 return result; 482 return result;
471 } 483 }
472 ucx_mempool_reg_destr(mp, rqbuf, (ucx_destructor)ucx_buffer_free); 484 util_regdestr(mp, rqbuf, (cx_destructor_func)cxBufferFree);
473 485
474 // compile field list 486 // compile field list
475 UcxList *cfieldlist = NULL; 487 CxList *cfieldlist = cxLinkedListCreate(mp->allocator, NULL, CX_STORE_POINTERS);
476 UCX_FOREACH(elm, st->fields) { 488 if(st->fields) {
477 DavQLField *field = elm->data; 489 CxIterator i = cxListIterator(st->fields);
478 if(sstrcmp(field->name, S("*")) && sstrcmp(field->name, S("-"))) { 490 cx_foreach(DavQLField*, field, i) {
479 // compile field expression 491 if(cx_strcmp(field->name, CX_STR("*")) && cx_strcmp(field->name, CX_STR("-"))) {
480 UcxBuffer *code = dav_compile_expr( 492 // compile field expression
481 sn->context, 493 CxBuffer *code = dav_compile_expr(
482 mp->allocator, 494 sn->context,
483 field->expr, 495 mp->allocator,
484 args); 496 field->expr,
485 if(!code) { 497 args);
486 // TODO: set error string 498 if(!code) {
487 return result; 499 // TODO: set error string
488 } 500 return result;
489 ucx_mempool_reg_destr(mp, code, (ucx_destructor)ucx_buffer_free); 501 }
490 DavCompiledField *cfield = ucx_mempool_malloc( 502 DavCompiledField *cfield = cxMalloc(
491 mp, 503 mp->allocator,
492 sizeof(DavCompiledField)); 504 sizeof(DavCompiledField));
493 505
494 char *ns;
495 char *name;
496 dav_get_property_namespace_str(
497 sn->context,
498 sstrdup_a(mp->allocator, field->name).ptr,
499 &ns,
500 &name);
501 if(!ns || !name) {
502 // TODO: set error string
503 return result;
504 }
505 cfield->ns = ns;
506 cfield->name = name;
507 cfield->code = code;
508 cfieldlist = ucx_list_append_a(mp->allocator, cfieldlist, cfield);
509 }
510 }
511
512 // get path string
513 davqlerror_t error;
514 sstr_t path = dav_format_string(mp->allocator, st->path, args, &error);
515 if(error) {
516 // TODO: cleanup
517 ucx_mempool_destroy(mp);
518 return result;
519 }
520
521 int depth = st->depth == DAV_DEPTH_PLACEHOLDER ?
522 dav_ql_getarg_int(args) : st->depth;
523
524 UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, args);
525 if(st->where && !where) {
526 // TODO: cleanup
527 ucx_mempool_destroy(mp);
528 return result;
529 }
530 if(where) {
531 ucx_mempool_reg_destr(mp, where, (ucx_destructor)ucx_buffer_free);
532 }
533
534 // compile order criterion
535 UcxList *ordercr = NULL;
536 UCX_FOREACH(elm, st->orderby) {
537 DavQLOrderCriterion *oc = elm->data;
538 DavQLExpression *column = oc->column;
539 //printf("%.*s %s\n", column->srctext.length, column->srctext.ptr, oc->descending ? "desc" : "asc");
540 if(column->type == DAVQL_IDENTIFIER) {
541 // TODO: remove code duplication (add_cmd)
542 davqlresprop_t resprop;
543 sstr_t propertyname = sstrchr(column->srctext, ':');
544 if(propertyname.length > 0) {
545 char *ns; 506 char *ns;
546 char *name; 507 char *name;
547 dav_get_property_namespace_str( 508 dav_get_property_namespace_str(
548 sn->context, 509 sn->context,
549 sstrdup_a(mp->allocator, column->srctext).ptr, 510 cx_strdup_a(mp->allocator, field->name).ptr,
550 &ns, 511 &ns,
551 &name); 512 &name);
552 if(ns && name) { 513 if(!ns || !name) {
553 DavOrderCriterion *cr = ucx_mempool_malloc(mp, sizeof(DavOrderCriterion)); 514 // TODO: set error string
554 cr->type = 1; 515 return result;
555 sstr_t keystr = dav_property_key_a(mp->allocator, ns, name); 516 }
556 cr->column.property = ucx_key(keystr.ptr, keystr.length); 517 cfield->ns = ns;
557 cr->descending = oc->descending; 518 cfield->name = name;
558 ordercr = ucx_list_append_a(mp->allocator, ordercr, cr); 519 cfield->code = code;
520 cxListAdd(cfieldlist, cfield);
521 }
522 }
523 }
524
525 // get path string
526 davqlerror_t error;
527 cxmutstr path = dav_format_string(mp->allocator, st->path, args, &error);
528 if(error) {
529 // TODO: cleanup
530 cxMempoolDestroy(mp);
531 return result;
532 }
533
534 int depth = st->depth == DAV_DEPTH_PLACEHOLDER ?
535 dav_ql_getarg_int(args) : st->depth;
536
537 CxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, args);
538 if(st->where && !where) {
539 // TODO: cleanup
540 cxMempoolDestroy(mp);
541 return result;
542 }
543
544 // compile order criterion
545 CxList *ordercr = NULL;
546 if(st->orderby) {
547 ordercr = cxLinkedListCreate(mp->allocator, NULL, sizeof(DavOrderCriterion));
548 CxIterator i = cxListIterator(st->orderby);
549 cx_foreach(DavQLOrderCriterion*, oc, i) {
550 DavQLExpression *column = oc->column;
551 //printf("%.*s %s\n", column->srctext.length, column->srctext.ptr, oc->descending ? "desc" : "asc");
552 if(column->type == DAVQL_IDENTIFIER) {
553 // TODO: remove code duplication (add_cmd)
554 davqlresprop_t resprop;
555 cxstring propertyname = cx_strchr(column->srctext, ':');
556 if(propertyname.length > 0) {
557 char *ns;
558 char *name;
559 dav_get_property_namespace_str(
560 sn->context,
561 cx_strdup_a(mp->allocator, column->srctext).ptr,
562 &ns,
563 &name);
564 if(ns && name) {
565 DavOrderCriterion cr;
566 cr.type = 1;
567 cxmutstr keystr = dav_property_key_a(mp->allocator, ns, name);
568 cr.column.property = cx_hash_key(keystr.ptr, keystr.length);
569 cr.descending = oc->descending;
570 cxListAdd(ordercr, &cr);
571 } else {
572 // error
573 // TODO: cleanup
574 cxMempoolDestroy(mp);
575 return result;
576 }
577 } else if(dav_identifier2resprop(column->srctext, &resprop)) {
578 DavOrderCriterion cr;
579 cr.type = 0;
580 cr.column.resprop = resprop;
581 cr.descending = oc->descending;
582 cxListAdd(ordercr, &cr);
559 } else { 583 } else {
560 // error 584 // error
561 // TODO: cleanup 585 // TODO: cleanup
562 ucx_mempool_destroy(mp); 586 cxMempoolDestroy(mp);
563 return result; 587 return result;
564 } 588 }
565 } else if(dav_identifier2resprop(column->srctext, &resprop)) { 589
566 DavOrderCriterion *cr = ucx_mempool_malloc(mp, sizeof(DavOrderCriterion)); 590 } else if(column->type == DAVQL_NUMBER) {
567 cr->type = 0; 591 // TODO: implement
568 cr->column.resprop = resprop; 592 fprintf(stderr, "order by number not supported\n");
569 cr->descending = oc->descending; 593 return result;
570 ordercr = ucx_list_append_a(mp->allocator, ordercr, cr);
571 } else { 594 } else {
572 // error 595 // something is broken
573 // TODO: cleanup 596 // TODO: cleanup
574 ucx_mempool_destroy(mp); 597 cxMempoolDestroy(mp);
575 return result; 598 return result;
576 } 599 }
577
578 } else if(column->type == DAVQL_NUMBER) {
579 // TODO: implement
580 fprintf(stderr, "order by number not supported\n");
581 return result;
582 } else {
583 // something is broken
584 // TODO: cleanup
585 ucx_mempool_destroy(mp);
586 return result;
587 } 600 }
588 } 601 }
589 602
590 DavResource *selroot = dav_resource_new(sn, path.ptr); 603 DavResource *selroot = dav_resource_new(sn, path.ptr);
591 604
592 UcxList *stack = NULL; // stack with DavResource* elements 605 CxList *stack = cxLinkedListCreateSimple(sizeof(DavQLRes));
593 // initialize the stack with the requested resource 606 // initialize the stack with the requested resource
594 DavQLRes *res = ucx_mempool_malloc(mp, sizeof(DavQLRes)); 607 DavQLRes res;
595 res->resource = selroot; 608 res.resource = selroot;
596 res->depth = 0; 609 res.depth = 0;
597 stack = ucx_list_prepend(stack, res); 610 cxListInsert(stack, 0, &res);
598 611
599 // reuseable response buffer 612 // reuseable response buffer
600 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); 613 CxBuffer *rpbuf = cxBufferCreate(NULL, 4096, mp->allocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
601 if(!rpbuf) { 614 if(!rpbuf) {
602 // TODO: cleanup 615 // TODO: cleanup
603 ucx_mempool_destroy(mp); 616 cxMempoolDestroy(mp);
604 return result; 617 return result;
605 } 618 }
606 ucx_mempool_reg_destr(mp, rpbuf, (ucx_destructor)ucx_buffer_free);
607 619
608 result.result = selroot; 620 result.result = selroot;
609 result.status = 0; 621 result.status = 0;
610 622
611 // do a propfind request for each resource on the stack 623 // do a propfind request for each resource on the stack
612 while(stack) { 624 while(stack->size > 0) {
613 DavQLRes *sr = stack->data; // get first element from the stack 625 DavQLRes *sr = cxListAt(stack, 0); // get first element from the stack
614 stack = ucx_list_remove(stack, stack); // remove first element 626 cxListRemove(stack, 0);
627 cxListRemove(stack, 0); // remove first element
615 DavResource *root = sr->resource; 628 DavResource *root = sr->resource;
616 629
617 util_set_url(sn, dav_resource_get_href(sr->resource)); 630 util_set_url(sn, dav_resource_get_href(sr->resource));
618 CURLcode ret = do_propfind_request(sn, rqbuf, rpbuf); 631 CURLcode ret = do_propfind_request(sn, rqbuf, rpbuf);
619 long http_status = 0; 632 long http_status = 0;
670 } 683 }
671 } 684 }
672 result.result = NULL; 685 result.result = NULL;
673 result.status = -1; 686 result.status = -1;
674 dav_resource_free_all(selroot); 687 dav_resource_free_all(selroot);
675 ucx_list_free(stack); 688 cxListDestroy(stack);
676 break; 689 break;
677 } 690 }
678 } else { 691 } else {
679 DavResource *child = response2resource( 692 DavResource *child = response2resource(
680 sn, 693 sn,
689 //resource_add_child(root, child); 702 //resource_add_child(root, child);
690 resource_add_ordered_child(root, child, ordercr); 703 resource_add_ordered_child(root, child, ordercr);
691 if(child->iscollection && 704 if(child->iscollection &&
692 (depth < 0 || depth > sr->depth+1)) 705 (depth < 0 || depth > sr->depth+1))
693 { 706 {
694 DavQLRes *rs = ucx_mempool_malloc( 707 DavQLRes rs;
695 mp, 708 rs.resource = child;
696 sizeof(DavQLRes)); 709 rs.depth = sr->depth + 1;
697 rs->resource = child; 710 cxListInsert(stack, 0, &rs);
698 rs->depth = sr->depth + 1;
699 stack = ucx_list_prepend(stack, rs);
700 } 711 }
701 } else { 712 } else {
702 dav_resource_free(child); 713 dav_resource_free(child);
703 } 714 }
704 } else { 715 } else {
715 dav_resource_free_all(selroot); 726 dav_resource_free_all(selroot);
716 break; 727 break;
717 } 728 }
718 729
719 // reset response buffer 730 // reset response buffer
720 ucx_buffer_seek(rpbuf, SEEK_SET, 0); 731 cxBufferSeek(rpbuf, SEEK_SET, 0);
721 } 732 }
722 733
723 ucx_mempool_destroy(mp); 734 cxMempoolDestroy(mp);
724 return result; 735 return result;
725 } 736 }
726 737
727 static int count_func_args(DavQLExpression *expr) { 738 static int count_func_args(DavQLExpression *expr) {
728 int count = 0; 739 int count = 0;
736 } 747 }
737 } 748 }
738 return count; 749 return count;
739 } 750 }
740 751
741 int dav_identifier2resprop(sstr_t src, davqlresprop_t *prop) { 752 int dav_identifier2resprop(cxstring src, davqlresprop_t *prop) {
742 if(!sstrcmp(src, S("name"))) { 753 if(!cx_strcmp(src, CX_STR("name"))) {
743 *prop = DAVQL_RES_NAME; 754 *prop = DAVQL_RES_NAME;
744 } else if(!sstrcmp(src, S("path"))) { 755 } else if(!cx_strcmp(src, CX_STR("path"))) {
745 *prop = DAVQL_RES_PATH; 756 *prop = DAVQL_RES_PATH;
746 } else if(!sstrcmp(src, S("href"))) { 757 } else if(!cx_strcmp(src, CX_STR("href"))) {
747 *prop = DAVQL_RES_HREF; 758 *prop = DAVQL_RES_HREF;
748 } else if(!sstrcmp(src, S("contentlength"))) { 759 } else if(!cx_strcmp(src, CX_STR("contentlength"))) {
749 *prop = DAVQL_RES_CONTENTLENGTH; 760 *prop = DAVQL_RES_CONTENTLENGTH;
750 } else if(!sstrcmp(src, S("contenttype"))) { 761 } else if(!cx_strcmp(src, CX_STR("contenttype"))) {
751 *prop = DAVQL_RES_CONTENTTYPE; 762 *prop = DAVQL_RES_CONTENTTYPE;
752 } else if(!sstrcmp(src, S("creationdate"))) { 763 } else if(!cx_strcmp(src, CX_STR("creationdate"))) {
753 *prop = DAVQL_RES_CREATIONDATE; 764 *prop = DAVQL_RES_CREATIONDATE;
754 } else if(!sstrcmp(src, S("lastmodified"))) { 765 } else if(!cx_strcmp(src, CX_STR("lastmodified"))) {
755 *prop = DAVQL_RES_LASTMODIFIED; 766 *prop = DAVQL_RES_LASTMODIFIED;
756 } else if(!sstrcmp(src, S("iscollection"))) { 767 } else if(!cx_strcmp(src, CX_STR("iscollection"))) {
757 *prop = DAVQL_RES_ISCOLLECTION; 768 *prop = DAVQL_RES_ISCOLLECTION;
758 } else { 769 } else {
759 return 0; 770 return 0;
760 } 771 }
761 return 1; 772 return 1;
762 } 773 }
763 774
764 static int add_cmd(DavContext *ctx, UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, DavQLArgList *ap) { 775 static int add_cmd(DavContext *ctx, const CxAllocator *a, CxBuffer *bcode, DavQLExpression *expr, DavQLArgList *ap) {
765 if(!expr) { 776 if(!expr) {
766 return 0; 777 return 0;
767 } 778 }
768 779
769 int numcmd = 1; 780 int numcmd = 1;
770 DavQLCmd cmd; 781 DavQLCmd cmd;
771 memset(&cmd, 0, sizeof(DavQLCmd)); 782 memset(&cmd, 0, sizeof(DavQLCmd));
772 davqlerror_t error; 783 davqlerror_t error;
773 784
774 sstr_t src = expr->srctext; 785 cxstring src = expr->srctext;
775 switch(expr->type) { 786 switch(expr->type) {
776 default: break; 787 default: break;
777 case DAVQL_NUMBER: { 788 case DAVQL_NUMBER: {
778 cmd.type = DAVQL_CMD_INT; 789 cmd.type = DAVQL_CMD_INT;
779 if(src.ptr[0] == '%') { 790 if(src.ptr[0] == '%') {
780 cmd.data.integer = dav_ql_getarg_int(ap); 791 cmd.data.integer = dav_ql_getarg_int(ap);
781 } else if(util_strtoint(src.ptr, &cmd.data.integer)) { 792 } else if(util_strtoint(src.ptr, &cmd.data.integer)) {
782 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 793 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
783 } else { 794 } else {
784 // error 795 // error
785 return -1; 796 return -1;
786 } 797 }
787 798
788 break; 799 break;
789 } 800 }
790 case DAVQL_STRING: { 801 case DAVQL_STRING: {
791 cmd.type = DAVQL_CMD_STRING; 802 cmd.type = DAVQL_CMD_STRING;
792 cmd.data.string = dav_format_string(a, src, ap, &error); 803 cmd.data.string = dav_format_string(a, src, ap, &error);
793 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 804 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
794 break; 805 break;
795 } 806 }
796 case DAVQL_TIMESTAMP: { 807 case DAVQL_TIMESTAMP: {
797 if(src.ptr[0] == '%') { 808 if(src.ptr[0] == '%') {
798 cmd.type = DAVQL_CMD_TIMESTAMP; 809 cmd.type = DAVQL_CMD_TIMESTAMP;
799 cmd.data.timestamp = dav_ql_getarg_time(ap); 810 cmd.data.timestamp = dav_ql_getarg_time(ap);
800 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 811 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
801 } else { 812 } else {
802 // error 813 // error
803 return -1; 814 return -1;
804 } 815 }
805 break; 816 break;
806 } 817 }
807 case DAVQL_IDENTIFIER: { 818 case DAVQL_IDENTIFIER: {
808 sstr_t propertyname = sstrchr(src, ':'); 819 cxstring propertyname = cx_strchr(src, ':');
809 cmd.type = DAVQL_CMD_RES_IDENTIFIER; 820 cmd.type = DAVQL_CMD_RES_IDENTIFIER;
810 if(propertyname.length > 0) { 821 if(propertyname.length > 0) {
811 cmd.type = DAVQL_CMD_PROP_IDENTIFIER; 822 cmd.type = DAVQL_CMD_PROP_IDENTIFIER;
812 char *ns; 823 char *ns;
813 char *name; 824 char *name;
814 dav_get_property_namespace_str( 825 dav_get_property_namespace_str(
815 ctx, 826 ctx,
816 sstrdup_a(a, src).ptr, 827 cx_strdup_a(a, src).ptr,
817 &ns, 828 &ns,
818 &name); 829 &name);
819 if(ns && name) { 830 if(ns && name) {
820 cmd.data.property.ns = ns; 831 cmd.data.property.ns = ns;
821 cmd.data.property.name = name; 832 cmd.data.property.name = name;
822 } else { 833 } else {
823 // error 834 // error
824 return -1; 835 return -1;
825 } 836 }
826 } else if(!dav_identifier2resprop(src, &cmd.data.resprop)) { 837 } else if(!dav_identifier2resprop(src, &cmd.data.resprop)) {
827 if(!sstrcmp(src, S("true"))) { 838 if(!cx_strcmp(src, CX_STR("true"))) {
828 cmd.type = DAVQL_CMD_INT; 839 cmd.type = DAVQL_CMD_INT;
829 cmd.data.integer = 1; 840 cmd.data.integer = 1;
830 } else if(!sstrcmp(src, S("false"))) { 841 } else if(!cx_strcmp(src, CX_STR("false"))) {
831 cmd.type = DAVQL_CMD_INT; 842 cmd.type = DAVQL_CMD_INT;
832 cmd.data.integer = 0; 843 cmd.data.integer = 0;
833 } else { 844 } else {
834 // error, unknown identifier 845 // error, unknown identifier
835 return -1; 846 return -1;
836 } 847 }
837 } 848 }
838 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 849 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
839 break; 850 break;
840 } 851 }
841 case DAVQL_UNARY: { 852 case DAVQL_UNARY: {
842 numcmd += add_cmd(ctx, a, bcode, expr->left, ap); 853 numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
843 switch(expr->op) { 854 switch(expr->op) {
846 numcmd = 0; 857 numcmd = 0;
847 break; 858 break;
848 } 859 }
849 case DAVQL_SUB: { 860 case DAVQL_SUB: {
850 cmd.type = DAVQL_CMD_OP_UNARY_SUB; 861 cmd.type = DAVQL_CMD_OP_UNARY_SUB;
851 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 862 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
852 break; 863 break;
853 } 864 }
854 case DAVQL_NEG: { 865 case DAVQL_NEG: {
855 cmd.type = DAVQL_CMD_OP_UNARY_NEG; 866 cmd.type = DAVQL_CMD_OP_UNARY_NEG;
856 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 867 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
857 break; 868 break;
858 } 869 }
859 default: break; 870 default: break;
860 } 871 }
861 break; 872 break;
892 cmd.type = DAVQL_CMD_OP_BINARY_XOR; 903 cmd.type = DAVQL_CMD_OP_BINARY_XOR;
893 break; 904 break;
894 } 905 }
895 default: break; 906 default: break;
896 } 907 }
897 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 908 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
898 break; 909 break;
899 } 910 }
900 case DAVQL_LOGICAL: { 911 case DAVQL_LOGICAL: {
901 if(expr->left && expr->right && expr->op != DAVQL_LOR) { 912 if(expr->left && expr->right && expr->op != DAVQL_LOR) {
902 numcmd += add_cmd(ctx, a, bcode, expr->left, ap); 913 numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
905 916
906 switch(expr->op) { 917 switch(expr->op) {
907 case DAVQL_NOT: { 918 case DAVQL_NOT: {
908 numcmd += add_cmd(ctx, a, bcode, expr->left, ap); 919 numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
909 cmd.type = DAVQL_CMD_OP_LOGICAL_NOT; 920 cmd.type = DAVQL_CMD_OP_LOGICAL_NOT;
910 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 921 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
911 break; 922 break;
912 } 923 }
913 case DAVQL_LAND: { 924 case DAVQL_LAND: {
914 cmd.type = DAVQL_CMD_OP_LOGICAL_AND; 925 cmd.type = DAVQL_CMD_OP_LOGICAL_AND;
915 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 926 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
916 break; 927 break;
917 } 928 }
918 case DAVQL_LOR: { 929 case DAVQL_LOR: {
919 int nleft = add_cmd(ctx, a, bcode, expr->left, ap); 930 int nleft = add_cmd(ctx, a, bcode, expr->left, ap);
920 931
921 cmd.type = DAVQL_CMD_OP_LOGICAL_OR_L; 932 cmd.type = DAVQL_CMD_OP_LOGICAL_OR_L;
922 DavQLCmd *or_l = (DavQLCmd*)(bcode->space + bcode->pos); 933 DavQLCmd *or_l = (DavQLCmd*)(bcode->space + bcode->pos);
923 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 934 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
924 935
925 int nright = add_cmd(ctx, a, bcode, expr->right, ap); 936 int nright = add_cmd(ctx, a, bcode, expr->right, ap);
926 or_l->data.integer = nright + 1; 937 or_l->data.integer = nright + 1;
927 938
928 cmd.type = DAVQL_CMD_OP_LOGICAL_OR; 939 cmd.type = DAVQL_CMD_OP_LOGICAL_OR;
929 cmd.data.integer = 0; 940 cmd.data.integer = 0;
930 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 941 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
931 942
932 numcmd += nleft + nright; 943 numcmd += nleft + nright;
933 break; 944 break;
934 } 945 }
935 case DAVQL_LXOR: { 946 case DAVQL_LXOR: {
936 cmd.type = DAVQL_CMD_OP_LOGICAL_XOR; 947 cmd.type = DAVQL_CMD_OP_LOGICAL_XOR;
937 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 948 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
938 break; 949 break;
939 } 950 }
940 case DAVQL_EQ: { 951 case DAVQL_EQ: {
941 cmd.type = DAVQL_CMD_OP_EQ; 952 cmd.type = DAVQL_CMD_OP_EQ;
942 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 953 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
943 break; 954 break;
944 } 955 }
945 case DAVQL_NEQ: { 956 case DAVQL_NEQ: {
946 cmd.type = DAVQL_CMD_OP_NEQ; 957 cmd.type = DAVQL_CMD_OP_NEQ;
947 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 958 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
948 break; 959 break;
949 } 960 }
950 case DAVQL_LT: { 961 case DAVQL_LT: {
951 cmd.type = DAVQL_CMD_OP_LT; 962 cmd.type = DAVQL_CMD_OP_LT;
952 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 963 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
953 break; 964 break;
954 } 965 }
955 case DAVQL_GT: { 966 case DAVQL_GT: {
956 cmd.type = DAVQL_CMD_OP_GT; 967 cmd.type = DAVQL_CMD_OP_GT;
957 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 968 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
958 break; 969 break;
959 } 970 }
960 case DAVQL_LE: { 971 case DAVQL_LE: {
961 cmd.type = DAVQL_CMD_OP_LE; 972 cmd.type = DAVQL_CMD_OP_LE;
962 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 973 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
963 break; 974 break;
964 } 975 }
965 case DAVQL_GE: { 976 case DAVQL_GE: {
966 cmd.type = DAVQL_CMD_OP_GE; 977 cmd.type = DAVQL_CMD_OP_GE;
967 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 978 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
968 break; 979 break;
969 } 980 }
970 case DAVQL_LIKE: { 981 case DAVQL_LIKE: {
971 cmd.type = DAVQL_CMD_OP_LIKE; 982 cmd.type = DAVQL_CMD_OP_LIKE;
972 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 983 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
973 break; 984 break;
974 } 985 }
975 case DAVQL_UNLIKE: { 986 case DAVQL_UNLIKE: {
976 cmd.type = DAVQL_CMD_OP_UNLIKE; 987 cmd.type = DAVQL_CMD_OP_UNLIKE;
977 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 988 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
978 break; 989 break;
979 } 990 }
980 default: break; 991 default: break;
981 } 992 }
982 break; 993 break;
993 } 1004 }
994 1005
995 // numargs 1006 // numargs
996 cmd.type = DAVQL_CMD_INT; 1007 cmd.type = DAVQL_CMD_INT;
997 cmd.data.integer = count_func_args(expr); 1008 cmd.data.integer = count_func_args(expr);
998 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 1009 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
999 1010
1000 // TODO: resolve function name 1011 // TODO: resolve function name
1001 cmd.type = DAVQL_CMD_CALL; 1012 cmd.type = DAVQL_CMD_CALL;
1002 cmd.data.func = NULL; 1013 cmd.data.func = NULL;
1003 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 1014 cxBufferWrite(&cmd, sizeof(cmd), 1, bcode);
1004 1015
1005 numcmd = 2; 1016 numcmd = 2;
1006 numcmd += nright; 1017 numcmd += nright;
1007 break; 1018 break;
1008 } 1019 }
1018 } 1029 }
1019 } 1030 }
1020 return numcmd; 1031 return numcmd;
1021 } 1032 }
1022 1033
1023 UcxBuffer* dav_compile_expr(DavContext *ctx, UcxAllocator *a, DavQLExpression *lexpr, DavQLArgList *ap) { 1034 CxBuffer* dav_compile_expr(DavContext *ctx, const CxAllocator *a, DavQLExpression *lexpr, DavQLArgList *ap) {
1024 UcxBuffer *bcode = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND); 1035 CxBuffer *bcode = cxBufferCreate(NULL, 512, a, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
1025 if(!bcode) { 1036 if(!bcode) {
1026 return NULL; 1037 return NULL;
1027 } 1038 }
1028 1039
1029 if(add_cmd(ctx, a, bcode, lexpr, ap) <= 0) { 1040 if(add_cmd(ctx, a, bcode, lexpr, ap) <= 0) {
1030 ucx_buffer_free(bcode); 1041 cxBufferFree(bcode);
1031 return NULL; 1042 return NULL;
1032 } 1043 }
1033 1044
1034 return bcode; 1045 return bcode;
1035 } 1046 }
1036 1047
1037 static int cmd_str_cmp(DavQLStackObj obj1, DavQLStackObj obj2, davqlcmdtype_t cmd) { 1048 static int cmd_str_cmp(DavQLStackObj obj1, DavQLStackObj obj2, davqlcmdtype_t cmd) {
1038 sstr_t s1 = obj1.type == 1 ? 1049 cxmutstr s1m = obj1.type == 1 ?
1039 sstrn(obj1.data.string, obj1.length) : 1050 cx_mutstrn(obj1.data.string, obj1.length) :
1040 ucx_sprintf("%" PRId64, obj1.data.integer); 1051 cx_asprintf("%" PRId64, obj1.data.integer);
1041 sstr_t s2 = obj1.type == 1 ? 1052 cxmutstr s2m = obj1.type == 1 ?
1042 sstrn(obj2.data.string, obj2.length) : 1053 cx_mutstrn(obj2.data.string, obj2.length) :
1043 ucx_sprintf("%" PRId64, obj2.data.integer); 1054 cx_asprintf("%" PRId64, obj2.data.integer);
1055
1056 cxstring s1 = cx_strcast(s1m);
1057 cxstring s2 = cx_strcast(s2m);
1044 1058
1045 int res = 0; 1059 int res = 0;
1046 switch(cmd) { 1060 switch(cmd) {
1047 case DAVQL_CMD_OP_EQ: { 1061 case DAVQL_CMD_OP_EQ: {
1048 res = sstrcmp(s1, s2) == 0; 1062 res = cx_strcmp(s1, s2) == 0;
1049 break; 1063 break;
1050 } 1064 }
1051 case DAVQL_CMD_OP_NEQ: { 1065 case DAVQL_CMD_OP_NEQ: {
1052 res = sstrcmp(s1, s2) != 0; 1066 res = cx_strcmp(s1, s2) != 0;
1053 break; 1067 break;
1054 } 1068 }
1055 case DAVQL_CMD_OP_LT: { 1069 case DAVQL_CMD_OP_LT: {
1056 res = sstrcmp(s1, s2) < 0; 1070 res = cx_strcmp(s1, s2) < 0;
1057 break; 1071 break;
1058 } 1072 }
1059 case DAVQL_CMD_OP_GT: { 1073 case DAVQL_CMD_OP_GT: {
1060 res = sstrcmp(s1, s2) > 0; 1074 res = cx_strcmp(s1, s2) > 0;
1061 break; 1075 break;
1062 } 1076 }
1063 case DAVQL_CMD_OP_LE: { 1077 case DAVQL_CMD_OP_LE: {
1064 res = sstrcmp(s1, s2) <= 0; 1078 res = cx_strcmp(s1, s2) <= 0;
1065 break; 1079 break;
1066 } 1080 }
1067 case DAVQL_CMD_OP_GE: { 1081 case DAVQL_CMD_OP_GE: {
1068 res = sstrcmp(s1, s2) >= 0; 1082 res = cx_strcmp(s1, s2) >= 0;
1069 break; 1083 break;
1070 } 1084 }
1071 default: break; 1085 default: break;
1072 } 1086 }
1073 1087
1074 if(obj1.type == 0) { 1088 if(obj1.type == 0) {
1075 free(s1.ptr); 1089 free(s1m.ptr);
1076 } 1090 }
1077 if(obj2.type == 0) { 1091 if(obj2.type == 0) {
1078 free(s2.ptr); 1092 free(s2m.ptr);
1079 } 1093 }
1080 1094
1081 return res; 1095 return res;
1082 } 1096 }
1083 1097
1084 int dav_exec_expr(UcxBuffer *bcode, DavResource *res, DavQLStackObj *result) { 1098 int dav_exec_expr(CxBuffer *bcode, DavResource *res, DavQLStackObj *result) {
1085 if(!bcode) { 1099 if(!bcode) {
1086 result->type = 0; 1100 result->type = 0;
1087 result->length = 0; 1101 result->length = 0;
1088 result->data.integer = 1; 1102 result->data.integer = 1;
1089 return 0; 1103 return 0;

mercurial