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 CHECK_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_ANY: 355 case VAR_VOID: 356 internal_error_no_abort("json_encode_item()"); 357 return FAIL; 358 } 359 return OK; 360 } 361 362 /* 363 * When "reader" has less than NUMBUFLEN bytes available, call the fill 364 * callback to get more. 365 */ 366 static void 367 fill_numbuflen(js_read_T *reader) 368 { 369 if (reader->js_fill != NULL && (int)(reader->js_end - reader->js_buf) 370 - reader->js_used < NUMBUFLEN) 371 { 372 if (reader->js_fill(reader)) 373 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 374 } 375 } 376 377 /* 378 * Skip white space in "reader". All characters <= space are considered white 379 * space. 380 * Also tops up readahead when needed. 381 */ 382 static void 383 json_skip_white(js_read_T *reader) 384 { 385 int c; 386 387 for (;;) 388 { 389 c = reader->js_buf[reader->js_used]; 390 if (reader->js_fill != NULL && c == NUL) 391 { 392 if (reader->js_fill(reader)) 393 { 394 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 395 continue; 396 } 397 } 398 if (c == NUL || c > ' ') 399 break; 400 ++reader->js_used; 401 } 402 fill_numbuflen(reader); 403 } 404 405 static int 406 json_decode_string(js_read_T *reader, typval_T *res, int quote) 407 { 408 garray_T ga; 409 int len; 410 char_u *p; 411 int c; 412 varnumber_T nr; 413 414 if (res != NULL) 415 ga_init2(&ga, 1, 200); 416 417 p = reader->js_buf + reader->js_used + 1; // skip over " or ' 418 while (*p != quote) 419 { 420 // The JSON is always expected to be utf-8, thus use utf functions 421 // here. The string is converted below if needed. 422 if (*p == NUL || p[1] == NUL || utf_ptr2len(p) < utf_byte2len(*p)) 423 { 424 // Not enough bytes to make a character or end of the string. Get 425 // more if possible. 426 if (reader->js_fill == NULL) 427 break; 428 len = (int)(reader->js_end - p); 429 reader->js_used = (int)(p - reader->js_buf); 430 if (!reader->js_fill(reader)) 431 break; // didn't get more 432 p = reader->js_buf + reader->js_used; 433 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 434 continue; 435 } 436 437 if (*p == '\\') 438 { 439 c = -1; 440 switch (p[1]) 441 { 442 case '\\': c = '\\'; break; 443 case '"': c = '"'; break; 444 case 'b': c = BS; break; 445 case 't': c = TAB; break; 446 case 'n': c = NL; break; 447 case 'f': c = FF; break; 448 case 'r': c = CAR; break; 449 case 'u': 450 if (reader->js_fill != NULL 451 && (int)(reader->js_end - p) < NUMBUFLEN) 452 { 453 reader->js_used = (int)(p - reader->js_buf); 454 if (reader->js_fill(reader)) 455 { 456 p = reader->js_buf + reader->js_used; 457 reader->js_end = reader->js_buf 458 + STRLEN(reader->js_buf); 459 } 460 } 461 nr = 0; 462 len = 0; 463 vim_str2nr(p + 2, NULL, &len, 464 STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE); 465 if (len == 0) 466 { 467 if (res != NULL) 468 ga_clear(&ga); 469 return FAIL; 470 } 471 p += len + 2; 472 if (0xd800 <= nr && nr <= 0xdfff 473 && (int)(reader->js_end - p) >= 6 474 && *p == '\\' && *(p+1) == 'u') 475 { 476 varnumber_T nr2 = 0; 477 478 // decode surrogate pair: \ud812\u3456 479 len = 0; 480 vim_str2nr(p + 2, NULL, &len, 481 STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4, TRUE); 482 if (len == 0) 483 { 484 if (res != NULL) 485 ga_clear(&ga); 486 return FAIL; 487 } 488 if (0xdc00 <= nr2 && nr2 <= 0xdfff) 489 { 490 p += len + 2; 491 nr = (((nr - 0xd800) << 10) | 492 ((nr2 - 0xdc00) & 0x3ff)) + 0x10000; 493 } 494 } 495 if (res != NULL) 496 { 497 char_u buf[NUMBUFLEN]; 498 499 buf[utf_char2bytes((int)nr, buf)] = NUL; 500 ga_concat(&ga, buf); 501 } 502 break; 503 default: 504 // not a special char, skip over backslash 505 ++p; 506 continue; 507 } 508 if (c > 0) 509 { 510 p += 2; 511 if (res != NULL) 512 ga_append(&ga, c); 513 } 514 } 515 else 516 { 517 len = utf_ptr2len(p); 518 if (res != NULL) 519 { 520 if (ga_grow(&ga, len) == FAIL) 521 { 522 ga_clear(&ga); 523 return FAIL; 524 } 525 mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len); 526 ga.ga_len += len; 527 } 528 p += len; 529 } 530 } 531 532 reader->js_used = (int)(p - reader->js_buf); 533 if (*p == quote) 534 { 535 ++reader->js_used; 536 if (res != NULL) 537 { 538 ga_append(&ga, NUL); 539 res->v_type = VAR_STRING; 540 #if defined(USE_ICONV) 541 if (!enc_utf8) 542 { 543 vimconv_T conv; 544 545 // Convert the utf-8 string to 'encoding'. 546 conv.vc_type = CONV_NONE; 547 convert_setup(&conv, (char_u*)"utf-8", p_enc); 548 if (conv.vc_type != CONV_NONE) 549 { 550 res->vval.v_string = 551 string_convert(&conv, ga.ga_data, NULL); 552 vim_free(ga.ga_data); 553 } 554 convert_setup(&conv, NULL, NULL); 555 } 556 else 557 #endif 558 res->vval.v_string = ga.ga_data; 559 } 560 return OK; 561 } 562 if (res != NULL) 563 { 564 res->v_type = VAR_SPECIAL; 565 res->vval.v_number = VVAL_NONE; 566 ga_clear(&ga); 567 } 568 return MAYBE; 569 } 570 571 typedef enum { 572 JSON_ARRAY, // parsing items in an array 573 JSON_OBJECT_KEY, // parsing key of an object 574 JSON_OBJECT // parsing item in an object, after the key 575 } json_decode_T; 576 577 typedef struct { 578 json_decode_T jd_type; 579 typval_T jd_tv; // the list or dict 580 typval_T jd_key_tv; 581 char_u *jd_key; 582 } json_dec_item_T; 583 584 /* 585 * Decode one item and put it in "res". If "res" is NULL only advance. 586 * Must already have skipped white space. 587 * 588 * Return FAIL for a decoding error (and give an error). 589 * Return MAYBE for an incomplete message. 590 */ 591 static int 592 json_decode_item(js_read_T *reader, typval_T *res, int options) 593 { 594 char_u *p; 595 int len; 596 int retval; 597 garray_T stack; 598 typval_T item; 599 typval_T *cur_item; 600 json_dec_item_T *top_item; 601 char_u key_buf[NUMBUFLEN]; 602 603 ga_init2(&stack, sizeof(json_dec_item_T), 100); 604 cur_item = res; 605 init_tv(&item); 606 if (res != NULL) 607 init_tv(res); 608 609 fill_numbuflen(reader); 610 p = reader->js_buf + reader->js_used; 611 for (;;) 612 { 613 top_item = NULL; 614 if (stack.ga_len > 0) 615 { 616 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; 617 json_skip_white(reader); 618 p = reader->js_buf + reader->js_used; 619 if (*p == NUL) 620 { 621 retval = MAYBE; 622 if (top_item->jd_type == JSON_OBJECT) 623 // did get the key, clear it 624 clear_tv(&top_item->jd_key_tv); 625 goto theend; 626 } 627 if (top_item->jd_type == JSON_OBJECT_KEY 628 || top_item->jd_type == JSON_ARRAY) 629 { 630 // Check for end of object or array. 631 if (*p == (top_item->jd_type == JSON_ARRAY ? ']' : '}')) 632 { 633 ++reader->js_used; // consume the ']' or '}' 634 --stack.ga_len; 635 if (stack.ga_len == 0) 636 { 637 retval = OK; 638 goto theend; 639 } 640 if (cur_item != NULL) 641 cur_item = &top_item->jd_tv; 642 goto item_end; 643 } 644 } 645 } 646 647 if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY 648 && (options & JSON_JS) 649 && reader->js_buf[reader->js_used] != '"' 650 && reader->js_buf[reader->js_used] != '\'' 651 && reader->js_buf[reader->js_used] != '[' 652 && reader->js_buf[reader->js_used] != '{') 653 { 654 char_u *key; 655 656 // accept an object key that is not in quotes 657 key = p = reader->js_buf + reader->js_used; 658 while (*p != NUL && *p != ':' && *p > ' ') 659 ++p; 660 if (cur_item != NULL) 661 { 662 cur_item->v_type = VAR_STRING; 663 cur_item->vval.v_string = vim_strnsave(key, (int)(p - key)); 664 top_item->jd_key = cur_item->vval.v_string; 665 } 666 reader->js_used += (int)(p - key); 667 } 668 else 669 { 670 switch (*p) 671 { 672 case '[': // start of array 673 if (top_item && top_item->jd_type == JSON_OBJECT_KEY) 674 { 675 retval = FAIL; 676 break; 677 } 678 if (ga_grow(&stack, 1) == FAIL) 679 { 680 retval = FAIL; 681 break; 682 } 683 if (cur_item != NULL && rettv_list_alloc(cur_item) == FAIL) 684 { 685 cur_item->v_type = VAR_SPECIAL; 686 cur_item->vval.v_number = VVAL_NONE; 687 retval = FAIL; 688 break; 689 } 690 691 ++reader->js_used; // consume the '[' 692 top_item = ((json_dec_item_T *)stack.ga_data) 693 + stack.ga_len; 694 top_item->jd_type = JSON_ARRAY; 695 ++stack.ga_len; 696 if (cur_item != NULL) 697 { 698 top_item->jd_tv = *cur_item; 699 cur_item = &item; 700 } 701 continue; 702 703 case '{': // start of object 704 if (top_item && top_item->jd_type == JSON_OBJECT_KEY) 705 { 706 retval = FAIL; 707 break; 708 } 709 if (ga_grow(&stack, 1) == FAIL) 710 { 711 retval = FAIL; 712 break; 713 } 714 if (cur_item != NULL && rettv_dict_alloc(cur_item) == FAIL) 715 { 716 cur_item->v_type = VAR_SPECIAL; 717 cur_item->vval.v_number = VVAL_NONE; 718 retval = FAIL; 719 break; 720 } 721 722 ++reader->js_used; // consume the '{' 723 top_item = ((json_dec_item_T *)stack.ga_data) 724 + stack.ga_len; 725 top_item->jd_type = JSON_OBJECT_KEY; 726 ++stack.ga_len; 727 if (cur_item != NULL) 728 { 729 top_item->jd_tv = *cur_item; 730 cur_item = &top_item->jd_key_tv; 731 } 732 continue; 733 734 case '"': // string 735 retval = json_decode_string(reader, cur_item, *p); 736 break; 737 738 case '\'': 739 if (options & JSON_JS) 740 retval = json_decode_string(reader, cur_item, *p); 741 else 742 { 743 emsg(_(e_invarg)); 744 retval = FAIL; 745 } 746 break; 747 748 case ',': // comma: empty item 749 if ((options & JSON_JS) == 0) 750 { 751 emsg(_(e_invarg)); 752 retval = FAIL; 753 break; 754 } 755 // FALLTHROUGH 756 case NUL: // empty 757 if (cur_item != NULL) 758 { 759 cur_item->v_type = VAR_SPECIAL; 760 cur_item->vval.v_number = VVAL_NONE; 761 } 762 retval = OK; 763 break; 764 765 default: 766 if (VIM_ISDIGIT(*p) || (*p == '-' 767 && (VIM_ISDIGIT(p[1]) || p[1] == NUL))) 768 { 769 char_u *sp = p; 770 771 if (*sp == '-') 772 { 773 ++sp; 774 if (*sp == NUL) 775 { 776 retval = MAYBE; 777 break; 778 } 779 if (!VIM_ISDIGIT(*sp)) 780 { 781 emsg(_(e_invarg)); 782 retval = FAIL; 783 break; 784 } 785 } 786 sp = skipdigits(sp); 787 #ifdef FEAT_FLOAT 788 if (*sp == '.' || *sp == 'e' || *sp == 'E') 789 { 790 if (cur_item == NULL) 791 { 792 float_T f; 793 794 len = string2float(p, &f); 795 } 796 else 797 { 798 cur_item->v_type = VAR_FLOAT; 799 len = string2float(p, &cur_item->vval.v_float); 800 } 801 } 802 else 803 #endif 804 { 805 varnumber_T nr; 806 807 vim_str2nr(reader->js_buf + reader->js_used, 808 NULL, &len, 0, // what 809 &nr, NULL, 0, TRUE); 810 if (len == 0) 811 { 812 emsg(_(e_invarg)); 813 retval = FAIL; 814 goto theend; 815 } 816 if (cur_item != NULL) 817 { 818 cur_item->v_type = VAR_NUMBER; 819 cur_item->vval.v_number = nr; 820 } 821 } 822 reader->js_used += len; 823 retval = OK; 824 break; 825 } 826 if (STRNICMP((char *)p, "false", 5) == 0) 827 { 828 reader->js_used += 5; 829 if (cur_item != NULL) 830 { 831 cur_item->v_type = VAR_BOOL; 832 cur_item->vval.v_number = VVAL_FALSE; 833 } 834 retval = OK; 835 break; 836 } 837 if (STRNICMP((char *)p, "true", 4) == 0) 838 { 839 reader->js_used += 4; 840 if (cur_item != NULL) 841 { 842 cur_item->v_type = VAR_BOOL; 843 cur_item->vval.v_number = VVAL_TRUE; 844 } 845 retval = OK; 846 break; 847 } 848 if (STRNICMP((char *)p, "null", 4) == 0) 849 { 850 reader->js_used += 4; 851 if (cur_item != NULL) 852 { 853 cur_item->v_type = VAR_SPECIAL; 854 cur_item->vval.v_number = VVAL_NULL; 855 } 856 retval = OK; 857 break; 858 } 859 #ifdef FEAT_FLOAT 860 if (STRNICMP((char *)p, "NaN", 3) == 0) 861 { 862 reader->js_used += 3; 863 if (cur_item != NULL) 864 { 865 cur_item->v_type = VAR_FLOAT; 866 cur_item->vval.v_float = NAN; 867 } 868 retval = OK; 869 break; 870 } 871 if (STRNICMP((char *)p, "-Infinity", 9) == 0) 872 { 873 reader->js_used += 9; 874 if (cur_item != NULL) 875 { 876 cur_item->v_type = VAR_FLOAT; 877 cur_item->vval.v_float = -INFINITY; 878 } 879 retval = OK; 880 break; 881 } 882 if (STRNICMP((char *)p, "Infinity", 8) == 0) 883 { 884 reader->js_used += 8; 885 if (cur_item != NULL) 886 { 887 cur_item->v_type = VAR_FLOAT; 888 cur_item->vval.v_float = INFINITY; 889 } 890 retval = OK; 891 break; 892 } 893 #endif 894 // check for truncated name 895 len = (int)(reader->js_end 896 - (reader->js_buf + reader->js_used)); 897 if ( 898 (len < 5 && STRNICMP((char *)p, "false", len) == 0) 899 #ifdef FEAT_FLOAT 900 || (len < 9 && STRNICMP((char *)p, "-Infinity", len) == 0) 901 || (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0) 902 || (len < 3 && STRNICMP((char *)p, "NaN", len) == 0) 903 #endif 904 || (len < 4 && (STRNICMP((char *)p, "true", len) == 0 905 || STRNICMP((char *)p, "null", len) == 0))) 906 907 retval = MAYBE; 908 else 909 retval = FAIL; 910 break; 911 } 912 913 // We are finished when retval is FAIL or MAYBE and when at the 914 // toplevel. 915 if (retval == FAIL) 916 break; 917 if (retval == MAYBE || stack.ga_len == 0) 918 goto theend; 919 920 if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY 921 && cur_item != NULL) 922 { 923 top_item->jd_key = tv_get_string_buf_chk(cur_item, key_buf); 924 if (top_item->jd_key == NULL) 925 { 926 clear_tv(cur_item); 927 emsg(_(e_invarg)); 928 retval = FAIL; 929 goto theend; 930 } 931 } 932 } 933 934 item_end: 935 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; 936 switch (top_item->jd_type) 937 { 938 case JSON_ARRAY: 939 if (res != NULL) 940 { 941 listitem_T *li = listitem_alloc(); 942 943 if (li == NULL) 944 { 945 clear_tv(cur_item); 946 retval = FAIL; 947 goto theend; 948 } 949 li->li_tv = *cur_item; 950 list_append(top_item->jd_tv.vval.v_list, li); 951 } 952 if (cur_item != NULL) 953 cur_item = &item; 954 955 json_skip_white(reader); 956 p = reader->js_buf + reader->js_used; 957 if (*p == ',') 958 ++reader->js_used; 959 else if (*p != ']') 960 { 961 if (*p == NUL) 962 retval = MAYBE; 963 else 964 { 965 emsg(_(e_invarg)); 966 retval = FAIL; 967 } 968 goto theend; 969 } 970 break; 971 972 case JSON_OBJECT_KEY: 973 json_skip_white(reader); 974 p = reader->js_buf + reader->js_used; 975 if (*p != ':') 976 { 977 if (cur_item != NULL) 978 clear_tv(cur_item); 979 if (*p == NUL) 980 retval = MAYBE; 981 else 982 { 983 emsg(_(e_invarg)); 984 retval = FAIL; 985 } 986 goto theend; 987 } 988 ++reader->js_used; 989 json_skip_white(reader); 990 top_item->jd_type = JSON_OBJECT; 991 if (cur_item != NULL) 992 cur_item = &item; 993 break; 994 995 case JSON_OBJECT: 996 if (cur_item != NULL 997 && dict_find(top_item->jd_tv.vval.v_dict, 998 top_item->jd_key, -1) != NULL) 999 { 1000 semsg(_("E938: Duplicate key in JSON: \"%s\""), 1001 top_item->jd_key); 1002 clear_tv(&top_item->jd_key_tv); 1003 clear_tv(cur_item); 1004 retval = FAIL; 1005 goto theend; 1006 } 1007 1008 if (cur_item != NULL) 1009 { 1010 dictitem_T *di = dictitem_alloc(top_item->jd_key); 1011 1012 clear_tv(&top_item->jd_key_tv); 1013 if (di == NULL) 1014 { 1015 clear_tv(cur_item); 1016 retval = FAIL; 1017 goto theend; 1018 } 1019 di->di_tv = *cur_item; 1020 di->di_tv.v_lock = 0; 1021 if (dict_add(top_item->jd_tv.vval.v_dict, di) == FAIL) 1022 { 1023 dictitem_free(di); 1024 retval = FAIL; 1025 goto theend; 1026 } 1027 } 1028 1029 json_skip_white(reader); 1030 p = reader->js_buf + reader->js_used; 1031 if (*p == ',') 1032 ++reader->js_used; 1033 else if (*p != '}') 1034 { 1035 if (*p == NUL) 1036 retval = MAYBE; 1037 else 1038 { 1039 emsg(_(e_invarg)); 1040 retval = FAIL; 1041 } 1042 goto theend; 1043 } 1044 top_item->jd_type = JSON_OBJECT_KEY; 1045 if (cur_item != NULL) 1046 cur_item = &top_item->jd_key_tv; 1047 break; 1048 } 1049 } 1050 1051 // Get here when parsing failed. 1052 if (res != NULL) 1053 { 1054 clear_tv(res); 1055 res->v_type = VAR_SPECIAL; 1056 res->vval.v_number = VVAL_NONE; 1057 } 1058 emsg(_(e_invarg)); 1059 1060 theend: 1061 ga_clear(&stack); 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 emsg(_(e_invarg)); 1083 return FAIL; 1084 } 1085 json_skip_white(reader); 1086 if (reader->js_buf[reader->js_used] != NUL) 1087 { 1088 emsg(_(e_trailing)); 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