195 case DAVQL_IDENTIFIER: { |
217 case DAVQL_IDENTIFIER: { |
196 sstr_t propertyname = sstrchr(src, ':'); |
218 sstr_t propertyname = sstrchr(src, ':'); |
197 cmd.type = DAVQL_CMD_RES_IDENTIFIER; |
219 cmd.type = DAVQL_CMD_RES_IDENTIFIER; |
198 if(propertyname.length > 0) { |
220 if(propertyname.length > 0) { |
199 cmd.type = DAVQL_CMD_PROP_IDENTIFIER; |
221 cmd.type = DAVQL_CMD_PROP_IDENTIFIER; |
200 |
222 if(identifier2propname(a, src, &cmd.data.property)) { |
201 // TODO |
223 // error |
|
224 return -1; |
|
225 } |
202 } else if(!sstrcmp(src, S("name"))) { |
226 } else if(!sstrcmp(src, S("name"))) { |
203 cmd.data.resprop = DAVQL_RES_NAME; |
227 cmd.data.resprop = DAVQL_RES_NAME; |
204 } else if(!sstrcmp(src, S("path"))) { |
228 } else if(!sstrcmp(src, S("path"))) { |
205 cmd.data.resprop = DAVQL_RES_PATH; |
229 cmd.data.resprop = DAVQL_RES_PATH; |
206 } else if(!sstrcmp(src, S("href"))) { |
230 } else if(!sstrcmp(src, S("href"))) { |
213 cmd.data.resprop = DAVQL_RES_CREATIONDATE; |
237 cmd.data.resprop = DAVQL_RES_CREATIONDATE; |
214 } else if(!sstrcmp(src, S("lastmodified"))) { |
238 } else if(!sstrcmp(src, S("lastmodified"))) { |
215 cmd.data.resprop = DAVQL_RES_LASTMODIFIED; |
239 cmd.data.resprop = DAVQL_RES_LASTMODIFIED; |
216 } else if(!sstrcmp(src, S("iscollection"))) { |
240 } else if(!sstrcmp(src, S("iscollection"))) { |
217 cmd.data.resprop = DAVQL_RES_ISCOLLECTION; |
241 cmd.data.resprop = DAVQL_RES_ISCOLLECTION; |
|
242 } else if(!sstrcmp(src, S("true"))) { |
|
243 cmd.type = DAVQL_CMD_INT; |
|
244 cmd.data.integer = 1; |
|
245 } else if(!sstrcmp(src, S("false"))) { |
|
246 cmd.type = DAVQL_CMD_INT; |
|
247 cmd.data.integer = 0; |
|
248 } else { |
|
249 // error, unknown identifier |
|
250 return -1; |
218 } |
251 } |
219 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
252 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
220 break; |
253 break; |
221 } |
254 } |
222 case DAVQL_UNARY: { |
255 case DAVQL_UNARY: { |
407 } |
440 } |
408 |
441 |
409 return bcode; |
442 return bcode; |
410 } |
443 } |
411 |
444 |
|
445 int dav_exec_expr(UcxBuffer *bcode, DavResource *res, DavQLStackObj *result) { |
|
446 size_t count = bcode->pos / sizeof(DavQLCmd); |
|
447 DavQLCmd *cmds = (DavQLCmd*)bcode->space; |
|
448 |
|
449 // create execution stack |
|
450 size_t stsize = 64; |
|
451 size_t stpos = 0; |
|
452 DavQLStackObj *stack = calloc(stsize, sizeof(DavQLStackObj)); |
|
453 #define DAVQL_PUSH(obj) \ |
|
454 if(stpos == stsize) { \ |
|
455 stsize += 64; \ |
|
456 stack = realloc(stack, stsize * sizeof(DavQLStackObj)); \ |
|
457 } \ |
|
458 stack[stpos++] = obj; |
|
459 #define DAVQL_POP() stack[--stpos] |
|
460 |
|
461 DavQLStackObj obj; |
|
462 for(size_t i=0;i<count;i++) { |
|
463 DavQLCmd cmd = cmds[i]; |
|
464 switch(cmd.type) { |
|
465 case DAVQL_CMD_INT: { |
|
466 printf("int %lld\n", cmd.data.integer); |
|
467 obj.type = 0; |
|
468 obj.length = 0; |
|
469 obj.data.integer = cmd.data.integer; |
|
470 DAVQL_PUSH(obj); |
|
471 break; |
|
472 } |
|
473 case DAVQL_CMD_STRING: { |
|
474 printf("string \"%.*s\"\n", cmd.data.string.length, cmd.data.string.ptr); |
|
475 obj.type = 1; |
|
476 obj.length = cmd.data.string.length; |
|
477 obj.data.string = cmd.data.string.ptr; |
|
478 DAVQL_PUSH(obj); |
|
479 break; |
|
480 } |
|
481 case DAVQL_CMD_TIMESTAMP: { |
|
482 printf("timestamp %d\n", cmd.data.timestamp); |
|
483 obj.type = 0; |
|
484 obj.length = 0; |
|
485 obj.data.integer = cmd.data.timestamp; |
|
486 DAVQL_PUSH(obj); |
|
487 break; |
|
488 } |
|
489 case DAVQL_CMD_RES_IDENTIFIER: { |
|
490 char *rid[8] = {"name", "path", "href", "contentlength", "contenttype", "creationdate", "lastmodified", "iscollection"}; |
|
491 printf("resprop %s\n", rid[cmd.data.resprop]); |
|
492 switch(cmd.data.resprop) { |
|
493 case DAVQL_RES_NAME: { |
|
494 obj.type = 1; |
|
495 obj.length = strlen(res->name); |
|
496 obj.data.string = res->name; |
|
497 break; |
|
498 } |
|
499 case DAVQL_RES_PATH: { |
|
500 obj.type = 1; |
|
501 obj.length = strlen(res->path); |
|
502 obj.data.string = res->path; |
|
503 break; |
|
504 } |
|
505 case DAVQL_RES_HREF: { |
|
506 obj.type = 1; |
|
507 obj.length = strlen(res->href); |
|
508 obj.data.string = res->href; |
|
509 break; |
|
510 } |
|
511 case DAVQL_RES_CONTENTLENGTH: { |
|
512 obj.type = 0; |
|
513 obj.length = 0; |
|
514 obj.data.integer = res->contentlength; |
|
515 break; |
|
516 } |
|
517 case DAVQL_RES_CONTENTTYPE: { |
|
518 obj.type = 1; |
|
519 obj.length = strlen(res->contenttype); |
|
520 obj.data.string = res->contenttype; |
|
521 break; |
|
522 } |
|
523 case DAVQL_RES_CREATIONDATE: { |
|
524 obj.type = 0; |
|
525 obj.length = 0; |
|
526 obj.data.integer = res->creationdate; |
|
527 break; |
|
528 } |
|
529 case DAVQL_RES_LASTMODIFIED: { |
|
530 obj.type = 0; |
|
531 obj.length = 0; |
|
532 obj.data.integer = res->lastmodified; |
|
533 break; |
|
534 } |
|
535 case DAVQL_RES_ISCOLLECTION: { |
|
536 obj.type = 0; |
|
537 obj.length = 0; |
|
538 obj.data.integer = res->iscollection; |
|
539 break; |
|
540 } |
|
541 } |
|
542 DAVQL_PUSH(obj); |
|
543 break; |
|
544 } |
|
545 case DAVQL_CMD_PROP_IDENTIFIER: { |
|
546 printf("property %s:%s\n", cmd.data.property.ns, cmd.data.property.name); |
|
547 char *value = dav_get_property_ns(res, cmd.data.property.ns, cmd.data.property.name); |
|
548 obj.type = 1; |
|
549 obj.length = value ? strlen(value) : 0; |
|
550 obj.data.string = value; |
|
551 DAVQL_PUSH(obj); |
|
552 break; |
|
553 } |
|
554 case DAVQL_CMD_OP_UNARY_ADD: { |
|
555 printf("uadd\n"); |
|
556 break; |
|
557 } |
|
558 case DAVQL_CMD_OP_UNARY_SUB: { |
|
559 printf("usub\n"); |
|
560 break; |
|
561 } |
|
562 case DAVQL_CMD_OP_UNARY_NEG: { |
|
563 printf("uneg\n"); |
|
564 break; |
|
565 } |
|
566 case DAVQL_CMD_OP_BINARY_ADD: { |
|
567 printf("add\n"); |
|
568 break; |
|
569 } |
|
570 case DAVQL_CMD_OP_BINARY_SUB: { |
|
571 printf("sub\n"); |
|
572 break; |
|
573 } |
|
574 case DAVQL_CMD_OP_BINARY_MUL: { |
|
575 printf("mul\n"); |
|
576 break; |
|
577 } |
|
578 case DAVQL_CMD_OP_BINARY_DIV: { |
|
579 printf("div\n"); |
|
580 break; |
|
581 } |
|
582 case DAVQL_CMD_OP_BINARY_AND: { |
|
583 printf("and\n"); |
|
584 break; |
|
585 } |
|
586 case DAVQL_CMD_OP_BINARY_OR: { |
|
587 printf("or\n"); |
|
588 break; |
|
589 } |
|
590 case DAVQL_CMD_OP_BINARY_XOR: { |
|
591 printf("xor\n"); |
|
592 break; |
|
593 } |
|
594 case DAVQL_CMD_OP_LOGICAL_NOT: { |
|
595 printf("not\n"); |
|
596 break; |
|
597 } |
|
598 case DAVQL_CMD_OP_LOGICAL_AND: { |
|
599 printf("land\n"); |
|
600 break; |
|
601 } |
|
602 case DAVQL_CMD_OP_LOGICAL_OR_L: { |
|
603 printf("or_l %d\n", cmd.data.integer); |
|
604 break; |
|
605 } |
|
606 case DAVQL_CMD_OP_LOGICAL_OR: { |
|
607 printf("or\n"); |
|
608 break; |
|
609 } |
|
610 case DAVQL_CMD_OP_LOGICAL_XOR: { |
|
611 printf("lxor\n"); |
|
612 break; |
|
613 } |
|
614 case DAVQL_CMD_OP_EQ: { |
|
615 printf("eq\n"); |
|
616 break; |
|
617 } |
|
618 case DAVQL_CMD_OP_NEQ: { |
|
619 printf("neq\n"); |
|
620 break; |
|
621 } |
|
622 case DAVQL_CMD_OP_LT: { |
|
623 printf("lt\n"); |
|
624 break; |
|
625 } |
|
626 case DAVQL_CMD_OP_GT: { |
|
627 printf("gt\n"); |
|
628 DavQLStackObj obj2 = DAVQL_POP(); |
|
629 DavQLStackObj obj1 = DAVQL_POP(); |
|
630 // result |
|
631 obj.type = 0; |
|
632 obj.length = 0; |
|
633 |
|
634 int64_t int1; |
|
635 int64_t int2; |
|
636 int isint = 1; |
|
637 if(obj1.type == 0) { |
|
638 int1 = obj1.data.integer; |
|
639 } else { |
|
640 isint = util_strtoint(obj1.data.string, &int1); |
|
641 } |
|
642 if(isint) { |
|
643 if(obj2.type == 0) { |
|
644 int2 = obj2.data.integer; |
|
645 } else { |
|
646 isint = util_strtoint(obj2.data.string, &int2); |
|
647 } |
|
648 if(isint) { |
|
649 obj.data.integer = int1 > int2; |
|
650 } |
|
651 } |
|
652 |
|
653 // string compare |
|
654 // TODO |
|
655 DAVQL_PUSH(obj); |
|
656 break; |
|
657 } |
|
658 case DAVQL_CMD_OP_LE: { |
|
659 printf("le\n"); |
|
660 break; |
|
661 } |
|
662 case DAVQL_CMD_OP_GE: { |
|
663 printf("ge\n"); |
|
664 break; |
|
665 } |
|
666 case DAVQL_CMD_OP_LIKE: { |
|
667 printf("like\n"); |
|
668 break; |
|
669 } |
|
670 case DAVQL_CMD_OP_UNLIKE: { |
|
671 printf("unlike\n"); |
|
672 break; |
|
673 } |
|
674 case DAVQL_CMD_CALL: { |
|
675 printf("call %x\n", cmd.data.func); |
|
676 break; |
|
677 } |
|
678 } |
|
679 } |
|
680 |
|
681 for(int i=0;i<stpos;i++) { |
|
682 DavQLStackObj obj = stack[i]; |
|
683 if(obj.type == 0) { |
|
684 printf("stack: int=%lld\n", obj.data.integer); |
|
685 } else { |
|
686 printf("stack: string=\"%.*s\"\n", obj.length, obj.data.string); |
|
687 } |
|
688 } |
|
689 return 0; |
|
690 } |
|
691 |
412 |
692 |
413 void print_bytecode(UcxBuffer *bcode) { |
693 void print_bytecode(UcxBuffer *bcode) { |
414 bcode->pos = 0; |
694 bcode->pos = 0; |
415 DavQLCmd cmd; |
695 DavQLCmd cmd; |
416 while(ucx_buffer_read(&cmd, sizeof(DavQLCmd), 1, bcode) == 1) { |
696 while(ucx_buffer_read(&cmd, sizeof(DavQLCmd), 1, bcode) == 1) { |
417 switch(cmd.type) { |
697 switch(cmd.type) { |
418 case DAVQL_CMD_INT: { |
698 case DAVQL_CMD_INT: { |
419 printf("int %ll\n", cmd.data.integer); |
699 printf("int %lld\n", cmd.data.integer); |
420 break; |
700 break; |
421 } |
701 } |
422 case DAVQL_CMD_STRING: { |
702 case DAVQL_CMD_STRING: { |
423 printf("string \"%.*s\"\n", cmd.data.string.length, cmd.data.string.ptr); |
703 printf("string \"%.*s\"\n", cmd.data.string.length, cmd.data.string.ptr); |
424 break; |
704 break; |