465{
466
467 char yml_buf[] = ""
468 "foo: 1" "\n"
469 "bar: [2, 3]" "\n"
470 "john: doe" "\n"
471 "";
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
505
506
511
512
513
518
519
523
524
525
526
527
528
529
530
531
532
533
534
535
536 CHECK(tree[
"foo"].is_keyval());
537 CHECK(tree[
"foo"].val() ==
"1");
538 CHECK(tree[
"foo"].key() ==
"foo");
539 CHECK(tree[
"bar"].is_seq());
540 CHECK(tree[
"bar"].has_key());
541 CHECK(tree[
"bar"].key() ==
"bar");
542
543 CHECK(tree[
"bar"][0].val() ==
"2");
544 CHECK(tree[
"bar"][1].val() ==
"3");
545 CHECK(tree[
"john"].val() ==
"doe");
546
547
548
549 CHECK(tree[0].
id() == tree[
"foo"].
id());
550 CHECK(tree[1].
id() == tree[
"bar"].
id());
551 CHECK(tree[2].
id() == tree[
"john"].
id());
552
553 CHECK(tree[0].
id() == tree[
"foo"].
id());
554 CHECK(tree[1].
id() == tree[
"bar"].
id());
555 CHECK(tree[2].
id() == tree[
"john"].
id());
556
557 CHECK(bar[0].val() ==
"2");
558 CHECK(bar[1].val() ==
"3");
559
560
561
562
563 CHECK(tree[
"foo"].key() ==
"foo");
564 CHECK(tree[
"bar"].key() ==
"bar");
565 CHECK(tree[
"john"].key() ==
"john");
567
568
569
570 CHECK(root[
"foo"].
id() == root[0].
id());
571 CHECK(root[
"bar"].
id() == root[1].
id());
572 CHECK(root[
"john"].
id() == root[2].
id());
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
602
603 {
614
620 }
621
622
623
624
625 {
627
628 {
631 CHECK(child.key() == expected_keys[count++]);
632 }
633
634 {
637 CHECK(child.key() == expected_keys[count++]);
638 }
639
640 {
643 CHECK(tree.
key(child_id) == expected_keys[count++]);
644 }
645
646
647
648
649 {
652 CHECK(tree.
key(child_id) == expected_keys[count++]);
653 }
654 }
655
656
657
658
659
660
661
662
663 {
666
669
670
673
674
676
677
678
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
726 {
727 int foo = 0, bar0 = 0, bar1 = 0;
728 root[
"foo"].
load(&foo);
729 root[
"bar"][0].
load(&bar0);
730 root[
"bar"][1].
load(&bar1);
734
735 }
736
737 {
738 int foo = 0, bar0 = 0, bar1 = 0;
739 CHECK(root[
"foo"].deserialize(&foo));
740 CHECK(root[
"bar"][0].deserialize(&bar0));
741 CHECK(root[
"bar"][1].deserialize(&bar1));
745
746 }
747
748
749 {
750 std::string john_str, bar_str;
751 root[
"john"].
load(&john_str);
753 CHECK(john_str ==
"doe");
754 CHECK(bar_str ==
"bar");
755 std::vector<int> bar_actual, bar_expected{{2, 3}};
756 root[
"bar"].
load(&bar_actual);
757 CHECK(bar_actual == bar_expected);
758 }
759 }
760
761
762
763
764
765
766
767
768
770
771
772
773
774
775 wroot[
"foo"].
set_val(
"says you");
779
780
781
782 CHECK(root[
"foo"].val() ==
"says you");
783 CHECK(root[
"bar"][0].val() ==
"-2");
784 CHECK(root[
"bar"][1].val() ==
"-3");
785 CHECK(root[
"john"].val() ==
"ron");
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
806 CHECK(root[
"foo"].val() ==
"says who");
807 CHECK(root[
"bar"][0].val() ==
"20");
808 CHECK(root[
"bar"][1].val() ==
"30");
809 CHECK(root[
"john"].val() ==
"deere");
811
812 {
813 std::string ok("in_scope");
814
816 }
817 CHECK(root[
"john"].val() ==
"in_scope");
818
820
821
823 CHECK(tree.
arena() ==
"says who2030deerein_scope2.42.400000");
824
825
826
827
828
829
831 wroot[
"newkeyval"].
set_val(
"shiny and new");
836 CHECK(root[
"newkeyval"].key() ==
"newkeyval");
837 CHECK(root[
"newkeyval"].val() ==
"shiny and new");
838 CHECK(root[
"newkeyval (serialized)"].key() ==
"newkeyval (serialized)");
839 CHECK(root[
"newkeyval (serialized)"].val() ==
"shiny and new (serialized)");
844
845 CHECK(root[
"bar"].num_children() == 2);
846 wroot[
"bar"][2].
set_val(
"oh so nice");
848 CHECK(root[
"bar"].num_children() == 4);
849 CHECK(root[
"bar"][2].val() ==
"oh so nice");
850 CHECK(root[
"bar"][3].val() ==
"oh so nice (serialized)");
851
858 CHECK(root[
"newseq"].num_children() == 0);
859 CHECK(root[
"newseq"].is_seq());
860 CHECK(root[
"newseq (serialized)"].num_children() == 0);
861 CHECK(root[
"newseq (serialized)"].is_seq());
862
869 CHECK(root[
"newmap"].num_children() == 0);
870 CHECK(root[
"newmap"].is_map());
871 CHECK(root[
"newmap (serialized)"].num_children() == 0);
872 CHECK(root[
"newmap (serialized)"].is_map());
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
900
901
905 nothing = wroot["I am nothing"];
910
918
919
922 CHECK(root[
"I am something"].val() ==
"indeed");
925
927
928
932
933
936
937
938
939
940
941
942
943
944
945
946
947
948
949
952 {
953 CHECK(wbar[0].readable() && wbar[0].val() ==
"20");
954 CHECK( ! wbar[100].readable());
955 CHECK( ! wbar[100].readable() || wbar[100].val() ==
"100");
956
957 CHECK( ! wbar[0].is_seed() && wbar[0].val() ==
"20");
958 CHECK(wbar[100].is_seed() || wbar[100].val() ==
"100");
959 }
960
961
962
963
964
965
966
967
968
969
970
971
972
973 {
974
975
977
979
981
983
985
987 return seed_node.at("is").at("an").at("invalid").at("operation");
988
989
990 }));
991
992
994 return seed_node["is"]["an"]["invalid"]["operation"];
995
996
997 }));
998 }
999
1000
1001
1002
1003
1005 "foo: says who" "\n"
1006 "bar: [20,30,oh so nice,oh so nice (serialized)]" "\n"
1007 "john: in_scope" "\n"
1008 "float: 2.4" "\n"
1009 "digits: 2.400000" "\n"
1010 "newkeyval: shiny and new" "\n"
1011 "newkeyval (serialized): shiny and new (serialized)" "\n"
1012 "newseq: []" "\n"
1013 "newseq (serialized): []" "\n"
1014 "newmap: {}" "\n"
1015 "newmap (serialized): {}" "\n"
1016 "I am something: indeed" "\n"
1017 "";
1018
1019
1021
1022
1023
1024
1025 std::stringstream ss;
1026 ss << tree;
1027 std::string stream_result = ss.str();
1028
1030
1031 char buf[1024];
1033
1034 CHECK(buf_result == expected_result);
1035 CHECK(str_result == expected_result);
1036 CHECK(stream_result == expected_result);
1037
1038
1039
1040
1041
1042
1043
1046
1047
1048
1049
1050
1052 CHECK(tree[
"bar"][0].val() ==
"21");
1054 CHECK(tree[
"bar"][0].val() ==
"22");
1055
1056
1057
1058
1059
1060 constnoderef = noderef;
1061
1062
1063
1065
1066 noderef = tree["bar"][0];
1067 constnoderef = consttree["bar"][0];
1068
1069
1070
1071 CHECK(constnoderef == noderef);
1072 CHECK(!(constnoderef != noderef));
1073
1074
1075
1076
1077
1078
1081
1083
1087 CHECK(parser.location_contents(loc).begins_with(
"30"));
1090
1091
1092
1093
1094
1095
1097 "#" "\n"
1098 "# UTF8/16/32 can be placed directly in any scalar:" "\n"
1099 "#" "\n"
1100 "en: Planet (Gas)" "\n"
1101 "fr: Planète (Gazeuse)" "\n"
1102 "ru: Планета (Газ)" "\n"
1103 "ja: 惑星(ガス)" "\n"
1104 "zh: 行星(气体)" "\n"
1105 "#" "\n"
1106 "# UTF8 decoding only happens in double-quoted strings," "\n"
1107 "# as per the YAML standard" "\n"
1108 "#" "\n"
1109 "decode this: \"\\u263A c\\x61f\\xE9\"" "\n"
1110 "and this as well: \"\\u2705 \\U0001D11E\"" "\n"
1111 "not decoded: '\\u263A \\xE2\\x98\\xBA'" "\n"
1112 "neither this: '\\u2705 \\U0001D11E'" "\n");
1113
1114 CHECK(langs[
"en"].val() ==
"Planet (Gas)");
1115 CHECK(langs[
"fr"].val() ==
"Planète (Gazeuse)");
1116 CHECK(langs[
"ru"].val() ==
"Планета (Газ)");
1117 CHECK(langs[
"ja"].val() ==
"惑星(ガス)");
1118 CHECK(langs[
"zh"].val() ==
"行星(气体)");
1119
1120
1121
1122 CHECK(langs[
"decode this"].val() ==
"☺ café");
1123 CHECK(langs[
"and this as well"].val() ==
"✅ 𝄞");
1124 CHECK(langs[
"not decoded"].val() ==
"\\u263A \\xE2\\x98\\xBA");
1125 CHECK(langs[
"neither this"].val() ==
"\\u2705 \\U0001D11E");
1126}
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().