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
2503 t[
"val"] >> valu8;
CHECK(valu8 == 2);
2504 t[
"val"] >> vali8;
CHECK(vali8 == 2);
2506 CHECK(ryml::overflows<uint8_t>(t[
"val"].val()));
2507 CHECK(ryml::overflows<int8_t>(t[
"val"].val()));
2508 CHECK( ! ryml::overflows<int16_t>(t[
"val"].val()));
2511 auto checku8 = ryml::fmt::overflow_checked(valu8);
2512 t[
"val"] >> checku8;
2515 auto checki8 = ryml::fmt::overflow_checked(vali8);
2516 t[
"val"] >> checki8;
2535 all_null: [~, null, Null, NULL]
2536 non_null: [nULL, non_null, non null, null it is not]
2540 CHECK(tree[
"plain"].has_val());
2541 CHECK(tree[
"squoted"].has_val());
2542 CHECK(tree[
"dquoted"].has_val());
2543 CHECK(tree[
"literal"].has_val());
2544 CHECK(tree[
"folded"].has_val());
2545 CHECK( ! tree[
"all_null"].has_val());
2546 CHECK( ! tree[
"non_null"].has_val());
2548 CHECK( ! tree[
"plain"].is_container());
2549 CHECK( ! tree[
"squoted"].is_container());
2550 CHECK( ! tree[
"dquoted"].is_container());
2551 CHECK( ! tree[
"literal"].is_container());
2552 CHECK( ! tree[
"folded"].is_container());
2553 CHECK(tree[
"all_null"].is_container());
2554 CHECK(tree[
"non_null"].is_container());
2559 CHECK(tree[
"plain"].val().len == 0);
2560 CHECK(tree[
"squoted"].val().len == 0);
2561 CHECK(tree[
"dquoted"].val().len == 0);
2562 CHECK(tree[
"literal"].val().len == 0);
2563 CHECK(tree[
"folded"].val().len == 0);
2565 CHECK(tree[
"plain"].val().str ==
nullptr);
2566 CHECK(tree[
"squoted"].val().str !=
nullptr);
2567 CHECK(tree[
"dquoted"].val().str !=
nullptr);
2568 CHECK(tree[
"literal"].val().str !=
nullptr);
2569 CHECK(tree[
"folded"].val().str !=
nullptr);
2573 CHECK(tree[
"plain"].val() ==
nullptr);
2574 CHECK(tree[
"squoted"].val() !=
nullptr);
2575 CHECK(tree[
"dquoted"].val() !=
nullptr);
2576 CHECK(tree[
"literal"].val() !=
nullptr);
2577 CHECK(tree[
"folded"].val() !=
nullptr);
2582 CHECK(tree[
"plain"].val_is_null());
2583 CHECK( ! tree[
"squoted"].val_is_null());
2584 CHECK( ! tree[
"dquoted"].val_is_null());
2585 CHECK( ! tree[
"literal"].val_is_null());
2586 CHECK( ! tree[
"folded"].val_is_null());
2591 CHECK(child.val() !=
nullptr);
2592 CHECK(child.val_is_null());
2596 CHECK(child.val() !=
nullptr);
2597 CHECK( ! child.val_is_null());
2608 ryml::csubstr
null = {};
2609 ryml::csubstr nonnull =
"";
2610 ryml::csubstr strnull =
"null";
2611 ryml::csubstr tilde =
"~";
2612 CHECK(
null .len == 0);
CHECK(
null .str ==
nullptr);
CHECK(
null ==
nullptr);
2613 CHECK(nonnull.len == 0);
CHECK(nonnull.str !=
nullptr);
CHECK(nonnull !=
nullptr);
2614 CHECK(strnull.len != 0);
CHECK(strnull.str !=
nullptr);
CHECK(strnull !=
nullptr);
2615 CHECK(tilde .len != 0);
CHECK(tilde .str !=
nullptr);
CHECK(tilde !=
nullptr);
2620 tree[
"empty_null"] <<
null;
CHECK(tree.
arena() ==
"");
2622 tree[
"empty_nonnull"] << nonnull;
CHECK(tree.
arena() ==
"");
2624 tree[
"str_null"] << strnull;
CHECK(tree.
arena() ==
"null");
2626 tree[
"str_tilde"] << tilde;
CHECK(tree.
arena() ==
"null~");
2628 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null:
2638 auto null_if_nullptr = [](ryml::csubstr s) {
2639 return s.str ==
nullptr ?
"null" : s;
2641 tree[
"empty_null"] << null_if_nullptr(
null);
2642 tree[
"empty_nonnull"] << null_if_nullptr(nonnull);
2643 tree[
"str_null"] << null_if_nullptr(strnull);
2644 tree[
"str_tilde"] << null_if_nullptr(tilde);
2646 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null: null
2654 auto null_if_predicate = [](ryml::csubstr s) {
2657 tree[
"empty_null"] << null_if_predicate(
null);
2658 tree[
"empty_nonnull"] << null_if_predicate(nonnull);
2659 tree[
"str_null"] << null_if_predicate(strnull);
2660 tree[
"str_tilde"] << null_if_predicate(tilde);
2662 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null: null
2670 auto tilde_if_predicate = [](ryml::csubstr s) {
2673 tree[
"empty_null"] << tilde_if_predicate(
null);
2674 tree[
"empty_nonnull"] << tilde_if_predicate(nonnull);
2675 tree[
"str_null"] << tilde_if_predicate(strnull);
2676 tree[
"str_tilde"] << tilde_if_predicate(tilde);
2678 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null: ~
2697 char buf_[256] = {};
2698 ryml::substr buf = buf_;
2699 size_t size =
ryml::format(buf,
"a={} foo {} {} bar {}", 0.1, 10, 11, 12);
2700 CHECK(size == strlen(
"a=0.1 foo 10 11 bar 12"));
2701 CHECK(buf.first(size) ==
"a=0.1 foo 10 11 bar 12");
2704 size =
ryml::format({} ,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12);
2705 CHECK(size ==
ryml::format(buf,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12));
2706 CHECK(size == strlen(
"a=this_is_a foo 10 11 bar 12"));
2708 char smallbuf[8] = {};
2709 size =
ryml::format(smallbuf,
"{} is too large {}",
"this",
"for the buffer");
2710 CHECK(size == strlen(
"this is too large for the buffer"));
2712 CHECK(ryml::substr(smallbuf,
sizeof(smallbuf)) ==
"this is\0");
2716 CHECK(result ==
"b=1, damn it.");
2717 CHECK(result.is_sub(buf));
2735 CHECK(sbuf ==
"and c=2 seems about right");
2736 std::vector<char> vbuf;
2738 CHECK(sbuf ==
"and c=2 seems about right");
2741 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2748 int a = 0, b = 1, c = 2;
2749 ryml::csubstr result =
ryml::format_sub(buf_,
"{} and {} and {}", a, b, c);
2750 CHECK(result ==
"0 and 1 and 2");
2751 int aa = -1, bb = -2, cc = -3;
2752 size_t num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2754 CHECK(num_characters == result.size());
2760 CHECK(result ==
"10 and 20 and 30");
2761 num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2763 CHECK(num_characters == result.size());
2771 char buf_[256] = {};
2772 ryml::substr buf = buf_;
2773 size_t size =
ryml::cat(buf,
"a=", 0.1,
"foo", 10, 11,
"bar", 12);
2774 CHECK(size == strlen(
"a=0.1foo1011bar12"));
2775 CHECK(buf.first(size) ==
"a=0.1foo1011bar12");
2780 char smallbuf[8] = {};
2781 size =
ryml::cat(smallbuf,
"this",
" is too large ",
"for the buffer");
2782 CHECK(size == strlen(
"this is too large for the buffer"));
2784 CHECK(ryml::substr(smallbuf,
sizeof(smallbuf)) ==
"this is\0");
2787 ryml::csubstr result =
ryml::cat_sub(buf,
"b=", 1,
", damn it.");
2788 CHECK(result ==
"b=1, damn it.");
2789 CHECK(result.is_sub(buf));
2806 ryml::catrs(&sbuf,
"and c=", 2,
" seems about right");
2807 CHECK(sbuf ==
"and c=2 seems about right");
2808 std::vector<char> vbuf;
2809 ryml::catrs(&vbuf,
"and c=", 2,
" seems about right");
2810 CHECK(sbuf ==
"and c=2 seems about right");
2813 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2820 int a = 0, b = 1, c = 2;
2821 ryml::csubstr result =
ryml::cat_sub(buf_, a,
' ', b,
' ', c);
2822 CHECK(result ==
"0 1 2");
2823 int aa = -1, bb = -2, cc = -3;
2824 char sep1 =
'a', sep2 =
'b';
2825 size_t num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2826 CHECK(num_characters == result.size());
2834 CHECK(result ==
"10 20 30");
2835 num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2836 CHECK(num_characters == result.size());
2846 char buf_[256] = {};
2847 ryml::substr buf = buf_;
2849 size_t size =
ryml::catsep(buf,
' ',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2850 CHECK(buf.first(size) ==
"a= 0 b= 1 c= 2 45 67");
2853 size =
ryml::catsep(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
2854 CHECK(buf.first(size) ==
"a=0 and b=1 and c=2 and 45 and 67");
2856 size =
ryml::catsep(buf,
" ... ",
"a=0",
"b=1",
"c=2", 45, 67);
2857 CHECK(buf.first(size) ==
"a=0 ... b=1 ... c=2 ... 45 ... 67");
2859 size =
ryml::catsep(buf,
'/',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2860 CHECK(buf.first(size) ==
"a=/0/b=/1/c=/2/45/67");
2862 size =
ryml::catsep(buf, 888,
"a=0",
"b=1",
"c=2", 45, 67);
2863 CHECK(buf.first(size) ==
"a=0888b=1888c=28884588867");
2869 char smallbuf[8] = {};
2871 CHECK(size == strlen(
"a=0888b=1888c=28884588867"));
2873 CHECK(ryml::substr(smallbuf,
sizeof(smallbuf)) ==
"a=0888b\0");
2876 ryml::csubstr result =
ryml::catsep_sub(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
2877 CHECK(result ==
"a=0 and b=1 and c=2 and 45 and 67");
2878 CHECK(result.is_sub(buf));
2896 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67");
2897 std::vector<char> vbuf;
2903 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");
2908 char buf_[256] = {};
2910 int a = 0, b = 1, c = 2;
2912 CHECK(result ==
"0 1 2");
2913 int aa = -1, bb = -2, cc = -3;
2916 CHECK(num_characters == result.size());
2924 CHECK(result ==
"10 20 30");
2926 CHECK(num_characters == result.size());
2935 using namespace ryml;
2936 char buf_[256] = {};
2955 CHECK(
"3735928559" ==
cat_sub(buf, UINT32_C(0xdeadbeef)));
3079 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wcast-align")
3080 const uint32_t payload[] = {10, 20, 30, 40, UINT32_C(0xdeadbeef)};
3082 csubstr expected = csubstr((
const char *)payload,
sizeof(payload));
3084 CHECK(!actual.overlaps(expected));
3085 CHECK(0 == memcmp(expected.str, actual.str, expected.len));
3087 for(
const uint32_t value : payload)
3090 expected = csubstr((
const char *)&value,
sizeof(value));
3092 CHECK(actual.size() ==
sizeof(uint32_t));
3093 CHECK(!actual.overlaps(expected));
3094 CHECK(0 == memcmp(expected.str, actual.str, expected.len));
3097 CHECK(actual.size() ==
sizeof(uint32_t));
3098 CHECK(!actual.overlaps(expected));
3099 CHECK(0 == memcmp(expected.str, actual.str, expected.len));
3104 CHECK(&result == (uint32_t*)reader.buf);
3105 CHECK(reader.len ==
sizeof(uint32_t));
3106 uncat(actual, reader);
3109 result = *(uint32_t*)reader.buf;
3110 CHECK(result == value);
3112 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3131 struct text_and_base64 { ryml::csubstr text,
base64; };
3132 text_and_base64 cases[] = {
3133 {{
"Love all, trust a few, do wrong to none."}, {
"TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg=="}},
3134 {{
"The fool doth think he is wise, but the wise man knows himself to be a fool."}, {
"VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg=="}},
3135 {{
"Brevity is the soul of wit."}, {
"QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu"}},
3136 {{
"All that glitters is not gold."}, {
"QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu"}},
3139 for(text_and_base64 c : cases)
3142 CHECK(tree[c.text].
val() == c.base64);
3145 for(text_and_base64 c : cases)
3148 CHECK(tree[c.base64].
val() == c.text);
3150 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"('Love all, trust a few, do wrong to none.': TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg==
3151 'The fool doth think he is wise, but the wise man knows himself to be a fool.': VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg==
3152 Brevity is the soul of wit.: QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu
3153 All that glitters is not gold.: QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu
3154 TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg==: 'Love all, trust a few, do wrong to none.'
3155 VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg==: 'The fool doth think he is wise, but the wise man knows himself to be a fool.'
3156 QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu: Brevity is the soul of wit.
3157 QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu: All that glitters is not gold.
3159 char buf1_[128], buf2_[128];
3160 ryml::substr buf1 = buf1_;
3161 ryml::substr buf2 = buf2_;
3162 std::string result = {};
3164 for(
const text_and_base64 c : cases)
3169 CHECK(len <= buf1.len);
3170 CHECK(len <= buf2.len);
3171 CHECK(c.text.len == len);
3172 CHECK(buf1.first(len) == c.text);
3173 CHECK(buf2.first(len) == c.text);
3178 if(len > result.size())
3184 CHECK(result == c.text);
3188 ryml::blob strblob(&result[0], result.size());
3189 CHECK(strblob.buf == result.data());
3190 CHECK(strblob.len == result.size());
3192 if(len > result.size())
3195 strblob = {&result[0], result.
size()};
3196 CHECK(strblob.buf == result.data());
3197 CHECK(strblob.len == result.size());
3201 CHECK(result == c.text);
3206 ryml::csubstr encoded = tree[c.text].
val();
3207 CHECK(encoded == c.base64);
3208 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3209 if(len > result.size())
3212 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3215 CHECK(result == c.text);
3218 for(
const text_and_base64 c : cases)
3223 CHECK(len <= buf1.len);
3224 CHECK(len <= buf2.len);
3225 CHECK(c.text.len == len);
3226 CHECK(buf1.first(len) == c.text);
3227 CHECK(buf2.first(len) == c.text);
3231 if(len > result.size())
3237 CHECK(result == c.text);
3241 ryml::blob strblob = {&result[0], result.size()};
3242 CHECK(strblob.buf == result.data());
3243 CHECK(strblob.len == result.size());
3245 if(len > result.size())
3248 strblob = {&result[0], result.
size()};
3249 CHECK(strblob.buf == result.data());
3250 CHECK(strblob.len == result.size());
3254 CHECK(result == c.text);
3259 ryml::csubstr encoded = tree[c.base64].
key();
3260 CHECK(encoded == c.base64);
3261 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3262 if(len > result.size())
3265 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3268 CHECK(result == c.text);
3272 const uint64_t valin = UINT64_C(0xdeadbeef);
3273 uint64_t valout = 0;
3276 CHECK(len <=
sizeof(valout));
3277 CHECK(valout == UINT64_C(0xdeadbeef));
3281 const uint32_t data_in[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xdeadbeef};
3282 uint32_t data_out[11] = {};
3283 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) != 0);
3286 CHECK(len <=
sizeof(data_out));
3287 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3518 CHECK(v2in.x == v2out.x);
3519 CHECK(v2in.y == v2out.y);
3524 CHECK(v3in.x == v3out.x);
3525 CHECK(v3in.y == v3out.y);
3526 CHECK(v3in.z == v3out.z);
3531 CHECK(v4in.x == v4out.x);
3532 CHECK(v4in.y == v4out.y);
3533 CHECK(v4in.z == v4out.z);
3534 CHECK(v4in.w == v4out.w);
3535 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(v2: '(10,11)'
3537 v4: '(1000,1001,1002,1003)'
3547 CHECK(eov2in.x == pov2out.x);
3548 CHECK(eov2in.y == pov2out.y);
3553 CHECK(eov3in.x == pov3out.x);
3554 CHECK(eov3in.y == pov3out.y);
3555 CHECK(eov3in.z == pov3out.z);
3560 CHECK(eov4in.x == pov4out.x);
3561 CHECK(eov4in.y == pov4out.y);
3562 CHECK(eov4in.z == pov4out.z);
3563 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(v2: '(20,21)'
3617 template<
class K,
class V>
3642 template<
class K,
class V>
3670 template<
class K,
class V>
3675 for(
auto const ch : n)
3678 map->
map_member.emplace(std::make_pair(std::move(k), std::move(v)));
3689 n[
"seq"] >> val->
seq;
3690 n[
"map"] >> val->
map;
3709 {{101, 102, 103, 104, 105, 106, 107}},
3710 {{{1001, 2001}, {1002, 2002}, {1003, 2003}}},
3726 CHECK(mt_in.seq.seq_member.size() > 0);
3728 for(
size_t i = 0; i < mt_in.seq.seq_member.size(); ++i)
3732 CHECK(mt_in.map.map_member.size() > 0);
3734 for(
auto const& kv : mt_in.map.map_member)
3739 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(v2: '(20,21)'
3766 std::string yml_std_string = R
"(- v2: '(20,21)'
3783 v4: '(140,141,142,143)'
3798 v4: '(240,241,242,243)'
3816 std::vector<my_type> vmt;
3818 CHECK(vmt.size() == 3);
3821 CHECK(ryml::emitrs_yaml<std::string>(tree_out) == yml_std_string);
3830 std::vector<double> reference{1.23234412342131234, 2.12323123143434237, 3.67847983572591234};
3834 const double precision_safe = 1.e-14;
3835 const size_t num_digits_safe = 14;
3836 const size_t num_digits_original = 17;
3837 auto get_num_digits = [](ryml::csubstr number){
return number.sub(2).len; };
3843 std::vector<double> output;
3845 CHECK(output.size() == reference.size());
3846 for(
size_t i = 0; i < reference.size(); ++i)
3849 CHECK(fabs(output[i] - reference[i]) < precision_safe);
3858 serialized.
rootref() << reference;
3859 std::cout << serialized;
3861 #if (!C4CORE_HAVE_STD_TOCHARS)
3862 CHECK(ryml::emitrs_yaml<std::string>(serialized) == R
"(- 1.23234
3865 )" || (bool)
"this is indicative; the exact results will vary from platform to platform.");
3866 C4_UNUSED(num_digits_safe);
3868 CHECK((ryml::emitrs_yaml<std::string>(serialized) == R
"(- 1.2323441234213124
3869 - 2.1232312314343424
3870 - 3.6784798357259123
3871 )") || (bool)
"this is indicative; the exact results will vary from platform to platform.");
3875 CHECK(get_num_digits(child.val()) >= num_digits_safe);
3878 CHECK(fabs(out - reference[pos++]) < precision_safe);
3909 auto check_precision = [&](
ryml::Tree serialized){
3910 std::cout << serialized;
3912 CHECK((ryml::emitrs_yaml<std::string>(serialized) == R
"(- 1.23234412342131239
3913 - 2.12323123143434245
3914 - 3.67847983572591231
3915 )") || (bool)
"this is indicative; the exact results will vary from platform to platform.");
3919 CHECK(get_num_digits(child.val()) == num_digits_original);
3922 CHECK(fabs(out - reference[pos++]) < precision_safe);
3931 for(
const double v : reference)
3933 check_precision(serialized);
3942 for(
const double v : reference)
3947 (void)snprintf(tmp,
sizeof(tmp),
"%.18g", v);
3953 check_precision(serialized);
3965 ryml::csubstr ymla =
"- 1\n- 2\n";
3966 ryml::csubstr ymlb = R
"(- a
3970 - champagne: Dom Perignon
3973 vinho verde: Soalheiro
3974 vinho tinto: Redoma 2017
3992 ryml::csubstr output =
ryml::emit_yaml(treea, treea.root_id(), ryml::substr{},
false);
3993 CHECK(output.str ==
nullptr);
3994 CHECK(output.len > 0);
3995 size_t num_needed_chars = output.len;
3996 std::vector<char> buf(num_needed_chars);
3999 CHECK(output == ymla);
4003 output =
ryml::emit_yaml(treeb, treeb.root_id(), ryml::substr{},
false);
4004 CHECK(output.str ==
nullptr);
4005 CHECK(output.len > 0);
4006 CHECK(output.len == ymlb.len);
4007 num_needed_chars = output.len;
4008 buf.resize(num_needed_chars);
4011 CHECK(output == ymlb);
4016 CHECK(output == ymlb);
4020 std::vector<char> another = ryml::emitrs_yaml<std::vector<char>>(treeb);
4024 another = ryml::emitrs_yaml<std::vector<char>>(treeb[3][2]);
4026 vinho verde: Soalheiro
4027 vinho tinto: Redoma 2017
4037 ryml::csubstr output =
ryml::emit_yaml(treea, treea.root_id(), ryml::substr{},
false);
4038 CHECK(output.str ==
nullptr);
4039 CHECK(output.len > 0);
4040 size_t num_needed_chars = output.len;
4042 buf.resize(num_needed_chars);
4045 CHECK(output == ymla);
4049 output =
ryml::emit_yaml(treeb, treeb.root_id(), ryml::substr{},
false);
4050 CHECK(output.str ==
nullptr);
4051 CHECK(output.len > 0);
4052 CHECK(output.len == ymlb.len);
4053 num_needed_chars = output.len;
4054 buf.resize(num_needed_chars);
4057 CHECK(output == ymlb);
4062 CHECK(output == ymlb);
4066 std::string another = ryml::emitrs_yaml<std::string>(treeb);
4070 another = ryml::emitrs_yaml<std::string>(treeb[3][2]);
4072 vinho verde: Soalheiro
4073 vinho tinto: Redoma 2017
4084 ryml::csubstr ymlb = R
"(- a
4088 - champagne: Dom Perignon
4091 vinho verde: Soalheiro
4092 vinho tinto: Redoma 2017
4108 std::stringstream ss;
4116 std::stringstream ss;
4119 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"])");
4124 std::stringstream ss;
4128 vinho verde: Soalheiro
4129 vinho tinto: Redoma 2017
4135 std::stringstream ss;
4138 CHECK(
ryml::to_csubstr(s) == R
"("more": {"vinho verde": "Soalheiro","vinho tinto": "Redoma 2017"})");
4148 ryml::csubstr yml = R
"(- a
4152 - champagne: Dom Perignon
4155 vinho verde: Soalheiro
4156 vinho tinto: Redoma 2017
4172 CHECK(len == yml.len);
4185 - champagne: Dom Perignon
4188 vinho verde: Soalheiro
4189 vinho tinto: Redoma 2017
4202 CHECK(ryml::emitrs_yaml<std::string>(tree[3]["beer"]) == R
"(beer:
4210 CHECK(ryml::emitrs_yaml<std::string>(tree[3]["beer"][0]) ==
"Rochefort 10\n");
4211 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"beer"][3]) == R
"(- and so
4239 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(NodeOne:
4256 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(NodeOne:
4257 - {key: a,desc: b,class: c,number: d}
4258 - {key: e,desc: f,class: g,number: h}
4259 - {key: i,desc: j,class: k,number: l}
4262 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}]
4265 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}]})");
4275 ryml::csubstr json = R
"({
4276 "doe":"a deer, a female deer",
4277 "ray":"a drop of golden sun",
4278 "me":"a name, I call myself",
4279 "far":"a long long way to go"
4289 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"})");
4290 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"})");
4292 std::stringstream ss;
4294 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"})");
4333 std::string unresolved = R
"(base: &base
4334 name: Everyone has same name
4345 city: East Centerville
4348 &keyref key: &valref val
4351 std::string resolved = R"(base:
4352 name: Everyone has same name
4354 name: Everyone has same name
4357 name: Everyone has same name
4363 city: East Centerville
4369 city: East Centerville
4377 CHECK( ! tree[
"base"].has_key_anchor());
4378 CHECK( tree[
"base"].has_val_anchor());
4379 CHECK( tree[
"base"].val_anchor() ==
"base");
4380 CHECK( tree[
"key"].key_anchor() ==
"keyref");
4381 CHECK( tree[
"key"].val_anchor() ==
"valref");
4382 CHECK( tree[
"*valref"].is_key_ref());
4383 CHECK( tree[
"*valref"].is_val_ref());
4384 CHECK( tree[
"*valref"].key_ref() ==
"valref");
4385 CHECK( tree[
"*valref"].val_ref() ==
"keyref");
4392 CHECK( ! tree[
"base"].has_key_anchor());
4393 CHECK( ! tree[
"base"].has_val_anchor());
4394 CHECK( ! tree[
"base"].has_val_anchor());
4395 CHECK( ! tree[
"key"].has_key_anchor());
4396 CHECK( ! tree[
"key"].has_val_anchor());
4397 CHECK( ! tree[
"val"].is_key_ref());
4398 CHECK( ! tree[
"val"].is_val_ref());
4400 CHECK(tree[
"ship_to"][
"city"].val() ==
"East Centerville");
4401 CHECK(tree[
"ship_to"][
"state"].val() ==
"KS");
4409 const std::string yaml = R
"(--- !!map
4435 CHECK(doc.is_doc());
4437 CHECK(root[0].has_val_tag());
4438 CHECK(root[0].val_tag() ==
"!!map");
4439 CHECK(root[1].val_tag() ==
"!map");
4440 CHECK(root[2].val_tag() ==
"!!seq");
4441 CHECK(root[3].val_tag() ==
"!!str");
4442 CHECK(root[4].val_tag() ==
"!!str");
4443 CHECK(root[5][
"a"].has_key_tag());
4444 CHECK(root[5][
"a"].key_tag() ==
"!!str");
4445 CHECK(root[6].val_tag() ==
"!!set");
4446 CHECK(root[7].val_tag() ==
"!!set");
4447 CHECK(root[8].val_tag() ==
"!!seq");
4448 CHECK(root[8][0].val_tag() ==
"!!int");
4449 CHECK(root[8][1].val_tag() ==
"!!str");
4498 CHECK(ryml::emitrs_yaml<std::string>(normalized_tree) == R
"(--- !!map
4521 CHECK(ryml::emitrs_yaml<std::string>(normalized_tree_long) == R
"(--- !<tag:yaml.org,2002:map>
4526 --- !<tag:yaml.org,2002:seq>
4529 --- !<tag:yaml.org,2002:str> a b
4530 --- !<tag:yaml.org,2002:str> 'a: b'
4532 !<tag:yaml.org,2002:str> a: b
4533 --- !<tag:yaml.org,2002:set>
4536 --- !<tag:yaml.org,2002:set>
4538 --- !<tag:yaml.org,2002:seq>
4539 - !<tag:yaml.org,2002:int> 0
4540 - !<tag:yaml.org,2002:str> 1
4549 const std::string yaml = R
"(
4552 !m!light fluorescent
4559 CHECK(ryml::emitrs_yaml<std::string>(tree) == R"(%TAG !m! !my-
4560 --- !m!light fluorescent
4568 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(%TAG !m! !my-
4569 --- !<!my-light> fluorescent
4572 --- !<!meta-light> green
4583 std::string yml = R
"(---
4596 CHECK(ryml::emitrs_yaml<std::string>(tree) == yml);
4607 CHECK(doc.is_doc());
4624 CHECK(stream[0].is_doc());
4625 CHECK(stream[0].is_map());
4626 CHECK(stream[0][
"a"].val() ==
"0");
4627 CHECK(stream[0][
"b"].val() ==
"1");
4636 CHECK(stream[1].is_doc());
4637 CHECK(stream[1].is_map());
4638 CHECK(stream[1][
"c"].val() ==
"2");
4639 CHECK(stream[1][
"d"].val() ==
"3");
4648 CHECK(stream[2].is_doc());
4649 CHECK(stream[2].is_seq());
4650 CHECK(stream[2][0].val() ==
"4");
4651 CHECK(stream[2][1].val() ==
"5");
4652 CHECK(stream[2][2].val() ==
"6");
4653 CHECK(stream[2][3].val() ==
"7");
4672 const std::string expected_json[] = {
4673 R
"({"a": 0,"b": 1})",
4674 R"({"c": 2,"d": 3})",
4683 CHECK(ryml::emitrs_json<std::string>(doc) == expected_json[count++]);
4691 CHECK(ryml::emitrs_json<std::string>(tree, doc_id) == expected_json[count++]);
4728 ryml::Tree tree = ryml::parse_in_arena(
"errorhandler.yml",
"[a: b\n}");
4768 uintptr_t uptr = (uintptr_t)ptr;
4769 const uintptr_t align =
alignof(max_align_t);
4772 uintptr_t prev = uptr - (uptr % align);
4773 uintptr_t next = prev + align;
4774 uintptr_t corr = next - uptr;
4775 ptr = (
void*)(((
char*)ptr) + corr);
4779 "out of memory! requested=%zu+%zu available=%zu\n",
4802 static void s_free(
void *mem,
size_t len,
void *this_)
4874 parse_in_arena(&parser,
"", R
"([a, b, c, d, {foo: bar, money: pennys}])", &tree);
4917 std::cerr <<
"out of memory! requested=" <<
alloc_size <<
" vs " <<
memory_pool.size() <<
" available" << std::endl;
4968 ryml::csubstr yml1 =
"{a: b}";
4969 ryml::csubstr yml2 =
"{c: d, e: f, g: [h, i, 0, 1, 2, 3]}";
5002 CHECK(tree["doe"].val() ==
"a deer, a female deer");
5016 ryml::csubstr yaml = R
"({
5018 foo: [one, [two, three]]
5061 loc = parser.
location(tree[
"foo"]);
5066 loc = parser.
location(tree[
"foo"][0]);
5071 loc = parser.
location(tree[
"foo"][1]);
5075 loc = parser.
location(tree[
"foo"][1][0]);
5079 loc = parser.
location(tree[
"foo"][1][1]);
5109 - nested first value
5110 - nested second value
5113 nested second: value
5127 loc = parser.
location(tree2[
"a new"]);
5132 loc = parser.
location(tree2[
"to"]);
5138 loc = parser.
location(tree2[
"map with key"]);
5142 loc = parser.
location(tree2[
"map with key"][
"first"]);
5146 loc = parser.
location(tree2[
"map with key"][
"second"]);
5151 loc = parser.
location(tree2[
"seq with key"]);
5155 loc = parser.
location(tree2[
"seq with key"][0]);
5159 loc = parser.
location(tree2[
"seq with key"][1]);
5164 loc = parser.
location(tree2[
"seq with key"][2]);
5168 loc = parser.
location(tree2[
"seq with key"][2][0]);
5173 loc = parser.
location(tree2[
"seq with key"][3]);
5177 loc = parser.
location(tree2[
"seq with key"][3][0]);
5193 static int num_checks = 0;
5194 static int num_failed_checks = 0;
5201 const char *msg = predicate ?
"OK! " :
"OK!";
5204 ++num_failed_checks;
5205 msg = predicate ?
"ERROR: " :
"ERROR";
5207 std::cout << __FILE__ <<
':' << line <<
": " << msg << (predicate ? predicate :
"") << std::endl;
5214 std::cout <<
"Completed " << num_checks <<
" checks." << std::endl;
5215 if(num_failed_checks)
5216 std::cout <<
"ERROR: " << num_failed_checks <<
'/' << num_checks <<
" checks failed." << std::endl;
5218 std::cout <<
"SUCCESS!" << std::endl;
5219 return num_failed_checks;
5227 static std::jmp_buf s_jmp_env;
5228 static std::string s_jmp_msg;
5235 bool expected_error_occurred =
false;
5242 expected_error_occurred =
true;
5244 return expected_error_occurred;
5266 std::string full_msg = ryml::formatrs<std::string>(
5267 "{}:{}:{} ({}B): ERROR: {}",
5271 throw std::runtime_error(full_msg);
5275 s_jmp_msg = full_msg;
5276 std::longjmp(s_jmp_env, 1);
5304 C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4996)
5306 template<class CharContainer>
5309 std::FILE *fp = std::fopen(filename,
"rb");
5310 RYML_CHECK_MSG(fp !=
nullptr,
"could not open file");
5311 std::fseek(fp, 0, SEEK_END);
5312 long sz = std::ftell(fp);
5313 v->resize(
static_cast<typename CharContainer::size_type
>(sz));
5317 size_t ret = std::fread(&(*v)[0], 1, v->size(), fp);
5318 RYML_CHECK(ret == (
size_t)sz);
5325 template<
class CharContainer>
5334 template<
class CharContainer>
5343 std::FILE *fp = std::fopen(filename, access);
5344 RYML_CHECK_MSG(fp !=
nullptr,
"could not open file");
5345 std::fwrite(buf, 1, sz, fp);
5348 C4_SUPPRESS_WARNING_MSVC_POP
5356 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.
auto to_arena(T const &a) -> typename std::enable_if< std::is_floating_point< T >::value, csubstr >::type
serialize the given floating-point variable to the tree's arena, growing it as needed to accomodate t...
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
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
@ 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