Mercurial > vim
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 |