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