1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * json.c: Encoding and decoding JSON. 12 * 13 * Follows this standard: https://tools.ietf.org/html/rfc7159.html 14 */ 15 #define USING_FLOAT_STUFF 16 17 #include "vim.h" 18 19 #if defined(FEAT_EVAL) || defined(PROTO) 20 21 static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int options); 22 static int json_decode_item(js_read_T *reader, typval_T *res, int options); 23 24 /* 25 * Encode "val" into a JSON format string. 26 * The result is added to "gap" 27 * Returns FAIL on failure and makes gap->ga_data empty. 28 */ 29 static int 30 json_encode_gap(garray_T *gap, typval_T *val, int options) 31 { 32 if (json_encode_item(gap, val, get_copyID(), options) == FAIL) 33 { 34 ga_clear(gap); 35 gap->ga_data = vim_strsave((char_u *)""); 36 return FAIL; 37 } 38 return OK; 39 } 40 41 /* 42 * Encode "val" into a JSON format string. 43 * The result is in allocated memory. 44 * The result is empty when encoding fails. 45 * "options" can contain JSON_JS, JSON_NO_NONE and JSON_NL. 46 */ 47 char_u * 48 json_encode(typval_T *val, int options) 49 { 50 garray_T ga; 51 52 /* Store bytes in the growarray. */ 53 ga_init2(&ga, 1, 4000); 54 json_encode_gap(&ga, val, options); 55 return ga.ga_data; 56 } 57 58 /* 59 * Encode ["nr", "val"] into a JSON format string in allocated memory. 60 * "options" can contain JSON_JS, JSON_NO_NONE and JSON_NL. 61 * Returns NULL when out of memory. 62 */ 63 char_u * 64 json_encode_nr_expr(int nr, typval_T *val, int options) 65 { 66 typval_T listtv; 67 typval_T nrtv; 68 garray_T ga; 69 70 nrtv.v_type = VAR_NUMBER; 71 nrtv.vval.v_number = nr; 72 if (rettv_list_alloc(&listtv) == FAIL) 73 return NULL; 74 if (list_append_tv(listtv.vval.v_list, &nrtv) == FAIL 75 || list_append_tv(listtv.vval.v_list, val) == FAIL) 76 { 77 list_unref(listtv.vval.v_list); 78 return NULL; 79 } 80 81 ga_init2(&ga, 1, 4000); 82 if (json_encode_gap(&ga, &listtv, options) == OK && (options & JSON_NL)) 83 ga_append(&ga, '\n'); 84 list_unref(listtv.vval.v_list); 85 return ga.ga_data; 86 } 87 88 static void 89 write_string(garray_T *gap, char_u *str) 90 { 91 char_u *res = str; 92 char_u numbuf[NUMBUFLEN]; 93 94 if (res == NULL) 95 ga_concat(gap, (char_u *)"\"\""); 96 else 97 { 98 #if defined(FEAT_MBYTE) && defined(USE_ICONV) 99 vimconv_T conv; 100 char_u *converted = NULL; 101 102 if (!enc_utf8) 103 { 104 /* Convert the text from 'encoding' to utf-8, the JSON string is 105 * always utf-8. */ 106 conv.vc_type = CONV_NONE; 107 convert_setup(&conv, p_enc, (char_u*)"utf-8"); 108 if (conv.vc_type != CONV_NONE) 109 converted = res = string_convert(&conv, res, NULL); 110 convert_setup(&conv, NULL, NULL); 111 } 112 #endif 113 ga_append(gap, '"'); 114 while (*res != NUL) 115 { 116 int c; 117 #ifdef FEAT_MBYTE 118 /* always use utf-8 encoding, ignore 'encoding' */ 119 c = utf_ptr2char(res); 120 #else 121 c = *res; 122 #endif 123 124 switch (c) 125 { 126 case 0x08: 127 ga_append(gap, '\\'); ga_append(gap, 'b'); break; 128 case 0x09: 129 ga_append(gap, '\\'); ga_append(gap, 't'); break; 130 case 0x0a: 131 ga_append(gap, '\\'); ga_append(gap, 'n'); break; 132 case 0x0c: 133 ga_append(gap, '\\'); ga_append(gap, 'f'); break; 134 case 0x0d: 135 ga_append(gap, '\\'); ga_append(gap, 'r'); break; 136 case 0x22: /* " */ 137 case 0x5c: /* \ */ 138 ga_append(gap, '\\'); 139 ga_append(gap, c); 140 break; 141 default: 142 if (c >= 0x20) 143 { 144 #ifdef FEAT_MBYTE 145 numbuf[utf_char2bytes(c, numbuf)] = NUL; 146 #else 147 numbuf[0] = c; 148 numbuf[1] = NUL; 149 #endif 150 ga_concat(gap, numbuf); 151 } 152 else 153 { 154 vim_snprintf((char *)numbuf, NUMBUFLEN, 155 "\\u%04lx", (long)c); 156 ga_concat(gap, numbuf); 157 } 158 } 159 #ifdef FEAT_MBYTE 160 res += utf_ptr2len(res); 161 #else 162 ++res; 163 #endif 164 } 165 ga_append(gap, '"'); 166 #if defined(FEAT_MBYTE) && defined(USE_ICONV) 167 vim_free(converted); 168 #endif 169 } 170 } 171 172 /* 173 * Return TRUE if "key" can be used without quotes. 174 * That is when it starts with a letter and only contains letters, digits and 175 * underscore. 176 */ 177 static int 178 is_simple_key(char_u *key) 179 { 180 char_u *p; 181 182 if (!ASCII_ISALPHA(*key)) 183 return FALSE; 184 for (p = key + 1; *p != NUL; ++p) 185 if (!ASCII_ISALPHA(*p) && *p != '_' && !vim_isdigit(*p)) 186 return FALSE; 187 return TRUE; 188 } 189 190 /* 191 * Encode "val" into "gap". 192 * Return FAIL or OK. 193 */ 194 static int 195 json_encode_item(garray_T *gap, typval_T *val, int copyID, int options) 196 { 197 char_u numbuf[NUMBUFLEN]; 198 char_u *res; 199 list_T *l; 200 dict_T *d; 201 202 switch (val->v_type) 203 { 204 case VAR_SPECIAL: 205 switch (val->vval.v_number) 206 { 207 case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break; 208 case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break; 209 case VVAL_NONE: if ((options & JSON_JS) != 0 210 && (options & JSON_NO_NONE) == 0) 211 /* empty item */ 212 break; 213 /* FALLTHROUGH */ 214 case VVAL_NULL: ga_concat(gap, (char_u *)"null"); break; 215 } 216 break; 217 218 case VAR_NUMBER: 219 vim_snprintf((char *)numbuf, NUMBUFLEN, "%lld", 220 val->vval.v_number); 221 ga_concat(gap, numbuf); 222 break; 223 224 case VAR_STRING: 225 res = val->vval.v_string; 226 write_string(gap, res); 227 break; 228 229 case VAR_FUNC: 230 case VAR_PARTIAL: 231 case VAR_JOB: 232 case VAR_CHANNEL: 233 /* no JSON equivalent TODO: better error */ 234 EMSG(_(e_invarg)); 235 return FAIL; 236 237 case VAR_LIST: 238 l = val->vval.v_list; 239 if (l == NULL) 240 ga_concat(gap, (char_u *)"[]"); 241 else 242 { 243 if (l->lv_copyID == copyID) 244 ga_concat(gap, (char_u *)"[]"); 245 else 246 { 247 listitem_T *li; 248 249 l->lv_copyID = copyID; 250 ga_append(gap, '['); 251 for (li = l->lv_first; li != NULL && !got_int; ) 252 { 253 if (json_encode_item(gap, &li->li_tv, copyID, 254 options & JSON_JS) == FAIL) 255 return FAIL; 256 if ((options & JSON_JS) 257 && li->li_next == NULL 258 && li->li_tv.v_type == VAR_SPECIAL 259 && li->li_tv.vval.v_number == VVAL_NONE) 260 /* add an extra comma if the last item is v:none */ 261 ga_append(gap, ','); 262 li = li->li_next; 263 if (li != NULL) 264 ga_append(gap, ','); 265 } 266 ga_append(gap, ']'); 267 l->lv_copyID = 0; 268 } 269 } 270 break; 271 272 case VAR_DICT: 273 d = val->vval.v_dict; 274 if (d == NULL) 275 ga_concat(gap, (char_u *)"{}"); 276 else 277 { 278 if (d->dv_copyID == copyID) 279 ga_concat(gap, (char_u *)"{}"); 280 else 281 { 282 int first = TRUE; 283 int todo = (int)d->dv_hashtab.ht_used; 284 hashitem_T *hi; 285 286 d->dv_copyID = copyID; 287 ga_append(gap, '{'); 288 289 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; 290 ++hi) 291 if (!HASHITEM_EMPTY(hi)) 292 { 293 --todo; 294 if (first) 295 first = FALSE; 296 else 297 ga_append(gap, ','); 298 if ((options & JSON_JS) 299 && is_simple_key(hi->hi_key)) 300 ga_concat(gap, hi->hi_key); 301 else 302 write_string(gap, hi->hi_key); 303 ga_append(gap, ':'); 304 if (json_encode_item(gap, &dict_lookup(hi)->di_tv, 305 copyID, options | JSON_NO_NONE) == FAIL) 306 return FAIL; 307 } 308 ga_append(gap, '}'); 309 d->dv_copyID = 0; 310 } 311 } 312 break; 313 314 case VAR_FLOAT: 315 #ifdef FEAT_FLOAT 316 # if defined(HAVE_MATH_H) 317 if (isnan(val->vval.v_float)) 318 ga_concat(gap, (char_u *)"NaN"); 319 else if (isinf(val->vval.v_float)) 320 ga_concat(gap, (char_u *)"Infinity"); 321 else 322 # endif 323 { 324 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", 325 val->vval.v_float); 326 ga_concat(gap, numbuf); 327 } 328 break; 329 #endif 330 case VAR_UNKNOWN: 331 internal_error("json_encode_item()"); 332 return FAIL; 333 } 334 return OK; 335 } 336 337 /* 338 * When "reader" has less than NUMBUFLEN bytes available, call the fill 339 * callback to get more. 340 */ 341 static void 342 fill_numbuflen(js_read_T *reader) 343 { 344 if (reader->js_fill != NULL && (int)(reader->js_end - reader->js_buf) 345 - reader->js_used < NUMBUFLEN) 346 { 347 if (reader->js_fill(reader)) 348 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 349 } 350 } 351 352 /* 353 * Skip white space in "reader". All characters <= space are considered white 354 * space. 355 * Also tops up readahead when needed. 356 */ 357 static void 358 json_skip_white(js_read_T *reader) 359 { 360 int c; 361 362 for (;;) 363 { 364 c = reader->js_buf[reader->js_used]; 365 if (reader->js_fill != NULL && c == NUL) 366 { 367 if (reader->js_fill(reader)) 368 { 369 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 370 continue; 371 } 372 } 373 if (c == NUL || c > ' ') 374 break; 375 ++reader->js_used; 376 } 377 fill_numbuflen(reader); 378 } 379 380 static int 381 json_decode_string(js_read_T *reader, typval_T *res, int quote) 382 { 383 garray_T ga; 384 int len; 385 char_u *p; 386 int c; 387 varnumber_T nr; 388 389 if (res != NULL) 390 ga_init2(&ga, 1, 200); 391 392 p = reader->js_buf + reader->js_used + 1; /* skip over " or ' */ 393 while (*p != quote) 394 { 395 /* The JSON is always expected to be utf-8, thus use utf functions 396 * here. The string is converted below if needed. */ 397 if (*p == NUL || p[1] == NUL 398 #ifdef FEAT_MBYTE 399 || utf_ptr2len(p) < utf_byte2len(*p) 400 #endif 401 ) 402 { 403 /* Not enough bytes to make a character or end of the string. Get 404 * more if possible. */ 405 if (reader->js_fill == NULL) 406 break; 407 len = (int)(reader->js_end - p); 408 reader->js_used = (int)(p - reader->js_buf); 409 if (!reader->js_fill(reader)) 410 break; /* didn't get more */ 411 p = reader->js_buf + reader->js_used; 412 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 413 continue; 414 } 415 416 if (*p == '\\') 417 { 418 c = -1; 419 switch (p[1]) 420 { 421 case '\\': c = '\\'; break; 422 case '"': c = '"'; break; 423 case 'b': c = BS; break; 424 case 't': c = TAB; break; 425 case 'n': c = NL; break; 426 case 'f': c = FF; break; 427 case 'r': c = CAR; break; 428 case 'u': 429 if (reader->js_fill != NULL 430 && (int)(reader->js_end - p) < NUMBUFLEN) 431 { 432 reader->js_used = (int)(p - reader->js_buf); 433 if (reader->js_fill(reader)) 434 { 435 p = reader->js_buf + reader->js_used; 436 reader->js_end = reader->js_buf 437 + STRLEN(reader->js_buf); 438 } 439 } 440 nr = 0; 441 len = 0; 442 vim_str2nr(p + 2, NULL, &len, 443 STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4); 444 p += len + 2; 445 if (0xd800 <= nr && nr <= 0xdfff 446 && (int)(reader->js_end - p) >= 6 447 && *p == '\\' && *(p+1) == 'u') 448 { 449 varnumber_T nr2 = 0; 450 451 /* decode surrogate pair: \ud812\u3456 */ 452 len = 0; 453 vim_str2nr(p + 2, NULL, &len, 454 STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4); 455 if (0xdc00 <= nr2 && nr2 <= 0xdfff) 456 { 457 p += len + 2; 458 nr = (((nr - 0xd800) << 10) | 459 ((nr2 - 0xdc00) & 0x3ff)) + 0x10000; 460 } 461 } 462 if (res != NULL) 463 { 464 #ifdef FEAT_MBYTE 465 char_u buf[NUMBUFLEN]; 466 buf[utf_char2bytes((int)nr, buf)] = NUL; 467 ga_concat(&ga, buf); 468 #else 469 ga_append(&ga, (int)nr); 470 #endif 471 } 472 break; 473 default: 474 /* not a special char, skip over \ */ 475 ++p; 476 continue; 477 } 478 if (c > 0) 479 { 480 p += 2; 481 if (res != NULL) 482 ga_append(&ga, c); 483 } 484 } 485 else 486 { 487 #ifdef FEAT_MBYTE 488 len = utf_ptr2len(p); 489 #else 490 len = 1; 491 #endif 492 if (res != NULL) 493 { 494 if (ga_grow(&ga, len) == FAIL) 495 { 496 ga_clear(&ga); 497 return FAIL; 498 } 499 mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len); 500 ga.ga_len += len; 501 } 502 p += len; 503 } 504 } 505 506 reader->js_used = (int)(p - reader->js_buf); 507 if (*p == quote) 508 { 509 ++reader->js_used; 510 if (res != NULL) 511 { 512 ga_append(&ga, NUL); 513 res->v_type = VAR_STRING; 514 #if defined(FEAT_MBYTE) && defined(USE_ICONV) 515 if (!enc_utf8) 516 { 517 vimconv_T conv; 518 519 /* Convert the utf-8 string to 'encoding'. */ 520 conv.vc_type = CONV_NONE; 521 convert_setup(&conv, (char_u*)"utf-8", p_enc); 522 if (conv.vc_type != CONV_NONE) 523 { 524 res->vval.v_string = 525 string_convert(&conv, ga.ga_data, NULL); 526 vim_free(ga.ga_data); 527 } 528 convert_setup(&conv, NULL, NULL); 529 } 530 else 531 #endif 532 res->vval.v_string = ga.ga_data; 533 } 534 return OK; 535 } 536 if (res != NULL) 537 { 538 res->v_type = VAR_SPECIAL; 539 res->vval.v_number = VVAL_NONE; 540 ga_clear(&ga); 541 } 542 return MAYBE; 543 } 544 545 typedef enum { 546 JSON_ARRAY, /* parsing items in an array */ 547 JSON_OBJECT_KEY, /* parsing key of an object */ 548 JSON_OBJECT /* parsing item in an object, after the key */ 549 } json_decode_T; 550 551 typedef struct { 552 json_decode_T jd_type; 553 typval_T jd_tv; /* the list or dict */ 554 typval_T jd_key_tv; 555 char_u *jd_key; 556 } json_dec_item_T; 557 558 /* 559 * Decode one item and put it in "res". If "res" is NULL only advance. 560 * Must already have skipped white space. 561 * 562 * Return FAIL for a decoding error (and give an error). 563 * Return MAYBE for an incomplete message. 564 */ 565 static int 566 json_decode_item(js_read_T *reader, typval_T *res, int options) 567 { 568 char_u *p; 569 int len; 570 int retval; 571 garray_T stack; 572 typval_T item; 573 typval_T *cur_item; 574 json_dec_item_T *top_item; 575 char_u key_buf[NUMBUFLEN]; 576 577 ga_init2(&stack, sizeof(json_dec_item_T), 100); 578 cur_item = res; 579 init_tv(&item); 580 if (res != NULL) 581 init_tv(res); 582 583 fill_numbuflen(reader); 584 p = reader->js_buf + reader->js_used; 585 for (;;) 586 { 587 top_item = NULL; 588 if (stack.ga_len > 0) 589 { 590 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; 591 json_skip_white(reader); 592 p = reader->js_buf + reader->js_used; 593 if (*p == NUL) 594 { 595 retval = MAYBE; 596 if (top_item->jd_type == JSON_OBJECT) 597 /* did get the key, clear it */ 598 clear_tv(&top_item->jd_key_tv); 599 goto theend; 600 } 601 if (top_item->jd_type == JSON_OBJECT_KEY 602 || top_item->jd_type == JSON_ARRAY) 603 { 604 /* Check for end of object or array. */ 605 if (*p == (top_item->jd_type == JSON_ARRAY ? ']' : '}')) 606 { 607 ++reader->js_used; /* consume the ']' or '}' */ 608 --stack.ga_len; 609 if (stack.ga_len == 0) 610 { 611 retval = OK; 612 goto theend; 613 } 614 if (cur_item != NULL) 615 cur_item = &top_item->jd_tv; 616 goto item_end; 617 } 618 } 619 } 620 621 if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY 622 && (options & JSON_JS) 623 && reader->js_buf[reader->js_used] != '"' 624 && reader->js_buf[reader->js_used] != '\'' 625 && reader->js_buf[reader->js_used] != '[' 626 && reader->js_buf[reader->js_used] != '{') 627 { 628 char_u *key; 629 630 /* accept an object key that is not in quotes */ 631 key = p = reader->js_buf + reader->js_used; 632 while (*p != NUL && *p != ':' && *p > ' ') 633 ++p; 634 if (cur_item != NULL) 635 { 636 cur_item->v_type = VAR_STRING; 637 cur_item->vval.v_string = vim_strnsave(key, (int)(p - key)); 638 top_item->jd_key = cur_item->vval.v_string; 639 } 640 reader->js_used += (int)(p - key); 641 } 642 else 643 { 644 switch (*p) 645 { 646 case '[': /* start of array */ 647 if (top_item && top_item->jd_type == JSON_OBJECT_KEY) 648 { 649 retval = FAIL; 650 break; 651 } 652 if (ga_grow(&stack, 1) == FAIL) 653 { 654 retval = FAIL; 655 break; 656 } 657 if (cur_item != NULL && rettv_list_alloc(cur_item) == FAIL) 658 { 659 cur_item->v_type = VAR_SPECIAL; 660 cur_item->vval.v_number = VVAL_NONE; 661 retval = FAIL; 662 break; 663 } 664 665 ++reader->js_used; /* consume the '[' */ 666 top_item = ((json_dec_item_T *)stack.ga_data) 667 + stack.ga_len; 668 top_item->jd_type = JSON_ARRAY; 669 ++stack.ga_len; 670 if (cur_item != NULL) 671 { 672 top_item->jd_tv = *cur_item; 673 cur_item = &item; 674 } 675 continue; 676 677 case '{': /* start of object */ 678 if (top_item && top_item->jd_type == JSON_OBJECT_KEY) 679 { 680 retval = FAIL; 681 break; 682 } 683 if (ga_grow(&stack, 1) == FAIL) 684 { 685 retval = FAIL; 686 break; 687 } 688 if (cur_item != NULL && rettv_dict_alloc(cur_item) == FAIL) 689 { 690 cur_item->v_type = VAR_SPECIAL; 691 cur_item->vval.v_number = VVAL_NONE; 692 retval = FAIL; 693 break; 694 } 695 696 ++reader->js_used; /* consume the '{' */ 697 top_item = ((json_dec_item_T *)stack.ga_data) 698 + stack.ga_len; 699 top_item->jd_type = JSON_OBJECT_KEY; 700 ++stack.ga_len; 701 if (cur_item != NULL) 702 { 703 top_item->jd_tv = *cur_item; 704 cur_item = &top_item->jd_key_tv; 705 } 706 continue; 707 708 case '"': /* string */ 709 retval = json_decode_string(reader, cur_item, *p); 710 break; 711 712 case '\'': 713 if (options & JSON_JS) 714 retval = json_decode_string(reader, cur_item, *p); 715 else 716 { 717 EMSG(_(e_invarg)); 718 retval = FAIL; 719 } 720 break; 721 722 case ',': /* comma: empty item */ 723 if ((options & JSON_JS) == 0) 724 { 725 EMSG(_(e_invarg)); 726 retval = FAIL; 727 break; 728 } 729 /* FALLTHROUGH */ 730 case NUL: /* empty */ 731 if (cur_item != NULL) 732 { 733 cur_item->v_type = VAR_SPECIAL; 734 cur_item->vval.v_number = VVAL_NONE; 735 } 736 retval = OK; 737 break; 738 739 default: 740 if (VIM_ISDIGIT(*p) || *p == '-') 741 { 742 #ifdef FEAT_FLOAT 743 char_u *sp = p; 744 745 if (*sp == '-') 746 { 747 ++sp; 748 if (*sp == NUL) 749 { 750 retval = MAYBE; 751 break; 752 } 753 if (!VIM_ISDIGIT(*sp)) 754 { 755 EMSG(_(e_invarg)); 756 retval = FAIL; 757 break; 758 } 759 } 760 sp = skipdigits(sp); 761 if (*sp == '.' || *sp == 'e' || *sp == 'E') 762 { 763 if (cur_item == NULL) 764 { 765 float_T f; 766 767 len = string2float(p, &f); 768 } 769 else 770 { 771 cur_item->v_type = VAR_FLOAT; 772 len = string2float(p, &cur_item->vval.v_float); 773 } 774 } 775 else 776 #endif 777 { 778 varnumber_T nr; 779 780 vim_str2nr(reader->js_buf + reader->js_used, 781 NULL, &len, 0, /* what */ 782 &nr, NULL, 0); 783 if (cur_item != NULL) 784 { 785 cur_item->v_type = VAR_NUMBER; 786 cur_item->vval.v_number = nr; 787 } 788 } 789 reader->js_used += len; 790 retval = OK; 791 break; 792 } 793 if (STRNICMP((char *)p, "false", 5) == 0) 794 { 795 reader->js_used += 5; 796 if (cur_item != NULL) 797 { 798 cur_item->v_type = VAR_SPECIAL; 799 cur_item->vval.v_number = VVAL_FALSE; 800 } 801 retval = OK; 802 break; 803 } 804 if (STRNICMP((char *)p, "true", 4) == 0) 805 { 806 reader->js_used += 4; 807 if (cur_item != NULL) 808 { 809 cur_item->v_type = VAR_SPECIAL; 810 cur_item->vval.v_number = VVAL_TRUE; 811 } 812 retval = OK; 813 break; 814 } 815 if (STRNICMP((char *)p, "null", 4) == 0) 816 { 817 reader->js_used += 4; 818 if (cur_item != NULL) 819 { 820 cur_item->v_type = VAR_SPECIAL; 821 cur_item->vval.v_number = VVAL_NULL; 822 } 823 retval = OK; 824 break; 825 } 826 #ifdef FEAT_FLOAT 827 if (STRNICMP((char *)p, "NaN", 3) == 0) 828 { 829 reader->js_used += 3; 830 if (cur_item != NULL) 831 { 832 cur_item->v_type = VAR_FLOAT; 833 cur_item->vval.v_float = NAN; 834 } 835 retval = OK; 836 break; 837 } 838 if (STRNICMP((char *)p, "Infinity", 8) == 0) 839 { 840 reader->js_used += 8; 841 if (cur_item != NULL) 842 { 843 cur_item->v_type = VAR_FLOAT; 844 cur_item->vval.v_float = INFINITY; 845 } 846 retval = OK; 847 break; 848 } 849 #endif 850 /* check for truncated name */ 851 len = (int)(reader->js_end - (reader->js_buf + reader->js_used)); 852 if ( 853 (len < 5 && STRNICMP((char *)p, "false", len) == 0) 854 #ifdef FEAT_FLOAT 855 || (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0) 856 || (len < 3 && STRNICMP((char *)p, "NaN", len) == 0) 857 #endif 858 || (len < 4 && (STRNICMP((char *)p, "true", len) == 0 859 || STRNICMP((char *)p, "null", len) == 0))) 860 861 retval = MAYBE; 862 else 863 retval = FAIL; 864 break; 865 } 866 867 /* We are finished when retval is FAIL or MAYBE and when at the 868 * toplevel. */ 869 if (retval == FAIL) 870 break; 871 if (retval == MAYBE || stack.ga_len == 0) 872 goto theend; 873 874 if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY 875 && cur_item != NULL) 876 { 877 top_item->jd_key = get_tv_string_buf_chk(cur_item, key_buf); 878 if (top_item->jd_key == NULL) 879 { 880 clear_tv(cur_item); 881 EMSG(_(e_invarg)); 882 retval = FAIL; 883 goto theend; 884 } 885 } 886 } 887 888 item_end: 889 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; 890 switch (top_item->jd_type) 891 { 892 case JSON_ARRAY: 893 if (res != NULL) 894 { 895 listitem_T *li = listitem_alloc(); 896 897 if (li == NULL) 898 { 899 clear_tv(cur_item); 900 retval = FAIL; 901 goto theend; 902 } 903 li->li_tv = *cur_item; 904 list_append(top_item->jd_tv.vval.v_list, li); 905 } 906 if (cur_item != NULL) 907 cur_item = &item; 908 909 json_skip_white(reader); 910 p = reader->js_buf + reader->js_used; 911 if (*p == ',') 912 ++reader->js_used; 913 else if (*p != ']') 914 { 915 if (*p == NUL) 916 retval = MAYBE; 917 else 918 { 919 EMSG(_(e_invarg)); 920 retval = FAIL; 921 } 922 goto theend; 923 } 924 break; 925 926 case JSON_OBJECT_KEY: 927 json_skip_white(reader); 928 p = reader->js_buf + reader->js_used; 929 if (*p != ':') 930 { 931 if (cur_item != NULL) 932 clear_tv(cur_item); 933 if (*p == NUL) 934 retval = MAYBE; 935 else 936 { 937 EMSG(_(e_invarg)); 938 retval = FAIL; 939 } 940 goto theend; 941 } 942 ++reader->js_used; 943 json_skip_white(reader); 944 top_item->jd_type = JSON_OBJECT; 945 if (cur_item != NULL) 946 cur_item = &item; 947 break; 948 949 case JSON_OBJECT: 950 if (cur_item != NULL 951 && dict_find(top_item->jd_tv.vval.v_dict, 952 top_item->jd_key, -1) != NULL) 953 { 954 EMSG2(_("E938: Duplicate key in JSON: \"%s\""), 955 top_item->jd_key); 956 clear_tv(&top_item->jd_key_tv); 957 clear_tv(cur_item); 958 retval = FAIL; 959 goto theend; 960 } 961 962 if (cur_item != NULL) 963 { 964 dictitem_T *di = dictitem_alloc(top_item->jd_key); 965 966 clear_tv(&top_item->jd_key_tv); 967 if (di == NULL) 968 { 969 clear_tv(cur_item); 970 retval = FAIL; 971 goto theend; 972 } 973 di->di_tv = *cur_item; 974 di->di_tv.v_lock = 0; 975 if (dict_add(top_item->jd_tv.vval.v_dict, di) == FAIL) 976 { 977 dictitem_free(di); 978 retval = FAIL; 979 goto theend; 980 } 981 } 982 983 json_skip_white(reader); 984 p = reader->js_buf + reader->js_used; 985 if (*p == ',') 986 ++reader->js_used; 987 else if (*p != '}') 988 { 989 if (*p == NUL) 990 retval = MAYBE; 991 else 992 { 993 EMSG(_(e_invarg)); 994 retval = FAIL; 995 } 996 goto theend; 997 } 998 top_item->jd_type = JSON_OBJECT_KEY; 999 if (cur_item != NULL) 1000 cur_item = &top_item->jd_key_tv; 1001 break; 1002 } 1003 } 1004 1005 /* Get here when parsing failed. */ 1006 if (res != NULL) 1007 { 1008 clear_tv(res); 1009 res->v_type = VAR_SPECIAL; 1010 res->vval.v_number = VVAL_NONE; 1011 } 1012 EMSG(_(e_invarg)); 1013 1014 theend: 1015 ga_clear(&stack); 1016 return retval; 1017 } 1018 1019 /* 1020 * Decode the JSON from "reader" and store the result in "res". 1021 * "options" can be JSON_JS or zero; 1022 * Return FAIL if not the whole message was consumed. 1023 */ 1024 int 1025 json_decode_all(js_read_T *reader, typval_T *res, int options) 1026 { 1027 int ret; 1028 1029 /* We find the end once, to avoid calling strlen() many times. */ 1030 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 1031 json_skip_white(reader); 1032 ret = json_decode_item(reader, res, options); 1033 if (ret != OK) 1034 { 1035 if (ret == MAYBE) 1036 EMSG(_(e_invarg)); 1037 return FAIL; 1038 } 1039 json_skip_white(reader); 1040 if (reader->js_buf[reader->js_used] != NUL) 1041 { 1042 EMSG(_(e_trailing)); 1043 return FAIL; 1044 } 1045 return OK; 1046 } 1047 1048 /* 1049 * Decode the JSON from "reader" and store the result in "res". 1050 * "options" can be JSON_JS or zero; 1051 * Return FAIL for a decoding error. 1052 * Return MAYBE for an incomplete message. 1053 * Consumes the message anyway. 1054 */ 1055 int 1056 json_decode(js_read_T *reader, typval_T *res, int options) 1057 { 1058 int ret; 1059 1060 /* We find the end once, to avoid calling strlen() many times. */ 1061 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 1062 json_skip_white(reader); 1063 ret = json_decode_item(reader, res, options); 1064 json_skip_white(reader); 1065 1066 return ret; 1067 } 1068 1069 /* 1070 * Decode the JSON from "reader" to find the end of the message. 1071 * "options" can be JSON_JS or zero. 1072 * This is only used for testing. 1073 * Return FAIL if the message has a decoding error. 1074 * Return MAYBE if the message is truncated, need to read more. 1075 * This only works reliable if the message contains an object, array or 1076 * string. A number might be trucated without knowing. 1077 * Does not advance the reader. 1078 */ 1079 int 1080 json_find_end(js_read_T *reader, int options) 1081 { 1082 int used_save = reader->js_used; 1083 int ret; 1084 1085 /* We find the end once, to avoid calling strlen() many times. */ 1086 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 1087 json_skip_white(reader); 1088 ret = json_decode_item(reader, NULL, options); 1089 reader->js_used = used_save; 1090 return ret; 1091 } 1092 #endif 1093