| 564 p->readvalue_stack[0] = NULL; |
563 p->readvalue_stack[0] = NULL; |
| 565 |
564 |
| 566 return 0; |
565 return 0; |
| 567 } |
566 } |
| 568 |
567 |
| 569 static int obj_init_values(CxJson *p, CxJsonValue *v) { |
|
| 570 v->value.object.values = calloc(p->reader_array_alloc, sizeof(CxJsonObjValue)); |
|
| 571 if (!v->value.object.values) { |
|
| 572 return -1; |
|
| 573 } |
|
| 574 v->value.object.alloc = p->reader_array_alloc; |
|
| 575 v->value.object.size = 0; |
|
| 576 |
|
| 577 return 0; |
|
| 578 } |
|
| 579 |
|
| 580 static int obj_add_value(CxJson *p, CxJsonValue *parent, CxJsonObjValue v) { |
|
| 581 if (!parent->value.object.values) { |
|
| 582 if (obj_init_values(p, parent)) { |
|
| 583 return -1; |
|
| 584 } |
|
| 585 } |
|
| 586 |
|
| 587 if (parent->value.object.size == parent->value.object.alloc) { |
|
| 588 parent->value.object.alloc *= 2; |
|
| 589 if (cx_reallocate(&parent->value.object.values, |
|
| 590 sizeof(CxJsonObjValue) * parent->value.object.alloc)) { |
|
| 591 return -1; |
|
| 592 } |
|
| 593 } |
|
| 594 |
|
| 595 parent->value.object.values[parent->value.object.size++] = v; |
|
| 596 |
|
| 597 return 0; |
|
| 598 } |
|
| 599 |
|
| 600 static int array_init(CxJson *p, CxJsonValue *v) { |
|
| 601 v->value.array.array = calloc(p->reader_array_alloc, sizeof(CxJsonValue *)); |
|
| 602 if (!v->value.array.array) { |
|
| 603 return -1; |
|
| 604 } |
|
| 605 v->value.array.alloc = p->reader_array_alloc; |
|
| 606 v->value.array.size = 0; |
|
| 607 |
|
| 608 return 0; |
|
| 609 } |
|
| 610 |
|
| 611 static int array_add_value(CxJson *p, CxJsonValue *parent, CxJsonValue *v) { |
|
| 612 if (!parent->value.array.array) { |
|
| 613 if (array_init(p, parent)) { |
|
| 614 return -1; |
|
| 615 } |
|
| 616 } |
|
| 617 |
|
| 618 if (parent->value.array.size == parent->value.array.alloc) { |
|
| 619 parent->value.array.alloc *= 2; |
|
| 620 if (cx_reallocate(parent->value.array.array, |
|
| 621 sizeof(CxJsonValue *) * parent->value.array.alloc)) { |
|
| 622 return -1; |
|
| 623 } |
|
| 624 } |
|
| 625 |
|
| 626 parent->value.array.array[parent->value.array.size++] = v; |
|
| 627 |
|
| 628 return 0; |
|
| 629 } |
|
| 630 |
|
| 631 static int add_to_parent(CxJson *p, CxJsonValue *parent, CxJsonValue *v) { |
568 static int add_to_parent(CxJson *p, CxJsonValue *parent, CxJsonValue *v) { |
| 632 if (!parent) { |
569 if (!parent) { |
| 633 return -1; // shouldn't happen but who knows |
570 return -1; // shouldn't happen but who knows |
| 634 } |
571 } |
| 635 |
572 |
| 636 int ret = 0; |
|
| 637 if (parent->type == CX_JSON_OBJECT) { |
573 if (parent->type == CX_JSON_OBJECT) { |
| 638 if (!p->value_name || p->value_name_len == 0) { |
574 if (!p->value_name || p->value_name_len == 0) { |
| 639 return -1; |
575 return -1; |
| 640 } |
576 } |
| 641 char *valuename = p->value_name; |
577 char *valuename = p->value_name; |
| 643 |
579 |
| 644 CxJsonObjValue newvalue; |
580 CxJsonObjValue newvalue; |
| 645 newvalue.name = valuename; |
581 newvalue.name = valuename; |
| 646 newvalue.value = v; |
582 newvalue.value = v; |
| 647 |
583 |
| 648 ret = obj_add_value(p, parent, newvalue); |
584 return cx_array_simple_add(parent->value.object.values, newvalue); |
| 649 } else if (parent->type == CX_JSON_ARRAY) { |
585 } else if (parent->type == CX_JSON_ARRAY) { |
| 650 ret = array_add_value(p, parent, v); |
586 return cx_array_simple_add(parent->value.array.array, v); |
| 651 } else { |
587 } else { |
| 652 ret = -1; // should also never happen |
588 return -1; // should also never happen |
| 653 } |
589 } |
| 654 |
|
| 655 return ret; |
|
| 656 } |
590 } |
| 657 |
591 |
| 658 |
592 |
| 659 static int readvaluestack_add(CxJson *p, CxJsonValue *v) { |
593 static int readvaluestack_add(CxJson *p, CxJsonValue *v) { |
| 660 if (p->readvalue_nelm == p->readvalue_alloc) { |
594 if (p->readvalue_nelm == p->readvalue_alloc) { |
| 790 |
724 |
| 791 // TODO: discuss if we should keep freeing the stuff recursively |
725 // TODO: discuss if we should keep freeing the stuff recursively |
| 792 switch (value->type) { |
726 switch (value->type) { |
| 793 case CX_JSON_OBJECT: { |
727 case CX_JSON_OBJECT: { |
| 794 CxJsonObject obj = value->value.object; |
728 CxJsonObject obj = value->value.object; |
| 795 for (size_t i = 0; i < obj.size; i++) { |
729 for (size_t i = 0; i < obj.values_size; i++) { |
| 796 cxJsonValueFree(obj.values[i].value); |
730 cxJsonValueFree(obj.values[i].value); |
| 797 free(obj.values[i].name); |
731 free(obj.values[i].name); |
| 798 } |
732 } |
| 799 free(obj.values); |
733 free(obj.values); |
| 800 break; |
734 break; |
| 801 } |
735 } |
| 802 case CX_JSON_ARRAY: { |
736 case CX_JSON_ARRAY: { |
| 803 CxJsonArray array = value->value.array; |
737 CxJsonArray array = value->value.array; |
| 804 for (size_t i = 0; i < array.size; i++) { |
738 for (size_t i = 0; i < array.array_size; i++) { |
| 805 cxJsonValueFree(array.array[i]); |
739 cxJsonValueFree(array.array[i]); |
| 806 } |
740 } |
| 807 free(array.array); |
741 free(array.array); |
| 808 break; |
742 break; |
| 809 } |
743 } |
| 817 } |
751 } |
| 818 free(value); |
752 free(value); |
| 819 } |
753 } |
| 820 |
754 |
| 821 CxJsonValue *cxJsonArrGet(CxJsonValue *value, size_t index) { |
755 CxJsonValue *cxJsonArrGet(CxJsonValue *value, size_t index) { |
| 822 if (index >= value->value.array.size) { |
756 if (index >= value->value.array.array_size) { |
| 823 return &cx_json_value_nothing; |
757 return &cx_json_value_nothing; |
| 824 } |
758 } |
| 825 return value->value.array.array[index]; |
759 return value->value.array.array[index]; |
| 826 } |
760 } |
| 827 |
761 |
| 828 CxJsonValue *cxJsonObjGet(CxJsonValue *value, const char *name) { |
762 CxJsonValue *cxJsonObjGet(CxJsonValue *value, const char *name) { |
| 829 CxJsonObject *obj = &(value->value.object); |
763 CxJsonObject *obj = &(value->value.object); |
| 830 // TODO: think about sorting the object so that we can use binary search here |
764 // TODO: think about sorting the object so that we can use binary search here |
| 831 for (size_t i = 0; i < obj->size; i++) { |
765 for (size_t i = 0; i < obj->values_size; i++) { |
| 832 // TODO: we might want to store names as cxmutstr |
766 // TODO: we might want to store names as cxmutstr |
| 833 if (0 == strcmp(name, obj->values[i].name)) { |
767 if (0 == strcmp(name, obj->values[i].name)) { |
| 834 return obj->values[i].value; |
768 return obj->values[i].value; |
| 835 } |
769 } |
| 836 } |
770 } |