38 * RFC 8259 |
39 * RFC 8259 |
39 * https://tools.ietf.org/html/rfc8259 |
40 * https://tools.ietf.org/html/rfc8259 |
40 */ |
41 */ |
41 |
42 |
42 static CxJsonValue cx_json_value_nothing = {.type = CX_JSON_NOTHING}; |
43 static CxJsonValue cx_json_value_nothing = {.type = CX_JSON_NOTHING}; |
|
44 |
|
45 static int json_cmp_objvalue(const void *l, const void *r) { |
|
46 const CxJsonObjValue *left = l; |
|
47 const CxJsonObjValue *right = r; |
|
48 return cx_strcmp(cx_strcast(left->name), cx_strcast(right->name)); |
|
49 } |
|
50 |
|
51 static CxJsonObjValue *json_find_objvalue(const CxJsonValue *obj, cxstring name) { |
|
52 assert(obj->type == CX_JSON_OBJECT); |
|
53 CxJsonObjValue kv_dummy; |
|
54 kv_dummy.name = cx_mutstrn((char*) name.ptr, name.length); |
|
55 size_t index = cx_array_binary_search( |
|
56 obj->value.object.values, |
|
57 obj->value.object.values_size, |
|
58 sizeof(CxJsonObjValue), |
|
59 &kv_dummy, |
|
60 json_cmp_objvalue |
|
61 ); |
|
62 if (index == obj->value.object.values_size) { |
|
63 return NULL; |
|
64 } else { |
|
65 return &obj->value.object.values[index]; |
|
66 } |
|
67 } |
|
68 |
|
69 static int json_add_objvalue(CxJsonValue *obj, CxJsonObjValue member) { |
|
70 assert(obj->type == CX_JSON_OBJECT); |
|
71 CxArrayReallocator value_realloc = cx_array_reallocator(obj->allocator, NULL); |
|
72 return cx_array_simple_add_sorted_a( |
|
73 &value_realloc, obj->value.object.values, |
|
74 member, json_cmp_objvalue |
|
75 ); |
|
76 } |
43 |
77 |
44 static void token_destroy(CxJsonToken *token) { |
78 static void token_destroy(CxJsonToken *token) { |
45 if (token->allocated) { |
79 if (token->allocated) { |
46 cx_strfree(&token->content); |
80 cx_strfree(&token->content); |
47 } |
81 } |
292 if (v == NULL) return NULL; // LCOV_EXCL_LINE |
326 if (v == NULL) return NULL; // LCOV_EXCL_LINE |
293 |
327 |
294 // initialize the value |
328 // initialize the value |
295 if (type == CX_JSON_ARRAY) { |
329 if (type == CX_JSON_ARRAY) { |
296 cx_array_initialize_a(json->allocator, v->value.array.array, 16); |
330 cx_array_initialize_a(json->allocator, v->value.array.array, 16); |
297 if (v->value.array.array == NULL) { // LCOV_EXCL_START |
331 if (v->value.array.array == NULL) goto create_json_value_exit_error; // LCOV_EXCL_LINE |
298 cxFree(json->allocator, v); |
|
299 return NULL; |
|
300 } // LCOV_EXCL_STOP |
|
301 } else if (type == CX_JSON_OBJECT) { |
332 } else if (type == CX_JSON_OBJECT) { |
302 cx_array_initialize_a(json->allocator, v->value.object.values, 16); |
333 cx_array_initialize_a(json->allocator, v->value.object.values, 16); |
303 if (v->value.object.values == NULL) { // LCOV_EXCL_START |
334 if (v->value.object.values == NULL) goto create_json_value_exit_error; // LCOV_EXCL_LINE |
304 cxFree(json->allocator, v); |
|
305 return NULL; |
|
306 } // LCOV_EXCL_STOP |
|
307 } else { |
335 } else { |
308 memset(v, 0, sizeof(CxJsonValue)); |
336 memset(v, 0, sizeof(CxJsonValue)); |
309 } |
337 } |
310 v->type = type; |
338 v->type = type; |
311 v->allocator = json->allocator; |
339 v->allocator = json->allocator; |
312 |
340 |
313 // add the new value to a possible parent |
341 // add the new value to a possible parent |
314 CxArrayReallocator value_realloc = cx_array_reallocator(json->allocator, NULL); |
|
315 if (json->vbuf_size > 0) { |
342 if (json->vbuf_size > 0) { |
316 CxJsonValue *parent = json->vbuf[json->vbuf_size - 1]; |
343 CxJsonValue *parent = json->vbuf[json->vbuf_size - 1]; |
|
344 assert(parent != NULL); |
317 if (parent->type == CX_JSON_ARRAY) { |
345 if (parent->type == CX_JSON_ARRAY) { |
318 cx_array_simple_add_a(&value_realloc, parent->value.array.array, v); |
346 CxArrayReallocator value_realloc = cx_array_reallocator(json->allocator, NULL); |
|
347 if (cx_array_simple_add_a(&value_realloc, parent->value.array.array, v)) { |
|
348 goto create_json_value_exit_error; // LCOV_EXCL_LINE |
|
349 } |
319 } else if (parent->type == CX_JSON_OBJECT) { |
350 } else if (parent->type == CX_JSON_OBJECT) { |
320 assert(parent->value.object.values_size > 0); |
351 // the member was already created after parsing the name |
321 assert(parent->value.object.values[parent->value.object.values_size - 1].value == NULL); |
352 assert(json->uncompleted_member.name.ptr != NULL); |
322 parent->value.object.values[parent->value.object.values_size - 1].value = v; |
353 json->uncompleted_member.value = v; |
|
354 if (json_add_objvalue(parent, json->uncompleted_member)) { |
|
355 goto create_json_value_exit_error; // LCOV_EXCL_LINE |
|
356 } |
|
357 json->uncompleted_member.name = (cxmutstr) {NULL, 0}; |
323 } else { |
358 } else { |
324 assert(false); // LCOV_EXCL_LINE |
359 assert(false); // LCOV_EXCL_LINE |
325 } |
360 } |
326 } |
361 } |
327 |
362 |
328 // add the new value to the stack, if it is an array or object |
363 // add the new value to the stack, if it is an array or object |
329 if (type == CX_JSON_ARRAY || type == CX_JSON_OBJECT) { |
364 if (type == CX_JSON_ARRAY || type == CX_JSON_OBJECT) { |
330 CxArrayReallocator vbuf_realloc = cx_array_reallocator(NULL, json->vbuf_internal); |
365 CxArrayReallocator vbuf_realloc = cx_array_reallocator(NULL, json->vbuf_internal); |
331 if (cx_array_simple_add_a(&vbuf_realloc, json->vbuf, v)) { |
366 if (cx_array_simple_add_a(&vbuf_realloc, json->vbuf, v)) { |
332 // LCOV_EXCL_START |
367 goto create_json_value_exit_error; // LCOV_EXCL_LINE |
333 cxFree(json->allocator, v); |
368 } |
334 return NULL; |
|
335 } // LCOV_EXCL_STOP |
|
336 } |
369 } |
337 |
370 |
338 // if currently no value is parsed, this is now the value of interest |
371 // if currently no value is parsed, this is now the value of interest |
339 if (json->parsed == NULL) { |
372 if (json->parsed == NULL) { |
340 json->parsed = v; |
373 json->parsed = v; |
341 } |
374 } |
342 |
375 |
343 return v; |
376 return v; |
|
377 // LCOV_EXCL_START |
|
378 create_json_value_exit_error: |
|
379 cxFree(json->allocator, v); |
|
380 return NULL; |
|
381 // LCOV_EXCL_STOP |
344 } |
382 } |
345 |
383 |
346 #define JP_STATE_VALUE_BEGIN 0 |
384 #define JP_STATE_VALUE_BEGIN 0 |
347 #define JP_STATE_VALUE_END 10 |
385 #define JP_STATE_VALUE_END 10 |
348 #define JP_STATE_VALUE_BEGIN_OBJ 1 |
386 #define JP_STATE_VALUE_BEGIN_OBJ 1 |
528 // add new entry |
566 // add new entry |
529 cxmutstr name = unescape_string(json->allocator, token.content); |
567 cxmutstr name = unescape_string(json->allocator, token.content); |
530 if (name.ptr == NULL) { |
568 if (name.ptr == NULL) { |
531 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
569 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
532 } |
570 } |
533 CxJsonObjValue kv = {name, NULL}; |
571 assert(json->uncompleted_member.name.ptr == NULL); |
|
572 json->uncompleted_member.name = name; |
534 assert(json->vbuf_size > 0); |
573 assert(json->vbuf_size > 0); |
535 CxJsonValue *parent = json->vbuf[json->vbuf_size - 1]; |
|
536 assert(parent != NULL); |
|
537 assert(parent->type == CX_JSON_OBJECT); |
|
538 CxArrayReallocator value_realloc = cx_array_reallocator(json->allocator, NULL); |
|
539 if (cx_array_simple_add_a(&value_realloc, parent->value.object.values, kv)) { |
|
540 return_rec(CX_JSON_VALUE_ALLOC_FAILED); // LCOV_EXCL_LINE |
|
541 } |
|
542 |
574 |
543 // next state |
575 // next state |
544 json_add_state(json, JP_STATE_OBJ_COLON); |
576 json_add_state(json, JP_STATE_OBJ_COLON); |
545 return_rec(CX_JSON_NO_ERROR); |
577 return_rec(CX_JSON_NO_ERROR); |
546 } |
578 } |
793 obj->value.object.values[i].value = child; |
825 obj->value.object.values[i].value = child; |
794 return 0; |
826 return 0; |
795 } |
827 } |
796 } |
828 } |
797 |
829 |
798 CxArrayReallocator value_realloc = cx_array_reallocator(obj->allocator, NULL); |
|
799 assert(obj->type == CX_JSON_OBJECT); |
|
800 cxmutstr k = cx_strdup_a(obj->allocator, name); |
830 cxmutstr k = cx_strdup_a(obj->allocator, name); |
801 if (k.ptr == NULL) return -1; |
831 if (k.ptr == NULL) return -1; |
802 CxJsonObjValue kv = {k, child}; |
832 CxJsonObjValue kv = {k, child}; |
803 return cx_array_simple_add_a(&value_realloc, obj->value.object.values, kv); |
833 return json_add_objvalue(obj, kv); |
804 } |
834 } |
805 |
835 |
806 CxJsonValue* cxJsonObjPutObj(CxJsonValue* obj, cxstring name) { |
836 CxJsonValue* cxJsonObjPutObj(CxJsonValue* obj, cxstring name) { |
807 CxJsonValue* v = cxJsonCreateObj(obj->allocator); |
837 CxJsonValue* v = cxJsonCreateObj(obj->allocator); |
808 if (v == NULL) return NULL; |
838 if (v == NULL) return NULL; |