201#if defined(RYML_SINGLE_HEADER)
202 #define RYML_SINGLE_HDR_DEFINE_NOW
203 #include <ryml_all.hpp>
204#elif defined(RYML_SINGLE_HEADER_LIB)
205 #include <ryml_all.hpp>
240int main(
int argc,
const char* argv[])
305bool report_check(
int line,
const char *predicate,
bool result);
310# define CHECK(predicate) assert(predicate)
313# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC_MINOR__ > 8))))
314# define CHECK(predicate) report_check(__LINE__, #predicate, (predicate))
316# define CHECK CheckPredicate{__LINE__}
318 struct CheckPredicate
321 void operator() (
bool result)
const {
report_check(line,
nullptr, result); }
387C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
388C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wold-style-cast")
389C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wcast-qual")
390C4_SUPPRESS_WARNING_GCC(
"-Wuseless-cast")
391C4_SUPPRESS_WARNING_GCC(
"-Wuseless-cast")
392#if defined(__GNUC__) && (__GNUC__ >= 6)
393C4_SUPPRESS_WARNING_GCC(
"-Wnull-dereference")
395#if defined(__clang__) && (__clang_major__ >= 13)
396C4_SUPPRESS_WARNING_CLANG(
"-Wreserved-identifier")
412 char yml_buf[] =
"{foo: 1, bar: [2, 3], john: doe}";
417 CHECK(bar[0].val() ==
"2");
418 CHECK(bar[1].val() ==
"3");
419 CHECK(bar[0].val().str == yml_buf + 15);
420 CHECK(bar[1].val().str == yml_buf + 18);
423 int bar0 = 0, bar1 = 0;
432 CHECK(bar[0].val() ==
"10");
433 CHECK(bar[1].val() ==
"11");
438 CHECK(bar[2].val() ==
"12");
441 std::string expected =
"{foo: 1,bar: [10,11,12],john: doe,new: node}";
447 std::cout << tree <<
"\n";
451 expected =
"foo: 1\n";
536 CHECK(tree[
"foo"].is_keyval());
537 CHECK(tree[
"foo"].val() ==
"1");
538 CHECK(tree[
"foo"].key() ==
"foo");
539 CHECK(tree[
"bar"].is_seq());
540 CHECK(tree[
"bar"].has_key());
541 CHECK(tree[
"bar"].key() ==
"bar");
543 CHECK(tree[
"bar"][0].val() ==
"2");
544 CHECK(tree[
"bar"][1].val() ==
"3");
545 CHECK(tree[
"john"].val() ==
"doe");
549 CHECK(tree[0].
id() == tree[
"foo"].
id());
550 CHECK(tree[1].
id() == tree[
"bar"].
id());
551 CHECK(tree[2].
id() == tree[
"john"].
id());
553 CHECK(tree[0].
id() == tree[
"foo"].
id());
554 CHECK(tree[1].
id() == tree[
"bar"].
id());
555 CHECK(tree[2].
id() == tree[
"john"].
id());
557 CHECK(bar[0].val() ==
"2");
558 CHECK(bar[1].val() ==
"3");
563 CHECK(tree[
"foo"].key() ==
"foo");
564 CHECK(tree[
"bar"].key() ==
"bar");
565 CHECK(tree[
"john"].key() ==
"john");
570 CHECK(root[
"foo"].
id() == root[0].
id());
571 CHECK(root[
"bar"].
id() == root[1].
id());
572 CHECK(root[
"john"].
id() == root[2].
id());
631 CHECK(child.key() == expected_keys[count++]);
637 CHECK(child.key() == expected_keys[count++]);
643 CHECK(tree.
key(child_id) == expected_keys[count++]);
652 CHECK(tree.
key(child_id) == expected_keys[count++]);
727 int foo = 0, bar0 = 0, bar1 = 0;
728 root[
"foo"].
load(&foo);
729 root[
"bar"][0].
load(&bar0);
730 root[
"bar"][1].
load(&bar1);
738 int foo = 0, bar0 = 0, bar1 = 0;
739 CHECK(root[
"foo"].deserialize(&foo));
740 CHECK(root[
"bar"][0].deserialize(&bar0));
741 CHECK(root[
"bar"][1].deserialize(&bar1));
750 std::string john_str, bar_str;
751 root[
"john"].
load(&john_str);
753 CHECK(john_str ==
"doe");
754 CHECK(bar_str ==
"bar");
755 std::vector<int> bar_actual, bar_expected{{2, 3}};
756 root[
"bar"].
load(&bar_actual);
757 CHECK(bar_actual == bar_expected);
775 wroot[
"foo"].
set_val(
"says you");
782 CHECK(root[
"foo"].val() ==
"says you");
783 CHECK(root[
"bar"][0].val() ==
"-2");
784 CHECK(root[
"bar"][1].val() ==
"-3");
785 CHECK(root[
"john"].val() ==
"ron");
806 CHECK(root[
"foo"].val() ==
"says who");
807 CHECK(root[
"bar"][0].val() ==
"20");
808 CHECK(root[
"bar"][1].val() ==
"30");
809 CHECK(root[
"john"].val() ==
"deere");
813 std::string ok(
"in_scope");
817 CHECK(root[
"john"].val() ==
"in_scope");
823 CHECK(tree.
arena() ==
"says who2030deerein_scope2.42.400000");
831 wroot[
"newkeyval"].
set_val(
"shiny and new");
836 CHECK(root[
"newkeyval"].key() ==
"newkeyval");
837 CHECK(root[
"newkeyval"].val() ==
"shiny and new");
838 CHECK(root[
"newkeyval (serialized)"].key() ==
"newkeyval (serialized)");
839 CHECK(root[
"newkeyval (serialized)"].val() ==
"shiny and new (serialized)");
845 CHECK(root[
"bar"].num_children() == 2);
846 wroot[
"bar"][2].
set_val(
"oh so nice");
848 CHECK(root[
"bar"].num_children() == 4);
849 CHECK(root[
"bar"][2].val() ==
"oh so nice");
850 CHECK(root[
"bar"][3].val() ==
"oh so nice (serialized)");
858 CHECK(root[
"newseq"].num_children() == 0);
859 CHECK(root[
"newseq"].is_seq());
860 CHECK(root[
"newseq (serialized)"].num_children() == 0);
861 CHECK(root[
"newseq (serialized)"].is_seq());
869 CHECK(root[
"newmap"].num_children() == 0);
870 CHECK(root[
"newmap"].is_map());
871 CHECK(root[
"newmap (serialized)"].num_children() == 0);
872 CHECK(root[
"newmap (serialized)"].is_map());
905 nothing = wroot[
"I am nothing"];
922 CHECK(root[
"I am something"].val() ==
"indeed");
953 CHECK(wbar[0].readable() && wbar[0].val() ==
"20");
954 CHECK( ! wbar[100].readable());
955 CHECK( ! wbar[100].readable() || wbar[100].val() ==
"100");
957 CHECK( ! wbar[0].is_seed() && wbar[0].val() ==
"20");
958 CHECK(wbar[100].is_seed() || wbar[100].val() ==
"100");
987 return seed_node.at(
"is").at(
"an").at(
"invalid").at(
"operation");
994 return seed_node[
"is"][
"an"][
"invalid"][
"operation"];
1005 "foo: says who" "\n"
1006 "bar: [20,30,oh so nice,oh so nice (serialized)]" "\n"
1007 "john: in_scope" "\n"
1009 "digits: 2.400000" "\n"
1010 "newkeyval: shiny and new" "\n"
1011 "newkeyval (serialized): shiny and new (serialized)" "\n"
1013 "newseq (serialized): []" "\n"
1015 "newmap (serialized): {}" "\n"
1016 "I am something: indeed" "\n"
1025 std::stringstream ss;
1027 std::string stream_result = ss.str();
1034 CHECK(buf_result == expected_result);
1035 CHECK(str_result == expected_result);
1036 CHECK(stream_result == expected_result);
1052 CHECK(tree[
"bar"][0].val() ==
"21");
1054 CHECK(tree[
"bar"][0].val() ==
"22");
1060 constnoderef = noderef;
1066 noderef = tree[
"bar"][0];
1067 constnoderef = consttree[
"bar"][0];
1071 CHECK(constnoderef == noderef);
1072 CHECK(!(constnoderef != noderef));
1082 ryml::Tree tree2 = parse_in_arena(&parser,
"expected.yml", expected_result);
1098 "# UTF8/16/32 can be placed directly in any scalar:" "\n"
1100 "en: Planet (Gas)" "\n"
1101 "fr: Planète (Gazeuse)" "\n"
1102 "ru: Планета (Газ)" "\n"
1106 "# UTF8 decoding only happens in double-quoted strings," "\n"
1107 "# as per the YAML standard" "\n"
1109 "decode this: \"\\u263A c\\x61f\\xE9\"" "\n"
1110 "and this as well: \"\\u2705 \\U0001D11E\"" "\n"
1111 "not decoded: '\\u263A \\xE2\\x98\\xBA'" "\n"
1112 "neither this: '\\u2705 \\U0001D11E'" "\n");
1114 CHECK(langs[
"en"].val() ==
"Planet (Gas)");
1115 CHECK(langs[
"fr"].val() ==
"Planète (Gazeuse)");
1116 CHECK(langs[
"ru"].val() ==
"Планета (Газ)");
1117 CHECK(langs[
"ja"].val() ==
"惑星(ガス)");
1118 CHECK(langs[
"zh"].val() ==
"行星(气体)");
1122 CHECK(langs[
"decode this"].val() ==
"☺ café");
1123 CHECK(langs[
"and this as well"].val() ==
"✅ 𝄞");
1124 CHECK(langs[
"not decoded"].val() ==
"\\u263A \\xE2\\x98\\xBA");
1125 CHECK(langs[
"neither this"].val() ==
"\\u2705 \\U0001D11E");
1153 const char foobar_str[] =
"foobar";
1155 CHECK(s ==
"foobar");
1156 CHECK(s.size() == 6);
1157 CHECK(s.data() == foobar_str);
1158 CHECK(s.size() == s.len);
1159 CHECK(s.data() == s.str);
1164 const char foobar_str[] =
"foobar";
1166 CHECK(s ==
"foobar");
1167 CHECK(s !=
"foobar0");
1176 CHECK(s ==
"foobar");
1177 CHECK(s !=
"foobar0");
1189 const char *foobar_str =
"foobar";
1191 CHECK(s ==
"foobar");
1192 CHECK(s !=
"foobar0");
1206 std::string foobar_str =
"foobar";
1208 CHECK(s ==
"foobar");
1209 CHECK(s !=
"foobar0");
1231 char const foobar_str_ro[] =
"foobar";
1232 char foobar_str_rw[] =
"foobar";
1233 static_assert(std::is_array<
decltype(foobar_str_ro)>::value,
"this is an array");
1234 static_assert(std::is_array<
decltype(foobar_str_rw)>::value,
"this is an array");
1239 CHECK(foobar.
size() == strlen(foobar_str_ro));
1240 CHECK(foobar ==
"foobar");
1246 CHECK(foobar.
size() == strlen(foobar_str_rw));
1247 CHECK(foobar ==
"foobar");
1253 CHECK(foobar.
size() == strlen(foobar_str_rw));
1254 CHECK(foobar ==
"foobar");
1265 char const* foobar_str_ro =
"foobar";
1266 char foobar_str_rw_[] =
"foobar";
1267 char * foobar_str_rw = foobar_str_rw_;
1268 static_assert(!std::is_array<
decltype(foobar_str_ro)>::value,
"this is a decayed pointer");
1269 static_assert(!std::is_array<
decltype(foobar_str_rw)>::value,
"this is a decayed pointer");
1275 CHECK(foobar.
size() == strlen(foobar_str_ro));
1276 CHECK(foobar ==
"foobar");
1282 CHECK(foobar.
size() == strlen(foobar_str_rw));
1283 CHECK(foobar ==
"foobar");
1289 CHECK(foobar.
size() == strlen(foobar_str_rw));
1290 CHECK(foobar ==
"foobar");
1300 char buf[] =
"foobar";
1302 CHECK(foobar ==
"foobar");
1303 foobar[0] =
'F';
CHECK(foobar ==
"Foobar");
1304 foobar.
back() =
'R';
CHECK(foobar ==
"FoobaR");
1316 foobar.
fill(
'.');
CHECK(foobar ==
"......");
1328 CHECK(s.
sub(0, 12) ==
"fooFOObarBAR");
1388 CHECK(some ==
"some");
1389 CHECK(s ==
"some substring");
1392 char result[32] = {0};
1393 std::snprintf(result,
sizeof(result),
"%.*s", (
int)some.
len, some.
str);
1394 printf(
"~~~%s~~~\n", result);
1404 char result[32] = {0};
1405 std::snprintf(result,
sizeof(result),
"%s", some.
str);
1415 CHECK(some ==
"some");
1416 CHECK(s ==
"some substring");
1419 std::stringstream ss;
1421 CHECK(ss.str() ==
"some substring");
1422 CHECK(ss.str() == s);
1430 std::stringstream ss;
1432 CHECK(ss.str() ==
"some substring");
1433 CHECK(ss.str() == s);
1437 std::stringstream ss;
1439 CHECK(ss.str() ==
"some substring");
1440 CHECK(ss.str() == s);
1444 std::stringstream ss;
1446 CHECK(ss.str() ==
"some");
1447 CHECK(ss.str() == some);
1484 CHECK(
ryml::csubstr(
" \t\n\rcontents without whitespace\t \n\r").trim(
"\t \n\r") ==
"contents without whitespace");
1505 CHECK(aaa___bbb.
trim (
'c') == aaa___bbb);
1524 CHECK(aaa___bbb.
trim (
"cd") == aaa___bbb);
1529 CHECK(
ryml::csubstr(
"'this is is single quoted'" ).unquoted() ==
"this is is single quoted");
1530 CHECK(
ryml::csubstr(
"\"this is is double quoted\"").unquoted() ==
"this is is double quoted");
1848 CHECK(
ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extshort() ==
"/path/to/file.tar");
1854 using namespace ryml;
1855 csubstr parts[] = {
"aa",
"bb",
"cc",
"dd",
"ee",
"ff"};
1859 CHECK(part == parts[count++]);
1865 CHECK(part == parts[count++]);
1871 CHECK(part == parts[count++]);
1880 const bool skip_empty =
true;
1953 const char filename[] =
"ryml_example.yml";
1954 std::string yaml =
""
1968 CHECK(tree[
"foo"].val() ==
"1");
1969 CHECK(tree[
"bar"][0].val() ==
"2");
1970 CHECK(tree[
"bar"][1].val() ==
"3");
1977 CHECK(tree[
"foo"].val() ==
"1");
1978 CHECK(tree[
"bar"][0].val() ==
"2");
1979 CHECK(tree[
"bar"][1].val() ==
"3");
2000 char src[] =
"{foo: 1, bar: [2, 3]}";
2006 CHECK(root[
"foo"].is_keyval());
2007 CHECK(root[
"foo"].key() ==
"foo");
2008 CHECK(root[
"foo"].val() ==
"1");
2009 CHECK(root[
"bar"].is_seq());
2010 CHECK(root[
"bar"].has_key());
2011 CHECK(root[
"bar"].key() ==
"bar");
2012 CHECK(root[
"bar"][0].val() ==
"2");
2013 CHECK(root[
"bar"][1].val() ==
"3");
2016 int foo = 0, bar0 = 0, bar1 = 0;
2017 root[
"foo"].
load(&foo);
2018 root[
"bar"][0].
load(&bar0);
2019 root[
"bar"][1].
load(&bar1);
2025 CHECK(root[
"foo"].val().data() == src + strlen(
"{foo: "));
2026 CHECK(root[
"foo"].val().begin() == src + strlen(
"{foo: "));
2027 CHECK(root[
"foo"].val().end() == src + strlen(
"{foo: 1"));
2028 CHECK(root[
"foo"].val().is_sub(srcview));
2029 CHECK(root[
"bar"][0].val().data() == src + strlen(
"{foo: 1, bar: ["));
2030 CHECK(root[
"bar"][0].val().begin() == src + strlen(
"{foo: 1, bar: ["));
2031 CHECK(root[
"bar"][0].val().end() == src + strlen(
"{foo: 1, bar: [2"));
2032 CHECK(root[
"bar"][0].val().is_sub(srcview));
2033 CHECK(root[
"bar"][1].val().data() == src + strlen(
"{foo: 1, bar: [2, "));
2034 CHECK(root[
"bar"][1].val().begin() == src + strlen(
"{foo: 1, bar: [2, "));
2035 CHECK(root[
"bar"][1].val().end() == src + strlen(
"{foo: 1, bar: [2, 3"));
2036 CHECK(root[
"bar"][1].val().is_sub(srcview));
2058 CHECK(root[
"foo"].is_keyval());
2059 CHECK(root[
"foo"].key() ==
"foo");
2060 CHECK(root[
"foo"].val() ==
"1");
2061 CHECK(root[
"bar"].is_seq());
2062 CHECK(root[
"bar"].has_key());
2063 CHECK(root[
"bar"].key() ==
"bar");
2064 CHECK(root[
"bar"][0].val() ==
"2");
2065 CHECK(root[
"bar"][1].val() ==
"3");
2068 int foo = 0, bar0 = 0, bar1 = 0;
2069 root[
"foo"].
load(&foo);
2070 root[
"bar"][0].
load(&bar0);
2071 root[
"bar"][1].
load(&bar1);
2079 char src[] =
"{foo: is it really true}";
2088 CHECK(tree[
"foo"].val() ==
"is it really true");
2116 CHECK(root[
"foo"].is_keyval());
2117 CHECK(root[
"foo"].key() ==
"foo");
2118 CHECK(root[
"foo"].val() ==
"1");
2119 CHECK(root[
"bar"].is_seq());
2120 CHECK(root[
"bar"].has_key());
2121 CHECK(root[
"bar"].key() ==
"bar");
2122 CHECK(root[
"bar"][0].val() ==
"2");
2123 CHECK(root[
"bar"][1].val() ==
"3");
2132 "bar2: [22,32]" "\n"
2135 CHECK(root[
"foo2"].is_keyval());
2136 CHECK(root[
"foo2"].key() ==
"foo2");
2137 CHECK(root[
"foo2"].val() ==
"12");
2138 CHECK(root[
"bar2"].is_seq());
2139 CHECK(root[
"bar2"].has_key());
2140 CHECK(root[
"bar2"].key() ==
"bar2");
2141 CHECK(root[
"bar2"][0].val() ==
"22");
2142 CHECK(root[
"bar2"][1].val() ==
"32");
2151 CHECK(root[0].val() ==
"a");
2152 CHECK(root[1].val() ==
"b");
2153 CHECK(root[2].is_map());
2154 CHECK(root[2][
"x0"].val() ==
"1");
2155 CHECK(root[2][
"x1"].val() ==
"2");
2163 "- {x0: 1,x1: 2}" "\n"
2164 "- champagne: Dom Perignon" "\n"
2165 " coffee: Arabica" "\n"
2168 CHECK(root[0].val() ==
"a");
2169 CHECK(root[1].val() ==
"b");
2170 CHECK(root[2].is_map());
2171 CHECK(root[2][
"x0"].val() ==
"1");
2172 CHECK(root[2][
"x1"].val() ==
"2");
2173 CHECK(root[3].is_map());
2174 CHECK(root[3][
"champagne"].val() ==
"Dom Perignon");
2175 CHECK(root[3][
"coffee"].val() ==
"Arabica");
2179 CHECK(mroot[3][
"more"].readable());
2180 CHECK(mroot[3][
"more"].key() ==
"more");
2181 CHECK(mroot[3][
"more"].is_map());
2182 CHECK(!mroot[3][
"more"].is_val());
2189 "- {x0: 1,x1: 2}" "\n"
2190 "- champagne: Dom Perignon" "\n"
2191 " coffee: Arabica" "\n"
2194 " vinho verde: Soalheiro" "\n"
2195 " vinho tinto: Redoma 2017" "\n"
2197 " - Rochefort 10" "\n"
2199 " - Leffe Rituel" "\n"
2200 " always: lots of water" "\n"
2208 "- {x0: 1,x1: 2}" "\n"
2209 "- champagne: Dom Perignon" "\n"
2210 " coffee: Arabica" "\n"
2212 " vinho verde: Soalheiro" "\n"
2213 " vinho tinto: Redoma 2017" "\n"
2215 " - Rochefort 10" "\n"
2217 " - Leffe Rituel" "\n"
2218 " always: lots of water" "\n"
2231 "- {x0: 1,x1: 2}" "\n"
2232 "- champagne: Dom Perignon" "\n"
2233 " coffee: Arabica" "\n"
2235 " vinho verde: Soalheiro" "\n"
2236 " vinho tinto: Redoma 2017" "\n"
2238 " - Rochefort 10" "\n"
2240 " - Leffe Rituel" "\n"
2241 " - Kasteel Donker" "\n"
2242 " always: lots of water" "\n"
2270 ryml::csubstr yaml =
"[Dom Perignon,Gosset Grande Reserve,Jacquesson 742]";
2274 yaml =
"[Rochefort 10,Busch,Leffe Rituel,Kasteel Donker]";
2308 "- Gosset Grande Reserve\n"
2309 "- Jacquesson 742\n"
2315 "- Kasteel Donker\n"
2319 "- Niepoort Redoma 2017\n"
2320 "- Vina Esmeralda\n"
2330 "- Gosset Grande Reserve\n"
2331 "- Jacquesson 742\n"
2335 "- Kasteel Donker\n"
2343 "- Niepoort Redoma 2017\n"
2344 "- Vina Esmeralda\n"
2360 "doe: a deer, a female deer" "\n"
2361 "ray: 'a drop of golden sun'" "\n"
2362 "me: \"a name I call myself\"" "\n"
2364 " a long long way to go" "\n"
2366 " a needle pulling thread" "\n"
2367 "seq: [0,1,2,3]" "\n"
2377 CHECK(tree[
"doe"].is_val_plain());
2378 CHECK(tree[
"ray"].is_val_squo());
2379 CHECK(tree[
"me"].is_val_dquo());
2380 CHECK(tree[
"far"].is_val_literal());
2381 CHECK(tree[
"sow"].is_val_folded());
2382 CHECK(tree[
"seq"].is_flow());
2383 CHECK(tree[
"seq"].is_flow_sl());
2384 CHECK(tree[
"map"].is_flow());
2385 CHECK(tree[
"map"].is_flow_mlx());
2401 "doe: a deer, a female deer" "\n"
2402 "ray: a drop of golden sun" "\n"
2405 "french-hens: 3" "\n"
2406 "calling-birds:" "\n"
2411 "xmas-fifth-day:" "\n"
2412 " calling-birds: four" "\n"
2413 " french-hens: 3" "\n"
2414 " golden-rings: 5" "\n"
2417 " location: a pear tree" "\n"
2418 " turtle-doves: two" "\n"
2425 std::vector<ryml::csubstr> keys, vals;
2428 keys.emplace_back(n.key());
2431 CHECK(keys.size() >= 6);
2432 CHECK(vals.size() >= 6);
2433 if(keys.size() >= 6 && vals.size() >= 6)
2435 CHECK(keys[0] ==
"doe");
2436 CHECK(vals[0] ==
"a deer, a female deer");
2437 CHECK(keys[1] ==
"ray");
2438 CHECK(vals[1] ==
"a drop of golden sun");
2439 CHECK(keys[2] ==
"pi");
2440 CHECK(vals[2] ==
"3.14159");
2441 CHECK(keys[3] ==
"xmas");
2442 CHECK(vals[3] ==
"true");
2443 CHECK(root[5].has_key());
2444 CHECK(root[5].is_seq());
2445 CHECK(root[5].key() ==
"calling-birds");
2446 CHECK(!root[5].has_val());
2448 CHECK(keys[5] ==
"calling-birds");
2449 CHECK(vals[5] ==
"");
2456 ryml::csubstr calling_birds[] = {
"huey",
"dewey",
"louie",
"fred"};
2458 CHECK(n.val() == calling_birds[count++]);
2478 "aa: contents," "\n"
2479 "foo: [one, [two, three]]" "\n"
2523 loc = tree[
"foo"].
location(parser);
2528 loc = tree[
"foo"][0].
location(parser);
2533 loc = tree[
"foo"][1].
location(parser);
2537 loc = tree[
"foo"][1][0].
location(parser);
2541 loc = tree[
"foo"][1][1].
location(parser);
2563 "a new: buffer" "\n"
2564 "to: be parsed" "\n"
2565 "map with key:" "\n"
2566 " first: value" "\n"
2567 " second: value" "\n"
2568 "seq with key:" "\n"
2569 " - first value" "\n"
2570 " - second value" "\n"
2572 " - nested first value" "\n"
2573 " - nested second value" "\n"
2575 " nested first: value" "\n"
2576 " nested second: value" "\n"
2590 loc = tree2[
"a new"].
location(parser);
2595 loc = tree2[
"to"].
location(parser);
2601 loc = tree2[
"map with key"].
location(parser);
2605 loc = tree2[
"map with key"][
"first"].
location(parser);
2609 loc = tree2[
"map with key"][
"second"].
location(parser);
2614 loc = tree2[
"seq with key"].
location(parser);
2618 loc = tree2[
"seq with key"][0].
location(parser);
2622 loc = tree2[
"seq with key"][1].
location(parser);
2627 loc = tree2[
"seq with key"][2].
location(parser);
2631 loc = tree2[
"seq with key"][2][0].
location(parser);
2636 loc = tree2[
"seq with key"][3].
location(parser);
2640 loc = tree2[
"seq with key"][3][0].
location(parser);
2667 const char a_deer[] =
"a deer, a female deer";
2676 std::string a_drop =
"a drop of golden sun";
2685 CHECK(root[
"ray"].val() ==
"a drop of golden sun");
2699 xmas5[
"calling-birds"].
set_val(
"four");
2702 xmas5[
"partridges"].
set_map();
2704 xmas5[
"partridges"][
"location"].
set_val(
"a pear tree");
2705 xmas5[
"turtle-doves"].
set_val(
"two");
2709 "doe: a deer, a female deer" "\n"
2710 "ray: a drop of golden sun" "\n"
2713 "french-hens: 3" "\n"
2714 "calling-birds:" "\n"
2719 "xmas-fifth-day:" "\n"
2720 " calling-birds: four" "\n"
2721 " french-hens: 3" "\n"
2722 " golden-rings: 5" "\n"
2725 " location: a pear tree" "\n"
2726 " turtle-doves: two" "\n"
2771 root[
"not plain"].
set_val(
" with whitespace ");
2785 for(
int i : {0, 1, 2, 3})
2810 "not plain: ' with whitespace '" "\n"
2814 "doe: a deer, a female deer" "\n"
2815 "ray: 'a drop of golden sun'" "\n"
2816 "me: \"a name I call myself\"" "\n"
2818 " a long long way to go" "\n"
2820 " a needle pulling thread" "\n"
2821 "seq: [0, 1, 2, 3]" "\n"
2829 " 1: 10,2: 20,3: 30,4: 40" "\n"
2842 "plain: with whitespace " "\n"
2856 char buf[] =
"[a, b, c, d]";
2886 CHECK(root[0].val().is_sub(arena));
2887 CHECK(root[1].val().is_sub(arena));
2888 CHECK(root[2].val().is_sub(arena));
2889 CHECK(root[3].val().is_sub(arena));
2899 char buf[] =
"[a, b, c, d]";
2907 CHECK(root[2].val() ==
"c");
2910 CHECK(root[2].val() ==
"12345");
2916 CHECK(root[3].val() ==
"d");
2919 CHECK(root[3].val() ==
"67890");
2935 CHECK(root[2].val() ==
"c");
2937 CHECK(root[2].val() ==
"12345");
2946 CHECK(root[3].val() ==
"67890");
2950 CHECK(tree.
arena() ==
"[a, b, c, d]1234567890");
2958 CHECK(c10 ==
"10101010");
2968 CHECK(root[
"a"].val() ==
"2222");
2978 CHECK(copied == mystr);
2979 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2988 memcpy(copied.
str, mystr.
str, mystr.
len);
2989 CHECK(copied == mystr);
2990 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
3039 CHECK(tree.
to_arena(
double(0.234)) ==
"0.234");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.234");
3049 const float fnan = std::numeric_limits<float >::quiet_NaN();
3050 const double dnan = std::numeric_limits<double>::quiet_NaN();
3051 const float finf = std::numeric_limits<float >::infinity();
3052 const double dinf = std::numeric_limits<double>::infinity();
3053 CHECK(tree.
to_arena( finf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf");
3054 CHECK(tree.
to_arena( dinf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf");
3055 CHECK(tree.
to_arena(-finf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf");
3056 CHECK(tree.
to_arena(-dinf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf");
3057 CHECK(tree.
to_arena( fnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan");
3058 CHECK(tree.
to_arena( dnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan.nan");
3062 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wfloat-equal");
3068 tree[
"ninf"].
load(&f);
CHECK(f == -finf);
3069 tree[
"ninf"].
load(&d);
CHECK(d == -dinf);
3070 tree[
"pinf"].
load(&f);
CHECK(f == finf);
3071 tree[
"pinf"].
load(&d);
CHECK(d == dinf);
3072 tree[
"nan" ].
load(&f);
CHECK(std::isnan(f));
3073 tree[
"nan" ].
load(&d);
CHECK(std::isnan(d));
3074 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3096 n.load(ryml::fmt::overflow_checked(valu8));
3099 n.load(ryml::fmt::overflow_checked(vali8));
3115 "dquoted: \"\"" "\n"
3118 "all_null: [~, null, Null, NULL]" "\n"
3119 "non_null: [nULL, non_null, non null, null it is not]" "\n"
3123 CHECK(tree[
"plain"].has_val());
3124 CHECK(tree[
"squoted"].has_val());
3125 CHECK(tree[
"dquoted"].has_val());
3126 CHECK(tree[
"literal"].has_val());
3127 CHECK(tree[
"folded"].has_val());
3128 CHECK( ! tree[
"all_null"].has_val());
3129 CHECK( ! tree[
"non_null"].has_val());
3131 CHECK( ! tree[
"plain"].is_container());
3132 CHECK( ! tree[
"squoted"].is_container());
3133 CHECK( ! tree[
"dquoted"].is_container());
3134 CHECK( ! tree[
"literal"].is_container());
3135 CHECK( ! tree[
"folded"].is_container());
3136 CHECK(tree[
"all_null"].is_container());
3137 CHECK(tree[
"non_null"].is_container());
3142 CHECK(tree[
"plain"].val().len == 0);
3143 CHECK(tree[
"squoted"].val().len == 0);
3144 CHECK(tree[
"dquoted"].val().len == 0);
3145 CHECK(tree[
"literal"].val().len == 0);
3146 CHECK(tree[
"folded"].val().len == 0);
3148 CHECK(tree[
"plain"].val().str ==
nullptr);
3149 CHECK(tree[
"squoted"].val().str !=
nullptr);
3150 CHECK(tree[
"dquoted"].val().str !=
nullptr);
3151 CHECK(tree[
"literal"].val().str !=
nullptr);
3152 CHECK(tree[
"folded"].val().str !=
nullptr);
3156 CHECK(tree[
"plain"].val() ==
nullptr);
3157 CHECK(tree[
"squoted"].val() !=
nullptr);
3158 CHECK(tree[
"dquoted"].val() !=
nullptr);
3159 CHECK(tree[
"literal"].val() !=
nullptr);
3160 CHECK(tree[
"folded"].val() !=
nullptr);
3165 CHECK(tree[
"plain"].val_is_null());
3166 CHECK( ! tree[
"squoted"].val_is_null());
3167 CHECK( ! tree[
"dquoted"].val_is_null());
3168 CHECK( ! tree[
"literal"].val_is_null());
3169 CHECK( ! tree[
"folded"].val_is_null());
3174 CHECK(child.val() !=
nullptr);
3175 CHECK(child.val_is_null());
3179 CHECK(child.val() !=
nullptr);
3180 CHECK( ! child.val_is_null());
3195 CHECK(null .len == 0);
CHECK(null .str ==
nullptr);
CHECK(null ==
nullptr);
3198 CHECK(tilde .len != 0);
CHECK(tilde .str !=
nullptr);
CHECK(tilde !=
nullptr);
3213 "empty_nonnull: ''" "\n"
3214 "str_null: null" "\n"
3223 return s.str ==
nullptr ?
"null" : s;
3231 "empty_null: null" "\n"
3232 "empty_nonnull: ''" "\n"
3233 "str_null: null" "\n"
3243 tree[
"empty_nonnull"].
set_serialized(null_if_predicate(nonnull));
3248 "empty_null: null" "\n"
3249 "empty_nonnull: ''" "\n"
3250 "str_null: null" "\n"
3251 "str_tilde: null" "\n"
3260 tree[
"empty_nonnull"].
set_serialized(tilde_if_predicate(nonnull));
3265 "empty_null: ~" "\n"
3266 "empty_nonnull: ''" "\n"
3284 char buf_[256] = {};
3286 size_t size =
ryml::format(buf,
"a={} foo {} {} bar {}", 0.1, 10, 11, 12);
3287 CHECK(size == strlen(
"a=0.1 foo 10 11 bar 12"));
3288 CHECK(buf.
first(size) ==
"a=0.1 foo 10 11 bar 12");
3291 size =
ryml::format({} ,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12);
3292 CHECK(size ==
ryml::format(buf,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12));
3293 CHECK(size == strlen(
"a=this_is_a foo 10 11 bar 12"));
3295 char smallbuf[8] = {};
3296 size =
ryml::format(smallbuf,
"{} is too large {}",
"this",
"for the buffer");
3297 CHECK(size == strlen(
"this is too large for the buffer"));
3303 CHECK(result ==
"b=1, damn it.");
3322 CHECK(sbuf ==
"and c=2 seems about right");
3323 std::vector<char> vbuf;
3325 CHECK(sbuf ==
"and c=2 seems about right");
3328 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
3335 int a = 0, b = 1, c = 2;
3337 CHECK(result ==
"0 and 1 and 2");
3338 int aa = -1, bb = -2, cc = -3;
3339 size_t num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
3347 CHECK(result ==
"10 and 20 and 30");
3348 num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
3358 char buf_[256] = {};
3360 size_t size =
ryml::cat(buf,
"a=", 0.1,
"foo", 10, 11,
"bar", 12);
3361 CHECK(size == strlen(
"a=0.1foo1011bar12"));
3362 CHECK(buf.
first(size) ==
"a=0.1foo1011bar12");
3367 char smallbuf[8] = {};
3368 size =
ryml::cat(smallbuf,
"this",
" is too large ",
"for the buffer");
3369 CHECK(size == strlen(
"this is too large for the buffer"));
3375 CHECK(result ==
"b=1, damn it.");
3393 ryml::catrs(&sbuf,
"and c=", 2,
" seems about right");
3394 CHECK(sbuf ==
"and c=2 seems about right");
3395 std::vector<char> vbuf;
3396 ryml::catrs(&vbuf,
"and c=", 2,
" seems about right");
3397 CHECK(sbuf ==
"and c=2 seems about right");
3400 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
3407 int a = 0, b = 1, c = 2;
3409 CHECK(result ==
"0 1 2");
3410 int aa = -1, bb = -2, cc = -3;
3411 char sep1 =
'a', sep2 =
'b';
3412 size_t num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
3421 CHECK(result ==
"10 20 30");
3422 num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
3433 char buf_[256] = {};
3436 size_t size =
ryml::catsep(buf,
' ',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
3437 CHECK(buf.
first(size) ==
"a= 0 b= 1 c= 2 45 67");
3440 size =
ryml::catsep(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
3441 CHECK(buf.
first(size) ==
"a=0 and b=1 and c=2 and 45 and 67");
3443 size =
ryml::catsep(buf,
" ... ",
"a=0",
"b=1",
"c=2", 45, 67);
3444 CHECK(buf.
first(size) ==
"a=0 ... b=1 ... c=2 ... 45 ... 67");
3446 size =
ryml::catsep(buf,
'/',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
3447 CHECK(buf.
first(size) ==
"a=/0/b=/1/c=/2/45/67");
3449 size =
ryml::catsep(buf, 888,
"a=0",
"b=1",
"c=2", 45, 67);
3450 CHECK(buf.
first(size) ==
"a=0888b=1888c=28884588867");
3456 char smallbuf[8] = {};
3458 CHECK(size == strlen(
"a=0888b=1888c=28884588867"));
3464 CHECK(result ==
"a=0 and b=1 and c=2 and 45 and 67");
3483 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67");
3484 std::vector<char> vbuf;
3490 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67 --- a=0 well b=11 well c=12 well 145 well 167");
3495 char buf_[256] = {};
3497 int a = 0, b = 1, c = 2;
3499 CHECK(result ==
"0 1 2");
3500 int aa = -1, bb = -2, cc = -3;
3508 CHECK(result ==
"10--20--30");
3518 using namespace ryml;
3519 char buf_[256] = {};
3538 CHECK(
"3735928559" ==
cat_sub(buf, UINT32_C(0xdeadbeef)));
3662 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wcast-align")
3663 const uint32_t payload[] = {10, 20, 30, 40, UINT32_C(0xdeadbeef)};
3665 csubstr expected =
csubstr((
const char *)payload,
sizeof(payload));
3670 for(
const uint32_t value : payload)
3673 expected =
csubstr((
const char *)&value,
sizeof(value));
3675 CHECK(actual.
size() ==
sizeof(uint32_t));
3680 CHECK(actual.
size() ==
sizeof(uint32_t));
3685 uint32_t result = 0;
3690 CHECK(result == value);
3692 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3712 text_and_base64 cases[] = {
3713 {{
"Hello, World!"}, {
"SGVsbG8sIFdvcmxkIQ=="}},
3714 {{
"Brevity is the soul of wit."}, {
"QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu"}},
3715 {{
"All that glitters is not gold."}, {
"QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu"}},
3718 for(text_and_base64 c : cases)
3721 for(text_and_base64 c : cases)
3728 for(text_and_base64 c : cases)
3730 CHECK(tree[c.text].
val() == c.base64);
3731 CHECK(tree[c.base64].
val() == c.text);
3735 "Hello, World!: SGVsbG8sIFdvcmxkIQ==" "\n"
3736 "Brevity is the soul of wit.: QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu" "\n"
3737 "All that glitters is not gold.: QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu" "\n"
3739 "SGVsbG8sIFdvcmxkIQ==: Hello, World!" "\n"
3740 "QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu: Brevity is the soul of wit." "\n"
3741 "QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu: All that glitters is not gold." "\n"
3743 char buf1_[128], buf2_[128];
3747 for(
const text_and_base64 c : cases)
3752 tree[c.text].
load(ryml::fmt::base64(buf1, &len));
3761 CHECK(c.text.len == len);
3764 tree[c.base64].
load_key(ryml::fmt::base64(buf2, &len));
3770 tree[c.text].
load(ryml::fmt::base64(result));
3771 CHECK(result == c.text);
3773 tree[c.base64].
load_key(ryml::fmt::base64(result));
3774 CHECK(result == c.text);
3785 if(len > result.size())
3794 CHECK(result == c.text);
3803 union { uint32_t u;
char c[
sizeof(uint32_t)]; } endianess_test = {1};
3804 const bool is_little_endian = endianess_test.c[0] == 1;
3806 return is_little_endian ? little_endian : big_endian;
3811 const uint64_t valin = UINT64_C(0xdeadbeef);
3814 CHECK(node.
val() == endian_select(
"776t3gAAAAA=",
"AAAAAN6tvu8="));
3815 uint64_t valout = 0;
3817 node.
load(ryml::fmt::base64(valout, &len));
3818 CHECK(len ==
sizeof(valout));
3819 CHECK(valout == UINT64_C(0xdeadbeef));
3822 node.
load(ryml::fmt::base64(valout));
3823 CHECK(valout == UINT64_C(0xdeadbeef));
3827 const double valin = 123456.7891011;
3830 CHECK(node.
val() == endian_select(
"nHkooAwk/kA=",
"QP4kDKAoeZw="));
3833 node.
load(ryml::fmt::base64(valout, &len));
3834 CHECK(len ==
sizeof(valout));
3835 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3838 node.
load(ryml::fmt::base64(valout));
3839 CHECK(memcmp(&valout, &valin,
sizeof(valout)) == 0);
3843 const uint32_t data_in[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xdeadbeef};
3844 uint32_t data_out[11] = {};
3848 endian_select(
"AAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAO++rd4=",
3849 "AAAAAAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACd6tvu8="));
3850 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) != 0);
3852 node.
load(ryml::fmt::base64(data_out, C4_COUNTOF(data_in), &len));
3853 CHECK(len ==
sizeof(data_out));
3854 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3857 memset(data_out, 0,
sizeof(data_out));
3858 node.
load(ryml::fmt::base64(data_out));
3859 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3881 {
int val = 1; tree[0].
load(&val);
CHECK(val == 0); }
3882 {
unsigned val = 0; tree[1].
load(&val);
CHECK(val == 10); }
3884 {
unsigned key = 0; tree[1].
load_key(&key);
CHECK(key == 10); }
3886 {
int val = 1; tree.
load(tree[0].
id(), &val);
CHECK(val == 0); }
3887 {
unsigned val = 0; tree.
load(tree[1].
id(), &val);
CHECK(val == 10); }
3888 {
int key = 1; tree.
load_key(tree[0].
id(), &key);
CHECK(key == 0); }
3889 {
unsigned key = 0; tree.
load_key(tree[1].
id(), &key);
CHECK(key == 10); }
3894 {
int val = 1;
CHECK(tree[0].deserialize(&val));
CHECK(val == 0); }
3895 {
unsigned val = 0;
CHECK(tree[1].deserialize(&val));
CHECK(val == 10); }
3896 {
int key = 1;
CHECK(tree[0].deserialize_key(&key));
CHECK(key == 0); }
3897 {
unsigned key = 0;
CHECK(tree[1].deserialize_key(&key));
CHECK(key == 10); }
3908 {
int val = 10; tree[0].
save(val);
CHECK(tree[0].val() ==
"10"); }
3909 {
unsigned val = 11; tree[1].
save(val);
CHECK(tree[1].val() ==
"11"); }
3910 {
int key = 12; tree[0].
save_key(key);
CHECK(tree[0].key() ==
"12"); }
3911 {
unsigned key = 13; tree[1].
save_key(key);
CHECK(tree[1].key() ==
"13"); }
3913 {
int val = 20; tree.
save(tree[0].
id(), val);
CHECK(tree[0].val() ==
"20"); }
3914 {
unsigned val = 21; tree.
save(tree[1].
id(), val);
CHECK(tree[1].val() ==
"21"); }
3915 {
int key = 22; tree.
save_key(tree[0].
id(), key);
CHECK(tree[0].key() ==
"22"); }
3916 {
unsigned key = 23; tree.
save_key(tree[1].
id(), key);
CHECK(tree[1].key() ==
"23"); }
3930 {
unsigned val = 19; tree.
set_serialized(tree[1].
id(), val);
CHECK(tree[1].val() ==
"19"); }
3938 tree[0].
set_val_tag(tree[0].to_arena(42));
CHECK(tree[0].val_tag() ==
"42");
3939 tree[1].
set_key_tag(tree[1].to_arena(43));
CHECK(tree[1].key_tag() ==
"43");
4026 root[
"v2"].
save(v2in);
4027 root[
"v2"].
load(&v2out);
4032 root[
"v3"].
save(v3in);
4033 root[
"v3"].
load(&v3out);
4039 root[
"v4"].
save(v4in);
4040 root[
"v4"].
load(&v4out);
4047 "v3: (100,101,102)" "\n"
4048 "v4: (1000,1001,1002,1003)" "\n"
4056 root[
"v2"].
save(eov2in);
4057 root[
"v2"].
load(&pov2out);
4062 root[
"v3"].
save(eov3in);
4063 root[
"v3"].
load(&pov3out);
4069 root[
"v4"].
save(eov4in);
4070 root[
"v4"].
load(&pov4out);
4076 "v3: (30,31,32)" "\n"
4077 "v4: (40,41,42,43)" "\n"
4147 Outer outer{{{0,1}, {2,3}}};
4154 "- {foo: 0,bar: 1}\n"
4155 "- {foo: 2,bar: 3}\n");
4157 root.
load(&roundtrip);
4159 CHECK(0 == memcmp(&outer, &roundtrip,
sizeof(
Outer)));
4184 for(
size_t i = 0; i <
seq_member.size(); ++i)
4189template<
class K,
class V>
4203 CHECK(it->second == itthat.second);
4270template<
class K,
class V>
4333template<
class K,
class V>
4430 {{101, 102, 103, 104, 105, 106, 107}},
4431 {{{1001, 2001}, {1002, 2002}, {1003, 2003}}},
4435 root_node.
save(orig);
4439 "v3: (30,31,32)" "\n"
4440 "v4: (40,41,42,43)" "\n"
4458 root_node.
load(&roundtrip);
4465 tree.
load(root_id, &roundtrip);
4474 "a deer, a female deer",
4476 "a drop of golden sun"
4479 tree[
"not in arena"].
save(strseq);
4483 "not in arena:" "\n"
4485 " - a deer, a female deer" "\n"
4487 " - a drop of golden sun" "\n"
4495 CHECK(child.val() == str_orig);
4497 CHECK(child.val().is_sub(str_orig));
4524 "v3: (30,31,32)" "\n"
4525 "v4: (40,41,42,43)" "\n"
4536 " 1002: not an int" "\n"
4566 std::string yml_std_string =
""
4567 "- v2: (20,21)" "\n"
4568 " v3: (30,31,32)" "\n"
4569 " v4: (40,41,42,43)" "\n"
4582 "- v2: (120,121)" "\n"
4583 " v3: (130,131,132)" "\n"
4584 " v4: (140,141,142,143)" "\n"
4594 " 11001: 12001" "\n"
4595 " 11002: 12002" "\n"
4596 " 11003: 12003" "\n"
4597 "- v2: (220,221)" "\n"
4598 " v3: (230,231,232)" "\n"
4599 " v4: (240,241,242,243)" "\n"
4609 " 21001: 22001" "\n"
4610 " 21002: 22002" "\n"
4611 " 21003: 22003" "\n"
4617 std::vector<my_type> vec;
4619 CHECK(vec.size() == 3);
4631 std::vector<double> reference{1.23234412342131234, 2.12323123143434237, 3.67847983572591234};
4635 const double precision_safe = 1.e-14;
4636 const size_t num_digits_safe = 14;
4637 const size_t num_digits_original = 17;
4638 auto get_num_digits = [](
ryml::csubstr number){
return number.len - 2u; };
4644 std::vector<double> output;
4646 CHECK(output.size() == reference.size());
4647 for(
size_t i = 0; i < reference.size(); ++i)
4650 CHECK(fabs(output[i] - reference[i]) < precision_safe);
4661 #if (!C4CORE_HAVE_STD_TOCHARS)
4666 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4667 C4_UNUSED(num_digits_safe);
4671 "- 1.2323441234213124" "\n"
4672 "- 2.1232312314343424" "\n"
4673 "- 3.6784798357259123" "\n"
4674 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4678 CHECK(get_num_digits(child.val()) >= num_digits_safe);
4681 CHECK(fabs(out - reference[pos++]) < precision_safe);
4712 auto check_precision = [&](
ryml::Tree const& serialized){
4713 std::cout << serialized;
4716 "- 1.23234412342131239" "\n"
4717 "- 2.12323123143434245" "\n"
4718 "- 3.67847983572591231" "\n"
4719 "") || (
bool)
"this is indicative; the exact results will vary from platform to platform.");
4723 CHECK(get_num_digits(child.val()) == num_digits_original);
4726 CHECK(fabs(out - reference[pos++]) < precision_safe);
4735 for(
const double v : reference)
4737 check_precision(serialized);
4746 for(
const double v : reference)
4751 (void)snprintf(tmp,
sizeof(tmp),
"%.18g", v);
4757 check_precision(serialized);
4776 "- champagne: Dom Perignon" "\n"
4777 " coffee: Arabica" "\n"
4779 " vinho verde: Soalheiro" "\n"
4780 " vinho tinto: Redoma 2017" "\n"
4782 " - Rochefort 10" "\n"
4784 " - Leffe Rituel" "\n"
4803 size_t num_needed_chars = output.
len;
4804 std::vector<char> buf(num_needed_chars);
4807 CHECK(output == ymla);
4815 num_needed_chars = output.
len;
4816 buf.resize(num_needed_chars);
4819 CHECK(output == ymlb);
4824 CHECK(output == ymlb);
4835 " vinho verde: Soalheiro" "\n"
4836 " vinho tinto: Redoma 2017" "\n"
4849 size_t num_needed_chars = output.
len;
4851 buf.resize(num_needed_chars);
4854 CHECK(output == ymla);
4862 num_needed_chars = output.
len;
4863 buf.resize(num_needed_chars);
4866 CHECK(output == ymlb);
4871 CHECK(output == ymlb);
4882 " vinho verde: Soalheiro" "\n"
4883 " vinho tinto: Redoma 2017" "\n"
4899 "- champagne: Dom Perignon" "\n"
4900 " coffee: Arabica" "\n"
4902 " vinho verde: Soalheiro" "\n"
4903 " vinho tinto: Redoma 2017" "\n"
4905 " - Rochefort 10" "\n"
4907 " - Leffe Rituel" "\n"
4919 std::stringstream ss;
4927 std::stringstream ss;
4939 " \"champagne\": \"Dom Perignon\"," "\n"
4940 " \"coffee\": \"Arabica\"," "\n"
4942 " \"vinho verde\": \"Soalheiro\"," "\n"
4943 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4946 " \"Rochefort 10\"," "\n"
4948 " \"Leffe Rituel\"" "\n"
4961 std::stringstream ss;
4966 " vinho verde: Soalheiro" "\n"
4967 " vinho tinto: Redoma 2017" "\n"
4973 std::stringstream ss;
4978 " \"vinho verde\": \"Soalheiro\"," "\n"
4979 " \"vinho tinto\": \"Redoma 2017\"" "\n"
4996 "- champagne: Dom Perignon" "\n"
4997 " coffee: Arabica" "\n"
4999 " vinho verde: Soalheiro" "\n"
5000 " vinho tinto: Redoma 2017" "\n"
5002 " - Rochefort 10" "\n"
5004 " - Leffe Rituel" "\n"
5027 "- champagne: Dom Perignon" "\n"
5028 " coffee: Arabica" "\n"
5030 " vinho verde: Soalheiro" "\n"
5031 " vinho tinto: Redoma 2017" "\n"
5033 " - Rochefort 10" "\n"
5035 " - Leffe Rituel" "\n"
5037 " - many other" "\n"
5038 " - wonderful beers" "\n"
5048 " - Rochefort 10" "\n"
5050 " - Leffe Rituel" "\n"
5052 " - many other" "\n"
5053 " - wonderful beers" "\n"
5060 "- Rochefort 10" "\n"
5062 "- Leffe Rituel" "\n"
5064 " - many other" "\n"
5065 " - wonderful beers" "\n"
5072 "- wonderful beers" "\n"
5078 " - many other" "\n"
5079 " - wonderful beers" "\n"
5113 " block key: block val" "\n"
5115 " - block val 1" "\n"
5116 " - block val 2" "\n"
5118 "flow map, singleline: {flow key: flow val}" "\n"
5119 "flow seq, singleline: [flow val,flow val]" "\n"
5120 "flow map, multiline: {" "\n"
5121 " flow key: flow val" "\n"
5123 "flow seq, multiline: [" "\n"
5131 CHECK(tree[
"block map"].is_key_plain());
5132 CHECK(tree[
"block seq"].is_key_plain());
5133 CHECK(tree[
"flow map, singleline"].is_key_plain());
5134 CHECK(tree[
"flow seq, singleline"].is_key_plain());
5135 CHECK(tree[
"flow map, multiline"].is_key_plain());
5136 CHECK(tree[
"flow seq, multiline"].is_key_plain());
5137 CHECK(tree[
"block map"].is_block());
5138 CHECK(tree[
"block seq"].is_block());
5140 CHECK(tree[
"flow map, singleline"].is_flow_sl());
5141 CHECK(tree[
"flow seq, singleline"].is_flow_sl());
5142 CHECK(tree[
"flow map, multiline"].is_flow_ml1());
5143 CHECK(tree[
"flow seq, multiline"].is_flow_ml1());
5145 CHECK(tree[
"flow map, singleline"].is_flow());
5146 CHECK(tree[
"flow seq, singleline"].is_flow());
5147 CHECK(tree[
"flow map, multiline"].is_flow());
5148 CHECK(tree[
"flow seq, multiline"].is_flow());
5154 CHECK(tostr(tree) == yaml);
5165 " block key: block val\n"
5172 "'block map': {block key: block val}\n"
5178 CHECK(tostr(n) ==
""
5187 CHECK(tostr(n) ==
""
5188 "\"block seq\": [\n"
5189 " block val 1,block val 2,quoted\n"
5192 CHECK(tostr(n) ==
""
5193 "\"block seq\": [\n"
5194 " block val 1, block val 2, quoted\n"
5197 CHECK(tostr_opts(n, maxcols20) ==
""
5198 "\"block seq\": [\n"
5199 " block val 1, block val 2,\n"
5203 CHECK(tostr_opts(n, maxcols20) ==
""
5204 "\"block seq\": [\n"
5205 " block val 1,block val 2,\n"
5209 CHECK(tostr(n) ==
""
5210 "\"block seq\": [block val 1,block val 2,quoted]\n");
5212 CHECK(tostr(n) ==
""
5213 "\"block seq\": [block val 1, block val 2, quoted]\n");
5215 CHECK(tostr(n) ==
""
5216 "\"block seq\": [\n"
5227 CHECK(tostr(n) ==
"flow map, singleline: {flow key: flow val}\n");
5230 CHECK(tostr(n) ==
""
5231 "flow map, singleline:\n"
5239 CHECK(tostr(n) ==
""
5240 "flow map, multiline: {\n"
5241 " flow key: flow val\n"
5245 CHECK(tostr(n) ==
""
5246 "flow map, multiline:\n"
5247 " flow key: flow val\n"
5253 CHECK(tostr(n) ==
"flow seq, singleline: [flow val,flow val]\n");
5258 CHECK(tostr(n) ==
""
5260 " flow seq, singleline\n"
5269 CHECK(tostr(n) ==
""
5270 "flow seq, multiline: [\n"
5276 CHECK(tostr(n) ==
"flow seq, multiline: [flow val,flow val]\n");
5279 CHECK(tostr(tree) != yaml);
5280 CHECK(tostr(tree) ==
5281 "'block map': {block key: block val}" "\n"
5282 "\"block seq\": [" "\n"
5283 " block val 1," "\n"
5284 " block val 2," "\n"
5287 "flow map, singleline:" "\n"
5288 " flow key: |-" "\n"
5291 " flow seq, singleline" "\n"
5293 " - 'flow val'" "\n"
5294 " - \"flow val\"" "\n"
5295 "flow map, multiline:" "\n"
5296 " flow key: flow val" "\n"
5297 "flow seq, multiline: [flow val,flow val]" "\n"
5302 CHECK(tostr(tree) ==
5304 " block key: block val" "\n"
5306 " - block val 1" "\n"
5307 " - block val 2" "\n"
5309 "flow map, singleline:" "\n"
5310 " flow key: |-" "\n"
5313 " flow seq, singleline" "\n"
5315 " - 'flow val'" "\n"
5316 " - \"flow val\"" "\n"
5317 "flow map, multiline:" "\n"
5318 " flow key: flow val" "\n"
5319 "flow seq, multiline: [flow val,flow val]" "\n"
5328 CHECK(tostr(tree) ==
5330 " block key: block val" "\n"
5332 " - block val 1" "\n"
5333 " - block val 2" "\n"
5335 "flow map, singleline:" "\n"
5336 " flow key: flow val" "\n"
5337 "flow seq, singleline:" "\n"
5340 "flow map, multiline:" "\n"
5341 " flow key: flow val" "\n"
5342 "flow seq, multiline:" "\n"
5353 CHECK(tostr(tree) ==
5355 " block key: block val" "\n"
5357 " - block val 1" "\n"
5358 " - block val 2" "\n"
5360 "flow map, singleline:" "\n"
5361 " flow key: flow val" "\n"
5362 "flow seq, singleline:" "\n"
5365 "flow map, multiline:" "\n"
5366 " flow key: flow val" "\n"
5367 "flow seq, multiline:" "\n"
5392 CHECK(tostr(tree) ==
""
5394 " 'block key': \"block val\"" "\n"
5395 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
5396 "'flow map, singleline':" "\n"
5397 " 'flow key': \"flow val\"" "\n"
5398 "'flow seq, singleline': [\"flow val\",\"flow val\"]" "\n"
5399 "'flow map, multiline':" "\n"
5400 " 'flow key': \"flow val\"" "\n"
5401 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
5408 CHECK(tostr(tree) ==
""
5410 " 'block key': \"block val\"" "\n"
5411 "'block seq': [\"block val 1\",\"block val 2\",\"quoted\"]" "\n"
5412 "'flow map, singleline':" "\n"
5413 " 'flow key': \"flow val\"" "\n"
5414 "'flow seq, singleline':" "\n"
5415 " - \"flow val\"" "\n"
5416 " - \"flow val\"" "\n"
5417 "'flow map, multiline':" "\n"
5418 " 'flow key': \"flow val\"" "\n"
5419 "'flow seq, multiline': [\"flow val\",\"flow val\"]" "\n"
5462 CHECK(tree[
"map"].is_flow_ml1());
5463 CHECK(tree[
"map"][
"seq"].is_flow_ml1());
5464 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
5466 CHECK(tostr(tree, emit_defaults) == yaml);
5468 CHECK(tostr_json(tree, emit_defaults) ==
5489 CHECK(tree[
"map"].is_flow_sl());
5491 CHECK(tostr(tree, emit_defaults) ==
5492 "{map: {seq: [0,1,2,3,[40,41]]}}");
5494 CHECK(tostr_json(tree, emit_defaults) ==
5495 "{\"map\": {\"seq\": [0,1,2,3,[40,41]]}}");
5500 CHECK(tostr(tree, with_spaces) ==
5501 "{map: {seq: [0, 1, 2, 3, [40, 41]]}}");
5503 CHECK(tostr_json(tree, with_spaces) ==
5504 "{\"map\": {\"seq\": [0, 1, 2, 3, [40, 41]]}}");
5513 CHECK(tree[
"map"].is_flow_mln());
5514 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
5515 CHECK(tostr(tree, emit_defaults) ==
5519 " 0,1,2,3,[40,41]" "\n"
5523 CHECK(tostr_json(tree, emit_defaults) ==
5527 " 0,1,2,3,[40,41]" "\n"
5534 CHECK(tostr(tree, with_spaces) ==
5538 " 0, 1, 2, 3, [40, 41]" "\n"
5542 CHECK(tostr_json(tree, with_spaces) ==
5546 " 0, 1, 2, 3, [40, 41]" "\n"
5557 CHECK(tree[
"map"].is_flow_ml1());
5558 CHECK(tree[
"map"][
"seq"][4].is_flow_sl());
5559 CHECK(tostr(tree, noindent) ==
""
5572 CHECK(tostr_json(tree, noindent) ==
""
5591 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9," "\n"
5592 " 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, " "\n"
5593 " 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, " "\n"
5594 " 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, " "\n"
5595 " 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, " "\n"
5596 " 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, " "\n"
5597 " 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, " "\n"
5598 " 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 " "\n"
5609 CHECK(tostr(tree, emit_defaults) ==
""
5611 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,\n"
5612 " 30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,\n"
5613 " 56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79\n"
5616 CHECK(tostr_json(tree, emit_defaults) ==
""
5618 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
5619 " 29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
5620 " 55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79\n"
5626 CHECK(tostr(tree, maxcols40) ==
""
5628 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
5629 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
5630 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
5631 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
5632 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
5633 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
5636 CHECK(tostr_json(tree, maxcols40) ==
""
5638 " 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n"
5639 " 16,17,18,19,20,21,22,23,24,25,26,27,28,\n"
5640 " 29,30,31,32,33,34,35,36,37,38,39,40,41,\n"
5641 " 42,43,44,45,46,47,48,49,50,51,52,53,54,\n"
5642 " 55,56,57,58,59,60,61,62,63,64,65,66,67,\n"
5643 " 68,69,70,71,72,73,74,75,76,77,78,79\n"
5650 CHECK(tostr(tree, with_spaces) ==
""
5652 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5653 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5654 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5655 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
5658 CHECK(tostr_json(tree, with_spaces) ==
""
5660 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5661 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5662 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5663 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79\n"
5670 CHECK(tostr(tree, maxcols40_spc) ==
""
5672 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
5673 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5674 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
5675 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5676 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
5677 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5678 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
5679 " 72, 73, 74, 75, 76, 77, 78, 79\n"
5682 CHECK(tostr_json(tree, maxcols40_spc) ==
""
5684 " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n"
5685 " 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n"
5686 " 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n"
5687 " 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,\n"
5688 " 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n"
5689 " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,\n"
5690 " 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\n"
5691 " 72, 73, 74, 75, 76, 77, 78, 79\n"
5699 CHECK(tostr(tree, maxcols40_spc_noindent) ==
""
5701 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
5702 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
5703 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
5704 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
5705 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
5706 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
5707 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
5708 "73, 74, 75, 76, 77, 78, 79\n"
5711 CHECK(tostr_json(tree, maxcols40_spc_noindent) ==
""
5713 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
5714 "13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
5715 "23, 24, 25, 26, 27, 28, 29, 30, 31, 32,\n"
5716 "33, 34, 35, 36, 37, 38, 39, 40, 41, 42,\n"
5717 "43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n"
5718 "53, 54, 55, 56, 57, 58, 59, 60, 61, 62,\n"
5719 "63, 64, 65, 66, 67, 68, 69, 70, 71, 72,\n"
5720 "73, 74, 75, 76, 77, 78, 79\n"
5739 ryml::csubstr yaml =
"{map: {seq: [0, 1, 2, 3, [40, 41]]}}";
5743 CHECK(tostr(tree, defaults) ==
"{map: {seq: [0,1,2,3,[40,41]]}}");
5750 CHECK(tostr(tree, defaults) ==
5768 CHECK(tostr(tree, noindent) ==
5787 CHECK(tostr(tree, noindent) ==
""
5803 CHECK(tostr(tree, noindent) ==
5829 " \"doe\": \"a deer, a female deer\"," "\n"
5830 " \"ray\": \"a drop of golden sun\"," "\n"
5831 " \"me\": \"a name, I call myself\"," "\n"
5832 " \"far\": \"a long long way to go\"" "\n"
5846 std::stringstream ss;
5848 CHECK(ss.str() == json);
5873 "\"doe\": \"a deer, a female deer\"" "\n"
5874 "\"ray\": \"a drop of golden sun\"" "\n"
5875 "\"me\": \"a name, I call myself\"" "\n"
5876 "\"far\": \"a long long way to go\"" "\n"
5883 "doe: a deer, a female deer" "\n"
5884 "ray: a drop of golden sun" "\n"
5885 "me: a name, I call myself" "\n"
5886 "far: a long long way to go" "\n"
5916 std::string unresolved =
""
5918 " name: Everyone has same name" "\n"
5925 "bill_to: &id001" "\n"
5927 " 123 Tornado Alley" "\n"
5929 " city: East Centerville" "\n"
5931 "ship_to: *id001" "\n"
5932 "&keyref key: &valref val" "\n"
5933 "*valref : *keyref" "\n"
5935 std::string resolved =
""
5937 " name: Everyone has same name" "\n"
5939 " name: Everyone has same name" "\n"
5942 " name: Everyone has same name" "\n"
5946 " 123 Tornado Alley" "\n"
5948 " city: East Centerville" "\n"
5952 " 123 Tornado Alley" "\n"
5954 " city: East Centerville" "\n"
5962 CHECK( ! tree[
"base"].has_key_anchor());
5963 CHECK( tree[
"base"].has_val_anchor());
5964 CHECK( tree[
"base"].val_anchor() ==
"base");
5965 CHECK( tree[
"key"].key_anchor() ==
"keyref");
5966 CHECK( tree[
"key"].val_anchor() ==
"valref");
5967 CHECK( tree[
"*valref"].is_key_ref());
5968 CHECK( tree[
"*valref"].is_val_ref());
5969 CHECK( tree[
"*valref"].key_ref() ==
"valref");
5970 CHECK( tree[
"*valref"].val_ref() ==
"keyref");
5977 CHECK( ! tree[
"base"].has_key_anchor());
5978 CHECK( ! tree[
"base"].has_val_anchor());
5979 CHECK( ! tree[
"base"].has_val_anchor());
5980 CHECK( ! tree[
"key"].has_key_anchor());
5981 CHECK( ! tree[
"key"].has_val_anchor());
5982 CHECK( ! tree[
"val"].is_key_ref());
5983 CHECK( ! tree[
"val"].is_val_ref());
5985 CHECK(tree[
"ship_to"][
"city"].val() ==
"East Centerville");
5986 CHECK(tree[
"ship_to"][
"state"].val() ==
"KS");
6004 t[
"nref"].
set_val(
"*vanchor");
6006 "&kanchor kanchor: 2" "\n"
6007 "vanchor: &vanchor 3" "\n"
6008 "kref: *kanchor" "\n"
6009 "vref: *vanchor" "\n"
6012 "nref: '*vanchor'" "\n"
6018 "kref: kanchor" "\n"
6021 "nref: '*vanchor'" "\n"
6028 "orig: &orig {foo: bar, baz: bat}" "\n"
6036 t[
"notref"][
"<<"].
set_val(
"*orig");
6038 "orig: &orig {foo: bar,baz: bat}" "\n"
6039 "copy: {<<: *orig}" "\n"
6040 "notcopy: {test: *orig,<<: *orig}" "\n"
6041 "notref: {<<: '*orig'}" "\n"
6045 "orig: {foo: bar,baz: bat}" "\n"
6046 "copy: {foo: bar,baz: bat}" "\n"
6047 "notcopy: {test: {foo: bar,baz: bat},foo: bar,baz: bat}" "\n"
6048 "notref: {<<: '*orig'}" "\n"
6055 "orig1: &orig1 {foo: bar}" "\n"
6056 "orig2: &orig2 {baz: bat}" "\n"
6057 "orig3: &orig3 {and: more}" "\n"
6066 "orig1: &orig1 {foo: bar}" "\n"
6067 "orig2: &orig2 {baz: bat}" "\n"
6068 "orig3: &orig3 {and: more}" "\n"
6069 "copy: {<<: [*orig1,*orig2,*orig3]}" "\n"
6073 "orig1: {foo: bar}" "\n"
6074 "orig2: {baz: bat}" "\n"
6075 "orig3: {and: more}" "\n"
6076 "copy: {foo: bar,baz: bat,and: more}" "\n");
6085 const std::string yaml =
""
6094 "--- !!str a b" "\n"
6095 "--- !!str 'a: b'" "\n"
6112 CHECK(doc.is_doc());
6114 CHECK(root[0].has_val_tag());
6115 CHECK(root[0].val_tag() ==
"!!map");
6116 CHECK(root[1].val_tag() ==
"!map");
6117 CHECK(root[2].val_tag() ==
"!!seq");
6118 CHECK(root[3].val_tag() ==
"!!str");
6119 CHECK(root[4].val_tag() ==
"!!str");
6120 CHECK(root[5][
"a"].has_key_tag());
6121 CHECK(root[5][
"a"].key_tag() ==
"!!str");
6122 CHECK(root[6].val_tag() ==
"!!set");
6123 CHECK(root[7].val_tag() ==
"!!set");
6124 CHECK(root[8].val_tag() ==
"!!seq");
6125 CHECK(root[8][0].val_tag() ==
"!!int");
6126 CHECK(root[8][1].val_tag() ==
"!!str");
6184 "--- !!str a b" "\n"
6185 "--- !!str 'a: b'" "\n"
6200 "--- !<tag:yaml.org,2002:map>" "\n"
6205 "--- !<tag:yaml.org,2002:seq>" "\n"
6208 "--- !<tag:yaml.org,2002:str> a b" "\n"
6209 "--- !<tag:yaml.org,2002:str> 'a: b'" "\n"
6211 "!<tag:yaml.org,2002:str> a: b" "\n"
6212 "--- !<tag:yaml.org,2002:set>" "\n"
6215 "--- !<tag:yaml.org,2002:set>" "\n"
6217 "--- !<tag:yaml.org,2002:seq>" "\n"
6218 "- !<tag:yaml.org,2002:int> 0" "\n"
6219 "- !<tag:yaml.org,2002:str> 1" "\n"
6228 const std::string yaml =
""
6229 "%TAG !m! !my-" "\n"
6230 "--- # Bulb here" "\n"
6231 "!m!light fluorescent" "\n"
6233 "%TAG !m! !meta-" "\n"
6234 "--- # Color here" "\n"
6235 "!m!light green" "\n"
6240 "%TAG !m! !my-" "\n"
6241 "--- !m!light fluorescent" "\n"
6243 "%TAG !m! !meta-" "\n"
6244 "--- !m!light green" "\n"
6251 "%TAG !m! !my-" "\n"
6252 "--- !<!my-light> fluorescent" "\n"
6254 "%TAG !m! !meta-" "\n"
6255 "--- !<!meta-light> green" "\n"
6262 "%TAG !m! !my-" "\n"
6263 "--- !<!my-light> fluorescent" "\n"
6265 "%TAG !m! !meta-" "\n"
6266 "--- !<!meta-light> green" "\n"
6302 CHECK(doc.is_doc());
6321 CHECK(stream[0].is_doc());
6322 CHECK(stream[0].is_map());
6323 CHECK(stream[0][
"a"].val() ==
"0");
6324 CHECK(stream[0][
"b"].val() ==
"1");
6333 CHECK(stream[1].is_doc());
6334 CHECK(stream[1].is_map());
6335 CHECK(stream[1][
"c"].val() ==
"2");
6336 CHECK(stream[1][
"d"].val() ==
"3");
6345 CHECK(stream[2].is_doc());
6346 CHECK(stream[2].is_seq());
6347 CHECK(stream[2][0].val() ==
"4");
6348 CHECK(stream[2][1].val() ==
"5");
6349 CHECK(stream[2][2].val() ==
"6");
6350 CHECK(stream[2][3].val() ==
"7");
6388 return ryml::emitrs_json<std::string>(err_tree, err_opts);
6392 const std::string expected_json[] = {
6451 ryml::Tree tree = ryml::parse_in_arena(
"errorhandler.yml",
"[a: b\n}");
6462 auto cause_basic_error = []{
6471#ifdef RYML_WITH_EXCEPTIONS_
6475 cause_basic_error();
6497 auto cause_parse_error = [&]{
6521 msg_ctx.append(s.
str, s.
len);
6523 CHECK(
ryml::to_csubstr(msg_ctx).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
6525 "file.yml:3: col=4 (12B): err:" "\n"
6531 "err: see region:" "\n"
6566 CHECK(errh.
saved_msg_full ==
"file.yml:3: col=4 (12B): ERROR: [basic] invalid character: '['");
6579#ifdef RYML_WITH_EXCEPTIONS_
6583 cause_parse_error();
6595 CHECK(msg ==
"invalid character: '['");
6600 auto dumpfn = [&full](
ryml::csubstr s) { full.append(s.str, s.len); };
6604 CHECK(
ryml::to_csubstr(full).begins_with(
"file.yml:3: col=4 (12B): ERROR: [parse] invalid character: '['"));
6606 "file.yml:3: col=4 (12B): err:" "\n"
6612 "err: see region:" "\n"
6625 cause_parse_error();
6651 tree[
"float"].load(&intval);
6680 tree[
"float"].load(&intval);
6692#ifdef RYML_WITH_EXCEPTIONS_
6704 tree[
"float"].
load(&intval);
6725 tree[
"float"].
load(&intval);
6762 "float: 123.456" "\n"
6766 auto cause_visit_error = [&]{
6768 tree[
"float"].
load(&intval);
6800 msg.append(s.
str, s.
len);
6801 }, ymlloc, ymlsrc,
"err", 3);
6803 "file.yml:3: col=0 (24B): err:" "\n"
6805 "err: float: 123.456" "\n"
6809 "err: see region:" "\n"
6811 "err: foo: bar" "\n"
6814 "err: float: 123.456" "\n"
6855 uintptr_t uptr = (uintptr_t)ptr;
6856 const uintptr_t align =
alignof(max_align_t);
6859 uintptr_t prev = uptr - (uptr % align);
6860 uintptr_t next = prev + align;
6861 uintptr_t corr = next - uptr;
6862 ptr = (
void*)(((
char*)ptr) + corr);
6866 "out of memory! requested=%zu+%zu available=%zu\n",
6892 static void s_free(
void *mem,
size_t len,
void *this_)
6964 parse_in_arena(&parser,
"", R
"([a, b, c, d, {foo: bar, money: pennys}])", &tree);
7007 std::cerr <<
"out of memory! requested=" <<
alloc_size <<
" vs " <<
memory_pool.size() <<
" available" << std::endl;
7093 CHECK(tree["doe"].val() ==
"a deer, a female deer");
7106static int num_checks = 0;
7107static int num_failed_checks = 0;
7108static bool quiet_mode =
false;
7113 auto arg_matches = [](
const char *arg,
const char *shortform,
const char *longform) {
7114 return (0 == strcmp(arg, shortform) || 0 == strcmp(arg, longform));
7116 for(
int i = 1; i < argc; ++i)
7117 if(arg_matches(argv[i],
"-q",
"--quiet"))
7124 const char *msg = predicate ?
"OK! " :
"OK!";
7127 ++num_failed_checks;
7128 msg = predicate ?
"FAIL: " :
"FAIL";
7130 if(!result || !quiet_mode)
7132 std::cout << __FILE__ <<
':' << line <<
": " << msg << (predicate ? predicate :
"") << std::endl;
7140 std::cout <<
"Completed " << num_checks <<
" checks." << std::endl;
7141 if(num_failed_checks)
7142 std::cout <<
"ERROR: " << num_failed_checks <<
'/' << num_checks <<
" checks failed." << std::endl;
7144 std::cout <<
"SUCCESS!" << std::endl;
7145 return num_failed_checks;
7160 fwrite(s.
str, 1, s.
len, stderr);
7166 fputc(
'\n', stderr);
7181 .set_free([](
void* mem,
size_t,
void *){
7219#ifdef RYML_NO_DEFAULT_CALLBACKS
7228#ifndef C4_EXCEPTIONS
7252 RYML_SAVE_TEST_EXPFAIL_();
7260 bool got_error =
false;
7261 #ifdef C4_EXCEPTIONS
7264 std::forward<Fn>(fn)();
7266 catch(std::exception
const&)
7273 std::forward<Fn>(fn)();
7286[[noreturn]]
void stopexec(std::string
const& s)
7288 #ifdef C4_EXCEPTIONS
7289 throw std::runtime_error(s);
7413C4_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_user_container_types_brief()
serialize/deserialize container (map or seq) types: brief version
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)
void write(ryml::NodeRef &n, Inner const &inner)
serializes as a seq
ryml::ReadResult read(ryml::ConstNodeRef const &n, Inner *inner)
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