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