463{
464
465 char yml_buf[] = ""
466 "foo: 1" "\n"
467 "bar: [2, 3]" "\n"
468 "john: doe" "\n"
469 "";
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
509
510
511
516
517
521
522
523
524
525
526
527
528
529
530
531
532
533
534 CHECK(tree[
"foo"].is_keyval());
535 CHECK(tree[
"foo"].val() ==
"1");
536 CHECK(tree[
"foo"].key() ==
"foo");
537 CHECK(tree[
"bar"].is_seq());
538 CHECK(tree[
"bar"].has_key());
539 CHECK(tree[
"bar"].key() ==
"bar");
540
541 CHECK(tree[
"bar"][0].val() ==
"2");
542 CHECK(tree[
"bar"][1].val() ==
"3");
543 CHECK(tree[
"john"].val() ==
"doe");
544
545
546
547 CHECK(tree[0].
id() == tree[
"foo"].
id());
548 CHECK(tree[1].
id() == tree[
"bar"].
id());
549 CHECK(tree[2].
id() == tree[
"john"].
id());
550
551 CHECK(tree[0].
id() == tree[
"foo"].
id());
552 CHECK(tree[1].
id() == tree[
"bar"].
id());
553 CHECK(tree[2].
id() == tree[
"john"].
id());
554
555 CHECK(bar[0].val() ==
"2");
556 CHECK(bar[1].val() ==
"3");
557
558
559
560
561 CHECK(tree[
"foo"].key() ==
"foo");
562 CHECK(tree[
"bar"].key() ==
"bar");
563 CHECK(tree[
"john"].key() ==
"john");
565
566
567
568 CHECK(root[
"foo"].
id() == root[0].
id());
569 CHECK(root[
"bar"].
id() == root[1].
id());
570 CHECK(root[
"john"].
id() == root[2].
id());
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601 {
612
618 }
619
620
621
622
623 {
625
626 {
629 CHECK(child.key() == expected_keys[count++]);
630 }
631
632 {
635 CHECK(child.key() == expected_keys[count++]);
636 }
637
638 {
641 CHECK(tree.
key(child_id) == expected_keys[count++]);
642 }
643
644
645
646
647 {
650 CHECK(tree.
key(child_id) == expected_keys[count++]);
651 }
652 }
653
654
655
656
657
658
659
660
661 {
664
667
668
671
672
674
675
676
678
679 }
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721 {
722
723
724 {
725 int foo = 0, bar0 = 0, bar1 = 0;
726 root[
"foo"].
load(&foo);
727 root[
"bar"][0].
load(&bar0);
728 root[
"bar"][1].
load(&bar1);
732
733 }
734
735 {
736 int foo = 0, bar0 = 0, bar1 = 0;
737 CHECK(root[
"foo"].deserialize(&foo));
738 CHECK(root[
"bar"][0].deserialize(&bar0));
739 CHECK(root[
"bar"][1].deserialize(&bar1));
743
744 }
745
746
747 {
748 std::string john_str, bar_str;
749 root[
"john"].
load(&john_str);
751 CHECK(john_str ==
"doe");
752 CHECK(bar_str ==
"bar");
753 std::vector<int> bar_actual, bar_expected{{2, 3}};
754 root[
"bar"].
load(&bar_actual);
755 CHECK(bar_actual == bar_expected);
756 }
757 }
758
759
760
761
762
763
764
765
766
768
769
770
771
772
773 wroot[
"foo"].
set_val(
"says you");
777
778
779
780 CHECK(root[
"foo"].val() ==
"says you");
781 CHECK(root[
"bar"][0].val() ==
"-2");
782 CHECK(root[
"bar"][1].val() ==
"-3");
783 CHECK(root[
"john"].val() ==
"ron");
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
804 CHECK(root[
"foo"].val() ==
"says who");
805 CHECK(root[
"bar"][0].val() ==
"20");
806 CHECK(root[
"bar"][1].val() ==
"30");
807 CHECK(root[
"john"].val() ==
"deere");
809
810 {
811 std::string ok("in_scope");
812
814 }
815 CHECK(root[
"john"].val() ==
"in_scope");
816
818
819
821 CHECK(tree.
arena() ==
"says who2030deerein_scope2.42.400000");
822
823
824
825
826
827
829 wroot[
"newkeyval"].
set_val(
"shiny and new");
834 CHECK(root[
"newkeyval"].key() ==
"newkeyval");
835 CHECK(root[
"newkeyval"].val() ==
"shiny and new");
836 CHECK(root[
"newkeyval (serialized)"].key() ==
"newkeyval (serialized)");
837 CHECK(root[
"newkeyval (serialized)"].val() ==
"shiny and new (serialized)");
842
843 CHECK(root[
"bar"].num_children() == 2);
844 wroot[
"bar"][2].
set_val(
"oh so nice");
846 CHECK(root[
"bar"].num_children() == 4);
847 CHECK(root[
"bar"][2].val() ==
"oh so nice");
848 CHECK(root[
"bar"][3].val() ==
"oh so nice (serialized)");
849
856 CHECK(root[
"newseq"].num_children() == 0);
857 CHECK(root[
"newseq"].is_seq());
858 CHECK(root[
"newseq (serialized)"].num_children() == 0);
859 CHECK(root[
"newseq (serialized)"].is_seq());
860
867 CHECK(root[
"newmap"].num_children() == 0);
868 CHECK(root[
"newmap"].is_map());
869 CHECK(root[
"newmap (serialized)"].num_children() == 0);
870 CHECK(root[
"newmap (serialized)"].is_map());
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
903 nothing = wroot["I am nothing"];
908
916
917
920 CHECK(root[
"I am something"].val() ==
"indeed");
923
925
926
930
931
934
935
936
937
938
939
940
941
942
943
944
945
946
947
950 {
951 CHECK(wbar[0].readable() && wbar[0].val() ==
"20");
952 CHECK( ! wbar[100].readable());
953 CHECK( ! wbar[100].readable() || wbar[100].val() ==
"100");
954
955 CHECK( ! wbar[0].is_seed() && wbar[0].val() ==
"20");
956 CHECK(wbar[100].is_seed() || wbar[100].val() ==
"100");
957 }
958
959
960
961
962
963
964
965
966
967
968
969
970
971 {
972
973
975
977
979
981
983
985 return seed_node.at("is").at("an").at("invalid").at("operation");
986
987
988 }));
989
990
992 return seed_node["is"]["an"]["invalid"]["operation"];
993
994
995 }));
996 }
997
998
999
1000
1001
1003 "foo: says who" "\n"
1004 "bar: [20,30,oh so nice,oh so nice (serialized)]" "\n"
1005 "john: in_scope" "\n"
1006 "float: 2.4" "\n"
1007 "digits: 2.400000" "\n"
1008 "newkeyval: shiny and new" "\n"
1009 "newkeyval (serialized): shiny and new (serialized)" "\n"
1010 "newseq: []" "\n"
1011 "newseq (serialized): []" "\n"
1012 "newmap: {}" "\n"
1013 "newmap (serialized): {}" "\n"
1014 "I am something: indeed" "\n"
1015 "";
1016
1017
1019
1020
1021
1022
1023 std::stringstream ss;
1024 ss << tree;
1025 std::string stream_result = ss.str();
1026
1028
1029 char buf[1024];
1031
1032 CHECK(buf_result == expected_result);
1033 CHECK(str_result == expected_result);
1034 CHECK(stream_result == expected_result);
1035
1036
1037
1038
1039
1040
1041
1044
1045
1046
1047
1048
1050 CHECK(tree[
"bar"][0].val() ==
"21");
1052 CHECK(tree[
"bar"][0].val() ==
"22");
1053
1054
1055
1056
1057
1058 constnoderef = noderef;
1059
1060
1061
1063
1064 noderef = tree["bar"][0];
1065 constnoderef = consttree["bar"][0];
1066
1067
1068
1069 CHECK(constnoderef == noderef);
1070 CHECK(!(constnoderef != noderef));
1071
1072
1073
1074
1075
1076
1079
1081
1085 CHECK(parser.location_contents(loc).begins_with(
"30"));
1088
1089
1090
1091
1092
1093
1095 "#" "\n"
1096 "# UTF8/16/32 can be placed directly in any scalar:" "\n"
1097 "#" "\n"
1098 "en: Planet (Gas)" "\n"
1099 "fr: Planète (Gazeuse)" "\n"
1100 "ru: Планета (Газ)" "\n"
1101 "ja: 惑星(ガス)" "\n"
1102 "zh: 行星(气体)" "\n"
1103 "#" "\n"
1104 "# UTF8 decoding only happens in double-quoted strings," "\n"
1105 "# as per the YAML standard" "\n"
1106 "#" "\n"
1107 "decode this: \"\\u263A c\\x61f\\xE9\"" "\n"
1108 "and this as well: \"\\u2705 \\U0001D11E\"" "\n"
1109 "not decoded: '\\u263A \\xE2\\x98\\xBA'" "\n"
1110 "neither this: '\\u2705 \\U0001D11E'" "\n");
1111
1112 CHECK(langs[
"en"].val() ==
"Planet (Gas)");
1113 CHECK(langs[
"fr"].val() ==
"Planète (Gazeuse)");
1114 CHECK(langs[
"ru"].val() ==
"Планета (Газ)");
1115 CHECK(langs[
"ja"].val() ==
"惑星(ガス)");
1116 CHECK(langs[
"zh"].val() ==
"行星(气体)");
1117
1118
1119
1120 CHECK(langs[
"decode this"].val() ==
"☺ café");
1121 CHECK(langs[
"and this as well"].val() ==
"✅ 𝄞");
1122 CHECK(langs[
"not decoded"].val() ==
"\\u263A \\xE2\\x98\\xBA");
1123 CHECK(langs[
"neither this"].val() ==
"\\u2705 \\U0001D11E");
1124}
ConstNodeRef parent() const RYML_NOEXCEPT
Forward to Tree::parent().
ConstNodeRef first_sibling() const RYML_NOEXCEPT
Forward to Tree::first_sibling().
id_type id() const noexcept
ConstNodeRef first_child() const RYML_NOEXCEPT
Forward to Tree::first_child().
ConstNodeRef last_child() const RYML_NOEXCEPT
Forward to Tree::last_child().
bool invalid() const noexcept
const_children_view children() const RYML_NOEXCEPT
get an iterable view over children
ConstNodeRef last_sibling() const RYML_NOEXCEPT
Forward to Tree::last_sibling().
Tree const * tree() const noexcept
ConstNodeRef next_sibling() const RYML_NOEXCEPT
Forward to Tree::next_sibling().
ConstNodeRef prev_sibling() const RYML_NOEXCEPT
Forward to Tree::prev_sibling().
bool readable() const noexcept
because a ConstNodeRef cannot be used to write to the tree, readable() has the same meaning as !...
void set_serialized(T const &v)
serialize a variable to this node.
void set_val(csubstr val)
void set_key_serialized(T const &k)
serialize a variable, then assign the result to the node's key
bool invalid() const noexcept
true if the object is not referring to any existing or seed node.
bool readable() const noexcept
true if the object is not invalid and not in seed state.
bool is_seed() const noexcept
true if the object is not invalid and in seed state.
csubstr const & key(id_type node) const
id_type first_child(id_type node) const
id_type root_id() const
Get the id of the root node. The tree must not be empty. The tree can be empty only when constructed ...
NodeRef rootref()
Get the root as a NodeRef . Note that a non-const Tree implicitly converts to NodeRef.
bool is_map(id_type node) const
bool in_arena(csubstr s) const
return true if the given substring is part of the tree's string arena
id_type next_sibling(id_type node) const
Callbacks const & callbacks() const
bool is_seq(id_type node) const
id_type find_child(id_type node, csubstr const &key) const
find child by name, or NONE if no child is found with this key like Tree::child(),...
id_type first_sibling(id_type node) const
csubstr arena() const
get the current arena
@ FTOA_FLOAT
print the real number in floating point format (like f)
void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *tree, id_type node_id)
(1) parse YAML into an existing tree node. The filename will be used in any error messages arising du...
ParseEngine< EventHandlerTree > Parser
This is the main ryml parser, where the parser events are handled to create a ryml tree (see Event Ha...
bool check_assertion_occurs(Fn &&fn)
checking that an assertion occurs while calling fn.
bool check_error_occurs(Fn &&fn)
checking that an error occurs while calling fn
ryml::Callbacks callbacks()
a helper to create the Callbacks object for the custom error handler
basic_substring< const char > csubstr
an immutable string view
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
Shows how to create a scoped error handler.
bool empty() const noexcept
The event handler to create a ryml Tree.
holds a source or yaml file position, for example when an error is detected; See also location_format...
Options to give to the ParseEngine to control its behavior.
bool is_val() const RYML_NOEXCEPT
Forward to Tree::is_val().
void load_key(T *k, bool check_readable=true) const
(1) deserialize the node's key (necessarily a scalar) to the given variable, forwarding to the user-o...
bool has_child(ConstImpl const &n) const RYML_NOEXCEPT
Forward to Tree::has_child().
bool is_map() const RYML_NOEXCEPT
Forward to Tree::is_map().
id_type num_siblings() const RYML_NOEXCEPT
O(num_children).
bool has_key() const RYML_NOEXCEPT
Forward to Tree::has_key().
csubstr key() const RYML_NOEXCEPT
Forward to Tree::key().
csubstr val() const RYML_NOEXCEPT
Forward to Tree::val().
id_type num_children() const RYML_NOEXCEPT
O(num_children).
Location location(Parser const &parser) const
bool is_seq() const RYML_NOEXCEPT
Forward to Tree::is_seq().
bool has_val() const RYML_NOEXCEPT
Forward to Tree::has_val().