90#if defined(RYML_SINGLE_HEADER)
91 #define RYML_SINGLE_HDR_DEFINE_NOW
92 #include <ryml_all.hpp>
93#elif defined(RYML_SINGLE_HEADER_LIB)
94 #include <ryml_all.hpp>
106 #include <c4/format_base64.hpp>
177int main(
int argc,
const char* argv[])
233C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
234C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wcast-qual")
235C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wold-style-cast")
236C4_SUPPRESS_WARNING_GCC(
"-Wuseless-cast")
306bool report_check(
int line,
const char *predicate,
bool result);
309#if defined(__DOXYGEN__) || defined(_DOXYGEN_)
311# define CHECK(predicate) assert(predicate)
313# if !(defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
315# define CHECK(predicate) do { if(!report_check(__LINE__, #predicate, (predicate))) { RYML_DEBUG_BREAK(); } } while(0)
317# define CHECK CheckPredicate{__FILE__, __LINE__}
318 struct CheckPredicate
322 void operator() (
bool result)
const
345 char yml_buf[] =
"{foo: 1, bar: [2, 3], john: doe}";
350 CHECK(bar[0].val() ==
"2");
351 CHECK(bar[1].val() ==
"3");
352 CHECK(bar[0].val().str == yml_buf + 15);
353 CHECK(bar[1].val().str == yml_buf + 18);
356 int bar0 = 0, bar1 = 0;
365 CHECK(bar[0].val() ==
"10");
366 CHECK(bar[1].val() ==
"11");
370 CHECK(bar[2].val() ==
"12");
373 std::string expected =
"{foo: 1,bar: [10,11,12],john: doe}";
379 std::cout << tree <<
"\n";
383 expected =
"foo: 1\n";
468 CHECK(tree[
"foo"].is_keyval());
469 CHECK(tree[
"foo"].val() ==
"1");
470 CHECK(tree[
"foo"].key() ==
"foo");
471 CHECK(tree[
"bar"].is_seq());
472 CHECK(tree[
"bar"].has_key());
473 CHECK(tree[
"bar"].key() ==
"bar");
475 CHECK(tree[
"bar"][0].val() ==
"2");
476 CHECK(tree[
"bar"][1].val() ==
"3");
477 CHECK(tree[
"john"].val() ==
"doe");
481 CHECK(tree[0].
id() == tree[
"foo"].
id());
482 CHECK(tree[1].
id() == tree[
"bar"].
id());
483 CHECK(tree[2].
id() == tree[
"john"].
id());
485 CHECK(tree[0].
id() == tree[
"foo"].
id());
486 CHECK(tree[1].
id() == tree[
"bar"].
id());
487 CHECK(tree[2].
id() == tree[
"john"].
id());
489 CHECK(bar[0].val() ==
"2");
490 CHECK(bar[1].val() ==
"3");
495 CHECK(tree[
"foo"].key() ==
"foo");
496 CHECK(tree[
"bar"].key() ==
"bar");
497 CHECK(tree[
"john"].key() ==
"john");
502 CHECK(root[
"foo"].
id() == root[0].
id());
503 CHECK(root[
"bar"].
id() == root[1].
id());
504 CHECK(root[
"john"].
id() == root[2].
id());
563 CHECK(child.key() == expected_keys[count++]);
569 CHECK(child.key() == expected_keys[count++]);
575 CHECK(tree.
key(child_id) == expected_keys[count++]);
584 CHECK(tree.
key(child_id) == expected_keys[count++]);
644 int foo = 0, bar0 = 0, bar1 = 0;
645 std::string john_str;
648 root[
"bar"][0] >> bar0;
649 root[
"bar"][1] >> bar1;
650 root[
"john"] >> john_str;
655 CHECK(john_str ==
"doe");
656 CHECK(bar_str ==
"bar");
673 wroot[
"foo"].
set_val(
"says you");
680 CHECK(root[
"foo"].val() ==
"says you");
681 CHECK(root[
"bar"][0].val() ==
"-2");
682 CHECK(root[
"bar"][1].val() ==
"-3");
683 CHECK(root[
"john"].val() ==
"ron");
698 wroot[
"foo"] <<
"says who";
699 wroot[
"bar"][0] << 20;
700 wroot[
"bar"][1] << 30;
701 wroot[
"john"] <<
"deere";
702 CHECK(root[
"foo"].val() ==
"says who");
703 CHECK(root[
"bar"][0].val() ==
"20");
704 CHECK(root[
"bar"][1].val() ==
"30");
705 CHECK(root[
"john"].val() ==
"deere");
709 std::string ok(
"in_scope");
713 CHECK(root[
"john"].val() ==
"in_scope");
715 wroot[
"float"] << 2.4f;
719 CHECK(tree.
arena() ==
"says who2030deerein_scope2.42.400000");
727 wroot[
"newkeyval"].
set_val(
"shiny and new");
730 CHECK(root[
"newkeyval"].key() ==
"newkeyval");
731 CHECK(root[
"newkeyval"].val() ==
"shiny and new");
732 CHECK(root[
"newkeyval (serialized)"].key() ==
"newkeyval (serialized)");
733 CHECK(root[
"newkeyval (serialized)"].val() ==
"shiny and new (serialized)");
739 CHECK(root[
"bar"].num_children() == 2);
740 wroot[
"bar"][2].
set_val(
"oh so nice");
741 wroot[
"bar"][3] <<
"oh so nice (serialized)";
742 CHECK(root[
"bar"].num_children() == 4);
743 CHECK(root[
"bar"][2].val() ==
"oh so nice");
744 CHECK(root[
"bar"][3].val() ==
"oh so nice (serialized)");
750 CHECK(root[
"newseq"].num_children() == 0);
751 CHECK(root[
"newseq"].is_seq());
752 CHECK(root[
"newseq (serialized)"].num_children() == 0);
753 CHECK(root[
"newseq (serialized)"].is_seq());
759 CHECK(root[
"newmap"].num_children() == 0);
760 CHECK(root[
"newmap"].is_map());
761 CHECK(root[
"newmap (serialized)"].num_children() == 0);
762 CHECK(root[
"newmap (serialized)"].is_map());
795 nothing = wroot[
"I am nothing"];
812 CHECK(root[
"I am something"].val() ==
"indeed");
843 CHECK(wbar[0].readable() && wbar[0].val() ==
"20");
844 CHECK( ! wbar[100].readable());
845 CHECK( ! wbar[100].readable() || wbar[100].val() ==
"100");
847 CHECK( ! wbar[0].is_seed() && wbar[0].val() ==
"20");
848 CHECK(wbar[100].is_seed() || wbar[100].val() ==
"100");
876 return seed_node.at(
"is").at(
"an").at(
"invalid").at(
"operation");
883 return seed_node[
"is"][
"an"][
"invalid"][
"operation"];
895 "bar: [20,30,oh so nice,oh so nice (serialized)]" "\n"
896 "john: in_scope" "\n"
898 "digits: 2.400000" "\n"
899 "newkeyval: shiny and new" "\n"
900 "newkeyval (serialized): shiny and new (serialized)" "\n"
902 "newseq (serialized): []" "\n"
904 "newmap (serialized): {}" "\n"
905 "I am something: indeed" "\n"
914 std::stringstream ss;
916 std::string stream_result = ss.str();
923 CHECK(buf_result == expected_result);
924 CHECK(str_result == expected_result);
925 CHECK(stream_result == expected_result);
941 CHECK(tree[
"bar"][0].val() ==
"21");
943 CHECK(tree[
"bar"][0].val() ==
"22");
949 constnoderef = noderef;
955 noderef = tree[
"bar"][0];
956 constnoderef = consttree[
"bar"][0];
960 CHECK(constnoderef == noderef);
961 CHECK(!(constnoderef != noderef));
971 ryml::Tree tree2 = parse_in_arena(&parser,
"expected.yml", expected_result);
986 "# UTF8/16/32 can be placed directly in any scalar:" "\n"
988 "en: Planet (Gas)" "\n"
989 "fr: Planète (Gazeuse)" "\n"
990 "ru: Планета (Газ)" "\n"
994 "# UTF8 decoding only happens in double-quoted strings," "\n"
995 "# as per the YAML standard" "\n"
997 "decode this: \"\\u263A c\\x61f\\xE9\"" "\n"
998 "and this as well: \"\\u2705 \\U0001D11E\"" "\n"
999 "not decoded: '\\u263A \\xE2\\x98\\xBA'" "\n"
1000 "neither this: '\\u2705 \\U0001D11E'" "\n");
1002 CHECK(langs[
"en"].val() ==
"Planet (Gas)");
1003 CHECK(langs[
"fr"].val() ==
"Planète (Gazeuse)");
1004 CHECK(langs[
"ru"].val() ==
"Планета (Газ)");
1005 CHECK(langs[
"ja"].val() ==
"惑星(ガス)");
1006 CHECK(langs[
"zh"].val() ==
"行星(气体)");
1010 CHECK(langs[
"decode this"].val() ==
"☺ café");
1011 CHECK(langs[
"and this as well"].val() ==
"✅ 𝄞");
1012 CHECK(langs[
"not decoded"].val() ==
"\\u263A \\xE2\\x98\\xBA");
1013 CHECK(langs[
"neither this"].val() ==
"\\u2705 \\U0001D11E");
1041 const char foobar_str[] =
"foobar";
1043 CHECK(s ==
"foobar");
1044 CHECK(s.size() == 6);
1045 CHECK(s.data() == foobar_str);
1046 CHECK(s.size() == s.len);
1047 CHECK(s.data() == s.str);
1052 const char foobar_str[] =
"foobar";
1054 CHECK(s ==
"foobar");
1055 CHECK(s !=
"foobar0");
1064 CHECK(s ==
"foobar");
1065 CHECK(s !=
"foobar0");
1077 const char *foobar_str =
"foobar";
1079 CHECK(s ==
"foobar");
1080 CHECK(s !=
"foobar0");
1094 std::string foobar_str =
"foobar";
1096 CHECK(s ==
"foobar");
1097 CHECK(s !=
"foobar0");
1119 char const foobar_str_ro[] =
"foobar";
1120 char foobar_str_rw[] =
"foobar";
1121 static_assert(std::is_array<
decltype(foobar_str_ro)>::value,
"this is an array");
1122 static_assert(std::is_array<
decltype(foobar_str_rw)>::value,
"this is an array");
1127 CHECK(foobar.
size() == strlen(foobar_str_ro));
1128 CHECK(foobar ==
"foobar");
1134 CHECK(foobar.
size() == strlen(foobar_str_rw));
1135 CHECK(foobar ==
"foobar");
1141 CHECK(foobar.
size() == strlen(foobar_str_rw));
1142 CHECK(foobar ==
"foobar");
1153 char const* foobar_str_ro =
"foobar";
1154 char foobar_str_rw_[] =
"foobar";
1155 char * foobar_str_rw = foobar_str_rw_;
1156 static_assert(!std::is_array<
decltype(foobar_str_ro)>::value,
"this is a decayed pointer");
1157 static_assert(!std::is_array<
decltype(foobar_str_rw)>::value,
"this is a decayed pointer");
1163 CHECK(foobar.
size() == strlen(foobar_str_ro));
1164 CHECK(foobar ==
"foobar");
1170 CHECK(foobar.
size() == strlen(foobar_str_rw));
1171 CHECK(foobar ==
"foobar");
1177 CHECK(foobar.
size() == strlen(foobar_str_rw));
1178 CHECK(foobar ==
"foobar");
1188 char buf[] =
"foobar";
1190 CHECK(foobar ==
"foobar");
1191 foobar[0] =
'F';
CHECK(foobar ==
"Foobar");
1192 foobar.
back() =
'R';
CHECK(foobar ==
"FoobaR");
1204 foobar.
fill(
'.');
CHECK(foobar ==
"......");
1216 CHECK(s.
sub(0, 12) ==
"fooFOObarBAR");
1276 CHECK(some ==
"some");
1277 CHECK(s ==
"some substring");
1280 char result[32] = {0};
1281 std::snprintf(result,
sizeof(result),
"%.*s", (
int)some.
len, some.
str);
1282 printf(
"~~~%s~~~\n", result);
1292 char result[32] = {0};
1293 std::snprintf(result,
sizeof(result),
"%s", some.
str);
1303 CHECK(some ==
"some");
1304 CHECK(s ==
"some substring");
1307 std::stringstream ss;
1309 CHECK(ss.str() ==
"some substring");
1310 CHECK(ss.str() == s);
1318 std::stringstream ss;
1320 CHECK(ss.str() ==
"some substring");
1321 CHECK(ss.str() == s);
1325 std::stringstream ss;
1327 CHECK(ss.str() ==
"some substring");
1328 CHECK(ss.str() == s);
1332 std::stringstream ss;
1334 CHECK(ss.str() ==
"some");
1335 CHECK(ss.str() == some);
1372 CHECK(
ryml::csubstr(
" \t\n\rcontents without whitespace\t \n\r").trim(
"\t \n\r") ==
"contents without whitespace");
1393 CHECK(aaa___bbb.
trim (
'c') == aaa___bbb);
1412 CHECK(aaa___bbb.
trim (
"cd") == aaa___bbb);
1417 CHECK(
ryml::csubstr(
"'this is is single quoted'" ).unquoted() ==
"this is is single quoted");
1418 CHECK(
ryml::csubstr(
"\"this is is double quoted\"").unquoted() ==
"this is is double quoted");
1736 CHECK(
ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extshort() ==
"/path/to/file.tar");
1742 using namespace ryml;
1743 csubstr parts[] = {
"aa",
"bb",
"cc",
"dd",
"ee",
"ff"};
1747 CHECK(part == parts[count++]);
1753 CHECK(part == parts[count++]);
1759 CHECK(part == parts[count++]);
1768 const bool skip_empty =
true;
1841 const char filename[] =
"ryml_example.yml";
1842 std::string yaml =
""
1856 CHECK(tree[
"foo"].val() ==
"1");
1857 CHECK(tree[
"bar"][0].val() ==
"2");
1858 CHECK(tree[
"bar"][1].val() ==
"3");
1865 CHECK(tree[
"foo"].val() ==
"1");
1866 CHECK(tree[
"bar"][0].val() ==
"2");
1867 CHECK(tree[
"bar"][1].val() ==
"3");
1888 char src[] =
"{foo: 1, bar: [2, 3]}";
1894 CHECK(root[
"foo"].is_keyval());
1896 CHECK(root[
"foo"].val() ==
"1");
1897 CHECK(root[
"bar"].is_seq());
1898 CHECK(root[
"bar"].has_key());
1900 CHECK(root[
"bar"][0].val() ==
"2");
1901 CHECK(root[
"bar"][1].val() ==
"3");
1904 int foo = 0, bar0 = 0, bar1 = 0;
1906 root[
"bar"][0] >> bar0;
1907 root[
"bar"][1] >> bar1;
1913 CHECK(root[
"foo"].val().data() == src + strlen(
"{foo: "));
1914 CHECK(root[
"foo"].val().begin() == src + strlen(
"{foo: "));
1915 CHECK(root[
"foo"].val().end() == src + strlen(
"{foo: 1"));
1916 CHECK(root[
"foo"].val().is_sub(srcview));
1917 CHECK(root[
"bar"][0].val().data() == src + strlen(
"{foo: 1, bar: ["));
1918 CHECK(root[
"bar"][0].val().begin() == src + strlen(
"{foo: 1, bar: ["));
1919 CHECK(root[
"bar"][0].val().end() == src + strlen(
"{foo: 1, bar: [2"));
1920 CHECK(root[
"bar"][0].val().is_sub(srcview));
1921 CHECK(root[
"bar"][1].val().data() == src + strlen(
"{foo: 1, bar: [2, "));
1922 CHECK(root[
"bar"][1].val().begin() == src + strlen(
"{foo: 1, bar: [2, "));
1923 CHECK(root[
"bar"][1].val().end() == src + strlen(
"{foo: 1, bar: [2, 3"));
1924 CHECK(root[
"bar"][1].val().is_sub(srcview));
1946 CHECK(root[
"foo"].is_keyval());
1948 CHECK(root[
"foo"].val() ==
"1");
1949 CHECK(root[
"bar"].is_seq());
1950 CHECK(root[
"bar"].has_key());
1952 CHECK(root[
"bar"][0].val() ==
"2");
1953 CHECK(root[
"bar"][1].val() ==
"3");
1956 int foo = 0, bar0 = 0, bar1 = 0;
1958 root[
"bar"][0] >> bar0;
1959 root[
"bar"][1] >> bar1;
1967 char src[] =
"{foo: is it really true}";
1976 CHECK(tree[
"foo"].val() ==
"is it really true");
2004 CHECK(root[
"foo"].is_keyval());
2006 CHECK(root[
"foo"].val() ==
"1");
2007 CHECK(root[
"bar"].is_seq());
2008 CHECK(root[
"bar"].has_key());
2010 CHECK(root[
"bar"][0].val() ==
"2");
2011 CHECK(root[
"bar"][1].val() ==
"3");
2020 "bar2: [22,32]" "\n"
2023 CHECK(root[
"foo2"].is_keyval());
2024 CHECK(root[
"foo2"].
key() ==
"foo2");
2025 CHECK(root[
"foo2"].val() ==
"12");
2026 CHECK(root[
"bar2"].is_seq());
2027 CHECK(root[
"bar2"].has_key());
2028 CHECK(root[
"bar2"].
key() ==
"bar2");
2029 CHECK(root[
"bar2"][0].val() ==
"22");
2030 CHECK(root[
"bar2"][1].val() ==
"32");
2039 CHECK(root[0].val() ==
"a");
2040 CHECK(root[1].val() ==
"b");
2041 CHECK(root[2].is_map());
2042 CHECK(root[2][
"x0"].val() ==
"1");
2043 CHECK(root[2][
"x1"].val() ==
"2");
2051 "- {x0: 1,x1: 2}" "\n"
2052 "- champagne: Dom Perignon" "\n"
2053 " coffee: Arabica" "\n"
2056 CHECK(root[0].val() ==
"a");
2057 CHECK(root[1].val() ==
"b");
2058 CHECK(root[2].is_map());
2059 CHECK(root[2][
"x0"].val() ==
"1");
2060 CHECK(root[2][
"x1"].val() ==
"2");
2061 CHECK(root[3].is_map());
2062 CHECK(root[3][
"champagne"].val() ==
"Dom Perignon");
2063 CHECK(root[3][
"coffee"].val() ==
"Arabica");
2067 CHECK(mroot[3][
"more"].readable());
2068 CHECK(mroot[3][
"more"].
key() ==
"more");
2069 CHECK(mroot[3][
"more"].is_map());
2070 CHECK(!mroot[3][
"more"].is_val());
2077 "- {x0: 1,x1: 2}" "\n"
2078 "- champagne: Dom Perignon" "\n"
2079 " coffee: Arabica" "\n"
2082 " vinho verde: Soalheiro" "\n"
2083 " vinho tinto: Redoma 2017" "\n"
2085 " - Rochefort 10" "\n"
2087 " - Leffe Rituel" "\n"
2088 " always: lots of water" "\n"
2096 "- {x0: 1,x1: 2}" "\n"
2097 "- champagne: Dom Perignon" "\n"
2098 " coffee: Arabica" "\n"
2100 " vinho verde: Soalheiro" "\n"
2101 " vinho tinto: Redoma 2017" "\n"
2103 " - Rochefort 10" "\n"
2105 " - Leffe Rituel" "\n"
2106 " always: lots of water" "\n"
2119 "- {x0: 1,x1: 2}" "\n"
2120 "- champagne: Dom Perignon" "\n"
2121 " coffee: Arabica" "\n"
2123 " vinho verde: Soalheiro" "\n"
2124 " vinho tinto: Redoma 2017" "\n"
2126 " - Rochefort 10" "\n"
2128 " - Leffe Rituel" "\n"
2129 " - Kasteel Donker" "\n"
2130 " always: lots of water" "\n"
2158 ryml::csubstr yaml =
"[Dom Perignon,Gosset Grande Reserve,Jacquesson 742]";
2162 yaml =
"[Rochefort 10,Busch,Leffe Rituel,Kasteel Donker]";
2196 "- Gosset Grande Reserve\n"
2197 "- Jacquesson 742\n"
2203 "- Kasteel Donker\n"
2207 "- Niepoort Redoma 2017\n"
2208 "- Vina Esmeralda\n"
2218 "- Gosset Grande Reserve\n"
2219 "- Jacquesson 742\n"
2223 "- Kasteel Donker\n"
2231 "- Niepoort Redoma 2017\n"
2232 "- Vina Esmeralda\n"
2246 "doe: a deer, a female deer" "\n"
2247 "ray: a drop of golden sun" "\n"
2250 "french-hens: 3" "\n"
2251 "calling-birds:" "\n"
2256 "xmas-fifth-day:" "\n"
2257 " calling-birds: four" "\n"
2258 " french-hens: 3" "\n"
2259 " golden-rings: 5" "\n"
2262 " location: a pear tree" "\n"
2263 " turtle-doves: two" "\n"
2270 std::vector<ryml::csubstr> keys, vals;
2273 keys.emplace_back(n.key());
2276 CHECK(keys.size() >= 6);
2277 CHECK(vals.size() >= 6);
2278 if(keys.size() >= 6 && vals.size() >= 6)
2280 CHECK(keys[0] ==
"doe");
2281 CHECK(vals[0] ==
"a deer, a female deer");
2282 CHECK(keys[1] ==
"ray");
2283 CHECK(vals[1] ==
"a drop of golden sun");
2284 CHECK(keys[2] ==
"pi");
2285 CHECK(vals[2] ==
"3.14159");
2286 CHECK(keys[3] ==
"xmas");
2287 CHECK(vals[3] ==
"true");
2288 CHECK(root[5].has_key());
2289 CHECK(root[5].is_seq());
2290 CHECK(root[5].
key() ==
"calling-birds");
2291 CHECK(!root[5].has_val());
2293 CHECK(keys[5] ==
"calling-birds");
2294 CHECK(vals[5] ==
"");
2301 ryml::csubstr calling_birds[] = {
"huey",
"dewey",
"louie",
"fred"};
2303 CHECK(n.val() == calling_birds[count++]);
2328 const char a_deer[] =
"a deer, a female deer";
2337 std::string a_drop =
"a drop of golden sun";
2340 root[
"ray"] << a_drop;
2346 CHECK(root[
"ray"].val() ==
"a drop of golden sun");
2349 root[
"pi"] << ryml::fmt::real(3.141592654, 5);
2350 root[
"xmas"] << ryml::fmt::boolalpha(
true);
2351 root[
"french-hens"] << 3;
2360 xmas5[
"calling-birds"].
set_val(
"four");
2361 xmas5[
"french-hens"] << 3;
2362 xmas5[
"golden-rings"] << 5;
2363 xmas5[
"partridges"].
set_map();
2364 xmas5[
"partridges"][
"count"] << 1;
2365 xmas5[
"partridges"][
"location"].
set_val(
"a pear tree");
2366 xmas5[
"turtle-doves"].
set_val(
"two");
2370 "doe: a deer, a female deer" "\n"
2371 "ray: a drop of golden sun" "\n"
2374 "french-hens: 3" "\n"
2375 "calling-birds:" "\n"
2380 "xmas-fifth-day:" "\n"
2381 " calling-birds: four" "\n"
2382 " french-hens: 3" "\n"
2383 " golden-rings: 5" "\n"
2386 " location: a pear tree" "\n"
2387 " turtle-doves: two" "\n"
2401 char buf[] =
"[a, b, c, d]";
2431 CHECK(root[0].val().is_sub(arena));
2432 CHECK(root[1].val().is_sub(arena));
2433 CHECK(root[2].val().is_sub(arena));
2434 CHECK(root[3].val().is_sub(arena));
2444 char buf[] =
"[a, b, c, d]";
2452 CHECK(root[2].val() ==
"c");
2455 CHECK(root[2].val() ==
"12345");
2461 CHECK(root[3].val() ==
"d");
2464 CHECK(root[3].val() ==
"67890");
2480 CHECK(root[2].val() ==
"c");
2482 CHECK(root[2].val() ==
"12345");
2491 CHECK(root[3].val() ==
"67890");
2495 CHECK(tree.
arena() ==
"[a, b, c, d]1234567890");
2503 CHECK(c10 ==
"10101010");
2513 CHECK(root[
"a"].val() ==
"2222");
2523 CHECK(copied == mystr);
2524 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2533 memcpy(copied.
str, mystr.
str, mystr.
len);
2534 CHECK(copied == mystr);
2535 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2584 CHECK(tree.
to_arena(
double(0.234)) ==
"0.234");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.234");
2594 const float fnan = std::numeric_limits<float >::quiet_NaN();
2595 const double dnan = std::numeric_limits<double>::quiet_NaN();
2596 const float finf = std::numeric_limits<float >::infinity();
2597 const double dinf = std::numeric_limits<double>::infinity();
2598 CHECK(tree.
to_arena( finf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf");
2599 CHECK(tree.
to_arena( dinf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf");
2600 CHECK(tree.
to_arena(-finf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf");
2601 CHECK(tree.
to_arena(-dinf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf");
2602 CHECK(tree.
to_arena( fnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan");
2603 CHECK(tree.
to_arena( dnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan.nan");
2607 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wfloat-equal");
2613 tree[
"ninf"] >> f;
CHECK(f == -finf);
2614 tree[
"ninf"] >> d;
CHECK(d == -dinf);
2615 tree[
"pinf"] >> f;
CHECK(f == finf);
2616 tree[
"pinf"] >> d;
CHECK(d == dinf);
2617 tree[
"nan" ] >> f;
CHECK(std::isnan(f));
2618 tree[
"nan" ] >> d;
CHECK(std::isnan(d));
2619 C4_SUPPRESS_WARNING_GCC_CLANG_POP
2632 t[
"val"] >> valu8;
CHECK(valu8 == 2);
2633 t[
"val"] >> vali8;
CHECK(vali8 == 2);
2640 auto checku8 = ryml::fmt::overflow_checked(valu8);
2641 t[
"val"] >> checku8;
2644 auto checki8 = ryml::fmt::overflow_checked(vali8);
2645 t[
"val"] >> checki8;
2661 "dquoted: \"\"" "\n"
2664 "all_null: [~, null, Null, NULL]" "\n"
2665 "non_null: [nULL, non_null, non null, null it is not]" "\n"
2669 CHECK(tree[
"plain"].has_val());
2670 CHECK(tree[
"squoted"].has_val());
2671 CHECK(tree[
"dquoted"].has_val());
2672 CHECK(tree[
"literal"].has_val());
2673 CHECK(tree[
"folded"].has_val());
2674 CHECK( ! tree[
"all_null"].has_val());
2675 CHECK( ! tree[
"non_null"].has_val());
2677 CHECK( ! tree[
"plain"].is_container());
2678 CHECK( ! tree[
"squoted"].is_container());
2679 CHECK( ! tree[
"dquoted"].is_container());
2680 CHECK( ! tree[
"literal"].is_container());
2681 CHECK( ! tree[
"folded"].is_container());
2682 CHECK(tree[
"all_null"].is_container());
2683 CHECK(tree[
"non_null"].is_container());
2688 CHECK(tree[
"plain"].val().len == 0);
2689 CHECK(tree[
"squoted"].val().len == 0);
2690 CHECK(tree[
"dquoted"].val().len == 0);
2691 CHECK(tree[
"literal"].val().len == 0);
2692 CHECK(tree[
"folded"].val().len == 0);
2694 CHECK(tree[
"plain"].val().str ==
nullptr);
2695 CHECK(tree[
"squoted"].val().str !=
nullptr);
2696 CHECK(tree[
"dquoted"].val().str !=
nullptr);
2697 CHECK(tree[
"literal"].val().str !=
nullptr);
2698 CHECK(tree[
"folded"].val().str !=
nullptr);
2702 CHECK(tree[
"plain"].val() ==
nullptr);
2703 CHECK(tree[
"squoted"].val() !=
nullptr);
2704 CHECK(tree[
"dquoted"].val() !=
nullptr);
2705 CHECK(tree[
"literal"].val() !=
nullptr);
2706 CHECK(tree[
"folded"].val() !=
nullptr);
2711 CHECK(tree[
"plain"].val_is_null());
2712 CHECK( ! tree[
"squoted"].val_is_null());
2713 CHECK( ! tree[
"dquoted"].val_is_null());
2714 CHECK( ! tree[
"literal"].val_is_null());
2715 CHECK( ! tree[
"folded"].val_is_null());
2720 CHECK(child.val() !=
nullptr);
2721 CHECK(child.val_is_null());
2725 CHECK(child.val() !=
nullptr);
2726 CHECK( ! child.val_is_null());
2741 CHECK(null .len == 0);
CHECK(null .str ==
nullptr);
CHECK(null ==
nullptr);
2744 CHECK(tilde .len != 0);
CHECK(tilde .str !=
nullptr);
CHECK(tilde !=
nullptr);
2749 tree[
"empty_null"] << null;
CHECK(tree.
arena() ==
"");
2751 tree[
"empty_nonnull"] << nonnull;
CHECK(tree.
arena() ==
"");
2753 tree[
"str_null"] << strnull;
CHECK(tree.
arena() ==
"null");
2755 tree[
"str_tilde"] << tilde;
CHECK(tree.
arena() ==
"null~");
2759 "empty_nonnull: ''" "\n"
2760 "str_null: null" "\n"
2769 return s.str ==
nullptr ?
"null" : s;
2771 tree[
"empty_null"] << null_if_nullptr(null);
2772 tree[
"empty_nonnull"] << null_if_nullptr(nonnull);
2773 tree[
"str_null"] << null_if_nullptr(strnull);
2774 tree[
"str_tilde"] << null_if_nullptr(tilde);
2777 "empty_null: null" "\n"
2778 "empty_nonnull: ''" "\n"
2779 "str_null: null" "\n"
2788 tree[
"empty_null"] << null_if_predicate(null);
2789 tree[
"empty_nonnull"] << null_if_predicate(nonnull);
2790 tree[
"str_null"] << null_if_predicate(strnull);
2791 tree[
"str_tilde"] << null_if_predicate(tilde);
2794 "empty_null: null" "\n"
2795 "empty_nonnull: ''" "\n"
2796 "str_null: null" "\n"
2797 "str_tilde: null" "\n"
2805 tree[
"empty_null"] << tilde_if_predicate(null);
2806 tree[
"empty_nonnull"] << tilde_if_predicate(nonnull);
2807 tree[
"str_null"] << tilde_if_predicate(strnull);
2808 tree[
"str_tilde"] << tilde_if_predicate(tilde);
2811 "empty_null: ~" "\n"
2812 "empty_nonnull: ''" "\n"
2830 char buf_[256] = {};
2832 size_t size =
ryml::format(buf,
"a={} foo {} {} bar {}", 0.1, 10, 11, 12);
2833 CHECK(size == strlen(
"a=0.1 foo 10 11 bar 12"));
2834 CHECK(buf.
first(size) ==
"a=0.1 foo 10 11 bar 12");
2837 size =
ryml::format({} ,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12);
2838 CHECK(size ==
ryml::format(buf,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12));
2839 CHECK(size == strlen(
"a=this_is_a foo 10 11 bar 12"));
2841 char smallbuf[8] = {};
2842 size =
ryml::format(smallbuf,
"{} is too large {}",
"this",
"for the buffer");
2843 CHECK(size == strlen(
"this is too large for the buffer"));
2849 CHECK(result ==
"b=1, damn it.");
2868 CHECK(sbuf ==
"and c=2 seems about right");
2869 std::vector<char> vbuf;
2871 CHECK(sbuf ==
"and c=2 seems about right");
2874 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2881 int a = 0, b = 1, c = 2;
2883 CHECK(result ==
"0 and 1 and 2");
2884 int aa = -1, bb = -2, cc = -3;
2885 size_t num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2893 CHECK(result ==
"10 and 20 and 30");
2894 num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2904 char buf_[256] = {};
2906 size_t size =
ryml::cat(buf,
"a=", 0.1,
"foo", 10, 11,
"bar", 12);
2907 CHECK(size == strlen(
"a=0.1foo1011bar12"));
2908 CHECK(buf.
first(size) ==
"a=0.1foo1011bar12");
2913 char smallbuf[8] = {};
2914 size =
ryml::cat(smallbuf,
"this",
" is too large ",
"for the buffer");
2915 CHECK(size == strlen(
"this is too large for the buffer"));
2921 CHECK(result ==
"b=1, damn it.");
2939 ryml::catrs(&sbuf,
"and c=", 2,
" seems about right");
2940 CHECK(sbuf ==
"and c=2 seems about right");
2941 std::vector<char> vbuf;
2942 ryml::catrs(&vbuf,
"and c=", 2,
" seems about right");
2943 CHECK(sbuf ==
"and c=2 seems about right");
2946 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2953 int a = 0, b = 1, c = 2;
2955 CHECK(result ==
"0 1 2");
2956 int aa = -1, bb = -2, cc = -3;
2957 char sep1 =
'a', sep2 =
'b';
2958 size_t num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2967 CHECK(result ==
"10 20 30");
2968 num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2979 char buf_[256] = {};
2982 size_t size =
ryml::catsep(buf,
' ',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2983 CHECK(buf.
first(size) ==
"a= 0 b= 1 c= 2 45 67");
2986 size =
ryml::catsep(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
2987 CHECK(buf.
first(size) ==
"a=0 and b=1 and c=2 and 45 and 67");
2989 size =
ryml::catsep(buf,
" ... ",
"a=0",
"b=1",
"c=2", 45, 67);
2990 CHECK(buf.
first(size) ==
"a=0 ... b=1 ... c=2 ... 45 ... 67");
2992 size =
ryml::catsep(buf,
'/',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2993 CHECK(buf.
first(size) ==
"a=/0/b=/1/c=/2/45/67");
2995 size =
ryml::catsep(buf, 888,
"a=0",
"b=1",
"c=2", 45, 67);
2996 CHECK(buf.
first(size) ==
"a=0888b=1888c=28884588867");
3002 char smallbuf[8] = {};
3004 CHECK(size == strlen(
"a=0888b=1888c=28884588867"));
3010 CHECK(result ==
"a=0 and b=1 and c=2 and 45 and 67");
3029 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67");
3030 std::vector<char> vbuf;
3036 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");
3041 char buf_[256] = {};
3043 int a = 0, b = 1, c = 2;
3045 CHECK(result ==
"0 1 2");
3046 int aa = -1, bb = -2, cc = -3;
3054 CHECK(result ==
"10--20--30");
3064 using namespace ryml;
3065 char buf_[256] = {};
3084 CHECK(
"3735928559" ==
cat_sub(buf, UINT32_C(0xdeadbeef)));
3208 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wcast-align")
3209 const uint32_t payload[] = {10, 20, 30, 40, UINT32_C(0xdeadbeef)};
3211 csubstr expected =
csubstr((
const char *)payload,
sizeof(payload));
3216 for(
const uint32_t value : payload)
3219 expected =
csubstr((
const char *)&value,
sizeof(value));
3221 CHECK(actual.
size() ==
sizeof(uint32_t));
3226 CHECK(actual.
size() ==
sizeof(uint32_t));
3231 uint32_t result = 0;
3236 CHECK(result == value);
3238 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3258 text_and_base64 cases[] = {
3259 {{
"Hello, World!"}, {
"SGVsbG8sIFdvcmxkIQ=="}},
3260 {{
"Brevity is the soul of wit."}, {
"QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu"}},
3261 {{
"All that glitters is not gold."}, {
"QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu"}},
3264 for(text_and_base64 c : cases)
3265 tree[c.text] << ryml::fmt::base64(c.text);
3267 for(text_and_base64 c : cases)
3270 for(text_and_base64 c : cases)
3272 CHECK(tree[c.text].
val() == c.base64);
3273 CHECK(tree[c.base64].
val() == c.text);
3277 "Hello, World!: SGVsbG8sIFdvcmxkIQ==" "\n"
3278 "Brevity is the soul of wit.: QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu" "\n"
3279 "All that glitters is not gold.: QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu" "\n"
3281 "SGVsbG8sIFdvcmxkIQ==: Hello, World!" "\n"
3282 "QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu: Brevity is the soul of wit." "\n"
3283 "QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu: All that glitters is not gold." "\n"
3285 char buf1_[128], buf2_[128];
3289 for(
const text_and_base64 c : cases)
3294 tree[c.text] >> ryml::fmt::base64(buf1, &len);
3303 CHECK(c.text.len == len);
3306 tree[c.base64] >>
ryml::key(ryml::fmt::base64(buf2, &len));
3312 tree[c.text] >> ryml::fmt::base64(result);
3313 CHECK(result == c.text);
3315 tree[c.base64] >>
ryml::key(ryml::fmt::base64(result));
3316 CHECK(result == c.text);
3320 const uint64_t valin = UINT64_C(0xdeadbeef);
3321 tree[
"deadbeef"] << c4::fmt::base64(valin);
3322 uint64_t valout = 0;
3324 tree[
"deadbeef"] >> ryml::fmt::base64(valout, &len);
3325 CHECK(len ==
sizeof(valout));
3326 CHECK(valout == UINT64_C(0xdeadbeef));
3329 tree[
"deadbeef"] >> ryml::fmt::base64(valout);
3330 CHECK(valout == UINT64_C(0xdeadbeef));
3334 const double valin = 123456.7891011;
3335 tree[
"float"] << c4::fmt::base64(valin);
3338 tree[
"float"] >> ryml::fmt::base64(valout, &len);
3339 CHECK(len ==
sizeof(valout));
3340 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3343 tree[
"float"] >> ryml::fmt::base64(valout);
3344 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3348 const uint32_t data_in[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xdeadbeef};
3349 uint32_t data_out[11] = {};
3350 tree[
"int_data"] << ryml::fmt::base64(data_in, 11);
3351 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) != 0);
3353 tree[
"int_data"] >> ryml::fmt::base64(data_out, 11, &len);
3354 CHECK(len ==
sizeof(data_out));
3355 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3357 memset(data_out, 0,
sizeof(data_out));
3358 tree[
"int_data"] >> ryml::fmt::base64(data_out);
3359 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3613 "v3: (100,101,102)" "\n"
3614 "v4: (1000,1001,1002,1003)" "\n"
3642 "v3: (30,31,32)" "\n"
3643 "v4: (40,41,42,43)" "\n"
3695template<
class K,
class V>
3720template<
class K,
class V>
3748template<
class K,
class V>
3753 for(
auto const ch : n)
3756 map->
map_member.emplace(std::make_pair(std::move(k), std::move(v)));
3767 n[
"seq"] >> val->
seq;
3768 n[
"map"] >> val->
map;
3787 {{101, 102, 103, 104, 105, 106, 107}},
3788 {{{1001, 2001}, {1002, 2002}, {1003, 2003}}},
3819 "v3: (30,31,32)" "\n"
3820 "v4: (40,41,42,43)" "\n"
3845 std::string yml_std_string =
""
3846 "- v2: (20,21)" "\n"
3847 " v3: (30,31,32)" "\n"
3848 " v4: (40,41,42,43)" "\n"
3861 "- v2: (120,121)" "\n"
3862 " v3: (130,131,132)" "\n"
3863 " v4: (140,141,142,143)" "\n"
3873 " 11001: 12001" "\n"
3874 " 11002: 12002" "\n"
3875 " 11003: 12003" "\n"
3876 "- v2: (220,221)" "\n"
3877 " v3: (230,231,232)" "\n"
3878 " v4: (240,241,242,243)" "\n"
3888 " 21001: 22001" "\n"
3889 " 21002: 22002" "\n"
3890 " 21003: 22003" "\n"
3896 std::vector<my_type> vmt;
3898 CHECK(vmt.size() == 3);
3910 std::vector<double> reference{1.23234412342131234, 2.12323123143434237, 3.67847983572591234};
3914 const double precision_safe = 1.e-14;
3915 const size_t num_digits_safe = 14;
3916 const size_t num_digits_original = 17;
3917 auto get_num_digits = [](
ryml::csubstr number){
return number.len - 2u; };
3923 std::vector<double> output;
3925 CHECK(output.size() == reference.size());
3926 for(
size_t i = 0; i < reference.size(); ++i)
3929 CHECK(fabs(output[i] - reference[i]) < precision_safe);
3938 serialized.
rootref() << reference;
3939 std::cout << serialized;
3941 #if (!C4CORE_HAVE_STD_TOCHARS)
3946 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
3947 C4_UNUSED(num_digits_safe);
3951 "- 1.2323441234213124" "\n"
3952 "- 2.1232312314343424" "\n"
3953 "- 3.6784798357259123" "\n"
3954 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
3958 CHECK(get_num_digits(child.val()) >= num_digits_safe);
3961 CHECK(fabs(out - reference[pos++]) < precision_safe);
3992 auto check_precision = [&](
ryml::Tree const& serialized){
3993 std::cout << serialized;
3996 "- 1.23234412342131239" "\n"
3997 "- 2.12323123143434245" "\n"
3998 "- 3.67847983572591231" "\n"
3999 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4003 CHECK(get_num_digits(child.val()) == num_digits_original);
4006 CHECK(fabs(out - reference[pos++]) < precision_safe);
4015 for(
const double v : reference)
4017 check_precision(serialized);
4026 for(
const double v : reference)
4031 (void)snprintf(tmp,
sizeof(tmp),
"%.18g", v);
4037 check_precision(serialized);
4057 "- champagne: Dom Perignon" "\n"
4058 " coffee: Arabica" "\n"
4060 " vinho verde: Soalheiro" "\n"
4061 " vinho tinto: Redoma 2017" "\n"
4063 " - Rochefort 10" "\n"
4065 " - Leffe Rituel" "\n"
4084 size_t num_needed_chars = output.
len;
4085 std::vector<char> buf(num_needed_chars);
4088 CHECK(output == ymla);
4096 num_needed_chars = output.
len;
4097 buf.resize(num_needed_chars);
4100 CHECK(output == ymlb);
4105 CHECK(output == ymlb);
4116 " vinho verde: Soalheiro" "\n"
4117 " vinho tinto: Redoma 2017" "\n"
4130 size_t num_needed_chars = output.
len;
4132 buf.resize(num_needed_chars);
4135 CHECK(output == ymla);
4143 num_needed_chars = output.
len;
4144 buf.resize(num_needed_chars);
4147 CHECK(output == ymlb);
4152 CHECK(output == ymlb);
4163 " vinho verde: Soalheiro" "\n"
4164 " vinho tinto: Redoma 2017" "\n"
4180 "- champagne: Dom Perignon" "\n"
4181 " coffee: Arabica" "\n"
4183 " vinho verde: Soalheiro" "\n"
4184 " vinho tinto: Redoma 2017" "\n"
4186 " - Rochefort 10" "\n"
4188 " - Leffe Rituel" "\n"
4200 std::stringstream ss;
4208 std::stringstream ss;
4220 " \"champagne\": \"Dom Perignon\"," "\n"
4221 " \"coffee\": \"Arabica\"," "\n"
4223 " \"vinho verde\": \"Soalheiro\"," "\n"
4224 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4227 " \"Rochefort 10\"," "\n"
4229 " \"Leffe Rituel\"" "\n"
4242 std::stringstream ss;
4247 " vinho verde: Soalheiro" "\n"
4248 " vinho tinto: Redoma 2017" "\n"
4254 std::stringstream ss;
4259 " \"vinho verde\": \"Soalheiro\"," "\n"
4260 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4277 "- champagne: Dom Perignon" "\n"
4278 " coffee: Arabica" "\n"
4280 " vinho verde: Soalheiro" "\n"
4281 " vinho tinto: Redoma 2017" "\n"
4283 " - Rochefort 10" "\n"
4285 " - Leffe Rituel" "\n"
4308 "- champagne: Dom Perignon" "\n"
4309 " coffee: Arabica" "\n"
4311 " vinho verde: Soalheiro" "\n"
4312 " vinho tinto: Redoma 2017" "\n"
4314 " - Rochefort 10" "\n"
4316 " - Leffe Rituel" "\n"
4318 " - many other" "\n"
4319 " - wonderful beers" "\n"
4329 " - Rochefort 10" "\n"
4331 " - Leffe Rituel" "\n"
4333 " - many other" "\n"
4334 " - wonderful beers" "\n"
4341 "- Rochefort 10" "\n"
4343 "- Leffe Rituel" "\n"
4345 " - many other" "\n"
4346 " - wonderful beers" "\n"
4353 "- wonderful beers" "\n"
4359 " - many other" "\n"
4360 " - wonderful beers" "\n"
4387 " block key: block val" "\n"
4389 " - block val 1" "\n"
4390 " - block val 2" "\n"
4392 "flow map, singleline: {flow key: flow val}" "\n"
4393 "flow seq, singleline: [flow val,flow val]" "\n"
4394 "flow map, multiline: {" "\n"
4395 " flow key: flow val" "\n"
4397 "flow seq, multiline: [" "\n"
4405 CHECK(tree[
"block map"].is_key_plain());
4406 CHECK(tree[
"block seq"].is_key_plain());
4407 CHECK(tree[
"flow map, singleline"].is_key_plain());
4408 CHECK(tree[
"flow seq, singleline"].is_key_plain());
4409 CHECK(tree[
"flow map, multiline"].is_key_plain());
4410 CHECK(tree[
"flow seq, multiline"].is_key_plain());
4411 CHECK(tree[
"block map"].is_block());
4412 CHECK(tree[
"block seq"].is_block());
4414 CHECK(tree[
"flow map, singleline"].is_flow_sl());
4415 CHECK(tree[
"flow seq, singleline"].is_flow_sl());
4416 CHECK(tree[
"flow map, multiline"].is_flow_ml1());
4417 CHECK(tree[
"flow seq, multiline"].is_flow_ml1());
4419 CHECK(tree[
"flow map, singleline"].is_flow());
4420 CHECK(tree[
"flow seq, singleline"].is_flow());
4421 CHECK(tree[
"flow map, multiline"].is_flow());
4422 CHECK(tree[
"flow seq, multiline"].is_flow());
4428 CHECK(tostr(tree) == yaml);
4439 " block key: block val\n"
4446 "'block map': {block key: block val}\n"
4452 CHECK(tostr(n) ==
""
4461 CHECK(tostr(n) ==
""
4462 "\"block seq\": [\n"
4463 " block val 1,block val 2,quoted\n"
4466 CHECK(tostr(n) ==
""
4467 "\"block seq\": [\n"
4468 " block val 1, block val 2, quoted\n"
4471 CHECK(tostr_opts(n, maxcols20) ==
""
4472 "\"block seq\": [\n"
4473 " block val 1, block val 2,\n"
4477 CHECK(tostr_opts(n, maxcols20) ==
""
4478 "\"block seq\": [\n"
4479 " block val 1,block val 2,\n"
4483 CHECK(tostr(n) ==
""
4484 "\"block seq\": [block val 1,block val 2,quoted]\n");
4486 CHECK(tostr(n) ==
""
4487 "\"block seq\": [block val 1, block val 2, quoted]\n");
4489 CHECK(tostr(n) ==
""
4490 "\"block seq\": [\n"
4501 CHECK(tostr(n) ==
"flow map, singleline: {flow key: flow val}\n");
4504 CHECK(tostr(n) ==
""
4505 "flow map, singleline:\n"
4513 CHECK(tostr(n) ==
""
4514 "flow map, multiline: {\n"
4515 " flow key: flow val\n"
4519 CHECK(tostr(n) ==
""
4520 "flow map, multiline:\n"
4521 " flow key: flow val\n"
4527 CHECK(tostr(n) ==
"flow seq, singleline: [flow val,flow val]\n");
4532 CHECK(tostr(n) ==
""
4534 " flow seq, singleline\n"
4543 CHECK(tostr(n) ==
""
4544 "flow seq, multiline: [\n"
4550 CHECK(tostr(n) ==
"flow seq, multiline: [flow val,flow val]\n");
4553 CHECK(tostr(tree) != yaml);
4554 CHECK(tostr(tree) ==
4555 "'block map': {block key: block val}" "\n"
4556 "\"block seq\": [" "\n"
4557 " block val 1," "\n"
4558 " block val 2," "\n"
4561 "flow map, singleline:" "\n"
4562 " flow key: |-" "\n"
4565 " flow seq, singleline" "\n"
4567 " - 'flow val'" "\n"
4568 " - \"flow val\"" "\n"
4569 "flow map, multiline:" "\n"
4570 " flow key: flow val" "\n"
4571 "flow seq, multiline: [flow val,flow val]" "\n"
4576 CHECK(tostr(tree) ==
4578 " block key: block val" "\n"
4580 " - block val 1" "\n"
4581 " - block val 2" "\n"
4583 "flow map, singleline:" "\n"
4584 " flow key: |-" "\n"
4587 " flow seq, singleline" "\n"
4589 " - 'flow val'" "\n"
4590 " - \"flow val\"" "\n"
4591 "flow map, multiline:" "\n"
4592 " flow key: flow val" "\n"
4593 "flow seq, multiline: [flow val,flow val]" "\n"
4602 CHECK(tostr(tree) ==
4604 " block key: block val" "\n"
4606 " - block val 1" "\n"
4607 " - block val 2" "\n"
4609 "flow map, singleline:" "\n"
4610 " flow key: flow val" "\n"
4611 "flow seq, singleline:" "\n"
4614 "flow map, multiline:" "\n"
4615 " flow key: flow val" "\n"
4616 "flow seq, multiline:" "\n"
4627 CHECK(tostr(tree) ==
4629 " block key: block val" "\n"
4631 " - block val 1" "\n"
4632 " - block val 2" "\n"
4634 "flow map, singleline:" "\n"
4635 " flow key: flow val" "\n"
4636 "flow seq, singleline:" "\n"
4639 "flow map, multiline:" "\n"
4640 " flow key: flow val" "\n"
4641 "flow seq, multiline:" "\n"
4666 CHECK(tostr(tree) ==
""
4668 " 'block key': \"block val\"" "\n"
4669 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
4670 "'flow map, singleline':" "\n"
4671 " 'flow key': \"flow val\"" "\n"
4672 "'flow seq, singleline': [\"flow val\",\"flow val\"]" "\n"
4673 "'flow map, multiline':" "\n"
4674 " 'flow key': \"flow val\"" "\n"
4675 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
4682 CHECK(tostr(tree) ==
""
4684 " 'block key': \"block val\"" "\n"
4685 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
4686 "'flow map, singleline':" "\n"
4687 " 'flow key': \"flow val\"" "\n"
4688 "'flow seq, singleline':" "\n"
4689 " - \"flow val\"" "\n"
4690 " - \"flow val\"" "\n"
4691 "'flow map, multiline':" "\n"
4692 " 'flow key': \"flow val\"" "\n"
4693 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
4735 CHECK(tree[
"map"].is_flow_ml1());
4736 CHECK(tree[
"map"][
"seq"].is_flow_ml1());
4737 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
4739 CHECK(tostr(tree, emit_defaults) == yaml);
4741 CHECK(tostr_json(tree, emit_defaults) ==
4762 CHECK(tree[
"map"].is_flow_sl());
4764 CHECK(tostr(tree, emit_defaults) ==
4765 "{map: {seq: [0,1,2,3,[40,41]]}}");
4767 CHECK(tostr_json(tree, emit_defaults) ==
4768 "{\"map\": {\"seq\": [0,1,2,3,[40,41]]}}");
4773 CHECK(tostr(tree, with_spaces) ==
4774 "{map: {seq: [0, 1, 2, 3, [40, 41]]}}");
4776 CHECK(tostr_json(tree, with_spaces) ==
4777 "{\"map\": {\"seq\": [0, 1, 2, 3, [40, 41]]}}");
4786 CHECK(tree[
"map"].is_flow_mln());
4787 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
4788 CHECK(tostr(tree, emit_defaults) ==
4792 " 0,1,2,3,[40,41]" "\n"
4796 CHECK(tostr_json(tree, emit_defaults) ==
4800 " 0,1,2,3,[40,41]" "\n"
4807 CHECK(tostr(tree, with_spaces) ==
4811 " 0, 1, 2, 3, [40, 41]" "\n"
4815 CHECK(tostr_json(tree, with_spaces) ==
4819 " 0, 1, 2, 3, [40, 41]" "\n"
4830 CHECK(tree[
"map"].is_flow_ml1());
4831 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
4832 CHECK(tostr(tree, noindent) ==
""
4845 CHECK(tostr_json(tree, noindent) ==
""
4864 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9," "\n"
4865 " 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, " "\n"
4866 " 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, " "\n"
4867 " 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, " "\n"
4868 " 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, " "\n"
4869 " 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, " "\n"
4870 " 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, " "\n"
4871 " 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 " "\n"
4882 CHECK(tostr(tree, emit_defaults) ==
""
4884 " 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"
4885 " 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"
4886 " 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"
4889 CHECK(tostr_json(tree, emit_defaults) ==
""
4891 " 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"
4892 " 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"
4893 " 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"
4899 CHECK(tostr(tree, maxcols40) ==
""
4901 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
4902 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
4903 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
4904 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
4905 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
4906 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
4909 CHECK(tostr_json(tree, maxcols40) ==
""
4911 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
4912 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
4913 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
4914 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
4915 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
4916 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
4923 CHECK(tostr(tree, with_spaces) ==
""
4925 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
4926 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
4927 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
4928 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
4931 CHECK(tostr_json(tree, with_spaces) ==
""
4933 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
4934 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
4935 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
4936 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
4943 CHECK(tostr(tree, maxcols40_spc) ==
""
4945 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
4946 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
4947 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
4948 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
4949 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
4950 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
4951 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
4952 " 72, 73, 74, 75, 76, 77, 78, 79\n"
4955 CHECK(tostr_json(tree, maxcols40_spc) ==
""
4957 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
4958 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
4959 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
4960 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
4961 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
4962 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
4963 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
4964 " 72, 73, 74, 75, 76, 77, 78, 79\n"
4972 CHECK(tostr(tree, maxcols40_spc_noindent) ==
""
4974 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
4975 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
4976 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
4977 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
4978 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
4979 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
4980 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
4981 "73, 74, 75, 76, 77, 78, 79\n"
4984 CHECK(tostr_json(tree, maxcols40_spc_noindent) ==
""
4986 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
4987 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
4988 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
4989 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
4990 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
4991 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
4992 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
4993 "73, 74, 75, 76, 77, 78, 79\n"
5012 ryml::csubstr yaml =
"{map: {seq: [0, 1, 2, 3, [40, 41]]}}";
5016 CHECK(tostr(tree, defaults) ==
"{map: {seq: [0,1,2,3,[40,41]]}}");
5023 CHECK(tostr(tree, defaults) ==
5041 CHECK(tostr(tree, noindent) ==
5060 CHECK(tostr(tree, noindent) ==
""
5076 CHECK(tostr(tree, noindent) ==
5102 " \"doe\": \"a deer, a female deer\"," "\n"
5103 " \"ray\": \"a drop of golden sun\"," "\n"
5104 " \"me\": \"a name, I call myself\"," "\n"
5105 " \"far\": \"a long long way to go\"" "\n"
5119 std::stringstream ss;
5121 CHECK(ss.str() == json);
5144 "\"doe\": \"a deer, a female deer\"" "\n"
5145 "\"ray\": \"a drop of golden sun\"" "\n"
5146 "\"me\": \"a name, I call myself\"" "\n"
5147 "\"far\": \"a long long way to go\"" "\n"
5155 "doe: a deer, a female deer" "\n"
5156 "ray: a drop of golden sun" "\n"
5157 "me: a name, I call myself" "\n"
5158 "far: a long long way to go" "\n"
5167 "doe: 'a deer, a female deer'" "\n"
5168 "ray: 'a drop of golden sun'" "\n"
5169 "me: 'a name, I call myself'" "\n"
5170 "far: 'a long long way to go'" "\n"
5200 std::string unresolved =
""
5202 " name: Everyone has same name" "\n"
5209 "bill_to: &id001" "\n"
5211 " 123 Tornado Alley" "\n"
5213 " city: East Centerville" "\n"
5215 "ship_to: *id001" "\n"
5216 "&keyref key: &valref val" "\n"
5217 "*valref : *keyref" "\n"
5219 std::string resolved =
""
5221 " name: Everyone has same name" "\n"
5223 " name: Everyone has same name" "\n"
5226 " name: Everyone has same name" "\n"
5230 " 123 Tornado Alley" "\n"
5232 " city: East Centerville" "\n"
5236 " 123 Tornado Alley" "\n"
5238 " city: East Centerville" "\n"
5246 CHECK( ! tree[
"base"].has_key_anchor());
5247 CHECK( tree[
"base"].has_val_anchor());
5248 CHECK( tree[
"base"].val_anchor() ==
"base");
5249 CHECK( tree[
"key"].key_anchor() ==
"keyref");
5250 CHECK( tree[
"key"].val_anchor() ==
"valref");
5251 CHECK( tree[
"*valref"].is_key_ref());
5252 CHECK( tree[
"*valref"].is_val_ref());
5253 CHECK( tree[
"*valref"].key_ref() ==
"valref");
5254 CHECK( tree[
"*valref"].val_ref() ==
"keyref");
5261 CHECK( ! tree[
"base"].has_key_anchor());
5262 CHECK( ! tree[
"base"].has_val_anchor());
5263 CHECK( ! tree[
"base"].has_val_anchor());
5264 CHECK( ! tree[
"key"].has_key_anchor());
5265 CHECK( ! tree[
"key"].has_val_anchor());
5266 CHECK( ! tree[
"val"].is_key_ref());
5267 CHECK( ! tree[
"val"].is_val_ref());
5269 CHECK(tree[
"ship_to"][
"city"].val() ==
"East Centerville");
5270 CHECK(tree[
"ship_to"][
"state"].val() ==
"KS");
5288 t[
"nref"].
set_val(
"*vanchor");
5290 "&kanchor kanchor: 2" "\n"
5291 "vanchor: &vanchor 3" "\n"
5292 "kref: *kanchor" "\n"
5293 "vref: *vanchor" "\n"
5296 "nref: '*vanchor'" "\n"
5302 "kref: kanchor" "\n"
5305 "nref: '*vanchor'" "\n"
5312 "orig: &orig {foo: bar, baz: bat}" "\n"
5320 t[
"notref"][
"<<"].
set_val(
"*orig");
5322 "orig: &orig {foo: bar,baz: bat}" "\n"
5323 "copy: {<<: *orig}" "\n"
5324 "notcopy: {test: *orig,<<: *orig}" "\n"
5325 "notref: {<<: '*orig'}" "\n"
5329 "orig: {foo: bar,baz: bat}" "\n"
5330 "copy: {foo: bar,baz: bat}" "\n"
5331 "notcopy: {test: {foo: bar,baz: bat},foo: bar,baz: bat}" "\n"
5332 "notref: {<<: '*orig'}" "\n"
5339 "orig1: &orig1 {foo: bar}" "\n"
5340 "orig2: &orig2 {baz: bat}" "\n"
5341 "orig3: &orig3 {and: more}" "\n"
5350 "orig1: &orig1 {foo: bar}" "\n"
5351 "orig2: &orig2 {baz: bat}" "\n"
5352 "orig3: &orig3 {and: more}" "\n"
5353 "copy: {<<: [*orig1,*orig2,*orig3]}" "\n"
5357 "orig1: {foo: bar}" "\n"
5358 "orig2: {baz: bat}" "\n"
5359 "orig3: {and: more}" "\n"
5360 "copy: {foo: bar,baz: bat,and: more}" "\n");
5369 const std::string yaml =
""
5378 "--- !!str a b" "\n"
5379 "--- !!str 'a: b'" "\n"
5396 CHECK(doc.is_doc());
5398 CHECK(root[0].has_val_tag());
5399 CHECK(root[0].val_tag() ==
"!!map");
5400 CHECK(root[1].val_tag() ==
"!map");
5401 CHECK(root[2].val_tag() ==
"!!seq");
5402 CHECK(root[3].val_tag() ==
"!!str");
5403 CHECK(root[4].val_tag() ==
"!!str");
5404 CHECK(root[5][
"a"].has_key_tag());
5405 CHECK(root[5][
"a"].key_tag() ==
"!!str");
5406 CHECK(root[6].val_tag() ==
"!!set");
5407 CHECK(root[7].val_tag() ==
"!!set");
5408 CHECK(root[8].val_tag() ==
"!!seq");
5409 CHECK(root[8][0].val_tag() ==
"!!int");
5410 CHECK(root[8][1].val_tag() ==
"!!str");
5468 "--- !!str a b" "\n"
5469 "--- !!str 'a: b'" "\n"
5484 "--- !<tag:yaml.org,2002:map>" "\n"
5489 "--- !<tag:yaml.org,2002:seq>" "\n"
5492 "--- !<tag:yaml.org,2002:str> a b" "\n"
5493 "--- !<tag:yaml.org,2002:str> 'a: b'" "\n"
5495 "!<tag:yaml.org,2002:str> a: b" "\n"
5496 "--- !<tag:yaml.org,2002:set>" "\n"
5499 "--- !<tag:yaml.org,2002:set>" "\n"
5501 "--- !<tag:yaml.org,2002:seq>" "\n"
5502 "- !<tag:yaml.org,2002:int> 0" "\n"
5503 "- !<tag:yaml.org,2002:str> 1" "\n"
5512 const std::string yaml =
""
5513 "%TAG !m! !my-" "\n"
5514 "--- # Bulb here" "\n"
5515 "!m!light fluorescent" "\n"
5517 "%TAG !m! !meta-" "\n"
5518 "--- # Color here" "\n"
5519 "!m!light green" "\n"
5524 "%TAG !m! !my-" "\n"
5525 "--- !m!light fluorescent" "\n"
5527 "%TAG !m! !meta-" "\n"
5528 "--- !m!light green" "\n"
5535 "%TAG !m! !my-" "\n"
5536 "--- !<!my-light> fluorescent" "\n"
5538 "%TAG !m! !meta-" "\n"
5539 "--- !<!meta-light> green" "\n"
5546 "%TAG !m! !my-" "\n"
5547 "--- !<!my-light> fluorescent" "\n"
5549 "%TAG !m! !meta-" "\n"
5550 "--- !<!meta-light> green" "\n"
5586 CHECK(doc.is_doc());
5605 CHECK(stream[0].is_doc());
5606 CHECK(stream[0].is_map());
5607 CHECK(stream[0][
"a"].val() ==
"0");
5608 CHECK(stream[0][
"b"].val() ==
"1");
5617 CHECK(stream[1].is_doc());
5618 CHECK(stream[1].is_map());
5619 CHECK(stream[1][
"c"].val() ==
"2");
5620 CHECK(stream[1][
"d"].val() ==
"3");
5629 CHECK(stream[2].is_doc());
5630 CHECK(stream[2].is_seq());
5631 CHECK(stream[2][0].val() ==
"4");
5632 CHECK(stream[2][1].val() ==
"5");
5633 CHECK(stream[2][2].val() ==
"6");
5634 CHECK(stream[2][3].val() ==
"7");
5672 return ryml::emitrs_json<std::string>(err_tree, err_opts);
5676 const std::string expected_json[] = {
5735 ryml::Tree tree = ryml::parse_in_arena(
"errorhandler.yml",
"[a: b\n}");
5746 auto cause_basic_error = []{
5755#ifdef _RYML_WITH_EXCEPTIONS
5759 cause_basic_error();
5781 auto cause_parse_error = [&]{
5805 msg_ctx.append(s.
str, s.
len);
5807 CHECK(
ryml::to_csubstr(msg_ctx).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
5809 "file.yml:3: col=4 (12B): err:" "\n"
5815 "err: see region:" "\n"
5850 CHECK(errh.
saved_msg_full ==
"file.yml:3: col=4 (12B): ERROR: [basic] invalid character: '['");
5863#ifdef _RYML_WITH_EXCEPTIONS
5867 cause_parse_error();
5879 CHECK(msg ==
"invalid character: '['");
5884 auto dumpfn = [&full](
ryml::csubstr s) { full.append(s.str, s.len); };
5888 CHECK(
ryml::to_csubstr(full).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
5890 "file.yml:3: col=4 (12B): err:" "\n"
5896 "err: see region:" "\n"
5909 cause_parse_error();
5935 tree[
"float"] >> intval;
5964 tree[
"float"] >> intval;
5976#ifdef _RYML_WITH_EXCEPTIONS
5988 tree[
"float"] >> intval;
6009 tree[
"float"] >> intval;
6046 "float: 123.456" "\n"
6050 auto cause_visit_error = [&]{
6052 tree[
"float"] >> intval;
6084 msg.append(s.
str, s.
len);
6085 }, ymlloc, ymlsrc,
"err", 3);
6087 "file.yml:3: col=0 (24B): err:" "\n"
6089 "err: float: 123.456" "\n"
6093 "err: see region:" "\n"
6095 "err: foo: bar" "\n"
6098 "err: float: 123.456" "\n"
6139 uintptr_t uptr = (uintptr_t)ptr;
6140 const uintptr_t align =
alignof(max_align_t);
6143 uintptr_t prev = uptr - (uptr % align);
6144 uintptr_t next = prev + align;
6145 uintptr_t corr = next - uptr;
6146 ptr = (
void*)(((
char*)ptr) + corr);
6150 "out of memory! requested=%zu+%zu available=%zu\n",
6176 static void s_free(
void *mem,
size_t len,
void *this_)
6248 parse_in_arena(&parser,
"", R
"([a, b, c, d, {foo: bar, money: pennys}])", &tree);
6291 std::cerr <<
"out of memory! requested=" <<
alloc_size <<
" vs " <<
memory_pool.size() <<
" available" << std::endl;
6377 CHECK(tree["doe"].val() ==
"a deer, a female deer");
6393 "aa: contents," "\n"
6394 "foo: [one, [two, three]]" "\n"
6438 loc = tree[
"foo"].
location(parser);
6443 loc = tree[
"foo"][0].
location(parser);
6448 loc = tree[
"foo"][1].
location(parser);
6452 loc = tree[
"foo"][1][0].
location(parser);
6456 loc = tree[
"foo"][1][1].
location(parser);
6478 "a new: buffer" "\n"
6479 "to: be parsed" "\n"
6480 "map with key:" "\n"
6481 " first: value" "\n"
6482 " second: value" "\n"
6483 "seq with key:" "\n"
6484 " - first value" "\n"
6485 " - second value" "\n"
6487 " - nested first value" "\n"
6488 " - nested second value" "\n"
6490 " nested first: value" "\n"
6491 " nested second: value" "\n"
6505 loc = tree2[
"a new"].
location(parser);
6510 loc = tree2[
"to"].
location(parser);
6516 loc = tree2[
"map with key"].
location(parser);
6520 loc = tree2[
"map with key"][
"first"].
location(parser);
6524 loc = tree2[
"map with key"][
"second"].
location(parser);
6529 loc = tree2[
"seq with key"].
location(parser);
6533 loc = tree2[
"seq with key"][0].
location(parser);
6537 loc = tree2[
"seq with key"][1].
location(parser);
6542 loc = tree2[
"seq with key"][2].
location(parser);
6546 loc = tree2[
"seq with key"][2][0].
location(parser);
6551 loc = tree2[
"seq with key"][3].
location(parser);
6555 loc = tree2[
"seq with key"][3][0].
location(parser);
6571static int num_checks = 0;
6572static int num_failed_checks = 0;
6573static bool quiet_mode =
false;
6578 auto arg_matches = [](
const char *arg,
const char *shortform,
const char *longform) {
6579 return (0 == strcmp(arg, shortform) || 0 == strcmp(arg, longform));
6581 for(
int i = 1; i < argc; ++i)
6582 if(arg_matches(argv[i],
"-q",
"--quiet"))
6589 const char *msg = predicate ?
"OK! " :
"OK!";
6592 ++num_failed_checks;
6593 msg = predicate ?
"FAIL: " :
"FAIL";
6595 if(!result || !quiet_mode)
6597 std::cout << __FILE__ <<
':' << line <<
": " << msg << (predicate ? predicate :
"") << std::endl;
6605 std::cout <<
"Completed " << num_checks <<
" checks." << std::endl;
6606 if(num_failed_checks)
6607 std::cout <<
"ERROR: " << num_failed_checks <<
'/' << num_checks <<
" checks failed." << std::endl;
6609 std::cout <<
"SUCCESS!" << std::endl;
6610 return num_failed_checks;
6625 fwrite(s.
str, 1, s.
len, stderr);
6631 fputc(
'\n', stderr);
6646 .set_free([](
void* mem,
size_t,
void *){
6682#ifdef RYML_NO_DEFAULT_CALLBACKS
6691#ifndef C4_EXCEPTIONS
6722 bool got_error =
false;
6723 #ifdef C4_EXCEPTIONS
6726 std::forward<Fn>(fn)();
6728 catch(std::exception
const&)
6735 std::forward<Fn>(fn)();
6748[[noreturn]]
void stopexec(std::string
const& s)
6750 #ifdef C4_EXCEPTIONS
6751 throw std::runtime_error(s);
6876C4_SUPPRESS_WARNING_GCC_CLANG_POP
Holds a pointer to an existing tree, and a node id.
ConstNodeRef parent() const RYML_NOEXCEPT
Forward to Tree::parent().
ConstNodeRef child(id_type pos) const RYML_NOEXCEPT
Forward to Tree::child().
ConstNodeRef first_sibling() const RYML_NOEXCEPT
Forward to Tree::first_sibling().
id_type id() const noexcept
ConstNodeRef first_child() const RYML_NOEXCEPT
Forward to Tree::first_child().
ConstNodeRef last_child() const RYML_NOEXCEPT
Forward to Tree::last_child().
bool invalid() const noexcept
const_children_view children() const RYML_NOEXCEPT
get an iterable view over children
ConstNodeRef last_sibling() const RYML_NOEXCEPT
Forward to Tree::last_sibling().
Tree const * tree() const noexcept
ConstNodeRef next_sibling() const RYML_NOEXCEPT
Forward to Tree::next_sibling().
ConstNodeRef prev_sibling() const RYML_NOEXCEPT
Forward to Tree::prev_sibling().
bool readable() const noexcept
because a ConstNodeRef cannot be used to write to the tree, readable() has the same meaning as !...
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)
children_view children() RYML_NOEXCEPT
get an iterable view over children
void set_val(csubstr val)
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. The tree can be empty only when constructed ...
NodeRef rootref()
Get the root as a NodeRef . Note that a non-const Tree implicitly converts to NodeRef.
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
void set_val(id_type node, csubstr val) RYML_NOEXCEPT
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 . Note that Tree implicitly converts to ConstNodeRef.
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 ...
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 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)
substr emit_yaml(Tree const &t, EmitOptions const &opts, substr buf, bool error_on_excess)
(1) emit YAML to the given buffer.
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<char>-like container,...
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<char>-like container,...
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, FILE *file, const char *filename=nullptr)
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 *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 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...
void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *tree, 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
@ npos
a null string position
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...
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.
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 (or emit as seq) when finding 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...
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 ParseEngine 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.
tag type to mark a tree or node to be emitted as yaml when using operator<<, with options.
bool is_val() const RYML_NOEXCEPT
Forward to Tree::is_val().
bool is_root() const RYML_NOEXCEPT
Forward to Tree::is_root().
bool is_stream() const RYML_NOEXCEPT
Forward to Tree::is_stream().
NodeType type() const RYML_NOEXCEPT
Forward to Tree::type().
bool has_child(ConstImpl const &n) const RYML_NOEXCEPT
Forward to Tree::has_child().
bool is_map() const RYML_NOEXCEPT
Forward to Tree::is_map().
id_type num_siblings() const RYML_NOEXCEPT
O(num_children).
bool has_key() const RYML_NOEXCEPT
Forward to Tree::has_key().
csubstr key() const RYML_NOEXCEPT
Forward to Tree::key().
csubstr val() const RYML_NOEXCEPT
Forward to Tree::val().
bool is_doc() const RYML_NOEXCEPT
Forward to Tree::is_doc().
id_type num_children() const RYML_NOEXCEPT
O(num_children).
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().
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