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