Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added omap support to yaml.load

  • Loading branch information...
commit deff58bf3152798f5dece14ee690b38b6a45a144 1 parent cb36849
Jeremy Stephens viking authored

Showing 3 changed files with 153 additions and 72 deletions. Show diff stats Hide diff stats

  1. +134 67 src/yaml.c
  2. +6 0 tests/as_yaml_test.R
  3. +13 5 tests/yaml_load_test.R
201 src/yaml.c
@@ -386,9 +386,10 @@ R_merge_list( map, list, use_named )
386 386 }
387 387
388 388 static SEXP
389   -default_null_handler(type, data, R_cmd)
  389 +default_null_handler(type, kind, data, R_cmd)
390 390 const char *type;
391   - const char *data;
  391 + enum syck_kind_tag kind;
  392 + void *data;
392 393 SEXP R_cmd;
393 394 {
394 395 return R_NilValue;
@@ -396,18 +397,20 @@ default_null_handler(type, data, R_cmd)
396 397
397 398 /*
398 399 static SEXP
399   -default_binary_handler(type, data, R_cmd)
  400 +default_binary_handler(type, kind, data, R_cmd)
400 401 const char *type;
401   - const char *data;
  402 + enum syck_kind_tag kind;
  403 + void *data;
402 404 SEXP R_cmd;
403 405 {
404 406 }
405 407 */
406 408
407 409 static SEXP
408   -default_bool_yes_handler(type, data, R_cmd)
  410 +default_bool_yes_handler(type, kind, data, R_cmd)
409 411 const char *type;
410   - const char *data;
  412 + enum syck_kind_tag kind;
  413 + void *data;
411 414 SEXP R_cmd;
412 415 {
413 416 SEXP obj = NEW_LOGICAL(1);
@@ -416,9 +419,10 @@ default_bool_yes_handler(type, data, R_cmd)
416 419 }
417 420
418 421 static SEXP
419   -default_bool_no_handler(type, data, R_cmd)
  422 +default_bool_no_handler(type, kind, data, R_cmd)
420 423 const char *type;
421   - const char *data;
  424 + enum syck_kind_tag kind;
  425 + void *data;
422 426 SEXP R_cmd;
423 427 {
424 428 SEXP obj = NEW_LOGICAL(1);
@@ -427,52 +431,57 @@ default_bool_no_handler(type, data, R_cmd)
427 431 }
428 432
429 433 static SEXP
430   -default_int_hex_handler(type, data, R_cmd)
  434 +default_int_hex_handler(type, kind, data, R_cmd)
431 435 const char *type;
432   - const char *data;
  436 + enum syck_kind_tag kind;
  437 + void *data;
433 438 SEXP R_cmd;
434 439 {
435 440 SEXP obj = NEW_INTEGER(1);
436   - INTEGER(obj)[0] = (int)strtol(data, NULL, 16);
  441 + INTEGER(obj)[0] = (int)strtol((char *)data, NULL, 16);
437 442 return obj;
438 443 }
439 444
440 445 static SEXP
441   -default_int_oct_handler(type, data, R_cmd)
  446 +default_int_oct_handler(type, kind, data, R_cmd)
442 447 const char *type;
443   - const char *data;
  448 + enum syck_kind_tag kind;
  449 + void *data;
444 450 SEXP R_cmd;
445 451 {
446 452 SEXP obj = NEW_INTEGER(1);
447   - INTEGER(obj)[0] = (int)strtol(data, NULL, 8);
  453 + INTEGER(obj)[0] = (int)strtol((char *)data, NULL, 8);
448 454 return obj;
449 455 }
450 456
451 457 /*
452 458 static SEXP
453   -default_int_base60_handler(type, data, R_cmd)
  459 +default_int_base60_handler(type, kind, data, R_cmd)
454 460 const char *type;
455   - const char *data;
  461 + enum syck_kind_tag kind;
  462 + void *data;
456 463 SEXP R_cmd;
457 464 {
458 465 }
459 466 */
460 467
461 468 static SEXP
462   -default_int_handler(type, data, R_cmd)
  469 +default_int_handler(type, kind, data, R_cmd)
463 470 const char *type;
464   - const char *data;
  471 + enum syck_kind_tag kind;
  472 + void *data;
465 473 SEXP R_cmd;
466 474 {
467 475 SEXP obj = NEW_INTEGER(1);
468   - INTEGER(obj)[0] = (int)strtol(data, NULL, 10);
  476 + INTEGER(obj)[0] = (int)strtol((char *)data, NULL, 10);
469 477 return obj;
470 478 }
471 479
472 480 static SEXP
473   -default_float_nan_handler(type, data, R_cmd)
  481 +default_float_nan_handler(type, kind, data, R_cmd)
474 482 const char *type;
475   - const char *data;
  483 + enum syck_kind_tag kind;
  484 + void *data;
476 485 SEXP R_cmd;
477 486 {
478 487 SEXP obj = NEW_NUMERIC(1);
@@ -481,9 +490,10 @@ default_float_nan_handler(type, data, R_cmd)
481 490 }
482 491
483 492 static SEXP
484   -default_float_inf_handler(type, data, R_cmd)
  493 +default_float_inf_handler(type, kind, data, R_cmd)
485 494 const char *type;
486   - const char *data;
  495 + enum syck_kind_tag kind;
  496 + void *data;
487 497 SEXP R_cmd;
488 498 {
489 499 SEXP obj = NEW_NUMERIC(1);
@@ -492,9 +502,10 @@ default_float_inf_handler(type, data, R_cmd)
492 502 }
493 503
494 504 static SEXP
495   -default_float_neginf_handler(type, data, R_cmd)
  505 +default_float_neginf_handler(type, kind, data, R_cmd)
496 506 const char *type;
497   - const char *data;
  507 + enum syck_kind_tag kind;
  508 + void *data;
498 509 SEXP R_cmd;
499 510 {
500 511 SEXP obj = NEW_NUMERIC(1);
@@ -503,13 +514,14 @@ default_float_neginf_handler(type, data, R_cmd)
503 514 }
504 515
505 516 static SEXP
506   -default_float_handler(type, data, R_cmd)
  517 +default_float_handler(type, kind, data, R_cmd)
507 518 const char *type;
508   - const char *data;
  519 + enum syck_kind_tag kind;
  520 + void *data;
509 521 SEXP R_cmd;
510 522 {
511 523 double f;
512   - f = strtod( data, NULL );
  524 + f = strtod( (char *)data, NULL );
513 525
514 526 SEXP obj;
515 527 obj = NEW_NUMERIC(1);
@@ -519,9 +531,10 @@ default_float_handler(type, data, R_cmd)
519 531
520 532 /*
521 533 static SEXP
522   -default_timestamp_iso8601_handler(type, data, R_cmd)
  534 +default_timestamp_iso8601_handler(type, kind, data, R_cmd)
523 535 const char *type;
524   - const char *data;
  536 + enum syck_kind_tag kind;
  537 + void *data;
525 538 SEXP R_cmd;
526 539 {
527 540 }
@@ -529,9 +542,10 @@ default_timestamp_iso8601_handler(type, data, R_cmd)
529 542
530 543 /*
531 544 static SEXP
532   -default_timestamp_spaced_handler(type, data, R_cmd)
  545 +default_timestamp_spaced_handler(type, kind, data, R_cmd)
533 546 const char *type;
534   - const char *data;
  547 + enum syck_kind_tag kind;
  548 + void *data;
535 549 SEXP R_cmd;
536 550 {
537 551 }
@@ -539,9 +553,10 @@ default_timestamp_spaced_handler(type, data, R_cmd)
539 553
540 554 /*
541 555 static SEXP
542   -default_timestamp_ymd_handler(type, data, R_cmd)
  556 +default_timestamp_ymd_handler(type, kind, data, R_cmd)
543 557 const char *type;
544   - const char *data;
  558 + enum syck_kind_tag kind;
  559 + void *data;
545 560 SEXP R_cmd;
546 561 {
547 562 }
@@ -549,18 +564,20 @@ default_timestamp_ymd_handler(type, data, R_cmd)
549 564
550 565 /*
551 566 static SEXP
552   -default_timestamp_handler(type, data, R_cmd)
  567 +default_timestamp_handler(type, kind, data, R_cmd)
553 568 const char *type;
554   - const char *data;
  569 + enum syck_kind_tag kind;
  570 + void *data;
555 571 SEXP R_cmd;
556 572 {
557 573 }
558 574 */
559 575
560 576 static SEXP
561   -default_merge_handler(type, data, R_cmd)
  577 +default_merge_handler(type, kind, data, R_cmd)
562 578 const char *type;
563   - const char *data;
  579 + enum syck_kind_tag kind;
  580 + void *data;
564 581 SEXP R_cmd;
565 582 {
566 583 SEXP obj;
@@ -573,9 +590,10 @@ default_merge_handler(type, data, R_cmd)
573 590 }
574 591
575 592 static SEXP
576   -default_default_handler(type, data, R_cmd)
  593 +default_default_handler(type, kind, data, R_cmd)
577 594 const char *type;
578   - const char *data;
  595 + enum syck_kind_tag kind;
  596 + void *data;
579 597 SEXP R_cmd;
580 598 {
581 599 SEXP obj;
@@ -588,29 +606,31 @@ default_default_handler(type, data, R_cmd)
588 606 }
589 607
590 608 static SEXP
591   -default_str_handler(type, data, R_cmd)
  609 +default_str_handler(type, kind, data, R_cmd)
592 610 const char *type;
593   - const char *data;
  611 + enum syck_kind_tag kind;
  612 + void *data;
594 613 SEXP R_cmd;
595 614 {
596 615 SEXP obj;
597 616 PROTECT(obj = NEW_STRING(1));
598   - SET_STRING_ELT(obj, 0, mkChar(data));
  617 + SET_STRING_ELT(obj, 0, mkChar((char *)data));
599 618 UNPROTECT(1);
600 619
601 620 return obj;
602 621 }
603 622
604 623 static SEXP
605   -default_anchor_bad_handler(type, data, R_cmd)
  624 +default_anchor_bad_handler(type, kind, data, R_cmd)
606 625 const char *type;
607   - const char *data;
  626 + enum syck_kind_tag kind;
  627 + void *data;
608 628 SEXP R_cmd;
609 629 {
610 630 SEXP obj;
611 631 PROTECT(obj = NEW_STRING(1));
612 632 SET_STRING_ELT(obj, 0, mkChar("_yaml.bad-anchor_"));
613   - R_set_str_attrib(obj, install("name"), data);
  633 + R_set_str_attrib(obj, install("name"), (char *)data);
614 634 R_set_class(obj, "_yaml.bad-anchor_");
615 635 UNPROTECT(1);
616 636
@@ -618,19 +638,56 @@ default_anchor_bad_handler(type, data, R_cmd)
618 638 }
619 639
620 640 static SEXP
621   -default_omap_handler(type, data, R_cmd)
  641 +default_omap_handler(type, kind, _data, R_cmd)
622 642 const char *type;
623   - const char *data;
  643 + enum syck_kind_tag kind;
  644 + void *_data;
624 645 SEXP R_cmd;
625 646 {
626   - return data;
  647 + SEXP elt, data, names, retval;
  648 + int i, j, data_len, elt_len, idx, total_len = 0;
  649 +
  650 + data = (SEXP)_data;
  651 + if (TYPEOF(data) != VECSXP) {
  652 + error(_("omap must be a sequence"));
  653 + }
  654 +
  655 + // get size of final list and check for validity
  656 + // FIXME: this is inefficient, since we've already sort of done this
  657 + // in the parsing loop
  658 + data_len = length(data);
  659 + for (i = 0; i < data_len; i++) {
  660 + elt = VECTOR_ELT(data, i);
  661 + if (TYPEOF(elt) != VECSXP) {
  662 + error(_("omap must be a sequence of maps"));
  663 + }
  664 + total_len += length(elt);
  665 + }
  666 +
  667 + // construct the list!
  668 + retval = allocVector(VECSXP, total_len);
  669 + PROTECT(retval);
  670 + names = allocVector(STRSXP, total_len);
  671 + SET_NAMES(retval, names);
  672 + for (i = 0, idx = 0; i < data_len; i++) {
  673 + elt = VECTOR_ELT(data, i);
  674 + elt_len = length(elt);
  675 + for (j = 0; j < elt_len; j++) {
  676 + SET_VECTOR_ELT(retval, idx, VECTOR_ELT(elt, j));
  677 + SET_STRING_ELT(names, idx, STRING_ELT(GET_NAMES(elt), j));
  678 + idx++;
  679 + }
  680 + }
  681 + UNPROTECT(1);
  682 + return(retval);
627 683 }
628 684
629 685 /*
630 686 static SEXP
631   -default_unknown_handler(type, data, R_cmd)
  687 +default_unknown_handler(type, kind, data, R_cmd)
632 688 const char *type;
633   - const char *data;
  689 + enum syck_kind_tag kind;
  690 + void *data;
634 691 SEXP R_cmd;
635 692 {
636 693 }
@@ -658,30 +715,40 @@ run_R_handler_function(func, arg, type)
658 715 }
659 716
660 717 static SEXP
661   -run_user_handler(type, data, R_cmd)
  718 +run_user_handler(type, kind, data, R_cmd)
662 719 const char *type;
663   - const char *data;
  720 + enum syck_kind_tag kind;
  721 + void *data;
664 722 SEXP R_cmd;
665 723 {
666 724 SEXP tmp_obj, obj;
667 725
668   - /* create a string to pass to the handler */
669   - tmp_obj = NEW_STRING(1);
670   - PROTECT(tmp_obj);
671   - SET_STRING_ELT(tmp_obj, 0, mkChar(data));
  726 + switch(kind) {
  727 + case syck_str_kind:
  728 + /* create a string to pass to the handler */
  729 + tmp_obj = NEW_STRING(1);
  730 + PROTECT(tmp_obj);
  731 + SET_STRING_ELT(tmp_obj, 0, mkChar(data));
672 732
673   - /* call R function */
674   - obj = run_R_handler_function(R_cmd, tmp_obj, type);
675   - UNPROTECT(1);
  733 + /* call R function */
  734 + obj = run_R_handler_function(R_cmd, tmp_obj, type);
  735 + UNPROTECT(1);
  736 + break;
  737 +
  738 + case syck_seq_kind:
  739 + obj = run_R_handler_function(R_cmd, data, type);
  740 + break;
  741 + }
676 742
677 743 return obj;
678 744 }
679 745
680 746 static SEXP
681   -find_and_run_handler(p, type, data)
  747 +find_and_run_handler(p, type, kind, data)
682 748 SyckParser *p;
683 749 const char *type;
684   - const char *data;
  750 + enum syck_kind_tag kind;
  751 + void *data;
685 752 {
686 753 handler *hndlr;
687 754 st_table *hash = ((parser_xtra *)p->bonus)->handlers;
@@ -689,7 +756,7 @@ find_and_run_handler(p, type, data)
689 756 if (!st_lookup(hash, (st_data_t)type, (st_data_t *)&hndlr))
690 757 st_lookup(hash, (st_data_t)"unknown", (st_data_t *)&hndlr);
691 758
692   - return hndlr->func(type, data, hndlr->R_cmd);
  759 + return hndlr->func(type, kind, data, hndlr->R_cmd);
693 760 }
694 761
695 762 /* originally from Ruby's syck extension; modified for R */
@@ -724,13 +791,13 @@ yaml_handler( p, n, ref )
724 791 data_ptr = n->data.str->ptr;
725 792
726 793 if ( type_id == NULL ) {
727   - obj = find_and_run_handler(p, "unknown", data_ptr);
  794 + obj = find_and_run_handler(p, "unknown", n->kind, data_ptr);
728 795 }
729 796 else {
730 797 if ( strncmp( type_id, "int", 3 ) == 0 || strncmp( type_id, "float", 5 ) == 0 )
731 798 syck_str_blow_away_commas( n );
732 799
733   - obj = find_and_run_handler(p, type_id, data_ptr);
  800 + obj = find_and_run_handler(p, type_id, n->kind, data_ptr);
734 801 }
735 802
736 803 PRESERVE(obj);
@@ -738,7 +805,7 @@ yaml_handler( p, n, ref )
738 805
739 806 case syck_seq_kind:
740 807 /* if there's a user handler for this type, we should always construct a list */
741   - custom = st_lookup(xtra->handlers, (st_data_t)(type_id == NULL ? "seq" : type_id), (st_data_t *)&hndlr);
  808 + custom = st_is_member(xtra->handlers, (st_data_t)(type_id == NULL ? "seq" : type_id));
742 809
743 810 list = Calloc(n->data.list->idx, SEXP);
744 811 type = -1;
@@ -814,7 +881,7 @@ yaml_handler( p, n, ref )
814 881 Free(list);
815 882
816 883 if (custom) {
817   - tmp_obj = hndlr->func(type_id == NULL ? "seq" : type_id, obj, hndlr->R_cmd);
  884 + tmp_obj = find_and_run_handler(p, type_id == NULL ? "seq" : type_id, n->kind, obj);
818 885 UNPROTECT_PTR(obj);
819 886 obj = tmp_obj;
820 887 }
6 tests/as_yaml_test.R
@@ -62,4 +62,10 @@ function() {
62 62 assert_equal(expected, as.yaml(x, omap=TRUE))
63 63 }
64 64
  65 +test_should_load_omap <-
  66 +function() {
  67 + x <- yaml.load(as.yaml(list(a=1:2, b=3:4), omap=TRUE))
  68 + print(x)
  69 +}
  70 +
65 71 source("test_runner.r")
18 tests/yaml_load_test.R
@@ -315,11 +315,19 @@ test_should_read_from_connection <- function() {
315 315 }
316 316
317 317 test_should_load_omap <- function() {
318   - x <- yaml.load("--- !omap\n- foo: [1,2,3]\n- bar: [1,2,3]")
319   - expected <- list(foo=1:3, bar=1:3)
320   - print(expected)
321   - print(x)
322   - assert_equal(expected, x)
  318 + x <- yaml.load("--- !omap\n- foo:\n - 1\n - 2\n- bar:\n - 3\n - 4")
  319 + assert_equal(2, length(x))
  320 + assert_equal(c("foo", "bar"), names(x))
  321 + assert_equal(1:2, x$foo)
  322 + assert_equal(3:4, x$bar)
  323 +}
  324 +
  325 +test_should_error_when_omap_is_invalid <- function() {
  326 + x <- try(yaml.load("--- !omap\nhey!"))
  327 + assert(inherits(x, "try-error"))
  328 +
  329 + x <- try(yaml.load("--- !omap\n- sup?"))
  330 + assert(inherits(x, "try-error"))
323 331 }
324 332
325 333 source("test_runner.r")

0 comments on commit deff58b

Please sign in to comment.
Something went wrong with that request. Please try again.