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); 456 p += len + 2; 457 if (0xd800 <= nr && nr <= 0xdfff 458 && (int)(reader->js_end - p) >= 6 459 && *p == '\\' && *(p+1) == 'u') 460 { 461 varnumber_T nr2 = 0; 462 463 /* decode surrogate pair: \ud812\u3456 */ 464 len = 0; 465 vim_str2nr(p + 2, NULL, &len, 466 STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4); 467 if (0xdc00 <= nr2 && nr2 <= 0xdfff) 468 { 469 p += len + 2; 470 nr = (((nr - 0xd800) << 10) | 471 ((nr2 - 0xdc00) & 0x3ff)) + 0x10000; 472 } 473 } 474 if (res != NULL) 475 { 476 char_u buf[NUMBUFLEN]; 477 buf[utf_char2bytes((int)nr, buf)] = NUL; 478 ga_concat(&ga, buf); 479 } 480 break; 481 default: 482 /* not a special char, skip over \ */ 483 ++p; 484 continue; 485 } 486 if (c > 0) 487 { 488 p += 2; 489 if (res != NULL) 490 ga_append(&ga, c); 491 } 492 } 493 else 494 { 495 len = utf_ptr2len(p); 496 if (res != NULL) 497 { 498 if (ga_grow(&ga, len) == FAIL) 499 { 500 ga_clear(&ga); 501 return FAIL; 502 } 503 mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len); 504 ga.ga_len += len; 505 } 506 p += len; 507 } 508 } 509 510 reader->js_used = (int)(p - reader->js_buf); 511 if (*p == quote) 512 { 513 ++reader->js_used; 514 if (res != NULL) 515 { 516 ga_append(&ga, NUL); 517 res->v_type = VAR_STRING; 518 #if defined(USE_ICONV) 519 if (!enc_utf8) 520 { 521 vimconv_T conv; 522 523 /* Convert the utf-8 string to 'encoding'. */ 524 conv.vc_type = CONV_NONE; 525 convert_setup(&conv, (char_u*)"utf-8", p_enc); 526 if (conv.vc_type != CONV_NONE) 527 { 528 res->vval.v_string = 529 string_convert(&conv, ga.ga_data, NULL); 530 vim_free(ga.ga_data); 531 } 532 convert_setup(&conv, NULL, NULL); 533 } 534 else 535 #endif 536 res->vval.v_string = ga.ga_data; 537 } 538 return OK; 539 } 540 if (res != NULL) 541 { 542 res->v_type = VAR_SPECIAL; 543 res->vval.v_number = VVAL_NONE; 544 ga_clear(&ga); 545 } 546 return MAYBE; 547 } 548 549 typedef enum { 550 JSON_ARRAY, /* parsing items in an array */ 551 JSON_OBJECT_KEY, /* parsing key of an object */ 552 JSON_OBJECT /* parsing item in an object, after the key */ 553 } json_decode_T; 554 555 typedef struct { 556 json_decode_T jd_type; 557 typval_T jd_tv; /* the list or dict */ 558 typval_T jd_key_tv; 559 char_u *jd_key; 560 } json_dec_item_T; 561 562 /* 563 * Decode one item and put it in "res". If "res" is NULL only advance. 564 * Must already have skipped white space. 565 * 566 * Return FAIL for a decoding error (and give an error). 567 * Return MAYBE for an incomplete message. 568 */ 569 static int 570 json_decode_item(js_read_T *reader, typval_T *res, int options) 571 { 572 char_u *p; 573 int len; 574 int retval; 575 garray_T stack; 576 typval_T item; 577 typval_T *cur_item; 578 json_dec_item_T *top_item; 579 char_u key_buf[NUMBUFLEN]; 580 581 ga_init2(&stack, sizeof(json_dec_item_T), 100); 582 cur_item = res; 583 init_tv(&item); 584 if (res != NULL) 585 init_tv(res); 586 587 fill_numbuflen(reader); 588 p = reader->js_buf + reader->js_used; 589 for (;;) 590 { 591 top_item = NULL; 592 if (stack.ga_len > 0) 593 { 594 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; 595 json_skip_white(reader); 596 p = reader->js_buf + reader->js_used; 597 if (*p == NUL) 598 { 599 retval = MAYBE; 600 if (top_item->jd_type == JSON_OBJECT) 601 /* did get the key, clear it */ 602 clear_tv(&top_item->jd_key_tv); 603 goto theend; 604 } 605 if (top_item->jd_type == JSON_OBJECT_KEY 606 || top_item->jd_type == JSON_ARRAY) 607 { 608 /* Check for end of object or array. */ 609 if (*p == (top_item->jd_type == JSON_ARRAY ? ']' : '}')) 610 { 611 ++reader->js_used; /* consume the ']' or '}' */ 612 --stack.ga_len; 613 if (stack.ga_len == 0) 614 { 615 retval = OK; 616 goto theend; 617 } 618 if (cur_item != NULL) 619 cur_item = &top_item->jd_tv; 620 goto item_end; 621 } 622 } 623 } 624 625 if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY 626 && (options & JSON_JS) 627 && reader->js_buf[reader->js_used] != '"' 628 && reader->js_buf[reader->js_used] != '\'' 629 && reader->js_buf[reader->js_used] != '[' 630 && reader->js_buf[reader->js_used] != '{') 631 { 632 char_u *key; 633 634 /* accept an object key that is not in quotes */ 635 key = p = reader->js_buf + reader->js_used; 636 while (*p != NUL && *p != ':' && *p > ' ') 637 ++p; 638 if (cur_item != NULL) 639 { 640 cur_item->v_type = VAR_STRING; 641 cur_item->vval.v_string = vim_strnsave(key, (int)(p - key)); 642 top_item->jd_key = cur_item->vval.v_string; 643 } 644 reader->js_used += (int)(p - key); 645 } 646 else 647 { 648 switch (*p) 649 { 650 case '[': /* start of array */ 651 if (top_item && top_item->jd_type == JSON_OBJECT_KEY) 652 { 653 retval = FAIL; 654 break; 655 } 656 if (ga_grow(&stack, 1) == FAIL) 657 { 658 retval = FAIL; 659 break; 660 } 661 if (cur_item != NULL && rettv_list_alloc(cur_item) == FAIL) 662 { 663 cur_item->v_type = VAR_SPECIAL; 664 cur_item->vval.v_number = VVAL_NONE; 665 retval = FAIL; 666 break; 667 } 668 669 ++reader->js_used; /* consume the '[' */ 670 top_item = ((json_dec_item_T *)stack.ga_data) 671 + stack.ga_len; 672 top_item->jd_type = JSON_ARRAY; 673 ++stack.ga_len; 674 if (cur_item != NULL) 675 { 676 top_item->jd_tv = *cur_item; 677 cur_item = &item; 678 } 679 continue; 680 681 case '{': /* start of object */ 682 if (top_item && top_item->jd_type == JSON_OBJECT_KEY) 683 { 684 retval = FAIL; 685 break; 686 } 687 if (ga_grow(&stack, 1) == FAIL) 688 { 689 retval = FAIL; 690 break; 691 } 692 if (cur_item != NULL && rettv_dict_alloc(cur_item) == FAIL) 693 { 694 cur_item->v_type = VAR_SPECIAL; 695 cur_item->vval.v_number = VVAL_NONE; 696 retval = FAIL; 697 break; 698 } 699 700 ++reader->js_used; /* consume the '{' */ 701 top_item = ((json_dec_item_T *)stack.ga_data) 702 + stack.ga_len; 703 top_item->jd_type = JSON_OBJECT_KEY; 704 ++stack.ga_len; 705 if (cur_item != NULL) 706 { 707 top_item->jd_tv = *cur_item; 708 cur_item = &top_item->jd_key_tv; 709 } 710 continue; 711 712 case '"': /* string */ 713 retval = json_decode_string(reader, cur_item, *p); 714 break; 715 716 case '\'': 717 if (options & JSON_JS) 718 retval = json_decode_string(reader, cur_item, *p); 719 else 720 { 721 emsg(_(e_invarg)); 722 retval = FAIL; 723 } 724 break; 725 726 case ',': /* comma: empty item */ 727 if ((options & JSON_JS) == 0) 728 { 729 emsg(_(e_invarg)); 730 retval = FAIL; 731 break; 732 } 733 /* FALLTHROUGH */ 734 case NUL: /* empty */ 735 if (cur_item != NULL) 736 { 737 cur_item->v_type = VAR_SPECIAL; 738 cur_item->vval.v_number = VVAL_NONE; 739 } 740 retval = OK; 741 break; 742 743 default: 744 if (VIM_ISDIGIT(*p) || (*p == '-' && VIM_ISDIGIT(p[1]))) 745 { 746 #ifdef FEAT_FLOAT 747 char_u *sp = p; 748 749 if (*sp == '-') 750 { 751 ++sp; 752 if (*sp == NUL) 753 { 754 retval = MAYBE; 755 break; 756 } 757 if (!VIM_ISDIGIT(*sp)) 758 { 759 emsg(_(e_invarg)); 760 retval = FAIL; 761 break; 762 } 763 } 764 sp = skipdigits(sp); 765 if (*sp == '.' || *sp == 'e' || *sp == 'E') 766 { 767 if (cur_item == NULL) 768 { 769 float_T f; 770 771 len = string2float(p, &f); 772 } 773 else 774 { 775 cur_item->v_type = VAR_FLOAT; 776 len = string2float(p, &cur_item->vval.v_float); 777 } 778 } 779 else 780 #endif 781 { 782 varnumber_T nr; 783 784 vim_str2nr(reader->js_buf + reader->js_used, 785 NULL, &len, 0, /* what */ 786 &nr, NULL, 0); 787 if (cur_item != NULL) 788 { 789 cur_item->v_type = VAR_NUMBER; 790 cur_item->vval.v_number = nr; 791 } 792 } 793 reader->js_used += len; 794 retval = OK; 795 break; 796 } 797 if (STRNICMP((char *)p, "false", 5) == 0) 798 { 799 reader->js_used += 5; 800 if (cur_item != NULL) 801 { 802 cur_item->v_type = VAR_SPECIAL; 803 cur_item->vval.v_number = VVAL_FALSE; 804 } 805 retval = OK; 806 break; 807 } 808 if (STRNICMP((char *)p, "true", 4) == 0) 809 { 810 reader->js_used += 4; 811 if (cur_item != NULL) 812 { 813 cur_item->v_type = VAR_SPECIAL; 814 cur_item->vval.v_number = VVAL_TRUE; 815 } 816 retval = OK; 817 break; 818 } 819 if (STRNICMP((char *)p, "null", 4) == 0) 820 { 821 reader->js_used += 4; 822 if (cur_item != NULL) 823 { 824 cur_item->v_type = VAR_SPECIAL; 825 cur_item->vval.v_number = VVAL_NULL; 826 } 827 retval = OK; 828 break; 829 } 830 #ifdef FEAT_FLOAT 831 if (STRNICMP((char *)p, "NaN", 3) == 0) 832 { 833 reader->js_used += 3; 834 if (cur_item != NULL) 835 { 836 cur_item->v_type = VAR_FLOAT; 837 cur_item->vval.v_float = NAN; 838 } 839 retval = OK; 840 break; 841 } 842 if (STRNICMP((char *)p, "-Infinity", 9) == 0) 843 { 844 reader->js_used += 9; 845 if (cur_item != NULL) 846 { 847 cur_item->v_type = VAR_FLOAT; 848 cur_item->vval.v_float = -INFINITY; 849 } 850 retval = OK; 851 break; 852 } 853 if (STRNICMP((char *)p, "Infinity", 8) == 0) 854 { 855 reader->js_used += 8; 856 if (cur_item != NULL) 857 { 858 cur_item->v_type = VAR_FLOAT; 859 cur_item->vval.v_float = INFINITY; 860 } 861 retval = OK; 862 break; 863 } 864 #endif 865 /* check for truncated name */ 866 len = (int)(reader->js_end - (reader->js_buf + reader->js_used)); 867 if ( 868 (len < 5 && STRNICMP((char *)p, "false", len) == 0) 869 #ifdef FEAT_FLOAT 870 || (len < 9 && STRNICMP((char *)p, "-Infinity", len) == 0) 871 || (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0) 872 || (len < 3 && STRNICMP((char *)p, "NaN", len) == 0) 873 #endif 874 || (len < 4 && (STRNICMP((char *)p, "true", len) == 0 875 || STRNICMP((char *)p, "null", len) == 0))) 876 877 retval = MAYBE; 878 else 879 retval = FAIL; 880 break; 881 } 882 883 /* We are finished when retval is FAIL or MAYBE and when at the 884 * toplevel. */ 885 if (retval == FAIL) 886 break; 887 if (retval == MAYBE || stack.ga_len == 0) 888 goto theend; 889 890 if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY 891 && cur_item != NULL) 892 { 893 top_item->jd_key = tv_get_string_buf_chk(cur_item, key_buf); 894 if (top_item->jd_key == NULL) 895 { 896 clear_tv(cur_item); 897 emsg(_(e_invarg)); 898 retval = FAIL; 899 goto theend; 900 } 901 } 902 } 903 904 item_end: 905 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; 906 switch (top_item->jd_type) 907 { 908 case JSON_ARRAY: 909 if (res != NULL) 910 { 911 listitem_T *li = listitem_alloc(); 912 913 if (li == NULL) 914 { 915 clear_tv(cur_item); 916 retval = FAIL; 917 goto theend; 918 } 919 li->li_tv = *cur_item; 920 list_append(top_item->jd_tv.vval.v_list, li); 921 } 922 if (cur_item != NULL) 923 cur_item = &item; 924 925 json_skip_white(reader); 926 p = reader->js_buf + reader->js_used; 927 if (*p == ',') 928 ++reader->js_used; 929 else if (*p != ']') 930 { 931 if (*p == NUL) 932 retval = MAYBE; 933 else 934 { 935 emsg(_(e_invarg)); 936 retval = FAIL; 937 } 938 goto theend; 939 } 940 break; 941 942 case JSON_OBJECT_KEY: 943 json_skip_white(reader); 944 p = reader->js_buf + reader->js_used; 945 if (*p != ':') 946 { 947 if (cur_item != NULL) 948 clear_tv(cur_item); 949 if (*p == NUL) 950 retval = MAYBE; 951 else 952 { 953 emsg(_(e_invarg)); 954 retval = FAIL; 955 } 956 goto theend; 957 } 958 ++reader->js_used; 959 json_skip_white(reader); 960 top_item->jd_type = JSON_OBJECT; 961 if (cur_item != NULL) 962 cur_item = &item; 963 break; 964 965 case JSON_OBJECT: 966 if (cur_item != NULL 967 && dict_find(top_item->jd_tv.vval.v_dict, 968 top_item->jd_key, -1) != NULL) 969 { 970 semsg(_("E938: Duplicate key in JSON: \"%s\""), 971 top_item->jd_key); 972 clear_tv(&top_item->jd_key_tv); 973 clear_tv(cur_item); 974 retval = FAIL; 975 goto theend; 976 } 977 978 if (cur_item != NULL) 979 { 980 dictitem_T *di = dictitem_alloc(top_item->jd_key); 981 982 clear_tv(&top_item->jd_key_tv); 983 if (di == NULL) 984 { 985 clear_tv(cur_item); 986 retval = FAIL; 987 goto theend; 988 } 989 di->di_tv = *cur_item; 990 di->di_tv.v_lock = 0; 991 if (dict_add(top_item->jd_tv.vval.v_dict, di) == FAIL) 992 { 993 dictitem_free(di); 994 retval = FAIL; 995 goto theend; 996 } 997 } 998 999 json_skip_white(reader); 1000 p = reader->js_buf + reader->js_used; 1001 if (*p == ',') 1002 ++reader->js_used; 1003 else if (*p != '}') 1004 { 1005 if (*p == NUL) 1006 retval = MAYBE; 1007 else 1008 { 1009 emsg(_(e_invarg)); 1010 retval = FAIL; 1011 } 1012 goto theend; 1013 } 1014 top_item->jd_type = JSON_OBJECT_KEY; 1015 if (cur_item != NULL) 1016 cur_item = &top_item->jd_key_tv; 1017 break; 1018 } 1019 } 1020 1021 /* Get here when parsing failed. */ 1022 if (res != NULL) 1023 { 1024 clear_tv(res); 1025 res->v_type = VAR_SPECIAL; 1026 res->vval.v_number = VVAL_NONE; 1027 } 1028 emsg(_(e_invarg)); 1029 1030 theend: 1031 ga_clear(&stack); 1032 return retval; 1033 } 1034 1035 /* 1036 * Decode the JSON from "reader" and store the result in "res". 1037 * "options" can be JSON_JS or zero; 1038 * Return FAIL if not the whole message was consumed. 1039 */ 1040 int 1041 json_decode_all(js_read_T *reader, typval_T *res, int options) 1042 { 1043 int ret; 1044 1045 /* We find the end once, to avoid calling strlen() many times. */ 1046 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 1047 json_skip_white(reader); 1048 ret = json_decode_item(reader, res, options); 1049 if (ret != OK) 1050 { 1051 if (ret == MAYBE) 1052 emsg(_(e_invarg)); 1053 return FAIL; 1054 } 1055 json_skip_white(reader); 1056 if (reader->js_buf[reader->js_used] != NUL) 1057 { 1058 emsg(_(e_trailing)); 1059 return FAIL; 1060 } 1061 return OK; 1062 } 1063 1064 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) 1065 /* 1066 * Decode the JSON from "reader" and store the result in "res". 1067 * "options" can be JSON_JS or zero; 1068 * Return FAIL for a decoding error. 1069 * Return MAYBE for an incomplete message. 1070 * Consumes the message anyway. 1071 */ 1072 int 1073 json_decode(js_read_T *reader, typval_T *res, int options) 1074 { 1075 int ret; 1076 1077 /* We find the end once, to avoid calling strlen() many times. */ 1078 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 1079 json_skip_white(reader); 1080 ret = json_decode_item(reader, res, options); 1081 json_skip_white(reader); 1082 1083 return ret; 1084 } 1085 #endif 1086 1087 /* 1088 * Decode the JSON from "reader" to find the end of the message. 1089 * "options" can be JSON_JS or zero. 1090 * This is only used for testing. 1091 * Return FAIL if the message has a decoding error. 1092 * Return MAYBE if the message is truncated, need to read more. 1093 * This only works reliable if the message contains an object, array or 1094 * string. A number might be truncated without knowing. 1095 * Does not advance the reader. 1096 */ 1097 int 1098 json_find_end(js_read_T *reader, int options) 1099 { 1100 int used_save = reader->js_used; 1101 int ret; 1102 1103 /* We find the end once, to avoid calling strlen() many times. */ 1104 reader->js_end = reader->js_buf + STRLEN(reader->js_buf); 1105 json_skip_white(reader); 1106 ret = json_decode_item(reader, NULL, options); 1107 reader->js_used = used_save; 1108 return ret; 1109 } 1110 #endif 1111