diff options
Diffstat (limited to 'xs_json.h')
| -rw-r--r-- | xs_json.h | 163 |
1 files changed, 94 insertions, 69 deletions
| @@ -8,6 +8,7 @@ | |||
| 8 | #define MAX_JSON_DEPTH 32 | 8 | #define MAX_JSON_DEPTH 32 |
| 9 | #endif | 9 | #endif |
| 10 | 10 | ||
| 11 | void xs_json_dump_value(const xs_val *data, int level, int indent, FILE *f); | ||
| 11 | int xs_json_dump(const xs_val *data, int indent, FILE *f); | 12 | int xs_json_dump(const xs_val *data, int indent, FILE *f); |
| 12 | xs_str *xs_json_dumps(const xs_val *data, int indent); | 13 | xs_str *xs_json_dumps(const xs_val *data, int indent); |
| 13 | 14 | ||
| @@ -19,8 +20,8 @@ xs_val *xs_json_loads_full(const xs_str *json, int maxdepth); | |||
| 19 | xstype xs_json_load_type(FILE *f); | 20 | xstype xs_json_load_type(FILE *f); |
| 20 | int xs_json_load_array_iter(FILE *f, xs_val **value, xstype *pt, int *c); | 21 | int xs_json_load_array_iter(FILE *f, xs_val **value, xstype *pt, int *c); |
| 21 | int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, xstype *pt, int *c); | 22 | int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, xstype *pt, int *c); |
| 22 | xs_list *xs_json_load_array(FILE *f, int maxdepth); | 23 | int xs_json_load_array(FILE *f, int maxdepth, xs_list **l); |
| 23 | xs_dict *xs_json_load_object(FILE *f, int maxdepth); | 24 | int xs_json_load_object(FILE *f, int maxdepth, xs_dict **d); |
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | #ifdef XS_IMPLEMENTATION | 27 | #ifdef XS_IMPLEMENTATION |
| @@ -77,7 +78,7 @@ static void _xs_json_indent(int level, int indent, FILE *f) | |||
| 77 | } | 78 | } |
| 78 | 79 | ||
| 79 | 80 | ||
| 80 | static void _xs_json_dump(const xs_val *data, int level, int indent, FILE *f) | 81 | void xs_json_dump_value(const xs_val *data, int level, int indent, FILE *f) |
| 81 | /* dumps partial data as JSON */ | 82 | /* dumps partial data as JSON */ |
| 82 | { | 83 | { |
| 83 | int c = 0; | 84 | int c = 0; |
| @@ -108,7 +109,7 @@ static void _xs_json_dump(const xs_val *data, int level, int indent, FILE *f) | |||
| 108 | fputc(',', f); | 109 | fputc(',', f); |
| 109 | 110 | ||
| 110 | _xs_json_indent(level + 1, indent, f); | 111 | _xs_json_indent(level + 1, indent, f); |
| 111 | _xs_json_dump(v, level + 1, indent, f); | 112 | xs_json_dump_value(v, level + 1, indent, f); |
| 112 | 113 | ||
| 113 | c++; | 114 | c++; |
| 114 | } | 115 | } |
| @@ -135,7 +136,7 @@ static void _xs_json_dump(const xs_val *data, int level, int indent, FILE *f) | |||
| 135 | if (indent) | 136 | if (indent) |
| 136 | fputc(' ', f); | 137 | fputc(' ', f); |
| 137 | 138 | ||
| 138 | _xs_json_dump(v, level + 1, indent, f); | 139 | xs_json_dump_value(v, level + 1, indent, f); |
| 139 | 140 | ||
| 140 | c++; | 141 | c++; |
| 141 | } | 142 | } |
| @@ -154,6 +155,20 @@ static void _xs_json_dump(const xs_val *data, int level, int indent, FILE *f) | |||
| 154 | } | 155 | } |
| 155 | 156 | ||
| 156 | 157 | ||
| 158 | int xs_json_dump(const xs_val *data, int indent, FILE *f) | ||
| 159 | /* dumps data into a file as JSON */ | ||
| 160 | { | ||
| 161 | xstype t = xs_type(data); | ||
| 162 | |||
| 163 | if (t == XSTYPE_LIST || t == XSTYPE_DICT) { | ||
| 164 | xs_json_dump_value(data, 0, indent, f); | ||
| 165 | return 1; | ||
| 166 | } | ||
| 167 | |||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | |||
| 157 | xs_str *xs_json_dumps(const xs_val *data, int indent) | 172 | xs_str *xs_json_dumps(const xs_val *data, int indent) |
| 158 | /* dumps data as a JSON string */ | 173 | /* dumps data as a JSON string */ |
| 159 | { | 174 | { |
| @@ -173,20 +188,6 @@ xs_str *xs_json_dumps(const xs_val *data, int indent) | |||
| 173 | } | 188 | } |
| 174 | 189 | ||
| 175 | 190 | ||
| 176 | int xs_json_dump(const xs_val *data, int indent, FILE *f) | ||
| 177 | /* dumps data into a file as JSON */ | ||
| 178 | { | ||
| 179 | xstype t = xs_type(data); | ||
| 180 | |||
| 181 | if (t == XSTYPE_LIST || t == XSTYPE_DICT) { | ||
| 182 | _xs_json_dump(data, 0, indent, f); | ||
| 183 | return 1; | ||
| 184 | } | ||
| 185 | |||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | |||
| 189 | |||
| 190 | /** JSON loads **/ | 191 | /** JSON loads **/ |
| 191 | 192 | ||
| 192 | typedef enum { | 193 | typedef enum { |
| @@ -370,6 +371,8 @@ int xs_json_load_array_iter(FILE *f, xs_val **value, xstype *pt, int *c) | |||
| 370 | else | 371 | else |
| 371 | return -1; | 372 | return -1; |
| 372 | } | 373 | } |
| 374 | else | ||
| 375 | *pt = xs_type(*value); | ||
| 373 | 376 | ||
| 374 | *c = *c + 1; | 377 | *c = *c + 1; |
| 375 | 378 | ||
| @@ -377,43 +380,51 @@ int xs_json_load_array_iter(FILE *f, xs_val **value, xstype *pt, int *c) | |||
| 377 | } | 380 | } |
| 378 | 381 | ||
| 379 | 382 | ||
| 380 | xs_list *xs_json_load_array(FILE *f, int maxdepth) | 383 | int xs_json_load_array(FILE *f, int maxdepth, xs_list **l) |
| 381 | /* loads a full JSON array (after the initial OBRACK) */ | 384 | /* loads a full JSON array (after the initial OBRACK) */ |
| 385 | /* l can be NULL for the content to be dropped */ | ||
| 382 | { | 386 | { |
| 383 | xstype t; | 387 | xstype t; |
| 384 | xs_list *l = xs_list_new(); | 388 | int r = 0; |
| 385 | int c = 0; | 389 | int c = 0; |
| 386 | 390 | ||
| 387 | for (;;) { | 391 | for (;;) { |
| 388 | xs *v = NULL; | 392 | xs *v = NULL; |
| 389 | int r = xs_json_load_array_iter(f, &v, &t, &c); | 393 | r = xs_json_load_array_iter(f, &v, &t, &c); |
| 390 | |||
| 391 | if (r == -1) | ||
| 392 | l = xs_free(l); | ||
| 393 | 394 | ||
| 394 | if (r == 1) { | 395 | if (r == 1) { |
| 395 | /* partial load? */ | 396 | /* partial load? */ |
| 396 | if (v == NULL && maxdepth != 0) { | 397 | if (v == NULL && maxdepth != 0) { |
| 397 | if (t == XSTYPE_LIST) | 398 | if (t == XSTYPE_LIST) { |
| 398 | v = xs_json_load_array(f, maxdepth - 1); | 399 | if (l) |
| 400 | v = xs_list_new(); | ||
| 401 | |||
| 402 | r = xs_json_load_array(f, maxdepth - 1, &v); | ||
| 403 | } | ||
| 399 | else | 404 | else |
| 400 | if (t == XSTYPE_DICT) | 405 | if (t == XSTYPE_DICT) { |
| 401 | v = xs_json_load_object(f, maxdepth - 1); | 406 | if (l) |
| 407 | v = xs_dict_new(); | ||
| 408 | |||
| 409 | r = xs_json_load_object(f, maxdepth - 1, &v); | ||
| 410 | } | ||
| 402 | } | 411 | } |
| 403 | 412 | ||
| 404 | /* still null? fail */ | 413 | /* error? */ |
| 405 | if (v == NULL) { | 414 | if (r < 0) |
| 406 | l = xs_free(l); | ||
| 407 | break; | 415 | break; |
| 408 | } | ||
| 409 | 416 | ||
| 410 | l = xs_list_append(l, v); | 417 | if (l) |
| 418 | *l = xs_list_append(*l, v); | ||
| 411 | } | 419 | } |
| 412 | else | 420 | else |
| 413 | break; | 421 | break; |
| 414 | } | 422 | } |
| 415 | 423 | ||
| 416 | return l; | 424 | if (r < 0 && l) |
| 425 | *l = xs_free(*l); | ||
| 426 | |||
| 427 | return r; | ||
| 417 | } | 428 | } |
| 418 | 429 | ||
| 419 | 430 | ||
| @@ -458,6 +469,8 @@ int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, xstype *pt, | |||
| 458 | else | 469 | else |
| 459 | return -1; | 470 | return -1; |
| 460 | } | 471 | } |
| 472 | else | ||
| 473 | *pt = xs_type(*value); | ||
| 461 | 474 | ||
| 462 | *c = *c + 1; | 475 | *c = *c + 1; |
| 463 | 476 | ||
| @@ -465,59 +478,52 @@ int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, xstype *pt, | |||
| 465 | } | 478 | } |
| 466 | 479 | ||
| 467 | 480 | ||
| 468 | xs_dict *xs_json_load_object(FILE *f, int maxdepth) | 481 | int xs_json_load_object(FILE *f, int maxdepth, xs_dict **d) |
| 469 | /* loads a full JSON object (after the initial OCURLY) */ | 482 | /* loads a full JSON object (after the initial OCURLY) */ |
| 483 | /* d can be NULL for the content to be dropped */ | ||
| 470 | { | 484 | { |
| 471 | xstype t; | 485 | xstype t; |
| 472 | xs_dict *d = xs_dict_new(); | 486 | int r = 0; |
| 473 | int c = 0; | 487 | int c = 0; |
| 474 | 488 | ||
| 475 | for (;;) { | 489 | for (;;) { |
| 476 | xs *k = NULL; | 490 | xs *k = NULL; |
| 477 | xs *v = NULL; | 491 | xs *v = NULL; |
| 478 | int r = xs_json_load_object_iter(f, &k, &v, &t, &c); | 492 | r = xs_json_load_object_iter(f, &k, &v, &t, &c); |
| 479 | |||
| 480 | if (r == -1) | ||
| 481 | d = xs_free(d); | ||
| 482 | 493 | ||
| 483 | if (r == 1) { | 494 | if (r == 1) { |
| 484 | /* partial load? */ | 495 | /* partial load? */ |
| 485 | if (v == NULL && maxdepth != 0) { | 496 | if (v == NULL && maxdepth != 0) { |
| 486 | if (t == XSTYPE_LIST) | 497 | if (t == XSTYPE_LIST) { |
| 487 | v = xs_json_load_array(f, maxdepth - 1); | 498 | if (d) |
| 499 | v = xs_list_new(); | ||
| 500 | |||
| 501 | r = xs_json_load_array(f, maxdepth - 1, &v); | ||
| 502 | } | ||
| 488 | else | 503 | else |
| 489 | if (t == XSTYPE_DICT) | 504 | if (t == XSTYPE_DICT) { |
| 490 | v = xs_json_load_object(f, maxdepth - 1); | 505 | if (d) |
| 506 | v = xs_dict_new(); | ||
| 507 | |||
| 508 | r = xs_json_load_object(f, maxdepth - 1, &v); | ||
| 509 | } | ||
| 491 | } | 510 | } |
| 492 | 511 | ||
| 493 | /* still null? fail */ | 512 | /* error? */ |
| 494 | if (v == NULL) { | 513 | if (r < 0) |
| 495 | d = xs_free(d); | ||
| 496 | break; | 514 | break; |
| 497 | } | ||
| 498 | 515 | ||
| 499 | d = xs_dict_append(d, k, v); | 516 | if (d) |
| 517 | *d = xs_dict_append(*d, k, v); | ||
| 500 | } | 518 | } |
| 501 | else | 519 | else |
| 502 | break; | 520 | break; |
| 503 | } | 521 | } |
| 504 | 522 | ||
| 505 | return d; | 523 | if (r < 0 && d) |
| 506 | } | 524 | *d = xs_free(*d); |
| 507 | |||
| 508 | |||
| 509 | xs_val *xs_json_loads_full(const xs_str *json, int maxdepth) | ||
| 510 | /* loads a string in JSON format and converts to a multiple data */ | ||
| 511 | { | ||
| 512 | FILE *f; | ||
| 513 | xs_val *v = NULL; | ||
| 514 | |||
| 515 | if ((f = fmemopen((char *)json, strlen(json), "r")) != NULL) { | ||
| 516 | v = xs_json_load_full(f, maxdepth); | ||
| 517 | fclose(f); | ||
| 518 | } | ||
| 519 | 525 | ||
| 520 | return v; | 526 | return r; |
| 521 | } | 527 | } |
| 522 | 528 | ||
| 523 | 529 | ||
| @@ -545,11 +551,30 @@ xs_val *xs_json_load_full(FILE *f, int maxdepth) | |||
| 545 | xs_val *v = NULL; | 551 | xs_val *v = NULL; |
| 546 | xstype t = xs_json_load_type(f); | 552 | xstype t = xs_json_load_type(f); |
| 547 | 553 | ||
| 548 | if (t == XSTYPE_LIST) | 554 | if (t == XSTYPE_LIST) { |
| 549 | v = xs_json_load_array(f, maxdepth); | 555 | v = xs_list_new(); |
| 556 | xs_json_load_array(f, maxdepth, &v); | ||
| 557 | } | ||
| 550 | else | 558 | else |
| 551 | if (t == XSTYPE_DICT) | 559 | if (t == XSTYPE_DICT) { |
| 552 | v = xs_json_load_object(f, maxdepth); | 560 | v = xs_dict_new(); |
| 561 | xs_json_load_object(f, maxdepth, &v); | ||
| 562 | } | ||
| 563 | |||
| 564 | return v; | ||
| 565 | } | ||
| 566 | |||
| 567 | |||
| 568 | xs_val *xs_json_loads_full(const xs_str *json, int maxdepth) | ||
| 569 | /* loads a string in JSON format and converts to a multiple data */ | ||
| 570 | { | ||
| 571 | FILE *f; | ||
| 572 | xs_val *v = NULL; | ||
| 573 | |||
| 574 | if ((f = fmemopen((char *)json, strlen(json), "r")) != NULL) { | ||
| 575 | v = xs_json_load_full(f, maxdepth); | ||
| 576 | fclose(f); | ||
| 577 | } | ||
| 553 | 578 | ||
| 554 | return v; | 579 | return v; |
| 555 | } | 580 | } |