85#if defined(RYML_SINGLE_HEADER)
86 #define RYML_SINGLE_HDR_DEFINE_NOW
87 #include <ryml_all.hpp>
88#elif defined(RYML_SINGLE_HEADER_LIB)
89 #include <ryml_all.hpp>
101 #include <c4/format_base64.hpp>
172int main(
int argc,
const char* argv[])
228C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
229C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wcast-qual")
230C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wold-style-cast")
231C4_SUPPRESS_WARNING_GCC(
"-Wuseless-cast")
301bool report_check(
int line,
const char *predicate,
bool result);
304#if defined(__DOXYGEN__) || defined(_DOXYGEN_)
306# define CHECK(predicate) assert(predicate)
308# if !(defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
310# define CHECK(predicate) do { if(!report_check(__LINE__, #predicate, (predicate))) { RYML_DEBUG_BREAK(); } } while(0)
312# define CHECK CheckPredicate{__FILE__, __LINE__}
313 struct CheckPredicate
317 void operator() (
bool result)
const
340 char yml_buf[] =
"{foo: 1, bar: [2, 3], john: doe}";
345 CHECK(bar[0].val() ==
"2");
346 CHECK(bar[1].val() ==
"3");
347 CHECK(bar[0].val().str == yml_buf + 15);
348 CHECK(bar[1].val().str == yml_buf + 18);
351 int bar0 = 0, bar1 = 0;
360 CHECK(bar[0].val() ==
"10");
361 CHECK(bar[1].val() ==
"11");
365 CHECK(bar[2].val() ==
"12");
368 std::string expected =
"{foo: 1,bar: [10,11,12],john: doe}";
374 std::cout << tree <<
"\n";
378 expected =
"foo: 1\n";
463 CHECK(tree[
"foo"].is_keyval());
464 CHECK(tree[
"foo"].val() ==
"1");
465 CHECK(tree[
"foo"].key() ==
"foo");
466 CHECK(tree[
"bar"].is_seq());
467 CHECK(tree[
"bar"].has_key());
468 CHECK(tree[
"bar"].key() ==
"bar");
470 CHECK(tree[
"bar"][0].val() ==
"2");
471 CHECK(tree[
"bar"][1].val() ==
"3");
472 CHECK(tree[
"john"].val() ==
"doe");
476 CHECK(tree[0].
id() == tree[
"foo"].
id());
477 CHECK(tree[1].
id() == tree[
"bar"].
id());
478 CHECK(tree[2].
id() == tree[
"john"].
id());
480 CHECK(tree[0].
id() == tree[
"foo"].
id());
481 CHECK(tree[1].
id() == tree[
"bar"].
id());
482 CHECK(tree[2].
id() == tree[
"john"].
id());
484 CHECK(bar[0].val() ==
"2");
485 CHECK(bar[1].val() ==
"3");
490 CHECK(tree[
"foo"].key() ==
"foo");
491 CHECK(tree[
"bar"].key() ==
"bar");
492 CHECK(tree[
"john"].key() ==
"john");
497 CHECK(root[
"foo"].
id() == root[0].
id());
498 CHECK(root[
"bar"].
id() == root[1].
id());
499 CHECK(root[
"john"].
id() == root[2].
id());
558 CHECK(child.key() == expected_keys[count++]);
564 CHECK(child.key() == expected_keys[count++]);
570 CHECK(tree.
key(child_id) == expected_keys[count++]);
579 CHECK(tree.
key(child_id) == expected_keys[count++]);
639 int foo = 0, bar0 = 0, bar1 = 0;
640 std::string john_str;
643 root[
"bar"][0] >> bar0;
644 root[
"bar"][1] >> bar1;
645 root[
"john"] >> john_str;
650 CHECK(john_str ==
"doe");
651 CHECK(bar_str ==
"bar");
668 wroot[
"foo"] =
"says you";
669 wroot[
"bar"][0] =
"-2";
670 wroot[
"bar"][1] =
"-3";
671 wroot[
"john"] =
"ron";
675 CHECK(root[
"foo"].val() ==
"says you");
676 CHECK(root[
"bar"][0].val() ==
"-2");
677 CHECK(root[
"bar"][1].val() ==
"-3");
678 CHECK(root[
"john"].val() ==
"ron");
693 wroot[
"foo"] <<
"says who";
694 wroot[
"bar"][0] << 20;
695 wroot[
"bar"][1] << 30;
696 wroot[
"john"] <<
"deere";
697 CHECK(root[
"foo"].val() ==
"says who");
698 CHECK(root[
"bar"][0].val() ==
"20");
699 CHECK(root[
"bar"][1].val() ==
"30");
700 CHECK(root[
"john"].val() ==
"deere");
704 std::string ok(
"in_scope");
708 CHECK(root[
"john"].val() ==
"in_scope");
710 wroot[
"float"] << 2.4f;
714 CHECK(tree.
arena() ==
"says who2030deerein_scope2.42.400000");
722 wroot[
"newkeyval"] =
"shiny and new";
725 CHECK(root[
"newkeyval"].key() ==
"newkeyval");
726 CHECK(root[
"newkeyval"].val() ==
"shiny and new");
727 CHECK(root[
"newkeyval (serialized)"].key() ==
"newkeyval (serialized)");
728 CHECK(root[
"newkeyval (serialized)"].val() ==
"shiny and new (serialized)");
734 CHECK(root[
"bar"].num_children() == 2);
735 wroot[
"bar"][2] =
"oh so nice";
736 wroot[
"bar"][3] <<
"oh so nice (serialized)";
737 CHECK(root[
"bar"].num_children() == 4);
738 CHECK(root[
"bar"][2].val() ==
"oh so nice");
739 CHECK(root[
"bar"][3].val() ==
"oh so nice (serialized)");
745 CHECK(root[
"newseq"].num_children() == 0);
746 CHECK(root[
"newseq"].is_seq());
747 CHECK(root[
"newseq (serialized)"].num_children() == 0);
748 CHECK(root[
"newseq (serialized)"].is_seq());
754 CHECK(root[
"newmap"].num_children() == 0);
755 CHECK(root[
"newmap"].is_map());
756 CHECK(root[
"newmap (serialized)"].num_children() == 0);
757 CHECK(root[
"newmap (serialized)"].is_map());
790 nothing = wroot[
"I am nothing"];
805 something =
"indeed";
807 CHECK(root[
"I am something"].val() ==
"indeed");
838 CHECK(wbar[0].readable() && wbar[0].val() ==
"20");
839 CHECK( ! wbar[100].readable());
840 CHECK( ! wbar[100].readable() || wbar[100].val() ==
"100");
842 CHECK( ! wbar[0].is_seed() && wbar[0].val() ==
"20");
843 CHECK(wbar[100].is_seed() || wbar[100].val() ==
"100");
871 return seed_node.at(
"is").at(
"an").at(
"invalid").at(
"operation");
878 return seed_node[
"is"][
"an"][
"invalid"][
"operation"];
890 "bar: [20,30,oh so nice,oh so nice (serialized)]" "\n"
891 "john: in_scope" "\n"
893 "digits: 2.400000" "\n"
894 "newkeyval: shiny and new" "\n"
895 "newkeyval (serialized): shiny and new (serialized)" "\n"
897 "newseq (serialized): []" "\n"
899 "newmap (serialized): {}" "\n"
900 "I am something: indeed" "\n"
909 std::stringstream ss;
911 std::string stream_result = ss.str();
918 CHECK(buf_result == expected_result);
919 CHECK(str_result == expected_result);
920 CHECK(stream_result == expected_result);
936 CHECK(tree[
"bar"][0].val() ==
"21");
938 CHECK(tree[
"bar"][0].val() ==
"22");
944 constnoderef = noderef;
950 noderef = tree[
"bar"][0];
951 constnoderef = consttree[
"bar"][0];
955 CHECK(constnoderef == noderef);
956 CHECK(!(constnoderef != noderef));
966 ryml::Tree tree2 = parse_in_arena(&parser,
"expected.yml", expected_result);
981 "# UTF8/16/32 can be placed directly in any scalar:" "\n"
983 "en: Planet (Gas)" "\n"
984 "fr: Planète (Gazeuse)" "\n"
985 "ru: Планета (Газ)" "\n"
989 "# UTF8 decoding only happens in double-quoted strings," "\n"
990 "# as per the YAML standard" "\n"
992 "decode this: \"\\u263A c\\x61f\\xE9\"" "\n"
993 "and this as well: \"\\u2705 \\U0001D11E\"" "\n"
994 "not decoded: '\\u263A \\xE2\\x98\\xBA'" "\n"
995 "neither this: '\\u2705 \\U0001D11E'" "\n");
997 CHECK(langs[
"en"].val() ==
"Planet (Gas)");
998 CHECK(langs[
"fr"].val() ==
"Planète (Gazeuse)");
999 CHECK(langs[
"ru"].val() ==
"Планета (Газ)");
1000 CHECK(langs[
"ja"].val() ==
"惑星(ガス)");
1001 CHECK(langs[
"zh"].val() ==
"行星(气体)");
1005 CHECK(langs[
"decode this"].val() ==
"☺ café");
1006 CHECK(langs[
"and this as well"].val() ==
"✅ 𝄞");
1007 CHECK(langs[
"not decoded"].val() ==
"\\u263A \\xE2\\x98\\xBA");
1008 CHECK(langs[
"neither this"].val() ==
"\\u2705 \\U0001D11E");
1036 const char foobar_str[] =
"foobar";
1038 CHECK(s ==
"foobar");
1039 CHECK(s.size() == 6);
1040 CHECK(s.data() == foobar_str);
1041 CHECK(s.size() == s.len);
1042 CHECK(s.data() == s.str);
1047 const char foobar_str[] =
"foobar";
1049 CHECK(s ==
"foobar");
1050 CHECK(s !=
"foobar0");
1059 CHECK(s ==
"foobar");
1060 CHECK(s !=
"foobar0");
1072 const char *foobar_str =
"foobar";
1074 CHECK(s ==
"foobar");
1075 CHECK(s !=
"foobar0");
1089 std::string foobar_str =
"foobar";
1091 CHECK(s ==
"foobar");
1092 CHECK(s !=
"foobar0");
1114 char const foobar_str_ro[] =
"foobar";
1115 char foobar_str_rw[] =
"foobar";
1116 static_assert(std::is_array<
decltype(foobar_str_ro)>::value,
"this is an array");
1117 static_assert(std::is_array<
decltype(foobar_str_rw)>::value,
"this is an array");
1122 CHECK(foobar.
size() == strlen(foobar_str_ro));
1123 CHECK(foobar ==
"foobar");
1129 CHECK(foobar.
size() == strlen(foobar_str_rw));
1130 CHECK(foobar ==
"foobar");
1136 CHECK(foobar.
size() == strlen(foobar_str_rw));
1137 CHECK(foobar ==
"foobar");
1148 char const* foobar_str_ro =
"foobar";
1149 char foobar_str_rw_[] =
"foobar";
1150 char * foobar_str_rw = foobar_str_rw_;
1151 static_assert(!std::is_array<
decltype(foobar_str_ro)>::value,
"this is a decayed pointer");
1152 static_assert(!std::is_array<
decltype(foobar_str_rw)>::value,
"this is a decayed pointer");
1158 CHECK(foobar.
size() == strlen(foobar_str_ro));
1159 CHECK(foobar ==
"foobar");
1165 CHECK(foobar.
size() == strlen(foobar_str_rw));
1166 CHECK(foobar ==
"foobar");
1172 CHECK(foobar.
size() == strlen(foobar_str_rw));
1173 CHECK(foobar ==
"foobar");
1183 char buf[] =
"foobar";
1185 CHECK(foobar ==
"foobar");
1186 foobar[0] =
'F';
CHECK(foobar ==
"Foobar");
1187 foobar.
back() =
'R';
CHECK(foobar ==
"FoobaR");
1199 foobar.
fill(
'.');
CHECK(foobar ==
"......");
1211 CHECK(s.
sub(0, 12) ==
"fooFOObarBAR");
1271 CHECK(some ==
"some");
1272 CHECK(s ==
"some substring");
1275 char result[32] = {0};
1276 std::snprintf(result,
sizeof(result),
"%.*s", (
int)some.
len, some.
str);
1277 printf(
"~~~%s~~~\n", result);
1287 char result[32] = {0};
1288 std::snprintf(result,
sizeof(result),
"%s", some.
str);
1298 CHECK(some ==
"some");
1299 CHECK(s ==
"some substring");
1302 std::stringstream ss;
1304 CHECK(ss.str() ==
"some substring");
1305 CHECK(ss.str() == s);
1313 std::stringstream ss;
1315 CHECK(ss.str() ==
"some substring");
1316 CHECK(ss.str() == s);
1320 std::stringstream ss;
1322 CHECK(ss.str() ==
"some substring");
1323 CHECK(ss.str() == s);
1327 std::stringstream ss;
1329 CHECK(ss.str() ==
"some");
1330 CHECK(ss.str() == some);
1367 CHECK(
ryml::csubstr(
" \t\n\rcontents without whitespace\t \n\r").trim(
"\t \n\r") ==
"contents without whitespace");
1388 CHECK(aaa___bbb.
trim (
'c') == aaa___bbb);
1407 CHECK(aaa___bbb.
trim (
"cd") == aaa___bbb);
1412 CHECK(
ryml::csubstr(
"'this is is single quoted'" ).unquoted() ==
"this is is single quoted");
1413 CHECK(
ryml::csubstr(
"\"this is is double quoted\"").unquoted() ==
"this is is double quoted");
1731 CHECK(
ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extshort() ==
"/path/to/file.tar");
1737 using namespace ryml;
1738 csubstr parts[] = {
"aa",
"bb",
"cc",
"dd",
"ee",
"ff"};
1742 CHECK(part == parts[count++]);
1748 CHECK(part == parts[count++]);
1754 CHECK(part == parts[count++]);
1763 const bool skip_empty =
true;
1836 const char filename[] =
"ryml_example.yml";
1837 std::string yaml =
""
1851 CHECK(tree[
"foo"].val() ==
"1");
1852 CHECK(tree[
"bar"][0].val() ==
"2");
1853 CHECK(tree[
"bar"][1].val() ==
"3");
1860 CHECK(tree[
"foo"].val() ==
"1");
1861 CHECK(tree[
"bar"][0].val() ==
"2");
1862 CHECK(tree[
"bar"][1].val() ==
"3");
1883 char src[] =
"{foo: 1, bar: [2, 3]}";
1889 CHECK(root[
"foo"].is_keyval());
1891 CHECK(root[
"foo"].val() ==
"1");
1892 CHECK(root[
"bar"].is_seq());
1893 CHECK(root[
"bar"].has_key());
1895 CHECK(root[
"bar"][0].val() ==
"2");
1896 CHECK(root[
"bar"][1].val() ==
"3");
1899 int foo = 0, bar0 = 0, bar1 = 0;
1901 root[
"bar"][0] >> bar0;
1902 root[
"bar"][1] >> bar1;
1908 CHECK(root[
"foo"].val().data() == src + strlen(
"{foo: "));
1909 CHECK(root[
"foo"].val().begin() == src + strlen(
"{foo: "));
1910 CHECK(root[
"foo"].val().end() == src + strlen(
"{foo: 1"));
1911 CHECK(root[
"foo"].val().is_sub(srcview));
1912 CHECK(root[
"bar"][0].val().data() == src + strlen(
"{foo: 1, bar: ["));
1913 CHECK(root[
"bar"][0].val().begin() == src + strlen(
"{foo: 1, bar: ["));
1914 CHECK(root[
"bar"][0].val().end() == src + strlen(
"{foo: 1, bar: [2"));
1915 CHECK(root[
"bar"][0].val().is_sub(srcview));
1916 CHECK(root[
"bar"][1].val().data() == src + strlen(
"{foo: 1, bar: [2, "));
1917 CHECK(root[
"bar"][1].val().begin() == src + strlen(
"{foo: 1, bar: [2, "));
1918 CHECK(root[
"bar"][1].val().end() == src + strlen(
"{foo: 1, bar: [2, 3"));
1919 CHECK(root[
"bar"][1].val().is_sub(srcview));
1941 CHECK(root[
"foo"].is_keyval());
1943 CHECK(root[
"foo"].val() ==
"1");
1944 CHECK(root[
"bar"].is_seq());
1945 CHECK(root[
"bar"].has_key());
1947 CHECK(root[
"bar"][0].val() ==
"2");
1948 CHECK(root[
"bar"][1].val() ==
"3");
1951 int foo = 0, bar0 = 0, bar1 = 0;
1953 root[
"bar"][0] >> bar0;
1954 root[
"bar"][1] >> bar1;
1962 char src[] =
"{foo: is it really true}";
1971 CHECK(tree[
"foo"].val() ==
"is it really true");
1999 CHECK(root[
"foo"].is_keyval());
2001 CHECK(root[
"foo"].val() ==
"1");
2002 CHECK(root[
"bar"].is_seq());
2003 CHECK(root[
"bar"].has_key());
2005 CHECK(root[
"bar"][0].val() ==
"2");
2006 CHECK(root[
"bar"][1].val() ==
"3");
2015 "bar2: [22,32]" "\n"
2018 CHECK(root[
"foo2"].is_keyval());
2019 CHECK(root[
"foo2"].
key() ==
"foo2");
2020 CHECK(root[
"foo2"].val() ==
"12");
2021 CHECK(root[
"bar2"].is_seq());
2022 CHECK(root[
"bar2"].has_key());
2023 CHECK(root[
"bar2"].
key() ==
"bar2");
2024 CHECK(root[
"bar2"][0].val() ==
"22");
2025 CHECK(root[
"bar2"][1].val() ==
"32");
2034 CHECK(root[0].val() ==
"a");
2035 CHECK(root[1].val() ==
"b");
2036 CHECK(root[2].is_map());
2037 CHECK(root[2][
"x0"].val() ==
"1");
2038 CHECK(root[2][
"x1"].val() ==
"2");
2046 "- {x0: 1,x1: 2}" "\n"
2047 "- champagne: Dom Perignon" "\n"
2048 " coffee: Arabica" "\n"
2051 CHECK(root[0].val() ==
"a");
2052 CHECK(root[1].val() ==
"b");
2053 CHECK(root[2].is_map());
2054 CHECK(root[2][
"x0"].val() ==
"1");
2055 CHECK(root[2][
"x1"].val() ==
"2");
2056 CHECK(root[3].is_map());
2057 CHECK(root[3][
"champagne"].val() ==
"Dom Perignon");
2058 CHECK(root[3][
"coffee"].val() ==
"Arabica");
2071 "- {x0: 1,x1: 2}" "\n"
2072 "- champagne: Dom Perignon" "\n"
2073 " coffee: Arabica" "\n"
2076 " vinho verde: Soalheiro" "\n"
2077 " vinho tinto: Redoma 2017" "\n"
2079 " - Rochefort 10" "\n"
2081 " - Leffe Rituel" "\n"
2082 " always: lots of water" "\n"
2090 "- {x0: 1,x1: 2}" "\n"
2091 "- champagne: Dom Perignon" "\n"
2092 " coffee: Arabica" "\n"
2094 " vinho verde: Soalheiro" "\n"
2095 " vinho tinto: Redoma 2017" "\n"
2097 " - Rochefort 10" "\n"
2099 " - Leffe Rituel" "\n"
2100 " always: lots of water" "\n"
2113 "- {x0: 1,x1: 2}" "\n"
2114 "- champagne: Dom Perignon" "\n"
2115 " coffee: Arabica" "\n"
2117 " vinho verde: Soalheiro" "\n"
2118 " vinho tinto: Redoma 2017" "\n"
2120 " - Rochefort 10" "\n"
2122 " - Leffe Rituel" "\n"
2123 " - Kasteel Donker" "\n"
2124 " always: lots of water" "\n"
2152 ryml::csubstr yaml =
"[Dom Perignon,Gosset Grande Reserve,Jacquesson 742]";
2156 yaml =
"[Rochefort 10,Busch,Leffe Rituel,Kasteel Donker]";
2190 "- Gosset Grande Reserve\n"
2191 "- Jacquesson 742\n"
2197 "- Kasteel Donker\n"
2201 "- Niepoort Redoma 2017\n"
2202 "- Vina Esmeralda\n"
2212 "- Gosset Grande Reserve\n"
2213 "- Jacquesson 742\n"
2217 "- Kasteel Donker\n"
2225 "- Niepoort Redoma 2017\n"
2226 "- Vina Esmeralda\n"
2240 "doe: a deer, a female deer" "\n"
2241 "ray: a drop of golden sun" "\n"
2244 "french-hens: 3" "\n"
2245 "calling-birds:" "\n"
2250 "xmas-fifth-day:" "\n"
2251 " calling-birds: four" "\n"
2252 " french-hens: 3" "\n"
2253 " golden-rings: 5" "\n"
2256 " location: a pear tree" "\n"
2257 " turtle-doves: two" "\n"
2264 std::vector<ryml::csubstr> keys, vals;
2267 keys.emplace_back(n.key());
2270 CHECK(keys.size() >= 6);
2271 CHECK(vals.size() >= 6);
2272 if(keys.size() >= 6 && vals.size() >= 6)
2274 CHECK(keys[0] ==
"doe");
2275 CHECK(vals[0] ==
"a deer, a female deer");
2276 CHECK(keys[1] ==
"ray");
2277 CHECK(vals[1] ==
"a drop of golden sun");
2278 CHECK(keys[2] ==
"pi");
2279 CHECK(vals[2] ==
"3.14159");
2280 CHECK(keys[3] ==
"xmas");
2281 CHECK(vals[3] ==
"true");
2282 CHECK(root[5].has_key());
2283 CHECK(root[5].is_seq());
2284 CHECK(root[5].
key() ==
"calling-birds");
2285 CHECK(!root[5].has_val());
2287 CHECK(keys[5] ==
"calling-birds");
2288 CHECK(vals[5] ==
"");
2295 ryml::csubstr calling_birds[] = {
"huey",
"dewey",
"louie",
"fred"};
2297 CHECK(n.val() == calling_birds[count++]);
2322 const char a_deer[] =
"a deer, a female deer";
2331 std::string a_drop =
"a drop of golden sun";
2334 root[
"ray"] << a_drop;
2340 CHECK(root[
"ray"].val() ==
"a drop of golden sun");
2343 root[
"pi"] << ryml::fmt::real(3.141592654, 5);
2344 root[
"xmas"] << ryml::fmt::boolalpha(
true);
2345 root[
"french-hens"] << 3;
2354 xmas5[
"calling-birds"] =
"four";
2355 xmas5[
"french-hens"] << 3;
2356 xmas5[
"golden-rings"] << 5;
2358 xmas5[
"partridges"][
"count"] << 1;
2359 xmas5[
"partridges"][
"location"] =
"a pear tree";
2360 xmas5[
"turtle-doves"] =
"two";
2361 root[
"cars"] =
"GTO";
2364 "doe: a deer, a female deer" "\n"
2365 "ray: a drop of golden sun" "\n"
2368 "french-hens: 3" "\n"
2369 "calling-birds:" "\n"
2374 "xmas-fifth-day:" "\n"
2375 " calling-birds: four" "\n"
2376 " french-hens: 3" "\n"
2377 " golden-rings: 5" "\n"
2380 " location: a pear tree" "\n"
2381 " turtle-doves: two" "\n"
2395 char buf[] =
"[a, b, c, d]";
2425 CHECK(root[0].val().is_sub(arena));
2426 CHECK(root[1].val().is_sub(arena));
2427 CHECK(root[2].val().is_sub(arena));
2428 CHECK(root[3].val().is_sub(arena));
2438 char buf[] =
"[a, b, c, d]";
2446 CHECK(root[2].val() ==
"c");
2449 CHECK(root[2].val() ==
"12345");
2455 CHECK(root[3].val() ==
"d");
2458 CHECK(root[3].val() ==
"67890");
2474 CHECK(root[2].val() ==
"c");
2476 CHECK(root[2].val() ==
"12345");
2485 CHECK(root[3].val() ==
"67890");
2489 CHECK(tree.
arena() ==
"[a, b, c, d]1234567890");
2497 CHECK(c10 ==
"10101010");
2507 CHECK(root[
"a"].val() ==
"2222");
2517 CHECK(copied == mystr);
2518 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2527 memcpy(copied.
str, mystr.
str, mystr.
len);
2528 CHECK(copied == mystr);
2529 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2578 CHECK(tree.
to_arena(
double(0.234)) ==
"0.234");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.234");
2588 const float fnan = std::numeric_limits<float >::quiet_NaN();
2589 const double dnan = std::numeric_limits<double>::quiet_NaN();
2590 const float finf = std::numeric_limits<float >::infinity();
2591 const double dinf = std::numeric_limits<double>::infinity();
2592 CHECK(tree.
to_arena( finf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf");
2593 CHECK(tree.
to_arena( dinf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf");
2594 CHECK(tree.
to_arena(-finf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf");
2595 CHECK(tree.
to_arena(-dinf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf");
2596 CHECK(tree.
to_arena( fnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan");
2597 CHECK(tree.
to_arena( dnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan.nan");
2601 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wfloat-equal");
2607 tree[
"ninf"] >> f;
CHECK(f == -finf);
2608 tree[
"ninf"] >> d;
CHECK(d == -dinf);
2609 tree[
"pinf"] >> f;
CHECK(f == finf);
2610 tree[
"pinf"] >> d;
CHECK(d == dinf);
2611 tree[
"nan" ] >> f;
CHECK(std::isnan(f));
2612 tree[
"nan" ] >> d;
CHECK(std::isnan(d));
2613 C4_SUPPRESS_WARNING_GCC_CLANG_POP
2626 t[
"val"] >> valu8;
CHECK(valu8 == 2);
2627 t[
"val"] >> vali8;
CHECK(vali8 == 2);
2634 auto checku8 = ryml::fmt::overflow_checked(valu8);
2635 t[
"val"] >> checku8;
2638 auto checki8 = ryml::fmt::overflow_checked(vali8);
2639 t[
"val"] >> checki8;
2655 "dquoted: \"\"" "\n"
2658 "all_null: [~, null, Null, NULL]" "\n"
2659 "non_null: [nULL, non_null, non null, null it is not]" "\n"
2663 CHECK(tree[
"plain"].has_val());
2664 CHECK(tree[
"squoted"].has_val());
2665 CHECK(tree[
"dquoted"].has_val());
2666 CHECK(tree[
"literal"].has_val());
2667 CHECK(tree[
"folded"].has_val());
2668 CHECK( ! tree[
"all_null"].has_val());
2669 CHECK( ! tree[
"non_null"].has_val());
2671 CHECK( ! tree[
"plain"].is_container());
2672 CHECK( ! tree[
"squoted"].is_container());
2673 CHECK( ! tree[
"dquoted"].is_container());
2674 CHECK( ! tree[
"literal"].is_container());
2675 CHECK( ! tree[
"folded"].is_container());
2676 CHECK(tree[
"all_null"].is_container());
2677 CHECK(tree[
"non_null"].is_container());
2682 CHECK(tree[
"plain"].val().len == 0);
2683 CHECK(tree[
"squoted"].val().len == 0);
2684 CHECK(tree[
"dquoted"].val().len == 0);
2685 CHECK(tree[
"literal"].val().len == 0);
2686 CHECK(tree[
"folded"].val().len == 0);
2688 CHECK(tree[
"plain"].val().str ==
nullptr);
2689 CHECK(tree[
"squoted"].val().str !=
nullptr);
2690 CHECK(tree[
"dquoted"].val().str !=
nullptr);
2691 CHECK(tree[
"literal"].val().str !=
nullptr);
2692 CHECK(tree[
"folded"].val().str !=
nullptr);
2696 CHECK(tree[
"plain"].val() ==
nullptr);
2697 CHECK(tree[
"squoted"].val() !=
nullptr);
2698 CHECK(tree[
"dquoted"].val() !=
nullptr);
2699 CHECK(tree[
"literal"].val() !=
nullptr);
2700 CHECK(tree[
"folded"].val() !=
nullptr);
2705 CHECK(tree[
"plain"].val_is_null());
2706 CHECK( ! tree[
"squoted"].val_is_null());
2707 CHECK( ! tree[
"dquoted"].val_is_null());
2708 CHECK( ! tree[
"literal"].val_is_null());
2709 CHECK( ! tree[
"folded"].val_is_null());
2714 CHECK(child.val() !=
nullptr);
2715 CHECK(child.val_is_null());
2719 CHECK(child.val() !=
nullptr);
2720 CHECK( ! child.val_is_null());
2735 CHECK(null .len == 0);
CHECK(null .str ==
nullptr);
CHECK(null ==
nullptr);
2738 CHECK(tilde .len != 0);
CHECK(tilde .str !=
nullptr);
CHECK(tilde !=
nullptr);
2743 tree[
"empty_null"] << null;
CHECK(tree.
arena() ==
"");
2745 tree[
"empty_nonnull"] << nonnull;
CHECK(tree.
arena() ==
"");
2747 tree[
"str_null"] << strnull;
CHECK(tree.
arena() ==
"null");
2749 tree[
"str_tilde"] << tilde;
CHECK(tree.
arena() ==
"null~");
2753 "empty_nonnull: ''" "\n"
2754 "str_null: null" "\n"
2763 return s.str ==
nullptr ?
"null" : s;
2765 tree[
"empty_null"] << null_if_nullptr(null);
2766 tree[
"empty_nonnull"] << null_if_nullptr(nonnull);
2767 tree[
"str_null"] << null_if_nullptr(strnull);
2768 tree[
"str_tilde"] << null_if_nullptr(tilde);
2771 "empty_null: null" "\n"
2772 "empty_nonnull: ''" "\n"
2773 "str_null: null" "\n"
2782 tree[
"empty_null"] << null_if_predicate(null);
2783 tree[
"empty_nonnull"] << null_if_predicate(nonnull);
2784 tree[
"str_null"] << null_if_predicate(strnull);
2785 tree[
"str_tilde"] << null_if_predicate(tilde);
2788 "empty_null: null" "\n"
2789 "empty_nonnull: ''" "\n"
2790 "str_null: null" "\n"
2791 "str_tilde: null" "\n"
2799 tree[
"empty_null"] << tilde_if_predicate(null);
2800 tree[
"empty_nonnull"] << tilde_if_predicate(nonnull);
2801 tree[
"str_null"] << tilde_if_predicate(strnull);
2802 tree[
"str_tilde"] << tilde_if_predicate(tilde);
2805 "empty_null: ~" "\n"
2806 "empty_nonnull: ''" "\n"
2824 char buf_[256] = {};
2826 size_t size =
ryml::format(buf,
"a={} foo {} {} bar {}", 0.1, 10, 11, 12);
2827 CHECK(size == strlen(
"a=0.1 foo 10 11 bar 12"));
2828 CHECK(buf.
first(size) ==
"a=0.1 foo 10 11 bar 12");
2831 size =
ryml::format({} ,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12);
2832 CHECK(size ==
ryml::format(buf,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12));
2833 CHECK(size == strlen(
"a=this_is_a foo 10 11 bar 12"));
2835 char smallbuf[8] = {};
2836 size =
ryml::format(smallbuf,
"{} is too large {}",
"this",
"for the buffer");
2837 CHECK(size == strlen(
"this is too large for the buffer"));
2843 CHECK(result ==
"b=1, damn it.");
2862 CHECK(sbuf ==
"and c=2 seems about right");
2863 std::vector<char> vbuf;
2865 CHECK(sbuf ==
"and c=2 seems about right");
2868 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2875 int a = 0, b = 1, c = 2;
2877 CHECK(result ==
"0 and 1 and 2");
2878 int aa = -1, bb = -2, cc = -3;
2879 size_t num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2887 CHECK(result ==
"10 and 20 and 30");
2888 num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2898 char buf_[256] = {};
2900 size_t size =
ryml::cat(buf,
"a=", 0.1,
"foo", 10, 11,
"bar", 12);
2901 CHECK(size == strlen(
"a=0.1foo1011bar12"));
2902 CHECK(buf.
first(size) ==
"a=0.1foo1011bar12");
2907 char smallbuf[8] = {};
2908 size =
ryml::cat(smallbuf,
"this",
" is too large ",
"for the buffer");
2909 CHECK(size == strlen(
"this is too large for the buffer"));
2915 CHECK(result ==
"b=1, damn it.");
2933 ryml::catrs(&sbuf,
"and c=", 2,
" seems about right");
2934 CHECK(sbuf ==
"and c=2 seems about right");
2935 std::vector<char> vbuf;
2936 ryml::catrs(&vbuf,
"and c=", 2,
" seems about right");
2937 CHECK(sbuf ==
"and c=2 seems about right");
2940 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2947 int a = 0, b = 1, c = 2;
2949 CHECK(result ==
"0 1 2");
2950 int aa = -1, bb = -2, cc = -3;
2951 char sep1 =
'a', sep2 =
'b';
2952 size_t num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2961 CHECK(result ==
"10 20 30");
2962 num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2973 char buf_[256] = {};
2976 size_t size =
ryml::catsep(buf,
' ',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2977 CHECK(buf.
first(size) ==
"a= 0 b= 1 c= 2 45 67");
2980 size =
ryml::catsep(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
2981 CHECK(buf.
first(size) ==
"a=0 and b=1 and c=2 and 45 and 67");
2983 size =
ryml::catsep(buf,
" ... ",
"a=0",
"b=1",
"c=2", 45, 67);
2984 CHECK(buf.
first(size) ==
"a=0 ... b=1 ... c=2 ... 45 ... 67");
2986 size =
ryml::catsep(buf,
'/',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2987 CHECK(buf.
first(size) ==
"a=/0/b=/1/c=/2/45/67");
2989 size =
ryml::catsep(buf, 888,
"a=0",
"b=1",
"c=2", 45, 67);
2990 CHECK(buf.
first(size) ==
"a=0888b=1888c=28884588867");
2996 char smallbuf[8] = {};
2998 CHECK(size == strlen(
"a=0888b=1888c=28884588867"));
3004 CHECK(result ==
"a=0 and b=1 and c=2 and 45 and 67");
3023 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67");
3024 std::vector<char> vbuf;
3030 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");
3035 char buf_[256] = {};
3037 int a = 0, b = 1, c = 2;
3039 CHECK(result ==
"0 1 2");
3040 int aa = -1, bb = -2, cc = -3;
3048 CHECK(result ==
"10--20--30");
3058 using namespace ryml;
3059 char buf_[256] = {};
3078 CHECK(
"3735928559" ==
cat_sub(buf, UINT32_C(0xdeadbeef)));
3202 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wcast-align")
3203 const uint32_t payload[] = {10, 20, 30, 40, UINT32_C(0xdeadbeef)};
3205 csubstr expected =
csubstr((
const char *)payload,
sizeof(payload));
3210 for(
const uint32_t value : payload)
3213 expected =
csubstr((
const char *)&value,
sizeof(value));
3215 CHECK(actual.
size() ==
sizeof(uint32_t));
3220 CHECK(actual.
size() ==
sizeof(uint32_t));
3225 uint32_t result = 0;
3230 CHECK(result == value);
3232 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3252 text_and_base64 cases[] = {
3253 {{
"Hello, World!"}, {
"SGVsbG8sIFdvcmxkIQ=="}},
3254 {{
"Brevity is the soul of wit."}, {
"QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu"}},
3255 {{
"All that glitters is not gold."}, {
"QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu"}},
3258 for(text_and_base64 c : cases)
3259 tree[c.text] << ryml::fmt::base64(c.text);
3261 for(text_and_base64 c : cases)
3264 for(text_and_base64 c : cases)
3266 CHECK(tree[c.text].
val() == c.base64);
3267 CHECK(tree[c.base64].
val() == c.text);
3271 "Hello, World!: SGVsbG8sIFdvcmxkIQ==" "\n"
3272 "Brevity is the soul of wit.: QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu" "\n"
3273 "All that glitters is not gold.: QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu" "\n"
3275 "SGVsbG8sIFdvcmxkIQ==: Hello, World!" "\n"
3276 "QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu: Brevity is the soul of wit." "\n"
3277 "QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu: All that glitters is not gold." "\n"
3279 char buf1_[128], buf2_[128];
3283 for(
const text_and_base64 c : cases)
3288 tree[c.text] >> ryml::fmt::base64(buf1, &len);
3297 CHECK(c.text.len == len);
3300 tree[c.base64] >>
ryml::key(ryml::fmt::base64(buf2, &len));
3306 tree[c.text] >> ryml::fmt::base64(result);
3307 CHECK(result == c.text);
3309 tree[c.base64] >>
ryml::key(ryml::fmt::base64(result));
3310 CHECK(result == c.text);
3314 const uint64_t valin = UINT64_C(0xdeadbeef);
3315 tree[
"deadbeef"] << c4::fmt::base64(valin);
3316 uint64_t valout = 0;
3318 tree[
"deadbeef"] >> ryml::fmt::base64(valout, &len);
3319 CHECK(len ==
sizeof(valout));
3320 CHECK(valout == UINT64_C(0xdeadbeef));
3323 tree[
"deadbeef"] >> ryml::fmt::base64(valout);
3324 CHECK(valout == UINT64_C(0xdeadbeef));
3328 const double valin = 123456.7891011;
3329 tree[
"float"] << c4::fmt::base64(valin);
3332 tree[
"float"] >> ryml::fmt::base64(valout, &len);
3333 CHECK(len ==
sizeof(valout));
3334 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3337 tree[
"float"] >> ryml::fmt::base64(valout);
3338 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3342 const uint32_t data_in[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xdeadbeef};
3343 uint32_t data_out[11] = {};
3344 tree[
"int_data"] << ryml::fmt::base64(data_in, 11);
3345 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) != 0);
3347 tree[
"int_data"] >> ryml::fmt::base64(data_out, 11, &len);
3348 CHECK(len ==
sizeof(data_out));
3349 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3351 memset(data_out, 0,
sizeof(data_out));
3352 tree[
"int_data"] >> ryml::fmt::base64(data_out);
3353 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3607 "v3: (100,101,102)" "\n"
3608 "v4: (1000,1001,1002,1003)" "\n"
3636 "v3: (30,31,32)" "\n"
3637 "v4: (40,41,42,43)" "\n"
3689template<
class K,
class V>
3714template<
class K,
class V>
3742template<
class K,
class V>
3747 for(
auto const ch : n)
3750 map->
map_member.emplace(std::make_pair(std::move(k), std::move(v)));
3761 n[
"seq"] >> val->
seq;
3762 n[
"map"] >> val->
map;
3781 {{101, 102, 103, 104, 105, 106, 107}},
3782 {{{1001, 2001}, {1002, 2002}, {1003, 2003}}},
3813 "v3: (30,31,32)" "\n"
3814 "v4: (40,41,42,43)" "\n"
3839 std::string yml_std_string =
""
3840 "- v2: (20,21)" "\n"
3841 " v3: (30,31,32)" "\n"
3842 " v4: (40,41,42,43)" "\n"
3855 "- v2: (120,121)" "\n"
3856 " v3: (130,131,132)" "\n"
3857 " v4: (140,141,142,143)" "\n"
3867 " 11001: 12001" "\n"
3868 " 11002: 12002" "\n"
3869 " 11003: 12003" "\n"
3870 "- v2: (220,221)" "\n"
3871 " v3: (230,231,232)" "\n"
3872 " v4: (240,241,242,243)" "\n"
3882 " 21001: 22001" "\n"
3883 " 21002: 22002" "\n"
3884 " 21003: 22003" "\n"
3890 std::vector<my_type> vmt;
3892 CHECK(vmt.size() == 3);
3904 std::vector<double> reference{1.23234412342131234, 2.12323123143434237, 3.67847983572591234};
3908 const double precision_safe = 1.e-14;
3909 const size_t num_digits_safe = 14;
3910 const size_t num_digits_original = 17;
3911 auto get_num_digits = [](
ryml::csubstr number){
return number.len - 2u; };
3917 std::vector<double> output;
3919 CHECK(output.size() == reference.size());
3920 for(
size_t i = 0; i < reference.size(); ++i)
3923 CHECK(fabs(output[i] - reference[i]) < precision_safe);
3932 serialized.
rootref() << reference;
3933 std::cout << serialized;
3935 #if (!C4CORE_HAVE_STD_TOCHARS)
3940 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
3941 C4_UNUSED(num_digits_safe);
3945 "- 1.2323441234213124" "\n"
3946 "- 2.1232312314343424" "\n"
3947 "- 3.6784798357259123" "\n"
3948 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
3952 CHECK(get_num_digits(child.val()) >= num_digits_safe);
3955 CHECK(fabs(out - reference[pos++]) < precision_safe);
3986 auto check_precision = [&](
ryml::Tree const& serialized){
3987 std::cout << serialized;
3990 "- 1.23234412342131239" "\n"
3991 "- 2.12323123143434245" "\n"
3992 "- 3.67847983572591231" "\n"
3993 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
3997 CHECK(get_num_digits(child.val()) == num_digits_original);
4000 CHECK(fabs(out - reference[pos++]) < precision_safe);
4009 for(
const double v : reference)
4011 check_precision(serialized);
4020 for(
const double v : reference)
4025 (void)snprintf(tmp,
sizeof(tmp),
"%.18g", v);
4031 check_precision(serialized);
4051 "- champagne: Dom Perignon" "\n"
4052 " coffee: Arabica" "\n"
4054 " vinho verde: Soalheiro" "\n"
4055 " vinho tinto: Redoma 2017" "\n"
4057 " - Rochefort 10" "\n"
4059 " - Leffe Rituel" "\n"
4078 size_t num_needed_chars = output.
len;
4079 std::vector<char> buf(num_needed_chars);
4082 CHECK(output == ymla);
4090 num_needed_chars = output.
len;
4091 buf.resize(num_needed_chars);
4094 CHECK(output == ymlb);
4099 CHECK(output == ymlb);
4110 " vinho verde: Soalheiro" "\n"
4111 " vinho tinto: Redoma 2017" "\n"
4124 size_t num_needed_chars = output.
len;
4126 buf.resize(num_needed_chars);
4129 CHECK(output == ymla);
4137 num_needed_chars = output.
len;
4138 buf.resize(num_needed_chars);
4141 CHECK(output == ymlb);
4146 CHECK(output == ymlb);
4157 " vinho verde: Soalheiro" "\n"
4158 " vinho tinto: Redoma 2017" "\n"
4174 "- champagne: Dom Perignon" "\n"
4175 " coffee: Arabica" "\n"
4177 " vinho verde: Soalheiro" "\n"
4178 " vinho tinto: Redoma 2017" "\n"
4180 " - Rochefort 10" "\n"
4182 " - Leffe Rituel" "\n"
4194 std::stringstream ss;
4202 std::stringstream ss;
4214 " \"champagne\": \"Dom Perignon\"," "\n"
4215 " \"coffee\": \"Arabica\"," "\n"
4217 " \"vinho verde\": \"Soalheiro\"," "\n"
4218 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4221 " \"Rochefort 10\"," "\n"
4223 " \"Leffe Rituel\"" "\n"
4236 std::stringstream ss;
4241 " vinho verde: Soalheiro" "\n"
4242 " vinho tinto: Redoma 2017" "\n"
4248 std::stringstream ss;
4253 " \"vinho verde\": \"Soalheiro\"," "\n"
4254 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4271 "- champagne: Dom Perignon" "\n"
4272 " coffee: Arabica" "\n"
4274 " vinho verde: Soalheiro" "\n"
4275 " vinho tinto: Redoma 2017" "\n"
4277 " - Rochefort 10" "\n"
4279 " - Leffe Rituel" "\n"
4305 "- champagne: Dom Perignon" "\n"
4306 " coffee: Arabica" "\n"
4308 " vinho verde: Soalheiro" "\n"
4309 " vinho tinto: Redoma 2017" "\n"
4311 " - Rochefort 10" "\n"
4313 " - Leffe Rituel" "\n"
4315 " - many other" "\n"
4316 " - wonderful beers" "\n"
4326 " - Rochefort 10" "\n"
4328 " - Leffe Rituel" "\n"
4330 " - many other" "\n"
4331 " - wonderful beers" "\n"
4338 "- Rochefort 10" "\n"
4340 "- Leffe Rituel" "\n"
4342 " - many other" "\n"
4343 " - wonderful beers" "\n"
4350 "- wonderful beers" "\n"
4356 " - many other" "\n"
4357 " - wonderful beers" "\n"
4384 " block key: block val" "\n"
4386 " - block val 1" "\n"
4387 " - block val 2" "\n"
4389 "flow map, singleline: {flow key: flow val}" "\n"
4390 "flow seq, singleline: [flow val,flow val]" "\n"
4391 "flow map, multiline: {" "\n"
4392 " flow key: flow val" "\n"
4394 "flow seq, multiline: [" "\n"
4402 CHECK(tree[
"block map"].is_key_plain());
4403 CHECK(tree[
"block seq"].is_key_plain());
4404 CHECK(tree[
"flow map, singleline"].is_key_plain());
4405 CHECK(tree[
"flow seq, singleline"].is_key_plain());
4406 CHECK(tree[
"flow map, multiline"].is_key_plain());
4407 CHECK(tree[
"flow seq, multiline"].is_key_plain());
4408 CHECK(tree[
"block map"].is_block());
4409 CHECK(tree[
"block seq"].is_block());
4411 CHECK(tree[
"flow map, singleline"].is_flow_sl());
4412 CHECK(tree[
"flow seq, singleline"].is_flow_sl());
4413 CHECK(tree[
"flow map, multiline"].is_flow_ml1());
4414 CHECK(tree[
"flow seq, multiline"].is_flow_ml1());
4416 CHECK(tree[
"flow map, singleline"].is_flow());
4417 CHECK(tree[
"flow seq, singleline"].is_flow());
4418 CHECK(tree[
"flow map, multiline"].is_flow());
4419 CHECK(tree[
"flow seq, multiline"].is_flow());
4425 CHECK(tostr(tree) == yaml);
4436 " block key: block val\n"
4443 "'block map': {block key: block val}\n"
4449 CHECK(tostr(n) ==
""
4458 CHECK(tostr(n) ==
""
4459 "\"block seq\": [\n"
4460 " block val 1,block val 2,quoted\n"
4463 CHECK(tostr(n) ==
""
4464 "\"block seq\": [\n"
4465 " block val 1, block val 2, quoted\n"
4468 CHECK(tostr_opts(n, maxcols20) ==
""
4469 "\"block seq\": [\n"
4470 " block val 1, block val 2,\n"
4474 CHECK(tostr_opts(n, maxcols20) ==
""
4475 "\"block seq\": [\n"
4476 " block val 1,block val 2,\n"
4480 CHECK(tostr(n) ==
""
4481 "\"block seq\": [block val 1,block val 2,quoted]\n");
4483 CHECK(tostr(n) ==
""
4484 "\"block seq\": [block val 1, block val 2, quoted]\n");
4486 CHECK(tostr(n) ==
""
4487 "\"block seq\": [\n"
4498 CHECK(tostr(n) ==
"flow map, singleline: {flow key: flow val}\n");
4501 CHECK(tostr(n) ==
""
4502 "flow map, singleline:\n"
4510 CHECK(tostr(n) ==
""
4511 "flow map, multiline: {\n"
4512 " flow key: flow val\n"
4516 CHECK(tostr(n) ==
""
4517 "flow map, multiline:\n"
4518 " flow key: flow val\n"
4524 CHECK(tostr(n) ==
"flow seq, singleline: [flow val,flow val]\n");
4529 CHECK(tostr(n) ==
""
4531 " flow seq, singleline\n"
4540 CHECK(tostr(n) ==
""
4541 "flow seq, multiline: [\n"
4547 CHECK(tostr(n) ==
"flow seq, multiline: [flow val,flow val]\n");
4550 CHECK(tostr(tree) != yaml);
4551 CHECK(tostr(tree) ==
4552 "'block map': {block key: block val}" "\n"
4553 "\"block seq\": [" "\n"
4554 " block val 1," "\n"
4555 " block val 2," "\n"
4558 "flow map, singleline:" "\n"
4559 " flow key: |-" "\n"
4562 " flow seq, singleline" "\n"
4564 " - 'flow val'" "\n"
4565 " - \"flow val\"" "\n"
4566 "flow map, multiline:" "\n"
4567 " flow key: flow val" "\n"
4568 "flow seq, multiline: [flow val,flow val]" "\n"
4573 CHECK(tostr(tree) ==
4575 " block key: block val" "\n"
4577 " - block val 1" "\n"
4578 " - block val 2" "\n"
4580 "flow map, singleline:" "\n"
4581 " flow key: |-" "\n"
4584 " flow seq, singleline" "\n"
4586 " - 'flow val'" "\n"
4587 " - \"flow val\"" "\n"
4588 "flow map, multiline:" "\n"
4589 " flow key: flow val" "\n"
4590 "flow seq, multiline: [flow val,flow val]" "\n"
4599 CHECK(tostr(tree) ==
4601 " block key: block val" "\n"
4603 " - block val 1" "\n"
4604 " - block val 2" "\n"
4606 "flow map, singleline:" "\n"
4607 " flow key: flow val" "\n"
4608 "flow seq, singleline:" "\n"
4611 "flow map, multiline:" "\n"
4612 " flow key: flow val" "\n"
4613 "flow seq, multiline:" "\n"
4624 CHECK(tostr(tree) ==
4626 " block key: block val" "\n"
4628 " - block val 1" "\n"
4629 " - block val 2" "\n"
4631 "flow map, singleline:" "\n"
4632 " flow key: flow val" "\n"
4633 "flow seq, singleline:" "\n"
4636 "flow map, multiline:" "\n"
4637 " flow key: flow val" "\n"
4638 "flow seq, multiline:" "\n"
4663 CHECK(tostr(tree) ==
""
4665 " 'block key': \"block val\"" "\n"
4666 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
4667 "'flow map, singleline':" "\n"
4668 " 'flow key': \"flow val\"" "\n"
4669 "'flow seq, singleline': [\"flow val\",\"flow val\"]" "\n"
4670 "'flow map, multiline':" "\n"
4671 " 'flow key': \"flow val\"" "\n"
4672 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
4679 CHECK(tostr(tree) ==
""
4681 " 'block key': \"block val\"" "\n"
4682 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
4683 "'flow map, singleline':" "\n"
4684 " 'flow key': \"flow val\"" "\n"
4685 "'flow seq, singleline':" "\n"
4686 " - \"flow val\"" "\n"
4687 " - \"flow val\"" "\n"
4688 "'flow map, multiline':" "\n"
4689 " 'flow key': \"flow val\"" "\n"
4690 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
4732 CHECK(tree[
"map"].is_flow_ml1());
4733 CHECK(tree[
"map"][
"seq"].is_flow_ml1());
4734 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
4736 CHECK(tostr(tree, emit_defaults) == yaml);
4738 CHECK(tostr_json(tree, emit_defaults) ==
4759 CHECK(tree[
"map"].is_flow_sl());
4761 CHECK(tostr(tree, emit_defaults) ==
4762 "{map: {seq: [0,1,2,3,[40,41]]}}");
4764 CHECK(tostr_json(tree, emit_defaults) ==
4765 "{\"map\": {\"seq\": [0,1,2,3,[40,41]]}}");
4770 CHECK(tostr(tree, with_spaces) ==
4771 "{map: {seq: [0, 1, 2, 3, [40, 41]]}}");
4773 CHECK(tostr_json(tree, with_spaces) ==
4774 "{\"map\": {\"seq\": [0, 1, 2, 3, [40, 41]]}}");
4783 CHECK(tree[
"map"].is_flow_mln());
4784 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
4785 CHECK(tostr(tree, emit_defaults) ==
4789 " 0,1,2,3,[40,41]" "\n"
4793 CHECK(tostr_json(tree, emit_defaults) ==
4797 " 0,1,2,3,[40,41]" "\n"
4804 CHECK(tostr(tree, with_spaces) ==
4808 " 0, 1, 2, 3, [40, 41]" "\n"
4812 CHECK(tostr_json(tree, with_spaces) ==
4816 " 0, 1, 2, 3, [40, 41]" "\n"
4827 CHECK(tree[
"map"].is_flow_ml1());
4828 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
4829 CHECK(tostr(tree, noindent) ==
""
4842 CHECK(tostr_json(tree, noindent) ==
""
4861 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9," "\n"
4862 " 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, " "\n"
4863 " 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, " "\n"
4864 " 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, " "\n"
4865 " 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, " "\n"
4866 " 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, " "\n"
4867 " 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, " "\n"
4868 " 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 " "\n"
4879 CHECK(tostr(tree, emit_defaults) ==
""
4881 " 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"
4882 " 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"
4883 " 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"
4886 CHECK(tostr_json(tree, emit_defaults) ==
""
4888 " 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"
4889 " 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"
4890 " 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"
4896 CHECK(tostr(tree, maxcols40) ==
""
4898 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
4899 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
4900 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
4901 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
4902 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
4903 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
4906 CHECK(tostr_json(tree, maxcols40) ==
""
4908 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
4909 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
4910 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
4911 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
4912 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
4913 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
4920 CHECK(tostr(tree, with_spaces) ==
""
4922 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
4923 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
4924 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
4925 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
4928 CHECK(tostr_json(tree, with_spaces) ==
""
4930 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
4931 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
4932 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
4933 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
4940 CHECK(tostr(tree, maxcols40_spc) ==
""
4942 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
4943 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
4944 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
4945 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
4946 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
4947 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
4948 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
4949 " 72, 73, 74, 75, 76, 77, 78, 79\n"
4952 CHECK(tostr_json(tree, maxcols40_spc) ==
""
4954 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
4955 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
4956 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
4957 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
4958 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
4959 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
4960 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
4961 " 72, 73, 74, 75, 76, 77, 78, 79\n"
4969 CHECK(tostr(tree, maxcols40_spc_noindent) ==
""
4971 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
4972 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
4973 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
4974 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
4975 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
4976 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
4977 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
4978 "73, 74, 75, 76, 77, 78, 79\n"
4981 CHECK(tostr_json(tree, maxcols40_spc_noindent) ==
""
4983 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
4984 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
4985 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
4986 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
4987 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
4988 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
4989 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
4990 "73, 74, 75, 76, 77, 78, 79\n"
5009 ryml::csubstr yaml =
"{map: {seq: [0, 1, 2, 3, [40, 41]]}}";
5013 CHECK(tostr(tree, defaults) ==
"{map: {seq: [0,1,2,3,[40,41]]}}");
5020 CHECK(tostr(tree, defaults) ==
5038 CHECK(tostr(tree, noindent) ==
5057 CHECK(tostr(tree, noindent) ==
""
5073 CHECK(tostr(tree, noindent) ==
5099 " \"doe\": \"a deer, a female deer\"," "\n"
5100 " \"ray\": \"a drop of golden sun\"," "\n"
5101 " \"me\": \"a name, I call myself\"," "\n"
5102 " \"far\": \"a long long way to go\"" "\n"
5116 std::stringstream ss;
5118 CHECK(ss.str() == json);
5141 "\"doe\": \"a deer, a female deer\"" "\n"
5142 "\"ray\": \"a drop of golden sun\"" "\n"
5143 "\"me\": \"a name, I call myself\"" "\n"
5144 "\"far\": \"a long long way to go\"" "\n"
5152 "doe: a deer, a female deer" "\n"
5153 "ray: a drop of golden sun" "\n"
5154 "me: a name, I call myself" "\n"
5155 "far: a long long way to go" "\n"
5164 "doe: 'a deer, a female deer'" "\n"
5165 "ray: 'a drop of golden sun'" "\n"
5166 "me: 'a name, I call myself'" "\n"
5167 "far: 'a long long way to go'" "\n"
5197 std::string unresolved =
""
5199 " name: Everyone has same name" "\n"
5206 "bill_to: &id001" "\n"
5208 " 123 Tornado Alley" "\n"
5210 " city: East Centerville" "\n"
5212 "ship_to: *id001" "\n"
5213 "&keyref key: &valref val" "\n"
5214 "*valref : *keyref" "\n"
5216 std::string resolved =
""
5218 " name: Everyone has same name" "\n"
5220 " name: Everyone has same name" "\n"
5223 " name: Everyone has same name" "\n"
5227 " 123 Tornado Alley" "\n"
5229 " city: East Centerville" "\n"
5233 " 123 Tornado Alley" "\n"
5235 " city: East Centerville" "\n"
5243 CHECK( ! tree[
"base"].has_key_anchor());
5244 CHECK( tree[
"base"].has_val_anchor());
5245 CHECK( tree[
"base"].val_anchor() ==
"base");
5246 CHECK( tree[
"key"].key_anchor() ==
"keyref");
5247 CHECK( tree[
"key"].val_anchor() ==
"valref");
5248 CHECK( tree[
"*valref"].is_key_ref());
5249 CHECK( tree[
"*valref"].is_val_ref());
5250 CHECK( tree[
"*valref"].key_ref() ==
"valref");
5251 CHECK( tree[
"*valref"].val_ref() ==
"keyref");
5258 CHECK( ! tree[
"base"].has_key_anchor());
5259 CHECK( ! tree[
"base"].has_val_anchor());
5260 CHECK( ! tree[
"base"].has_val_anchor());
5261 CHECK( ! tree[
"key"].has_key_anchor());
5262 CHECK( ! tree[
"key"].has_val_anchor());
5263 CHECK( ! tree[
"val"].is_key_ref());
5264 CHECK( ! tree[
"val"].is_val_ref());
5266 CHECK(tree[
"ship_to"][
"city"].val() ==
"East Centerville");
5267 CHECK(tree[
"ship_to"][
"state"].val() ==
"KS");
5285 t[
"nref"] =
"*vanchor";
5287 "&kanchor kanchor: 2" "\n"
5288 "vanchor: &vanchor 3" "\n"
5289 "kref: *kanchor" "\n"
5290 "vref: *vanchor" "\n"
5293 "nref: '*vanchor'" "\n"
5299 "kref: kanchor" "\n"
5302 "nref: '*vanchor'" "\n"
5309 "orig: &orig {foo: bar, baz: bat}" "\n"
5317 t[
"notref"][
"<<"] =
"*orig";
5319 "orig: &orig {foo: bar,baz: bat}" "\n"
5320 "copy: {<<: *orig}" "\n"
5321 "notcopy: {test: *orig,<<: *orig}" "\n"
5322 "notref: {<<: '*orig'}" "\n"
5326 "orig: {foo: bar,baz: bat}" "\n"
5327 "copy: {foo: bar,baz: bat}" "\n"
5328 "notcopy: {test: {foo: bar,baz: bat},foo: bar,baz: bat}" "\n"
5329 "notref: {<<: '*orig'}" "\n"
5336 "orig1: &orig1 {foo: bar}" "\n"
5337 "orig2: &orig2 {baz: bat}" "\n"
5338 "orig3: &orig3 {and: more}" "\n"
5347 "orig1: &orig1 {foo: bar}" "\n"
5348 "orig2: &orig2 {baz: bat}" "\n"
5349 "orig3: &orig3 {and: more}" "\n"
5350 "copy: {<<: [*orig1,*orig2,*orig3]}" "\n"
5354 "orig1: {foo: bar}" "\n"
5355 "orig2: {baz: bat}" "\n"
5356 "orig3: {and: more}" "\n"
5357 "copy: {foo: bar,baz: bat,and: more}" "\n");
5366 const std::string yaml =
""
5375 "--- !!str a b" "\n"
5376 "--- !!str 'a: b'" "\n"
5393 CHECK(doc.is_doc());
5395 CHECK(root[0].has_val_tag());
5396 CHECK(root[0].val_tag() ==
"!!map");
5397 CHECK(root[1].val_tag() ==
"!map");
5398 CHECK(root[2].val_tag() ==
"!!seq");
5399 CHECK(root[3].val_tag() ==
"!!str");
5400 CHECK(root[4].val_tag() ==
"!!str");
5401 CHECK(root[5][
"a"].has_key_tag());
5402 CHECK(root[5][
"a"].key_tag() ==
"!!str");
5403 CHECK(root[6].val_tag() ==
"!!set");
5404 CHECK(root[7].val_tag() ==
"!!set");
5405 CHECK(root[8].val_tag() ==
"!!seq");
5406 CHECK(root[8][0].val_tag() ==
"!!int");
5407 CHECK(root[8][1].val_tag() ==
"!!str");
5465 "--- !!str a b" "\n"
5466 "--- !!str 'a: b'" "\n"
5481 "--- !<tag:yaml.org,2002:map>" "\n"
5486 "--- !<tag:yaml.org,2002:seq>" "\n"
5489 "--- !<tag:yaml.org,2002:str> a b" "\n"
5490 "--- !<tag:yaml.org,2002:str> 'a: b'" "\n"
5492 "!<tag:yaml.org,2002:str> a: b" "\n"
5493 "--- !<tag:yaml.org,2002:set>" "\n"
5496 "--- !<tag:yaml.org,2002:set>" "\n"
5498 "--- !<tag:yaml.org,2002:seq>" "\n"
5499 "- !<tag:yaml.org,2002:int> 0" "\n"
5500 "- !<tag:yaml.org,2002:str> 1" "\n"
5509 const std::string yaml =
""
5510 "%TAG !m! !my-" "\n"
5511 "--- # Bulb here" "\n"
5512 "!m!light fluorescent" "\n"
5514 "%TAG !m! !meta-" "\n"
5515 "--- # Color here" "\n"
5516 "!m!light green" "\n"
5521 "%TAG !m! !my-" "\n"
5522 "--- !m!light fluorescent" "\n"
5524 "%TAG !m! !meta-" "\n"
5525 "--- !m!light green" "\n"
5532 "%TAG !m! !my-" "\n"
5533 "--- !<!my-light> fluorescent" "\n"
5535 "%TAG !m! !meta-" "\n"
5536 "--- !<!meta-light> green" "\n"
5543 "%TAG !m! !my-" "\n"
5544 "--- !<!my-light> fluorescent" "\n"
5546 "%TAG !m! !meta-" "\n"
5547 "--- !<!meta-light> green" "\n"
5583 CHECK(doc.is_doc());
5602 CHECK(stream[0].is_doc());
5603 CHECK(stream[0].is_map());
5604 CHECK(stream[0][
"a"].val() ==
"0");
5605 CHECK(stream[0][
"b"].val() ==
"1");
5614 CHECK(stream[1].is_doc());
5615 CHECK(stream[1].is_map());
5616 CHECK(stream[1][
"c"].val() ==
"2");
5617 CHECK(stream[1][
"d"].val() ==
"3");
5626 CHECK(stream[2].is_doc());
5627 CHECK(stream[2].is_seq());
5628 CHECK(stream[2][0].val() ==
"4");
5629 CHECK(stream[2][1].val() ==
"5");
5630 CHECK(stream[2][2].val() ==
"6");
5631 CHECK(stream[2][3].val() ==
"7");
5669 return ryml::emitrs_json<std::string>(err_tree, err_opts);
5673 const std::string expected_json[] = {
5732 ryml::Tree tree = ryml::parse_in_arena(
"errorhandler.yml",
"[a: b\n}");
5743 auto cause_basic_error = []{
5752#ifdef _RYML_WITH_EXCEPTIONS
5756 cause_basic_error();
5778 auto cause_parse_error = [&]{
5802 msg_ctx.append(s.
str, s.
len);
5804 CHECK(
ryml::to_csubstr(msg_ctx).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
5806 "file.yml:3: col=4 (12B): err:" "\n"
5812 "err: see region:" "\n"
5847 CHECK(errh.
saved_msg_full ==
"file.yml:3: col=4 (12B): ERROR: [basic] invalid character: '['");
5860#ifdef _RYML_WITH_EXCEPTIONS
5864 cause_parse_error();
5876 CHECK(msg ==
"invalid character: '['");
5881 auto dumpfn = [&full](
ryml::csubstr s) { full.append(s.str, s.len); };
5885 CHECK(
ryml::to_csubstr(full).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
5887 "file.yml:3: col=4 (12B): err:" "\n"
5893 "err: see region:" "\n"
5906 cause_parse_error();
5932 tree[
"float"] >> intval;
5961 tree[
"float"] >> intval;
5973#ifdef _RYML_WITH_EXCEPTIONS
5985 tree[
"float"] >> intval;
6006 tree[
"float"] >> intval;
6043 "float: 123.456" "\n"
6047 auto cause_visit_error = [&]{
6049 tree[
"float"] >> intval;
6081 msg.append(s.
str, s.
len);
6082 }, ymlloc, ymlsrc,
"err", 3);
6084 "file.yml:3: col=0 (24B): err:" "\n"
6086 "err: float: 123.456" "\n"
6090 "err: see region:" "\n"
6092 "err: foo: bar" "\n"
6095 "err: float: 123.456" "\n"
6136 uintptr_t uptr = (uintptr_t)ptr;
6137 const uintptr_t align =
alignof(max_align_t);
6140 uintptr_t prev = uptr - (uptr % align);
6141 uintptr_t next = prev + align;
6142 uintptr_t corr = next - uptr;
6143 ptr = (
void*)(((
char*)ptr) + corr);
6147 "out of memory! requested=%zu+%zu available=%zu\n",
6173 static void s_free(
void *mem,
size_t len,
void *this_)
6245 parse_in_arena(&parser,
"", R
"([a, b, c, d, {foo: bar, money: pennys}])", &tree);
6288 std::cerr <<
"out of memory! requested=" <<
alloc_size <<
" vs " <<
memory_pool.size() <<
" available" << std::endl;
6374 CHECK(tree["doe"].val() ==
"a deer, a female deer");
6390 "aa: contents," "\n"
6391 "foo: [one, [two, three]]" "\n"
6435 loc = tree[
"foo"].
location(parser);
6440 loc = tree[
"foo"][0].
location(parser);
6445 loc = tree[
"foo"][1].
location(parser);
6449 loc = tree[
"foo"][1][0].
location(parser);
6453 loc = tree[
"foo"][1][1].
location(parser);
6475 "a new: buffer" "\n"
6476 "to: be parsed" "\n"
6477 "map with key:" "\n"
6478 " first: value" "\n"
6479 " second: value" "\n"
6480 "seq with key:" "\n"
6481 " - first value" "\n"
6482 " - second value" "\n"
6484 " - nested first value" "\n"
6485 " - nested second value" "\n"
6487 " nested first: value" "\n"
6488 " nested second: value" "\n"
6502 loc = tree2[
"a new"].
location(parser);
6507 loc = tree2[
"to"].
location(parser);
6513 loc = tree2[
"map with key"].
location(parser);
6517 loc = tree2[
"map with key"][
"first"].
location(parser);
6521 loc = tree2[
"map with key"][
"second"].
location(parser);
6526 loc = tree2[
"seq with key"].
location(parser);
6530 loc = tree2[
"seq with key"][0].
location(parser);
6534 loc = tree2[
"seq with key"][1].
location(parser);
6539 loc = tree2[
"seq with key"][2].
location(parser);
6543 loc = tree2[
"seq with key"][2][0].
location(parser);
6548 loc = tree2[
"seq with key"][3].
location(parser);
6552 loc = tree2[
"seq with key"][3][0].
location(parser);
6568static int num_checks = 0;
6569static int num_failed_checks = 0;
6570static bool quiet_mode =
false;
6575 auto arg_matches = [](
const char *arg,
const char *shortform,
const char *longform) {
6576 return (0 == strcmp(arg, shortform) || 0 == strcmp(arg, longform));
6578 for(
int i = 1; i < argc; ++i)
6579 if(arg_matches(argv[i],
"-q",
"--quiet"))
6586 const char *msg = predicate ?
"OK! " :
"OK!";
6589 ++num_failed_checks;
6590 msg = predicate ?
"FAIL: " :
"FAIL";
6592 if(!result || !quiet_mode)
6594 std::cout << __FILE__ <<
':' << line <<
": " << msg << (predicate ? predicate :
"") << std::endl;
6602 std::cout <<
"Completed " << num_checks <<
" checks." << std::endl;
6603 if(num_failed_checks)
6604 std::cout <<
"ERROR: " << num_failed_checks <<
'/' << num_checks <<
" checks failed." << std::endl;
6606 std::cout <<
"SUCCESS!" << std::endl;
6607 return num_failed_checks;
6622 fwrite(s.
str, 1, s.
len, stderr);
6628 fputc(
'\n', stderr);
6643 .set_free([](
void* mem,
size_t,
void *){
6679#ifdef RYML_NO_DEFAULT_CALLBACKS
6688#ifndef C4_EXCEPTIONS
6719 bool got_error =
false;
6720 #ifdef C4_EXCEPTIONS
6723 std::forward<Fn>(fn)();
6725 catch(std::exception
const&)
6732 std::forward<Fn>(fn)();
6745[[noreturn]]
void stopexec(std::string
const& s)
6747 #ifdef C4_EXCEPTIONS
6748 throw std::runtime_error(s);
6873C4_SUPPRESS_WARNING_GCC_CLANG_POP
Holds a pointer to an existing tree, and a node id.
id_type id() const noexcept
bool invalid() const noexcept
Tree const * tree() const noexcept
bool readable() const noexcept
because a ConstNodeRef cannot be used to write to the tree, readable() has the same meaning as !...
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
void set_key_style(NodeType_e style)
void set_style_conditionally(NodeType type_mask, NodeType rem_style_flags, NodeType add_style_flags, bool recurse=false)
void clear_style(bool recurse=false)
void set_val_style(NodeType_e style)
id_type id() const noexcept
bool invalid() const noexcept
true if the object is not referring to any existing or seed node.
void set_container_style(NodeType_e style)
bool readable() const noexcept
true if the object is not invalid and not in seed state.
size_t set_val_serialized(T const &v)
bool is_seed() const noexcept
true if the object is not invalid and in seed state.
void set_val_ref(csubstr val_ref)
void reserve_stack(id_type capacity)
Reserve a certain capacity for the parsing stack.
csubstr location_contents(Location const &loc) const
Get the string starting at a particular location, to the end of the parsed source buffer.
ParserOptions const & options() const
Get the options used to build this parser object.
Callbacks const & callbacks() const
Get the current callbacks in the parser.
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 clear()
clear the tree and zero every node
csubstr const & key(id_type node) const
id_type first_child(id_type node) const
bool is_stream(id_type node) const
void set_val_ref(id_type node, csubstr ref)
id_type root_id() const
Get the id of the root node. The tree must not be empty.
NodeRef rootref()
Get the root as a NodeRef.
void resolve_tags(TagCache &cache, bool all=true)
Resolve tags in the tree such as "!!str" -> "<tag:yaml.org,2002:str>", "!foo" -> "<!...
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 is_map(id_type node) const
void reserve(id_type node_capacity=RYML_DEFAULT_TREE_CAPACITY)
csubstr const & val(id_type node) const
bool is_root(id_type node) const
substr alloc_arena(size_t sz)
grow the tree's string arena by the given size and return a substr of the added portion
bool in_arena(csubstr s) const
return true if the given substring is part of the tree's string arena
void clear_style(id_type node, bool recurse=false)
id_type next_sibling(id_type node) const
ConstNodeRef crootref() const
Get the root as a ConstNodeRef.
id_type id(NodeData const *n) const
get the index of a node belonging to this tree. n can be nullptr, in which case NONE is returned
void set_style_conditionally(id_type node, NodeType type_mask, NodeType rem_style_flags, NodeType add_style_flags, bool recurse=false)
csubstr to_arena(T const &a)
serialize the given variable to the tree's arena, growing it as needed to accomodate the serializatio...
void set_val_anchor(id_type node, csubstr anchor)
NodeRef docref(id_type i)
get the i-th document of the stream
bool is_doc(id_type node) const
void set_container_style(id_type node, NodeType_e style)
Callbacks const & callbacks() const
size_t arena_capacity() const
get the current capacity of the tree's internal arena
id_type doc(id_type i) const
gets the i document node index.
void set_val(id_type node, csubstr val)
void normalize_tags_long()
void resolve(ReferenceResolver *rr, bool clear_anchors=true)
Resolve references (aliases <- anchors), by forwarding to ReferenceResolver::resolve(); refer to Refe...
bool is_seq(id_type node) const
id_type find_child(id_type node, csubstr const &key) const
Location location(Parser const &p, id_type node) const
Get the location of a node from the parse used to parse this tree.
void add_tag_directive(csubstr handle, csubstr prefix, id_type id)
id_type first_sibling(id_type node) const
substr copy_to_arena(csubstr s)
copy the given string to the tree's arena, growing the arena by the required size.
id_type num_children(id_type node) const
O(num_children).
csubstr arena() const
get the current arena
id_type child(id_type node, id_type pos) const
void set_key_anchor(id_type node, csubstr anchor)
Definitions of error utilities used by ryml.
right_< T > right(T val, size_t width, char padchar=' ')
tag function to mark an argument to be aligned right
left_< T > left(T val, size_t width, char padchar=' ')
tag type to mark an argument to be aligned left.
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
void set_callbacks(Callbacks const &c)
set the global callbacks for the library; after a call to this function, these callbacks will be used...
Callbacks const & get_callbacks()
get the global callbacks
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...
size_t cat(substr buf, Arg const &a, Args const &...more)
serialize the arguments, concatenating them to the given fixed-size buffer.
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.
substr cat_sub(substr buf, Args const &...args)
like c4::cat() but return a substr instead of a size
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 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...
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...
substr catsep_sub(substr buf, Args &&...args)
like c4::catsep() but return a substr instead of a size
@ FTOA_FLEX
print the real number in flexible format (like g)
@ FTOA_SCIENT
print the real number in scientific format (like e)
@ FTOA_FLOAT
print the real number in floating point format (like f)
@ FTOA_HEXA
print the real number in hexadecimal format (like a)
EmitOptions & max_cols(id_type cols) noexcept
Set max columns for the emitted YAML in FLOW_MLN mode.
EmitOptions & json_err_on_stream(bool enabled) noexcept
Whether to trigger an error when findind a stream in json mode.
bool indent_flow_ml() const noexcept
Indent the contents of FLOW_ML1 and FLOW_MLN containers.
EmitOptions & emit_nonroot_key(bool enabled) noexcept
When emit starts on a node which is not the root node, emit the node key as well.
EmitOptions & emit_nonroot_dash(bool enabled) noexcept
When emit starts on a node which is not the root node, emit a leading dash.
EmitOptions & force_flow_spc(bool enabled) noexcept
Force everywhere a space after comma in flow mode, overriding the FLOW_SPC status of individual conta...
substr emitrs_json(Tree const &t, id_type id, EmitOptions const &opts, CharOwningContainer *cont, bool append=false)
(1) emit+resize: emit JSON to the given std::string/std::vector-like container, resizing it as needed...
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...
size_t emit_yaml(Tree const &t, id_type id, EmitOptions const &opts, FILE *f)
(1) emit YAML to the given file, starting at the given node.
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.
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.
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.
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.
void file_get_contents(const char *filename, FILE *fp, size_t filesz, void *buf, size_t bufsz)
load a file of specified size from disk into an existing contiguous buffer.
void file_put_contents(void const *buf, size_t sz, const char *filename, const char *access="wb")
save a contiguous buffer into a file
integral_< intptr_t > hex(std::nullptr_t)
format null as an hexadecimal value
integral_< intptr_t > oct(std::nullptr_t)
format null as an octal value
integral_< intptr_t > bin(std::nullptr_t)
format null as a binary 0-1 value
bool scalar_is_null(csubstr s) noexcept
YAML-sense query of nullity.
@ KEY_DQUO
mark key scalar as double quoted "
@ MAP
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
@ KEY
the scalar to the left of : in a map's member
@ FLOW_ML1
mark container with multi-line flow style, 1 element per line
@ VAL_STYLE
mask of VALQUO|VAL_PLAIN : all the val scalar styles for val (not container styles!...
@ FLOW_SL
mark container with single-line flow style
@ VAL
a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or S...
@ FLOW_MLN
mark container with multi-line flow style, n elements per line, wrapped (as set by EmitOptions::max_c...
@ SEQ
a seq: a parent of VAL/SEQ/MAP nodes
@ VAL_SQUO
mark val scalar as single quoted '
@ KEY_STYLE
mask of KEYQUO|KEY_PLAIN : all the key scalar styles for key (not container styles!...
@ VAL_PLAIN
mark val scalar as plain scalar (unquoted, even when multiline)
@ BLOCK
mark container with block style
@ FLOW_SPC
mark container with spaces after comma when in flow mode. Applies to both FLOW_SL and FLOW_MLN (but n...
@ VAL_DQUO
mark val scalar as double quoted "
@ CONTAINER_STYLE
mask of CONTAINER_STYLE_FLOW|CONTAINER_STYLE_BLOCK : all container style flags
@ KEY_SQUO
mark key scalar as single quoted '
@ VAL_LITERAL
mark val scalar as multiline, block literal |
@ KEY_FOLDED
mark key scalar as multiline, block folded >
auto overflows(csubstr str) noexcept -> typename std::enable_if< std::is_unsigned< T >::value, bool >::type
Test if the following string would overflow when converted to associated integral types; this functio...
void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *t, id_type node_id)
(1) parse YAML into an existing tree node. The filename will be used in any error messages arising du...
void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *t, id_type node_id)
(1) parse JSON into an existing tree node. The filename will be used in any error messages arising du...
void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *t, id_type node_id)
(1) parse YAML into an existing tree node.
ParseEngine< EventHandlerTree > Parser
This is the main ryml parser, where the parser events are handled to create a ryml tree (see Event Ha...
void sample_anchors_and_aliases()
demonstrates usage with anchors and alias references.
void sample_emit_to_file()
demonstrates how to emit to a FILE*
void sample_formatting()
ryml provides facilities for formatting/deformatting (imported from c4core into the ryml namespace).
void sample_quick_overview()
a brief tour over most features
void sample_style_flow_ml_indent()
control the indentation of emitted flow multiline containers
void sample_per_tree_allocator()
void sample_lightning_overview()
a lightning tour over most features see sample_quick_overview
void sample_user_container_types()
shows how to serialize/deserialize container types.
void sample_empty_null_values()
Shows how to deal with empty/null values.
void sample_global_allocator()
demonstrates how to set the global allocator for ryml
void sample_base64()
demonstrates how to read and write base64-encoded blobs.
void sample_error_visit()
Visit errors happen when an error is triggered while reading from a node.
void sample_static_trees()
shows how to work around the static initialization order fiasco when using a static-duration ryml tre...
void sample_parse_file()
demonstrate how to load a YAML file from disk to parse with ryml.
void sample_json()
shows how to parse and emit JSON.
void sample_error_parse()
void sample_parse_in_arena()
demonstrate parsing of a read-only YAML source buffer
void sample_emit_nested_node()
just like parsing into a nested node, you can also emit from a nested node.
void sample_style()
query/set/modify node style to control formatting of emitted YAML code.
void sample_location_tracking()
demonstrates how to obtain the (zero-based) location of a node from a recently parsed tree
void sample_parse_reuse_parser()
Demonstrates reuse of an existing parser.
void sample_iterate_trees()
shows how to programatically iterate through trees
void sample_style_flow_formatting()
Shows how to control formatting of flow styles.
void sample_create_trees()
shows how to programatically create trees
void sample_parse_reuse_tree_and_parser()
for ultimate speed when parsing multiple times, reuse both the tree and parser
void sample_emit_to_container()
demonstrates how to emit to a linear container of char
void sample_parse_in_place()
demonstrate in-place parsing of a mutable YAML source buffer.
void sample_fundamental_types()
ryml provides facilities for serializing and deserializing the C++ fundamental types,...
void sample_std_types()
demonstrates usage with the std implementations provided by ryml in the ryml_std.hpp header
void sample_float_precision()
control precision of serialized floats
void sample_anchors_and_aliases_create()
demonstrates how to use the API to programatically create anchors and aliases
void sample_user_scalar_types()
to add scalar types (ie leaf types converting to/from string), define the functions above for those t...
void sample_error_visit_location()
It is possible to obtain the YAML location from a visit error: when the tree is obtained from parsing...
void sample_error_basic()
void sample_tag_directives()
void sample_error_handler()
demonstrates how to set a custom error handler for ryml
void sample_emit_to_stream()
demonstrates how to emit to a stream-like structure
void sample_tree_arena()
demonstrates explicit and implicit interaction with the tree's string arena.
void sample_parse_reuse_tree()
demonstrate reuse/modification of tree when parsing
void sample_substr()
demonstrate usage of ryml::substr and ryml::csubstr
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
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
real_< T > real(T val, int precision, RealFormat_e fmt=FTOA_FLOAT)
void write(ryml::NodeRef *n, my_seq_type< T > const &seq)
bool read(ryml::ConstNodeRef const &n, my_seq_type< T > *seq)
bool from_chars(ryml::csubstr buf, vec2< T > *v)
static void s_error_basic(ryml::csubstr msg, ryml::ErrorDataBasic const &errdata, void *this_)
trampoline function to call the object's method
bool report_check(int line, const char *predicate, bool result)
static void s_error_parse(ryml::csubstr msg, ryml::ErrorDataParse const &errdata, void *this_)
trampoline function to call the object's method
bool check_assertion_occurs(Fn &&fn)
checking that an assertion occurs while calling fn.
void on_error_visit(ryml::csubstr msg, ryml::ErrorDataVisit const &errdata)
this is where the callback implementation goes.
static std::string s_jmp_msg
void ensure_callbacks()
set up default callbacks when ryml does not provide them (ie when RYML_NO_DEFAULT_CALLBACKS is define...
static void s_error_visit(ryml::csubstr msg, ryml::ErrorDataVisit const &errdata, void *this_)
trampoline function to call the object's method
void on_error_parse(ryml::csubstr msg, ryml::ErrorDataParse const &errdata)
this is where the callback implementation goes.
bool check_error_occurs(Fn &&fn)
checking that an error occurs while calling fn
ryml::Callbacks default_callbacks()
a bare-bones implementation of the callbacks
void check_disabled() const
test that this handler is currently not set
#define CHECK(predicate)
a quick'n'dirty assertion to verify a predicate
ryml::Callbacks callbacks()
a helper to create the Callbacks object for the custom error handler
void on_error_basic(ryml::csubstr msg, ryml::ErrorDataBasic const &errdata)
this is where the callback implementation goes.
static std::jmp_buf s_jmp_env
void check_enabled() const
test that this handler is currently set
void handle_args(int argc, const char *argv[])
size_t to_chars(ryml::substr buf, vec2< T > v)
substr to_substr(char(&s)[N]) noexcept
csubstr to_csubstr(const char(&s)[N]) noexcept
basic_substring< char > substr
a mutable string view
basic_substring< const char > csubstr
an immutable string view
csubstr from_tag_long(YamlTag_e tag)
csubstr normalize_tag_long(csubstr tag)
csubstr normalize_tag(csubstr tag)
csubstr from_tag(YamlTag_e tag)
YamlTag_e to_tag(csubstr tag)
size_t uncat(csubstr buf, Arg &a, Args &...more)
deserialize the arguments from the given buffer.
size_t uncatsep(csubstr buf, csubstr sep, Arg &a, Args &...more)
deserialize the arguments from the given buffer, using a separator.
integral_padded_< T > zpad(T val, size_t num_digits)
pad the argument with zeroes on the left, with decimal radix
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...
@ npos
a null string position
int main(int, const char *[])
an example error handler, required for some of the quickstart examples.
ryml::Location saved_basic_loc
ryml::Callbacks original_callbacks
std::string saved_msg_full
ryml::id_type saved_visit_id
std::string saved_msg_short
ryml::Tree const * saved_visit_tree
ryml::Location saved_parse_loc
std::string saved_msg_full_with_context
void free(void *mem, size_t len)
~GlobalAllocatorExample()
std::vector< char > memory_pool
static void s_free(void *mem, size_t len, void *this_)
void * allocate(size_t len)
ryml::Callbacks callbacks()
static void * s_allocate(size_t len, void *, void *this_)
an example for a per-tree memory allocator
std::vector< char > memory_pool
ryml::Callbacks callbacks() const
void * allocate(size_t len)
void free(void *mem, size_t len)
Shows how to create a scoped error handler.
~ScopedErrorHandlerExample()
ScopedErrorHandlerExample()
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
size_t count(const C c, size_t pos=0) const
count the number of occurrences of c
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
basic_substring range(size_t first, size_t last=npos) const noexcept
return [first,last[.
size_t first_not_of(const C c) const
auto tolower() -> typename std::enable_if< !std::is_const< U >::value, void >::type
convert the string to lower-case
bool begins_with(const C c) const noexcept
true if the first character of the string is c
basic_substring triml(const C c) const
trim left
size_t last_of(const C c, size_t start=npos) const
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 fill(C val) -> typename std::enable_if< !std::is_const< U >::value, void >::type
fill the entire contents with the given val
size_t len
the length of the substring
basic_substring last(size_t num) const noexcept
return the last num elements: [len-num,len[
bool ends_with(const C c) const noexcept
true if the last character of the string is c
size_t first_of(const C c, size_t start=0) const
basic_substring stripl(ro_substr pattern) const
remove a pattern from the left
size_t find(const C c, size_t start_pos=0) const
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
basic_substring stripr(ro_substr pattern) const
remove a pattern from the right
size_t size() const noexcept
bool overlaps(ro_substr const that) const noexcept
true if there is overlap of at least one element between that and *this
basic_substring first(size_t num) const noexcept
return the first num elements: [0,num[
basic_substring left_of(size_t pos) const noexcept
return [0, pos[ .
basic_substring sub(size_t first) const noexcept
return [first,len[
bool ends_with_any(ro_substr chars) const noexcept
true if the last character of the string is any of the given chars
bool empty() const noexcept
basic_substring trimr(const C c) const
trim the character c from the right
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
bool is_super(ro_substr const that) const noexcept
true if that is a substring of *this (ie, from the same buffer)
size_t last_not_of(const C c) const
auto toupper() -> typename std::enable_if< ! std::is_const< U >::value, void >::type
convert the string to upper-case
C * str
a restricted pointer to the first character of the substring
basic_substring right_of(size_t pos) const noexcept
return [pos+1, len[
bool is_sub(ro_substr const that) const noexcept
true if *this is a substring of that (ie, from the same buffer)
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
auto reverse() -> typename std::enable_if< !std::is_const< U >::value, void >::type
reverse in place
A c-style callbacks class to customize behavior on errors or allocation.
pfn_error_basic m_error_basic
a pointer to a basic error handler function
pfn_error_parse m_error_parse
a pointer to a parse error handler function
Callbacks & set_error_visit(pfn_error_visit error_visit=nullptr)
Set or reset the error_visit callback.
Callbacks & set_free(pfn_free free=nullptr)
Set or reset the free callback.
void * m_user_data
data to be forwarded in every call to a callback
pfn_allocate m_allocate
a pointer to an allocate handler function
Callbacks & set_error_parse(pfn_error_parse error_parse=nullptr)
Set or reset the error_parse callback.
Callbacks & set_allocate(pfn_allocate allocate=nullptr)
Set or reset the allocate callback.
Callbacks & set_error_basic(pfn_error_basic error_basic=nullptr)
Set or reset the error_basic callback.
pfn_error_visit m_error_visit
a pointer to a visit error handler function
pfn_free m_free
a pointer to a free handler function
Callbacks & set_user_data(void *user_data)
Set the user data.
A lightweight object containing options to be used when emitting.
Location location
location where the error was detected (may be from YAML or C++ source code)
Location cpploc
location in the C++ source file where the error was detected.
Location ymlloc
location in the YAML source buffer where the error was detected.
Location cpploc
location in the C++ source file where the error was detected.
Tree const * tree
tree where the error was detected
id_type node
node where the error was detected
The event handler to create a ryml Tree.
Callbacks const & callbacks() const
Exception thrown by the default basic error implementation.
const char * what() const noexcept override
ErrorDataBasic errdata_basic
error data
Exception thrown by the default parse error implementation.
ErrorDataParse errdata_parse
Exception thrown by the default visit error implementation.
ErrorDataVisit errdata_visit
holds a source or yaml file position, for example when an error is detected; See also location_format...
size_t offset
number of bytes from the beginning of the source buffer
csubstr name
name of the file
bool is_flow_mln() const noexcept
Options to give to the parser to control its behavior.
ParserOptions & detect_flow_ml(bool enabled) noexcept
enable/disable detection of flow multiline container style.
ParserOptions & locations(bool enabled) noexcept
enable/disable source location tracking.
ParserOptions & resolve_tags(bool enabled) noexcept
enable/disable resolution of YAML tags during parsing.
ParserOptions & flow_ml_style(NodeType style) noexcept
choose the default style of multiline flow containers, when a container is detected as flow multiline...
Accelerator structure to reduce memory requirements by enabling reuse of resolved tags.
mark a tree or node to be emitted as yaml when using operator<<, with options.
auto first_child() RYML_NOEXCEPT -> Impl
Forward to Tree::first_child().
auto children() RYML_NOEXCEPT -> children_view
get an iterable view over children.
bool is_val() const RYML_NOEXCEPT
Forward to Tree::is_val().
bool is_root() const RYML_NOEXCEPT
Forward to Tree::is_root().
auto last_child() RYML_NOEXCEPT -> Impl
Forward to Tree::last_child().
bool is_stream() const RYML_NOEXCEPT
Forward to Tree::is_stream().
NodeType type() const RYML_NOEXCEPT
Forward to Tree::type().
auto parent() RYML_NOEXCEPT -> Impl
Forward to Tree::parent().
bool has_child(ConstImpl const &n) const RYML_NOEXCEPT
Forward to Tree::has_child().
auto next_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::next_sibling().
auto last_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::last_sibling().
bool is_map() const RYML_NOEXCEPT
Forward to Tree::is_map().
id_type num_siblings() const RYML_NOEXCEPT
O(num_children).
bool has_key() const RYML_NOEXCEPT
Forward to Tree::has_key().
csubstr key() const RYML_NOEXCEPT
Forward to Tree::key().
auto first_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::first_sibling().
csubstr val() const RYML_NOEXCEPT
Forward to Tree::val().
bool is_doc() const RYML_NOEXCEPT
Forward to Tree::is_doc().
id_type num_children() const RYML_NOEXCEPT
O(num_children).
auto child(id_type pos) RYML_NOEXCEPT -> Impl
Forward to Tree::child().
bool is_block() const RYML_NOEXCEPT
Forward to Tree::is_block().
Location location(Parser const &parser) const
bool is_seq() const RYML_NOEXCEPT
Forward to Tree::is_seq().
bool has_val() const RYML_NOEXCEPT
Forward to Tree::has_val().
auto prev_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::prev_sibling().
example scalar type, serialized only
example scalar type, serialized only
example scalar type, serialized only
example user container type: map-like
std::map< K, V > map_member
example user container type: seq-like
std::vector< T > seq_member
example user container type with nested container members.
my_map_type< int, int > map
example scalar type, deserialized only
example scalar type, deserialized only
example scalar type, deserialized only
example scalar type, serialized and deserialized
example scalar type, serialized and deserialized
example scalar type, serialized and deserialized