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