7 #if defined(RYML_SINGLE_HEADER)
8 #define RYML_SINGLE_HDR_DEFINE_NOW
9 #include <ryml_all.hpp>
10 #elif defined(RYML_SINGLE_HEADER_LIB)
11 #include <ryml_all.hpp>
126 C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
127 C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wcast-qual")
128 C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast")
129 C4_SUPPRESS_WARNING_GCC("-Wuseless-cast")
201 bool report_check(
int line,
const char *predicate,
bool result);
206 #if (defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
208 #define CHECK CheckPredicate{__FILE__, __LINE__}
209 struct CheckPredicate
213 void operator() (
bool predicate)
const
225 #define CHECK(predicate) do { if(!report_check(__LINE__, #predicate, (predicate))) { RYML_DEBUG_BREAK(); } } while(0)
229 #define CHECK(predicate) assert(predicate)
234 template<
class CharContainer> CharContainer
file_get_contents(
const char *filename);
235 template<
class CharContainer>
size_t file_get_contents(
const char *filename, CharContainer *v);
236 template<
class CharContainer>
void file_put_contents(
const char *filename, CharContainer
const& v,
const char* access=
"wb");
237 void file_put_contents(
const char *filename,
const char *buf,
size_t sz,
const char* access);
245 C4_NORETURN
void on_error(
const char* msg,
size_t len,
ryml::Location loc);
249 void check_effect(
bool committed)
const;
272 char yml_buf[] =
"{foo: 1, bar: [2, 3], john: doe}";
277 CHECK(bar[0].val() ==
"2");
278 CHECK(bar[1].val() ==
"3");
279 CHECK(bar[0].val().str == yml_buf + 15);
280 CHECK(bar[1].val().str == yml_buf + 18);
283 int bar0 = 0, bar1 = 0;
292 CHECK(bar[0].val() ==
"10");
293 CHECK(bar[1].val() ==
"11");
297 CHECK(bar[2].val() ==
"12");
301 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"({foo: 1,bar: [10,11,12],john: doe})");
308 CHECK(ryml::emitrs_yaml<std::string>(foo) ==
"foo: 1\n");
388 CHECK(tree[
"foo"].is_keyval());
389 CHECK(tree[
"foo"].val() ==
"1");
391 CHECK(tree[
"bar"].is_seq());
392 CHECK(tree[
"bar"].has_key());
395 CHECK(tree[
"bar"][0].val() ==
"2");
396 CHECK(tree[
"bar"][1].val() ==
"3");
397 CHECK(tree[
"john"].val() ==
"doe");
401 CHECK(tree[0].
id() == tree[
"foo"].
id());
402 CHECK(tree[1].
id() == tree[
"bar"].
id());
403 CHECK(tree[2].
id() == tree[
"john"].
id());
405 CHECK(tree[0].
id() == tree[
"foo"].
id());
406 CHECK(tree[1].
id() == tree[
"bar"].
id());
407 CHECK(tree[2].
id() == tree[
"john"].
id());
409 CHECK(bar[0].val() ==
"2");
410 CHECK(bar[1].val() ==
"3");
417 CHECK(tree[
"john"].
key() ==
"john");
422 CHECK(root[
"foo"].
id() == root[0].
id());
423 CHECK(root[
"bar"].
id() == root[1].
id());
424 CHECK(root[
"john"].
id() == root[2].
id());
478 ryml::csubstr expected_keys[] = {
"foo",
"bar",
"john"};
483 CHECK(child.key() == expected_keys[count++]);
489 CHECK(child.key() == expected_keys[count++]);
495 CHECK(tree.
key(child_id) == expected_keys[count++]);
504 CHECK(tree.
key(child_id) == expected_keys[count++]);
559 int foo = 0, bar0 = 0, bar1 = 0;
560 std::string john_str;
563 root[
"bar"][0] >> bar0;
564 root[
"bar"][1] >> bar1;
565 root[
"john"] >> john_str;
570 CHECK(john_str ==
"doe");
571 CHECK(bar_str ==
"bar");
588 wroot[
"foo"] =
"says you";
589 wroot[
"bar"][0] =
"-2";
590 wroot[
"bar"][1] =
"-3";
591 wroot[
"john"] =
"ron";
595 CHECK(root[
"foo"].val() ==
"says you");
596 CHECK(root[
"bar"][0].val() ==
"-2");
597 CHECK(root[
"bar"][1].val() ==
"-3");
598 CHECK(root[
"john"].val() ==
"ron");
613 wroot[
"foo"] <<
"says who";
614 wroot[
"bar"][0] << 20;
615 wroot[
"bar"][1] << 30;
616 wroot[
"john"] <<
"deere";
617 CHECK(root[
"foo"].val() ==
"says who");
618 CHECK(root[
"bar"][0].val() ==
"20");
619 CHECK(root[
"bar"][1].val() ==
"30");
620 CHECK(root[
"john"].val() ==
"deere");
624 std::string ok(
"in_scope");
628 CHECK(root[
"john"].val() ==
"in_scope");
630 wroot[
"float"] << 2.4;
634 CHECK(tree.
arena() ==
"says who2030deerein_scope2.42.400000");
642 wroot[
"newkeyval"] =
"shiny and new";
645 CHECK(root[
"newkeyval"].
key() ==
"newkeyval");
646 CHECK(root[
"newkeyval"].val() ==
"shiny and new");
647 CHECK(root[
"newkeyval (serialized)"].
key() ==
"newkeyval (serialized)");
648 CHECK(root[
"newkeyval (serialized)"].val() ==
"shiny and new (serialized)");
654 CHECK(root[
"bar"].num_children() == 2);
655 wroot[
"bar"][2] =
"oh so nice";
656 wroot[
"bar"][3] <<
"oh so nice (serialized)";
657 CHECK(root[
"bar"].num_children() == 4);
658 CHECK(root[
"bar"][2].val() ==
"oh so nice");
659 CHECK(root[
"bar"][3].val() ==
"oh so nice (serialized)");
665 CHECK(root[
"newseq"].num_children() == 0);
666 CHECK(root[
"newseq"].is_seq());
667 CHECK(root[
"newseq (serialized)"].num_children() == 0);
668 CHECK(root[
"newseq (serialized)"].is_seq());
674 CHECK(root[
"newmap"].num_children() == 0);
675 CHECK(root[
"newmap"].is_map());
676 CHECK(root[
"newmap (serialized)"].num_children() == 0);
677 CHECK(root[
"newmap (serialized)"].is_map());
705 nothing = wroot[
"I am nothing"];
720 something =
"indeed";
722 CHECK(root[
"I am something"].val() ==
"indeed");
753 CHECK(wbar[0].readable() && wbar[0].val() ==
"20");
754 CHECK( ! wbar[100].readable());
755 CHECK( ! wbar[100].readable() || wbar[100].val() ==
"100");
757 CHECK( ! wbar[0].is_seed() && wbar[0].val() ==
"20");
758 CHECK(wbar[100].is_seed() || wbar[100].val() ==
"100");
786 return seed_node.at(
"is").at(
"an").at(
"invalid").at(
"operation");
793 return seed_node[
"is"][
"an"][
"invalid"][
"operation"];
803 ryml::csubstr expected_result = R
"(foo: says who
804 bar: [20,30,oh so nice,oh so nice (serialized)]
808 newkeyval: shiny and new
809 newkeyval (serialized): shiny and new (serialized)
811 newseq (serialized): []
813 newmap (serialized): {}
814 I am something: indeed
820 std::stringstream ss;
822 std::string stream_result = ss.str();
824 std::string str_result = ryml::emitrs_yaml<std::string>(tree);
829 CHECK(buf_result == expected_result);
830 CHECK(str_result == expected_result);
831 CHECK(stream_result == expected_result);
847 CHECK(tree[
"bar"][0].val() ==
"21");
849 CHECK(tree[
"bar"][0].val() ==
"22");
855 constnoderef = noderef;
861 noderef = tree[
"bar"][0];
862 constnoderef = consttree[
"bar"][0];
866 CHECK(constnoderef == noderef);
867 CHECK(!(constnoderef != noderef));
892 fr: Planète (Gazeuse)
896 # UTF8 decoding only happens in double-quoted strings,
897 # as per the YAML standard
898 decode this: "\u263A \xE2\x98\xBA"
899 and this as well: "\u2705 \U0001D11E"
900 not decoded: '\u263A \xE2\x98\xBA'
901 neither this: '\u2705 \U0001D11E'
904 CHECK(langs[
"en"].val() ==
"Planet (Gas)");
905 CHECK(langs[
"fr"].val() ==
"Planète (Gazeuse)");
906 CHECK(langs[
"ru"].val() ==
"Планета (Газ)");
907 CHECK(langs[
"ja"].val() ==
"惑星(ガス)");
908 CHECK(langs[
"zh"].val() ==
"行星(气体)");
912 CHECK(langs[
"decode this"].val() ==
"☺ ☺");
913 CHECK(langs[
"and this as well"].val() ==
"✅ 𝄞");
914 CHECK(langs[
"not decoded"].val() ==
"\\u263A \\xE2\\x98\\xBA");
915 CHECK(langs[
"neither this"].val() ==
"\\u2705 \\U0001D11E");
943 const char foobar_str[] =
"foobar";
944 auto s = ryml::csubstr(foobar_str, strlen(foobar_str));
945 CHECK(s ==
"foobar");
946 CHECK(s.size() == 6);
947 CHECK(s.data() == foobar_str);
948 CHECK(s.size() == s.len);
949 CHECK(s.data() == s.str);
954 const char foobar_str[] =
"foobar";
955 ryml::csubstr s = foobar_str;
956 CHECK(s ==
"foobar");
957 CHECK(s !=
"foobar0");
958 CHECK(s.size() == 6);
959 CHECK(s.data() == foobar_str);
960 CHECK(s.size() == s.len);
961 CHECK(s.data() == s.str);
965 ryml::csubstr s =
"foobar";
966 CHECK(s ==
"foobar");
967 CHECK(s !=
"foobar0");
968 CHECK(s.size() == 6);
969 CHECK(s.size() == s.len);
970 CHECK(s.data() == s.str);
979 const char *foobar_str =
"foobar";
981 CHECK(s ==
"foobar");
982 CHECK(s !=
"foobar0");
983 CHECK(s.size() == 6);
984 CHECK(s.size() == s.len);
985 CHECK(s.data() == s.str);
996 std::string foobar_str =
"foobar";
998 CHECK(s ==
"foobar");
999 CHECK(s !=
"foobar0");
1000 CHECK(s.size() == 6);
1001 CHECK(s.size() == s.len);
1002 CHECK(s.data() == s.str);
1008 ryml::substr foo = buf;
1009 CHECK(foo.len == 3);
1010 CHECK(foo.data() == buf);
1011 ryml::csubstr cfoo = foo;
1012 CHECK(cfoo.data() == buf);
1021 char const foobar_str_ro[] =
"foobar";
1022 char foobar_str_rw[] =
"foobar";
1023 static_assert(std::is_array<decltype(foobar_str_ro)>::value,
"this is an array");
1024 static_assert(std::is_array<decltype(foobar_str_rw)>::value,
"this is an array");
1027 ryml::csubstr foobar = foobar_str_ro;
1028 CHECK(foobar.data() == foobar_str_ro);
1029 CHECK(foobar.size() == strlen(foobar_str_ro));
1030 CHECK(foobar ==
"foobar");
1034 ryml::csubstr foobar = foobar_str_rw;
1035 CHECK(foobar.data() == foobar_str_rw);
1036 CHECK(foobar.size() == strlen(foobar_str_rw));
1037 CHECK(foobar ==
"foobar");
1041 ryml::substr foobar = foobar_str_rw;
1042 CHECK(foobar.data() == foobar_str_rw);
1043 CHECK(foobar.size() == strlen(foobar_str_rw));
1044 CHECK(foobar ==
"foobar");
1055 char const* foobar_str_ro =
"foobar";
1056 char foobar_str_rw_[] =
"foobar";
1057 char * foobar_str_rw = foobar_str_rw_;
1058 static_assert(!std::is_array<decltype(foobar_str_ro)>::value,
"this is a decayed pointer");
1059 static_assert(!std::is_array<decltype(foobar_str_rw)>::value,
"this is a decayed pointer");
1064 CHECK(foobar.data() == foobar_str_ro);
1065 CHECK(foobar.size() == strlen(foobar_str_ro));
1066 CHECK(foobar ==
"foobar");
1071 CHECK(foobar.data() == foobar_str_rw);
1072 CHECK(foobar.size() == strlen(foobar_str_rw));
1073 CHECK(foobar ==
"foobar");
1078 CHECK(foobar.data() == foobar_str_rw);
1079 CHECK(foobar.size() == strlen(foobar_str_rw));
1080 CHECK(foobar ==
"foobar");
1090 char buf[] =
"foobar";
1091 ryml::substr foobar = buf;
1092 CHECK(foobar ==
"foobar");
1093 foobar[0] =
'F';
CHECK(foobar ==
"Foobar");
1094 foobar.back() =
'R';
CHECK(foobar ==
"FoobaR");
1095 foobar.reverse();
CHECK(foobar ==
"RabooF");
1096 foobar.reverse();
CHECK(foobar ==
"FoobaR");
1097 foobar.reverse_sub(1, 4);
CHECK(foobar ==
"FabooR");
1098 foobar.reverse_sub(1, 4);
CHECK(foobar ==
"FoobaR");
1099 foobar.reverse_range(2, 5);
CHECK(foobar ==
"FoaboR");
1100 foobar.reverse_range(2, 5);
CHECK(foobar ==
"FoobaR");
1101 foobar.replace(
'o',
'0');
CHECK(foobar ==
"F00baR");
1102 foobar.replace(
'a',
'_');
CHECK(foobar ==
"F00b_R");
1103 foobar.replace(
"_0b",
'a');
CHECK(foobar ==
"FaaaaR");
1104 foobar.toupper();
CHECK(foobar ==
"FAAAAR");
1105 foobar.tolower();
CHECK(foobar ==
"faaaar");
1106 foobar.fill(
'.');
CHECK(foobar ==
"......");
1114 ryml::csubstr s =
"fooFOObarBAR";
1115 CHECK(s.len == 12u);
1117 CHECK(s.sub(0) ==
"fooFOObarBAR");
1118 CHECK(s.sub(0, 12) ==
"fooFOObarBAR");
1119 CHECK(s.sub(0, 3) ==
"foo" );
1120 CHECK(s.sub(3) ==
"FOObarBAR");
1121 CHECK(s.sub(3, 3) ==
"FOO" );
1122 CHECK(s.sub(6) ==
"barBAR");
1123 CHECK(s.sub(6, 3) ==
"bar" );
1124 CHECK(s.sub(9) ==
"BAR");
1125 CHECK(s.sub(9, 3) ==
"BAR");
1127 CHECK(s.first(0) ==
"" );
1128 CHECK(s.first(1) ==
"f" );
1129 CHECK(s.first(2) !=
"f" );
1130 CHECK(s.first(2) ==
"fo" );
1131 CHECK(s.first(3) ==
"foo");
1133 CHECK(s.last(0) ==
"");
1134 CHECK(s.last(1) ==
"R");
1135 CHECK(s.last(2) ==
"AR");
1136 CHECK(s.last(3) ==
"BAR");
1138 CHECK(s.range(0, 12) ==
"fooFOObarBAR");
1139 CHECK(s.range(1, 12) ==
"ooFOObarBAR");
1140 CHECK(s.range(1, 11) ==
"ooFOObarBA" );
1141 CHECK(s.range(2, 10) ==
"oFOObarB" );
1142 CHECK(s.range(3, 9) ==
"FOObar" );
1144 CHECK(s.offs(0, 0) ==
"fooFOObarBAR");
1145 CHECK(s.offs(1, 0) ==
"ooFOObarBAR");
1146 CHECK(s.offs(1, 1) ==
"ooFOObarBA" );
1147 CHECK(s.offs(2, 1) ==
"oFOObarBA" );
1148 CHECK(s.offs(2, 2) ==
"oFOObarB" );
1149 CHECK(s.offs(3, 3) ==
"FOObar" );
1151 CHECK(s.right_of(0,
true) ==
"fooFOObarBAR");
1152 CHECK(s.right_of(0,
false) ==
"ooFOObarBAR");
1153 CHECK(s.right_of(1,
true) ==
"ooFOObarBAR");
1154 CHECK(s.right_of(1,
false) ==
"oFOObarBAR");
1155 CHECK(s.right_of(2,
true) ==
"oFOObarBAR");
1156 CHECK(s.right_of(2,
false) ==
"FOObarBAR");
1157 CHECK(s.right_of(3,
true) ==
"FOObarBAR");
1158 CHECK(s.right_of(3,
false) ==
"OObarBAR");
1160 CHECK(s.left_of(12,
false) ==
"fooFOObarBAR");
1161 CHECK(s.left_of(11,
true) ==
"fooFOObarBAR");
1162 CHECK(s.left_of(11,
false) ==
"fooFOObarBA" );
1163 CHECK(s.left_of(10,
true) ==
"fooFOObarBA" );
1164 CHECK(s.left_of(10,
false) ==
"fooFOObarB" );
1165 CHECK(s.left_of( 9,
true) ==
"fooFOObarB" );
1166 CHECK(s.left_of( 9,
false) ==
"fooFOObar" );
1168 ryml::csubstr FOO = s.sub(3, 3);
1169 CHECK(s.is_super(FOO));
1170 CHECK(s.left_of(FOO) ==
"foo");
1171 CHECK(s.right_of(FOO) ==
"barBAR");
1176 ryml::csubstr s =
"some substring";
1177 ryml::csubstr some = s.first(4);
1178 CHECK(some ==
"some");
1179 CHECK(s ==
"some substring");
1182 char result[32] = {0};
1183 std::snprintf(result,
sizeof(result),
"%.*s", (
int)some.len, some.str);
1184 printf(
"~~~%s~~~\n", result);
1194 char result[32] = {0};
1195 std::snprintf(result,
sizeof(result),
"%s", some.str);
1203 ryml::csubstr s =
"some substring";
1204 ryml::csubstr some = s.first(4);
1205 CHECK(some ==
"some");
1206 CHECK(s ==
"some substring");
1209 std::stringstream ss;
1211 CHECK(ss.str() ==
"some substring");
1212 CHECK(ss.str() == s);
1220 std::stringstream ss;
1222 CHECK(ss.str() ==
"some substring");
1223 CHECK(ss.str() == s);
1227 std::stringstream ss;
1229 CHECK(ss.str() ==
"some substring");
1230 CHECK(ss.str() == s);
1234 std::stringstream ss;
1236 CHECK(ss.str() ==
"some");
1237 CHECK(ss.str() == some);
1243 ryml::csubstr foobar =
"foobar";
1244 ryml::csubstr foo = foobar.first(3);
1245 CHECK(foo.is_sub(foobar));
1246 CHECK(foo.is_sub(foo));
1247 CHECK(!foo.is_super(foobar));
1248 CHECK(!foobar.is_sub(foo));
1250 CHECK(foo.is_super(foo));
1251 CHECK(foo.is_sub(foo));
1252 CHECK(foobar.is_sub(foobar));
1253 CHECK(foobar.is_super(foobar));
1258 ryml::csubstr foobar =
"foobar";
1259 ryml::csubstr foo = foobar.first(3);
1260 ryml::csubstr oba = foobar.offs(2, 1);
1261 ryml::csubstr abc =
"abc";
1262 CHECK(foobar.overlaps(foo));
1263 CHECK(foobar.overlaps(oba));
1264 CHECK(foo.overlaps(foobar));
1265 CHECK(foo.overlaps(oba));
1266 CHECK(!foo.overlaps(abc));
1267 CHECK(!abc.overlaps(foo));
1274 CHECK(ryml::csubstr(
" \t\n\rcontents without whitespace\t \n\r").trim(
"\t \n\r") ==
"contents without whitespace");
1275 ryml::csubstr aaabbb =
"aaabbb";
1276 ryml::csubstr aaa___bbb =
"aaa___bbb";
1278 CHECK(aaabbb.triml(
'a') == aaabbb.last(3));
1279 CHECK(aaabbb.trimr(
'a') == aaabbb);
1280 CHECK(aaabbb.trim (
'a') == aaabbb.last(3));
1281 CHECK(aaabbb.triml(
'b') == aaabbb);
1282 CHECK(aaabbb.trimr(
'b') == aaabbb.first(3));
1283 CHECK(aaabbb.trim (
'b') == aaabbb.first(3));
1284 CHECK(aaabbb.triml(
'c') == aaabbb);
1285 CHECK(aaabbb.trimr(
'c') == aaabbb);
1286 CHECK(aaabbb.trim (
'c') == aaabbb);
1287 CHECK(aaa___bbb.triml(
'a') == aaa___bbb.last(6));
1288 CHECK(aaa___bbb.trimr(
'a') == aaa___bbb);
1289 CHECK(aaa___bbb.trim (
'a') == aaa___bbb.last(6));
1290 CHECK(aaa___bbb.triml(
'b') == aaa___bbb);
1291 CHECK(aaa___bbb.trimr(
'b') == aaa___bbb.first(6));
1292 CHECK(aaa___bbb.trim (
'b') == aaa___bbb.first(6));
1293 CHECK(aaa___bbb.triml(
'c') == aaa___bbb);
1294 CHECK(aaa___bbb.trimr(
'c') == aaa___bbb);
1295 CHECK(aaa___bbb.trim (
'c') == aaa___bbb);
1297 CHECK(aaabbb.triml(
"ab") ==
"");
1298 CHECK(aaabbb.trimr(
"ab") ==
"");
1299 CHECK(aaabbb.trim (
"ab") ==
"");
1300 CHECK(aaabbb.triml(
"ba") ==
"");
1301 CHECK(aaabbb.trimr(
"ba") ==
"");
1302 CHECK(aaabbb.trim (
"ba") ==
"");
1303 CHECK(aaabbb.triml(
"cd") == aaabbb);
1304 CHECK(aaabbb.trimr(
"cd") == aaabbb);
1305 CHECK(aaabbb.trim (
"cd") == aaabbb);
1306 CHECK(aaa___bbb.triml(
"ab") == aaa___bbb.last(6));
1307 CHECK(aaa___bbb.triml(
"ba") == aaa___bbb.last(6));
1308 CHECK(aaa___bbb.triml(
"cd") == aaa___bbb);
1309 CHECK(aaa___bbb.trimr(
"ab") == aaa___bbb.first(6));
1310 CHECK(aaa___bbb.trimr(
"ba") == aaa___bbb.first(6));
1311 CHECK(aaa___bbb.trimr(
"cd") == aaa___bbb);
1312 CHECK(aaa___bbb.trim (
"ab") == aaa___bbb.range(3, 6));
1313 CHECK(aaa___bbb.trim (
"ba") == aaa___bbb.range(3, 6));
1314 CHECK(aaa___bbb.trim (
"cd") == aaa___bbb);
1319 CHECK(ryml::csubstr(R
"('this is is single quoted')").unquoted() == "this is is single quoted");
1320 CHECK(ryml::csubstr(R
"("this is is double quoted")").unquoted() == "this is is double quoted");
1326 ryml::csubstr abc___cba =
"abc___cba";
1327 ryml::csubstr abc___abc =
"abc___abc";
1328 CHECK(abc___cba.stripl(
"abc") == abc___cba.last(6));
1329 CHECK(abc___cba.stripr(
"abc") == abc___cba);
1330 CHECK(abc___cba.stripl(
"ab") == abc___cba.last(7));
1331 CHECK(abc___cba.stripr(
"ab") == abc___cba);
1332 CHECK(abc___cba.stripl(
"a") == abc___cba.last(8));
1333 CHECK(abc___cba.stripr(
"a") == abc___cba.first(8));
1334 CHECK(abc___abc.stripl(
"abc") == abc___abc.last(6));
1335 CHECK(abc___abc.stripr(
"abc") == abc___abc.first(6));
1336 CHECK(abc___abc.stripl(
"ab") == abc___abc.last(7));
1337 CHECK(abc___abc.stripr(
"ab") == abc___abc);
1338 CHECK(abc___abc.stripl(
"a") == abc___abc.last(8));
1339 CHECK(abc___abc.stripr(
"a") == abc___abc);
1345 ryml::csubstr s =
"foobar123";
1347 CHECK(s.begins_with(
'f'));
1348 CHECK(s.ends_with(
'3'));
1349 CHECK(!s.ends_with(
'2'));
1350 CHECK(!s.ends_with(
'o'));
1352 CHECK(s.begins_with(
"foobar"));
1353 CHECK(s.begins_with(
"foo"));
1354 CHECK(s.begins_with_any(
"foo"));
1355 CHECK(!s.begins_with(
"oof"));
1356 CHECK(s.begins_with_any(
"oof"));
1357 CHECK(s.ends_with(
"23"));
1358 CHECK(s.ends_with(
"123"));
1359 CHECK(s.ends_with_any(
"123"));
1360 CHECK(!s.ends_with(
"321"));
1361 CHECK(s.ends_with_any(
"231"));
1366 ryml::csubstr s =
"0123456789";
1367 CHECK(s.select(
'0') == s.sub(0, 1));
1368 CHECK(s.select(
'1') == s.sub(1, 1));
1369 CHECK(s.select(
'2') == s.sub(2, 1));
1370 CHECK(s.select(
'8') == s.sub(8, 1));
1371 CHECK(s.select(
'9') == s.sub(9, 1));
1372 CHECK(s.select(
"0123") == s.range(0, 4));
1373 CHECK(s.select(
"012" ) == s.range(0, 3));
1374 CHECK(s.select(
"01" ) == s.range(0, 2));
1375 CHECK(s.select(
"0" ) == s.range(0, 1));
1376 CHECK(s.select(
"123") == s.range(1, 4));
1377 CHECK(s.select(
"23") == s.range(2, 4));
1378 CHECK(s.select(
"3") == s.range(3, 4));
1383 ryml::csubstr s012345 =
"012345";
1386 CHECK(s012345.find(
'0' ) == 0u);
1388 CHECK(s012345.find(
'1' ) == 1u);
1390 CHECK(s012345.find(
'2' ) == 2u);
1392 CHECK(s012345.find(
'3' ) == 3u);
1396 CHECK(s012345.find(
"01" ) == 0u);
1398 CHECK(s012345.find(
"12" ) == 1u);
1400 CHECK(s012345.find(
"23" ) == 2u);
1406 ryml::csubstr buf =
"00110022003300440055";
1407 CHECK(buf.count(
'1' ) == 2u);
1408 CHECK(buf.count(
'1', 0u) == 2u);
1409 CHECK(buf.count(
'1', 1u) == 2u);
1410 CHECK(buf.count(
'1', 2u) == 2u);
1411 CHECK(buf.count(
'1', 3u) == 1u);
1412 CHECK(buf.count(
'1', 4u) == 0u);
1413 CHECK(buf.count(
'1', 5u) == 0u);
1414 CHECK(buf.count(
'0' ) == 10u);
1415 CHECK(buf.count(
'0', 0u) == 10u);
1416 CHECK(buf.count(
'0', 1u) == 9u);
1417 CHECK(buf.count(
'0', 2u) == 8u);
1418 CHECK(buf.count(
'0', 3u) == 8u);
1419 CHECK(buf.count(
'0', 4u) == 8u);
1420 CHECK(buf.count(
'0', 5u) == 7u);
1421 CHECK(buf.count(
'0', 6u) == 6u);
1422 CHECK(buf.count(
'0', 7u) == 6u);
1423 CHECK(buf.count(
'0', 8u) == 6u);
1424 CHECK(buf.count(
'0', 9u) == 5u);
1425 CHECK(buf.count(
'0', 10u) == 4u);
1426 CHECK(buf.count(
'0', 11u) == 4u);
1427 CHECK(buf.count(
'0', 12u) == 4u);
1428 CHECK(buf.count(
'0', 13u) == 3u);
1429 CHECK(buf.count(
'0', 14u) == 2u);
1430 CHECK(buf.count(
'0', 15u) == 2u);
1431 CHECK(buf.count(
'0', 16u) == 2u);
1432 CHECK(buf.count(
'0', 17u) == 1u);
1433 CHECK(buf.count(
'0', 18u) == 0u);
1434 CHECK(buf.count(
'0', 19u) == 0u);
1435 CHECK(buf.count(
'0', 20u) == 0u);
1440 ryml::csubstr s012345 =
"012345";
1443 CHECK(s012345.first_of(
'0') == 0u);
1444 CHECK(s012345.first_of(
"0") == 0u);
1445 CHECK(s012345.first_of(
"01") == 0u);
1446 CHECK(s012345.first_of(
"10") == 0u);
1447 CHECK(s012345.first_of(
"012") == 0u);
1448 CHECK(s012345.first_of(
"210") == 0u);
1449 CHECK(s012345.first_of(
"0123") == 0u);
1450 CHECK(s012345.first_of(
"3210") == 0u);
1451 CHECK(s012345.first_of(
"01234") == 0u);
1452 CHECK(s012345.first_of(
"43210") == 0u);
1453 CHECK(s012345.first_of(
"012345") == 0u);
1454 CHECK(s012345.first_of(
"543210") == 0u);
1455 CHECK(s012345.first_of(
'5') == 5u);
1456 CHECK(s012345.first_of(
"5") == 5u);
1457 CHECK(s012345.first_of(
"45") == 4u);
1458 CHECK(s012345.first_of(
"54") == 4u);
1459 CHECK(s012345.first_of(
"345") == 3u);
1460 CHECK(s012345.first_of(
"543") == 3u);
1461 CHECK(s012345.first_of(
"2345") == 2u);
1462 CHECK(s012345.first_of(
"5432") == 2u);
1463 CHECK(s012345.first_of(
"12345") == 1u);
1464 CHECK(s012345.first_of(
"54321") == 1u);
1465 CHECK(s012345.first_of(
"012345") == 0u);
1466 CHECK(s012345.first_of(
"543210") == 0u);
1473 CHECK(s012345.last_of(
'0') == 0u);
1474 CHECK(s012345.last_of(
"0") == 0u);
1475 CHECK(s012345.last_of(
"01") == 1u);
1476 CHECK(s012345.last_of(
"10") == 1u);
1477 CHECK(s012345.last_of(
"012") == 2u);
1478 CHECK(s012345.last_of(
"210") == 2u);
1479 CHECK(s012345.last_of(
"0123") == 3u);
1480 CHECK(s012345.last_of(
"3210") == 3u);
1481 CHECK(s012345.last_of(
"01234") == 4u);
1482 CHECK(s012345.last_of(
"43210") == 4u);
1483 CHECK(s012345.last_of(
"012345") == 5u);
1484 CHECK(s012345.last_of(
"543210") == 5u);
1485 CHECK(s012345.last_of(
'5') == 5u);
1486 CHECK(s012345.last_of(
"5") == 5u);
1487 CHECK(s012345.last_of(
"45") == 5u);
1488 CHECK(s012345.last_of(
"54") == 5u);
1489 CHECK(s012345.last_of(
"345") == 5u);
1490 CHECK(s012345.last_of(
"543") == 5u);
1491 CHECK(s012345.last_of(
"2345") == 5u);
1492 CHECK(s012345.last_of(
"5432") == 5u);
1493 CHECK(s012345.last_of(
"12345") == 5u);
1494 CHECK(s012345.last_of(
"54321") == 5u);
1495 CHECK(s012345.last_of(
"012345") == 5u);
1496 CHECK(s012345.last_of(
"543210") == 5u);
1497 CHECK(s012345.last_of(
'0', 6u) == 0u);
1498 CHECK(s012345.last_of(
'5', 6u) == 5u);
1499 CHECK(s012345.last_of(
"012345", 6u) == 5u);
1504 ryml::csubstr s012345 =
"012345";
1505 CHECK(s012345.first_not_of(
'a') == 0u);
1506 CHECK(s012345.first_not_of(
"ab") == 0u);
1507 CHECK(s012345.first_not_of(
'0') == 1u);
1508 CHECK(s012345.first_not_of(
"0") == 1u);
1509 CHECK(s012345.first_not_of(
"01") == 2u);
1510 CHECK(s012345.first_not_of(
"10") == 2u);
1511 CHECK(s012345.first_not_of(
"012") == 3u);
1512 CHECK(s012345.first_not_of(
"210") == 3u);
1513 CHECK(s012345.first_not_of(
"0123") == 4u);
1514 CHECK(s012345.first_not_of(
"3210") == 4u);
1515 CHECK(s012345.first_not_of(
"01234") == 5u);
1516 CHECK(s012345.first_not_of(
"43210") == 5u);
1519 CHECK(s012345.first_not_of(
'5') == 0u);
1520 CHECK(s012345.first_not_of(
"5") == 0u);
1521 CHECK(s012345.first_not_of(
"45") == 0u);
1522 CHECK(s012345.first_not_of(
"54") == 0u);
1523 CHECK(s012345.first_not_of(
"345") == 0u);
1524 CHECK(s012345.first_not_of(
"543") == 0u);
1525 CHECK(s012345.first_not_of(
"2345") == 0u);
1526 CHECK(s012345.first_not_of(
"5432") == 0u);
1527 CHECK(s012345.first_not_of(
"12345") == 0u);
1528 CHECK(s012345.first_not_of(
"54321") == 0u);
1531 CHECK(s012345.last_not_of(
'a') == 5u);
1532 CHECK(s012345.last_not_of(
"ab") == 5u);
1533 CHECK(s012345.last_not_of(
'5') == 4u);
1534 CHECK(s012345.last_not_of(
"5") == 4u);
1535 CHECK(s012345.last_not_of(
"45") == 3u);
1536 CHECK(s012345.last_not_of(
"54") == 3u);
1537 CHECK(s012345.last_not_of(
"345") == 2u);
1538 CHECK(s012345.last_not_of(
"543") == 2u);
1539 CHECK(s012345.last_not_of(
"2345") == 1u);
1540 CHECK(s012345.last_not_of(
"5432") == 1u);
1541 CHECK(s012345.last_not_of(
"12345") == 0u);
1542 CHECK(s012345.last_not_of(
"54321") == 0u);
1545 CHECK(s012345.last_not_of(
'0') == 5u);
1546 CHECK(s012345.last_not_of(
"0") == 5u);
1547 CHECK(s012345.last_not_of(
"01") == 5u);
1548 CHECK(s012345.last_not_of(
"10") == 5u);
1549 CHECK(s012345.last_not_of(
"012") == 5u);
1550 CHECK(s012345.last_not_of(
"210") == 5u);
1551 CHECK(s012345.last_not_of(
"0123") == 5u);
1552 CHECK(s012345.last_not_of(
"3210") == 5u);
1553 CHECK(s012345.last_not_of(
"01234") == 5u);
1554 CHECK(s012345.last_not_of(
"43210") == 5u);
1561 CHECK(ryml::csubstr(
"foo bar").first_non_empty_span() ==
"foo");
1562 CHECK(ryml::csubstr(
" foo bar").first_non_empty_span() ==
"foo");
1563 CHECK(ryml::csubstr(
"\n \r \t foo bar").first_non_empty_span() ==
"foo");
1564 CHECK(ryml::csubstr(
"\n \r \t foo\n\r\t bar").first_non_empty_span() ==
"foo");
1565 CHECK(ryml::csubstr(
"\n \r \t foo\n\r\t bar").first_non_empty_span() ==
"foo");
1566 CHECK(ryml::csubstr(
",\n \r \t foo\n\r\t bar").first_non_empty_span() ==
",");
1570 CHECK(ryml::csubstr(
"1234 asdkjh").first_uint_span() ==
"1234");
1571 CHECK(ryml::csubstr(
"1234\rasdkjh").first_uint_span() ==
"1234");
1572 CHECK(ryml::csubstr(
"1234\tasdkjh").first_uint_span() ==
"1234");
1573 CHECK(ryml::csubstr(
"1234\nasdkjh").first_uint_span() ==
"1234");
1574 CHECK(ryml::csubstr(
"1234]asdkjh").first_uint_span() ==
"1234");
1575 CHECK(ryml::csubstr(
"1234)asdkjh").first_uint_span() ==
"1234");
1576 CHECK(ryml::csubstr(
"1234gasdkjh").first_uint_span() ==
"");
1580 CHECK(ryml::csubstr(
"-1234 asdkjh").first_int_span() ==
"-1234");
1581 CHECK(ryml::csubstr(
"-1234\rasdkjh").first_int_span() ==
"-1234");
1582 CHECK(ryml::csubstr(
"-1234\tasdkjh").first_int_span() ==
"-1234");
1583 CHECK(ryml::csubstr(
"-1234\nasdkjh").first_int_span() ==
"-1234");
1584 CHECK(ryml::csubstr(
"-1234]asdkjh").first_int_span() ==
"-1234");
1585 CHECK(ryml::csubstr(
"-1234)asdkjh").first_int_span() ==
"-1234");
1586 CHECK(ryml::csubstr(
"-1234gasdkjh").first_int_span() ==
"");
1590 CHECK(ryml::csubstr(
"-1234 asdkjh").first_real_span() ==
"-1234");
1591 CHECK(ryml::csubstr(
"-1234\rasdkjh").first_real_span() ==
"-1234");
1592 CHECK(ryml::csubstr(
"-1234\tasdkjh").first_real_span() ==
"-1234");
1593 CHECK(ryml::csubstr(
"-1234\nasdkjh").first_real_span() ==
"-1234");
1594 CHECK(ryml::csubstr(
"-1234]asdkjh").first_real_span() ==
"-1234");
1595 CHECK(ryml::csubstr(
"-1234)asdkjh").first_real_span() ==
"-1234");
1596 CHECK(ryml::csubstr(
"-1234gasdkjh").first_real_span() ==
"");
1597 CHECK(ryml::csubstr(
"1.234 asdkjh").first_real_span() ==
"1.234");
1598 CHECK(ryml::csubstr(
"1.234e+5 asdkjh").first_real_span() ==
"1.234e+5");
1599 CHECK(ryml::csubstr(
"1.234e-5 asdkjh").first_real_span() ==
"1.234e-5");
1600 CHECK(ryml::csubstr(
"1.234 asdkjh").first_real_span() ==
"1.234");
1601 CHECK(ryml::csubstr(
"1.234e+5 asdkjh").first_real_span() ==
"1.234e+5");
1602 CHECK(ryml::csubstr(
"1.234e-5 asdkjh").first_real_span() ==
"1.234e-5");
1603 CHECK(ryml::csubstr(
"-1.234 asdkjh").first_real_span() ==
"-1.234");
1604 CHECK(ryml::csubstr(
"-1.234e+5 asdkjh").first_real_span() ==
"-1.234e+5");
1605 CHECK(ryml::csubstr(
"-1.234e-5 asdkjh").first_real_span() ==
"-1.234e-5");
1607 CHECK(ryml::csubstr(
"0x1.e8480p+19 asdkjh").first_real_span() ==
"0x1.e8480p+19");
1608 CHECK(ryml::csubstr(
"0x1.e8480p-19 asdkjh").first_real_span() ==
"0x1.e8480p-19");
1609 CHECK(ryml::csubstr(
"-0x1.e8480p+19 asdkjh").first_real_span() ==
"-0x1.e8480p+19");
1610 CHECK(ryml::csubstr(
"-0x1.e8480p-19 asdkjh").first_real_span() ==
"-0x1.e8480p-19");
1611 CHECK(ryml::csubstr(
"+0x1.e8480p+19 asdkjh").first_real_span() ==
"+0x1.e8480p+19");
1612 CHECK(ryml::csubstr(
"+0x1.e8480p-19 asdkjh").first_real_span() ==
"+0x1.e8480p-19");
1614 CHECK(ryml::csubstr(
"0b101.011p+19 asdkjh").first_real_span() ==
"0b101.011p+19");
1615 CHECK(ryml::csubstr(
"0b101.011p-19 asdkjh").first_real_span() ==
"0b101.011p-19");
1616 CHECK(ryml::csubstr(
"-0b101.011p+19 asdkjh").first_real_span() ==
"-0b101.011p+19");
1617 CHECK(ryml::csubstr(
"-0b101.011p-19 asdkjh").first_real_span() ==
"-0b101.011p-19");
1618 CHECK(ryml::csubstr(
"+0b101.011p+19 asdkjh").first_real_span() ==
"+0b101.011p+19");
1619 CHECK(ryml::csubstr(
"+0b101.011p-19 asdkjh").first_real_span() ==
"+0b101.011p-19");
1621 CHECK(ryml::csubstr(
"0o173.045p+19 asdkjh").first_real_span() ==
"0o173.045p+19");
1622 CHECK(ryml::csubstr(
"0o173.045p-19 asdkjh").first_real_span() ==
"0o173.045p-19");
1623 CHECK(ryml::csubstr(
"-0o173.045p+19 asdkjh").first_real_span() ==
"-0o173.045p+19");
1624 CHECK(ryml::csubstr(
"-0o173.045p-19 asdkjh").first_real_span() ==
"-0o173.045p-19");
1625 CHECK(ryml::csubstr(
"+0o173.045p+19 asdkjh").first_real_span() ==
"+0o173.045p+19");
1626 CHECK(ryml::csubstr(
"+0o173.045p-19 asdkjh").first_real_span() ==
"+0o173.045p-19");
1632 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").basename() ==
"file.tar.gz");
1633 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").dirname() ==
"/path/to/");
1634 CHECK(ryml::csubstr(
"C:\\path\\to\\file.tar.gz").basename(
'\\') ==
"file.tar.gz");
1635 CHECK(ryml::csubstr(
"C:\\path\\to\\file.tar.gz").dirname(
'\\') ==
"C:\\path\\to\\");
1636 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").extshort() ==
"gz");
1637 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").extlong() ==
"tar.gz");
1638 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extshort() ==
"/path/to/file.tar");
1639 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extlong() ==
"/path/to/file");
1644 using namespace ryml;
1645 csubstr parts[] = {
"aa",
"bb",
"cc",
"dd",
"ee",
"ff"};
1648 for(csubstr part : csubstr(
"aa/bb/cc/dd/ee/ff").split(
'/'))
1649 CHECK(part == parts[count++]);
1654 for(csubstr part : csubstr(
"aa.bb.cc.dd.ee.ff").split(
'.'))
1655 CHECK(part == parts[count++]);
1660 for(csubstr part : csubstr(
"aa-bb-cc-dd-ee-ff").split(
'-'))
1661 CHECK(part == parts[count++]);
1670 const bool skip_empty =
true;
1672 CHECK(ryml::csubstr(
"0/1/2" ). pop_left(
'/' ) ==
"0" );
1673 CHECK(ryml::csubstr(
"/0/1/2" ). pop_left(
'/' ) ==
"" );
1674 CHECK(ryml::csubstr(
"//0/1/2" ). pop_left(
'/' ) ==
"" );
1675 CHECK(ryml::csubstr(
"0/1/2" ). pop_left(
'/', skip_empty) ==
"0" );
1676 CHECK(ryml::csubstr(
"/0/1/2" ). pop_left(
'/', skip_empty) ==
"/0" );
1677 CHECK(ryml::csubstr(
"//0/1/2" ). pop_left(
'/', skip_empty) ==
"//0" );
1679 CHECK(ryml::csubstr(
"0/1/2" ).gpop_left(
'/' ) ==
"0/1" );
1680 CHECK(ryml::csubstr(
"/0/1/2" ).gpop_left(
'/' ) ==
"/0/1" );
1681 CHECK(ryml::csubstr(
"//0/1/2" ).gpop_left(
'/' ) ==
"//0/1" );
1682 CHECK(ryml::csubstr(
"0/1/2/" ).gpop_left(
'/' ) ==
"0/1/2");
1683 CHECK(ryml::csubstr(
"/0/1/2/" ).gpop_left(
'/' ) ==
"/0/1/2");
1684 CHECK(ryml::csubstr(
"//0/1/2/" ).gpop_left(
'/' ) ==
"//0/1/2");
1685 CHECK(ryml::csubstr(
"0/1/2//" ).gpop_left(
'/' ) ==
"0/1/2/");
1686 CHECK(ryml::csubstr(
"/0/1/2//" ).gpop_left(
'/' ) ==
"/0/1/2/");
1687 CHECK(ryml::csubstr(
"//0/1/2//" ).gpop_left(
'/' ) ==
"//0/1/2/");
1688 CHECK(ryml::csubstr(
"0/1/2" ).gpop_left(
'/', skip_empty) ==
"0/1" );
1689 CHECK(ryml::csubstr(
"/0/1/2" ).gpop_left(
'/', skip_empty) ==
"/0/1" );
1690 CHECK(ryml::csubstr(
"//0/1/2" ).gpop_left(
'/', skip_empty) ==
"//0/1" );
1691 CHECK(ryml::csubstr(
"0/1/2/" ).gpop_left(
'/', skip_empty) ==
"0/1" );
1692 CHECK(ryml::csubstr(
"/0/1/2/" ).gpop_left(
'/', skip_empty) ==
"/0/1" );
1693 CHECK(ryml::csubstr(
"//0/1/2/" ).gpop_left(
'/', skip_empty) ==
"//0/1" );
1694 CHECK(ryml::csubstr(
"0/1/2//" ).gpop_left(
'/', skip_empty) ==
"0/1" );
1695 CHECK(ryml::csubstr(
"/0/1/2//" ).gpop_left(
'/', skip_empty) ==
"/0/1" );
1696 CHECK(ryml::csubstr(
"//0/1/2//" ).gpop_left(
'/', skip_empty) ==
"//0/1" );
1698 CHECK(ryml::csubstr(
"0/1/2" ). pop_right(
'/' ) ==
"2" );
1699 CHECK(ryml::csubstr(
"0/1/2/" ). pop_right(
'/' ) ==
"" );
1700 CHECK(ryml::csubstr(
"0/1/2//" ). pop_right(
'/' ) ==
"" );
1701 CHECK(ryml::csubstr(
"0/1/2" ). pop_right(
'/', skip_empty) ==
"2" );
1702 CHECK(ryml::csubstr(
"0/1/2/" ). pop_right(
'/', skip_empty) ==
"2/" );
1703 CHECK(ryml::csubstr(
"0/1/2//" ). pop_right(
'/', skip_empty) ==
"2//" );
1705 CHECK(ryml::csubstr(
"0/1/2" ).gpop_right(
'/' ) ==
"1/2");
1706 CHECK(ryml::csubstr(
"0/1/2/" ).gpop_right(
'/' ) ==
"1/2/" );
1707 CHECK(ryml::csubstr(
"0/1/2//" ).gpop_right(
'/' ) ==
"1/2//" );
1708 CHECK(ryml::csubstr(
"/0/1/2" ).gpop_right(
'/' ) ==
"0/1/2");
1709 CHECK(ryml::csubstr(
"/0/1/2/" ).gpop_right(
'/' ) ==
"0/1/2/" );
1710 CHECK(ryml::csubstr(
"/0/1/2//" ).gpop_right(
'/' ) ==
"0/1/2//" );
1711 CHECK(ryml::csubstr(
"//0/1/2" ).gpop_right(
'/' ) ==
"/0/1/2");
1712 CHECK(ryml::csubstr(
"//0/1/2/" ).gpop_right(
'/' ) ==
"/0/1/2/" );
1713 CHECK(ryml::csubstr(
"//0/1/2//" ).gpop_right(
'/' ) ==
"/0/1/2//" );
1714 CHECK(ryml::csubstr(
"0/1/2" ).gpop_right(
'/', skip_empty) ==
"1/2");
1715 CHECK(ryml::csubstr(
"0/1/2/" ).gpop_right(
'/', skip_empty) ==
"1/2/" );
1716 CHECK(ryml::csubstr(
"0/1/2//" ).gpop_right(
'/', skip_empty) ==
"1/2//" );
1717 CHECK(ryml::csubstr(
"/0/1/2" ).gpop_right(
'/', skip_empty) ==
"1/2");
1718 CHECK(ryml::csubstr(
"/0/1/2/" ).gpop_right(
'/', skip_empty) ==
"1/2/" );
1719 CHECK(ryml::csubstr(
"/0/1/2//" ).gpop_right(
'/', skip_empty) ==
"1/2//" );
1720 CHECK(ryml::csubstr(
"//0/1/2" ).gpop_right(
'/', skip_empty) ==
"1/2");
1721 CHECK(ryml::csubstr(
"//0/1/2/" ).gpop_right(
'/', skip_empty) ==
"1/2/" );
1722 CHECK(ryml::csubstr(
"//0/1/2//" ).gpop_right(
'/', skip_empty) ==
"1/2//" );
1745 const char filename[] =
"ryml_example.yml";
1754 std::string contents = file_get_contents<std::string>(filename);
1756 CHECK(tree[
"foo"].val() ==
"1");
1757 CHECK(tree[
"bar"][0].val() ==
"2");
1758 CHECK(tree[
"bar"][1].val() ==
"3");
1763 std::vector<char> contents = file_get_contents<std::vector<char>>(filename);
1765 CHECK(tree[
"foo"].val() ==
"1");
1766 CHECK(tree[
"bar"][0].val() ==
"2");
1767 CHECK(tree[
"bar"][1].val() ==
"3");
1788 char src[] =
"{foo: 1, bar: [2, 3]}";
1789 ryml::substr srcview = src;
1794 CHECK(root[
"foo"].is_keyval());
1796 CHECK(root[
"foo"].val() ==
"1");
1797 CHECK(root[
"bar"].is_seq());
1798 CHECK(root[
"bar"].has_key());
1800 CHECK(root[
"bar"][0].val() ==
"2");
1801 CHECK(root[
"bar"][1].val() ==
"3");
1804 int foo = 0, bar0 = 0, bar1 = 0;
1806 root[
"bar"][0] >> bar0;
1807 root[
"bar"][1] >> bar1;
1813 CHECK(root[
"foo"].val().data() == src + strlen(
"{foo: "));
1814 CHECK(root[
"foo"].val().begin() == src + strlen(
"{foo: "));
1815 CHECK(root[
"foo"].val().end() == src + strlen(
"{foo: 1"));
1816 CHECK(root[
"foo"].val().is_sub(srcview));
1817 CHECK(root[
"bar"][0].val().data() == src + strlen(
"{foo: 1, bar: ["));
1818 CHECK(root[
"bar"][0].val().begin() == src + strlen(
"{foo: 1, bar: ["));
1819 CHECK(root[
"bar"][0].val().end() == src + strlen(
"{foo: 1, bar: [2"));
1820 CHECK(root[
"bar"][0].val().is_sub(srcview));
1821 CHECK(root[
"bar"][1].val().data() == src + strlen(
"{foo: 1, bar: [2, "));
1822 CHECK(root[
"bar"][1].val().begin() == src + strlen(
"{foo: 1, bar: [2, "));
1823 CHECK(root[
"bar"][1].val().end() == src + strlen(
"{foo: 1, bar: [2, 3"));
1824 CHECK(root[
"bar"][1].val().is_sub(srcview));
1828 ryml::csubstr csrcview = srcview;
1846 CHECK(root[
"foo"].is_keyval());
1848 CHECK(root[
"foo"].val() ==
"1");
1849 CHECK(root[
"bar"].is_seq());
1850 CHECK(root[
"bar"].has_key());
1852 CHECK(root[
"bar"][0].val() ==
"2");
1853 CHECK(root[
"bar"][1].val() ==
"3");
1856 int foo = 0, bar0 = 0, bar1 = 0;
1858 root[
"bar"][0] >> bar0;
1859 root[
"bar"][1] >> bar1;
1867 char src[] =
"{foo: is it really true}";
1868 ryml::substr srcview = src;
1874 ryml::csubstr csrcview = srcview;
1876 CHECK(tree[
"foo"].val() ==
"is it really true");
1895 ryml::csubstr yaml = R
"(foo: 1
1903 CHECK(root["foo"].is_keyval());
1905 CHECK(root[
"foo"].val() ==
"1");
1906 CHECK(root[
"bar"].is_seq());
1907 CHECK(root[
"bar"].has_key());
1909 CHECK(root[
"bar"][0].val() ==
"2");
1910 CHECK(root[
"bar"][1].val() ==
"3");
1911 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(foo: 1
1917 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(foo: 1
1923 CHECK(root["foo2"].is_keyval());
1924 CHECK(root[
"foo2"].
key() ==
"foo2");
1925 CHECK(root[
"foo2"].val() ==
"12");
1926 CHECK(root[
"bar2"].is_seq());
1927 CHECK(root[
"bar2"].has_key());
1928 CHECK(root[
"bar2"].
key() ==
"bar2");
1929 CHECK(root[
"bar2"][0].val() ==
"22");
1930 CHECK(root[
"bar2"][1].val() ==
"32");
1936 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
"- a\n- b\n- {x0: 1,x1: 2}\n");
1938 CHECK(root[0].val() ==
"a");
1939 CHECK(root[1].val() ==
"b");
1940 CHECK(root[2].is_map());
1941 CHECK(root[2][
"x0"].val() ==
"1");
1942 CHECK(root[2][
"x1"].val() ==
"2");
1947 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- a
1950 - champagne: Dom Perignon
1954 CHECK(root[0].val() == "a");
1955 CHECK(root[1].val() ==
"b");
1956 CHECK(root[2].is_map());
1957 CHECK(root[2][
"x0"].val() ==
"1");
1958 CHECK(root[2][
"x1"].val() ==
"2");
1959 CHECK(root[3].is_map());
1960 CHECK(root[3][
"champagne"].val() ==
"Dom Perignon");
1961 CHECK(root[3][
"coffee"].val() ==
"Arabica");
1971 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- a
1974 - champagne: Dom Perignon
1977 vinho verde: Soalheiro
1978 vinho tinto: Redoma 2017
1983 always: lots of water
1988 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- a
1991 - champagne: Dom Perignon
1994 vinho verde: Soalheiro
1995 vinho tinto: Redoma 2017
2000 always: lots of water
2009 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- a
2012 - champagne: Dom Perignon
2015 vinho verde: Soalheiro
2016 vinho tinto: Redoma 2017
2022 always: lots of water
2050 ryml::Tree champagnes =
parse_in_arena(&parser,
"champagnes.yml",
"[Dom Perignon, Gosset Grande Reserve, Jacquesson 742]");
2051 CHECK(ryml::emitrs_yaml<std::string>(champagnes) ==
"[Dom Perignon,Gosset Grande Reserve,Jacquesson 742]");
2054 CHECK(ryml::emitrs_yaml<std::string>(beers) ==
"[Rochefort 10,Busch,Leffe Rituel,Kasteel Donker]");
2084 ryml::csubstr champagnes =
"- Dom Perignon\n- Gosset Grande Reserve\n- Jacquesson 742";
2085 ryml::csubstr beers =
"- Rochefort 10\n- Busch\n- Leffe Rituel\n- Kasteel Donker";
2086 ryml::csubstr wines =
"- Soalheiro\n- Niepoort Redoma 2017\n- Vina Esmeralda";
2089 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- Dom Perignon
2090 - Gosset Grande Reserve
2096 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- Dom Perignon
2097 - Gosset Grande Reserve
2108 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- Soalheiro
2109 - Niepoort Redoma 2017
2124 ray: "a drop of golden sun"
2139 location: a pear tree
2147 std::vector<ryml::csubstr> keys, vals;
2150 keys.emplace_back(n.key());
2151 vals.emplace_back(n.has_val() ? n.val() : ryml::csubstr{});
2153 CHECK(keys[0] ==
"doe");
2154 CHECK(vals[0] ==
"a deer, a female deer");
2155 CHECK(keys[1] ==
"ray");
2156 CHECK(vals[1] ==
"a drop of golden sun");
2157 CHECK(keys[2] ==
"pi");
2158 CHECK(vals[2] ==
"3.14159");
2159 CHECK(keys[3] ==
"xmas");
2160 CHECK(vals[3] ==
"true");
2161 CHECK(root[5].has_key());
2162 CHECK(root[5].is_seq());
2163 CHECK(root[5].
key() ==
"calling-birds");
2164 CHECK(!root[5].has_val());
2166 CHECK(keys[5] ==
"calling-birds");
2167 CHECK(vals[5] ==
"");
2173 ryml::csubstr calling_birds[] = {
"huey",
"dewey",
"louie",
"fred"};
2175 CHECK(n.val() == calling_birds[count++]);
2200 const char a_deer[] =
"a deer, a female deer";
2209 std::string a_drop =
"a drop of golden sun";
2212 root[
"ray"] << a_drop;
2218 CHECK(root[
"ray"].val() ==
"a drop of golden sun");
2223 root[
"french-hens"] << 3;
2232 xmas5[
"calling-birds"] =
"four";
2233 xmas5[
"french-hens"] << 3;
2234 xmas5[
"golden-rings"] << 5;
2236 xmas5[
"partridges"][
"count"] << 1;
2237 xmas5[
"partridges"][
"location"] =
"a pear tree";
2238 xmas5[
"turtle-doves"] =
"two";
2239 root[
"cars"] =
"GTO";
2241 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(doe: 'a deer, a female deer'
2242 ray: a drop of golden sun
2257 location: a pear tree
2272 char buf[] =
"[a, b, c, d]";
2273 ryml::substr yml = buf;
2279 CHECK(root[0].val().is_sub(yml));
2280 CHECK(root[1].val().is_sub(yml));
2281 CHECK(root[2].val().is_sub(yml));
2282 CHECK(root[3].val().is_sub(yml));
2283 CHECK(yml.is_super(root[0].
val()));
2284 CHECK(yml.is_super(root[1].
val()));
2285 CHECK(yml.is_super(root[2].
val()));
2286 CHECK(yml.is_super(root[3].
val()));
2293 ryml::csubstr yml =
"[a, b, c, d]";
2301 ryml::csubstr arena = tree.
arena();
2302 CHECK(root[0].val().is_sub(arena));
2303 CHECK(root[1].val().is_sub(arena));
2304 CHECK(root[2].val().is_sub(arena));
2305 CHECK(root[3].val().is_sub(arena));
2306 CHECK(arena.is_super(root[0].
val()));
2307 CHECK(arena.is_super(root[1].
val()));
2308 CHECK(arena.is_super(root[2].
val()));
2309 CHECK(arena.is_super(root[3].
val()));
2315 char buf[] =
"[a, b, c, d]";
2316 ryml::substr yml = buf;
2323 CHECK(root[2].val() ==
"c");
2324 CHECK(root[2].val().is_sub(yml));
2326 CHECK(root[2].val() ==
"12345");
2332 CHECK(root[3].val() ==
"d");
2333 CHECK(root[3].val().is_sub(yml));
2335 CHECK(root[3].val() ==
"67890");
2343 ryml::csubstr yml =
"[a, b, c, d]";
2351 CHECK(root[2].val() ==
"c");
2353 CHECK(root[2].val() ==
"12345");
2362 CHECK(root[3].val() ==
"67890");
2366 CHECK(tree.
arena() ==
"[a, b, c, d]1234567890");
2373 ryml::csubstr c10 = tree.
to_arena(10101010);
2374 CHECK(c10 ==
"10101010");
2384 CHECK(root[
"a"].val() ==
"2222");
2391 ryml::csubstr mystr =
"Gosset Grande Reserve";
2393 CHECK(!copied.overlaps(mystr));
2394 CHECK(copied == mystr);
2395 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2401 ryml::csubstr mystr =
"Gosset Grande Reserve";
2402 ryml::substr copied = tree.
alloc_arena(mystr.size());
2403 CHECK(!copied.overlaps(mystr));
2404 memcpy(copied.str, mystr.str, mystr.len);
2405 CHECK(copied == mystr);
2406 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2412 CHECK(tree.
arena().size() == strlen(
"{a: b}"));
2415 CHECK(tree.
arena().size() == strlen(
"{a: b}"));
2417 CHECK(tree.
arena().first(12) ==
"{a: b}123456");
2455 CHECK(tree.
to_arena(
double(0.234)) ==
"0.234");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.234");
2465 const float fnan = std::numeric_limits<float >::quiet_NaN();
2466 const double dnan = std::numeric_limits<double>::quiet_NaN();
2467 const float finf = std::numeric_limits<float >::infinity();
2468 const double dinf = std::numeric_limits<double>::infinity();
2469 CHECK(tree.
to_arena( finf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf");
2470 CHECK(tree.
to_arena( dinf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf");
2471 CHECK(tree.
to_arena(-finf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf");
2472 CHECK(tree.
to_arena(-dinf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf");
2473 CHECK(tree.
to_arena( fnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan");
2474 CHECK(tree.
to_arena( dnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan.nan");
2478 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wfloat-equal");
2484 tree[
"ninf"] >> f;
CHECK(f == -finf);
2485 tree[
"ninf"] >> d;
CHECK(d == -dinf);
2486 tree[
"pinf"] >> f;
CHECK(f == finf);
2487 tree[
"pinf"] >> d;
CHECK(d == dinf);
2488 tree[
"nan" ] >> f;
CHECK(std::isnan(f));
2489 tree[
"nan" ] >> d;
CHECK(std::isnan(d));
2490 C4_SUPPRESS_WARNING_GCC_CLANG_POP
2507 all_null: [~, null, Null, NULL]
2508 non_null: [nULL, non_null, non null, null it is not]
2512 CHECK(tree[
"plain"].has_val());
2513 CHECK(tree[
"squoted"].has_val());
2514 CHECK(tree[
"dquoted"].has_val());
2515 CHECK(tree[
"literal"].has_val());
2516 CHECK(tree[
"folded"].has_val());
2517 CHECK( ! tree[
"all_null"].has_val());
2518 CHECK( ! tree[
"non_null"].has_val());
2520 CHECK( ! tree[
"plain"].is_container());
2521 CHECK( ! tree[
"squoted"].is_container());
2522 CHECK( ! tree[
"dquoted"].is_container());
2523 CHECK( ! tree[
"literal"].is_container());
2524 CHECK( ! tree[
"folded"].is_container());
2525 CHECK(tree[
"all_null"].is_container());
2526 CHECK(tree[
"non_null"].is_container());
2531 CHECK(tree[
"plain"].val().len == 0);
2532 CHECK(tree[
"squoted"].val().len == 0);
2533 CHECK(tree[
"dquoted"].val().len == 0);
2534 CHECK(tree[
"literal"].val().len == 0);
2535 CHECK(tree[
"folded"].val().len == 0);
2537 CHECK(tree[
"plain"].val().str ==
nullptr);
2538 CHECK(tree[
"squoted"].val().str !=
nullptr);
2539 CHECK(tree[
"dquoted"].val().str !=
nullptr);
2540 CHECK(tree[
"literal"].val().str !=
nullptr);
2541 CHECK(tree[
"folded"].val().str !=
nullptr);
2545 CHECK(tree[
"plain"].val() ==
nullptr);
2546 CHECK(tree[
"squoted"].val() !=
nullptr);
2547 CHECK(tree[
"dquoted"].val() !=
nullptr);
2548 CHECK(tree[
"literal"].val() !=
nullptr);
2549 CHECK(tree[
"folded"].val() !=
nullptr);
2554 CHECK(tree[
"plain"].val_is_null());
2555 CHECK( ! tree[
"squoted"].val_is_null());
2556 CHECK( ! tree[
"dquoted"].val_is_null());
2557 CHECK( ! tree[
"literal"].val_is_null());
2558 CHECK( ! tree[
"folded"].val_is_null());
2563 CHECK(child.val() !=
nullptr);
2564 CHECK(child.val_is_null());
2568 CHECK(child.val() !=
nullptr);
2569 CHECK( ! child.val_is_null());
2580 ryml::csubstr
null = {};
2581 ryml::csubstr nonnull =
"";
2582 ryml::csubstr strnull =
"null";
2583 ryml::csubstr tilde =
"~";
2584 CHECK(
null .len == 0);
CHECK(
null .str ==
nullptr);
CHECK(
null ==
nullptr);
2585 CHECK(nonnull.len == 0);
CHECK(nonnull.str !=
nullptr);
CHECK(nonnull !=
nullptr);
2586 CHECK(strnull.len != 0);
CHECK(strnull.str !=
nullptr);
CHECK(strnull !=
nullptr);
2587 CHECK(tilde .len != 0);
CHECK(tilde .str !=
nullptr);
CHECK(tilde !=
nullptr);
2592 tree[
"empty_null"] <<
null;
CHECK(tree.
arena() ==
"");
2594 tree[
"empty_nonnull"] << nonnull;
CHECK(tree.
arena() ==
"");
2596 tree[
"str_null"] << strnull;
CHECK(tree.
arena() ==
"null");
2598 tree[
"str_tilde"] << tilde;
CHECK(tree.
arena() ==
"null~");
2600 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null:
2610 auto null_if_nullptr = [](ryml::csubstr s) {
2611 return s.str ==
nullptr ?
"null" : s;
2613 tree[
"empty_null"] << null_if_nullptr(
null);
2614 tree[
"empty_nonnull"] << null_if_nullptr(nonnull);
2615 tree[
"str_null"] << null_if_nullptr(strnull);
2616 tree[
"str_tilde"] << null_if_nullptr(tilde);
2618 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null: null
2626 auto null_if_predicate = [](ryml::csubstr s) {
2629 tree[
"empty_null"] << null_if_predicate(
null);
2630 tree[
"empty_nonnull"] << null_if_predicate(nonnull);
2631 tree[
"str_null"] << null_if_predicate(strnull);
2632 tree[
"str_tilde"] << null_if_predicate(tilde);
2634 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null: null
2642 auto tilde_if_predicate = [](ryml::csubstr s) {
2645 tree[
"empty_null"] << tilde_if_predicate(
null);
2646 tree[
"empty_nonnull"] << tilde_if_predicate(nonnull);
2647 tree[
"str_null"] << tilde_if_predicate(strnull);
2648 tree[
"str_tilde"] << tilde_if_predicate(tilde);
2650 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null: ~
2669 char buf_[256] = {};
2670 ryml::substr buf = buf_;
2671 size_t size =
ryml::format(buf,
"a={} foo {} {} bar {}", 0.1, 10, 11, 12);
2672 CHECK(size == strlen(
"a=0.1 foo 10 11 bar 12"));
2673 CHECK(buf.first(size) ==
"a=0.1 foo 10 11 bar 12");
2676 size =
ryml::format({} ,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12);
2677 CHECK(size ==
ryml::format(buf,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12));
2678 CHECK(size == strlen(
"a=this_is_a foo 10 11 bar 12"));
2680 char smallbuf[8] = {};
2681 size =
ryml::format(smallbuf,
"{} is too large {}",
"this",
"for the buffer");
2682 CHECK(size == strlen(
"this is too large for the buffer"));
2684 CHECK(ryml::substr(smallbuf,
sizeof(smallbuf)) ==
"this is\0");
2688 CHECK(result ==
"b=1, damn it.");
2689 CHECK(result.is_sub(buf));
2707 CHECK(sbuf ==
"and c=2 seems about right");
2708 std::vector<char> vbuf;
2710 CHECK(sbuf ==
"and c=2 seems about right");
2713 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2720 int a = 0, b = 1, c = 2;
2721 ryml::csubstr result =
ryml::format_sub(buf_,
"{} and {} and {}", a, b, c);
2722 CHECK(result ==
"0 and 1 and 2");
2723 int aa = -1, bb = -2, cc = -3;
2724 size_t num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2726 CHECK(num_characters == result.size());
2732 CHECK(result ==
"10 and 20 and 30");
2733 num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2735 CHECK(num_characters == result.size());
2743 char buf_[256] = {};
2744 ryml::substr buf = buf_;
2745 size_t size =
ryml::cat(buf,
"a=", 0.1,
"foo", 10, 11,
"bar", 12);
2746 CHECK(size == strlen(
"a=0.1foo1011bar12"));
2747 CHECK(buf.first(size) ==
"a=0.1foo1011bar12");
2752 char smallbuf[8] = {};
2753 size =
ryml::cat(smallbuf,
"this",
" is too large ",
"for the buffer");
2754 CHECK(size == strlen(
"this is too large for the buffer"));
2756 CHECK(ryml::substr(smallbuf,
sizeof(smallbuf)) ==
"this is\0");
2759 ryml::csubstr result =
ryml::cat_sub(buf,
"b=", 1,
", damn it.");
2760 CHECK(result ==
"b=1, damn it.");
2761 CHECK(result.is_sub(buf));
2778 ryml::catrs(&sbuf,
"and c=", 2,
" seems about right");
2779 CHECK(sbuf ==
"and c=2 seems about right");
2780 std::vector<char> vbuf;
2781 ryml::catrs(&vbuf,
"and c=", 2,
" seems about right");
2782 CHECK(sbuf ==
"and c=2 seems about right");
2785 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2792 int a = 0, b = 1, c = 2;
2793 ryml::csubstr result =
ryml::cat_sub(buf_, a,
' ', b,
' ', c);
2794 CHECK(result ==
"0 1 2");
2795 int aa = -1, bb = -2, cc = -3;
2796 char sep1 =
'a', sep2 =
'b';
2797 size_t num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2798 CHECK(num_characters == result.size());
2806 CHECK(result ==
"10 20 30");
2807 num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2808 CHECK(num_characters == result.size());
2818 char buf_[256] = {};
2819 ryml::substr buf = buf_;
2821 size_t size =
ryml::catsep(buf,
' ',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2822 CHECK(buf.first(size) ==
"a= 0 b= 1 c= 2 45 67");
2825 size =
ryml::catsep(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
2826 CHECK(buf.first(size) ==
"a=0 and b=1 and c=2 and 45 and 67");
2828 size =
ryml::catsep(buf,
" ... ",
"a=0",
"b=1",
"c=2", 45, 67);
2829 CHECK(buf.first(size) ==
"a=0 ... b=1 ... c=2 ... 45 ... 67");
2831 size =
ryml::catsep(buf,
'/',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2832 CHECK(buf.first(size) ==
"a=/0/b=/1/c=/2/45/67");
2834 size =
ryml::catsep(buf, 888,
"a=0",
"b=1",
"c=2", 45, 67);
2835 CHECK(buf.first(size) ==
"a=0888b=1888c=28884588867");
2841 char smallbuf[8] = {};
2843 CHECK(size == strlen(
"a=0888b=1888c=28884588867"));
2845 CHECK(ryml::substr(smallbuf,
sizeof(smallbuf)) ==
"a=0888b\0");
2848 ryml::csubstr result =
ryml::catsep_sub(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
2849 CHECK(result ==
"a=0 and b=1 and c=2 and 45 and 67");
2850 CHECK(result.is_sub(buf));
2868 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67");
2869 std::vector<char> vbuf;
2875 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");
2880 char buf_[256] = {};
2882 int a = 0, b = 1, c = 2;
2884 CHECK(result ==
"0 1 2");
2885 int aa = -1, bb = -2, cc = -3;
2888 CHECK(num_characters == result.size());
2896 CHECK(result ==
"10 20 30");
2898 CHECK(num_characters == result.size());
2907 using namespace ryml;
2908 char buf_[256] = {};
2927 CHECK(
"3735928559" ==
cat_sub(buf, UINT32_C(0xdeadbeef)));
3051 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wcast-align")
3052 const uint32_t payload[] = {10, 20, 30, 40, UINT32_C(0xdeadbeef)};
3054 csubstr expected = csubstr((
const char *)payload,
sizeof(payload));
3056 CHECK(!actual.overlaps(expected));
3057 CHECK(0 == memcmp(expected.str, actual.str, expected.len));
3059 for(
const uint32_t value : payload)
3062 expected = csubstr((
const char *)&value,
sizeof(value));
3064 CHECK(actual.size() ==
sizeof(uint32_t));
3065 CHECK(!actual.overlaps(expected));
3066 CHECK(0 == memcmp(expected.str, actual.str, expected.len));
3069 CHECK(actual.size() ==
sizeof(uint32_t));
3070 CHECK(!actual.overlaps(expected));
3071 CHECK(0 == memcmp(expected.str, actual.str, expected.len));
3076 CHECK(&result == (uint32_t*)reader.buf);
3077 CHECK(reader.len ==
sizeof(uint32_t));
3078 uncat(actual, reader);
3081 result = *(uint32_t*)reader.buf;
3082 CHECK(result == value);
3084 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3103 struct text_and_base64 { ryml::csubstr text,
base64; };
3104 text_and_base64 cases[] = {
3105 {{
"Love all, trust a few, do wrong to none."}, {
"TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg=="}},
3106 {{
"The fool doth think he is wise, but the wise man knows himself to be a fool."}, {
"VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg=="}},
3107 {{
"Brevity is the soul of wit."}, {
"QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu"}},
3108 {{
"All that glitters is not gold."}, {
"QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu"}},
3111 for(text_and_base64 c : cases)
3114 CHECK(tree[c.text].
val() == c.base64);
3117 for(text_and_base64 c : cases)
3120 CHECK(tree[c.base64].
val() == c.text);
3122 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"('Love all, trust a few, do wrong to none.': TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg==
3123 'The fool doth think he is wise, but the wise man knows himself to be a fool.': VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg==
3124 Brevity is the soul of wit.: QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu
3125 All that glitters is not gold.: QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu
3126 TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg==: 'Love all, trust a few, do wrong to none.'
3127 VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg==: 'The fool doth think he is wise, but the wise man knows himself to be a fool.'
3128 QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu: Brevity is the soul of wit.
3129 QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu: All that glitters is not gold.
3131 char buf1_[128], buf2_[128];
3132 ryml::substr buf1 = buf1_;
3133 ryml::substr buf2 = buf2_;
3134 std::string result = {};
3136 for(
const text_and_base64 c : cases)
3141 CHECK(len <= buf1.len);
3142 CHECK(len <= buf2.len);
3143 CHECK(c.text.len == len);
3144 CHECK(buf1.first(len) == c.text);
3145 CHECK(buf2.first(len) == c.text);
3150 if(len > result.size())
3156 CHECK(result == c.text);
3160 ryml::blob strblob(&result[0], result.size());
3161 CHECK(strblob.buf == result.data());
3162 CHECK(strblob.len == result.size());
3164 if(len > result.size())
3167 strblob = {&result[0], result.
size()};
3168 CHECK(strblob.buf == result.data());
3169 CHECK(strblob.len == result.size());
3173 CHECK(result == c.text);
3178 ryml::csubstr encoded = tree[c.text].
val();
3179 CHECK(encoded == c.base64);
3180 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3181 if(len > result.size())
3184 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3187 CHECK(result == c.text);
3190 for(
const text_and_base64 c : cases)
3195 CHECK(len <= buf1.len);
3196 CHECK(len <= buf2.len);
3197 CHECK(c.text.len == len);
3198 CHECK(buf1.first(len) == c.text);
3199 CHECK(buf2.first(len) == c.text);
3203 if(len > result.size())
3209 CHECK(result == c.text);
3213 ryml::blob strblob = {&result[0], result.size()};
3214 CHECK(strblob.buf == result.data());
3215 CHECK(strblob.len == result.size());
3217 if(len > result.size())
3220 strblob = {&result[0], result.
size()};
3221 CHECK(strblob.buf == result.data());
3222 CHECK(strblob.len == result.size());
3226 CHECK(result == c.text);
3231 ryml::csubstr encoded = tree[c.base64].
key();
3232 CHECK(encoded == c.base64);
3233 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3234 if(len > result.size())
3237 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3240 CHECK(result == c.text);
3244 const uint64_t valin = UINT64_C(0xdeadbeef);
3245 uint64_t valout = 0;
3248 CHECK(len <=
sizeof(valout));
3249 CHECK(valout == UINT64_C(0xdeadbeef));
3253 const uint32_t data_in[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xdeadbeef};
3254 uint32_t data_out[11] = {};
3255 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) != 0);
3258 CHECK(len <=
sizeof(data_out));
3259 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3490 CHECK(v2in.x == v2out.x);
3491 CHECK(v2in.y == v2out.y);
3496 CHECK(v3in.x == v3out.x);
3497 CHECK(v3in.y == v3out.y);
3498 CHECK(v3in.z == v3out.z);
3503 CHECK(v4in.x == v4out.x);
3504 CHECK(v4in.y == v4out.y);
3505 CHECK(v4in.z == v4out.z);
3506 CHECK(v4in.w == v4out.w);
3507 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(v2: '(10,11)'
3509 v4: '(1000,1001,1002,1003)'
3519 CHECK(eov2in.x == pov2out.x);
3520 CHECK(eov2in.y == pov2out.y);
3525 CHECK(eov3in.x == pov3out.x);
3526 CHECK(eov3in.y == pov3out.y);
3527 CHECK(eov3in.z == pov3out.z);
3532 CHECK(eov4in.x == pov4out.x);
3533 CHECK(eov4in.y == pov4out.y);
3534 CHECK(eov4in.z == pov4out.z);
3535 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(v2: '(20,21)'
3589 template<
class K,
class V>
3614 template<
class K,
class V>
3642 template<
class K,
class V>
3647 for(
auto const ch : n)
3650 map->
map_member.emplace(std::make_pair(std::move(k), std::move(v)));
3661 n[
"seq"] >> val->
seq;
3662 n[
"map"] >> val->
map;
3681 {{101, 102, 103, 104, 105, 106, 107}},
3682 {{{1001, 2001}, {1002, 2002}, {1003, 2003}}},
3698 CHECK(mt_in.seq.seq_member.size() > 0);
3700 for(
size_t i = 0; i < mt_in.seq.seq_member.size(); ++i)
3704 CHECK(mt_in.map.map_member.size() > 0);
3706 for(
auto const& kv : mt_in.map.map_member)
3711 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(v2: '(20,21)'
3738 std::string yml_std_string = R
"(- v2: '(20,21)'
3755 v4: '(140,141,142,143)'
3770 v4: '(240,241,242,243)'
3788 std::vector<my_type> vmt;
3790 CHECK(vmt.size() == 3);
3793 CHECK(ryml::emitrs_yaml<std::string>(tree_out) == yml_std_string);
3802 std::vector<double> reference{1.23234412342131234, 2.12323123143434237, 3.67847983572591234};
3806 const double precision_safe = 1.e-14;
3807 const size_t num_digits_safe = 14;
3808 const size_t num_digits_original = 17;
3809 auto get_num_digits = [](ryml::csubstr number){
return number.sub(2).len; };
3815 std::vector<double> output;
3817 CHECK(output.size() == reference.size());
3818 for(
size_t i = 0; i < reference.size(); ++i)
3821 CHECK(fabs(output[i] - reference[i]) < precision_safe);
3830 serialized.
rootref() << reference;
3831 std::cout << serialized;
3833 #if (!C4CORE_HAVE_STD_TOCHARS)
3834 CHECK(ryml::emitrs_yaml<std::string>(serialized) == R
"(- 1.23234
3837 )" || (bool)
"this is indicative; the exact results will vary from platform to platform.");
3838 C4_UNUSED(num_digits_safe);
3840 CHECK((ryml::emitrs_yaml<std::string>(serialized) == R
"(- 1.2323441234213124
3841 - 2.1232312314343424
3842 - 3.6784798357259123
3843 )") || (bool)
"this is indicative; the exact results will vary from platform to platform.");
3847 CHECK(get_num_digits(child.val()) >= num_digits_safe);
3850 CHECK(fabs(out - reference[pos++]) < precision_safe);
3881 auto check_precision = [&](
ryml::Tree serialized){
3882 std::cout << serialized;
3884 CHECK((ryml::emitrs_yaml<std::string>(serialized) == R
"(- 1.23234412342131239
3885 - 2.12323123143434245
3886 - 3.67847983572591231
3887 )") || (bool)
"this is indicative; the exact results will vary from platform to platform.");
3891 CHECK(get_num_digits(child.val()) == num_digits_original);
3894 CHECK(fabs(out - reference[pos++]) < precision_safe);
3903 for(
const double v : reference)
3905 check_precision(serialized);
3914 for(
const double v : reference)
3919 (void)snprintf(tmp,
sizeof(tmp),
"%.18g", v);
3925 check_precision(serialized);
3937 ryml::csubstr ymla =
"- 1\n- 2\n";
3938 ryml::csubstr ymlb = R
"(- a
3942 - champagne: Dom Perignon
3945 vinho verde: Soalheiro
3946 vinho tinto: Redoma 2017
3964 ryml::csubstr output =
ryml::emit_yaml(treea, treea.root_id(), ryml::substr{},
false);
3965 CHECK(output.str ==
nullptr);
3966 CHECK(output.len > 0);
3967 size_t num_needed_chars = output.len;
3968 std::vector<char> buf(num_needed_chars);
3971 CHECK(output == ymla);
3975 output =
ryml::emit_yaml(treeb, treeb.root_id(), ryml::substr{},
false);
3976 CHECK(output.str ==
nullptr);
3977 CHECK(output.len > 0);
3978 CHECK(output.len == ymlb.len);
3979 num_needed_chars = output.len;
3980 buf.resize(num_needed_chars);
3983 CHECK(output == ymlb);
3988 CHECK(output == ymlb);
3992 std::vector<char> another = ryml::emitrs_yaml<std::vector<char>>(treeb);
3996 another = ryml::emitrs_yaml<std::vector<char>>(treeb[3][2]);
3998 vinho verde: Soalheiro
3999 vinho tinto: Redoma 2017
4009 ryml::csubstr output =
ryml::emit_yaml(treea, treea.root_id(), ryml::substr{},
false);
4010 CHECK(output.str ==
nullptr);
4011 CHECK(output.len > 0);
4012 size_t num_needed_chars = output.len;
4014 buf.resize(num_needed_chars);
4017 CHECK(output == ymla);
4021 output =
ryml::emit_yaml(treeb, treeb.root_id(), ryml::substr{},
false);
4022 CHECK(output.str ==
nullptr);
4023 CHECK(output.len > 0);
4024 CHECK(output.len == ymlb.len);
4025 num_needed_chars = output.len;
4026 buf.resize(num_needed_chars);
4029 CHECK(output == ymlb);
4034 CHECK(output == ymlb);
4038 std::string another = ryml::emitrs_yaml<std::string>(treeb);
4042 another = ryml::emitrs_yaml<std::string>(treeb[3][2]);
4044 vinho verde: Soalheiro
4045 vinho tinto: Redoma 2017
4056 ryml::csubstr ymlb = R
"(- a
4060 - champagne: Dom Perignon
4063 vinho verde: Soalheiro
4064 vinho tinto: Redoma 2017
4080 std::stringstream ss;
4088 std::stringstream ss;
4091 CHECK(
ryml::to_csubstr(s) == R
"(["a","b",{"x0": 1,"x1": 2},{"champagne": "Dom Perignon","coffee": "Arabica","more": {"vinho verde": "Soalheiro","vinho tinto": "Redoma 2017"},"beer": ["Rochefort 10","Busch","Leffe Rituel"]},"foo","bar","baz","bat"])");
4096 std::stringstream ss;
4100 vinho verde: Soalheiro
4101 vinho tinto: Redoma 2017
4107 std::stringstream ss;
4110 CHECK(
ryml::to_csubstr(s) == R
"("more": {"vinho verde": "Soalheiro","vinho tinto": "Redoma 2017"})");
4120 ryml::csubstr yml = R
"(- a
4124 - champagne: Dom Perignon
4127 vinho verde: Soalheiro
4128 vinho tinto: Redoma 2017
4144 CHECK(len == yml.len);
4157 - champagne: Dom Perignon
4160 vinho verde: Soalheiro
4161 vinho tinto: Redoma 2017
4174 CHECK(ryml::emitrs_yaml<std::string>(tree[3]["beer"]) == R
"(beer:
4182 CHECK(ryml::emitrs_yaml<std::string>(tree[3]["beer"][0]) ==
"Rochefort 10\n");
4183 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"beer"][3]) == R
"(- and so
4211 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(NodeOne:
4228 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(NodeOne:
4229 - {key: a,desc: b,class: c,number: d}
4230 - {key: e,desc: f,class: g,number: h}
4231 - {key: i,desc: j,class: k,number: l}
4234 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(NodeOne: [{key: a,desc: b,class: c,number: d},{key: e,desc: f,class: g,number: h},{key: i,desc: j,class: k,number: l}]
4237 CHECK(ryml::emitrs_yaml<std::string>(tree) == R"({NodeOne: [{key: a,desc: b,class: c,number: d},{key: e,desc: f,class: g,number: h},{key: i,desc: j,class: k,number: l}]})");
4247 ryml::csubstr json = R
"({
4248 "doe":"a deer, a female deer",
4249 "ray":"a drop of golden sun",
4250 "me":"a name, I call myself",
4251 "far":"a long long way to go"
4261 CHECK(ryml::emitrs_json<std::string>(tree) == R
"({"doe": "a deer, a female deer","ray": "a drop of golden sun","me": "a name, I call myself","far": "a long long way to go"})");
4262 CHECK(ryml::emitrs_json<std::string>(json_tree) == R"({"doe": "a deer, a female deer","ray": "a drop of golden sun","me": "a name, I call myself","far": "a long long way to go"})");
4264 std::stringstream ss;
4266 CHECK(ss.str() == R
"({"doe": "a deer, a female deer","ray": "a drop of golden sun","me": "a name, I call myself","far": "a long long way to go"})");
4305 std::string unresolved = R
"(base: &base
4306 name: Everyone has same name
4317 city: East Centerville
4320 &keyref key: &valref val
4323 std::string resolved = R"(base:
4324 name: Everyone has same name
4326 name: Everyone has same name
4329 name: Everyone has same name
4335 city: East Centerville
4341 city: East Centerville
4349 CHECK( ! tree[
"base"].has_key_anchor());
4350 CHECK( tree[
"base"].has_val_anchor());
4351 CHECK( tree[
"base"].val_anchor() ==
"base");
4352 CHECK( tree[
"key"].key_anchor() ==
"keyref");
4353 CHECK( tree[
"key"].val_anchor() ==
"valref");
4354 CHECK( tree[
"*valref"].is_key_ref());
4355 CHECK( tree[
"*valref"].is_val_ref());
4356 CHECK( tree[
"*valref"].key_ref() ==
"valref");
4357 CHECK( tree[
"*valref"].val_ref() ==
"keyref");
4364 CHECK( ! tree[
"base"].has_key_anchor());
4365 CHECK( ! tree[
"base"].has_val_anchor());
4366 CHECK( ! tree[
"base"].has_val_anchor());
4367 CHECK( ! tree[
"key"].has_key_anchor());
4368 CHECK( ! tree[
"key"].has_val_anchor());
4369 CHECK( ! tree[
"val"].is_key_ref());
4370 CHECK( ! tree[
"val"].is_val_ref());
4372 CHECK(tree[
"ship_to"][
"city"].val() ==
"East Centerville");
4373 CHECK(tree[
"ship_to"][
"state"].val() ==
"KS");
4381 const std::string yaml = R
"(--- !!map
4407 CHECK(doc.is_doc());
4409 CHECK(root[0].has_val_tag());
4410 CHECK(root[0].val_tag() ==
"!!map");
4411 CHECK(root[1].val_tag() ==
"!map");
4412 CHECK(root[2].val_tag() ==
"!!seq");
4413 CHECK(root[3].val_tag() ==
"!!str");
4414 CHECK(root[4].val_tag() ==
"!!str");
4415 CHECK(root[5][
"a"].has_key_tag());
4416 CHECK(root[5][
"a"].key_tag() ==
"!!str");
4417 CHECK(root[6].val_tag() ==
"!!set");
4418 CHECK(root[7].val_tag() ==
"!!set");
4419 CHECK(root[8].val_tag() ==
"!!seq");
4420 CHECK(root[8][0].val_tag() ==
"!!int");
4421 CHECK(root[8][1].val_tag() ==
"!!str");
4470 CHECK(ryml::emitrs_yaml<std::string>(normalized_tree) == R
"(--- !!map
4493 CHECK(ryml::emitrs_yaml<std::string>(normalized_tree_long) == R
"(--- !<tag:yaml.org,2002:map>
4498 --- !<tag:yaml.org,2002:seq>
4501 --- !<tag:yaml.org,2002:str> a b
4502 --- !<tag:yaml.org,2002:str> 'a: b'
4504 !<tag:yaml.org,2002:str> a: b
4505 --- !<tag:yaml.org,2002:set>
4508 --- !<tag:yaml.org,2002:set>
4510 --- !<tag:yaml.org,2002:seq>
4511 - !<tag:yaml.org,2002:int> 0
4512 - !<tag:yaml.org,2002:str> 1
4521 const std::string yaml = R
"(
4524 !m!light fluorescent
4531 CHECK(ryml::emitrs_yaml<std::string>(tree) == R"(%TAG !m! !my-
4532 --- !m!light fluorescent
4540 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(%TAG !m! !my-
4541 --- !<!my-light> fluorescent
4544 --- !<!meta-light> green
4555 std::string yml = R
"(---
4568 CHECK(ryml::emitrs_yaml<std::string>(tree) == yml);
4579 CHECK(doc.is_doc());
4596 CHECK(stream[0].is_doc());
4597 CHECK(stream[0].is_map());
4598 CHECK(stream[0][
"a"].val() ==
"0");
4599 CHECK(stream[0][
"b"].val() ==
"1");
4608 CHECK(stream[1].is_doc());
4609 CHECK(stream[1].is_map());
4610 CHECK(stream[1][
"c"].val() ==
"2");
4611 CHECK(stream[1][
"d"].val() ==
"3");
4620 CHECK(stream[2].is_doc());
4621 CHECK(stream[2].is_seq());
4622 CHECK(stream[2][0].val() ==
"4");
4623 CHECK(stream[2][1].val() ==
"5");
4624 CHECK(stream[2][2].val() ==
"6");
4625 CHECK(stream[2][3].val() ==
"7");
4644 const std::string expected_json[] = {
4645 R
"({"a": 0,"b": 1})",
4646 R"({"c": 2,"d": 3})",
4655 CHECK(ryml::emitrs_json<std::string>(doc) == expected_json[count++]);
4663 CHECK(ryml::emitrs_json<std::string>(tree, doc_id) == expected_json[count++]);
4700 ryml::Tree tree = ryml::parse_in_arena(
"errorhandler.yml",
"[a: b\n}");
4740 uintptr_t uptr = (uintptr_t)ptr;
4741 const uintptr_t align =
alignof(max_align_t);
4744 uintptr_t prev = uptr - (uptr % align);
4745 uintptr_t next = prev + align;
4746 uintptr_t corr = next - uptr;
4747 ptr = (
void*)(((
char*)ptr) + corr);
4751 "out of memory! requested=%zu+%zu available=%zu\n",
4774 static void s_free(
void *mem,
size_t len,
void *this_)
4846 parse_in_arena(&parser,
"", R
"([a, b, c, d, {foo: bar, money: pennys}])", &tree);
4889 std::cerr <<
"out of memory! requested=" <<
alloc_size <<
" vs " <<
memory_pool.size() <<
" available" << std::endl;
4940 ryml::csubstr yml1 =
"{a: b}";
4941 ryml::csubstr yml2 =
"{c: d, e: f, g: [h, i, 0, 1, 2, 3]}";
4974 CHECK(tree["doe"].val() ==
"a deer, a female deer");
4988 ryml::csubstr yaml = R
"({
4990 foo: [one, [two, three]]
5033 loc = parser.
location(tree[
"foo"]);
5038 loc = parser.
location(tree[
"foo"][0]);
5043 loc = parser.
location(tree[
"foo"][1]);
5047 loc = parser.
location(tree[
"foo"][1][0]);
5051 loc = parser.
location(tree[
"foo"][1][1]);
5081 - nested first value
5082 - nested second value
5085 nested second: value
5099 loc = parser.
location(tree2[
"a new"]);
5104 loc = parser.
location(tree2[
"to"]);
5110 loc = parser.
location(tree2[
"map with key"]);
5114 loc = parser.
location(tree2[
"map with key"][
"first"]);
5118 loc = parser.
location(tree2[
"map with key"][
"second"]);
5123 loc = parser.
location(tree2[
"seq with key"]);
5127 loc = parser.
location(tree2[
"seq with key"][0]);
5131 loc = parser.
location(tree2[
"seq with key"][1]);
5136 loc = parser.
location(tree2[
"seq with key"][2]);
5140 loc = parser.
location(tree2[
"seq with key"][2][0]);
5145 loc = parser.
location(tree2[
"seq with key"][3]);
5149 loc = parser.
location(tree2[
"seq with key"][3][0]);
5165 static int num_checks = 0;
5166 static int num_failed_checks = 0;
5173 const char *msg = predicate ?
"OK! " :
"OK!";
5176 ++num_failed_checks;
5177 msg = predicate ?
"ERROR: " :
"ERROR";
5179 std::cout << __FILE__ <<
':' << line <<
": " << msg << (predicate ? predicate :
"") << std::endl;
5186 std::cout <<
"Completed " << num_checks <<
" checks." << std::endl;
5187 if(num_failed_checks)
5188 std::cout <<
"ERROR: " << num_failed_checks <<
'/' << num_checks <<
" checks failed." << std::endl;
5190 std::cout <<
"SUCCESS!" << std::endl;
5191 return num_failed_checks;
5199 static std::jmp_buf s_jmp_env;
5200 static std::string s_jmp_msg;
5207 bool expected_error_occurred =
false;
5214 expected_error_occurred =
true;
5216 return expected_error_occurred;
5238 std::string full_msg = ryml::formatrs<std::string>(
5239 "{}:{}:{} ({}B): ERROR: {}",
5243 throw std::runtime_error(full_msg);
5247 s_jmp_msg = full_msg;
5248 std::longjmp(s_jmp_env, 1);
5276 C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4996)
5278 template<class CharContainer>
5281 std::FILE *fp = std::fopen(filename,
"rb");
5282 RYML_CHECK_MSG(fp !=
nullptr,
"could not open file");
5283 std::fseek(fp, 0, SEEK_END);
5284 long sz = std::ftell(fp);
5285 v->resize(
static_cast<typename CharContainer::size_type
>(sz));
5289 size_t ret = std::fread(&(*v)[0], 1, v->size(), fp);
5290 RYML_CHECK(ret == (
size_t)sz);
5297 template<
class CharContainer>
5306 template<
class CharContainer>
5315 std::FILE *fp = std::fopen(filename, access);
5316 RYML_CHECK_MSG(fp !=
nullptr,
"could not open file");
5317 std::fwrite(buf, 1, sz, fp);
5320 C4_SUPPRESS_WARNING_MSVC_POP
5328 C4_SUPPRESS_WARNING_GCC_CLANG_POP
Holds a pointer to an existing tree, and a node id.
Tree const * tree() const noexcept
id_type id() const noexcept
bool invalid() const noexcept
bool readable() const noexcept
because a ConstNodeRef cannot be used to write to the tree, readable() has the same meaning as !...
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
id_type id() const noexcept
bool invalid() const noexcept
true if the object is not referring to any existing or seed node.
bool readable() const noexcept
true if the object is not invalid and not in seed state.
size_t set_val_serialized(T const &v)
bool is_seed() const noexcept
true if the object is not invalid and in seed state.
This is the main driver of parsing logic: it scans the YAML or JSON source for tokens,...
Location location(Tree const &tree, id_type node_id) const
Get the location of a node of the last tree to be parsed by this parser.
void reserve_stack(id_type capacity)
Reserve a certain capacity for the parsing stack.
csubstr location_contents(Location const &loc) const
Get the string starting at a particular location, to the end of the parsed source buffer.
ParserOptions const & options() const
Get the options used to build this parser object.
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 reserve_arena(size_t arena_cap)
ensure the tree's internal string arena is at least the given capacity
void clear()
clear the tree and zero every node
id_type first_child(id_type node) const
bool is_stream(id_type node) const
NodeRef rootref()
Get the root as a NodeRef.
bool is_map(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
void reserve(id_type node_capacity)
void resolve(ReferenceResolver *rr)
Resolve references (aliases <- anchors) in the tree.
bool in_arena(csubstr s) const
return true if the given substring is part of the tree's string arena
Callbacks const & callbacks() const
id_type next_sibling(id_type node) const
ConstNodeRef crootref() const
Get the root as a ConstNodeRef.
csubstr const & key(id_type node) const
NodeRef docref(id_type i)
get the i-th document of the stream
bool is_doc(id_type node) const
size_t arena_capacity() const
get the current capacity of the tree's internal arena
id_type doc(id_type i) const
gets the i document node index.
void set_val(id_type node, csubstr val)
void normalize_tags_long()
csubstr const & val(id_type node) const
bool is_seq(id_type node) const
std::enable_if< std::is_floating_point< T >::value, csubstr >::type to_arena(T const &a)
serialize the given floating-point variable to the tree's arena, growing it as needed to accomodate t...
id_type find_child(id_type node, csubstr const &key) const
id_type root_id()
Get the id of the root node.
id_type first_sibling(id_type node) const
substr copy_to_arena(csubstr s)
copy the given substr to the tree's arena, growing it by the required size
id_type num_children(id_type node) const
O(num_children)
csubstr arena() const
get the current arena
id_type child(id_type node, id_type pos) const
left_< T > left(T val, size_t width, char padchar=' ')
mark an argument to be aligned left
right_< T > right(T val, size_t width, char padchar=' ')
mark an argument to be aligned right
const_base64_wrapper base64(Args const &...args)
mark a variable to be written in base64 format
size_t base64_decode(csubstr encoded, blob data)
decode the base64 encoding in the given buffer
boolalpha_< T > boolalpha(T const &val, bool strict_read=false)
void(*)(const char *msg, size_t msg_len, Location location, void *user_data) pfn_error
the type of the function used to report errors
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
substr cat_sub(substr buf, Args &&...args)
like c4::cat() but return a substr instead of a size
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.
csubstr catseprs_append(CharOwningContainer *cont, Sep const &sep, Args const &...args)
catsep+resize+append: like 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 emitrs_yaml(Tree const &t, id_type id, EmitOptions const &opts, CharOwningContainer *cont, bool append=false)
(1) emit+resize: emit YAML to the given std::string/std::vector-like container, resizing it as needed...
size_t emit_yaml(Tree const &t, id_type id, EmitOptions const &opts, FILE *f)
(1) emit YAML to the given file, starting at the given node.
integral_< intptr_t > hex(std::nullptr_t)
format null as an hexadecimal value
integral_< intptr_t > bin(std::nullptr_t)
format null as a binary 0-1 value
integral_< intptr_t > oct(std::nullptr_t)
format null as an octal value
bool scalar_is_null(csubstr s) noexcept
YAML-sense query of nullity.
@ MAP
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
@ KEY
is member of a map, must have non-empty key
@ FLOW_SL
mark container with single-line flow style (seqs as '[val1,val2], maps as '{key: val,...
@ SEQ
a seq: a parent of VAL/SEQ/MAP nodes
void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *t, id_type node_id)
(1) parse YAML into an existing tree node. The filename will be used in any error messages arising du...
void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *t, id_type node_id)
(1) parse JSON into an existing tree node. The filename will be used in any error messages arising du...
void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *t, id_type node_id)
(1) parse YAML into an existing tree node.
void sample_fundamental_types()
ryml provides facilities for serializing and deserializing the C++ fundamental types,...
void sample_parse_in_place()
demonstrate in-place parsing of a mutable YAML source buffer.
void sample_quick_overview()
a brief tour over most features
void sample_per_tree_allocator()
void sample_lightning_overview()
a lightning tour over most features see sample_quick_overview
void sample_anchors_and_aliases()
demonstrates usage with anchors and alias references.
~ScopedErrorHandlerExample()
ScopedErrorHandlerExample()
void sample_location_tracking()
demonstrates how to obtain the (zero-based) location of a node from a recently parsed tree
void sample_parse_reuse_tree()
demonstrate reuse/modification of tree when parsing
void check_effect(bool committed) const
void sample_substr()
demonstrate usage of ryml::substr and ryml::csubstr
void sample_tag_directives()
void sample_emit_nested_node()
just like parsing into a nested node, you can also emit from a nested node.
void sample_float_precision()
control precision of serialized floats
bool check_assertion_occurs(Fn &&fn) const
void sample_create_trees()
shows how to programatically create trees
static void s_error(const char *msg, size_t len, ryml::Location loc, void *this_)
void sample_user_scalar_types()
to add scalar types (ie leaf types converting to/from string), define the functions above for those t...
void sample_user_container_types()
shows how to serialize/deserialize container types.
bool check_error_occurs(Fn &&fn) const
void sample_error_handler()
demonstrates how to set a custom error handler for ryml
void sample_parse_in_arena()
demonstrate parsing of a read-only YAML source buffer
void sample_emit_to_file()
demonstrates how to emit to a FILE*
void sample_emit_style()
[experimental] pick flow/block style for certain nodes.
void sample_empty_null_values()
Shows how to deal with empty/null values.
void sample_std_types()
demonstrates usage with the std implementations provided by ryml in the ryml_std.hpp header
ryml::Callbacks callbacks()
a helper to create the Callbacks object with the custom error handler
void sample_emit_to_stream()
demonstrates how to emit to a stream-like structure
void sample_global_allocator()
demonstrates how to set the global allocator for ryml
void sample_formatting()
ryml provides facilities for formatting/deformatting (imported from c4core into the ryml namespace).
void sample_parse_file()
demonstrate how to load a YAML file from disk to parse with ryml.
void sample_json()
shows how to parse and emit JSON.
void sample_emit_to_container()
demonstrates how to emit to a linear container of char
void sample_parse_reuse_tree_and_parser()
for ultimate speed when parsing multiple times, reuse both the tree and parser
void sample_base64()
demonstrates how to read and write base64-encoded blobs.
void sample_static_trees()
shows how to work around the static initialization order fiasco when using a static-duration ryml tre...
void sample_tree_arena()
demonstrates explicit and implicit interaction with the tree's string arena.
void sample_parse_reuse_parser()
Demonstrates reuse of an existing parser.
void sample_iterate_trees()
shows how to programatically iterate through trees
const_raw_wrapper raw(cblob data, size_t alignment=alignof(max_align_t))
mark a variable to be written in raw binary format, using memcpy
const_raw_wrapper craw(cblob data, size_t alignment=alignof(max_align_t))
mark a variable to be written in raw binary format, using memcpy
real_< T > real(T val, int precision, RealFormat_e fmt=FTOA_FLOAT)
void write(ryml::NodeRef *n, my_seq_type< T > const &seq)
bool read(ryml::ConstNodeRef const &n, my_seq_type< T > *seq)
bool from_chars(ryml::csubstr buf, vec2< T > *v)
size_t file_get_contents(const char *filename, CharContainer *v)
load a file from disk into an existing CharContainer
void file_put_contents(const char *filename, CharContainer const &v, const char *access="wb")
save a buffer into a file
C4_IF_EXCEPTIONS_(, static std::jmp_buf s_jmp_env;static std::string s_jmp_msg;) template< class Fn > bool ErrorHandlerExample
this C-style callback is the one stored and used by ryml.
void file_put_contents(const char *filename, const char *buf, size_t sz, const char *access)
save a buffer into a file
bool report_check(int line, const char *predicate, bool result)
CharContainer file_get_contents(const char *filename)
load a file from disk and return a newly created CharContainer
void on_error(const char *msg, size_t len, ryml::Location loc)
this is the where the callback implementation goes.
size_t to_chars(ryml::substr buf, vec2< T > v)
csubstr to_csubstr(substr s) noexcept
neutral version for use in generic code
substr to_substr(substr s) noexcept
neutral version for use in generic code
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)
@ TAG_SET
!!set Unordered set of non-equal values.
@ TAG_INT
!!float Mathematical integers.
@ TAG_SEQ
!!seq Sequence of arbitrary values.
@ TAG_STR
!!str A sequence of zero or more Unicode characters.
@ TAG_MAP
!!map Unordered set of key: value pairs without duplicates.
size_t uncat(csubstr buf, Arg &a, Args &...more)
deserialize the arguments from the given buffer.
size_t uncatsep(csubstr buf, Sep &sep, Arg &a, Args &...more)
deserialize the arguments from the given buffer.
integral_padded_< T > zpad(T val, size_t num_digits)
pad the argument with zeroes on the left, with decimal radix
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
@ npos
a null string position
a c-style callbacks class.
The event handler to create a ryml Tree.
size_t offset
number of bytes from the beginning of the source buffer
Options to give to the parser to control its behavior.
ParserOptions & locations(bool enabled) noexcept
enable/disable source location tracking
mark a tree or node to be emitted as yaml when using operator<<, with options.
auto first_child() RYML_NOEXCEPT -> Impl
Forward to Tree::first_child().
auto children() RYML_NOEXCEPT -> children_view
get an iterable view over children
bool is_val() const RYML_NOEXCEPT
Forward to Tree::is_val().
bool is_root() const RYML_NOEXCEPT
Forward to Tree::is_root().
auto last_child() RYML_NOEXCEPT -> Impl
Forward to Tree::last_child().
bool is_stream() const RYML_NOEXCEPT
Forward to Tree::is_stream().
auto parent() RYML_NOEXCEPT -> Impl
Forward to Tree::parent().
bool has_child(ConstImpl const &n) const RYML_NOEXCEPT
Forward to Tree::has_child().
auto next_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::next_sibling().
auto last_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::last_sibling().
bool is_map() const RYML_NOEXCEPT
Forward to Tree::is_map().
id_type num_siblings() const RYML_NOEXCEPT
O(num_children).
bool has_key() const RYML_NOEXCEPT
Forward to Tree::has_key().
csubstr key() const RYML_NOEXCEPT
Forward to Tree::key().
auto first_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::first_sibling().
csubstr val() const RYML_NOEXCEPT
Forward to Tree::val().
bool is_doc() const RYML_NOEXCEPT
Forward to Tree::is_doc().
id_type num_children() const RYML_NOEXCEPT
O(num_children).
auto child(id_type pos) RYML_NOEXCEPT -> Impl
Forward to Tree::child().
bool is_seq() const RYML_NOEXCEPT
Forward to Tree::is_seq().
bool has_val() const RYML_NOEXCEPT
Forward to Tree::has_val().
auto prev_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::prev_sibling().
this is an example error handler, required for some of the quickstart examples.
static void * s_allocate(size_t len, void *, void *this_)
ryml::Callbacks callbacks()
void free(void *mem, size_t len)
void * allocate(size_t len)
~GlobalAllocatorExample()
std::vector< char > memory_pool
static void s_free(void *mem, size_t len, void *this_)
an example for a per-tree memory allocator
std::vector< char > memory_pool
ryml::Callbacks callbacks() const
void free(void *mem, size_t len)
void * allocate(size_t len)
Shows how to easily create a scoped error handler.
example scalar type, serialized only
example scalar type, serialized only
example scalar type, serialized only
example user container type: map-like
std::map< K, V > map_member
example user container type: seq-like
std::vector< T > seq_member
example user container type with nested container members.
my_map_type< int, int > map
example scalar type, deserialized only
example scalar type, deserialized only
example scalar type, deserialized only
example scalar type, serialized and deserialized
example scalar type, serialized and deserialized
example scalar type, serialized and deserialized