| 373 } |
373 } |
| 374 |
374 |
| 375 return v; |
375 return v; |
| 376 } |
376 } |
| 377 |
377 |
| 378 static int json_obj_add_entry(const CxJson *json, char *name) { |
|
| 379 CxJsonObjValue kv = {name, NULL}; |
|
| 380 assert(json->vbuf_size > 0); |
|
| 381 CxJsonValue *parent = json->vbuf[json->vbuf_size - 1]; |
|
| 382 assert(parent != NULL); |
|
| 383 assert(parent->type == CX_JSON_OBJECT); |
|
| 384 CxArrayReallocator value_realloc = cx_array_reallocator(json->allocator, NULL); |
|
| 385 return cx_array_simple_add_a(&value_realloc, parent->value.object.values, kv); |
|
| 386 } |
|
| 387 |
|
| 388 #define JP_STATE_VALUE_BEGIN 0 |
378 #define JP_STATE_VALUE_BEGIN 0 |
| 389 #define JP_STATE_VALUE_END 10 |
379 #define JP_STATE_VALUE_END 10 |
| 390 #define JP_STATE_VALUE_BEGIN_OBJ 1 |
380 #define JP_STATE_VALUE_BEGIN_OBJ 1 |
| 391 #define JP_STATE_OBJ_SEP_OR_CLOSE 11 |
381 #define JP_STATE_OBJ_SEP_OR_CLOSE 11 |
| 392 #define JP_STATE_VALUE_BEGIN_AR 2 |
382 #define JP_STATE_VALUE_BEGIN_AR 2 |
| 566 // add new entry |
556 // add new entry |
| 567 cxmutstr name = unescape_string(json->allocator, token.content); |
557 cxmutstr name = unescape_string(json->allocator, token.content); |
| 568 if (name.ptr == NULL) { |
558 if (name.ptr == NULL) { |
| 569 return_rec(CX_JSON_VALUE_ALLOC_FAILED); |
559 return_rec(CX_JSON_VALUE_ALLOC_FAILED); |
| 570 } |
560 } |
| 571 json_obj_add_entry(json, name.ptr); |
561 CxJsonObjValue kv = {name, NULL}; |
| |
562 assert(json->vbuf_size > 0); |
| |
563 CxJsonValue *parent = json->vbuf[json->vbuf_size - 1]; |
| |
564 assert(parent != NULL); |
| |
565 assert(parent->type == CX_JSON_OBJECT); |
| |
566 CxArrayReallocator value_realloc = cx_array_reallocator(json->allocator, NULL); |
| |
567 if (cx_array_simple_add_a(&value_realloc, parent->value.object.values, kv)) { |
| |
568 return_rec(CX_JSON_VALUE_ALLOC_FAILED); |
| |
569 } |
| 572 |
570 |
| 573 // next state |
571 // next state |
| 574 json_add_state(json, JP_STATE_OBJ_COLON); |
572 json_add_state(json, JP_STATE_OBJ_COLON); |
| 575 return_rec(CX_JSON_NO_ERROR); |
573 return_rec(CX_JSON_NO_ERROR); |
| 576 } |
574 } |
| 641 switch (value->type) { |
639 switch (value->type) { |
| 642 case CX_JSON_OBJECT: { |
640 case CX_JSON_OBJECT: { |
| 643 CxJsonObject obj = value->value.object; |
641 CxJsonObject obj = value->value.object; |
| 644 for (size_t i = 0; i < obj.values_size; i++) { |
642 for (size_t i = 0; i < obj.values_size; i++) { |
| 645 cxJsonValueFree(obj.values[i].value); |
643 cxJsonValueFree(obj.values[i].value); |
| 646 cxFree(value->allocator, obj.values[i].name); |
644 cx_strfree_a(value->allocator, &obj.values[i].name); |
| 647 } |
645 } |
| 648 cxFree(value->allocator, obj.values); |
646 cxFree(value->allocator, obj.values); |
| 649 break; |
647 break; |
| 650 } |
648 } |
| 651 case CX_JSON_ARRAY: { |
649 case CX_JSON_ARRAY: { |
| 705 iter.base.mutating = false; |
703 iter.base.mutating = false; |
| 706 |
704 |
| 707 return iter; |
705 return iter; |
| 708 } |
706 } |
| 709 |
707 |
| 710 CxJsonValue *cxJsonObjGet(const CxJsonValue *value, const char *name) { |
708 CxJsonValue *cx_json_obj_get_cxstr(const CxJsonValue *value, cxstring name) { |
| 711 const CxJsonObject *obj = &(value->value.object); |
709 const CxJsonObject *obj = &(value->value.object); |
| 712 // TODO: think about sorting the object so that we can use binary search here |
710 // TODO: think about sorting the object so that we can use binary search here |
| 713 for (size_t i = 0; i < obj->values_size; i++) { |
711 for (size_t i = 0; i < obj->values_size; i++) { |
| 714 if (0 == strcmp(name, obj->values[i].name)) { |
712 if (0 == cx_strcmp(name, cx_strcast(obj->values[i].name))) { |
| 715 return obj->values[i].value; |
713 return obj->values[i].value; |
| 716 } |
714 } |
| 717 } |
715 } |
| 718 return &cx_json_value_nothing; |
716 return &cx_json_value_nothing; |
| 719 } |
717 } |