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