200#if defined(RYML_SINGLE_HEADER)
201 #define RYML_SINGLE_HDR_DEFINE_NOW
202 #include <ryml_all.hpp>
203#elif defined(RYML_SINGLE_HEADER_LIB)
204 #include <ryml_all.hpp>
239int main(
int argc,
const char* argv[])
303bool report_check(
int line,
const char *predicate,
bool result);
308# define CHECK(predicate) assert(predicate)
311# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC_MINOR__ > 8))))
312# define CHECK(predicate) report_check(__LINE__, #predicate, (predicate))
314# define CHECK CheckPredicate{__LINE__}
316 struct CheckPredicate
319 void operator() (
bool result)
const {
report_check(line,
nullptr, result); }
385C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
386C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wold-style-cast")
387C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wcast-qual")
388C4_SUPPRESS_WARNING_GCC(
"-Wuseless-cast")
389C4_SUPPRESS_WARNING_GCC(
"-Wuseless-cast")
390#if defined(__GNUC__) && (__GNUC__ >= 6)
391C4_SUPPRESS_WARNING_GCC(
"-Wnull-dereference")
393#if defined(__clang__) && (__clang_major__ >= 13)
394C4_SUPPRESS_WARNING_CLANG(
"-Wreserved-identifier")
410 char yml_buf[] =
"{foo: 1, bar: [2, 3], john: doe}";
415 CHECK(bar[0].val() ==
"2");
416 CHECK(bar[1].val() ==
"3");
417 CHECK(bar[0].val().str == yml_buf + 15);
418 CHECK(bar[1].val().str == yml_buf + 18);
421 int bar0 = 0, bar1 = 0;
430 CHECK(bar[0].val() ==
"10");
431 CHECK(bar[1].val() ==
"11");
436 CHECK(bar[2].val() ==
"12");
439 std::string expected =
"{foo: 1,bar: [10,11,12],john: doe,new: node}";
445 std::cout << tree <<
"\n";
449 expected =
"foo: 1\n";
534 CHECK(tree[
"foo"].is_keyval());
535 CHECK(tree[
"foo"].val() ==
"1");
536 CHECK(tree[
"foo"].key() ==
"foo");
537 CHECK(tree[
"bar"].is_seq());
538 CHECK(tree[
"bar"].has_key());
539 CHECK(tree[
"bar"].key() ==
"bar");
541 CHECK(tree[
"bar"][0].val() ==
"2");
542 CHECK(tree[
"bar"][1].val() ==
"3");
543 CHECK(tree[
"john"].val() ==
"doe");
547 CHECK(tree[0].
id() == tree[
"foo"].
id());
548 CHECK(tree[1].
id() == tree[
"bar"].
id());
549 CHECK(tree[2].
id() == tree[
"john"].
id());
551 CHECK(tree[0].
id() == tree[
"foo"].
id());
552 CHECK(tree[1].
id() == tree[
"bar"].
id());
553 CHECK(tree[2].
id() == tree[
"john"].
id());
555 CHECK(bar[0].val() ==
"2");
556 CHECK(bar[1].val() ==
"3");
561 CHECK(tree[
"foo"].key() ==
"foo");
562 CHECK(tree[
"bar"].key() ==
"bar");
563 CHECK(tree[
"john"].key() ==
"john");
568 CHECK(root[
"foo"].
id() == root[0].
id());
569 CHECK(root[
"bar"].
id() == root[1].
id());
570 CHECK(root[
"john"].
id() == root[2].
id());
629 CHECK(child.key() == expected_keys[count++]);
635 CHECK(child.key() == expected_keys[count++]);
641 CHECK(tree.
key(child_id) == expected_keys[count++]);
650 CHECK(tree.
key(child_id) == expected_keys[count++]);
725 int foo = 0, bar0 = 0, bar1 = 0;
726 root[
"foo"].
load(&foo);
727 root[
"bar"][0].
load(&bar0);
728 root[
"bar"][1].
load(&bar1);
736 int foo = 0, bar0 = 0, bar1 = 0;
737 CHECK(root[
"foo"].deserialize(&foo));
738 CHECK(root[
"bar"][0].deserialize(&bar0));
739 CHECK(root[
"bar"][1].deserialize(&bar1));
748 std::string john_str, bar_str;
749 root[
"john"].
load(&john_str);
751 CHECK(john_str ==
"doe");
752 CHECK(bar_str ==
"bar");
753 std::vector<int> bar_actual, bar_expected{{2, 3}};
754 root[
"bar"].
load(&bar_actual);
755 CHECK(bar_actual == bar_expected);
773 wroot[
"foo"].
set_val(
"says you");
780 CHECK(root[
"foo"].val() ==
"says you");
781 CHECK(root[
"bar"][0].val() ==
"-2");
782 CHECK(root[
"bar"][1].val() ==
"-3");
783 CHECK(root[
"john"].val() ==
"ron");
804 CHECK(root[
"foo"].val() ==
"says who");
805 CHECK(root[
"bar"][0].val() ==
"20");
806 CHECK(root[
"bar"][1].val() ==
"30");
807 CHECK(root[
"john"].val() ==
"deere");
811 std::string ok(
"in_scope");
815 CHECK(root[
"john"].val() ==
"in_scope");
821 CHECK(tree.
arena() ==
"says who2030deerein_scope2.42.400000");
829 wroot[
"newkeyval"].
set_val(
"shiny and new");
834 CHECK(root[
"newkeyval"].key() ==
"newkeyval");
835 CHECK(root[
"newkeyval"].val() ==
"shiny and new");
836 CHECK(root[
"newkeyval (serialized)"].key() ==
"newkeyval (serialized)");
837 CHECK(root[
"newkeyval (serialized)"].val() ==
"shiny and new (serialized)");
843 CHECK(root[
"bar"].num_children() == 2);
844 wroot[
"bar"][2].
set_val(
"oh so nice");
846 CHECK(root[
"bar"].num_children() == 4);
847 CHECK(root[
"bar"][2].val() ==
"oh so nice");
848 CHECK(root[
"bar"][3].val() ==
"oh so nice (serialized)");
856 CHECK(root[
"newseq"].num_children() == 0);
857 CHECK(root[
"newseq"].is_seq());
858 CHECK(root[
"newseq (serialized)"].num_children() == 0);
859 CHECK(root[
"newseq (serialized)"].is_seq());
867 CHECK(root[
"newmap"].num_children() == 0);
868 CHECK(root[
"newmap"].is_map());
869 CHECK(root[
"newmap (serialized)"].num_children() == 0);
870 CHECK(root[
"newmap (serialized)"].is_map());
903 nothing = wroot[
"I am nothing"];
920 CHECK(root[
"I am something"].val() ==
"indeed");
951 CHECK(wbar[0].readable() && wbar[0].val() ==
"20");
952 CHECK( ! wbar[100].readable());
953 CHECK( ! wbar[100].readable() || wbar[100].val() ==
"100");
955 CHECK( ! wbar[0].is_seed() && wbar[0].val() ==
"20");
956 CHECK(wbar[100].is_seed() || wbar[100].val() ==
"100");
985 return seed_node.at(
"is").at(
"an").at(
"invalid").at(
"operation");
992 return seed_node[
"is"][
"an"][
"invalid"][
"operation"];
1003 "foo: says who" "\n"
1004 "bar: [20,30,oh so nice,oh so nice (serialized)]" "\n"
1005 "john: in_scope" "\n"
1007 "digits: 2.400000" "\n"
1008 "newkeyval: shiny and new" "\n"
1009 "newkeyval (serialized): shiny and new (serialized)" "\n"
1011 "newseq (serialized): []" "\n"
1013 "newmap (serialized): {}" "\n"
1014 "I am something: indeed" "\n"
1023 std::stringstream ss;
1025 std::string stream_result = ss.str();
1032 CHECK(buf_result == expected_result);
1033 CHECK(str_result == expected_result);
1034 CHECK(stream_result == expected_result);
1050 CHECK(tree[
"bar"][0].val() ==
"21");
1052 CHECK(tree[
"bar"][0].val() ==
"22");
1058 constnoderef = noderef;
1064 noderef = tree[
"bar"][0];
1065 constnoderef = consttree[
"bar"][0];
1069 CHECK(constnoderef == noderef);
1070 CHECK(!(constnoderef != noderef));
1080 ryml::Tree tree2 = parse_in_arena(&parser,
"expected.yml", expected_result);
1096 "# UTF8/16/32 can be placed directly in any scalar:" "\n"
1098 "en: Planet (Gas)" "\n"
1099 "fr: Planète (Gazeuse)" "\n"
1100 "ru: Планета (Газ)" "\n"
1104 "# UTF8 decoding only happens in double-quoted strings," "\n"
1105 "# as per the YAML standard" "\n"
1107 "decode this: \"\\u263A c\\x61f\\xE9\"" "\n"
1108 "and this as well: \"\\u2705 \\U0001D11E\"" "\n"
1109 "not decoded: '\\u263A \\xE2\\x98\\xBA'" "\n"
1110 "neither this: '\\u2705 \\U0001D11E'" "\n");
1112 CHECK(langs[
"en"].val() ==
"Planet (Gas)");
1113 CHECK(langs[
"fr"].val() ==
"Planète (Gazeuse)");
1114 CHECK(langs[
"ru"].val() ==
"Планета (Газ)");
1115 CHECK(langs[
"ja"].val() ==
"惑星(ガス)");
1116 CHECK(langs[
"zh"].val() ==
"行星(气体)");
1120 CHECK(langs[
"decode this"].val() ==
"☺ café");
1121 CHECK(langs[
"and this as well"].val() ==
"✅ 𝄞");
1122 CHECK(langs[
"not decoded"].val() ==
"\\u263A \\xE2\\x98\\xBA");
1123 CHECK(langs[
"neither this"].val() ==
"\\u2705 \\U0001D11E");
1151 const char foobar_str[] =
"foobar";
1153 CHECK(s ==
"foobar");
1154 CHECK(s.size() == 6);
1155 CHECK(s.data() == foobar_str);
1156 CHECK(s.size() == s.len);
1157 CHECK(s.data() == s.str);
1162 const char foobar_str[] =
"foobar";
1164 CHECK(s ==
"foobar");
1165 CHECK(s !=
"foobar0");
1174 CHECK(s ==
"foobar");
1175 CHECK(s !=
"foobar0");
1187 const char *foobar_str =
"foobar";
1189 CHECK(s ==
"foobar");
1190 CHECK(s !=
"foobar0");
1204 std::string foobar_str =
"foobar";
1206 CHECK(s ==
"foobar");
1207 CHECK(s !=
"foobar0");
1229 char const foobar_str_ro[] =
"foobar";
1230 char foobar_str_rw[] =
"foobar";
1231 static_assert(std::is_array<
decltype(foobar_str_ro)>::value,
"this is an array");
1232 static_assert(std::is_array<
decltype(foobar_str_rw)>::value,
"this is an array");
1237 CHECK(foobar.
size() == strlen(foobar_str_ro));
1238 CHECK(foobar ==
"foobar");
1244 CHECK(foobar.
size() == strlen(foobar_str_rw));
1245 CHECK(foobar ==
"foobar");
1251 CHECK(foobar.
size() == strlen(foobar_str_rw));
1252 CHECK(foobar ==
"foobar");
1263 char const* foobar_str_ro =
"foobar";
1264 char foobar_str_rw_[] =
"foobar";
1265 char * foobar_str_rw = foobar_str_rw_;
1266 static_assert(!std::is_array<
decltype(foobar_str_ro)>::value,
"this is a decayed pointer");
1267 static_assert(!std::is_array<
decltype(foobar_str_rw)>::value,
"this is a decayed pointer");
1273 CHECK(foobar.
size() == strlen(foobar_str_ro));
1274 CHECK(foobar ==
"foobar");
1280 CHECK(foobar.
size() == strlen(foobar_str_rw));
1281 CHECK(foobar ==
"foobar");
1287 CHECK(foobar.
size() == strlen(foobar_str_rw));
1288 CHECK(foobar ==
"foobar");
1298 char buf[] =
"foobar";
1300 CHECK(foobar ==
"foobar");
1301 foobar[0] =
'F';
CHECK(foobar ==
"Foobar");
1302 foobar.
back() =
'R';
CHECK(foobar ==
"FoobaR");
1314 foobar.
fill(
'.');
CHECK(foobar ==
"......");
1326 CHECK(s.
sub(0, 12) ==
"fooFOObarBAR");
1386 CHECK(some ==
"some");
1387 CHECK(s ==
"some substring");
1390 char result[32] = {0};
1391 std::snprintf(result,
sizeof(result),
"%.*s", (
int)some.
len, some.
str);
1392 printf(
"~~~%s~~~\n", result);
1402 char result[32] = {0};
1403 std::snprintf(result,
sizeof(result),
"%s", some.
str);
1413 CHECK(some ==
"some");
1414 CHECK(s ==
"some substring");
1417 std::stringstream ss;
1419 CHECK(ss.str() ==
"some substring");
1420 CHECK(ss.str() == s);
1428 std::stringstream ss;
1430 CHECK(ss.str() ==
"some substring");
1431 CHECK(ss.str() == s);
1435 std::stringstream ss;
1437 CHECK(ss.str() ==
"some substring");
1438 CHECK(ss.str() == s);
1442 std::stringstream ss;
1444 CHECK(ss.str() ==
"some");
1445 CHECK(ss.str() == some);
1482 CHECK(
ryml::csubstr(
" \t\n\rcontents without whitespace\t \n\r").trim(
"\t \n\r") ==
"contents without whitespace");
1503 CHECK(aaa___bbb.
trim (
'c') == aaa___bbb);
1522 CHECK(aaa___bbb.
trim (
"cd") == aaa___bbb);
1527 CHECK(
ryml::csubstr(
"'this is is single quoted'" ).unquoted() ==
"this is is single quoted");
1528 CHECK(
ryml::csubstr(
"\"this is is double quoted\"").unquoted() ==
"this is is double quoted");
1846 CHECK(
ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extshort() ==
"/path/to/file.tar");
1852 using namespace ryml;
1853 csubstr parts[] = {
"aa",
"bb",
"cc",
"dd",
"ee",
"ff"};
1857 CHECK(part == parts[count++]);
1863 CHECK(part == parts[count++]);
1869 CHECK(part == parts[count++]);
1878 const bool skip_empty =
true;
1951 const char filename[] =
"ryml_example.yml";
1952 std::string yaml =
""
1966 CHECK(tree[
"foo"].val() ==
"1");
1967 CHECK(tree[
"bar"][0].val() ==
"2");
1968 CHECK(tree[
"bar"][1].val() ==
"3");
1975 CHECK(tree[
"foo"].val() ==
"1");
1976 CHECK(tree[
"bar"][0].val() ==
"2");
1977 CHECK(tree[
"bar"][1].val() ==
"3");
1998 char src[] =
"{foo: 1, bar: [2, 3]}";
2004 CHECK(root[
"foo"].is_keyval());
2005 CHECK(root[
"foo"].key() ==
"foo");
2006 CHECK(root[
"foo"].val() ==
"1");
2007 CHECK(root[
"bar"].is_seq());
2008 CHECK(root[
"bar"].has_key());
2009 CHECK(root[
"bar"].key() ==
"bar");
2010 CHECK(root[
"bar"][0].val() ==
"2");
2011 CHECK(root[
"bar"][1].val() ==
"3");
2014 int foo = 0, bar0 = 0, bar1 = 0;
2015 root[
"foo"].
load(&foo);
2016 root[
"bar"][0].
load(&bar0);
2017 root[
"bar"][1].
load(&bar1);
2023 CHECK(root[
"foo"].val().data() == src + strlen(
"{foo: "));
2024 CHECK(root[
"foo"].val().begin() == src + strlen(
"{foo: "));
2025 CHECK(root[
"foo"].val().end() == src + strlen(
"{foo: 1"));
2026 CHECK(root[
"foo"].val().is_sub(srcview));
2027 CHECK(root[
"bar"][0].val().data() == src + strlen(
"{foo: 1, bar: ["));
2028 CHECK(root[
"bar"][0].val().begin() == src + strlen(
"{foo: 1, bar: ["));
2029 CHECK(root[
"bar"][0].val().end() == src + strlen(
"{foo: 1, bar: [2"));
2030 CHECK(root[
"bar"][0].val().is_sub(srcview));
2031 CHECK(root[
"bar"][1].val().data() == src + strlen(
"{foo: 1, bar: [2, "));
2032 CHECK(root[
"bar"][1].val().begin() == src + strlen(
"{foo: 1, bar: [2, "));
2033 CHECK(root[
"bar"][1].val().end() == src + strlen(
"{foo: 1, bar: [2, 3"));
2034 CHECK(root[
"bar"][1].val().is_sub(srcview));
2056 CHECK(root[
"foo"].is_keyval());
2057 CHECK(root[
"foo"].key() ==
"foo");
2058 CHECK(root[
"foo"].val() ==
"1");
2059 CHECK(root[
"bar"].is_seq());
2060 CHECK(root[
"bar"].has_key());
2061 CHECK(root[
"bar"].key() ==
"bar");
2062 CHECK(root[
"bar"][0].val() ==
"2");
2063 CHECK(root[
"bar"][1].val() ==
"3");
2066 int foo = 0, bar0 = 0, bar1 = 0;
2067 root[
"foo"].
load(&foo);
2068 root[
"bar"][0].
load(&bar0);
2069 root[
"bar"][1].
load(&bar1);
2077 char src[] =
"{foo: is it really true}";
2086 CHECK(tree[
"foo"].val() ==
"is it really true");
2114 CHECK(root[
"foo"].is_keyval());
2115 CHECK(root[
"foo"].key() ==
"foo");
2116 CHECK(root[
"foo"].val() ==
"1");
2117 CHECK(root[
"bar"].is_seq());
2118 CHECK(root[
"bar"].has_key());
2119 CHECK(root[
"bar"].key() ==
"bar");
2120 CHECK(root[
"bar"][0].val() ==
"2");
2121 CHECK(root[
"bar"][1].val() ==
"3");
2130 "bar2: [22,32]" "\n"
2133 CHECK(root[
"foo2"].is_keyval());
2134 CHECK(root[
"foo2"].key() ==
"foo2");
2135 CHECK(root[
"foo2"].val() ==
"12");
2136 CHECK(root[
"bar2"].is_seq());
2137 CHECK(root[
"bar2"].has_key());
2138 CHECK(root[
"bar2"].key() ==
"bar2");
2139 CHECK(root[
"bar2"][0].val() ==
"22");
2140 CHECK(root[
"bar2"][1].val() ==
"32");
2149 CHECK(root[0].val() ==
"a");
2150 CHECK(root[1].val() ==
"b");
2151 CHECK(root[2].is_map());
2152 CHECK(root[2][
"x0"].val() ==
"1");
2153 CHECK(root[2][
"x1"].val() ==
"2");
2161 "- {x0: 1,x1: 2}" "\n"
2162 "- champagne: Dom Perignon" "\n"
2163 " coffee: Arabica" "\n"
2166 CHECK(root[0].val() ==
"a");
2167 CHECK(root[1].val() ==
"b");
2168 CHECK(root[2].is_map());
2169 CHECK(root[2][
"x0"].val() ==
"1");
2170 CHECK(root[2][
"x1"].val() ==
"2");
2171 CHECK(root[3].is_map());
2172 CHECK(root[3][
"champagne"].val() ==
"Dom Perignon");
2173 CHECK(root[3][
"coffee"].val() ==
"Arabica");
2177 CHECK(mroot[3][
"more"].readable());
2178 CHECK(mroot[3][
"more"].key() ==
"more");
2179 CHECK(mroot[3][
"more"].is_map());
2180 CHECK(!mroot[3][
"more"].is_val());
2187 "- {x0: 1,x1: 2}" "\n"
2188 "- champagne: Dom Perignon" "\n"
2189 " coffee: Arabica" "\n"
2192 " vinho verde: Soalheiro" "\n"
2193 " vinho tinto: Redoma 2017" "\n"
2195 " - Rochefort 10" "\n"
2197 " - Leffe Rituel" "\n"
2198 " always: lots of water" "\n"
2206 "- {x0: 1,x1: 2}" "\n"
2207 "- champagne: Dom Perignon" "\n"
2208 " coffee: Arabica" "\n"
2210 " vinho verde: Soalheiro" "\n"
2211 " vinho tinto: Redoma 2017" "\n"
2213 " - Rochefort 10" "\n"
2215 " - Leffe Rituel" "\n"
2216 " always: lots of water" "\n"
2229 "- {x0: 1,x1: 2}" "\n"
2230 "- champagne: Dom Perignon" "\n"
2231 " coffee: Arabica" "\n"
2233 " vinho verde: Soalheiro" "\n"
2234 " vinho tinto: Redoma 2017" "\n"
2236 " - Rochefort 10" "\n"
2238 " - Leffe Rituel" "\n"
2239 " - Kasteel Donker" "\n"
2240 " always: lots of water" "\n"
2268 ryml::csubstr yaml =
"[Dom Perignon,Gosset Grande Reserve,Jacquesson 742]";
2272 yaml =
"[Rochefort 10,Busch,Leffe Rituel,Kasteel Donker]";
2306 "- Gosset Grande Reserve\n"
2307 "- Jacquesson 742\n"
2313 "- Kasteel Donker\n"
2317 "- Niepoort Redoma 2017\n"
2318 "- Vina Esmeralda\n"
2328 "- Gosset Grande Reserve\n"
2329 "- Jacquesson 742\n"
2333 "- Kasteel Donker\n"
2341 "- Niepoort Redoma 2017\n"
2342 "- Vina Esmeralda\n"
2358 "doe: a deer, a female deer" "\n"
2359 "ray: 'a drop of golden sun'" "\n"
2360 "me: \"a name I call myself\"" "\n"
2362 " a long long way to go" "\n"
2364 " a needle pulling thread" "\n"
2365 "seq: [0,1,2,3]" "\n"
2375 CHECK(tree[
"doe"].is_val_plain());
2376 CHECK(tree[
"ray"].is_val_squo());
2377 CHECK(tree[
"me"].is_val_dquo());
2378 CHECK(tree[
"far"].is_val_literal());
2379 CHECK(tree[
"sow"].is_val_folded());
2380 CHECK(tree[
"seq"].is_flow());
2381 CHECK(tree[
"seq"].is_flow_sl());
2382 CHECK(tree[
"map"].is_flow());
2383 CHECK(tree[
"map"].is_flow_mlx());
2399 "doe: a deer, a female deer" "\n"
2400 "ray: a drop of golden sun" "\n"
2403 "french-hens: 3" "\n"
2404 "calling-birds:" "\n"
2409 "xmas-fifth-day:" "\n"
2410 " calling-birds: four" "\n"
2411 " french-hens: 3" "\n"
2412 " golden-rings: 5" "\n"
2415 " location: a pear tree" "\n"
2416 " turtle-doves: two" "\n"
2423 std::vector<ryml::csubstr> keys, vals;
2426 keys.emplace_back(n.key());
2429 CHECK(keys.size() >= 6);
2430 CHECK(vals.size() >= 6);
2431 if(keys.size() >= 6 && vals.size() >= 6)
2433 CHECK(keys[0] ==
"doe");
2434 CHECK(vals[0] ==
"a deer, a female deer");
2435 CHECK(keys[1] ==
"ray");
2436 CHECK(vals[1] ==
"a drop of golden sun");
2437 CHECK(keys[2] ==
"pi");
2438 CHECK(vals[2] ==
"3.14159");
2439 CHECK(keys[3] ==
"xmas");
2440 CHECK(vals[3] ==
"true");
2441 CHECK(root[5].has_key());
2442 CHECK(root[5].is_seq());
2443 CHECK(root[5].key() ==
"calling-birds");
2444 CHECK(!root[5].has_val());
2446 CHECK(keys[5] ==
"calling-birds");
2447 CHECK(vals[5] ==
"");
2454 ryml::csubstr calling_birds[] = {
"huey",
"dewey",
"louie",
"fred"};
2456 CHECK(n.val() == calling_birds[count++]);
2476 "aa: contents," "\n"
2477 "foo: [one, [two, three]]" "\n"
2521 loc = tree[
"foo"].
location(parser);
2526 loc = tree[
"foo"][0].
location(parser);
2531 loc = tree[
"foo"][1].
location(parser);
2535 loc = tree[
"foo"][1][0].
location(parser);
2539 loc = tree[
"foo"][1][1].
location(parser);
2561 "a new: buffer" "\n"
2562 "to: be parsed" "\n"
2563 "map with key:" "\n"
2564 " first: value" "\n"
2565 " second: value" "\n"
2566 "seq with key:" "\n"
2567 " - first value" "\n"
2568 " - second value" "\n"
2570 " - nested first value" "\n"
2571 " - nested second value" "\n"
2573 " nested first: value" "\n"
2574 " nested second: value" "\n"
2588 loc = tree2[
"a new"].
location(parser);
2593 loc = tree2[
"to"].
location(parser);
2599 loc = tree2[
"map with key"].
location(parser);
2603 loc = tree2[
"map with key"][
"first"].
location(parser);
2607 loc = tree2[
"map with key"][
"second"].
location(parser);
2612 loc = tree2[
"seq with key"].
location(parser);
2616 loc = tree2[
"seq with key"][0].
location(parser);
2620 loc = tree2[
"seq with key"][1].
location(parser);
2625 loc = tree2[
"seq with key"][2].
location(parser);
2629 loc = tree2[
"seq with key"][2][0].
location(parser);
2634 loc = tree2[
"seq with key"][3].
location(parser);
2638 loc = tree2[
"seq with key"][3][0].
location(parser);
2665 const char a_deer[] =
"a deer, a female deer";
2674 std::string a_drop =
"a drop of golden sun";
2683 CHECK(root[
"ray"].val() ==
"a drop of golden sun");
2697 xmas5[
"calling-birds"].
set_val(
"four");
2700 xmas5[
"partridges"].
set_map();
2702 xmas5[
"partridges"][
"location"].
set_val(
"a pear tree");
2703 xmas5[
"turtle-doves"].
set_val(
"two");
2707 "doe: a deer, a female deer" "\n"
2708 "ray: a drop of golden sun" "\n"
2711 "french-hens: 3" "\n"
2712 "calling-birds:" "\n"
2717 "xmas-fifth-day:" "\n"
2718 " calling-birds: four" "\n"
2719 " french-hens: 3" "\n"
2720 " golden-rings: 5" "\n"
2723 " location: a pear tree" "\n"
2724 " turtle-doves: two" "\n"
2769 root[
"not plain"].
set_val(
" with whitespace ");
2783 for(
int i : {0, 1, 2, 3})
2808 "not plain: ' with whitespace '" "\n"
2812 "doe: a deer, a female deer" "\n"
2813 "ray: 'a drop of golden sun'" "\n"
2814 "me: \"a name I call myself\"" "\n"
2816 " a long long way to go" "\n"
2818 " a needle pulling thread" "\n"
2819 "seq: [0, 1, 2, 3]" "\n"
2827 " 1: 10,2: 20,3: 30,4: 40" "\n"
2840 "plain: with whitespace " "\n"
2854 char buf[] =
"[a, b, c, d]";
2884 CHECK(root[0].val().is_sub(arena));
2885 CHECK(root[1].val().is_sub(arena));
2886 CHECK(root[2].val().is_sub(arena));
2887 CHECK(root[3].val().is_sub(arena));
2897 char buf[] =
"[a, b, c, d]";
2905 CHECK(root[2].val() ==
"c");
2908 CHECK(root[2].val() ==
"12345");
2914 CHECK(root[3].val() ==
"d");
2917 CHECK(root[3].val() ==
"67890");
2933 CHECK(root[2].val() ==
"c");
2935 CHECK(root[2].val() ==
"12345");
2944 CHECK(root[3].val() ==
"67890");
2948 CHECK(tree.
arena() ==
"[a, b, c, d]1234567890");
2956 CHECK(c10 ==
"10101010");
2966 CHECK(root[
"a"].val() ==
"2222");
2976 CHECK(copied == mystr);
2977 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2986 memcpy(copied.
str, mystr.
str, mystr.
len);
2987 CHECK(copied == mystr);
2988 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
3037 CHECK(tree.
to_arena(
double(0.234)) ==
"0.234");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.234");
3047 const float fnan = std::numeric_limits<float >::quiet_NaN();
3048 const double dnan = std::numeric_limits<double>::quiet_NaN();
3049 const float finf = std::numeric_limits<float >::infinity();
3050 const double dinf = std::numeric_limits<double>::infinity();
3051 CHECK(tree.
to_arena( finf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf");
3052 CHECK(tree.
to_arena( dinf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf");
3053 CHECK(tree.
to_arena(-finf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf");
3054 CHECK(tree.
to_arena(-dinf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf");
3055 CHECK(tree.
to_arena( fnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan");
3056 CHECK(tree.
to_arena( dnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan.nan");
3060 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wfloat-equal");
3066 tree[
"ninf"].
load(&f);
CHECK(f == -finf);
3067 tree[
"ninf"].
load(&d);
CHECK(d == -dinf);
3068 tree[
"pinf"].
load(&f);
CHECK(f == finf);
3069 tree[
"pinf"].
load(&d);
CHECK(d == dinf);
3070 tree[
"nan" ].
load(&f);
CHECK(std::isnan(f));
3071 tree[
"nan" ].
load(&d);
CHECK(std::isnan(d));
3072 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3094 n.load(ryml::fmt::overflow_checked(valu8));
3097 n.load(ryml::fmt::overflow_checked(vali8));
3113 "dquoted: \"\"" "\n"
3116 "all_null: [~, null, Null, NULL]" "\n"
3117 "non_null: [nULL, non_null, non null, null it is not]" "\n"
3121 CHECK(tree[
"plain"].has_val());
3122 CHECK(tree[
"squoted"].has_val());
3123 CHECK(tree[
"dquoted"].has_val());
3124 CHECK(tree[
"literal"].has_val());
3125 CHECK(tree[
"folded"].has_val());
3126 CHECK( ! tree[
"all_null"].has_val());
3127 CHECK( ! tree[
"non_null"].has_val());
3129 CHECK( ! tree[
"plain"].is_container());
3130 CHECK( ! tree[
"squoted"].is_container());
3131 CHECK( ! tree[
"dquoted"].is_container());
3132 CHECK( ! tree[
"literal"].is_container());
3133 CHECK( ! tree[
"folded"].is_container());
3134 CHECK(tree[
"all_null"].is_container());
3135 CHECK(tree[
"non_null"].is_container());
3140 CHECK(tree[
"plain"].val().len == 0);
3141 CHECK(tree[
"squoted"].val().len == 0);
3142 CHECK(tree[
"dquoted"].val().len == 0);
3143 CHECK(tree[
"literal"].val().len == 0);
3144 CHECK(tree[
"folded"].val().len == 0);
3146 CHECK(tree[
"plain"].val().str ==
nullptr);
3147 CHECK(tree[
"squoted"].val().str !=
nullptr);
3148 CHECK(tree[
"dquoted"].val().str !=
nullptr);
3149 CHECK(tree[
"literal"].val().str !=
nullptr);
3150 CHECK(tree[
"folded"].val().str !=
nullptr);
3154 CHECK(tree[
"plain"].val() ==
nullptr);
3155 CHECK(tree[
"squoted"].val() !=
nullptr);
3156 CHECK(tree[
"dquoted"].val() !=
nullptr);
3157 CHECK(tree[
"literal"].val() !=
nullptr);
3158 CHECK(tree[
"folded"].val() !=
nullptr);
3163 CHECK(tree[
"plain"].val_is_null());
3164 CHECK( ! tree[
"squoted"].val_is_null());
3165 CHECK( ! tree[
"dquoted"].val_is_null());
3166 CHECK( ! tree[
"literal"].val_is_null());
3167 CHECK( ! tree[
"folded"].val_is_null());
3172 CHECK(child.val() !=
nullptr);
3173 CHECK(child.val_is_null());
3177 CHECK(child.val() !=
nullptr);
3178 CHECK( ! child.val_is_null());
3193 CHECK(null .len == 0);
CHECK(null .str ==
nullptr);
CHECK(null ==
nullptr);
3196 CHECK(tilde .len != 0);
CHECK(tilde .str !=
nullptr);
CHECK(tilde !=
nullptr);
3211 "empty_nonnull: ''" "\n"
3212 "str_null: null" "\n"
3221 return s.str ==
nullptr ?
"null" : s;
3229 "empty_null: null" "\n"
3230 "empty_nonnull: ''" "\n"
3231 "str_null: null" "\n"
3241 tree[
"empty_nonnull"].
set_serialized(null_if_predicate(nonnull));
3246 "empty_null: null" "\n"
3247 "empty_nonnull: ''" "\n"
3248 "str_null: null" "\n"
3249 "str_tilde: null" "\n"
3258 tree[
"empty_nonnull"].
set_serialized(tilde_if_predicate(nonnull));
3263 "empty_null: ~" "\n"
3264 "empty_nonnull: ''" "\n"
3282 char buf_[256] = {};
3284 size_t size =
ryml::format(buf,
"a={} foo {} {} bar {}", 0.1, 10, 11, 12);
3285 CHECK(size == strlen(
"a=0.1 foo 10 11 bar 12"));
3286 CHECK(buf.
first(size) ==
"a=0.1 foo 10 11 bar 12");
3289 size =
ryml::format({} ,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12);
3290 CHECK(size ==
ryml::format(buf,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12));
3291 CHECK(size == strlen(
"a=this_is_a foo 10 11 bar 12"));
3293 char smallbuf[8] = {};
3294 size =
ryml::format(smallbuf,
"{} is too large {}",
"this",
"for the buffer");
3295 CHECK(size == strlen(
"this is too large for the buffer"));
3301 CHECK(result ==
"b=1, damn it.");
3320 CHECK(sbuf ==
"and c=2 seems about right");
3321 std::vector<char> vbuf;
3323 CHECK(sbuf ==
"and c=2 seems about right");
3326 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
3333 int a = 0, b = 1, c = 2;
3335 CHECK(result ==
"0 and 1 and 2");
3336 int aa = -1, bb = -2, cc = -3;
3337 size_t num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
3345 CHECK(result ==
"10 and 20 and 30");
3346 num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
3356 char buf_[256] = {};
3358 size_t size =
ryml::cat(buf,
"a=", 0.1,
"foo", 10, 11,
"bar", 12);
3359 CHECK(size == strlen(
"a=0.1foo1011bar12"));
3360 CHECK(buf.
first(size) ==
"a=0.1foo1011bar12");
3365 char smallbuf[8] = {};
3366 size =
ryml::cat(smallbuf,
"this",
" is too large ",
"for the buffer");
3367 CHECK(size == strlen(
"this is too large for the buffer"));
3373 CHECK(result ==
"b=1, damn it.");
3391 ryml::catrs(&sbuf,
"and c=", 2,
" seems about right");
3392 CHECK(sbuf ==
"and c=2 seems about right");
3393 std::vector<char> vbuf;
3394 ryml::catrs(&vbuf,
"and c=", 2,
" seems about right");
3395 CHECK(sbuf ==
"and c=2 seems about right");
3398 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
3405 int a = 0, b = 1, c = 2;
3407 CHECK(result ==
"0 1 2");
3408 int aa = -1, bb = -2, cc = -3;
3409 char sep1 =
'a', sep2 =
'b';
3410 size_t num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
3419 CHECK(result ==
"10 20 30");
3420 num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
3431 char buf_[256] = {};
3434 size_t size =
ryml::catsep(buf,
' ',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
3435 CHECK(buf.
first(size) ==
"a= 0 b= 1 c= 2 45 67");
3438 size =
ryml::catsep(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
3439 CHECK(buf.
first(size) ==
"a=0 and b=1 and c=2 and 45 and 67");
3441 size =
ryml::catsep(buf,
" ... ",
"a=0",
"b=1",
"c=2", 45, 67);
3442 CHECK(buf.
first(size) ==
"a=0 ... b=1 ... c=2 ... 45 ... 67");
3444 size =
ryml::catsep(buf,
'/',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
3445 CHECK(buf.
first(size) ==
"a=/0/b=/1/c=/2/45/67");
3447 size =
ryml::catsep(buf, 888,
"a=0",
"b=1",
"c=2", 45, 67);
3448 CHECK(buf.
first(size) ==
"a=0888b=1888c=28884588867");
3454 char smallbuf[8] = {};
3456 CHECK(size == strlen(
"a=0888b=1888c=28884588867"));
3462 CHECK(result ==
"a=0 and b=1 and c=2 and 45 and 67");
3481 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67");
3482 std::vector<char> vbuf;
3488 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");
3493 char buf_[256] = {};
3495 int a = 0, b = 1, c = 2;
3497 CHECK(result ==
"0 1 2");
3498 int aa = -1, bb = -2, cc = -3;
3506 CHECK(result ==
"10--20--30");
3516 using namespace ryml;
3517 char buf_[256] = {};
3536 CHECK(
"3735928559" ==
cat_sub(buf, UINT32_C(0xdeadbeef)));
3660 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wcast-align")
3661 const uint32_t payload[] = {10, 20, 30, 40, UINT32_C(0xdeadbeef)};
3663 csubstr expected =
csubstr((
const char *)payload,
sizeof(payload));
3668 for(
const uint32_t value : payload)
3671 expected =
csubstr((
const char *)&value,
sizeof(value));
3673 CHECK(actual.
size() ==
sizeof(uint32_t));
3678 CHECK(actual.
size() ==
sizeof(uint32_t));
3683 uint32_t result = 0;
3688 CHECK(result == value);
3690 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3710 text_and_base64 cases[] = {
3711 {{
"Hello, World!"}, {
"SGVsbG8sIFdvcmxkIQ=="}},
3712 {{
"Brevity is the soul of wit."}, {
"QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu"}},
3713 {{
"All that glitters is not gold."}, {
"QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu"}},
3716 for(text_and_base64 c : cases)
3719 for(text_and_base64 c : cases)
3726 for(text_and_base64 c : cases)
3728 CHECK(tree[c.text].
val() == c.base64);
3729 CHECK(tree[c.base64].
val() == c.text);
3733 "Hello, World!: SGVsbG8sIFdvcmxkIQ==" "\n"
3734 "Brevity is the soul of wit.: QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu" "\n"
3735 "All that glitters is not gold.: QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu" "\n"
3737 "SGVsbG8sIFdvcmxkIQ==: Hello, World!" "\n"
3738 "QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu: Brevity is the soul of wit." "\n"
3739 "QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu: All that glitters is not gold." "\n"
3741 char buf1_[128], buf2_[128];
3745 for(
const text_and_base64 c : cases)
3750 tree[c.text].
load(ryml::fmt::base64(buf1, &len));
3759 CHECK(c.text.len == len);
3762 tree[c.base64].
load_key(ryml::fmt::base64(buf2, &len));
3768 tree[c.text].
load(ryml::fmt::base64(result));
3769 CHECK(result == c.text);
3771 tree[c.base64].
load_key(ryml::fmt::base64(result));
3772 CHECK(result == c.text);
3783 if(len > result.size())
3792 CHECK(result == c.text);
3801 union { uint32_t u;
char c[
sizeof(uint32_t)]; } endianess_test = {1};
3802 const bool is_little_endian = endianess_test.c[0] == 1;
3804 return is_little_endian ? little_endian : big_endian;
3809 const uint64_t valin = UINT64_C(0xdeadbeef);
3812 CHECK(node.
val() == endian_select(
"776t3gAAAAA=",
"AAAAAN6tvu8="));
3813 uint64_t valout = 0;
3815 node.
load(ryml::fmt::base64(valout, &len));
3816 CHECK(len ==
sizeof(valout));
3817 CHECK(valout == UINT64_C(0xdeadbeef));
3820 node.
load(ryml::fmt::base64(valout));
3821 CHECK(valout == UINT64_C(0xdeadbeef));
3825 const double valin = 123456.7891011;
3828 CHECK(node.
val() == endian_select(
"nHkooAwk/kA=",
"QP4kDKAoeZw="));
3831 node.
load(ryml::fmt::base64(valout, &len));
3832 CHECK(len ==
sizeof(valout));
3833 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3836 node.
load(ryml::fmt::base64(valout));
3837 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3841 const uint32_t data_in[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xdeadbeef};
3842 uint32_t data_out[11] = {};
3846 endian_select(
"AAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAO++rd4=",
3847 "AAAAAAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACd6tvu8="));
3848 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) != 0);
3850 node.
load(ryml::fmt::base64(data_out, C4_COUNTOF(data_in), &len));
3851 CHECK(len ==
sizeof(data_out));
3852 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3855 memset(data_out, 0,
sizeof(data_out));
3856 node.
load(ryml::fmt::base64(data_out));
3857 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3879 {
int val = 1; tree[0].
load(&val);
CHECK(val == 0); }
3880 {
unsigned val = 0; tree[1].
load(&val);
CHECK(val == 10); }
3882 {
unsigned key = 0; tree[1].
load_key(&key);
CHECK(key == 10); }
3884 {
int val = 1; tree.
load(tree[0].
id(), &val);
CHECK(val == 0); }
3885 {
unsigned val = 0; tree.
load(tree[1].
id(), &val);
CHECK(val == 10); }
3886 {
int key = 1; tree.
load_key(tree[0].
id(), &key);
CHECK(key == 0); }
3887 {
unsigned key = 0; tree.
load_key(tree[1].
id(), &key);
CHECK(key == 10); }
3892 {
int val = 1;
CHECK(tree[0].deserialize(&val));
CHECK(val == 0); }
3893 {
unsigned val = 0;
CHECK(tree[1].deserialize(&val));
CHECK(val == 10); }
3894 {
int key = 1;
CHECK(tree[0].deserialize_key(&key));
CHECK(key == 0); }
3895 {
unsigned key = 0;
CHECK(tree[1].deserialize_key(&key));
CHECK(key == 10); }
3906 {
int val = 10; tree[0].
save(val);
CHECK(tree[0].val() ==
"10"); }
3907 {
unsigned val = 11; tree[1].
save(val);
CHECK(tree[1].val() ==
"11"); }
3908 {
int key = 12; tree[0].
save_key(key);
CHECK(tree[0].key() ==
"12"); }
3909 {
unsigned key = 13; tree[1].
save_key(key);
CHECK(tree[1].key() ==
"13"); }
3911 {
int val = 20; tree.
save(tree[0].
id(), val);
CHECK(tree[0].val() ==
"20"); }
3912 {
unsigned val = 21; tree.
save(tree[1].
id(), val);
CHECK(tree[1].val() ==
"21"); }
3913 {
int key = 22; tree.
save_key(tree[0].
id(), key);
CHECK(tree[0].key() ==
"22"); }
3914 {
unsigned key = 23; tree.
save_key(tree[1].
id(), key);
CHECK(tree[1].key() ==
"23"); }
3928 {
unsigned val = 19; tree.
set_serialized(tree[1].
id(), val);
CHECK(tree[1].val() ==
"19"); }
3936 tree[0].
set_val_tag(tree[0].to_arena(42));
CHECK(tree[0].val_tag() ==
"42");
3937 tree[1].
set_key_tag(tree[1].to_arena(43));
CHECK(tree[1].key_tag() ==
"43");
4026 r[
"v2"].load(&v2out);
4032 r[
"v3"].load(&v3out);
4039 r[
"v4"].load(&v4out);
4046 "v3: (100,101,102)" "\n"
4047 "v4: (1000,1001,1002,1003)" "\n"
4055 r[
"v2"].save(eov2in);
4056 r[
"v2"].load(&pov2out);
4061 r[
"v3"].save(eov3in);
4062 r[
"v3"].load(&pov3out);
4068 r[
"v4"].save(eov4in);
4069 r[
"v4"].load(&pov4out);
4075 "v3: (30,31,32)" "\n"
4076 "v4: (40,41,42,43)" "\n"
4103 for(
size_t i = 0; i <
seq_member.size(); ++i)
4108template<
class K,
class V>
4122 CHECK(it->second == itthat.second);
4189template<
class K,
class V>
4251template<
class K,
class V>
4346 {{101, 102, 103, 104, 105, 106, 107}},
4347 {{{1001, 2001}, {1002, 2002}, {1003, 2003}}},
4351 root_node.
save(orig);
4355 "v3: (30,31,32)" "\n"
4356 "v4: (40,41,42,43)" "\n"
4374 root_node.
load(&roundtrip);
4381 tree.
load(root_id, &roundtrip);
4390 "a deer, a female deer",
4392 "a drop of golden sun"
4395 tree[
"not in arena"].
save(strseq);
4399 "not in arena:" "\n"
4401 " - a deer, a female deer" "\n"
4403 " - a drop of golden sun" "\n"
4411 CHECK(child.val() == str_orig);
4413 CHECK(child.val().is_sub(str_orig));
4440 "v3: (30,31,32)" "\n"
4441 "v4: (40,41,42,43)" "\n"
4452 " 1002: not an int" "\n"
4482 std::string yml_std_string =
""
4483 "- v2: (20,21)" "\n"
4484 " v3: (30,31,32)" "\n"
4485 " v4: (40,41,42,43)" "\n"
4498 "- v2: (120,121)" "\n"
4499 " v3: (130,131,132)" "\n"
4500 " v4: (140,141,142,143)" "\n"
4510 " 11001: 12001" "\n"
4511 " 11002: 12002" "\n"
4512 " 11003: 12003" "\n"
4513 "- v2: (220,221)" "\n"
4514 " v3: (230,231,232)" "\n"
4515 " v4: (240,241,242,243)" "\n"
4525 " 21001: 22001" "\n"
4526 " 21002: 22002" "\n"
4527 " 21003: 22003" "\n"
4533 std::vector<my_type> vec;
4535 CHECK(vec.size() == 3);
4547 std::vector<double> reference{1.23234412342131234, 2.12323123143434237, 3.67847983572591234};
4551 const double precision_safe = 1.e-14;
4552 const size_t num_digits_safe = 14;
4553 const size_t num_digits_original = 17;
4554 auto get_num_digits = [](
ryml::csubstr number){
return number.len - 2u; };
4560 std::vector<double> output;
4562 CHECK(output.size() == reference.size());
4563 for(
size_t i = 0; i < reference.size(); ++i)
4566 CHECK(fabs(output[i] - reference[i]) < precision_safe);
4577 #if (!C4CORE_HAVE_STD_TOCHARS)
4582 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4583 C4_UNUSED(num_digits_safe);
4587 "- 1.2323441234213124" "\n"
4588 "- 2.1232312314343424" "\n"
4589 "- 3.6784798357259123" "\n"
4590 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4594 CHECK(get_num_digits(child.val()) >= num_digits_safe);
4597 CHECK(fabs(out - reference[pos++]) < precision_safe);
4628 auto check_precision = [&](
ryml::Tree const& serialized){
4629 std::cout << serialized;
4632 "- 1.23234412342131239" "\n"
4633 "- 2.12323123143434245" "\n"
4634 "- 3.67847983572591231" "\n"
4635 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4639 CHECK(get_num_digits(child.val()) == num_digits_original);
4642 CHECK(fabs(out - reference[pos++]) < precision_safe);
4651 for(
const double v : reference)
4653 check_precision(serialized);
4662 for(
const double v : reference)
4667 (void)snprintf(tmp,
sizeof(tmp),
"%.18g", v);
4673 check_precision(serialized);
4692 "- champagne: Dom Perignon" "\n"
4693 " coffee: Arabica" "\n"
4695 " vinho verde: Soalheiro" "\n"
4696 " vinho tinto: Redoma 2017" "\n"
4698 " - Rochefort 10" "\n"
4700 " - Leffe Rituel" "\n"
4719 size_t num_needed_chars = output.
len;
4720 std::vector<char> buf(num_needed_chars);
4723 CHECK(output == ymla);
4731 num_needed_chars = output.
len;
4732 buf.resize(num_needed_chars);
4735 CHECK(output == ymlb);
4740 CHECK(output == ymlb);
4751 " vinho verde: Soalheiro" "\n"
4752 " vinho tinto: Redoma 2017" "\n"
4765 size_t num_needed_chars = output.
len;
4767 buf.resize(num_needed_chars);
4770 CHECK(output == ymla);
4778 num_needed_chars = output.
len;
4779 buf.resize(num_needed_chars);
4782 CHECK(output == ymlb);
4787 CHECK(output == ymlb);
4798 " vinho verde: Soalheiro" "\n"
4799 " vinho tinto: Redoma 2017" "\n"
4815 "- champagne: Dom Perignon" "\n"
4816 " coffee: Arabica" "\n"
4818 " vinho verde: Soalheiro" "\n"
4819 " vinho tinto: Redoma 2017" "\n"
4821 " - Rochefort 10" "\n"
4823 " - Leffe Rituel" "\n"
4835 std::stringstream ss;
4843 std::stringstream ss;
4855 " \"champagne\": \"Dom Perignon\"," "\n"
4856 " \"coffee\": \"Arabica\"," "\n"
4858 " \"vinho verde\": \"Soalheiro\"," "\n"
4859 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4862 " \"Rochefort 10\"," "\n"
4864 " \"Leffe Rituel\"" "\n"
4877 std::stringstream ss;
4882 " vinho verde: Soalheiro" "\n"
4883 " vinho tinto: Redoma 2017" "\n"
4889 std::stringstream ss;
4894 " \"vinho verde\": \"Soalheiro\"," "\n"
4895 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4912 "- champagne: Dom Perignon" "\n"
4913 " coffee: Arabica" "\n"
4915 " vinho verde: Soalheiro" "\n"
4916 " vinho tinto: Redoma 2017" "\n"
4918 " - Rochefort 10" "\n"
4920 " - Leffe Rituel" "\n"
4943 "- champagne: Dom Perignon" "\n"
4944 " coffee: Arabica" "\n"
4946 " vinho verde: Soalheiro" "\n"
4947 " vinho tinto: Redoma 2017" "\n"
4949 " - Rochefort 10" "\n"
4951 " - Leffe Rituel" "\n"
4953 " - many other" "\n"
4954 " - wonderful beers" "\n"
4964 " - Rochefort 10" "\n"
4966 " - Leffe Rituel" "\n"
4968 " - many other" "\n"
4969 " - wonderful beers" "\n"
4976 "- Rochefort 10" "\n"
4978 "- Leffe Rituel" "\n"
4980 " - many other" "\n"
4981 " - wonderful beers" "\n"
4988 "- wonderful beers" "\n"
4994 " - many other" "\n"
4995 " - wonderful beers" "\n"
5029 " block key: block val" "\n"
5031 " - block val 1" "\n"
5032 " - block val 2" "\n"
5034 "flow map, singleline: {flow key: flow val}" "\n"
5035 "flow seq, singleline: [flow val,flow val]" "\n"
5036 "flow map, multiline: {" "\n"
5037 " flow key: flow val" "\n"
5039 "flow seq, multiline: [" "\n"
5047 CHECK(tree[
"block map"].is_key_plain());
5048 CHECK(tree[
"block seq"].is_key_plain());
5049 CHECK(tree[
"flow map, singleline"].is_key_plain());
5050 CHECK(tree[
"flow seq, singleline"].is_key_plain());
5051 CHECK(tree[
"flow map, multiline"].is_key_plain());
5052 CHECK(tree[
"flow seq, multiline"].is_key_plain());
5053 CHECK(tree[
"block map"].is_block());
5054 CHECK(tree[
"block seq"].is_block());
5056 CHECK(tree[
"flow map, singleline"].is_flow_sl());
5057 CHECK(tree[
"flow seq, singleline"].is_flow_sl());
5058 CHECK(tree[
"flow map, multiline"].is_flow_ml1());
5059 CHECK(tree[
"flow seq, multiline"].is_flow_ml1());
5061 CHECK(tree[
"flow map, singleline"].is_flow());
5062 CHECK(tree[
"flow seq, singleline"].is_flow());
5063 CHECK(tree[
"flow map, multiline"].is_flow());
5064 CHECK(tree[
"flow seq, multiline"].is_flow());
5070 CHECK(tostr(tree) == yaml);
5081 " block key: block val\n"
5088 "'block map': {block key: block val}\n"
5094 CHECK(tostr(n) ==
""
5103 CHECK(tostr(n) ==
""
5104 "\"block seq\": [\n"
5105 " block val 1,block val 2,quoted\n"
5108 CHECK(tostr(n) ==
""
5109 "\"block seq\": [\n"
5110 " block val 1, block val 2, quoted\n"
5113 CHECK(tostr_opts(n, maxcols20) ==
""
5114 "\"block seq\": [\n"
5115 " block val 1, block val 2,\n"
5119 CHECK(tostr_opts(n, maxcols20) ==
""
5120 "\"block seq\": [\n"
5121 " block val 1,block val 2,\n"
5125 CHECK(tostr(n) ==
""
5126 "\"block seq\": [block val 1,block val 2,quoted]\n");
5128 CHECK(tostr(n) ==
""
5129 "\"block seq\": [block val 1, block val 2, quoted]\n");
5131 CHECK(tostr(n) ==
""
5132 "\"block seq\": [\n"
5143 CHECK(tostr(n) ==
"flow map, singleline: {flow key: flow val}\n");
5146 CHECK(tostr(n) ==
""
5147 "flow map, singleline:\n"
5155 CHECK(tostr(n) ==
""
5156 "flow map, multiline: {\n"
5157 " flow key: flow val\n"
5161 CHECK(tostr(n) ==
""
5162 "flow map, multiline:\n"
5163 " flow key: flow val\n"
5169 CHECK(tostr(n) ==
"flow seq, singleline: [flow val,flow val]\n");
5174 CHECK(tostr(n) ==
""
5176 " flow seq, singleline\n"
5185 CHECK(tostr(n) ==
""
5186 "flow seq, multiline: [\n"
5192 CHECK(tostr(n) ==
"flow seq, multiline: [flow val,flow val]\n");
5195 CHECK(tostr(tree) != yaml);
5196 CHECK(tostr(tree) ==
5197 "'block map': {block key: block val}" "\n"
5198 "\"block seq\": [" "\n"
5199 " block val 1," "\n"
5200 " block val 2," "\n"
5203 "flow map, singleline:" "\n"
5204 " flow key: |-" "\n"
5207 " flow seq, singleline" "\n"
5209 " - 'flow val'" "\n"
5210 " - \"flow val\"" "\n"
5211 "flow map, multiline:" "\n"
5212 " flow key: flow val" "\n"
5213 "flow seq, multiline: [flow val,flow val]" "\n"
5218 CHECK(tostr(tree) ==
5220 " block key: block val" "\n"
5222 " - block val 1" "\n"
5223 " - block val 2" "\n"
5225 "flow map, singleline:" "\n"
5226 " flow key: |-" "\n"
5229 " flow seq, singleline" "\n"
5231 " - 'flow val'" "\n"
5232 " - \"flow val\"" "\n"
5233 "flow map, multiline:" "\n"
5234 " flow key: flow val" "\n"
5235 "flow seq, multiline: [flow val,flow val]" "\n"
5244 CHECK(tostr(tree) ==
5246 " block key: block val" "\n"
5248 " - block val 1" "\n"
5249 " - block val 2" "\n"
5251 "flow map, singleline:" "\n"
5252 " flow key: flow val" "\n"
5253 "flow seq, singleline:" "\n"
5256 "flow map, multiline:" "\n"
5257 " flow key: flow val" "\n"
5258 "flow seq, multiline:" "\n"
5269 CHECK(tostr(tree) ==
5271 " block key: block val" "\n"
5273 " - block val 1" "\n"
5274 " - block val 2" "\n"
5276 "flow map, singleline:" "\n"
5277 " flow key: flow val" "\n"
5278 "flow seq, singleline:" "\n"
5281 "flow map, multiline:" "\n"
5282 " flow key: flow val" "\n"
5283 "flow seq, multiline:" "\n"
5308 CHECK(tostr(tree) ==
""
5310 " 'block key': \"block val\"" "\n"
5311 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
5312 "'flow map, singleline':" "\n"
5313 " 'flow key': \"flow val\"" "\n"
5314 "'flow seq, singleline': [\"flow val\",\"flow val\"]" "\n"
5315 "'flow map, multiline':" "\n"
5316 " 'flow key': \"flow val\"" "\n"
5317 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
5324 CHECK(tostr(tree) ==
""
5326 " 'block key': \"block val\"" "\n"
5327 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
5328 "'flow map, singleline':" "\n"
5329 " 'flow key': \"flow val\"" "\n"
5330 "'flow seq, singleline':" "\n"
5331 " - \"flow val\"" "\n"
5332 " - \"flow val\"" "\n"
5333 "'flow map, multiline':" "\n"
5334 " 'flow key': \"flow val\"" "\n"
5335 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
5378 CHECK(tree[
"map"].is_flow_ml1());
5379 CHECK(tree[
"map"][
"seq"].is_flow_ml1());
5380 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
5382 CHECK(tostr(tree, emit_defaults) == yaml);
5384 CHECK(tostr_json(tree, emit_defaults) ==
5405 CHECK(tree[
"map"].is_flow_sl());
5407 CHECK(tostr(tree, emit_defaults) ==
5408 "{map: {seq: [0,1,2,3,[40,41]]}}");
5410 CHECK(tostr_json(tree, emit_defaults) ==
5411 "{\"map\": {\"seq\": [0,1,2,3,[40,41]]}}");
5416 CHECK(tostr(tree, with_spaces) ==
5417 "{map: {seq: [0, 1, 2, 3, [40, 41]]}}");
5419 CHECK(tostr_json(tree, with_spaces) ==
5420 "{\"map\": {\"seq\": [0, 1, 2, 3, [40, 41]]}}");
5429 CHECK(tree[
"map"].is_flow_mln());
5430 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
5431 CHECK(tostr(tree, emit_defaults) ==
5435 " 0,1,2,3,[40,41]" "\n"
5439 CHECK(tostr_json(tree, emit_defaults) ==
5443 " 0,1,2,3,[40,41]" "\n"
5450 CHECK(tostr(tree, with_spaces) ==
5454 " 0, 1, 2, 3, [40, 41]" "\n"
5458 CHECK(tostr_json(tree, with_spaces) ==
5462 " 0, 1, 2, 3, [40, 41]" "\n"
5473 CHECK(tree[
"map"].is_flow_ml1());
5474 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
5475 CHECK(tostr(tree, noindent) ==
""
5488 CHECK(tostr_json(tree, noindent) ==
""
5507 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9," "\n"
5508 " 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, " "\n"
5509 " 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, " "\n"
5510 " 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, " "\n"
5511 " 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, " "\n"
5512 " 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, " "\n"
5513 " 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, " "\n"
5514 " 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 " "\n"
5525 CHECK(tostr(tree, emit_defaults) ==
""
5527 " 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"
5528 " 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"
5529 " 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"
5532 CHECK(tostr_json(tree, emit_defaults) ==
""
5534 " 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"
5535 " 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"
5536 " 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"
5542 CHECK(tostr(tree, maxcols40) ==
""
5544 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
5545 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
5546 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
5547 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
5548 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
5549 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
5552 CHECK(tostr_json(tree, maxcols40) ==
""
5554 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
5555 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
5556 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
5557 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
5558 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
5559 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
5566 CHECK(tostr(tree, with_spaces) ==
""
5568 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5569 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5570 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5571 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
5574 CHECK(tostr_json(tree, with_spaces) ==
""
5576 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5577 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5578 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5579 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
5586 CHECK(tostr(tree, maxcols40_spc) ==
""
5588 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
5589 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5590 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
5591 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5592 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
5593 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5594 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
5595 " 72, 73, 74, 75, 76, 77, 78, 79\n"
5598 CHECK(tostr_json(tree, maxcols40_spc) ==
""
5600 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
5601 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5602 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
5603 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5604 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
5605 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5606 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
5607 " 72, 73, 74, 75, 76, 77, 78, 79\n"
5615 CHECK(tostr(tree, maxcols40_spc_noindent) ==
""
5617 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
5618 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
5619 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
5620 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
5621 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
5622 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
5623 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
5624 "73, 74, 75, 76, 77, 78, 79\n"
5627 CHECK(tostr_json(tree, maxcols40_spc_noindent) ==
""
5629 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
5630 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
5631 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
5632 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
5633 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
5634 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
5635 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
5636 "73, 74, 75, 76, 77, 78, 79\n"
5655 ryml::csubstr yaml =
"{map: {seq: [0, 1, 2, 3, [40, 41]]}}";
5659 CHECK(tostr(tree, defaults) ==
"{map: {seq: [0,1,2,3,[40,41]]}}");
5666 CHECK(tostr(tree, defaults) ==
5684 CHECK(tostr(tree, noindent) ==
5703 CHECK(tostr(tree, noindent) ==
""
5719 CHECK(tostr(tree, noindent) ==
5745 " \"doe\": \"a deer, a female deer\"," "\n"
5746 " \"ray\": \"a drop of golden sun\"," "\n"
5747 " \"me\": \"a name, I call myself\"," "\n"
5748 " \"far\": \"a long long way to go\"" "\n"
5762 std::stringstream ss;
5764 CHECK(ss.str() == json);
5789 "\"doe\": \"a deer, a female deer\"" "\n"
5790 "\"ray\": \"a drop of golden sun\"" "\n"
5791 "\"me\": \"a name, I call myself\"" "\n"
5792 "\"far\": \"a long long way to go\"" "\n"
5799 "doe: a deer, a female deer" "\n"
5800 "ray: a drop of golden sun" "\n"
5801 "me: a name, I call myself" "\n"
5802 "far: a long long way to go" "\n"
5832 std::string unresolved =
""
5834 " name: Everyone has same name" "\n"
5841 "bill_to: &id001" "\n"
5843 " 123 Tornado Alley" "\n"
5845 " city: East Centerville" "\n"
5847 "ship_to: *id001" "\n"
5848 "&keyref key: &valref val" "\n"
5849 "*valref : *keyref" "\n"
5851 std::string resolved =
""
5853 " name: Everyone has same name" "\n"
5855 " name: Everyone has same name" "\n"
5858 " name: Everyone has same name" "\n"
5862 " 123 Tornado Alley" "\n"
5864 " city: East Centerville" "\n"
5868 " 123 Tornado Alley" "\n"
5870 " city: East Centerville" "\n"
5878 CHECK( ! tree[
"base"].has_key_anchor());
5879 CHECK( tree[
"base"].has_val_anchor());
5880 CHECK( tree[
"base"].val_anchor() ==
"base");
5881 CHECK( tree[
"key"].key_anchor() ==
"keyref");
5882 CHECK( tree[
"key"].val_anchor() ==
"valref");
5883 CHECK( tree[
"*valref"].is_key_ref());
5884 CHECK( tree[
"*valref"].is_val_ref());
5885 CHECK( tree[
"*valref"].key_ref() ==
"valref");
5886 CHECK( tree[
"*valref"].val_ref() ==
"keyref");
5893 CHECK( ! tree[
"base"].has_key_anchor());
5894 CHECK( ! tree[
"base"].has_val_anchor());
5895 CHECK( ! tree[
"base"].has_val_anchor());
5896 CHECK( ! tree[
"key"].has_key_anchor());
5897 CHECK( ! tree[
"key"].has_val_anchor());
5898 CHECK( ! tree[
"val"].is_key_ref());
5899 CHECK( ! tree[
"val"].is_val_ref());
5901 CHECK(tree[
"ship_to"][
"city"].val() ==
"East Centerville");
5902 CHECK(tree[
"ship_to"][
"state"].val() ==
"KS");
5920 t[
"nref"].
set_val(
"*vanchor");
5922 "&kanchor kanchor: 2" "\n"
5923 "vanchor: &vanchor 3" "\n"
5924 "kref: *kanchor" "\n"
5925 "vref: *vanchor" "\n"
5928 "nref: '*vanchor'" "\n"
5934 "kref: kanchor" "\n"
5937 "nref: '*vanchor'" "\n"
5944 "orig: &orig {foo: bar, baz: bat}" "\n"
5952 t[
"notref"][
"<<"].
set_val(
"*orig");
5954 "orig: &orig {foo: bar,baz: bat}" "\n"
5955 "copy: {<<: *orig}" "\n"
5956 "notcopy: {test: *orig,<<: *orig}" "\n"
5957 "notref: {<<: '*orig'}" "\n"
5961 "orig: {foo: bar,baz: bat}" "\n"
5962 "copy: {foo: bar,baz: bat}" "\n"
5963 "notcopy: {test: {foo: bar,baz: bat},foo: bar,baz: bat}" "\n"
5964 "notref: {<<: '*orig'}" "\n"
5971 "orig1: &orig1 {foo: bar}" "\n"
5972 "orig2: &orig2 {baz: bat}" "\n"
5973 "orig3: &orig3 {and: more}" "\n"
5982 "orig1: &orig1 {foo: bar}" "\n"
5983 "orig2: &orig2 {baz: bat}" "\n"
5984 "orig3: &orig3 {and: more}" "\n"
5985 "copy: {<<: [*orig1,*orig2,*orig3]}" "\n"
5989 "orig1: {foo: bar}" "\n"
5990 "orig2: {baz: bat}" "\n"
5991 "orig3: {and: more}" "\n"
5992 "copy: {foo: bar,baz: bat,and: more}" "\n");
6001 const std::string yaml =
""
6010 "--- !!str a b" "\n"
6011 "--- !!str 'a: b'" "\n"
6028 CHECK(doc.is_doc());
6030 CHECK(root[0].has_val_tag());
6031 CHECK(root[0].val_tag() ==
"!!map");
6032 CHECK(root[1].val_tag() ==
"!map");
6033 CHECK(root[2].val_tag() ==
"!!seq");
6034 CHECK(root[3].val_tag() ==
"!!str");
6035 CHECK(root[4].val_tag() ==
"!!str");
6036 CHECK(root[5][
"a"].has_key_tag());
6037 CHECK(root[5][
"a"].key_tag() ==
"!!str");
6038 CHECK(root[6].val_tag() ==
"!!set");
6039 CHECK(root[7].val_tag() ==
"!!set");
6040 CHECK(root[8].val_tag() ==
"!!seq");
6041 CHECK(root[8][0].val_tag() ==
"!!int");
6042 CHECK(root[8][1].val_tag() ==
"!!str");
6100 "--- !!str a b" "\n"
6101 "--- !!str 'a: b'" "\n"
6116 "--- !<tag:yaml.org,2002:map>" "\n"
6121 "--- !<tag:yaml.org,2002:seq>" "\n"
6124 "--- !<tag:yaml.org,2002:str> a b" "\n"
6125 "--- !<tag:yaml.org,2002:str> 'a: b'" "\n"
6127 "!<tag:yaml.org,2002:str> a: b" "\n"
6128 "--- !<tag:yaml.org,2002:set>" "\n"
6131 "--- !<tag:yaml.org,2002:set>" "\n"
6133 "--- !<tag:yaml.org,2002:seq>" "\n"
6134 "- !<tag:yaml.org,2002:int> 0" "\n"
6135 "- !<tag:yaml.org,2002:str> 1" "\n"
6144 const std::string yaml =
""
6145 "%TAG !m! !my-" "\n"
6146 "--- # Bulb here" "\n"
6147 "!m!light fluorescent" "\n"
6149 "%TAG !m! !meta-" "\n"
6150 "--- # Color here" "\n"
6151 "!m!light green" "\n"
6156 "%TAG !m! !my-" "\n"
6157 "--- !m!light fluorescent" "\n"
6159 "%TAG !m! !meta-" "\n"
6160 "--- !m!light green" "\n"
6167 "%TAG !m! !my-" "\n"
6168 "--- !<!my-light> fluorescent" "\n"
6170 "%TAG !m! !meta-" "\n"
6171 "--- !<!meta-light> green" "\n"
6178 "%TAG !m! !my-" "\n"
6179 "--- !<!my-light> fluorescent" "\n"
6181 "%TAG !m! !meta-" "\n"
6182 "--- !<!meta-light> green" "\n"
6218 CHECK(doc.is_doc());
6237 CHECK(stream[0].is_doc());
6238 CHECK(stream[0].is_map());
6239 CHECK(stream[0][
"a"].val() ==
"0");
6240 CHECK(stream[0][
"b"].val() ==
"1");
6249 CHECK(stream[1].is_doc());
6250 CHECK(stream[1].is_map());
6251 CHECK(stream[1][
"c"].val() ==
"2");
6252 CHECK(stream[1][
"d"].val() ==
"3");
6261 CHECK(stream[2].is_doc());
6262 CHECK(stream[2].is_seq());
6263 CHECK(stream[2][0].val() ==
"4");
6264 CHECK(stream[2][1].val() ==
"5");
6265 CHECK(stream[2][2].val() ==
"6");
6266 CHECK(stream[2][3].val() ==
"7");
6304 return ryml::emitrs_json<std::string>(err_tree, err_opts);
6308 const std::string expected_json[] = {
6367 ryml::Tree tree = ryml::parse_in_arena(
"errorhandler.yml",
"[a: b\n}");
6378 auto cause_basic_error = []{
6387#ifdef RYML_WITH_EXCEPTIONS_
6391 cause_basic_error();
6413 auto cause_parse_error = [&]{
6437 msg_ctx.append(s.
str, s.
len);
6439 CHECK(
ryml::to_csubstr(msg_ctx).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
6441 "file.yml:3: col=4 (12B): err:" "\n"
6447 "err: see region:" "\n"
6482 CHECK(errh.
saved_msg_full ==
"file.yml:3: col=4 (12B): ERROR: [basic] invalid character: '['");
6495#ifdef RYML_WITH_EXCEPTIONS_
6499 cause_parse_error();
6511 CHECK(msg ==
"invalid character: '['");
6516 auto dumpfn = [&full](
ryml::csubstr s) { full.append(s.str, s.len); };
6520 CHECK(
ryml::to_csubstr(full).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
6522 "file.yml:3: col=4 (12B): err:" "\n"
6528 "err: see region:" "\n"
6541 cause_parse_error();
6567 tree[
"float"].load(&intval);
6596 tree[
"float"].load(&intval);
6608#ifdef RYML_WITH_EXCEPTIONS_
6620 tree[
"float"].
load(&intval);
6641 tree[
"float"].
load(&intval);
6678 "float: 123.456" "\n"
6682 auto cause_visit_error = [&]{
6684 tree[
"float"].
load(&intval);
6716 msg.append(s.
str, s.
len);
6717 }, ymlloc, ymlsrc,
"err", 3);
6719 "file.yml:3: col=0 (24B): err:" "\n"
6721 "err: float: 123.456" "\n"
6725 "err: see region:" "\n"
6727 "err: foo: bar" "\n"
6730 "err: float: 123.456" "\n"
6771 uintptr_t uptr = (uintptr_t)ptr;
6772 const uintptr_t align =
alignof(max_align_t);
6775 uintptr_t prev = uptr - (uptr % align);
6776 uintptr_t next = prev + align;
6777 uintptr_t corr = next - uptr;
6778 ptr = (
void*)(((
char*)ptr) + corr);
6782 "out of memory! requested=%zu+%zu available=%zu\n",
6808 static void s_free(
void *mem,
size_t len,
void *this_)
6880 parse_in_arena(&parser,
"", R
"([a, b, c, d, {foo: bar, money: pennys}])", &tree);
6923 std::cerr <<
"out of memory! requested=" <<
alloc_size <<
" vs " <<
memory_pool.size() <<
" available" << std::endl;
7009 CHECK(tree["doe"].val() ==
"a deer, a female deer");
7022static int num_checks = 0;
7023static int num_failed_checks = 0;
7024static bool quiet_mode =
false;
7029 auto arg_matches = [](
const char *arg,
const char *shortform,
const char *longform) {
7030 return (0 == strcmp(arg, shortform) || 0 == strcmp(arg, longform));
7032 for(
int i = 1; i < argc; ++i)
7033 if(arg_matches(argv[i],
"-q",
"--quiet"))
7040 const char *msg = predicate ?
"OK! " :
"OK!";
7043 ++num_failed_checks;
7044 msg = predicate ?
"FAIL: " :
"FAIL";
7046 if(!result || !quiet_mode)
7048 std::cout << __FILE__ <<
':' << line <<
": " << msg << (predicate ? predicate :
"") << std::endl;
7056 std::cout <<
"Completed " << num_checks <<
" checks." << std::endl;
7057 if(num_failed_checks)
7058 std::cout <<
"ERROR: " << num_failed_checks <<
'/' << num_checks <<
" checks failed." << std::endl;
7060 std::cout <<
"SUCCESS!" << std::endl;
7061 return num_failed_checks;
7076 fwrite(s.
str, 1, s.
len, stderr);
7082 fputc(
'\n', stderr);
7097 .set_free([](
void* mem,
size_t,
void *){
7135#ifdef RYML_NO_DEFAULT_CALLBACKS
7144#ifndef C4_EXCEPTIONS
7175 bool got_error =
false;
7176 #ifdef C4_EXCEPTIONS
7179 std::forward<Fn>(fn)();
7181 catch(std::exception
const&)
7188 std::forward<Fn>(fn)();
7201[[noreturn]]
void stopexec(std::string
const& s)
7203 #ifdef C4_EXCEPTIONS
7204 throw std::runtime_error(s);
7328C4_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_style_conditionally(NodeType type_mask, NodeType rem_style_flags, NodeType add_style_flags, bool recurse=false)
void set_serialized(T const &v)
serialize a variable to this node.
void clear_style(bool recurse=false)
children_view children() RYML_NOEXCEPT
get an iterable view over children
void set_val(csubstr val)
void set_key_serialized(T const &k)
serialize a variable, then assign the result to the node's key
void set_container_style(type_bits 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_key_style(type_bits style)
bool readable() const noexcept
true if the object is not invalid and not in seed state.
void set_val_style(type_bits style)
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.
Location val_location(const char *val) const
Given a pointer to a buffer position, get the location.
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 save(id_type node, T const &val)
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 set_serialized(id_type node, T const &val) RYML_NOEXCEPT
void set_key_serialized(id_type node, T const &key) RYML_NOEXCEPT
void reserve(id_type node_capacity=RYML_DEFAULT_TREE_CAPACITY)
void load(id_type node, T *v, bool check_readable=true) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
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 load_key(id_type node, T *k, bool check_readable=true) const
(1) deserialize the node's key (necessarily a scalar) to the given variable, forwarding to the user-o...
void set_seq(id_type node) RYML_NOEXCEPT
id_type append_child(id_type parent)
create and insert a node as the last child of parent
void clear_style(id_type node, bool recurse=false)
ReadResult deserialize(id_type node, T *v) const
(1) deserialize a node's contents to a variable
id_type next_sibling(id_type node) const
ConstNodeRef crootref() const
Get the root as a ConstNodeRef . Note that Tree implicitly converts to ConstNodeRef.
void save_key(id_type node, T const &key)
void set_key_tag(id_type node, csubstr tag)
void set_container_style(id_type node, type_bits style)
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
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
void set_map(id_type node) RYML_NOEXCEPT
ReadResult deserialize_key(id_type node, T *v) const
(1) deserialize a node's key to a variable
id_type find_child(id_type node, csubstr const &key) const
find child by name, or NONE if no child is found with this key like Tree::child(),...
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.
void set_key(id_type node, csubstr key) RYML_NOEXCEPT
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
find child by position, or NONE if there are less than pos children posi
void set_val_tag(id_type node, csubstr tag)
void set_key_anchor(id_type node, csubstr anchor)
ReadResult deserialize_child(id_type node, csubstr child_key, T *v) const
(1) find a child by name and deserialize its contents to the given variable (ie call ....
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.
const_base64_wrapper base64(csubstr s, size_t *reqsize=nullptr)
a tag function to mark a csubstr payload to be encoded in base64 format
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
@ 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_FOLDED
mark val scalar as multiline, block folded >
@ 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_per_tree_allocator()
set per-tree allocators
void sample_global_allocator()
set a global allocator for ryml
void sample_anchors_and_aliases()
deal with YAML anchors and aliases
void sample_anchors_and_aliases_create()
how to create YAML anchors and aliases
void sample_docs()
deal with YAML docs
void sample_emit_to_file()
emit to a FILE*
void sample_emit_nested_node()
pick a nested node as the root when emitting
void sample_emit_to_container()
emit to memory, eg a string or vector-like container
void sample_emit_to_stream()
emit to a stream, eg std::ostream
void sample_error_visit()
handler for visit errors, and obtain a full error message with visit context
void sample_error_parse()
handler for parse errors, and obtain a full error message with parse context
void sample_error_visit_location()
obtaining the YAML location from a visit error
void sample_error_basic()
handler for basic errors, and obtain a full error message with basic context
void sample_error_handler()
set custom error handlers
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)
used by CHECK()
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()
set up a bare-bones implementation of the callbacks
void check_disabled() const
test that this handler is currently not set
#define CHECK(predicate)
a testing assertion, used only in this quickstart
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[])
void sample_json()
JSON parsing and emitting.
void sample_quick_overview()
quick overview of most common features
void sample_lightning_overview()
lightning overview of most common features
void sample_parse_style()
shows how rapidyaml retains the style of parsed YAML
void sample_parse_file()
ready-to-go example of parsing a file from disk
void sample_parse_in_arena()
parse a read-only YAML source buffer
void sample_parse_reuse_parser()
reuse an existing parser
void sample_parse_reuse_tree_and_parser()
how to reuse existing trees and parsers
void sample_parse_in_place()
parse a mutable YAML source buffer
void sample_parse_reuse_tree()
parse into an existing tree, maybe into a node
void sample_formatting()
control formatting when serializing/deserializing
void sample_user_container_types()
serialize/deserialize container (map or seq) types
void sample_empty_null_values()
serialize/deserialize/query empty or null values
void sample_base64()
encode/decode base64
void sample_serialize_basic()
serialize/deserialize fundamental types
void sample_fundamental_types()
serialize/deserialize fundamental types
void sample_std_types()
serialize/deserialize STL containers
void sample_float_precision()
control precision of serialized floats
void sample_user_scalar_types()
serialize/deserialize scalar (leaf/scalar) types
void sample_deserialize_error()
shows error on deserializing nested nodes
void sample_static_trees()
how to use static trees in ryml
void sample_style_flow_ml_indent()
control indentation of FLOW_ML1 and FLOW_MLN containers
void sample_style()
query/set node styles
void sample_style_flow_formatting()
control formatting of flow containers
void sample_substr()
about ryml's string views (from c4core)
void sample_create_tree_style()
set node styles while creating trees
void sample_location_tracking()
track node YAML source locations in the parsed tree
void sample_create_tree()
programatically create trees
void sample_iterate_tree()
visit individual nodes and iterate through trees
void sample_tree_arena()
interact with the tree's serialization arena
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)
ryml::ReadResult read(ryml::Tree const *tree, ryml::id_type id, my_seq_type< T > *seq)
void write(ryml::Tree *tree, ryml::id_type id, my_seq_type< T > const &seq)
size_t to_chars(ryml::substr buf, vec2< T > v)
bool from_chars(ryml::csubstr buf, vec2< T > *v)
bool scalar_is_null(csubstr s) noexcept
YAML-sense query of nullity.
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 argc, const char *argv[])
an error handler used by 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 nested (non-root) node, emit the node's key as well.
EmitOptions & emit_nonroot_dash(bool enabled) noexcept
When emit starts on a nested (non-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...
A lightweight truthy type, used to enable reporting the offending node when a deserializing error hap...
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().
void load_key(T *k, bool check_readable=true) const
(1) deserialize the node's key (necessarily a scalar) to the given variable, forwarding to the user-o...
bool is_root() const RYML_NOEXCEPT
Forward to Tree::is_root().
bool is_key_plain() const RYML_NOEXCEPT
Forward to Tree::is_key_plain().
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().
ReadResult deserialize_child(csubstr child_key, T *v) const
(1) find a child by name and deserialize its contents to the given variable (ie call ....
bool is_doc() const RYML_NOEXCEPT
Forward to Tree::is_doc().
id_type num_children() const RYML_NOEXCEPT
O(num_children).
ReadResult deserialize(T *v) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
bool is_block() const RYML_NOEXCEPT
Forward to Tree::is_block().
Location location(Parser const &parser) const
bool is_val_plain() const RYML_NOEXCEPT
Forward to Tree::is_val_plain().
bool is_seq() const RYML_NOEXCEPT
Forward to Tree::is_seq().
void load(T *v, bool check_readable=true) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
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
void check_eq(my_map_type const &that) const
std::map< K, V > map_member
example user container type: seq-like
std::vector< T > seq_member
void check_eq(my_seq_type const &that) const
example user container type with nested user types.
void check_eq(my_type const &that) const
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