201 #if defined(RYML_SINGLE_HEADER) // using the single header directly in the executable
202 #define RYML_SINGLE_HDR_DEFINE_NOW
203 #include <ryml_all.hpp>
204 #elif defined(RYML_SINGLE_HEADER_LIB) // using the single header from a library
205 #include <ryml_all.hpp>
240 int main(
int argc,
const char* argv[])
305 bool report_check(
int line,
const char *predicate,
bool result);
310 # define CHECK(predicate) assert(predicate) // enable doxygen to link to the functions called inside CHECK()
313 # if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC_MINOR__ > 8))))
314 # define CHECK(predicate) report_check(__LINE__, #predicate, (predicate))
316 # define CHECK CheckPredicate{__LINE__}
318 struct CheckPredicate
321 void operator() (
bool result)
const {
report_check(line,
nullptr, result); }
387 C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
388 C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wold-style-cast")
389 C4_SUPPRESS_WARNING_GCC_CLANG("-Wcast-qual")
390 C4_SUPPRESS_WARNING_GCC("-Wuseless-cast")
391 C4_SUPPRESS_WARNING_GCC("-Wuseless-cast")
392 #if defined(__GNUC__) && (__GNUC__ >= 6)
393 C4_SUPPRESS_WARNING_GCC(
"-Wnull-dereference")
395 #if defined(__clang__) && (__clang_major__ >= 13)
396 C4_SUPPRESS_WARNING_CLANG(
"-Wreserved-identifier")
412 char yml_buf[] =
"{foo: 1, bar: [2, 3], john: doe}";
417 CHECK(bar[0].val() ==
"2");
418 CHECK(bar[1].val() ==
"3");
419 CHECK(bar[0].val().
str == yml_buf + 15);
420 CHECK(bar[1].val().
str == yml_buf + 18);
423 int bar0 = 0, bar1 = 0;
432 CHECK(bar[0].val() ==
"10");
433 CHECK(bar[1].val() ==
"11");
438 CHECK(bar[2].val() ==
"12");
441 std::string expected =
"{foo: 1,bar: [10,11,12],john: doe,new: node}";
443 CHECK(ryml::emitrs_yaml<std::string>(tree) == expected);
447 std::cout << tree <<
"\n";
451 expected =
"foo: 1\n";
453 CHECK(ryml::emitrs_yaml<std::string>(foo) == expected);
516 CHECK(root.is_map());
520 CHECK(root.tree() == &tree);
521 CHECK(root.id() == root_id);
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");
543 CHECK(tree[
"bar"][0].val() ==
"2");
544 CHECK(tree[
"bar"][1].val() ==
"3");
545 CHECK(tree[
"john"].val() ==
"doe");
549 CHECK(tree[0].
id() == tree[
"foo"].
id());
550 CHECK(tree[1].
id() == tree[
"bar"].
id());
551 CHECK(tree[2].
id() == tree[
"john"].
id());
553 CHECK(tree[0].
id() == tree[
"foo"].
id());
554 CHECK(tree[1].
id() == tree[
"bar"].
id());
555 CHECK(tree[2].
id() == tree[
"john"].
id());
557 CHECK(bar[0].val() ==
"2");
558 CHECK(bar[1].val() ==
"3");
563 CHECK(tree[
"foo"].key() ==
"foo");
564 CHECK(tree[
"bar"].key() ==
"bar");
565 CHECK(tree[
"john"].key() ==
"john");
570 CHECK(root[
"foo"].
id() == root[0].
id());
571 CHECK(root[
"bar"].
id() == root[1].
id());
572 CHECK(root[
"john"].
id() == root[2].
id());
607 CHECK(root.num_children() == 3);
610 CHECK(root.first_child().id() == root[
"foo"].id());
611 CHECK(root.last_child().id() == root[
"john"].id());
631 CHECK(child.key() == expected_keys[count++]);
637 CHECK(child.key() == expected_keys[count++]);
643 CHECK(tree.
key(child_id) == expected_keys[count++]);
652 CHECK(tree.
key(child_id) == expected_keys[count++]);
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);
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));
750 std::string john_str, bar_str;
751 root[
"john"].load(&john_str);
752 root[
"bar"].load_key(&bar_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);
775 wroot[
"foo"].
set_val(
"says you");
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");
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");
813 std::string ok(
"in_scope");
817 CHECK(root[
"john"].val() ==
"in_scope");
823 CHECK(tree.
arena() ==
"says who2030deerein_scope2.42.400000");
830 CHECK(root.num_children() == 5);
831 wroot[
"newkeyval"].
set_val(
"shiny and new");
835 CHECK(root.num_children() == 7);
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)");
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)");
852 CHECK(root.num_children() == 7);
857 CHECK(root.num_children() == 9);
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());
863 CHECK(root.num_children() == 9);
868 CHECK(root.num_children() == 11);
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());
902 CHECK(!root.has_child(
"I am not nothing"));
904 CHECK(nothing.invalid());
905 nothing = wroot[
"I am nothing"];
906 CHECK(!nothing.invalid());
907 CHECK(nothing.is_seed());
908 CHECK(!root.has_child(
"I am nothing"));
909 CHECK(!nothing.readable());
913 CHECK(!root.has_child(
"I am something"));
914 CHECK(!something.invalid());
915 CHECK(something.is_seed());
916 CHECK(!something.readable());
920 something.set_val(
"indeed");
921 CHECK(root.has_child(
"I am something"));
922 CHECK(root[
"I am something"].val() ==
"indeed");
923 CHECK(!something.invalid());
924 CHECK(!something.is_seed());
926 CHECK(something.readable());
930 CHECK(!constsomethingnew.invalid());
931 CHECK(constsomethingnew.readable());
951 if(wbar.readable() && wbar.is_seq())
953 CHECK(wbar[0].readable() && wbar[0].val() ==
"20");
954 CHECK( ! wbar[100].readable());
955 CHECK( ! wbar[100].readable() || wbar[100].val() ==
"100");
957 CHECK( ! wbar[0].is_seed() && wbar[0].val() ==
"20");
958 CHECK(wbar[100].is_seed() || wbar[100].val() ==
"100");
984 CHECK(!seed_node.readable());
987 return seed_node.at(
"is").at(
"an").at(
"invalid").at(
"operation");
994 return seed_node[
"is"][
"an"][
"invalid"][
"operation"];
1005 "foo: says who" "\n"
1006 "bar: [20,30,oh so nice,oh so nice (serialized)]" "\n"
1007 "john: in_scope" "\n"
1009 "digits: 2.400000" "\n"
1010 "newkeyval: shiny and new" "\n"
1011 "newkeyval (serialized): shiny and new (serialized)" "\n"
1013 "newseq (serialized): []" "\n"
1015 "newmap (serialized): {}" "\n"
1016 "I am something: indeed" "\n"
1025 std::stringstream ss;
1027 std::string stream_result = ss.str();
1029 std::string str_result = ryml::emitrs_yaml<std::string>(tree);
1034 CHECK(buf_result == expected_result);
1035 CHECK(str_result == expected_result);
1036 CHECK(stream_result == expected_result);
1052 CHECK(tree[
"bar"][0].val() ==
"21");
1054 CHECK(tree[
"bar"][0].val() ==
"22");
1060 constnoderef = noderef;
1066 noderef = tree[
"bar"][0];
1067 constnoderef = consttree[
"bar"][0];
1071 CHECK(constnoderef == noderef);
1072 CHECK(!(constnoderef != noderef));
1088 CHECK(loc.line == 1u);
1089 CHECK(loc.col == 9u);
1098 "# UTF8/16/32 can be placed directly in any scalar:" "\n"
1100 "en: Planet (Gas)" "\n"
1101 "fr: Planète (Gazeuse)" "\n"
1102 "ru: Планета (Газ)" "\n"
1106 "# UTF8 decoding only happens in double-quoted strings," "\n"
1107 "# as per the YAML standard" "\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");
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() ==
"行星(气体)");
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");
1153 const char foobar_str[] =
"foobar";
1155 CHECK(s ==
"foobar");
1156 CHECK(s.size() == 6);
1157 CHECK(s.data() == foobar_str);
1158 CHECK(s.size() == s.len);
1159 CHECK(s.data() == s.str);
1164 const char foobar_str[] =
"foobar";
1166 CHECK(s ==
"foobar");
1167 CHECK(s !=
"foobar0");
1176 CHECK(s ==
"foobar");
1177 CHECK(s !=
"foobar0");
1189 const char *foobar_str =
"foobar";
1191 CHECK(s ==
"foobar");
1192 CHECK(s !=
"foobar0");
1206 std::string foobar_str =
"foobar";
1208 CHECK(s ==
"foobar");
1209 CHECK(s !=
"foobar0");
1222 CHECK(cfoo.data() == buf);
1231 char const foobar_str_ro[] =
"foobar";
1232 char foobar_str_rw[] =
"foobar";
1233 static_assert(std::is_array<decltype(foobar_str_ro)>::value,
"this is an array");
1234 static_assert(std::is_array<decltype(foobar_str_rw)>::value,
"this is an array");
1239 CHECK(foobar.
size() == strlen(foobar_str_ro));
1240 CHECK(foobar ==
"foobar");
1246 CHECK(foobar.
size() == strlen(foobar_str_rw));
1247 CHECK(foobar ==
"foobar");
1253 CHECK(foobar.
size() == strlen(foobar_str_rw));
1254 CHECK(foobar ==
"foobar");
1265 char const* foobar_str_ro =
"foobar";
1266 char foobar_str_rw_[] =
"foobar";
1267 char * foobar_str_rw = foobar_str_rw_;
1268 static_assert(!std::is_array<decltype(foobar_str_ro)>::value,
"this is a decayed pointer");
1269 static_assert(!std::is_array<decltype(foobar_str_rw)>::value,
"this is a decayed pointer");
1275 CHECK(foobar.
size() == strlen(foobar_str_ro));
1276 CHECK(foobar ==
"foobar");
1282 CHECK(foobar.
size() == strlen(foobar_str_rw));
1283 CHECK(foobar ==
"foobar");
1289 CHECK(foobar.
size() == strlen(foobar_str_rw));
1290 CHECK(foobar ==
"foobar");
1300 char buf[] =
"foobar";
1302 CHECK(foobar ==
"foobar");
1303 foobar[0] =
'F';
CHECK(foobar ==
"Foobar");
1304 foobar.
back() =
'R';
CHECK(foobar ==
"FoobaR");
1316 foobar.
fill(
'.');
CHECK(foobar ==
"......");
1328 CHECK(s.
sub(0, 12) ==
"fooFOObarBAR");
1388 CHECK(some ==
"some");
1389 CHECK(s ==
"some substring");
1392 char result[32] = {0};
1393 std::snprintf(result,
sizeof(result),
"%.*s", (
int)some.
len, some.
str);
1394 printf(
"~~~%s~~~\n", result);
1404 char result[32] = {0};
1405 std::snprintf(result,
sizeof(result),
"%s", some.
str);
1415 CHECK(some ==
"some");
1416 CHECK(s ==
"some substring");
1419 std::stringstream ss;
1421 CHECK(ss.str() ==
"some substring");
1422 CHECK(ss.str() == s);
1430 std::stringstream ss;
1432 CHECK(ss.str() ==
"some substring");
1433 CHECK(ss.str() == s);
1437 std::stringstream ss;
1439 CHECK(ss.str() ==
"some substring");
1440 CHECK(ss.str() == s);
1444 std::stringstream ss;
1446 CHECK(ss.str() ==
"some");
1447 CHECK(ss.str() == some);
1484 CHECK(
ryml::csubstr(
" \t\n\rcontents without whitespace\t \n\r").trim(
"\t \n\r") ==
"contents without whitespace");
1505 CHECK(aaa___bbb.
trim (
'c') == aaa___bbb);
1524 CHECK(aaa___bbb.
trim (
"cd") == aaa___bbb);
1529 CHECK(
ryml::csubstr(
"'this is is single quoted'" ).unquoted() ==
"this is is single quoted");
1530 CHECK(
ryml::csubstr(
"\"this is is double quoted\"").unquoted() ==
"this is is double quoted");
1848 CHECK(
ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extshort() ==
"/path/to/file.tar");
1854 using namespace ryml;
1855 csubstr parts[] = {
"aa",
"bb",
"cc",
"dd",
"ee",
"ff"};
1859 CHECK(part == parts[count++]);
1865 CHECK(part == parts[count++]);
1871 CHECK(part == parts[count++]);
1880 const bool skip_empty =
true;
1953 const char filename[] =
"ryml_example.yml";
1954 std::string yaml =
""
1966 std::string contents = ryml::file_get_contents<std::string>(filename);
1968 CHECK(tree[
"foo"].val() ==
"1");
1969 CHECK(tree[
"bar"][0].val() ==
"2");
1970 CHECK(tree[
"bar"][1].val() ==
"3");
1975 std::vector<char> contents = ryml::file_get_contents<std::vector<char>>(filename);
1977 CHECK(tree[
"foo"].val() ==
"1");
1978 CHECK(tree[
"bar"][0].val() ==
"2");
1979 CHECK(tree[
"bar"][1].val() ==
"3");
2000 char src[] =
"{foo: 1, bar: [2, 3]}";
2006 CHECK(root[
"foo"].is_keyval());
2007 CHECK(root[
"foo"].key() ==
"foo");
2008 CHECK(root[
"foo"].val() ==
"1");
2009 CHECK(root[
"bar"].is_seq());
2010 CHECK(root[
"bar"].has_key());
2011 CHECK(root[
"bar"].key() ==
"bar");
2012 CHECK(root[
"bar"][0].val() ==
"2");
2013 CHECK(root[
"bar"][1].val() ==
"3");
2016 int foo = 0, bar0 = 0, bar1 = 0;
2017 root[
"foo"].
load(&foo);
2018 root[
"bar"][0].
load(&bar0);
2019 root[
"bar"][1].
load(&bar1);
2025 CHECK(root[
"foo"].val().data() == src + strlen(
"{foo: "));
2026 CHECK(root[
"foo"].val().begin() == src + strlen(
"{foo: "));
2027 CHECK(root[
"foo"].val().end() == src + strlen(
"{foo: 1"));
2028 CHECK(root[
"foo"].val().is_sub(srcview));
2029 CHECK(root[
"bar"][0].val().data() == src + strlen(
"{foo: 1, bar: ["));
2030 CHECK(root[
"bar"][0].val().begin() == src + strlen(
"{foo: 1, bar: ["));
2031 CHECK(root[
"bar"][0].val().end() == src + strlen(
"{foo: 1, bar: [2"));
2032 CHECK(root[
"bar"][0].val().is_sub(srcview));
2033 CHECK(root[
"bar"][1].val().data() == src + strlen(
"{foo: 1, bar: [2, "));
2034 CHECK(root[
"bar"][1].val().begin() == src + strlen(
"{foo: 1, bar: [2, "));
2035 CHECK(root[
"bar"][1].val().end() == src + strlen(
"{foo: 1, bar: [2, 3"));
2036 CHECK(root[
"bar"][1].val().is_sub(srcview));
2058 CHECK(root[
"foo"].is_keyval());
2059 CHECK(root[
"foo"].key() ==
"foo");
2060 CHECK(root[
"foo"].val() ==
"1");
2061 CHECK(root[
"bar"].is_seq());
2062 CHECK(root[
"bar"].has_key());
2063 CHECK(root[
"bar"].key() ==
"bar");
2064 CHECK(root[
"bar"][0].val() ==
"2");
2065 CHECK(root[
"bar"][1].val() ==
"3");
2068 int foo = 0, bar0 = 0, bar1 = 0;
2069 root[
"foo"].
load(&foo);
2070 root[
"bar"][0].
load(&bar0);
2071 root[
"bar"][1].
load(&bar1);
2079 char src[] =
"{foo: is it really true}";
2088 CHECK(tree[
"foo"].val() ==
"is it really true");
2116 CHECK(root[
"foo"].is_keyval());
2117 CHECK(root[
"foo"].key() ==
"foo");
2118 CHECK(root[
"foo"].val() ==
"1");
2119 CHECK(root[
"bar"].is_seq());
2120 CHECK(root[
"bar"].has_key());
2121 CHECK(root[
"bar"].key() ==
"bar");
2122 CHECK(root[
"bar"][0].val() ==
"2");
2123 CHECK(root[
"bar"][1].val() ==
"3");
2124 CHECK(ryml::emitrs_yaml<std::string>(tree) == yaml);
2128 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
2132 "bar2: [22,32]" "\n"
2135 CHECK(root[
"foo2"].is_keyval());
2136 CHECK(root[
"foo2"].key() ==
"foo2");
2137 CHECK(root[
"foo2"].val() ==
"12");
2138 CHECK(root[
"bar2"].is_seq());
2139 CHECK(root[
"bar2"].has_key());
2140 CHECK(root[
"bar2"].key() ==
"bar2");
2141 CHECK(root[
"bar2"][0].val() ==
"22");
2142 CHECK(root[
"bar2"][1].val() ==
"32");
2149 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
"- a\n- b\n- {x0: 1,x1: 2}\n");
2151 CHECK(root[0].val() ==
"a");
2152 CHECK(root[1].val() ==
"b");
2153 CHECK(root[2].is_map());
2154 CHECK(root[2][
"x0"].val() ==
"1");
2155 CHECK(root[2][
"x1"].val() ==
"2");
2160 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
2163 "- {x0: 1,x1: 2}" "\n"
2164 "- champagne: Dom Perignon" "\n"
2165 " coffee: Arabica" "\n"
2168 CHECK(root[0].val() ==
"a");
2169 CHECK(root[1].val() ==
"b");
2170 CHECK(root[2].is_map());
2171 CHECK(root[2][
"x0"].val() ==
"1");
2172 CHECK(root[2][
"x1"].val() ==
"2");
2173 CHECK(root[3].is_map());
2174 CHECK(root[3][
"champagne"].val() ==
"Dom Perignon");
2175 CHECK(root[3][
"coffee"].val() ==
"Arabica");
2179 CHECK(mroot[3][
"more"].readable());
2180 CHECK(mroot[3][
"more"].key() ==
"more");
2181 CHECK(mroot[3][
"more"].is_map());
2182 CHECK(!mroot[3][
"more"].is_val());
2186 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
2189 "- {x0: 1,x1: 2}" "\n"
2190 "- champagne: Dom Perignon" "\n"
2191 " coffee: Arabica" "\n"
2194 " vinho verde: Soalheiro" "\n"
2195 " vinho tinto: Redoma 2017" "\n"
2197 " - Rochefort 10" "\n"
2199 " - Leffe Rituel" "\n"
2200 " always: lots of water" "\n"
2205 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
2208 "- {x0: 1,x1: 2}" "\n"
2209 "- champagne: Dom Perignon" "\n"
2210 " coffee: Arabica" "\n"
2212 " vinho verde: Soalheiro" "\n"
2213 " vinho tinto: Redoma 2017" "\n"
2215 " - Rochefort 10" "\n"
2217 " - Leffe Rituel" "\n"
2218 " always: lots of water" "\n"
2228 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
2231 "- {x0: 1,x1: 2}" "\n"
2232 "- champagne: Dom Perignon" "\n"
2233 " coffee: Arabica" "\n"
2235 " vinho verde: Soalheiro" "\n"
2236 " vinho tinto: Redoma 2017" "\n"
2238 " - Rochefort 10" "\n"
2240 " - Leffe Rituel" "\n"
2241 " - Kasteel Donker" "\n"
2242 " always: lots of water" "\n"
2270 ryml::csubstr yaml =
"[Dom Perignon,Gosset Grande Reserve,Jacquesson 742]";
2272 CHECK(ryml::emitrs_yaml<std::string>(champagnes) == yaml);
2274 yaml =
"[Rochefort 10,Busch,Leffe Rituel,Kasteel Donker]";
2276 CHECK(ryml::emitrs_yaml<std::string>(beers) == yaml);
2308 "- Gosset Grande Reserve\n"
2309 "- Jacquesson 742\n"
2315 "- Kasteel Donker\n"
2319 "- Niepoort Redoma 2017\n"
2320 "- Vina Esmeralda\n"
2324 CHECK(ryml::emitrs_yaml<std::string>(tree) == champagnes);
2328 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
2330 "- Gosset Grande Reserve\n"
2331 "- Jacquesson 742\n"
2335 "- Kasteel Donker\n"
2341 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
2343 "- Niepoort Redoma 2017\n"
2344 "- Vina Esmeralda\n"
2360 "doe: a deer, a female deer" "\n"
2361 "ray: 'a drop of golden sun'" "\n"
2362 "me: \"a name I call myself\"" "\n"
2364 " a long long way to go" "\n"
2366 " a needle pulling thread" "\n"
2367 "seq: [0,1,2,3]" "\n"
2377 CHECK(tree[
"doe"].is_val_plain());
2378 CHECK(tree[
"ray"].is_val_squo());
2379 CHECK(tree[
"me"].is_val_dquo());
2380 CHECK(tree[
"far"].is_val_literal());
2381 CHECK(tree[
"sow"].is_val_folded());
2382 CHECK(tree[
"seq"].is_flow());
2383 CHECK(tree[
"seq"].is_flow_sl());
2384 CHECK(tree[
"map"].is_flow());
2385 CHECK(tree[
"map"].is_flow_mlx());
2388 CHECK(ryml::emitrs_yaml<std::string>(tree) == yaml);
2401 "doe: a deer, a female deer" "\n"
2402 "ray: a drop of golden sun" "\n"
2405 "french-hens: 3" "\n"
2406 "calling-birds:" "\n"
2411 "xmas-fifth-day:" "\n"
2412 " calling-birds: four" "\n"
2413 " french-hens: 3" "\n"
2414 " golden-rings: 5" "\n"
2417 " location: a pear tree" "\n"
2418 " turtle-doves: two" "\n"
2425 std::vector<ryml::csubstr> keys, vals;
2428 keys.emplace_back(n.key());
2431 CHECK(keys.size() >= 6);
2432 CHECK(vals.size() >= 6);
2433 if(keys.size() >= 6 && vals.size() >= 6)
2435 CHECK(keys[0] ==
"doe");
2436 CHECK(vals[0] ==
"a deer, a female deer");
2437 CHECK(keys[1] ==
"ray");
2438 CHECK(vals[1] ==
"a drop of golden sun");
2439 CHECK(keys[2] ==
"pi");
2440 CHECK(vals[2] ==
"3.14159");
2441 CHECK(keys[3] ==
"xmas");
2442 CHECK(vals[3] ==
"true");
2443 CHECK(root[5].has_key());
2444 CHECK(root[5].is_seq());
2445 CHECK(root[5].key() ==
"calling-birds");
2446 CHECK(!root[5].has_val());
2448 CHECK(keys[5] ==
"calling-birds");
2449 CHECK(vals[5] ==
"");
2456 ryml::csubstr calling_birds[] = {
"huey",
"dewey",
"louie",
"fred"};
2458 CHECK(n.val() == calling_birds[count++]);
2478 "aa: contents," "\n"
2479 "foo: [one, [two, three]]" "\n"
2523 loc = tree[
"foo"].
location(parser);
2528 loc = tree[
"foo"][0].
location(parser);
2533 loc = tree[
"foo"][1].
location(parser);
2537 loc = tree[
"foo"][1][0].
location(parser);
2541 loc = tree[
"foo"][1][1].
location(parser);
2563 "a new: buffer" "\n"
2564 "to: be parsed" "\n"
2565 "map with key:" "\n"
2566 " first: value" "\n"
2567 " second: value" "\n"
2568 "seq with key:" "\n"
2569 " - first value" "\n"
2570 " - second value" "\n"
2572 " - nested first value" "\n"
2573 " - nested second value" "\n"
2575 " nested first: value" "\n"
2576 " nested second: value" "\n"
2590 loc = tree2[
"a new"].
location(parser);
2595 loc = tree2[
"to"].
location(parser);
2601 loc = tree2[
"map with key"].
location(parser);
2605 loc = tree2[
"map with key"][
"first"].
location(parser);
2609 loc = tree2[
"map with key"][
"second"].
location(parser);
2614 loc = tree2[
"seq with key"].
location(parser);
2618 loc = tree2[
"seq with key"][0].
location(parser);
2622 loc = tree2[
"seq with key"][1].
location(parser);
2627 loc = tree2[
"seq with key"][2].
location(parser);
2631 loc = tree2[
"seq with key"][2][0].
location(parser);
2636 loc = tree2[
"seq with key"][3].
location(parser);
2640 loc = tree2[
"seq with key"][3][0].
location(parser);
2667 const char a_deer[] =
"a deer, a female deer";
2676 std::string a_drop =
"a drop of golden sun";
2685 CHECK(root[
"ray"].val() ==
"a drop of golden sun");
2699 xmas5[
"calling-birds"].
set_val(
"four");
2702 xmas5[
"partridges"].
set_map();
2704 xmas5[
"partridges"][
"location"].
set_val(
"a pear tree");
2705 xmas5[
"turtle-doves"].
set_val(
"two");
2708 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
2709 "doe: a deer, a female deer" "\n"
2710 "ray: a drop of golden sun" "\n"
2713 "french-hens: 3" "\n"
2714 "calling-birds:" "\n"
2719 "xmas-fifth-day:" "\n"
2720 " calling-birds: four" "\n"
2721 " french-hens: 3" "\n"
2722 " golden-rings: 5" "\n"
2725 " location: a pear tree" "\n"
2726 " turtle-doves: two" "\n"
2771 root[
"not plain"].
set_val(
" with whitespace ");
2785 for(
int i : {0, 1, 2, 3})
2804 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
2810 "not plain: ' with whitespace '" "\n"
2814 "doe: a deer, a female deer" "\n"
2815 "ray: 'a drop of golden sun'" "\n"
2816 "me: \"a name I call myself\"" "\n"
2818 " a long long way to go" "\n"
2820 " a needle pulling thread" "\n"
2821 "seq: [0, 1, 2, 3]" "\n"
2829 " 1: 10,2: 20,3: 30,4: 40" "\n"
2841 CHECK(ryml::emitrs_yaml<std::string>(root[
"plain"]) ==
2842 "plain: with whitespace " "\n"
2856 char buf[] =
"[a, b, c, d]";
2863 CHECK(root[0].val().is_sub(yml));
2864 CHECK(root[1].val().is_sub(yml));
2865 CHECK(root[2].val().is_sub(yml));
2866 CHECK(root[3].val().is_sub(yml));
2886 CHECK(root[0].val().is_sub(arena));
2887 CHECK(root[1].val().is_sub(arena));
2888 CHECK(root[2].val().is_sub(arena));
2889 CHECK(root[3].val().is_sub(arena));
2899 char buf[] =
"[a, b, c, d]";
2907 CHECK(root[2].val() ==
"c");
2908 CHECK(root[2].val().is_sub(yml));
2909 root[2].set_serialized(12345);
2910 CHECK(root[2].val() ==
"12345");
2916 CHECK(root[3].val() ==
"d");
2917 CHECK(root[3].val().is_sub(yml));
2918 root[3].set_serialized(67890);
2919 CHECK(root[3].val() ==
"67890");
2935 CHECK(root[2].val() ==
"c");
2936 root[2].set_serialized(12345);
2937 CHECK(root[2].val() ==
"12345");
2945 root[3].set_serialized(67890);
2946 CHECK(root[3].val() ==
"67890");
2950 CHECK(tree.
arena() ==
"[a, b, c, d]1234567890");
2958 CHECK(c10 ==
"10101010");
2968 CHECK(root[
"a"].val() ==
"2222");
2978 CHECK(copied == mystr);
2979 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2988 memcpy(copied.
str, mystr.
str, mystr.
len);
2989 CHECK(copied == mystr);
2990 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
3039 CHECK(tree.
to_arena(
double(0.234)) ==
"0.234");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.234");
3049 const float fnan = std::numeric_limits<float >::quiet_NaN();
3050 const double dnan = std::numeric_limits<double>::quiet_NaN();
3051 const float finf = std::numeric_limits<float >::infinity();
3052 const double dinf = std::numeric_limits<double>::infinity();
3053 CHECK(tree.
to_arena( finf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf");
3054 CHECK(tree.
to_arena( dinf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf");
3055 CHECK(tree.
to_arena(-finf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf");
3056 CHECK(tree.
to_arena(-dinf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf");
3057 CHECK(tree.
to_arena( fnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan");
3058 CHECK(tree.
to_arena( dnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan.nan");
3062 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wfloat-equal");
3068 tree[
"ninf"].
load(&f);
CHECK(f == -finf);
3069 tree[
"ninf"].
load(&d);
CHECK(d == -dinf);
3070 tree[
"pinf"].
load(&f);
CHECK(f == finf);
3071 tree[
"pinf"].
load(&d);
CHECK(d == dinf);
3072 tree[
"nan" ].
load(&f);
CHECK(std::isnan(f));
3073 tree[
"nan" ].
load(&d);
CHECK(std::isnan(d));
3074 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3091 CHECK(ryml::overflows<uint8_t>(n.
val()));
3092 CHECK(ryml::overflows<int8_t>(n.
val()));
3093 CHECK( ! ryml::overflows<int16_t>(n.
val()));
3096 n.load(ryml::fmt::overflow_checked(valu8));
3099 n.load(ryml::fmt::overflow_checked(vali8));
3115 "dquoted: \"\"" "\n"
3118 "all_null: [~, null, Null, NULL]" "\n"
3119 "non_null: [nULL, non_null, non null, null it is not]" "\n"
3123 CHECK(tree[
"plain"].has_val());
3124 CHECK(tree[
"squoted"].has_val());
3125 CHECK(tree[
"dquoted"].has_val());
3126 CHECK(tree[
"literal"].has_val());
3127 CHECK(tree[
"folded"].has_val());
3128 CHECK( ! tree[
"all_null"].has_val());
3129 CHECK( ! tree[
"non_null"].has_val());
3131 CHECK( ! tree[
"plain"].is_container());
3132 CHECK( ! tree[
"squoted"].is_container());
3133 CHECK( ! tree[
"dquoted"].is_container());
3134 CHECK( ! tree[
"literal"].is_container());
3135 CHECK( ! tree[
"folded"].is_container());
3136 CHECK(tree[
"all_null"].is_container());
3137 CHECK(tree[
"non_null"].is_container());
3142 CHECK(tree[
"plain"].val().len == 0);
3143 CHECK(tree[
"squoted"].val().len == 0);
3144 CHECK(tree[
"dquoted"].val().len == 0);
3145 CHECK(tree[
"literal"].val().len == 0);
3146 CHECK(tree[
"folded"].val().len == 0);
3148 CHECK(tree[
"plain"].val().
str ==
nullptr);
3149 CHECK(tree[
"squoted"].val().
str !=
nullptr);
3150 CHECK(tree[
"dquoted"].val().
str !=
nullptr);
3151 CHECK(tree[
"literal"].val().
str !=
nullptr);
3152 CHECK(tree[
"folded"].val().
str !=
nullptr);
3156 CHECK(tree[
"plain"].val() ==
nullptr);
3157 CHECK(tree[
"squoted"].val() !=
nullptr);
3158 CHECK(tree[
"dquoted"].val() !=
nullptr);
3159 CHECK(tree[
"literal"].val() !=
nullptr);
3160 CHECK(tree[
"folded"].val() !=
nullptr);
3165 CHECK(tree[
"plain"].val_is_null());
3166 CHECK( ! tree[
"squoted"].val_is_null());
3167 CHECK( ! tree[
"dquoted"].val_is_null());
3168 CHECK( ! tree[
"literal"].val_is_null());
3169 CHECK( ! tree[
"folded"].val_is_null());
3174 CHECK(child.val() !=
nullptr);
3175 CHECK(child.val_is_null());
3179 CHECK(child.val() !=
nullptr);
3180 CHECK( ! child.val_is_null());
3211 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
3213 "empty_nonnull: ''" "\n"
3214 "str_null: null" "\n"
3223 return s.str ==
nullptr ?
"null" : s;
3230 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
3231 "empty_null: null" "\n"
3232 "empty_nonnull: ''" "\n"
3233 "str_null: null" "\n"
3243 tree[
"empty_nonnull"].
set_serialized(null_if_predicate(nonnull));
3247 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
3248 "empty_null: null" "\n"
3249 "empty_nonnull: ''" "\n"
3250 "str_null: null" "\n"
3251 "str_tilde: null" "\n"
3260 tree[
"empty_nonnull"].
set_serialized(tilde_if_predicate(nonnull));
3264 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
3265 "empty_null: ~" "\n"
3266 "empty_nonnull: ''" "\n"
3284 char buf_[256] = {};
3286 size_t size =
ryml::format(buf,
"a={} foo {} {} bar {}", 0.1, 10, 11, 12);
3287 CHECK(size == strlen(
"a=0.1 foo 10 11 bar 12"));
3288 CHECK(buf.
first(size) ==
"a=0.1 foo 10 11 bar 12");
3291 size =
ryml::format({} ,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12);
3292 CHECK(size ==
ryml::format(buf,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12));
3293 CHECK(size == strlen(
"a=this_is_a foo 10 11 bar 12"));
3295 char smallbuf[8] = {};
3296 size =
ryml::format(smallbuf,
"{} is too large {}",
"this",
"for the buffer");
3297 CHECK(size == strlen(
"this is too large for the buffer"));
3303 CHECK(result ==
"b=1, damn it.");
3322 CHECK(sbuf ==
"and c=2 seems about right");
3323 std::vector<char> vbuf;
3325 CHECK(sbuf ==
"and c=2 seems about right");
3328 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
3335 int a = 0, b = 1, c = 2;
3337 CHECK(result ==
"0 and 1 and 2");
3338 int aa = -1, bb = -2, cc = -3;
3339 size_t num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
3347 CHECK(result ==
"10 and 20 and 30");
3348 num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
3358 char buf_[256] = {};
3360 size_t size =
ryml::cat(buf,
"a=", 0.1,
"foo", 10, 11,
"bar", 12);
3361 CHECK(size == strlen(
"a=0.1foo1011bar12"));
3362 CHECK(buf.
first(size) ==
"a=0.1foo1011bar12");
3367 char smallbuf[8] = {};
3368 size =
ryml::cat(smallbuf,
"this",
" is too large ",
"for the buffer");
3369 CHECK(size == strlen(
"this is too large for the buffer"));
3375 CHECK(result ==
"b=1, damn it.");
3393 ryml::catrs(&sbuf,
"and c=", 2,
" seems about right");
3394 CHECK(sbuf ==
"and c=2 seems about right");
3395 std::vector<char> vbuf;
3396 ryml::catrs(&vbuf,
"and c=", 2,
" seems about right");
3397 CHECK(sbuf ==
"and c=2 seems about right");
3400 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
3407 int a = 0, b = 1, c = 2;
3409 CHECK(result ==
"0 1 2");
3410 int aa = -1, bb = -2, cc = -3;
3411 char sep1 =
'a', sep2 =
'b';
3412 size_t num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
3421 CHECK(result ==
"10 20 30");
3422 num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
3433 char buf_[256] = {};
3436 size_t size =
ryml::catsep(buf,
' ',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
3437 CHECK(buf.
first(size) ==
"a= 0 b= 1 c= 2 45 67");
3440 size =
ryml::catsep(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
3441 CHECK(buf.
first(size) ==
"a=0 and b=1 and c=2 and 45 and 67");
3443 size =
ryml::catsep(buf,
" ... ",
"a=0",
"b=1",
"c=2", 45, 67);
3444 CHECK(buf.
first(size) ==
"a=0 ... b=1 ... c=2 ... 45 ... 67");
3446 size =
ryml::catsep(buf,
'/',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
3447 CHECK(buf.
first(size) ==
"a=/0/b=/1/c=/2/45/67");
3449 size =
ryml::catsep(buf, 888,
"a=0",
"b=1",
"c=2", 45, 67);
3450 CHECK(buf.
first(size) ==
"a=0888b=1888c=28884588867");
3456 char smallbuf[8] = {};
3458 CHECK(size == strlen(
"a=0888b=1888c=28884588867"));
3464 CHECK(result ==
"a=0 and b=1 and c=2 and 45 and 67");
3483 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67");
3484 std::vector<char> vbuf;
3490 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67 --- a=0 well b=11 well c=12 well 145 well 167");
3495 char buf_[256] = {};
3497 int a = 0, b = 1, c = 2;
3499 CHECK(result ==
"0 1 2");
3500 int aa = -1, bb = -2, cc = -3;
3508 CHECK(result ==
"10--20--30");
3518 using namespace ryml;
3519 char buf_[256] = {};
3538 CHECK(
"3735928559" ==
cat_sub(buf, UINT32_C(0xdeadbeef)));
3662 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wcast-align")
3663 const uint32_t payload[] = {10, 20, 30, 40, UINT32_C(0xdeadbeef)};
3665 csubstr expected =
csubstr((
const char *)payload,
sizeof(payload));
3670 for(
const uint32_t value : payload)
3673 expected =
csubstr((
const char *)&value,
sizeof(value));
3675 CHECK(actual.
size() ==
sizeof(uint32_t));
3680 CHECK(actual.
size() ==
sizeof(uint32_t));
3685 uint32_t result = 0;
3690 CHECK(result == value);
3692 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3712 text_and_base64 cases[] = {
3713 {{
"Hello, World!"}, {
"SGVsbG8sIFdvcmxkIQ=="}},
3714 {{
"Brevity is the soul of wit."}, {
"QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu"}},
3715 {{
"All that glitters is not gold."}, {
"QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu"}},
3718 for(text_and_base64 c : cases)
3721 for(text_and_base64 c : cases)
3728 for(text_and_base64 c : cases)
3730 CHECK(tree[c.text].
val() == c.base64);
3731 CHECK(tree[c.base64].
val() == c.text);
3734 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
3735 "Hello, World!: SGVsbG8sIFdvcmxkIQ==" "\n"
3736 "Brevity is the soul of wit.: QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu" "\n"
3737 "All that glitters is not gold.: QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu" "\n"
3739 "SGVsbG8sIFdvcmxkIQ==: Hello, World!" "\n"
3740 "QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu: Brevity is the soul of wit." "\n"
3741 "QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu: All that glitters is not gold." "\n"
3743 char buf1_[128], buf2_[128];
3747 for(
const text_and_base64 c : cases)
3761 CHECK(c.text.len == len);
3771 CHECK(result == c.text);
3774 CHECK(result == c.text);
3785 if(len > result.size())
3794 CHECK(result == c.text);
3803 union { uint32_t u;
char c[
sizeof(uint32_t)]; } endianess_test = {1};
3804 const bool is_little_endian = endianess_test.c[0] == 1;
3806 return is_little_endian ? little_endian : big_endian;
3811 const uint64_t valin = UINT64_C(0xdeadbeef);
3814 CHECK(node.
val() == endian_select(
"776t3gAAAAA=",
"AAAAAN6tvu8="));
3815 uint64_t valout = 0;
3818 CHECK(len ==
sizeof(valout));
3819 CHECK(valout == UINT64_C(0xdeadbeef));
3823 CHECK(valout == UINT64_C(0xdeadbeef));
3827 const double valin = 123456.7891011;
3830 CHECK(node.
val() == endian_select(
"nHkooAwk/kA=",
"QP4kDKAoeZw="));
3834 CHECK(len ==
sizeof(valout));
3835 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3839 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3843 const uint32_t data_in[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xdeadbeef};
3844 uint32_t data_out[11] = {};
3848 endian_select(
"AAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAO++rd4=",
3849 "AAAAAAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACd6tvu8="));
3850 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) != 0);
3853 CHECK(len ==
sizeof(data_out));
3854 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3857 memset(data_out, 0,
sizeof(data_out));
3859 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3881 {
int val = 1; tree[0].
load(&val);
CHECK(val == 0); }
3882 {
unsigned val = 0; tree[1].
load(&val);
CHECK(val == 10); }
3884 {
unsigned key = 0; tree[1].
load_key(&key);
CHECK(key == 10); }
3886 {
int val = 1; tree.
load(tree[0].
id(), &val);
CHECK(val == 0); }
3887 {
unsigned val = 0; tree.
load(tree[1].
id(), &val);
CHECK(val == 10); }
3888 {
int key = 1; tree.
load_key(tree[0].
id(), &key);
CHECK(key == 0); }
3889 {
unsigned key = 0; tree.
load_key(tree[1].
id(), &key);
CHECK(key == 10); }
3894 {
int val = 1;
CHECK(tree[0].deserialize(&val));
CHECK(val == 0); }
3895 {
unsigned val = 0;
CHECK(tree[1].deserialize(&val));
CHECK(val == 10); }
3896 {
int key = 1;
CHECK(tree[0].deserialize_key(&key));
CHECK(key == 0); }
3897 {
unsigned key = 0;
CHECK(tree[1].deserialize_key(&key));
CHECK(key == 10); }
3908 {
int val = 10; tree[0].
save(val);
CHECK(tree[0].val() ==
"10"); }
3909 {
unsigned val = 11; tree[1].
save(val);
CHECK(tree[1].val() ==
"11"); }
3910 {
int key = 12; tree[0].
save_key(key);
CHECK(tree[0].key() ==
"12"); }
3911 {
unsigned key = 13; tree[1].
save_key(key);
CHECK(tree[1].key() ==
"13"); }
3913 {
int val = 20; tree.
save(tree[0].
id(), val);
CHECK(tree[0].val() ==
"20"); }
3914 {
unsigned val = 21; tree.
save(tree[1].
id(), val);
CHECK(tree[1].val() ==
"21"); }
3915 {
int key = 22; tree.
save_key(tree[0].
id(), key);
CHECK(tree[0].key() ==
"22"); }
3916 {
unsigned key = 23; tree.
save_key(tree[1].
id(), key);
CHECK(tree[1].key() ==
"23"); }
3930 {
unsigned val = 19; tree.
set_serialized(tree[1].
id(), val);
CHECK(tree[1].val() ==
"19"); }
3938 tree[0].
set_val_tag(tree[0].to_arena(42));
CHECK(tree[0].val_tag() ==
"42");
3939 tree[1].
set_key_tag(tree[1].to_arena(43));
CHECK(tree[1].key_tag() ==
"43");
4026 root[
"v2"].
save(v2in);
4027 root[
"v2"].
load(&v2out);
4028 CHECK(v2in.x == v2out.x);
4029 CHECK(v2in.y == v2out.y);
4032 root[
"v3"].
save(v3in);
4033 root[
"v3"].
load(&v3out);
4034 CHECK(v3in.x == v3out.x);
4035 CHECK(v3in.y == v3out.y);
4036 CHECK(v3in.z == v3out.z);
4039 root[
"v4"].
save(v4in);
4040 root[
"v4"].
load(&v4out);
4041 CHECK(v4in.x == v4out.x);
4042 CHECK(v4in.y == v4out.y);
4043 CHECK(v4in.z == v4out.z);
4044 CHECK(v4in.w == v4out.w);
4045 CHECK(ryml::emitrs_yaml<std::string>(t) ==
""
4047 "v3: (100,101,102)" "\n"
4048 "v4: (1000,1001,1002,1003)" "\n"
4056 root[
"v2"].
save(eov2in);
4057 root[
"v2"].
load(&pov2out);
4058 CHECK(eov2in.x == pov2out.x);
4059 CHECK(eov2in.y == pov2out.y);
4062 root[
"v3"].
save(eov3in);
4063 root[
"v3"].
load(&pov3out);
4064 CHECK(eov3in.x == pov3out.x);
4065 CHECK(eov3in.y == pov3out.y);
4066 CHECK(eov3in.z == pov3out.z);
4069 root[
"v4"].
save(eov4in);
4070 root[
"v4"].
load(&pov4out);
4071 CHECK(eov4in.x == pov4out.x);
4072 CHECK(eov4in.y == pov4out.y);
4073 CHECK(eov4in.z == pov4out.z);
4074 CHECK(ryml::emitrs_yaml<std::string>(t) ==
""
4076 "v3: (30,31,32)" "\n"
4077 "v4: (40,41,42,43)" "\n"
4147 Outer outer{{{0,1}, {2,3}}};
4153 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
4154 "- {foo: 0,bar: 1}\n"
4155 "- {foo: 2,bar: 3}\n");
4157 root.
load(&roundtrip);
4159 CHECK(0 == memcmp(&outer, &roundtrip,
sizeof(
Outer)));
4183 if(seq_member.size() == that.
seq_member.size())
4184 for(
size_t i = 0; i < seq_member.size(); ++i)
4189 template<
class K,
class V>
4196 if(map_member.size() == that.
map_member.size())
4200 auto it = map_member.find(itthat.first);
4201 CHECK(it != map_member.end());
4202 if(it != map_member.end())
4203 CHECK(it->second == itthat.second);
4270 template<
class K,
class V>
4333 template<
class K,
class V>
4430 {{101, 102, 103, 104, 105, 106, 107}},
4431 {{{1001, 2001}, {1002, 2002}, {1003, 2003}}},
4435 root_node.
save(orig);
4437 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
4439 "v3: (30,31,32)" "\n"
4440 "v4: (40,41,42,43)" "\n"
4458 root_node.
load(&roundtrip);
4465 tree.
load(root_id, &roundtrip);
4474 "a deer, a female deer",
4476 "a drop of golden sun"
4479 tree[
"not in arena"].
save(strseq);
4481 CHECK(ryml::emitrs_yaml<std::string>(tree[
"not in arena"]) ==
""
4483 "not in arena:" "\n"
4485 " - a deer, a female deer" "\n"
4487 " - a drop of golden sun" "\n"
4495 CHECK(child.val() == str_orig);
4497 CHECK(child.val().is_sub(str_orig));
4524 "v3: (30,31,32)" "\n"
4525 "v4: (40,41,42,43)" "\n"
4536 " 1002: not an int" "\n"
4546 CHECK(result.
node == tree[
"map"][
"1002"].id());
4566 std::string yml_std_string =
""
4567 "- v2: (20,21)" "\n"
4568 " v3: (30,31,32)" "\n"
4569 " v4: (40,41,42,43)" "\n"
4582 "- v2: (120,121)" "\n"
4583 " v3: (130,131,132)" "\n"
4584 " v4: (140,141,142,143)" "\n"
4594 " 11001: 12001" "\n"
4595 " 11002: 12002" "\n"
4596 " 11003: 12003" "\n"
4597 "- v2: (220,221)" "\n"
4598 " v3: (230,231,232)" "\n"
4599 " v4: (240,241,242,243)" "\n"
4609 " 21001: 22001" "\n"
4610 " 21002: 22002" "\n"
4611 " 21003: 22003" "\n"
4617 std::vector<my_type> vec;
4619 CHECK(vec.size() == 3);
4622 CHECK(ryml::emitrs_yaml<std::string>(tree_out) == yml_std_string);
4631 std::vector<double> reference{1.23234412342131234, 2.12323123143434237, 3.67847983572591234};
4635 const double precision_safe = 1.e-14;
4636 const size_t num_digits_safe = 14;
4637 const size_t num_digits_original = 17;
4638 auto get_num_digits = [](
ryml::csubstr number){
return number.len - 2u; };
4644 std::vector<double> output;
4646 CHECK(output.size() == reference.size());
4647 for(
size_t i = 0; i < reference.size(); ++i)
4650 CHECK(fabs(output[i] - reference[i]) < precision_safe);
4661 #if (!C4CORE_HAVE_STD_TOCHARS) // check if std::to_chars() is available.
4662 CHECK((ryml::emitrs_yaml<std::string>(serialized) ==
""
4666 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4667 C4_UNUSED(num_digits_safe);
4670 CHECK((ryml::emitrs_yaml<std::string>(serialized) ==
""
4671 "- 1.2323441234213124" "\n"
4672 "- 2.1232312314343424" "\n"
4673 "- 3.6784798357259123" "\n"
4674 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4678 CHECK(get_num_digits(child.val()) >= num_digits_safe);
4681 CHECK(fabs(out - reference[pos++]) < precision_safe);
4712 auto check_precision = [&](
ryml::Tree const& serialized){
4713 std::cout << serialized;
4715 CHECK((ryml::emitrs_yaml<std::string>(serialized) ==
""
4716 "- 1.23234412342131239" "\n"
4717 "- 2.12323123143434245" "\n"
4718 "- 3.67847983572591231" "\n"
4719 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4723 CHECK(get_num_digits(child.val()) == num_digits_original);
4726 CHECK(fabs(out - reference[pos++]) < precision_safe);
4735 for(
const double v : reference)
4737 check_precision(serialized);
4746 for(
const double v : reference)
4751 (void)snprintf(tmp,
sizeof(tmp),
"%.18g", v);
4757 check_precision(serialized);
4776 "- champagne: Dom Perignon" "\n"
4777 " coffee: Arabica" "\n"
4779 " vinho verde: Soalheiro" "\n"
4780 " vinho tinto: Redoma 2017" "\n"
4782 " - Rochefort 10" "\n"
4784 " - Leffe Rituel" "\n"
4803 size_t num_needed_chars = output.
len;
4804 std::vector<char> buf(num_needed_chars);
4807 CHECK(output == ymla);
4815 num_needed_chars = output.
len;
4816 buf.resize(num_needed_chars);
4819 CHECK(output == ymlb);
4824 CHECK(output == ymlb);
4828 std::vector<char> another = ryml::emitrs_yaml<std::vector<char>>(treeb);
4832 another = ryml::emitrs_yaml<std::vector<char>>(treeb[3][2]);
4835 " vinho verde: Soalheiro" "\n"
4836 " vinho tinto: Redoma 2017" "\n"
4849 size_t num_needed_chars = output.
len;
4851 buf.resize(num_needed_chars);
4854 CHECK(output == ymla);
4862 num_needed_chars = output.
len;
4863 buf.resize(num_needed_chars);
4866 CHECK(output == ymlb);
4871 CHECK(output == ymlb);
4875 std::string another = ryml::emitrs_yaml<std::string>(treeb);
4879 another = ryml::emitrs_yaml<std::string>(treeb[3][2]);
4882 " vinho verde: Soalheiro" "\n"
4883 " vinho tinto: Redoma 2017" "\n"
4899 "- champagne: Dom Perignon" "\n"
4900 " coffee: Arabica" "\n"
4902 " vinho verde: Soalheiro" "\n"
4903 " vinho tinto: Redoma 2017" "\n"
4905 " - Rochefort 10" "\n"
4907 " - Leffe Rituel" "\n"
4919 std::stringstream ss;
4927 std::stringstream ss;
4939 " \"champagne\": \"Dom Perignon\"," "\n"
4940 " \"coffee\": \"Arabica\"," "\n"
4942 " \"vinho verde\": \"Soalheiro\"," "\n"
4943 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4946 " \"Rochefort 10\"," "\n"
4948 " \"Leffe Rituel\"" "\n"
4961 std::stringstream ss;
4966 " vinho verde: Soalheiro" "\n"
4967 " vinho tinto: Redoma 2017" "\n"
4973 std::stringstream ss;
4978 " \"vinho verde\": \"Soalheiro\"," "\n"
4979 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4996 "- champagne: Dom Perignon" "\n"
4997 " coffee: Arabica" "\n"
4999 " vinho verde: Soalheiro" "\n"
5000 " vinho tinto: Redoma 2017" "\n"
5002 " - Rochefort 10" "\n"
5004 " - Leffe Rituel" "\n"
5027 "- champagne: Dom Perignon" "\n"
5028 " coffee: Arabica" "\n"
5030 " vinho verde: Soalheiro" "\n"
5031 " vinho tinto: Redoma 2017" "\n"
5033 " - Rochefort 10" "\n"
5035 " - Leffe Rituel" "\n"
5037 " - many other" "\n"
5038 " - wonderful beers" "\n"
5046 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"beer"]) ==
""
5048 " - Rochefort 10" "\n"
5050 " - Leffe Rituel" "\n"
5052 " - many other" "\n"
5053 " - wonderful beers" "\n"
5059 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"beer"], without_key) ==
""
5060 "- Rochefort 10" "\n"
5062 "- Leffe Rituel" "\n"
5064 " - many other" "\n"
5065 " - wonderful beers" "\n"
5069 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"beer"][3]) ==
""
5072 "- wonderful beers" "\n"
5076 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"beer"][3], with_dash) ==
""
5078 " - many other" "\n"
5079 " - wonderful beers" "\n"
5082 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"beer"][0]) ==
"Rochefort 10");
5083 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"beer"][0], with_dash) ==
"- Rochefort 10\n");
5085 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"more"][0]) ==
"vinho verde: Soalheiro\n");
5086 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"more"][0], without_key) ==
"Soalheiro");
5105 return ryml::emitrs_yaml<std::string>(n);
5108 return ryml::emitrs_yaml<std::string>(n, opts);
5113 " block key: block val" "\n"
5115 " - block val 1" "\n"
5116 " - block val 2" "\n"
5118 "flow map, singleline: {flow key: flow val}" "\n"
5119 "flow seq, singleline: [flow val,flow val]" "\n"
5120 "flow map, multiline: {" "\n"
5121 " flow key: flow val" "\n"
5123 "flow seq, multiline: [" "\n"
5131 CHECK(tree[
"block map"].is_key_plain());
5132 CHECK(tree[
"block seq"].is_key_plain());
5133 CHECK(tree[
"flow map, singleline"].is_key_plain());
5134 CHECK(tree[
"flow seq, singleline"].is_key_plain());
5135 CHECK(tree[
"flow map, multiline"].is_key_plain());
5136 CHECK(tree[
"flow seq, multiline"].is_key_plain());
5137 CHECK(tree[
"block map"].is_block());
5138 CHECK(tree[
"block seq"].is_block());
5140 CHECK(tree[
"flow map, singleline"].is_flow_sl());
5141 CHECK(tree[
"flow seq, singleline"].is_flow_sl());
5142 CHECK(tree[
"flow map, multiline"].is_flow_ml1());
5143 CHECK(tree[
"flow seq, multiline"].is_flow_ml1());
5145 CHECK(tree[
"flow map, singleline"].is_flow());
5146 CHECK(tree[
"flow seq, singleline"].is_flow());
5147 CHECK(tree[
"flow map, multiline"].is_flow());
5148 CHECK(tree[
"flow seq, multiline"].is_flow());
5154 CHECK(tostr(tree) == yaml);
5165 " block key: block val\n"
5172 "'block map': {block key: block val}\n"
5178 CHECK(tostr(n) ==
""
5187 CHECK(tostr(n) ==
""
5188 "\"block seq\": [\n"
5189 " block val 1,block val 2,quoted\n"
5192 CHECK(tostr(n) ==
""
5193 "\"block seq\": [\n"
5194 " block val 1, block val 2, quoted\n"
5197 CHECK(tostr_opts(n, maxcols20) ==
""
5198 "\"block seq\": [\n"
5199 " block val 1, block val 2,\n"
5203 CHECK(tostr_opts(n, maxcols20) ==
""
5204 "\"block seq\": [\n"
5205 " block val 1,block val 2,\n"
5209 CHECK(tostr(n) ==
""
5210 "\"block seq\": [block val 1,block val 2,quoted]\n");
5212 CHECK(tostr(n) ==
""
5213 "\"block seq\": [block val 1, block val 2, quoted]\n");
5215 CHECK(tostr(n) ==
""
5216 "\"block seq\": [\n"
5227 CHECK(tostr(n) ==
"flow map, singleline: {flow key: flow val}\n");
5230 CHECK(tostr(n) ==
""
5231 "flow map, singleline:\n"
5239 CHECK(tostr(n) ==
""
5240 "flow map, multiline: {\n"
5241 " flow key: flow val\n"
5245 CHECK(tostr(n) ==
""
5246 "flow map, multiline:\n"
5247 " flow key: flow val\n"
5253 CHECK(tostr(n) ==
"flow seq, singleline: [flow val,flow val]\n");
5258 CHECK(tostr(n) ==
""
5260 " flow seq, singleline\n"
5269 CHECK(tostr(n) ==
""
5270 "flow seq, multiline: [\n"
5276 CHECK(tostr(n) ==
"flow seq, multiline: [flow val,flow val]\n");
5279 CHECK(tostr(tree) != yaml);
5280 CHECK(tostr(tree) ==
5281 "'block map': {block key: block val}" "\n"
5282 "\"block seq\": [" "\n"
5283 " block val 1," "\n"
5284 " block val 2," "\n"
5287 "flow map, singleline:" "\n"
5288 " flow key: |-" "\n"
5291 " flow seq, singleline" "\n"
5293 " - 'flow val'" "\n"
5294 " - \"flow val\"" "\n"
5295 "flow map, multiline:" "\n"
5296 " flow key: flow val" "\n"
5297 "flow seq, multiline: [flow val,flow val]" "\n"
5302 CHECK(tostr(tree) ==
5304 " block key: block val" "\n"
5306 " - block val 1" "\n"
5307 " - block val 2" "\n"
5309 "flow map, singleline:" "\n"
5310 " flow key: |-" "\n"
5313 " flow seq, singleline" "\n"
5315 " - 'flow val'" "\n"
5316 " - \"flow val\"" "\n"
5317 "flow map, multiline:" "\n"
5318 " flow key: flow val" "\n"
5319 "flow seq, multiline: [flow val,flow val]" "\n"
5328 CHECK(tostr(tree) ==
5330 " block key: block val" "\n"
5332 " - block val 1" "\n"
5333 " - block val 2" "\n"
5335 "flow map, singleline:" "\n"
5336 " flow key: flow val" "\n"
5337 "flow seq, singleline:" "\n"
5340 "flow map, multiline:" "\n"
5341 " flow key: flow val" "\n"
5342 "flow seq, multiline:" "\n"
5353 CHECK(tostr(tree) ==
5355 " block key: block val" "\n"
5357 " - block val 1" "\n"
5358 " - block val 2" "\n"
5360 "flow map, singleline:" "\n"
5361 " flow key: flow val" "\n"
5362 "flow seq, singleline:" "\n"
5365 "flow map, multiline:" "\n"
5366 " flow key: flow val" "\n"
5367 "flow seq, multiline:" "\n"
5392 CHECK(tostr(tree) ==
""
5394 " 'block key': \"block val\"" "\n"
5395 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
5396 "'flow map, singleline':" "\n"
5397 " 'flow key': \"flow val\"" "\n"
5398 "'flow seq, singleline': [\"flow val\",\"flow val\"]" "\n"
5399 "'flow map, multiline':" "\n"
5400 " 'flow key': \"flow val\"" "\n"
5401 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
5408 CHECK(tostr(tree) ==
""
5410 " 'block key': \"block val\"" "\n"
5411 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
5412 "'flow map, singleline':" "\n"
5413 " 'flow key': \"flow val\"" "\n"
5414 "'flow seq, singleline':" "\n"
5415 " - \"flow val\"" "\n"
5416 " - \"flow val\"" "\n"
5417 "'flow map, multiline':" "\n"
5418 " 'flow key': \"flow val\"" "\n"
5419 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
5438 return ryml::emitrs_yaml<std::string>(n, opts);
5441 return ryml::emitrs_json<std::string>(n, opts);
5462 CHECK(tree[
"map"].is_flow_ml1());
5463 CHECK(tree[
"map"][
"seq"].is_flow_ml1());
5464 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
5466 CHECK(tostr(tree, emit_defaults) == yaml);
5468 CHECK(tostr_json(tree, emit_defaults) ==
5489 CHECK(tree[
"map"].is_flow_sl());
5491 CHECK(tostr(tree, emit_defaults) ==
5492 "{map: {seq: [0,1,2,3,[40,41]]}}");
5494 CHECK(tostr_json(tree, emit_defaults) ==
5495 "{\"map\": {\"seq\": [0,1,2,3,[40,41]]}}");
5500 CHECK(tostr(tree, with_spaces) ==
5501 "{map: {seq: [0, 1, 2, 3, [40, 41]]}}");
5503 CHECK(tostr_json(tree, with_spaces) ==
5504 "{\"map\": {\"seq\": [0, 1, 2, 3, [40, 41]]}}");
5513 CHECK(tree[
"map"].is_flow_mln());
5514 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
5515 CHECK(tostr(tree, emit_defaults) ==
5519 " 0,1,2,3,[40,41]" "\n"
5523 CHECK(tostr_json(tree, emit_defaults) ==
5527 " 0,1,2,3,[40,41]" "\n"
5534 CHECK(tostr(tree, with_spaces) ==
5538 " 0, 1, 2, 3, [40, 41]" "\n"
5542 CHECK(tostr_json(tree, with_spaces) ==
5546 " 0, 1, 2, 3, [40, 41]" "\n"
5557 CHECK(tree[
"map"].is_flow_ml1());
5558 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
5559 CHECK(tostr(tree, noindent) ==
""
5572 CHECK(tostr_json(tree, noindent) ==
""
5591 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9," "\n"
5592 " 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, " "\n"
5593 " 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, " "\n"
5594 " 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, " "\n"
5595 " 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, " "\n"
5596 " 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, " "\n"
5597 " 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, " "\n"
5598 " 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 " "\n"
5609 CHECK(tostr(tree, emit_defaults) ==
""
5611 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,\n"
5612 " 30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,\n"
5613 " 56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79\n"
5616 CHECK(tostr_json(tree, emit_defaults) ==
""
5618 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
5619 " 29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
5620 " 55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79\n"
5626 CHECK(tostr(tree, maxcols40) ==
""
5628 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
5629 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
5630 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
5631 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
5632 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
5633 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
5636 CHECK(tostr_json(tree, maxcols40) ==
""
5638 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
5639 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
5640 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
5641 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
5642 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
5643 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
5650 CHECK(tostr(tree, with_spaces) ==
""
5652 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5653 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5654 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5655 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
5658 CHECK(tostr_json(tree, with_spaces) ==
""
5660 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5661 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5662 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5663 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
5670 CHECK(tostr(tree, maxcols40_spc) ==
""
5672 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
5673 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5674 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
5675 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5676 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
5677 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5678 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
5679 " 72, 73, 74, 75, 76, 77, 78, 79\n"
5682 CHECK(tostr_json(tree, maxcols40_spc) ==
""
5684 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
5685 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5686 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
5687 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5688 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
5689 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5690 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
5691 " 72, 73, 74, 75, 76, 77, 78, 79\n"
5699 CHECK(tostr(tree, maxcols40_spc_noindent) ==
""
5701 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
5702 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
5703 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
5704 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
5705 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
5706 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
5707 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
5708 "73, 74, 75, 76, 77, 78, 79\n"
5711 CHECK(tostr_json(tree, maxcols40_spc_noindent) ==
""
5713 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
5714 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
5715 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
5716 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
5717 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
5718 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
5719 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
5720 "73, 74, 75, 76, 77, 78, 79\n"
5737 return ryml::emitrs_yaml<std::string>(n, opts);
5739 ryml::csubstr yaml =
"{map: {seq: [0, 1, 2, 3, [40, 41]]}}";
5743 CHECK(tostr(tree, defaults) ==
"{map: {seq: [0,1,2,3,[40,41]]}}");
5750 CHECK(tostr(tree, defaults) ==
5768 CHECK(tostr(tree, noindent) ==
5787 CHECK(tostr(tree, noindent) ==
""
5803 CHECK(tostr(tree, noindent) ==
5829 " \"doe\": \"a deer, a female deer\"," "\n"
5830 " \"ray\": \"a drop of golden sun\"," "\n"
5831 " \"me\": \"a name, I call myself\"," "\n"
5832 " \"far\": \"a long long way to go\"" "\n"
5843 CHECK(ryml::emitrs_json<std::string>(tree) == json);
5844 CHECK(ryml::emitrs_json<std::string>(json_tree) == json);
5846 std::stringstream ss;
5848 CHECK(ss.str() == json);
5867 CHECK(ryml::emitrs_yaml<std::string>(json_tree) == json);
5872 CHECK(ryml::emitrs_yaml<std::string>(json_tree) ==
""
5873 "\"doe\": \"a deer, a female deer\"" "\n"
5874 "\"ray\": \"a drop of golden sun\"" "\n"
5875 "\"me\": \"a name, I call myself\"" "\n"
5876 "\"far\": \"a long long way to go\"" "\n"
5882 CHECK(ryml::emitrs_yaml<std::string>(json_tree) ==
""
5883 "doe: a deer, a female deer" "\n"
5884 "ray: a drop of golden sun" "\n"
5885 "me: a name, I call myself" "\n"
5886 "far: a long long way to go" "\n"
5916 std::string unresolved =
""
5918 " name: Everyone has same name" "\n"
5925 "bill_to: &id001" "\n"
5927 " 123 Tornado Alley" "\n"
5929 " city: East Centerville" "\n"
5931 "ship_to: *id001" "\n"
5932 "&keyref key: &valref val" "\n"
5933 "*valref : *keyref" "\n"
5935 std::string resolved =
""
5937 " name: Everyone has same name" "\n"
5939 " name: Everyone has same name" "\n"
5942 " name: Everyone has same name" "\n"
5946 " 123 Tornado Alley" "\n"
5948 " city: East Centerville" "\n"
5952 " 123 Tornado Alley" "\n"
5954 " city: East Centerville" "\n"
5962 CHECK( ! tree[
"base"].has_key_anchor());
5963 CHECK( tree[
"base"].has_val_anchor());
5964 CHECK( tree[
"base"].val_anchor() ==
"base");
5965 CHECK( tree[
"key"].key_anchor() ==
"keyref");
5966 CHECK( tree[
"key"].val_anchor() ==
"valref");
5967 CHECK( tree[
"*valref"].is_key_ref());
5968 CHECK( tree[
"*valref"].is_val_ref());
5969 CHECK( tree[
"*valref"].key_ref() ==
"valref");
5970 CHECK( tree[
"*valref"].val_ref() ==
"keyref");
5977 CHECK( ! tree[
"base"].has_key_anchor());
5978 CHECK( ! tree[
"base"].has_val_anchor());
5979 CHECK( ! tree[
"base"].has_val_anchor());
5980 CHECK( ! tree[
"key"].has_key_anchor());
5981 CHECK( ! tree[
"key"].has_val_anchor());
5982 CHECK( ! tree[
"val"].is_key_ref());
5983 CHECK( ! tree[
"val"].is_val_ref());
5985 CHECK(tree[
"ship_to"][
"city"].val() ==
"East Centerville");
5986 CHECK(tree[
"ship_to"][
"state"].val() ==
"KS");
6004 t[
"nref"].
set_val(
"*vanchor");
6005 CHECK(ryml::emitrs_yaml<std::string>(t) ==
""
6006 "&kanchor kanchor: 2" "\n"
6007 "vanchor: &vanchor 3" "\n"
6008 "kref: *kanchor" "\n"
6009 "vref: *vanchor" "\n"
6012 "nref: '*vanchor'" "\n"
6015 CHECK(ryml::emitrs_yaml<std::string>(t) ==
""
6018 "kref: kanchor" "\n"
6021 "nref: '*vanchor'" "\n"
6028 "orig: &orig {foo: bar, baz: bat}" "\n"
6036 t[
"notref"][
"<<"].
set_val(
"*orig");
6037 CHECK(ryml::emitrs_yaml<std::string>(t) ==
""
6038 "orig: &orig {foo: bar,baz: bat}" "\n"
6039 "copy: {<<: *orig}" "\n"
6040 "notcopy: {test: *orig,<<: *orig}" "\n"
6041 "notref: {<<: '*orig'}" "\n"
6044 CHECK(ryml::emitrs_yaml<std::string>(t) ==
""
6045 "orig: {foo: bar,baz: bat}" "\n"
6046 "copy: {foo: bar,baz: bat}" "\n"
6047 "notcopy: {test: {foo: bar,baz: bat},foo: bar,baz: bat}" "\n"
6048 "notref: {<<: '*orig'}" "\n"
6055 "orig1: &orig1 {foo: bar}" "\n"
6056 "orig2: &orig2 {baz: bat}" "\n"
6057 "orig3: &orig3 {and: more}" "\n"
6065 CHECK(ryml::emitrs_yaml<std::string>(t) ==
""
6066 "orig1: &orig1 {foo: bar}" "\n"
6067 "orig2: &orig2 {baz: bat}" "\n"
6068 "orig3: &orig3 {and: more}" "\n"
6069 "copy: {<<: [*orig1,*orig2,*orig3]}" "\n"
6072 CHECK(ryml::emitrs_yaml<std::string>(t) ==
""
6073 "orig1: {foo: bar}" "\n"
6074 "orig2: {baz: bat}" "\n"
6075 "orig3: {and: more}" "\n"
6076 "copy: {foo: bar,baz: bat,and: more}" "\n");
6085 const std::string yaml =
""
6094 "--- !!str a b" "\n"
6095 "--- !!str 'a: b'" "\n"
6112 CHECK(doc.is_doc());
6114 CHECK(root[0].has_val_tag());
6115 CHECK(root[0].val_tag() ==
"!!map");
6116 CHECK(root[1].val_tag() ==
"!map");
6117 CHECK(root[2].val_tag() ==
"!!seq");
6118 CHECK(root[3].val_tag() ==
"!!str");
6119 CHECK(root[4].val_tag() ==
"!!str");
6120 CHECK(root[5][
"a"].has_key_tag());
6121 CHECK(root[5][
"a"].key_tag() ==
"!!str");
6122 CHECK(root[6].val_tag() ==
"!!set");
6123 CHECK(root[7].val_tag() ==
"!!set");
6124 CHECK(root[8].val_tag() ==
"!!seq");
6125 CHECK(root[8][0].val_tag() ==
"!!int");
6126 CHECK(root[8][1].val_tag() ==
"!!str");
6175 CHECK(ryml::emitrs_yaml<std::string>(normalized_tree) ==
""
6184 "--- !!str a b" "\n"
6185 "--- !!str 'a: b'" "\n"
6199 CHECK(ryml::emitrs_yaml<std::string>(normalized_tree_long) ==
""
6200 "--- !<tag:yaml.org,2002:map>" "\n"
6205 "--- !<tag:yaml.org,2002:seq>" "\n"
6208 "--- !<tag:yaml.org,2002:str> a b" "\n"
6209 "--- !<tag:yaml.org,2002:str> 'a: b'" "\n"
6211 "!<tag:yaml.org,2002:str> a: b" "\n"
6212 "--- !<tag:yaml.org,2002:set>" "\n"
6215 "--- !<tag:yaml.org,2002:set>" "\n"
6217 "--- !<tag:yaml.org,2002:seq>" "\n"
6218 "- !<tag:yaml.org,2002:int> 0" "\n"
6219 "- !<tag:yaml.org,2002:str> 1" "\n"
6228 const std::string yaml =
""
6229 "%TAG !m! !my-" "\n"
6230 "--- # Bulb here" "\n"
6231 "!m!light fluorescent" "\n"
6233 "%TAG !m! !meta-" "\n"
6234 "--- # Color here" "\n"
6235 "!m!light green" "\n"
6239 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
6240 "%TAG !m! !my-" "\n"
6241 "--- !m!light fluorescent" "\n"
6243 "%TAG !m! !meta-" "\n"
6244 "--- !m!light green" "\n"
6250 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
""
6251 "%TAG !m! !my-" "\n"
6252 "--- !<!my-light> fluorescent" "\n"
6254 "%TAG !m! !meta-" "\n"
6255 "--- !<!meta-light> green" "\n"
6261 CHECK(ryml::emitrs_yaml<std::string>(resolved_tree) ==
""
6262 "%TAG !m! !my-" "\n"
6263 "--- !<!my-light> fluorescent" "\n"
6265 "%TAG !m! !meta-" "\n"
6266 "--- !<!meta-light> green" "\n"
6291 CHECK(ryml::emitrs_yaml<std::string>(tree) == yml);
6302 CHECK(doc.is_doc());
6321 CHECK(stream[0].is_doc());
6322 CHECK(stream[0].is_map());
6323 CHECK(stream[0][
"a"].val() ==
"0");
6324 CHECK(stream[0][
"b"].val() ==
"1");
6333 CHECK(stream[1].is_doc());
6334 CHECK(stream[1].is_map());
6335 CHECK(stream[1][
"c"].val() ==
"2");
6336 CHECK(stream[1][
"d"].val() ==
"3");
6345 CHECK(stream[2].is_doc());
6346 CHECK(stream[2].is_seq());
6347 CHECK(stream[2][0].val() ==
"4");
6348 CHECK(stream[2][1].val() ==
"5");
6349 CHECK(stream[2][2].val() ==
"6");
6350 CHECK(stream[2][3].val() ==
"7");
6362 CHECK(ryml::emitrs_json<std::string>(tree) ==
6388 return ryml::emitrs_json<std::string>(err_tree, err_opts);
6392 const std::string expected_json[] = {
6414 CHECK(ryml::emitrs_json<std::string>(doc, err_opts) == expected_json[count++]);
6451 ryml::Tree tree = ryml::parse_in_arena(
"errorhandler.yml",
"[a: b\n}");
6462 auto cause_basic_error = []{
6471 #ifdef RYML_WITH_EXCEPTIONS_
6475 cause_basic_error();
6497 auto cause_parse_error = [&]{
6521 msg_ctx.append(s.
str, s.
len);
6523 CHECK(
ryml::to_csubstr(msg_ctx).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
6525 "file.yml:3: col=4 (12B): err:" "\n"
6531 "err: see region:" "\n"
6566 CHECK(errh.
saved_msg_full ==
"file.yml:3: col=4 (12B): ERROR: [basic] invalid character: '['");
6579 #ifdef RYML_WITH_EXCEPTIONS_
6583 cause_parse_error();
6595 CHECK(msg ==
"invalid character: '['");
6600 auto dumpfn = [&full](
ryml::csubstr s) { full.append(s.str, s.len); };
6604 CHECK(
ryml::to_csubstr(full).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
6606 "file.yml:3: col=4 (12B): err:" "\n"
6612 "err: see region:" "\n"
6625 cause_parse_error();
6651 tree[
"float"].load(&intval);
6680 tree[
"float"].load(&intval);
6692 #ifdef RYML_WITH_EXCEPTIONS_
6704 tree[
"float"].
load(&intval);
6725 tree[
"float"].
load(&intval);
6762 "float: 123.456" "\n"
6766 auto cause_visit_error = [&]{
6768 tree[
"float"].
load(&intval);
6794 CHECK(ymlloc.name == ymlfile);
6800 msg.append(s.
str, s.
len);
6801 }, ymlloc, ymlsrc,
"err", 3);
6803 "file.yml:3: col=0 (24B): err:" "\n"
6805 "err: float: 123.456" "\n"
6809 "err: see region:" "\n"
6811 "err: foo: bar" "\n"
6814 "err: float: 123.456" "\n"
6855 uintptr_t uptr = (uintptr_t)ptr;
6856 const uintptr_t align =
alignof(max_align_t);
6859 uintptr_t prev = uptr - (uptr % align);
6860 uintptr_t next = prev + align;
6861 uintptr_t corr = next - uptr;
6862 ptr = (
void*)(((
char*)ptr) + corr);
6866 "out of memory! requested=%zu+%zu available=%zu\n",
6873 CHECK((
char*)mem >= &memory_pool.front() && (
char*)mem < &memory_pool.back());
6874 CHECK((
char*)mem+len >= &memory_pool.front() && (
char*)mem+len <= &memory_pool.back());
6892 static void s_free(
void *mem,
size_t len,
void *this_)
6905 std::cout <<
"count: #allocs=" << num_allocs <<
" #deallocs=" << num_deallocs << std::endl;
6906 CHECK(num_allocs == num_deallocs);
6964 parse_in_arena(&parser,
"", R
"([a, b, c, d, {foo: bar, money: pennys}])", &tree);
7005 if C4_UNLIKELY(
alloc_size > memory_pool.size())
7007 std::cerr <<
"out of memory! requested=" <<
alloc_size <<
" vs " << memory_pool.size() <<
" available" << std::endl;
7015 CHECK((
char*)mem >= &memory_pool.front() && (
char*)mem < &memory_pool.back());
7016 CHECK((
char*)mem+len >= &memory_pool.front() && (
char*)mem+len <= &memory_pool.back());
7030 std::cout <<
"count: #allocs=" << num_allocs <<
" #deallocs=" << num_deallocs << std::endl;
7031 CHECK(num_allocs == num_deallocs);
7093 CHECK(tree["doe"].val() ==
"a deer, a female deer");
7106 static int num_checks = 0;
7107 static int num_failed_checks = 0;
7108 static bool quiet_mode =
false;
7113 auto arg_matches = [](
const char *arg,
const char *shortform,
const char *longform) {
7114 return (0 == strcmp(arg, shortform) || 0 == strcmp(arg, longform));
7116 for(
int i = 1; i < argc; ++i)
7117 if(arg_matches(argv[i],
"-q",
"--quiet"))
7124 const char *msg = predicate ?
"OK! " :
"OK!";
7127 ++num_failed_checks;
7128 msg = predicate ?
"FAIL: " :
"FAIL";
7130 if(!result || !quiet_mode)
7132 std::cout << __FILE__ <<
':' << line <<
": " << msg << (predicate ? predicate :
"") << std::endl;
7140 std::cout <<
"Completed " << num_checks <<
" checks." << std::endl;
7141 if(num_failed_checks)
7142 std::cout <<
"ERROR: " << num_failed_checks <<
'/' << num_checks <<
" checks failed." << std::endl;
7144 std::cout <<
"SUCCESS!" << std::endl;
7145 return num_failed_checks;
7160 fwrite(s.
str, 1, s.
len, stderr);
7166 fputc(
'\n', stderr);
7181 .set_free([](
void* mem,
size_t,
void *){
7219 #ifdef RYML_NO_DEFAULT_CALLBACKS
7228 #ifndef C4_EXCEPTIONS
7252 RYML_SAVE_TEST_EXPFAIL_();
7260 bool got_error =
false;
7261 #ifdef C4_EXCEPTIONS
7264 std::forward<Fn>(fn)();
7266 catch(std::exception
const&)
7271 if(setjmp(s_jmp_env) == 0)
7273 std::forward<Fn>(fn)();
7286 [[noreturn]]
void stopexec(std::string
const& s)
7288 #ifdef C4_EXCEPTIONS
7289 throw std::runtime_error(s);
7292 std::longjmp(s_jmp_env, 1);
7413 C4_SUPPRESS_WARNING_GCC_CLANG_POP
void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *tree, id_type node_id)
(1) parse JSON into an existing tree node. The filename will be used in any error messages arising du...
csubstr const & key(id_type node) const
csubstr const & val(id_type node) const
print the real number in hexadecimal format (like a)
bool is_seed() const noexcept
true if the object is not invalid and in seed state.
void on_error_parse(ryml::csubstr msg, ryml::ErrorDataParse const &errdata)
this is where the callback implementation goes.
bool indent_flow_ml() const noexcept
Indent the contents of FLOW_ML1 and FLOW_MLN containers.
void set_val(id_type node, csubstr val) RYML_NOEXCEPT
void sample_fundamental_types()
serialize/deserialize fundamental types
mark val scalar as plain scalar (unquoted, even when multiline)
basic_substring trimr(const C c) const
trim the character c from the right
void sample_style_flow_ml_indent()
control indentation of FLOW_ML1 and FLOW_MLN containers
bool invalid() const noexcept
true if the object is not referring to any existing or seed node.
bool is_key_plain() const RYML_NOEXCEPT
Forward to Tree::is_key_plain().
bool scalar_is_null(csubstr s) noexcept
YAML-sense query of nullity.
ConstNodeRef last_sibling() const RYML_NOEXCEPT
Forward to Tree::last_sibling().
bool is_doc(id_type node) const
~ScopedErrorHandlerExample()
ryml::Location saved_basic_loc
bool begins_with_any(ro_substr chars) const noexcept
true if the first character of the string is any of the given chars
basic_substring trim(const C c) const
trim the character c left and right
bool is_super(ro_substr const that) const noexcept
true if that is a substring of *this (ie, from the same buffer)
void check_disabled() const
test that this handler is currently not set
Location cpploc
location in the C++ source file where the error was detected.
void sample_user_container_types()
serialize/deserialize container (map or seq) types
Callbacks & set_error_parse(pfn_error_parse error_parse=nullptr)
Set or reset the error_parse callback.
example user container type: map-like
void load_key(id_type node, 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...
id_type first_child(id_type node) const
basic_substring stripr(ro_substr pattern) const
remove a pattern from the right
void sample_error_visit_location()
obtaining the YAML location from a visit error
bool is_map() const RYML_NOEXCEPT
Forward to Tree::is_map().
static void s_error_basic(ryml::csubstr msg, ryml::ErrorDataBasic const &errdata, void *this_)
trampoline function to call the object's method
void sample_error_basic()
handler for basic errors, and obtain a full error message with basic context
void check_enabled() const
test that this handler is currently set
mark key scalar as double quoted "
size_t offset
number of bytes from the beginning of the source buffer
bool overlaps(ro_substr const that) const noexcept
true if there is overlap of at least one element between that and *this
my_map_type< int, int > map
A lightweight truthy type, used to enable reporting the offending node when a deserializing error hap...
Callbacks & set_allocate(pfn_allocate allocate=nullptr)
Set or reset the allocate callback.
ParserOptions & detect_flow_ml(bool enabled) noexcept
enable/disable detection of flow multiline container style.
!!float Mathematical integers.
substr copy_to_arena(csubstr s)
copy the given string to the tree's arena, growing the arena by the required size.
void catseprs(CharOwningContainer *cont, Sep const &sep, Args const &...args)
catsep+resize: like c4::catsep(), but receives a container, and resizes it as needed to contain the r...
void * allocate(size_t len)
id_type num_siblings() const RYML_NOEXCEPT
O(num_children).
bool is_stream(id_type node) const
size_t uncatsep(csubstr buf, csubstr sep, Arg &a, Args &...more)
deserialize the arguments from the given buffer, using a separator.
Callbacks & set_free(pfn_free free=nullptr)
Set or reset the free callback.
mark val scalar as single quoted '
ryml::Callbacks callbacks()
a helper to create the Callbacks object for the custom error handler
void location_format_with_context(DumpFn &&dumpfn, Location const &location, csubstr source_buffer, csubstr call, size_t num_lines_before, size_t num_lines_after, size_t first_col_highlight, size_t last_col_highlight, size_t maxlen)
Generic formatting of a location, printing the source code buffer region around the location...
Location location(Parser const &parser) const
void normalize_tags_long()
bool is_seq() const RYML_NOEXCEPT
Forward to Tree::is_seq().
example scalar type, serialized and deserialized
ConstNodeRef parent() const RYML_NOEXCEPT
Forward to Tree::parent().
bool check_assertion_occurs(Fn &&fn)
checking that an assertion occurs while calling fn.
bool is_root() const RYML_NOEXCEPT
Forward to Tree::is_root().
void set_map(id_type node) RYML_NOEXCEPT
ConstNodeRef last_child() const RYML_NOEXCEPT
Forward to Tree::last_child().
void sample_emit_nested_node()
pick a nested node as the root when emitting
void sample_error_parse()
handler for parse errors, and obtain a full error message with parse context
print the real number in flexible format (like g)
substr emitrs_yaml(Tree const &t, id_type id, EmitOptions const &opts, CharOwningContainer *cont, bool append=false)
(1) emit+resize: emit YAML to the given std::string/std::vector-like container, resizing it as needed to fit the emitted YAML.
void * allocate(size_t len)
void sample_lightning_overview()
lightning overview of most common features
void reserve_stack(id_type capacity)
Reserve a certain capacity for the parsing stack.
example scalar type, serialized only
Shows how to create a scoped error handler.
The event handler to create a ryml Tree.
print the real number in scientific format (like e)
size_t to_chars(ryml::substr buf, vec2< T > v)
id_type id() const noexcept
children_view children() RYML_NOEXCEPT
get an iterable view over children
bool is_flow_mln() const noexcept
void set_callbacks(Callbacks const &c)
set the global callbacks for the library; after a call to this function, these callbacks will be used...
csubstr name
name of the file
C * str
a restricted pointer to the first character of the substring
size_t first_of(const C c, size_t start=0) const
example scalar type, serialized and deserialized
an example for a per-tree memory allocator
void sample_substr()
about ryml's string views (from c4core)
A c-style callbacks class to customize behavior on errors or allocation.
Callbacks & set_user_data(void *user_data)
Set the user data.
Exception thrown by the default visit error implementation.
void sample_anchors_and_aliases_create()
how to create YAML anchors and aliases
void sample_parse_in_arena()
parse a read-only YAML source buffer
void sample_iterate_tree()
visit individual nodes and iterate through trees
Exception thrown by the default basic error implementation.
auto fill(C val) -> typename std::enable_if< !std::is_const< U >::value, void >::type
fill the entire contents with the given val
void set_val_ref(id_type node, csubstr ref)
bool ends_with(const C c) const noexcept
true if the last character of the string is c
id_type first_sibling(id_type node) const
void check_eq(my_seq_type const &that) const
void load(id_type node, T *v, bool check_readable=true) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
bool has_key() const RYML_NOEXCEPT
Forward to Tree::has_key().
substr to_substr(char(&s)[N]) noexcept
void sample_create_tree_style()
set node styles while creating trees
void sample_parse_reuse_parser()
reuse an existing parser
ryml::Location saved_parse_loc
integral_< intptr_t > hex(std::nullptr_t)
format null as an hexadecimal value
mask of CONTAINER_STYLE_FLOW|CONTAINER_STYLE_BLOCK : all container style flags
void load(T *v, bool check_readable=true) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
void check_eq(my_type const &that) const
basic_substring right_of(size_t pos) const noexcept
return [pos+1, len[
mark val scalar as double quoted "
Location ymlloc
location in the YAML source buffer where the error was detected.
bool is_doc() const RYML_NOEXCEPT
Forward to Tree::is_doc().
std::string saved_msg_full
void catrs(CharOwningContainer *cont, Args const &...args)
cat+resize: like c4::cat(), but receives a container, and resizes it as needed to contain the result...
auto replace(C value, C repl, size_t pos=0) -> typename std::enable_if< !std::is_const< U >::value, size_t >::type
replace every occurrence of character value with the character repl
bool is_map(id_type node) const
std::map< K, V > map_member
bool invalid() const noexcept
const_raw_wrapper craw(cblob data, size_t alignment=alignof(max_align_t))
mark a variable to be written in raw binary format, using memcpy
void sample_serialize_basic()
serialize/deserialize fundamental types
csubstr arena() const
get the current arena
void sample_parse_style()
shows how rapidyaml retains the style of parsed YAML
size_t cat(substr buf, Arg const &a, Args const &...more)
serialize the arguments, concatenating them to the given fixed-size buffer.
std::vector< char > memory_pool
Accelerator structure to reduce memory requirements by enabling reuse of resolved tags...
ConstNodeRef next_sibling() const RYML_NOEXCEPT
Forward to Tree::next_sibling().
ErrorDataVisit errdata_visit
void set_key_serialized(id_type node, T const &key) RYML_NOEXCEPT
print the real number in floating point format (like f)
basic_substring first(size_t num) const noexcept
return the first num elements: [0,num[
mark container with multi-line flow style, n elements per line, < wrapped (as set by EmitOptions::max...
void sample_per_tree_allocator()
set per-tree allocators
std::vector< T > seq_member
void sample_docs()
deal with YAML docs
id_type doc(id_type i) const
gets the i document node index.
Location cpploc
location in the C++ source file where the error was detected.
Tree const * tree
tree where the error was detected
void sample_tree_arena()
interact with the tree's serialization arena
void sample_std_types()
serialize/deserialize STL containers
id_type num_children() const RYML_NOEXCEPT
O(num_children).
void err_visit_format(DumpFn &&dumpfn, csubstr msg, ErrorDataVisit const &errdata)
Given an error message and associated visit error data, format it fully as a visit error message...
static void s_error_parse(ryml::csubstr msg, ryml::ErrorDataParse const &errdata, void *this_)
trampoline function to call the object's method
ReadResult deserialize(T *v) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
size_t last_not_of(const C c) const
real_< T > real(T val, int precision, RealFormat_e fmt=FTOA_FLOAT)
void set_val(csubstr val)
example scalar type, serialized and deserialized
example scalar type, deserialized only
void set_key_tag(id_type node, csubstr tag)
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...
void sample_parse_reuse_tree_and_parser()
how to reuse existing trees and parsers
ConstNodeRef first_sibling() const RYML_NOEXCEPT
Forward to Tree::first_sibling().
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 ...
ConstNodeRef first_child() const RYML_NOEXCEPT
Forward to Tree::first_child().
ErrorDataBasic errdata_basic
error data
bool from_chars(ryml::csubstr buf, vec2< T > *v)
a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or S...
size_t last_of(const C c, size_t start=npos) const
example scalar type, serialized only
ConstNodeRef crootref() const
Get the root as a ConstNodeRef . Note that Tree implicitly converts to ConstNodeRef.
ScopedErrorHandlerExample()
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
id_type append_child(id_type parent)
create and insert a node as the last child of parent
Location location
location where the error was detected (may be from YAML or C++ source code)
ParserOptions const & options() const
Get the options used to build this parser object.
size_t arena_capacity() const
get the current capacity of the tree's internal arena
integral_< intptr_t > bin(std::nullptr_t)
format null as a binary 0-1 value
csubstr from_tag(YamlTag_e tag)
ryml::id_type saved_visit_id
Callbacks & set_error_basic(pfn_error_basic error_basic=nullptr)
Set or reset the error_basic callback.
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...
size_t size() const noexcept
const char * what() const noexcept override
basic_substring stripl(ro_substr pattern) const
remove a pattern from the left
Options to give to the ParseEngine to control its behavior.
void set_val_anchor(id_type node, csubstr anchor)
ryml::Callbacks original_callbacks
ReadResult deserialize_child(csubstr child_key, T *v) const
(1) find a child by name and deserialize its contents to the given variable (ie call ...
integral_< intptr_t > oct(std::nullptr_t)
format null as an octal value
void resolve(ReferenceResolver *rr, bool clear_anchors=true)
Resolve references (aliases <- anchors), by forwarding to ReferenceResolver::resolve(); refer to Refe...
mark val scalar as multiline, block folded >
id_type num_children(id_type node) const
O(num_children)
void sample_style()
query/set node styles
std::string saved_msg_full_with_context
void sample_user_container_types_brief()
serialize/deserialize container (map or seq) types: brief version
mark key scalar as multiline, block folded >
void reserve_locations(size_t num_source_lines)
Reserve a certain capacity for the array used to track node locations in the source buffer...
void sample_create_tree()
programatically create trees
auto reverse() -> typename std::enable_if< !std::is_const< U >::value, void >::type
reverse in place
csubstr normalize_tag_long(csubstr tag)
size_t count(const C c, size_t pos=0) const
count the number of occurrences of c
void * m_user_data
data to be forwarded in every call to a callback
auto reverse_sub(size_t ifirst, size_t num) -> typename std::enable_if< !std::is_const< U >::value, void >::type
revert a subpart in place
void reserve_arena(size_t arena_cap=RYML_DEFAULT_TREE_ARENA_CAPACITY)
ensure the tree's internal string arena is at least the given capacity
bool in_arena(csubstr s) const
return true if the given substring is part of the tree's string arena
basic_substring sub(size_t first) const noexcept
return [first,len[
bool is_seq(id_type node) const
void clear_style(id_type node, bool recurse=false)
bool is_block() const RYML_NOEXCEPT
Forward to Tree::is_block().
csubstr from_tag_long(YamlTag_e tag)
pfn_error_parse m_error_parse
a pointer to a parse error handler function
void sample_formatting()
control formatting when serializing/deserializing
Callbacks const & callbacks() const
csubstr to_csubstr(const char(&s)[N]) noexcept
id_type id() const noexcept
EmitOptions & emit_nonroot_dash(bool enabled) noexcept
When emit starts on a nested (non-root) node, emit a leading dash.
void sample_static_trees()
how to use static trees in ryml
csubstr normalize_tag(csubstr tag)
EmitOptions & force_flow_spc(bool enabled) noexcept
Force everywhere a space after comma in flow mode, overriding the FLOW_SPC status of individual conta...
bool is_stream() const RYML_NOEXCEPT
Forward to Tree::is_stream().
basic_substring< char > substr
a mutable string view
basic_substring< const char > csubstr
an immutable string view
substr cat_sub(substr buf, Args const &...args)
like c4::cat() but return a substr instead of a size
static void s_error_visit(ryml::csubstr msg, ryml::ErrorDataVisit const &errdata, void *this_)
trampoline function to call the object's method
bool readable() const noexcept
because a ConstNodeRef cannot be used to write to the tree, readable() has the same meaning as !inval...
pfn_free m_free
a pointer to a free handler function
holds a source or yaml file position, for example when an error is detected; See also location_format...
void sample_anchors_and_aliases()
deal with YAML anchors and aliases
ryml::Callbacks callbacks() const
csubstr catrs_append(CharOwningContainer *cont, Args const &...args)
cat+resize+append: like c4::cat(), but receives a container, and appends to it instead of overwriting...
ReadResult deserialize(id_type node, T *v) const
(1) deserialize a node's contents to a variable
ParserOptions & resolve_tags(bool enabled) noexcept
enable/disable resolution of YAML tags during parsing.
#define CHECK(predicate)
a testing assertion, used only in this quickstart
example scalar type, deserialized only
id_type child(id_type node, id_type pos) const
find child by position, or NONE if there are less than pos children posi
mark container with block style < - seqs as <
ConstNodeRef prev_sibling() const RYML_NOEXCEPT
Forward to Tree::prev_sibling().
Definitions of error utilities used by ryml.
basic_substring offs(size_t left, size_t right) const noexcept
offset from the ends: return [left,len-right[ ; ie, trim a number of characters from the left and rig...
auto toupper() -> typename std::enable_if< !std::is_const< U >::value, void >::type
convert the string to upper-case
Holds a pointer to an existing tree, and a node id.
the scalar to the left of : in a map's member
void sample_parse_file()
ready-to-go example of parsing a file from disk
void add_tag_directive(csubstr handle, csubstr prefix, id_type id)
static std::jmp_buf s_jmp_env
basic_substring range(size_t first, size_t last=npos) const noexcept
return [first,last[.
void sample_location_tracking()
track node YAML source locations in the parsed tree
mask of KEYQUO|KEY_PLAIN : all the key scalar styles for key (not container styles!) ...
basic_substring triml(const C c) const
trim left
id_type next_sibling(id_type node) const
void set_serialized(id_type node, T const &val) RYML_NOEXCEPT
pfn_error_basic m_error_basic
a pointer to a basic error handler function
!!set Unordered set of non-equal values.
ConstNodeRef child(id_type pos) const RYML_NOEXCEPT
Forward to Tree::child().
auto reverse_range(size_t ifirst, size_t ilast) -> typename std::enable_if< !std::is_const< U >::value, void >::type
revert a range in place
void sample_parse_in_place()
parse a mutable YAML source buffer
EmitOptions & max_cols(id_type cols) noexcept
Set max columns for the emitted YAML in FLOW_MLN mode.
ParserOptions & locations(bool enabled) noexcept
enable/disable source location tracking.
size_t len
the length of the substring
void set_key_style(type_bits style)
basic_substring select(const C c, size_t pos=0) const
get the substr consisting of the first occurrence of c after pos, or an empty substr if none occurs ...
substr emit_yaml(Tree const &t, EmitOptions const &opts, substr buf, bool error_on_excess)
(1) emit YAML to the given buffer.
csubstr catseprs_append(CharOwningContainer *cont, Sep const &sep, Args const &...args)
catsep+resize+append: like c4::catsep(), but receives a container, and appends the arguments...
void sample_float_precision()
control precision of serialized floats
mark container with spaces after comma when in flow mode. < Applies to both FLOW_SL and FLOW_MLN (but...
size_t catsep(substr buf, Sep const &sep, Arg const &a, Args const &...more)
serialize the arguments, concatenating them to the given fixed-size buffer, using a separator between...
example user container type with nested user types.
void set_style_conditionally(id_type node, NodeType type_mask, NodeType rem_style_flags, NodeType add_style_flags, bool recurse=false)
NodeRef rootref()
Get the root as a NodeRef . Note that a non-const Tree implicitly converts to NodeRef.
This is the main driver of parsing logic: it scans the YAML or JSON source for tokens, and emits the appropriate sequence of parsing events to its event handler.
pfn_error_visit m_error_visit
a pointer to a visit error handler function
Exception thrown by the default parse error implementation.
id_type node
node where the error was detected
A lightweight object containing options to be used when emitting.
pfn_allocate m_allocate
a pointer to an allocate handler function
void sample_global_allocator()
set a global allocator for ryml
void write(ryml::NodeRef &n, Inner const &inner)
serializes as a seq
!!map Unordered set of key: value pairs without duplicates.
void on_error_visit(ryml::csubstr msg, ryml::ErrorDataVisit const &errdata)
this is where the callback implementation goes.
boolalpha_ boolalpha(T const &val=false)
tag function to mark a variable to be written as an alphabetic boolean, ie as either true or false ...
example scalar type, serialized only
std::string saved_msg_short
void set_container_style(type_bits style)
bool is_val_plain() const RYML_NOEXCEPT
Forward to Tree::is_val_plain().
Callbacks const & get_callbacks()
get the global callbacks
auto tolower() -> typename std::enable_if< !std::is_const< U >::value, void >::type
convert the string to lower-case
void sample_parse_reuse_tree()
parse into an existing tree, maybe into a node
bool empty() const noexcept
void sample_emit_to_container()
emit to memory, eg a string or vector-like container
mark val scalar as multiline, block literal |
!!seq Sequence of arbitrary values.
ryml::Callbacks callbacks()
void set_key_anchor(id_type node, csubstr anchor)
csubstr val() const RYML_NOEXCEPT
Forward to Tree::val().
void sample_style_flow_formatting()
control formatting of flow containers
bool check_error_occurs(Fn &&fn)
checking that an error occurs while calling fn
substr alloc_arena(size_t sz)
grow the tree's string arena by the given size and return a substr of the added portion ...
void resolve_tags(TagCache &cache, bool all=true)
Resolve tags in the tree such as "!!str" -> "", "!foo" -> "" and custom ...
const_base64_wrapper base64(csubstr s, size_t *reqsize=nullptr)
a tag function to mark a csubstr payload to be encoded in base64 format
void ensure_callbacks()
set up default callbacks when ryml does not provide them (ie when RYML_NO_DEFAULT_CALLBACKS is define...
void on_error_basic(ryml::csubstr msg, ryml::ErrorDataBasic const &errdata)
this is where the callback implementation goes.
Callbacks & set_error_visit(pfn_error_visit error_visit=nullptr)
Set or reset the error_visit callback.
~GlobalAllocatorExample()
NodeRef docref(id_type i)
get the i-th document of the stream
csubstr location_contents(Location const &loc) const
Get the string starting at a particular location, to the end of the parsed source buffer...
void sample_user_scalar_types()
serialize/deserialize scalar (leaf/scalar) types
const_children_view children() const RYML_NOEXCEPT
get an iterable view over children
static void * s_allocate(size_t len, void *, void *this_)
Callbacks const & callbacks() const
Get the current callbacks in the parser.
basic_substring last(size_t num) const noexcept
return the last num elements: [len-num,len[
void sample_quick_overview()
quick overview of most common features
void free(void *mem, size_t len)
size_t find(const C c, size_t start_pos=0) const
example scalar type, deserialized only
void set_key(id_type node, csubstr key) RYML_NOEXCEPT
ryml::ReadResult read(ryml::ConstNodeRef const &n, Inner *inner)
static std::string s_jmp_msg
void clear()
clear the tree and zero every node
void set_val_ref(csubstr val_ref)
ReadResult deserialize_key(id_type node, T *v) const
(1) deserialize a node's key to a variable
bool is_root(id_type node) const
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
ParserOptions & flow_ml_style(NodeType style) noexcept
choose the default style of multiline flow containers, when a container is detected as flow multiline...
bool is_val() const RYML_NOEXCEPT
Forward to Tree::is_val().
void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *tree, id_type node_id)
(1) parse YAML into an existing tree node.
example user container type: seq-like
EmitOptions & emit_nonroot_key(bool enabled) noexcept
When emit starts on a nested (non-root) node, emit the node's key as well.
an error handler used by some of the quickstart examples.
int main(int argc, const char *argv[])
void set_serialized(T const &v)
serialize a variable to this node.
void sample_base64()
encode/decode base64
void sample_empty_null_values()
serialize/deserialize/query empty or null values
size_t first_not_of(const C c) const
mark key scalar as single quoted '
ReadResult deserialize_child(id_type node, csubstr child_key, T *v) const
(1) find a child by name and deserialize its contents to the given variable (ie call ...
void sample_emit_to_stream()
emit to a stream, eg std::ostream
void set_key_serialized(T const &k)
serialize a variable, then assign the result to the node's key
void reserve(id_type node_capacity=RYML_DEFAULT_TREE_CAPACITY)
id_type id(NodeData const *n) const
get the id of a node belonging to this tree. n can be nullptr, in which case NONE is returned n must ...
YamlTag_e to_tag(csubstr tag)
!!str A sequence of zero or more Unicode characters.
void err_parse_format(DumpFn &&dumpfn, csubstr msg, ErrorDataParse const &errdata)
Given an error message and associated parse error data, format it fully as a parse error message...
substr catsep_sub(substr buf, Args &&...args)
like c4::catsep() but return a substr instead of a size
bool begins_with(const C c) const noexcept
true if the first character of the string is c
mark container with multi-line flow style, 1 element per line < - seqs as <
bool ends_with_any(ro_substr chars) const noexcept
true if the last character of the string is any of the given chars
void handle_args(int argc, const char *argv[])
static void s_free(void *mem, size_t len, void *this_)
integral_padded_< T > zpad(T val, size_t num_digits)
pad the argument with zeroes on the left, with decimal radix
ErrorDataParse errdata_parse
mask of VALQUO|VAL_PLAIN : all the val scalar styles for val (not container styles!) ...
EmitOptions & json_err_on_stream(bool enabled) noexcept
Whether to trigger an error (or emit as seq) when finding a stream in json mode.
void sample_error_visit()
handler for visit errors, and obtain a full error message with visit context
void set_val_style(type_bits style)
void file_put_contents(void const *buf, size_t sz, FILE *file, const char *filename=nullptr)
save a contiguous buffer into a file
ryml::Tree const * saved_visit_tree
a seq: a parent of VAL/SEQ/MAP nodes
void sample_deserialize_error()
shows error on deserializing nested nodes
void set_seq(id_type node) RYML_NOEXCEPT
left_< T > left(T val, size_t width, char padchar=' ')
tag type to mark an argument to be aligned left.
void err_basic_format(DumpFn &&dumpfn, csubstr msg, ErrorDataBasic const &errdata)
Given an error message and associated basic error data, format it fully as a basic error message...
basic_substring left_of(size_t pos) const noexcept
return [0, pos[ .
const_raw_wrapper raw(cblob data, size_t alignment=alignof(max_align_t))
mark a variable to be written in raw binary format, using memcpy
void sample_json()
JSON parsing and emitting.
std::vector< char > memory_pool
void sample_emit_to_file()
emit to a FILE*
void set_val_tag(id_type node, csubstr tag)
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(), but return a ReadResult with the status
void sample_error_handler()
set custom error handlers
bool has_val() const RYML_NOEXCEPT
Forward to Tree::has_val().
void free(void *mem, size_t len)
void set_container_style(id_type node, type_bits style)
right_< T > right(T val, size_t width, char padchar=' ')
tag function to mark an argument to be aligned right
csubstr to_arena(T const &a)
serialize the given variable to the tree's arena, growing it as needed to accomodate the serializatio...
tag type to mark a tree or node to be emitted as yaml when using operator<<, with options...
Location location(Parser const &p, id_type node) const
Get the location of a node from the parse used to parse this tree.
ryml::Callbacks default_callbacks()
set up a bare-bones implementation of the callbacks
bool is_sub(ro_substr const that) const noexcept
true if *this is a substring of that (ie, from the same buffer)
mark container with single-line flow style < - seqs as <
bool report_check(int line, const char *predicate, bool result)
used by CHECK()
size_t uncat(csubstr buf, Arg &a, Args &...more)
deserialize the arguments from the given buffer.
NodeType type() const RYML_NOEXCEPT
Forward to Tree::type().
void set_style_conditionally(NodeType type_mask, NodeType rem_style_flags, NodeType add_style_flags, bool recurse=false)
void save_key(id_type node, T const &key)
void check_eq(my_map_type const &that) const
csubstr key() const RYML_NOEXCEPT
Forward to Tree::key().
void clear_style(bool recurse=false)
void save(id_type node, T const &val)