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 } |