36 * RFC 8259 |
36 * RFC 8259 |
37 * https://tools.ietf.org/html/rfc8259 |
37 * https://tools.ietf.org/html/rfc8259 |
38 */ |
38 */ |
39 |
39 |
40 #define PARSER_STATES_ALLOC 32 |
40 #define PARSER_STATES_ALLOC 32 |
|
41 #define PARSER_READVALUE_ALLOC 32 |
41 |
42 |
42 static CxJsonValue cx_json_value_nothing = {.type = CX_JSON_NOTHING}; |
43 static CxJsonValue cx_json_value_nothing = {.type = CX_JSON_NOTHING}; |
43 |
44 |
44 |
45 |
45 static int token_append(CxJsonToken *token, const char *buf, size_t len) { |
46 static int token_append(CxJsonToken *token, const char *buf, size_t len) { |
337 |
338 |
338 return 0; |
339 return 0; |
339 } |
340 } |
340 |
341 |
341 static int add_state(CxJson *p, int state) { |
342 static int add_state(CxJson *p, int state) { |
|
343 // TODO: this is such a common pattern, try to reuse code here |
342 if (p->nstates >= p->states_alloc) { |
344 if (p->nstates >= p->states_alloc) { |
343 p->states_alloc += PARSER_STATES_ALLOC; |
345 unsigned newcap = PARSER_STATES_ALLOC; |
344 if (cx_reallocate(&p->states, p->states_alloc * sizeof(int))) { |
346 if (p->states == p->states_internal) { |
345 return 1; |
347 void *mem = malloc(newcap * sizeof(int)); |
346 } |
348 if (mem == NULL) return 1; |
|
349 memcpy(mem, p->states, p->nstates * sizeof(int)); |
|
350 p->states = mem; |
|
351 } else { |
|
352 newcap += p->states_alloc; |
|
353 if (cx_reallocate(&p->states, newcap * sizeof(int))) { |
|
354 return 1; |
|
355 } |
|
356 } |
|
357 p->states_alloc = newcap; |
347 } |
358 } |
348 p->states[++p->nstates] = state; |
359 p->states[++p->nstates] = state; |
349 return 0; |
360 return 0; |
350 } |
361 } |
351 |
362 |
543 } |
554 } |
544 |
555 |
545 /* -------------------- read value functions -------------------- */ |
556 /* -------------------- read value functions -------------------- */ |
546 |
557 |
547 static int setup_read_value(CxJson *p) { |
558 static int setup_read_value(CxJson *p) { |
548 p->readvalue_alloc = PARSER_STATES_ALLOC; |
559 p->readvalue_alloc = PARSER_READVALUE_ALLOC; |
549 p->readvalue_nelm = 0; |
560 p->readvalue_nelm = 0; |
550 p->readvalue_stack = calloc(PARSER_STATES_ALLOC, sizeof(CxJsonValue *)); |
561 p->readvalue_stack = calloc(p->readvalue_alloc, sizeof(CxJsonValue *)); |
551 if (!p->readvalue_stack) return -1; |
562 if (!p->readvalue_stack) return -1; |
552 |
563 |
553 p->read_value = NULL; |
564 p->read_value = NULL; |
554 p->readvalue_stack[0] = NULL; |
565 p->readvalue_stack[0] = NULL; |
555 |
566 |
657 return 0; |
668 return 0; |
658 } |
669 } |
659 |
670 |
660 void cxJsonInit(CxJson *json) { |
671 void cxJsonInit(CxJson *json) { |
661 memset(json, 0, sizeof(CxJson)); |
672 memset(json, 0, sizeof(CxJson)); |
662 // TODO: do not allocate states right away |
673 json->states = json->states_internal; |
663 json->states_alloc = PARSER_STATES_ALLOC; |
674 json->states_alloc = cx_nmemb(json->states_internal); |
664 json->states = calloc(PARSER_STATES_ALLOC, sizeof(int)); |
|
665 // TODO: find better way to configure the initial allocation size for arrays and objects |
675 // TODO: find better way to configure the initial allocation size for arrays and objects |
666 json->reader_array_alloc = 8; |
676 json->reader_array_alloc = 8; |
667 } |
677 } |
668 |
678 |
669 void cxJsonDestroy(CxJson *p) { |
679 void cxJsonDestroy(CxJson *p) { |
670 free(p->states); |
680 if (p->states != p->states_internal) { |
|
681 free(p->states); |
|
682 } |
671 free(p->readvalue_stack); |
683 free(p->readvalue_stack); |
672 cxJsonValueFree(p->read_value); |
684 cxJsonValueFree(p->read_value); |
673 free(p->value_name); |
685 free(p->value_name); |
674 free(p->value_str); |
686 free(p->value_str); |
675 } |
687 } |
682 } |
694 } |
683 |
695 |
684 int cxJsonNext(CxJson *p, CxJsonValue **value) { |
696 int cxJsonNext(CxJson *p, CxJsonValue **value) { |
685 // TODO: replace int with a status enum like in CxProperties |
697 // TODO: replace int with a status enum like in CxProperties |
686 |
698 |
687 *value = NULL; |
699 *value = NULL; // TODO: maybe better initialize with NOTHING? |
688 if (!p->readvalue_stack) { |
700 if (!p->readvalue_stack) { |
689 if (setup_read_value(p)) return -1; |
701 if (setup_read_value(p)) return -1; |
690 } |
702 } |
691 |
703 |
692 while (p->readvalue_nelm > 0 || !p->read_value) { |
704 while (p->readvalue_nelm > 0 || !p->read_value) { |