diff options
| author | 2023-09-03 20:22:32 +0200 | |
|---|---|---|
| committer | 2023-09-03 20:22:32 +0200 | |
| commit | 8535fc84c92e42ca379558b3c0a3a9a2d0faedaa (patch) | |
| tree | 115bddc23890b45322a5088cb4308696f22820cf /xs_json.h | |
| parent | Improved heart <3 emoji. (diff) | |
| download | snac2-8535fc84c92e42ca379558b3c0a3a9a2d0faedaa.tar.gz snac2-8535fc84c92e42ca379558b3c0a3a9a2d0faedaa.tar.xz snac2-8535fc84c92e42ca379558b3c0a3a9a2d0faedaa.zip | |
Backport from xs.
Diffstat (limited to '')
| -rw-r--r-- | xs_json.h | 179 |
1 files changed, 116 insertions, 63 deletions
| @@ -6,8 +6,13 @@ | |||
| 6 | 6 | ||
| 7 | int xs_json_dump(const xs_val *data, int indent, FILE *f); | 7 | int xs_json_dump(const xs_val *data, int indent, FILE *f); |
| 8 | xs_str *xs_json_dumps(const xs_val *data, int indent); | 8 | xs_str *xs_json_dumps(const xs_val *data, int indent); |
| 9 | xs_val *xs_json_loads(const xs_str *json); | 9 | |
| 10 | xs_val *xs_json_load(FILE *f); | 10 | xs_val *xs_json_load(FILE *f); |
| 11 | xs_val *xs_json_loads(const xs_str *json); | ||
| 12 | |||
| 13 | xstype xs_json_load_type(FILE *f); | ||
| 14 | int xs_json_load_array_iter(FILE *f, xs_val **value, int *c); | ||
| 15 | int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, int *c); | ||
| 11 | 16 | ||
| 12 | 17 | ||
| 13 | #ifdef XS_IMPLEMENTATION | 18 | #ifdef XS_IMPLEMENTATION |
| @@ -176,8 +181,6 @@ int xs_json_dump(const xs_val *data, int indent, FILE *f) | |||
| 176 | 181 | ||
| 177 | /** JSON loads **/ | 182 | /** JSON loads **/ |
| 178 | 183 | ||
| 179 | /* this code comes mostly from the Minimum Profit Text Editor (MPDM) */ | ||
| 180 | |||
| 181 | typedef enum { | 184 | typedef enum { |
| 182 | JS_ERROR = -1, | 185 | JS_ERROR = -1, |
| 183 | JS_INCOMPLETE, | 186 | JS_INCOMPLETE, |
| @@ -326,6 +329,40 @@ static xs_val *_xs_json_load_lexer(FILE *f, js_type *t) | |||
| 326 | static xs_list *_xs_json_load_array(FILE *f); | 329 | static xs_list *_xs_json_load_array(FILE *f); |
| 327 | static xs_dict *_xs_json_load_object(FILE *f); | 330 | static xs_dict *_xs_json_load_object(FILE *f); |
| 328 | 331 | ||
| 332 | int xs_json_load_array_iter(FILE *f, xs_val **value, int *c) | ||
| 333 | { | ||
| 334 | js_type t; | ||
| 335 | |||
| 336 | *value = _xs_json_load_lexer(f, &t); | ||
| 337 | |||
| 338 | if (t == JS_ERROR) | ||
| 339 | return -1; | ||
| 340 | |||
| 341 | if (t == JS_CBRACK) | ||
| 342 | return 0; | ||
| 343 | |||
| 344 | if (*c > 0) { | ||
| 345 | if (t == JS_COMMA) | ||
| 346 | *value = _xs_json_load_lexer(f, &t); | ||
| 347 | else | ||
| 348 | return -1; | ||
| 349 | } | ||
| 350 | |||
| 351 | if (t == JS_OBRACK) | ||
| 352 | *value = _xs_json_load_array(f); | ||
| 353 | else | ||
| 354 | if (t == JS_OCURLY) | ||
| 355 | *value = _xs_json_load_object(f); | ||
| 356 | |||
| 357 | if (*value == NULL) | ||
| 358 | return -1; | ||
| 359 | |||
| 360 | *c = *c + 1; | ||
| 361 | |||
| 362 | return 1; | ||
| 363 | } | ||
| 364 | |||
| 365 | |||
| 329 | static xs_list *_xs_json_load_array(FILE *f) | 366 | static xs_list *_xs_json_load_array(FILE *f) |
| 330 | /* parses a JSON array */ | 367 | /* parses a JSON array */ |
| 331 | { | 368 | { |
| @@ -333,36 +370,63 @@ static xs_list *_xs_json_load_array(FILE *f) | |||
| 333 | int c = 0; | 370 | int c = 0; |
| 334 | 371 | ||
| 335 | for (;;) { | 372 | for (;;) { |
| 336 | js_type tt; | 373 | xs *v = NULL; |
| 337 | xs *v = _xs_json_load_lexer(f, &tt); | 374 | int r = xs_json_load_array_iter(f, &v, &c); |
| 375 | |||
| 376 | if (r == -1) | ||
| 377 | l = xs_free(l); | ||
| 338 | 378 | ||
| 339 | if (tt == JS_ERROR) | 379 | if (r == 1) |
| 380 | l = xs_list_append(l, v); | ||
| 381 | else | ||
| 340 | break; | 382 | break; |
| 383 | } | ||
| 341 | 384 | ||
| 342 | if (tt == JS_CBRACK) | 385 | return l; |
| 343 | return l; | 386 | } |
| 344 | 387 | ||
| 345 | if (c > 0) { | ||
| 346 | if (tt == JS_COMMA) | ||
| 347 | v = _xs_json_load_lexer(f, &tt); | ||
| 348 | else | ||
| 349 | break; | ||
| 350 | } | ||
| 351 | 388 | ||
| 352 | if (tt == JS_OBRACK) | 389 | int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, int *c) |
| 353 | v = _xs_json_load_array(f); | 390 | { |
| 354 | else | 391 | js_type t; |
| 355 | if (tt == JS_OCURLY) | ||
| 356 | v = _xs_json_load_object(f); | ||
| 357 | 392 | ||
| 358 | if (v == NULL) | 393 | *key = _xs_json_load_lexer(f, &t); |
| 359 | break; | 394 | |
| 395 | if (t == JS_ERROR) | ||
| 396 | return -1; | ||
| 360 | 397 | ||
| 361 | l = xs_list_append(l, v); | 398 | if (t == JS_CCURLY) |
| 362 | c++; | 399 | return 0; |
| 400 | |||
| 401 | if (*c > 0) { | ||
| 402 | if (t == JS_COMMA) | ||
| 403 | *key = _xs_json_load_lexer(f, &t); | ||
| 404 | else | ||
| 405 | return -1; | ||
| 363 | } | 406 | } |
| 364 | 407 | ||
| 365 | return xs_free(l); | 408 | if (t != JS_STRING) |
| 409 | return -1; | ||
| 410 | |||
| 411 | xs_free(_xs_json_load_lexer(f, &t)); | ||
| 412 | |||
| 413 | if (t != JS_COLON) | ||
| 414 | return -1; | ||
| 415 | |||
| 416 | *value = _xs_json_load_lexer(f, &t); | ||
| 417 | |||
| 418 | if (t == JS_OBRACK) | ||
| 419 | *value = _xs_json_load_array(f); | ||
| 420 | else | ||
| 421 | if (t == JS_OCURLY) | ||
| 422 | *value = _xs_json_load_object(f); | ||
| 423 | |||
| 424 | if (*value == NULL) | ||
| 425 | return -1; | ||
| 426 | |||
| 427 | *c = *c + 1; | ||
| 428 | |||
| 429 | return 1; | ||
| 366 | } | 430 | } |
| 367 | 431 | ||
| 368 | 432 | ||
| @@ -375,47 +439,20 @@ static xs_dict *_xs_json_load_object(FILE *f) | |||
| 375 | d = xs_dict_new(); | 439 | d = xs_dict_new(); |
| 376 | 440 | ||
| 377 | for (;;) { | 441 | for (;;) { |
| 378 | js_type tt; | 442 | xs *k = NULL; |
| 379 | xs *k = _xs_json_load_lexer(f, &tt); | ||
| 380 | xs *v = NULL; | 443 | xs *v = NULL; |
| 444 | int r = xs_json_load_object_iter(f, &k, &v, &c); | ||
| 381 | 445 | ||
| 382 | if (tt == JS_ERROR) | 446 | if (r == -1) |
| 383 | break; | 447 | d = xs_free(d); |
| 384 | |||
| 385 | if (tt == JS_CCURLY) | ||
| 386 | return d; | ||
| 387 | |||
| 388 | if (c > 0) { | ||
| 389 | if (tt == JS_COMMA) | ||
| 390 | k = _xs_json_load_lexer(f, &tt); | ||
| 391 | else | ||
| 392 | break; | ||
| 393 | } | ||
| 394 | |||
| 395 | if (tt != JS_STRING) | ||
| 396 | break; | ||
| 397 | |||
| 398 | xs_free(_xs_json_load_lexer(f, &tt)); | ||
| 399 | 448 | ||
| 400 | if (tt != JS_COLON) | 449 | if (r == 1) |
| 401 | break; | 450 | d = xs_dict_append(d, k, v); |
| 402 | |||
| 403 | v = _xs_json_load_lexer(f, &tt); | ||
| 404 | |||
| 405 | if (tt == JS_OBRACK) | ||
| 406 | v = _xs_json_load_array(f); | ||
| 407 | else | 451 | else |
| 408 | if (tt == JS_OCURLY) | ||
| 409 | v = _xs_json_load_object(f); | ||
| 410 | |||
| 411 | if (v == NULL) | ||
| 412 | break; | 452 | break; |
| 413 | |||
| 414 | d = xs_dict_append(d, k, v); | ||
| 415 | c++; | ||
| 416 | } | 453 | } |
| 417 | 454 | ||
| 418 | return xs_free(d); | 455 | return d; |
| 419 | } | 456 | } |
| 420 | 457 | ||
| 421 | 458 | ||
| @@ -434,18 +471,34 @@ xs_val *xs_json_loads(const xs_str *json) | |||
| 434 | } | 471 | } |
| 435 | 472 | ||
| 436 | 473 | ||
| 474 | xstype xs_json_load_type(FILE *f) | ||
| 475 | /* identifies the type of a JSON stream */ | ||
| 476 | { | ||
| 477 | xstype t = XSTYPE_NULL; | ||
| 478 | js_type jt; | ||
| 479 | |||
| 480 | xs_free(_xs_json_load_lexer(f, &jt)); | ||
| 481 | |||
| 482 | if (jt == JS_OBRACK) | ||
| 483 | t = XSTYPE_LIST; | ||
| 484 | else | ||
| 485 | if (jt == JS_OCURLY) | ||
| 486 | t = XSTYPE_DICT; | ||
| 487 | |||
| 488 | return t; | ||
| 489 | } | ||
| 490 | |||
| 491 | |||
| 437 | xs_val *xs_json_load(FILE *f) | 492 | xs_val *xs_json_load(FILE *f) |
| 438 | /* loads a JSON file */ | 493 | /* loads a JSON file */ |
| 439 | { | 494 | { |
| 440 | xs_val *v = NULL; | 495 | xs_val *v = NULL; |
| 441 | js_type t; | 496 | xstype t = xs_json_load_type(f); |
| 442 | 497 | ||
| 443 | xs_free(_xs_json_load_lexer(f, &t)); | 498 | if (t == XSTYPE_LIST) |
| 444 | |||
| 445 | if (t == JS_OBRACK) | ||
| 446 | v = _xs_json_load_array(f); | 499 | v = _xs_json_load_array(f); |
| 447 | else | 500 | else |
| 448 | if (t == JS_OCURLY) | 501 | if (t == XSTYPE_DICT) |
| 449 | v = _xs_json_load_object(f); | 502 | v = _xs_json_load_object(f); |
| 450 | 503 | ||
| 451 | return v; | 504 | return v; |