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