comparison src/json.c @ 7883:98a96e0ca73b v7.4.1238

commit https://github.com/vim/vim/commit/56ead341a75e1a0395eee94a3280c67e2278a57e Author: Bram Moolenaar <Bram@vim.org> Date: Tue Feb 2 18:20:08 2016 +0100 patch 7.4.1238 Problem: Can't handle two messages right after each other. Solution: Find the end of the JSON. Read more when incomplete. Add a C test for the JSON decoding.
author Christian Brabandt <cb@256bit.org>
date Tue, 02 Feb 2016 18:30:04 +0100
parents 17e6ff1a74f1
children df2b8af14072
comparison
equal deleted inserted replaced
7882:a3d3ab0f7b27 7883:98a96e0ca73b
15 15
16 #include "vim.h" 16 #include "vim.h"
17 17
18 #if defined(FEAT_EVAL) || defined(PROTO) 18 #if defined(FEAT_EVAL) || defined(PROTO)
19 static int json_encode_item(garray_T *gap, typval_T *val, int copyID); 19 static int json_encode_item(garray_T *gap, typval_T *val, int copyID);
20 static void json_decode_item(js_read_T *reader, typval_T *res); 20 static int json_decode_item(js_read_T *reader, typval_T *res);
21 21
22 /* 22 /*
23 * Encode "val" into a JSON format string. 23 * Encode "val" into a JSON format string.
24 */ 24 */
25 char_u * 25 char_u *
233 } 233 }
234 return OK; 234 return OK;
235 } 235 }
236 236
237 /* 237 /*
238 * When "reader" has less than NUMBUFLEN bytes available, call the fill
239 * callback to get more.
240 */
241 static void
242 fill_numbuflen(js_read_T *reader)
243 {
244 if (reader->js_fill != NULL && (int)(reader->js_end - reader->js_buf)
245 - reader->js_used < NUMBUFLEN)
246 {
247 if (reader->js_fill(reader))
248 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
249 }
250 }
251
252 /*
238 * Skip white space in "reader". 253 * Skip white space in "reader".
254 * Also tops up readahead when needed.
239 */ 255 */
240 static void 256 static void
241 json_skip_white(js_read_T *reader) 257 json_skip_white(js_read_T *reader)
242 { 258 {
243 int c; 259 int c;
244 260
245 while ((c = reader->js_buf[reader->js_used]) == ' ' 261 for (;;)
246 || c == TAB || c == NL || c == CAR) 262 {
263 c = reader->js_buf[reader->js_used];
264 if (reader->js_fill != NULL && c == NUL)
265 {
266 if (reader->js_fill(reader))
267 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
268 continue;
269 }
270 if (c != ' ' && c != TAB && c != NL && c != CAR)
271 break;
247 ++reader->js_used; 272 ++reader->js_used;
248 } 273 }
249 274 fill_numbuflen(reader);
250 /* 275 }
251 * Make sure there are at least enough characters buffered to read a number. 276
252 */ 277 static int
253 static void
254 json_fill_buffer(js_read_T *reader UNUSED)
255 {
256 /* TODO */
257 }
258
259 static void
260 json_decode_array(js_read_T *reader, typval_T *res) 278 json_decode_array(js_read_T *reader, typval_T *res)
261 { 279 {
262 char_u *p; 280 char_u *p;
263 typval_T item; 281 typval_T item;
264 listitem_T *li; 282 listitem_T *li;
265 283 int ret;
266 if (rettv_list_alloc(res) == FAIL) 284
267 goto failsilent; 285 if (res != NULL && rettv_list_alloc(res) == FAIL)
286 {
287 res->v_type = VAR_SPECIAL;
288 res->vval.v_number = VVAL_NONE;
289 return FAIL;
290 }
268 ++reader->js_used; /* consume the '[' */ 291 ++reader->js_used; /* consume the '[' */
269 292
270 while (TRUE) 293 while (TRUE)
271 { 294 {
272 json_skip_white(reader); 295 json_skip_white(reader);
273 p = reader->js_buf + reader->js_used; 296 p = reader->js_buf + reader->js_used;
274 if (*p == NUL) 297 if (*p == NUL)
275 goto fail; 298 return MAYBE;
276 if (*p == ']') 299 if (*p == ']')
277 { 300 {
278 ++reader->js_used; /* consume the ']' */ 301 ++reader->js_used; /* consume the ']' */
279 return; 302 break;
280 } 303 }
281 304
282 if (!reader->js_eof && (int)(reader->js_end - p) < NUMBUFLEN) 305 ret = json_decode_item(reader, res == NULL ? NULL : &item);
283 json_fill_buffer(reader); 306 if (ret != OK)
284 307 return ret;
285 json_decode_item(reader, &item); 308 if (res != NULL)
286 li = listitem_alloc(); 309 {
287 if (li == NULL) 310 li = listitem_alloc();
288 return; 311 if (li == NULL)
289 li->li_tv = item; 312 {
290 list_append(res->vval.v_list, li); 313 clear_tv(&item);
314 return FAIL;
315 }
316 li->li_tv = item;
317 list_append(res->vval.v_list, li);
318 }
291 319
292 json_skip_white(reader); 320 json_skip_white(reader);
293 p = reader->js_buf + reader->js_used; 321 p = reader->js_buf + reader->js_used;
294 if (*p == ',') 322 if (*p == ',')
295 ++reader->js_used; 323 ++reader->js_used;
296 else if (*p != ']') 324 else if (*p != ']')
297 goto fail; 325 {
298 } 326 if (*p == NUL)
299 fail: 327 return MAYBE;
300 EMSG(_(e_invarg)); 328 return FAIL;
301 failsilent: 329 }
302 res->v_type = VAR_SPECIAL; 330 }
303 res->vval.v_number = VVAL_NONE; 331 return OK;
304 } 332 }
305 333
306 static void 334 static int
307 json_decode_object(js_read_T *reader, typval_T *res) 335 json_decode_object(js_read_T *reader, typval_T *res)
308 { 336 {
309 char_u *p; 337 char_u *p;
310 typval_T tvkey; 338 typval_T tvkey;
311 typval_T item; 339 typval_T item;
312 dictitem_T *di; 340 dictitem_T *di;
313 char_u buf[NUMBUFLEN]; 341 char_u buf[NUMBUFLEN];
314 char_u *key; 342 char_u *key;
315 343 int ret;
316 if (rettv_dict_alloc(res) == FAIL) 344
317 goto failsilent; 345 if (res != NULL && rettv_dict_alloc(res) == FAIL)
346 {
347 res->v_type = VAR_SPECIAL;
348 res->vval.v_number = VVAL_NONE;
349 return FAIL;
350 }
318 ++reader->js_used; /* consume the '{' */ 351 ++reader->js_used; /* consume the '{' */
319 352
320 while (TRUE) 353 while (TRUE)
321 { 354 {
322 json_skip_white(reader); 355 json_skip_white(reader);
323 p = reader->js_buf + reader->js_used; 356 p = reader->js_buf + reader->js_used;
324 if (*p == NUL) 357 if (*p == NUL)
325 goto fail; 358 return MAYBE;
326 if (*p == '}') 359 if (*p == '}')
327 { 360 {
328 ++reader->js_used; /* consume the '}' */ 361 ++reader->js_used; /* consume the '}' */
329 return; 362 break;
330 } 363 }
331 364
332 if (!reader->js_eof && (int)(reader->js_end - p) < NUMBUFLEN) 365 ret = json_decode_item(reader, res == NULL ? NULL : &tvkey);
333 json_fill_buffer(reader); 366 if (ret != OK)
334 json_decode_item(reader, &tvkey); 367 return ret;
335 key = get_tv_string_buf_chk(&tvkey, buf); 368 if (res != NULL)
336 if (key == NULL || *key == NUL) 369 {
337 { 370 key = get_tv_string_buf_chk(&tvkey, buf);
338 /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */ 371 if (key == NULL || *key == NUL)
339 if (key != NULL) 372 {
340 EMSG(_(e_emptykey)); 373 clear_tv(&tvkey);
341 clear_tv(&tvkey); 374 return FAIL;
342 goto failsilent; 375 }
343 } 376 }
344 377
345 json_skip_white(reader); 378 json_skip_white(reader);
346 p = reader->js_buf + reader->js_used; 379 p = reader->js_buf + reader->js_used;
347 if (*p != ':') 380 if (*p != ':')
348 { 381 {
349 clear_tv(&tvkey); 382 if (res != NULL)
350 goto fail; 383 clear_tv(&tvkey);
384 if (*p == NUL)
385 return MAYBE;
386 return FAIL;
351 } 387 }
352 ++reader->js_used; 388 ++reader->js_used;
353 json_skip_white(reader); 389 json_skip_white(reader);
354 390
355 if (!reader->js_eof && (int)(reader->js_end - p) < NUMBUFLEN) 391 ret = json_decode_item(reader, res == NULL ? NULL : &item);
356 json_fill_buffer(reader); 392 if (ret != OK)
357 json_decode_item(reader, &item); 393 {
358 394 if (res != NULL)
359 di = dictitem_alloc(key); 395 clear_tv(&tvkey);
360 clear_tv(&tvkey); 396 return ret;
361 if (di == NULL) 397 }
362 { 398
363 clear_tv(&item); 399 if (res != NULL)
364 goto fail; 400 {
365 } 401 di = dictitem_alloc(key);
366 di->di_tv = item; 402 clear_tv(&tvkey);
367 if (dict_add(res->vval.v_dict, di) == FAIL) 403 if (di == NULL)
368 dictitem_free(di); 404 {
405 clear_tv(&item);
406 return FAIL;
407 }
408 di->di_tv = item;
409 if (dict_add(res->vval.v_dict, di) == FAIL)
410 {
411 dictitem_free(di);
412 return FAIL;
413 }
414 }
369 415
370 json_skip_white(reader); 416 json_skip_white(reader);
371 p = reader->js_buf + reader->js_used; 417 p = reader->js_buf + reader->js_used;
372 if (*p == ',') 418 if (*p == ',')
373 ++reader->js_used; 419 ++reader->js_used;
374 else if (*p != '}') 420 else if (*p != '}')
375 goto fail; 421 {
376 } 422 if (*p == NUL)
377 fail: 423 return MAYBE;
378 EMSG(_(e_invarg)); 424 return FAIL;
379 failsilent: 425 }
380 res->v_type = VAR_SPECIAL; 426 }
381 res->vval.v_number = VVAL_NONE; 427 return OK;
382 } 428 }
383 429
384 static void 430 static int
385 json_decode_string(js_read_T *reader, typval_T *res) 431 json_decode_string(js_read_T *reader, typval_T *res)
386 { 432 {
387 garray_T ga; 433 garray_T ga;
388 int len; 434 int len;
389 char_u *p = reader->js_buf + reader->js_used + 1; 435 char_u *p;
390 int c; 436 int c;
391 long nr; 437 long nr;
392 char_u buf[NUMBUFLEN]; 438 char_u buf[NUMBUFLEN];
393 439
394 ga_init2(&ga, 1, 200); 440 if (res != NULL)
395 441 ga_init2(&ga, 1, 200);
396 /* TODO: fill buffer when needed. */ 442
397 while (*p != NUL && *p != '"') 443 p = reader->js_buf + reader->js_used + 1; /* skip over " */
398 { 444 while (*p != '"')
445 {
446 if (*p == NUL || p[1] == NUL
447 #ifdef FEAT_MBYTE
448 || utf_ptr2len(p) < utf_byte2len(*p)
449 #endif
450 )
451 {
452 if (reader->js_fill == NULL)
453 break;
454 len = (int)(reader->js_end - p);
455 reader->js_used = (int)(p - reader->js_buf);
456 if (!reader->js_fill(reader))
457 break; /* didn't get more */
458 p = reader->js_buf + reader->js_used;
459 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
460 continue;
461 }
462
399 if (*p == '\\') 463 if (*p == '\\')
400 { 464 {
401 c = -1; 465 c = -1;
402 switch (p[1]) 466 switch (p[1])
403 { 467 {
468 case '\\': c = '\\'; break;
469 case '"': c = '"'; break;
404 case 'b': c = BS; break; 470 case 'b': c = BS; break;
405 case 't': c = TAB; break; 471 case 't': c = TAB; break;
406 case 'n': c = NL; break; 472 case 'n': c = NL; break;
407 case 'f': c = FF; break; 473 case 'f': c = FF; break;
408 case 'r': c = CAR; break; 474 case 'r': c = CAR; break;
409 case 'u': 475 case 'u':
476 if (reader->js_fill != NULL
477 && (int)(reader->js_end - p) < NUMBUFLEN)
478 {
479 reader->js_used = (int)(p - reader->js_buf);
480 if (reader->js_fill(reader))
481 {
482 p = reader->js_buf + reader->js_used;
483 reader->js_end = reader->js_buf
484 + STRLEN(reader->js_buf);
485 }
486 }
410 vim_str2nr(p + 2, NULL, &len, 487 vim_str2nr(p + 2, NULL, &len,
411 STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4); 488 STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4);
412 p += len + 2; 489 p += len + 2;
490 if (res != NULL)
491 {
413 #ifdef FEAT_MBYTE 492 #ifdef FEAT_MBYTE
414 buf[(*mb_char2bytes)((int)nr, buf)] = NUL; 493 buf[(*mb_char2bytes)((int)nr, buf)] = NUL;
415 ga_concat(&ga, buf); 494 ga_concat(&ga, buf);
416 #else 495 #else
417 ga_append(&ga, nr); 496 ga_append(&ga, nr);
418 #endif 497 #endif
498 }
419 break; 499 break;
420 default: c = p[1]; break; 500 default:
501 /* not a special char, skip over \ */
502 ++p;
503 continue;
421 } 504 }
422 if (c > 0) 505 if (c > 0)
423 { 506 {
424 p += 2; 507 p += 2;
425 ga_append(&ga, c); 508 if (res != NULL)
509 ga_append(&ga, c);
426 } 510 }
427 } 511 }
428 else 512 else
429 { 513 {
430 len = MB_PTR2LEN(p); 514 len = MB_PTR2LEN(p);
431 if (ga_grow(&ga, len) == OK) 515 if (res != NULL)
432 { 516 {
517 if (ga_grow(&ga, len) == FAIL)
518 {
519 ga_clear(&ga);
520 return FAIL;
521 }
433 mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len); 522 mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len);
434 ga.ga_len += len; 523 ga.ga_len += len;
435 } 524 }
436 p += len; 525 p += len;
437 } 526 }
438 if (!reader->js_eof && (int)(reader->js_end - p) < NUMBUFLEN) 527 }
439 { 528
440 reader->js_used = (int)(p - reader->js_buf);
441 json_fill_buffer(reader);
442 p = reader->js_buf + reader->js_used;
443 }
444 }
445 reader->js_used = (int)(p - reader->js_buf); 529 reader->js_used = (int)(p - reader->js_buf);
446 if (*p == '"') 530 if (*p == '"')
447 { 531 {
448 ++reader->js_used; 532 ++reader->js_used;
449 res->v_type = VAR_STRING; 533 if (res != NULL)
450 if (ga.ga_data == NULL) 534 {
451 res->vval.v_string = NULL; 535 res->v_type = VAR_STRING;
452 else 536 if (ga.ga_data == NULL)
453 res->vval.v_string = vim_strsave(ga.ga_data); 537 res->vval.v_string = NULL;
454 } 538 else
455 else 539 res->vval.v_string = vim_strsave(ga.ga_data);
456 { 540 }
457 EMSG(_(e_invarg)); 541 return OK;
542 }
543 if (res != NULL)
544 {
458 res->v_type = VAR_SPECIAL; 545 res->v_type = VAR_SPECIAL;
459 res->vval.v_number = VVAL_NONE; 546 res->vval.v_number = VVAL_NONE;
460 } 547 ga_clear(&ga);
461 ga_clear(&ga); 548 }
462 } 549 return MAYBE;
463 550 }
464 /* 551
465 * Decode one item and put it in "result". 552 /*
553 * Decode one item and put it in "res". If "res" is NULL only advance.
466 * Must already have skipped white space. 554 * Must already have skipped white space.
467 */ 555 *
468 static void 556 * Return FAIL for a decoding error.
557 * Return MAYBE for an incomplete message.
558 */
559 static int
469 json_decode_item(js_read_T *reader, typval_T *res) 560 json_decode_item(js_read_T *reader, typval_T *res)
470 { 561 {
471 char_u *p = reader->js_buf + reader->js_used; 562 char_u *p;
472 563 int len;
564
565 fill_numbuflen(reader);
566 p = reader->js_buf + reader->js_used;
473 switch (*p) 567 switch (*p)
474 { 568 {
475 case '[': /* array */ 569 case '[': /* array */
476 json_decode_array(reader, res); 570 return json_decode_array(reader, res);
477 return;
478 571
479 case '{': /* object */ 572 case '{': /* object */
480 json_decode_object(reader, res); 573 return json_decode_object(reader, res);
481 return;
482 574
483 case '"': /* string */ 575 case '"': /* string */
484 json_decode_string(reader, res); 576 return json_decode_string(reader, res);
485 return;
486 577
487 case ',': /* comma: empty item */ 578 case ',': /* comma: empty item */
488 case NUL: /* empty */ 579 case NUL: /* empty */
489 res->v_type = VAR_SPECIAL; 580 if (res != NULL)
490 res->vval.v_number = VVAL_NONE; 581 {
491 return; 582 res->v_type = VAR_SPECIAL;
583 res->vval.v_number = VVAL_NONE;
584 }
585 return OK;
492 586
493 default: 587 default:
494 if (VIM_ISDIGIT(*p) || *p == '-') 588 if (VIM_ISDIGIT(*p) || *p == '-')
495 { 589 {
496 int len;
497 char_u *sp = p; 590 char_u *sp = p;
591
498 #ifdef FEAT_FLOAT 592 #ifdef FEAT_FLOAT
499 if (*sp == '-') 593 if (*sp == '-')
594 {
500 ++sp; 595 ++sp;
596 if (*sp == NUL)
597 return MAYBE;
598 if (!VIM_ISDIGIT(*sp))
599 return FAIL;
600 }
501 sp = skipdigits(sp); 601 sp = skipdigits(sp);
502 if (*sp == '.' || *sp == 'e' || *sp == 'E') 602 if (*sp == '.' || *sp == 'e' || *sp == 'E')
503 { 603 {
504 res->v_type = VAR_FLOAT; 604 if (res == NULL)
505 len = string2float(p, &res->vval.v_float); 605 {
606 float_T f;
607
608 len = string2float(p, &f);
609 }
610 else
611 {
612 res->v_type = VAR_FLOAT;
613 len = string2float(p, &res->vval.v_float);
614 }
506 } 615 }
507 else 616 else
508 #endif 617 #endif
509 { 618 {
510 long nr; 619 long nr;
511 620
512 res->v_type = VAR_NUMBER;
513 vim_str2nr(reader->js_buf + reader->js_used, 621 vim_str2nr(reader->js_buf + reader->js_used,
514 NULL, &len, 0, /* what */ 622 NULL, &len, 0, /* what */
515 &nr, NULL, 0); 623 &nr, NULL, 0);
516 res->vval.v_number = nr; 624 if (res != NULL)
625 {
626 res->v_type = VAR_NUMBER;
627 res->vval.v_number = nr;
628 }
517 } 629 }
518 reader->js_used += len; 630 reader->js_used += len;
519 return; 631 return OK;
520 } 632 }
521 if (STRNICMP((char *)p, "false", 5) == 0) 633 if (STRNICMP((char *)p, "false", 5) == 0)
522 { 634 {
523 reader->js_used += 5; 635 reader->js_used += 5;
524 res->v_type = VAR_SPECIAL; 636 if (res != NULL)
525 res->vval.v_number = VVAL_FALSE; 637 {
526 return; 638 res->v_type = VAR_SPECIAL;
639 res->vval.v_number = VVAL_FALSE;
640 }
641 return OK;
527 } 642 }
528 if (STRNICMP((char *)p, "true", 4) == 0) 643 if (STRNICMP((char *)p, "true", 4) == 0)
529 { 644 {
530 reader->js_used += 4; 645 reader->js_used += 4;
531 res->v_type = VAR_SPECIAL; 646 if (res != NULL)
532 res->vval.v_number = VVAL_TRUE; 647 {
533 return; 648 res->v_type = VAR_SPECIAL;
649 res->vval.v_number = VVAL_TRUE;
650 }
651 return OK;
534 } 652 }
535 if (STRNICMP((char *)p, "null", 4) == 0) 653 if (STRNICMP((char *)p, "null", 4) == 0)
536 { 654 {
537 reader->js_used += 4; 655 reader->js_used += 4;
538 res->v_type = VAR_SPECIAL; 656 if (res != NULL)
539 res->vval.v_number = VVAL_NULL; 657 {
540 return; 658 res->v_type = VAR_SPECIAL;
541 } 659 res->vval.v_number = VVAL_NULL;
542 break; 660 }
543 } 661 return OK;
544 662 }
545 EMSG(_(e_invarg)); 663 /* check for truncated name */
546 res->v_type = VAR_SPECIAL; 664 len = (int)(reader->js_end - (reader->js_buf + reader->js_used));
547 res->vval.v_number = VVAL_NONE; 665 if ((len < 5 && STRNICMP((char *)p, "false", len) == 0)
666 || (len < 4 && (STRNICMP((char *)p, "true", len) == 0
667 || STRNICMP((char *)p, "null", len) == 0)))
668 return MAYBE;
669 break;
670 }
671
672 if (res != NUL)
673 {
674 res->v_type = VAR_SPECIAL;
675 res->vval.v_number = VVAL_NONE;
676 }
677 return FAIL;
548 } 678 }
549 679
550 /* 680 /*
551 * Decode the JSON from "reader" and store the result in "res". 681 * Decode the JSON from "reader" and store the result in "res".
552 * Return OK or FAIL; 682 * Return FAIL if not the whole message was consumed.
553 */ 683 */
554 int 684 int
555 json_decode(js_read_T *reader, typval_T *res) 685 json_decode_all(js_read_T *reader, typval_T *res)
556 { 686 {
687 int ret;
688
689 /* We get the end once, to avoid calling strlen() many times. */
690 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
557 json_skip_white(reader); 691 json_skip_white(reader);
558 json_decode_item(reader, res); 692 ret = json_decode_item(reader, res);
693 if (ret != OK)
694 return FAIL;
559 json_skip_white(reader); 695 json_skip_white(reader);
560 if (reader->js_buf[reader->js_used] != NUL) 696 if (reader->js_buf[reader->js_used] != NUL)
561 return FAIL; 697 return FAIL;
562 return OK; 698 return OK;
563 } 699 }
700
701 /*
702 * Decode the JSON from "reader" and store the result in "res".
703 * Return FAIL if the message has a decoding error or the message is
704 * truncated. Consumes the message anyway.
705 */
706 int
707 json_decode(js_read_T *reader, typval_T *res)
708 {
709 int ret;
710
711 /* We get the end once, to avoid calling strlen() many times. */
712 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
713 json_skip_white(reader);
714 ret = json_decode_item(reader, res);
715 json_skip_white(reader);
716
717 return ret == OK ? OK : FAIL;
718 }
719
720 /*
721 * Decode the JSON from "reader" to find the end of the message.
722 * Return FAIL if the message has a decoding error.
723 * Return MAYBE if the message is truncated, need to read more.
724 * This only works reliable if the message contains an object, array or
725 * string. A number might be trucated without knowing.
726 * Does not advance the reader.
727 */
728 int
729 json_find_end(js_read_T *reader)
730 {
731 int used_save = reader->js_used;
732 int ret;
733
734 /* We get the end once, to avoid calling strlen() many times. */
735 reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
736 json_skip_white(reader);
737 ret = json_decode_item(reader, NULL);
738 reader->js_used = used_save;
739 return ret;
740 }
564 #endif 741 #endif