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 ((long)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 ((long)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 (varnumber_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 range_list_materialize(l); 269 for (li = l->lv_first; li != NULL && !got_int; ) 270 { 271 if (json_encode_item(gap, &li->li_tv, copyID, 272 options & JSON_JS) == FAIL) 273 return FAIL; 274 if ((options & JSON_JS) 275 && li->li_next == NULL 276 && li->li_tv.v_type == VAR_SPECIAL 277 && li->li_tv.vval.v_number == VVAL_NONE) 278 // add an extra comma if the last item is v:none 279 ga_append(gap, ','); 280 li = li->li_next; 281 if (li != NULL) 282 ga_append(gap, ','); 283 } 284 ga_append(gap, ']'); 285 l->lv_copyID = 0; 286 } 287 } 288 break; 289 290 case VAR_DICT: 291 d = val->vval.v_dict; 292 if (d == NULL) 293 ga_concat(gap, (char_u *)"{}"); 294 else 295 { 296 if (d->dv_copyID == copyID) 297 ga_concat(gap, (char_u *)"{}"); 298 else 299 { 300 int first = TRUE; 301 int todo = (int)d->dv_hashtab.ht_used; 302 hashitem_T *hi; 303 304 d->dv_copyID = copyID; 305 ga_append(gap, '{'); 306 307 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; 308 ++hi) 309 if (!HASHITEM_EMPTY(hi)) 310 { 311 --todo; 312 if (first) 313 first = FALSE; 314 else 315 ga_append(gap, ','); 316 if ((options & JSON_JS) 317 && is_simple_key(hi->hi_key)) 318 ga_concat(gap, hi->hi_key); 319 else 320 write_string(gap, hi->hi_key); 321 ga_append(gap, ':'); 322 if (json_encode_item(gap, &dict_lookup(hi)->di_tv, 323 copyID, options | JSON_NO_NONE) == FAIL) 324 return FAIL; 325 } 326 ga_append(gap, '}'); 327 d->dv_copyID = 0; 328 } 329 } 330 break; 331 332 case VAR_FLOAT: 333 #ifdef FEAT_FLOAT 334 # if defined(HAVE_MATH_H) 335 if (isnan(val->vval.v_float)) 336 ga_concat(gap, (char_u *)"NaN"); 337 else if (isinf(val->vval.v_float)) 338 { 339 if (val->vval.v_float < 0.0) 340 ga_concat(gap, (char_u *)"-Infinity"); 341 else 342 ga_concat(gap, (char_u *)"Infinity"); 343 } 344 else 345 # endif 346 { 347 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", 348 val->vval.v_float); 349 ga_concat(gap, numbuf); 350 } 351 break; 352 #endif 353 case VAR_UNKNOWN: 354 case VAR_VOID: 355 internal_error("json_encode_item()"); 356 return FAIL; 357 } 358 return OK; 359 } 360 361 /* 362 * When "reader" has less than NUMBUFLEN bytes available, call the fill 363 * callback to get more. 364 */ 365 static void 366 fill_numbuflen(js_read_T *reader) 367 { 368 if (reader->js_fill != NULL && (int)(reader->js_end - reader->js_buf) 369 - reader->js_used < NUMBUFLEN) 370 { 371 if (reader->js_fill(reader)) 372 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 373 } 374 } 375 376 /* 377 * Skip white space in "reader". All characters <= space are considered white 378 * space. 379 * Also tops up readahead when needed. 380 */ 381 static void 382 json_skip_white(js_read_T *reader) 383 { 384 int c; 385 386 for (;;) 387 { 388 c = reader->js_buf[reader->js_used]; 389 if (reader->js_fill != NULL && c == NUL) 390 { 391 if (reader->js_fill(reader)) 392 { 393 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 394 continue; 395 } 396 } 397 if (c == NUL || c > ' ') 398 break; 399 ++reader->js_used; 400 } 401 fill_numbuflen(reader); 402 } 403 404 static int 405 json_decode_string(js_read_T *reader, typval_T *res, int quote) 406 { 407 garray_T ga; 408 int len; 409 char_u *p; 410 int c; 411 varnumber_T nr; 412 413 if (res != NULL) 414 ga_init2(&ga, 1, 200); 415 416 p = reader->js_buf + reader->js_used + 1; // skip over " or ' 417 while (*p != quote) 418 { 419 // The JSON is always expected to be utf-8, thus use utf functions 420 // here. The string is converted below if needed. 421 if (*p == NUL || p[1] == NUL || utf_ptr2len(p) < utf_byte2len(*p)) 422 { 423 // Not enough bytes to make a character or end of the string. Get 424 // more if possible. 425 if (reader->js_fill == NULL) 426 break; 427 len = (int)(reader->js_end - p); 428 reader->js_used = (int)(p - reader->js_buf); 429 if (!reader->js_fill(reader)) 430 break; // didn't get more 431 p = reader->js_buf + reader->js_used; 432 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 433 continue; 434 } 435 436 if (*p == '\\') 437 { 438 c = -1; 439 switch (p[1]) 440 { 441 case '\\': c = '\\'; break; 442 case '"': c = '"'; break; 443 case 'b': c = BS; break; 444 case 't': c = TAB; break; 445 case 'n': c = NL; break; 446 case 'f': c = FF; break; 447 case 'r': c = CAR; break; 448 case 'u': 449 if (reader->js_fill != NULL 450 && (int)(reader->js_end - p) < NUMBUFLEN) 451 { 452 reader->js_used = (int)(p - reader->js_buf); 453 if (reader->js_fill(reader)) 454 { 455 p = reader->js_buf + reader->js_used; 456 reader->js_end = reader->js_buf 457 + STRLEN(reader->js_buf); 458 } 459 } 460 nr = 0; 461 len = 0; 462 vim_str2nr(p + 2, NULL, &len, 463 STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE); 464 if (len == 0) 465 { 466 if (res != NULL) 467 ga_clear(&ga); 468 return FAIL; 469 } 470 p += len + 2; 471 if (0xd800 <= nr && nr <= 0xdfff 472 && (int)(reader->js_end - p) >= 6 473 && *p == '\\' && *(p+1) == 'u') 474 { 475 varnumber_T nr2 = 0; 476 477 // decode surrogate pair: \ud812\u3456 478 len = 0; 479 vim_str2nr(p + 2, NULL, &len, 480 STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4, TRUE); 481 if (len == 0) 482 { 483 if (res != NULL) 484 ga_clear(&ga); 485 return FAIL; 486 } 487 if (0xdc00 <= nr2 && nr2 <= 0xdfff) 488 { 489 p += len + 2; 490 nr = (((nr - 0xd800) << 10) | 491 ((nr2 - 0xdc00) & 0x3ff)) + 0x10000; 492 } 493 } 494 if (res != NULL) 495 { 496 char_u buf[NUMBUFLEN]; 497 498 buf[utf_char2bytes((int)nr, buf)] = NUL; 499 ga_concat(&ga, buf); 500 } 501 break; 502 default: 503 // not a special char, skip over backslash 504 ++p; 505 continue; 506 } 507 if (c > 0) 508 { 509 p += 2; 510 if (res != NULL) 511 ga_append(&ga, c); 512 } 513 } 514 else 515 { 516 len = utf_ptr2len(p); 517 if (res != NULL) 518 { 519 if (ga_grow(&ga, len) == FAIL) 520 { 521 ga_clear(&ga); 522 return FAIL; 523 } 524 mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len); 525 ga.ga_len += len; 526 } 527 p += len; 528 } 529 } 530 531 reader->js_used = (int)(p - reader->js_buf); 532 if (*p == quote) 533 { 534 ++reader->js_used; 535 if (res != NULL) 536 { 537 ga_append(&ga, NUL); 538 res->v_type = VAR_STRING; 539 #if defined(USE_ICONV) 540 if (!enc_utf8) 541 { 542 vimconv_T conv; 543 544 // Convert the utf-8 string to 'encoding'. 545 conv.vc_type = CONV_NONE; 546 convert_setup(&conv, (char_u*)"utf-8", p_enc); 547 if (conv.vc_type != CONV_NONE) 548 { 549 res->vval.v_string = 550 string_convert(&conv, ga.ga_data, NULL); 551 vim_free(ga.ga_data); 552 } 553 convert_setup(&conv, NULL, NULL); 554 } 555 else 556 #endif 557 res->vval.v_string = ga.ga_data; 558 } 559 return OK; 560 } 561 if (res != NULL) 562 { 563 res->v_type = VAR_SPECIAL; 564 res->vval.v_number = VVAL_NONE; 565 ga_clear(&ga); 566 } 567 return MAYBE; 568 } 569 570 typedef enum { 571 JSON_ARRAY, // parsing items in an array 572 JSON_OBJECT_KEY, // parsing key of an object 573 JSON_OBJECT // parsing item in an object, after the key 574 } json_decode_T; 575 576 typedef struct { 577 json_decode_T jd_type; 578 typval_T jd_tv; // the list or dict 579 typval_T jd_key_tv; 580 char_u *jd_key; 581 } json_dec_item_T; 582 583 /* 584 * Decode one item and put it in "res". If "res" is NULL only advance. 585 * Must already have skipped white space. 586 * 587 * Return FAIL for a decoding error (and give an error). 588 * Return MAYBE for an incomplete message. 589 */ 590 static int 591 json_decode_item(js_read_T *reader, typval_T *res, int options) 592 { 593 char_u *p; 594 int len; 595 int retval; 596 garray_T stack; 597 typval_T item; 598 typval_T *cur_item; 599 json_dec_item_T *top_item; 600 char_u key_buf[NUMBUFLEN]; 601 602 ga_init2(&stack, sizeof(json_dec_item_T), 100); 603 cur_item = res; 604 init_tv(&item); 605 if (res != NULL) 606 init_tv(res); 607 608 fill_numbuflen(reader); 609 p = reader->js_buf + reader->js_used; 610 for (;;) 611 { 612 top_item = NULL; 613 if (stack.ga_len > 0) 614 { 615 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; 616 json_skip_white(reader); 617 p = reader->js_buf + reader->js_used; 618 if (*p == NUL) 619 { 620 retval = MAYBE; 621 if (top_item->jd_type == JSON_OBJECT) 622 // did get the key, clear it 623 clear_tv(&top_item->jd_key_tv); 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, (int)(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 emsg(_(e_invarg)); 743 retval = FAIL; 744 } 745 break; 746 747 case ',': // comma: empty item 748 if ((options & JSON_JS) == 0) 749 { 750 emsg(_(e_invarg)); 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 emsg(_(e_invarg)); 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 emsg(_(e_invarg)); 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 clear_tv(cur_item); 926 emsg(_(e_invarg)); 927 retval = FAIL; 928 goto theend; 929 } 930 } 931 } 932 933 item_end: 934 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; 935 switch (top_item->jd_type) 936 { 937 case JSON_ARRAY: 938 if (res != NULL) 939 { 940 listitem_T *li = listitem_alloc(); 941 942 if (li == NULL) 943 { 944 clear_tv(cur_item); 945 retval = FAIL; 946 goto theend; 947 } 948 li->li_tv = *cur_item; 949 list_append(top_item->jd_tv.vval.v_list, li); 950 } 951 if (cur_item != NULL) 952 cur_item = &item; 953 954 json_skip_white(reader); 955 p = reader->js_buf + reader->js_used; 956 if (*p == ',') 957 ++reader->js_used; 958 else if (*p != ']') 959 { 960 if (*p == NUL) 961 retval = MAYBE; 962 else 963 { 964 emsg(_(e_invarg)); 965 retval = FAIL; 966 } 967 goto theend; 968 } 969 break; 970 971 case JSON_OBJECT_KEY: 972 json_skip_white(reader); 973 p = reader->js_buf + reader->js_used; 974 if (*p != ':') 975 { 976 if (cur_item != NULL) 977 clear_tv(cur_item); 978 if (*p == NUL) 979 retval = MAYBE; 980 else 981 { 982 emsg(_(e_invarg)); 983 retval = FAIL; 984 } 985 goto theend; 986 } 987 ++reader->js_used; 988 json_skip_white(reader); 989 top_item->jd_type = JSON_OBJECT; 990 if (cur_item != NULL) 991 cur_item = &item; 992 break; 993 994 case JSON_OBJECT: 995 if (cur_item != NULL 996 && dict_find(top_item->jd_tv.vval.v_dict, 997 top_item->jd_key, -1) != NULL) 998 { 999 semsg(_("E938: Duplicate key in JSON: \"%s\""), 1000 top_item->jd_key); 1001 clear_tv(&top_item->jd_key_tv); 1002 clear_tv(cur_item); 1003 retval = FAIL; 1004 goto theend; 1005 } 1006 1007 if (cur_item != NULL) 1008 { 1009 dictitem_T *di = dictitem_alloc(top_item->jd_key); 1010 1011 clear_tv(&top_item->jd_key_tv); 1012 if (di == NULL) 1013 { 1014 clear_tv(cur_item); 1015 retval = FAIL; 1016 goto theend; 1017 } 1018 di->di_tv = *cur_item; 1019 di->di_tv.v_lock = 0; 1020 if (dict_add(top_item->jd_tv.vval.v_dict, di) == FAIL) 1021 { 1022 dictitem_free(di); 1023 retval = FAIL; 1024 goto theend; 1025 } 1026 } 1027 1028 json_skip_white(reader); 1029 p = reader->js_buf + reader->js_used; 1030 if (*p == ',') 1031 ++reader->js_used; 1032 else if (*p != '}') 1033 { 1034 if (*p == NUL) 1035 retval = MAYBE; 1036 else 1037 { 1038 emsg(_(e_invarg)); 1039 retval = FAIL; 1040 } 1041 goto theend; 1042 } 1043 top_item->jd_type = JSON_OBJECT_KEY; 1044 if (cur_item != NULL) 1045 cur_item = &top_item->jd_key_tv; 1046 break; 1047 } 1048 } 1049 1050 // Get here when parsing failed. 1051 if (res != NULL) 1052 { 1053 clear_tv(res); 1054 res->v_type = VAR_SPECIAL; 1055 res->vval.v_number = VVAL_NONE; 1056 } 1057 emsg(_(e_invarg)); 1058 1059 theend: 1060 ga_clear(&stack); 1061 return retval; 1062 } 1063 1064 /* 1065 * Decode the JSON from "reader" and store the result in "res". 1066 * "options" can be JSON_JS or zero; 1067 * Return FAIL if not the whole message was consumed. 1068 */ 1069 static int 1070 json_decode_all(js_read_T *reader, typval_T *res, int options) 1071 { 1072 int ret; 1073 1074 // We find the end once, to avoid calling strlen() many times. 1075 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 1076 json_skip_white(reader); 1077 ret = json_decode_item(reader, res, options); 1078 if (ret != OK) 1079 { 1080 if (ret == MAYBE) 1081 emsg(_(e_invarg)); 1082 return FAIL; 1083 } 1084 json_skip_white(reader); 1085 if (reader->js_buf[reader->js_used] != NUL) 1086 { 1087 emsg(_(e_trailing)); 1088 return FAIL; 1089 } 1090 return OK; 1091 } 1092 1093 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) 1094 /* 1095 * Decode the JSON from "reader" and store the result in "res". 1096 * "options" can be JSON_JS or zero; 1097 * Return FAIL for a decoding error. 1098 * Return MAYBE for an incomplete message. 1099 * Consumes the message anyway. 1100 */ 1101 int 1102 json_decode(js_read_T *reader, typval_T *res, int options) 1103 { 1104 int ret; 1105 1106 // We find the end once, to avoid calling strlen() many times. 1107 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 1108 json_skip_white(reader); 1109 ret = json_decode_item(reader, res, options); 1110 json_skip_white(reader); 1111 1112 return ret; 1113 } 1114 #endif 1115 1116 /* 1117 * Decode the JSON from "reader" to find the end of the message. 1118 * "options" can be JSON_JS or zero. 1119 * This is only used for testing. 1120 * Return FAIL if the message has a decoding error. 1121 * Return MAYBE if the message is truncated, need to read more. 1122 * This only works reliable if the message contains an object, array or 1123 * string. A number might be truncated without knowing. 1124 * Does not advance the reader. 1125 */ 1126 int 1127 json_find_end(js_read_T *reader, int options) 1128 { 1129 int used_save = reader->js_used; 1130 int ret; 1131 1132 // We find the end once, to avoid calling strlen() many times. 1133 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 1134 json_skip_white(reader); 1135 ret = json_decode_item(reader, NULL, options); 1136 reader->js_used = used_save; 1137 return ret; 1138 } 1139 1140 /* 1141 * "js_decode()" function 1142 */ 1143 void 1144 f_js_decode(typval_T *argvars, typval_T *rettv) 1145 { 1146 js_read_T reader; 1147 1148 reader.js_buf = tv_get_string(&argvars[0]); 1149 reader.js_fill = NULL; 1150 reader.js_used = 0; 1151 if (json_decode_all(&reader, rettv, JSON_JS) != OK) 1152 emsg(_(e_invarg)); 1153 } 1154 1155 /* 1156 * "js_encode()" function 1157 */ 1158 void 1159 f_js_encode(typval_T *argvars, typval_T *rettv) 1160 { 1161 rettv->v_type = VAR_STRING; 1162 rettv->vval.v_string = json_encode(&argvars[0], JSON_JS); 1163 } 1164 1165 /* 1166 * "json_decode()" function 1167 */ 1168 void 1169 f_json_decode(typval_T *argvars, typval_T *rettv) 1170 { 1171 js_read_T reader; 1172 1173 reader.js_buf = tv_get_string(&argvars[0]); 1174 reader.js_fill = NULL; 1175 reader.js_used = 0; 1176 json_decode_all(&reader, rettv, 0); 1177 } 1178 1179 /* 1180 * "json_encode()" function 1181 */ 1182 void 1183 f_json_encode(typval_T *argvars, typval_T *rettv) 1184 { 1185 rettv->v_type = VAR_STRING; 1186 rettv->vval.v_string = json_encode(&argvars[0], 0); 1187 } 1188 #endif 1189