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>
128 C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
129 C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wcast-qual")
130 C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast")
131 C4_SUPPRESS_WARNING_GCC("-Wuseless-cast")
133 C4_SUPPRESS_WARNING_GCC_WITH_PUSH(
"-Wnull-dereference")
206 bool report_check(
int line,
const char *predicate,
bool result);
211 #if (defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
213 #define CHECK CheckPredicate{__FILE__, __LINE__}
214 struct CheckPredicate
218 void operator() (
bool predicate)
const
230 #define CHECK(predicate) do { if(!report_check(__LINE__, #predicate, (predicate))) { RYML_DEBUG_BREAK(); } } while(0)
234 #define CHECK(predicate) assert(predicate)
239 template<
class CharContainer> CharContainer
file_get_contents(
const char *filename);
240 template<
class CharContainer>
size_t file_get_contents(
const char *filename, CharContainer *v);
241 template<
class CharContainer>
void file_put_contents(
const char *filename, CharContainer
const& v,
const char* access=
"wb");
242 void file_put_contents(
const char *filename,
const char *buf,
size_t sz,
const char* access);
277 char yml_buf[] =
"{foo: 1, bar: [2, 3], john: doe}";
282 CHECK(bar[0].val() ==
"2");
283 CHECK(bar[1].val() ==
"3");
284 CHECK(bar[0].val().str == yml_buf + 15);
285 CHECK(bar[1].val().str == yml_buf + 18);
288 int bar0 = 0, bar1 = 0;
297 CHECK(bar[0].val() ==
"10");
298 CHECK(bar[1].val() ==
"11");
302 CHECK(bar[2].val() ==
"12");
306 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"({foo: 1,bar: [10,11,12],john: doe})");
313 CHECK(ryml::emitrs_yaml<std::string>(foo) ==
"foo: 1\n");
393 CHECK(tree[
"foo"].is_keyval());
394 CHECK(tree[
"foo"].val() ==
"1");
396 CHECK(tree[
"bar"].is_seq());
397 CHECK(tree[
"bar"].has_key());
400 CHECK(tree[
"bar"][0].val() ==
"2");
401 CHECK(tree[
"bar"][1].val() ==
"3");
402 CHECK(tree[
"john"].val() ==
"doe");
406 CHECK(tree[0].
id() == tree[
"foo"].
id());
407 CHECK(tree[1].
id() == tree[
"bar"].
id());
408 CHECK(tree[2].
id() == tree[
"john"].
id());
410 CHECK(tree[0].
id() == tree[
"foo"].
id());
411 CHECK(tree[1].
id() == tree[
"bar"].
id());
412 CHECK(tree[2].
id() == tree[
"john"].
id());
414 CHECK(bar[0].val() ==
"2");
415 CHECK(bar[1].val() ==
"3");
422 CHECK(tree[
"john"].
key() ==
"john");
427 CHECK(root[
"foo"].
id() == root[0].
id());
428 CHECK(root[
"bar"].
id() == root[1].
id());
429 CHECK(root[
"john"].
id() == root[2].
id());
483 ryml::csubstr expected_keys[] = {
"foo",
"bar",
"john"};
488 CHECK(child.key() == expected_keys[count++]);
494 CHECK(child.key() == expected_keys[count++]);
500 CHECK(tree.
key(child_id) == expected_keys[count++]);
509 CHECK(tree.
key(child_id) == expected_keys[count++]);
564 int foo = 0, bar0 = 0, bar1 = 0;
565 std::string john_str;
568 root[
"bar"][0] >> bar0;
569 root[
"bar"][1] >> bar1;
570 root[
"john"] >> john_str;
575 CHECK(john_str ==
"doe");
576 CHECK(bar_str ==
"bar");
593 wroot[
"foo"] =
"says you";
594 wroot[
"bar"][0] =
"-2";
595 wroot[
"bar"][1] =
"-3";
596 wroot[
"john"] =
"ron";
600 CHECK(root[
"foo"].val() ==
"says you");
601 CHECK(root[
"bar"][0].val() ==
"-2");
602 CHECK(root[
"bar"][1].val() ==
"-3");
603 CHECK(root[
"john"].val() ==
"ron");
618 wroot[
"foo"] <<
"says who";
619 wroot[
"bar"][0] << 20;
620 wroot[
"bar"][1] << 30;
621 wroot[
"john"] <<
"deere";
622 CHECK(root[
"foo"].val() ==
"says who");
623 CHECK(root[
"bar"][0].val() ==
"20");
624 CHECK(root[
"bar"][1].val() ==
"30");
625 CHECK(root[
"john"].val() ==
"deere");
629 std::string ok(
"in_scope");
633 CHECK(root[
"john"].val() ==
"in_scope");
635 wroot[
"float"] << 2.4;
639 CHECK(tree.
arena() ==
"says who2030deerein_scope2.42.400000");
647 wroot[
"newkeyval"] =
"shiny and new";
650 CHECK(root[
"newkeyval"].
key() ==
"newkeyval");
651 CHECK(root[
"newkeyval"].val() ==
"shiny and new");
652 CHECK(root[
"newkeyval (serialized)"].
key() ==
"newkeyval (serialized)");
653 CHECK(root[
"newkeyval (serialized)"].val() ==
"shiny and new (serialized)");
659 CHECK(root[
"bar"].num_children() == 2);
660 wroot[
"bar"][2] =
"oh so nice";
661 wroot[
"bar"][3] <<
"oh so nice (serialized)";
662 CHECK(root[
"bar"].num_children() == 4);
663 CHECK(root[
"bar"][2].val() ==
"oh so nice");
664 CHECK(root[
"bar"][3].val() ==
"oh so nice (serialized)");
670 CHECK(root[
"newseq"].num_children() == 0);
671 CHECK(root[
"newseq"].is_seq());
672 CHECK(root[
"newseq (serialized)"].num_children() == 0);
673 CHECK(root[
"newseq (serialized)"].is_seq());
679 CHECK(root[
"newmap"].num_children() == 0);
680 CHECK(root[
"newmap"].is_map());
681 CHECK(root[
"newmap (serialized)"].num_children() == 0);
682 CHECK(root[
"newmap (serialized)"].is_map());
710 nothing = wroot[
"I am nothing"];
725 something =
"indeed";
727 CHECK(root[
"I am something"].val() ==
"indeed");
758 CHECK(wbar[0].readable() && wbar[0].val() ==
"20");
759 CHECK( ! wbar[100].readable());
760 CHECK( ! wbar[100].readable() || wbar[100].val() ==
"100");
762 CHECK( ! wbar[0].is_seed() && wbar[0].val() ==
"20");
763 CHECK(wbar[100].is_seed() || wbar[100].val() ==
"100");
791 return seed_node.at(
"is").at(
"an").at(
"invalid").at(
"operation");
798 return seed_node[
"is"][
"an"][
"invalid"][
"operation"];
808 ryml::csubstr expected_result = R
"(foo: says who
809 bar: [20,30,oh so nice,oh so nice (serialized)]
813 newkeyval: shiny and new
814 newkeyval (serialized): shiny and new (serialized)
816 newseq (serialized): []
818 newmap (serialized): {}
819 I am something: indeed
825 std::stringstream ss;
827 std::string stream_result = ss.str();
829 std::string str_result = ryml::emitrs_yaml<std::string>(tree);
834 CHECK(buf_result == expected_result);
835 CHECK(str_result == expected_result);
836 CHECK(stream_result == expected_result);
852 CHECK(tree[
"bar"][0].val() ==
"21");
854 CHECK(tree[
"bar"][0].val() ==
"22");
860 constnoderef = noderef;
866 noderef = tree[
"bar"][0];
867 constnoderef = consttree[
"bar"][0];
871 CHECK(constnoderef == noderef);
872 CHECK(!(constnoderef != noderef));
897 fr: Planète (Gazeuse)
901 # UTF8 decoding only happens in double-quoted strings,
902 # as per the YAML standard
903 decode this: "\u263A c\x61f\xE9"
904 and this as well: "\u2705 \U0001D11E"
905 not decoded: '\u263A \xE2\x98\xBA'
906 neither this: '\u2705 \U0001D11E'
909 CHECK(langs[
"en"].val() ==
"Planet (Gas)");
910 CHECK(langs[
"fr"].val() ==
"Planète (Gazeuse)");
911 CHECK(langs[
"ru"].val() ==
"Планета (Газ)");
912 CHECK(langs[
"ja"].val() ==
"惑星(ガス)");
913 CHECK(langs[
"zh"].val() ==
"行星(气体)");
917 CHECK(langs[
"decode this"].val() ==
"☺ café");
918 CHECK(langs[
"and this as well"].val() ==
"✅ 𝄞");
919 CHECK(langs[
"not decoded"].val() ==
"\\u263A \\xE2\\x98\\xBA");
920 CHECK(langs[
"neither this"].val() ==
"\\u2705 \\U0001D11E");
948 const char foobar_str[] =
"foobar";
949 auto s = ryml::csubstr(foobar_str, strlen(foobar_str));
950 CHECK(s ==
"foobar");
951 CHECK(s.size() == 6);
952 CHECK(s.data() == foobar_str);
953 CHECK(s.size() == s.len);
954 CHECK(s.data() == s.str);
959 const char foobar_str[] =
"foobar";
960 ryml::csubstr s = foobar_str;
961 CHECK(s ==
"foobar");
962 CHECK(s !=
"foobar0");
963 CHECK(s.size() == 6);
964 CHECK(s.data() == foobar_str);
965 CHECK(s.size() == s.len);
966 CHECK(s.data() == s.str);
970 ryml::csubstr s =
"foobar";
971 CHECK(s ==
"foobar");
972 CHECK(s !=
"foobar0");
973 CHECK(s.size() == 6);
974 CHECK(s.size() == s.len);
975 CHECK(s.data() == s.str);
984 const char *foobar_str =
"foobar";
986 CHECK(s ==
"foobar");
987 CHECK(s !=
"foobar0");
988 CHECK(s.size() == 6);
989 CHECK(s.size() == s.len);
990 CHECK(s.data() == s.str);
1001 std::string foobar_str =
"foobar";
1003 CHECK(s ==
"foobar");
1004 CHECK(s !=
"foobar0");
1005 CHECK(s.size() == 6);
1006 CHECK(s.size() == s.len);
1007 CHECK(s.data() == s.str);
1013 ryml::substr foo = buf;
1014 CHECK(foo.len == 3);
1015 CHECK(foo.data() == buf);
1016 ryml::csubstr cfoo = foo;
1017 CHECK(cfoo.data() == buf);
1026 char const foobar_str_ro[] =
"foobar";
1027 char foobar_str_rw[] =
"foobar";
1028 static_assert(std::is_array<decltype(foobar_str_ro)>::value,
"this is an array");
1029 static_assert(std::is_array<decltype(foobar_str_rw)>::value,
"this is an array");
1032 ryml::csubstr foobar = foobar_str_ro;
1033 CHECK(foobar.data() == foobar_str_ro);
1034 CHECK(foobar.size() == strlen(foobar_str_ro));
1035 CHECK(foobar ==
"foobar");
1039 ryml::csubstr foobar = foobar_str_rw;
1040 CHECK(foobar.data() == foobar_str_rw);
1041 CHECK(foobar.size() == strlen(foobar_str_rw));
1042 CHECK(foobar ==
"foobar");
1046 ryml::substr foobar = foobar_str_rw;
1047 CHECK(foobar.data() == foobar_str_rw);
1048 CHECK(foobar.size() == strlen(foobar_str_rw));
1049 CHECK(foobar ==
"foobar");
1060 char const* foobar_str_ro =
"foobar";
1061 char foobar_str_rw_[] =
"foobar";
1062 char * foobar_str_rw = foobar_str_rw_;
1063 static_assert(!std::is_array<decltype(foobar_str_ro)>::value,
"this is a decayed pointer");
1064 static_assert(!std::is_array<decltype(foobar_str_rw)>::value,
"this is a decayed pointer");
1069 CHECK(foobar.data() == foobar_str_ro);
1070 CHECK(foobar.size() == strlen(foobar_str_ro));
1071 CHECK(foobar ==
"foobar");
1076 CHECK(foobar.data() == foobar_str_rw);
1077 CHECK(foobar.size() == strlen(foobar_str_rw));
1078 CHECK(foobar ==
"foobar");
1083 CHECK(foobar.data() == foobar_str_rw);
1084 CHECK(foobar.size() == strlen(foobar_str_rw));
1085 CHECK(foobar ==
"foobar");
1095 char buf[] =
"foobar";
1096 ryml::substr foobar = buf;
1097 CHECK(foobar ==
"foobar");
1098 foobar[0] =
'F';
CHECK(foobar ==
"Foobar");
1099 foobar.back() =
'R';
CHECK(foobar ==
"FoobaR");
1100 foobar.reverse();
CHECK(foobar ==
"RabooF");
1101 foobar.reverse();
CHECK(foobar ==
"FoobaR");
1102 foobar.reverse_sub(1, 4);
CHECK(foobar ==
"FabooR");
1103 foobar.reverse_sub(1, 4);
CHECK(foobar ==
"FoobaR");
1104 foobar.reverse_range(2, 5);
CHECK(foobar ==
"FoaboR");
1105 foobar.reverse_range(2, 5);
CHECK(foobar ==
"FoobaR");
1106 foobar.replace(
'o',
'0');
CHECK(foobar ==
"F00baR");
1107 foobar.replace(
'a',
'_');
CHECK(foobar ==
"F00b_R");
1108 foobar.replace(
"_0b",
'a');
CHECK(foobar ==
"FaaaaR");
1109 foobar.toupper();
CHECK(foobar ==
"FAAAAR");
1110 foobar.tolower();
CHECK(foobar ==
"faaaar");
1111 foobar.fill(
'.');
CHECK(foobar ==
"......");
1119 ryml::csubstr s =
"fooFOObarBAR";
1120 CHECK(s.len == 12u);
1122 CHECK(s.sub(0) ==
"fooFOObarBAR");
1123 CHECK(s.sub(0, 12) ==
"fooFOObarBAR");
1124 CHECK(s.sub(0, 3) ==
"foo" );
1125 CHECK(s.sub(3) ==
"FOObarBAR");
1126 CHECK(s.sub(3, 3) ==
"FOO" );
1127 CHECK(s.sub(6) ==
"barBAR");
1128 CHECK(s.sub(6, 3) ==
"bar" );
1129 CHECK(s.sub(9) ==
"BAR");
1130 CHECK(s.sub(9, 3) ==
"BAR");
1132 CHECK(s.first(0) ==
"" );
1133 CHECK(s.first(1) ==
"f" );
1134 CHECK(s.first(2) !=
"f" );
1135 CHECK(s.first(2) ==
"fo" );
1136 CHECK(s.first(3) ==
"foo");
1138 CHECK(s.last(0) ==
"");
1139 CHECK(s.last(1) ==
"R");
1140 CHECK(s.last(2) ==
"AR");
1141 CHECK(s.last(3) ==
"BAR");
1143 CHECK(s.range(0, 12) ==
"fooFOObarBAR");
1144 CHECK(s.range(1, 12) ==
"ooFOObarBAR");
1145 CHECK(s.range(1, 11) ==
"ooFOObarBA" );
1146 CHECK(s.range(2, 10) ==
"oFOObarB" );
1147 CHECK(s.range(3, 9) ==
"FOObar" );
1149 CHECK(s.offs(0, 0) ==
"fooFOObarBAR");
1150 CHECK(s.offs(1, 0) ==
"ooFOObarBAR");
1151 CHECK(s.offs(1, 1) ==
"ooFOObarBA" );
1152 CHECK(s.offs(2, 1) ==
"oFOObarBA" );
1153 CHECK(s.offs(2, 2) ==
"oFOObarB" );
1154 CHECK(s.offs(3, 3) ==
"FOObar" );
1156 CHECK(s.right_of(0,
true) ==
"fooFOObarBAR");
1157 CHECK(s.right_of(0,
false) ==
"ooFOObarBAR");
1158 CHECK(s.right_of(1,
true) ==
"ooFOObarBAR");
1159 CHECK(s.right_of(1,
false) ==
"oFOObarBAR");
1160 CHECK(s.right_of(2,
true) ==
"oFOObarBAR");
1161 CHECK(s.right_of(2,
false) ==
"FOObarBAR");
1162 CHECK(s.right_of(3,
true) ==
"FOObarBAR");
1163 CHECK(s.right_of(3,
false) ==
"OObarBAR");
1165 CHECK(s.left_of(12,
false) ==
"fooFOObarBAR");
1166 CHECK(s.left_of(11,
true) ==
"fooFOObarBAR");
1167 CHECK(s.left_of(11,
false) ==
"fooFOObarBA" );
1168 CHECK(s.left_of(10,
true) ==
"fooFOObarBA" );
1169 CHECK(s.left_of(10,
false) ==
"fooFOObarB" );
1170 CHECK(s.left_of( 9,
true) ==
"fooFOObarB" );
1171 CHECK(s.left_of( 9,
false) ==
"fooFOObar" );
1173 ryml::csubstr FOO = s.sub(3, 3);
1174 CHECK(s.is_super(FOO));
1175 CHECK(s.left_of(FOO) ==
"foo");
1176 CHECK(s.right_of(FOO) ==
"barBAR");
1181 ryml::csubstr s =
"some substring";
1182 ryml::csubstr some = s.first(4);
1183 CHECK(some ==
"some");
1184 CHECK(s ==
"some substring");
1187 char result[32] = {0};
1188 std::snprintf(result,
sizeof(result),
"%.*s", (
int)some.len, some.str);
1189 printf(
"~~~%s~~~\n", result);
1199 char result[32] = {0};
1200 std::snprintf(result,
sizeof(result),
"%s", some.str);
1208 ryml::csubstr s =
"some substring";
1209 ryml::csubstr some = s.first(4);
1210 CHECK(some ==
"some");
1211 CHECK(s ==
"some substring");
1214 std::stringstream ss;
1216 CHECK(ss.str() ==
"some substring");
1217 CHECK(ss.str() == s);
1225 std::stringstream ss;
1227 CHECK(ss.str() ==
"some substring");
1228 CHECK(ss.str() == s);
1232 std::stringstream ss;
1234 CHECK(ss.str() ==
"some substring");
1235 CHECK(ss.str() == s);
1239 std::stringstream ss;
1241 CHECK(ss.str() ==
"some");
1242 CHECK(ss.str() == some);
1248 ryml::csubstr foobar =
"foobar";
1249 ryml::csubstr foo = foobar.first(3);
1250 CHECK(foo.is_sub(foobar));
1251 CHECK(foo.is_sub(foo));
1252 CHECK(!foo.is_super(foobar));
1253 CHECK(!foobar.is_sub(foo));
1255 CHECK(foo.is_super(foo));
1256 CHECK(foo.is_sub(foo));
1257 CHECK(foobar.is_sub(foobar));
1258 CHECK(foobar.is_super(foobar));
1263 ryml::csubstr foobar =
"foobar";
1264 ryml::csubstr foo = foobar.first(3);
1265 ryml::csubstr oba = foobar.offs(2, 1);
1266 ryml::csubstr abc =
"abc";
1267 CHECK(foobar.overlaps(foo));
1268 CHECK(foobar.overlaps(oba));
1269 CHECK(foo.overlaps(foobar));
1270 CHECK(foo.overlaps(oba));
1271 CHECK(!foo.overlaps(abc));
1272 CHECK(!abc.overlaps(foo));
1279 CHECK(ryml::csubstr(
" \t\n\rcontents without whitespace\t \n\r").trim(
"\t \n\r") ==
"contents without whitespace");
1280 ryml::csubstr aaabbb =
"aaabbb";
1281 ryml::csubstr aaa___bbb =
"aaa___bbb";
1283 CHECK(aaabbb.triml(
'a') == aaabbb.last(3));
1284 CHECK(aaabbb.trimr(
'a') == aaabbb);
1285 CHECK(aaabbb.trim (
'a') == aaabbb.last(3));
1286 CHECK(aaabbb.triml(
'b') == aaabbb);
1287 CHECK(aaabbb.trimr(
'b') == aaabbb.first(3));
1288 CHECK(aaabbb.trim (
'b') == aaabbb.first(3));
1289 CHECK(aaabbb.triml(
'c') == aaabbb);
1290 CHECK(aaabbb.trimr(
'c') == aaabbb);
1291 CHECK(aaabbb.trim (
'c') == aaabbb);
1292 CHECK(aaa___bbb.triml(
'a') == aaa___bbb.last(6));
1293 CHECK(aaa___bbb.trimr(
'a') == aaa___bbb);
1294 CHECK(aaa___bbb.trim (
'a') == aaa___bbb.last(6));
1295 CHECK(aaa___bbb.triml(
'b') == aaa___bbb);
1296 CHECK(aaa___bbb.trimr(
'b') == aaa___bbb.first(6));
1297 CHECK(aaa___bbb.trim (
'b') == aaa___bbb.first(6));
1298 CHECK(aaa___bbb.triml(
'c') == aaa___bbb);
1299 CHECK(aaa___bbb.trimr(
'c') == aaa___bbb);
1300 CHECK(aaa___bbb.trim (
'c') == aaa___bbb);
1302 CHECK(aaabbb.triml(
"ab") ==
"");
1303 CHECK(aaabbb.trimr(
"ab") ==
"");
1304 CHECK(aaabbb.trim (
"ab") ==
"");
1305 CHECK(aaabbb.triml(
"ba") ==
"");
1306 CHECK(aaabbb.trimr(
"ba") ==
"");
1307 CHECK(aaabbb.trim (
"ba") ==
"");
1308 CHECK(aaabbb.triml(
"cd") == aaabbb);
1309 CHECK(aaabbb.trimr(
"cd") == aaabbb);
1310 CHECK(aaabbb.trim (
"cd") == aaabbb);
1311 CHECK(aaa___bbb.triml(
"ab") == aaa___bbb.last(6));
1312 CHECK(aaa___bbb.triml(
"ba") == aaa___bbb.last(6));
1313 CHECK(aaa___bbb.triml(
"cd") == aaa___bbb);
1314 CHECK(aaa___bbb.trimr(
"ab") == aaa___bbb.first(6));
1315 CHECK(aaa___bbb.trimr(
"ba") == aaa___bbb.first(6));
1316 CHECK(aaa___bbb.trimr(
"cd") == aaa___bbb);
1317 CHECK(aaa___bbb.trim (
"ab") == aaa___bbb.range(3, 6));
1318 CHECK(aaa___bbb.trim (
"ba") == aaa___bbb.range(3, 6));
1319 CHECK(aaa___bbb.trim (
"cd") == aaa___bbb);
1324 CHECK(ryml::csubstr(R
"('this is is single quoted')").unquoted() == "this is is single quoted");
1325 CHECK(ryml::csubstr(R
"("this is is double quoted")").unquoted() == "this is is double quoted");
1331 ryml::csubstr abc___cba =
"abc___cba";
1332 ryml::csubstr abc___abc =
"abc___abc";
1333 CHECK(abc___cba.stripl(
"abc") == abc___cba.last(6));
1334 CHECK(abc___cba.stripr(
"abc") == abc___cba);
1335 CHECK(abc___cba.stripl(
"ab") == abc___cba.last(7));
1336 CHECK(abc___cba.stripr(
"ab") == abc___cba);
1337 CHECK(abc___cba.stripl(
"a") == abc___cba.last(8));
1338 CHECK(abc___cba.stripr(
"a") == abc___cba.first(8));
1339 CHECK(abc___abc.stripl(
"abc") == abc___abc.last(6));
1340 CHECK(abc___abc.stripr(
"abc") == abc___abc.first(6));
1341 CHECK(abc___abc.stripl(
"ab") == abc___abc.last(7));
1342 CHECK(abc___abc.stripr(
"ab") == abc___abc);
1343 CHECK(abc___abc.stripl(
"a") == abc___abc.last(8));
1344 CHECK(abc___abc.stripr(
"a") == abc___abc);
1350 ryml::csubstr s =
"foobar123";
1352 CHECK(s.begins_with(
'f'));
1353 CHECK(s.ends_with(
'3'));
1354 CHECK(!s.ends_with(
'2'));
1355 CHECK(!s.ends_with(
'o'));
1357 CHECK(s.begins_with(
"foobar"));
1358 CHECK(s.begins_with(
"foo"));
1359 CHECK(s.begins_with_any(
"foo"));
1360 CHECK(!s.begins_with(
"oof"));
1361 CHECK(s.begins_with_any(
"oof"));
1362 CHECK(s.ends_with(
"23"));
1363 CHECK(s.ends_with(
"123"));
1364 CHECK(s.ends_with_any(
"123"));
1365 CHECK(!s.ends_with(
"321"));
1366 CHECK(s.ends_with_any(
"231"));
1371 ryml::csubstr s =
"0123456789";
1372 CHECK(s.select(
'0') == s.sub(0, 1));
1373 CHECK(s.select(
'1') == s.sub(1, 1));
1374 CHECK(s.select(
'2') == s.sub(2, 1));
1375 CHECK(s.select(
'8') == s.sub(8, 1));
1376 CHECK(s.select(
'9') == s.sub(9, 1));
1377 CHECK(s.select(
"0123") == s.range(0, 4));
1378 CHECK(s.select(
"012" ) == s.range(0, 3));
1379 CHECK(s.select(
"01" ) == s.range(0, 2));
1380 CHECK(s.select(
"0" ) == s.range(0, 1));
1381 CHECK(s.select(
"123") == s.range(1, 4));
1382 CHECK(s.select(
"23") == s.range(2, 4));
1383 CHECK(s.select(
"3") == s.range(3, 4));
1388 ryml::csubstr s012345 =
"012345";
1391 CHECK(s012345.find(
'0' ) == 0u);
1393 CHECK(s012345.find(
'1' ) == 1u);
1395 CHECK(s012345.find(
'2' ) == 2u);
1397 CHECK(s012345.find(
'3' ) == 3u);
1401 CHECK(s012345.find(
"01" ) == 0u);
1403 CHECK(s012345.find(
"12" ) == 1u);
1405 CHECK(s012345.find(
"23" ) == 2u);
1411 ryml::csubstr buf =
"00110022003300440055";
1412 CHECK(buf.count(
'1' ) == 2u);
1413 CHECK(buf.count(
'1', 0u) == 2u);
1414 CHECK(buf.count(
'1', 1u) == 2u);
1415 CHECK(buf.count(
'1', 2u) == 2u);
1416 CHECK(buf.count(
'1', 3u) == 1u);
1417 CHECK(buf.count(
'1', 4u) == 0u);
1418 CHECK(buf.count(
'1', 5u) == 0u);
1419 CHECK(buf.count(
'0' ) == 10u);
1420 CHECK(buf.count(
'0', 0u) == 10u);
1421 CHECK(buf.count(
'0', 1u) == 9u);
1422 CHECK(buf.count(
'0', 2u) == 8u);
1423 CHECK(buf.count(
'0', 3u) == 8u);
1424 CHECK(buf.count(
'0', 4u) == 8u);
1425 CHECK(buf.count(
'0', 5u) == 7u);
1426 CHECK(buf.count(
'0', 6u) == 6u);
1427 CHECK(buf.count(
'0', 7u) == 6u);
1428 CHECK(buf.count(
'0', 8u) == 6u);
1429 CHECK(buf.count(
'0', 9u) == 5u);
1430 CHECK(buf.count(
'0', 10u) == 4u);
1431 CHECK(buf.count(
'0', 11u) == 4u);
1432 CHECK(buf.count(
'0', 12u) == 4u);
1433 CHECK(buf.count(
'0', 13u) == 3u);
1434 CHECK(buf.count(
'0', 14u) == 2u);
1435 CHECK(buf.count(
'0', 15u) == 2u);
1436 CHECK(buf.count(
'0', 16u) == 2u);
1437 CHECK(buf.count(
'0', 17u) == 1u);
1438 CHECK(buf.count(
'0', 18u) == 0u);
1439 CHECK(buf.count(
'0', 19u) == 0u);
1440 CHECK(buf.count(
'0', 20u) == 0u);
1445 ryml::csubstr s012345 =
"012345";
1448 CHECK(s012345.first_of(
'0') == 0u);
1449 CHECK(s012345.first_of(
"0") == 0u);
1450 CHECK(s012345.first_of(
"01") == 0u);
1451 CHECK(s012345.first_of(
"10") == 0u);
1452 CHECK(s012345.first_of(
"012") == 0u);
1453 CHECK(s012345.first_of(
"210") == 0u);
1454 CHECK(s012345.first_of(
"0123") == 0u);
1455 CHECK(s012345.first_of(
"3210") == 0u);
1456 CHECK(s012345.first_of(
"01234") == 0u);
1457 CHECK(s012345.first_of(
"43210") == 0u);
1458 CHECK(s012345.first_of(
"012345") == 0u);
1459 CHECK(s012345.first_of(
"543210") == 0u);
1460 CHECK(s012345.first_of(
'5') == 5u);
1461 CHECK(s012345.first_of(
"5") == 5u);
1462 CHECK(s012345.first_of(
"45") == 4u);
1463 CHECK(s012345.first_of(
"54") == 4u);
1464 CHECK(s012345.first_of(
"345") == 3u);
1465 CHECK(s012345.first_of(
"543") == 3u);
1466 CHECK(s012345.first_of(
"2345") == 2u);
1467 CHECK(s012345.first_of(
"5432") == 2u);
1468 CHECK(s012345.first_of(
"12345") == 1u);
1469 CHECK(s012345.first_of(
"54321") == 1u);
1470 CHECK(s012345.first_of(
"012345") == 0u);
1471 CHECK(s012345.first_of(
"543210") == 0u);
1478 CHECK(s012345.last_of(
'0') == 0u);
1479 CHECK(s012345.last_of(
"0") == 0u);
1480 CHECK(s012345.last_of(
"01") == 1u);
1481 CHECK(s012345.last_of(
"10") == 1u);
1482 CHECK(s012345.last_of(
"012") == 2u);
1483 CHECK(s012345.last_of(
"210") == 2u);
1484 CHECK(s012345.last_of(
"0123") == 3u);
1485 CHECK(s012345.last_of(
"3210") == 3u);
1486 CHECK(s012345.last_of(
"01234") == 4u);
1487 CHECK(s012345.last_of(
"43210") == 4u);
1488 CHECK(s012345.last_of(
"012345") == 5u);
1489 CHECK(s012345.last_of(
"543210") == 5u);
1490 CHECK(s012345.last_of(
'5') == 5u);
1491 CHECK(s012345.last_of(
"5") == 5u);
1492 CHECK(s012345.last_of(
"45") == 5u);
1493 CHECK(s012345.last_of(
"54") == 5u);
1494 CHECK(s012345.last_of(
"345") == 5u);
1495 CHECK(s012345.last_of(
"543") == 5u);
1496 CHECK(s012345.last_of(
"2345") == 5u);
1497 CHECK(s012345.last_of(
"5432") == 5u);
1498 CHECK(s012345.last_of(
"12345") == 5u);
1499 CHECK(s012345.last_of(
"54321") == 5u);
1500 CHECK(s012345.last_of(
"012345") == 5u);
1501 CHECK(s012345.last_of(
"543210") == 5u);
1502 CHECK(s012345.last_of(
'0', 6u) == 0u);
1503 CHECK(s012345.last_of(
'5', 6u) == 5u);
1504 CHECK(s012345.last_of(
"012345", 6u) == 5u);
1509 ryml::csubstr s012345 =
"012345";
1510 CHECK(s012345.first_not_of(
'a') == 0u);
1511 CHECK(s012345.first_not_of(
"ab") == 0u);
1512 CHECK(s012345.first_not_of(
'0') == 1u);
1513 CHECK(s012345.first_not_of(
"0") == 1u);
1514 CHECK(s012345.first_not_of(
"01") == 2u);
1515 CHECK(s012345.first_not_of(
"10") == 2u);
1516 CHECK(s012345.first_not_of(
"012") == 3u);
1517 CHECK(s012345.first_not_of(
"210") == 3u);
1518 CHECK(s012345.first_not_of(
"0123") == 4u);
1519 CHECK(s012345.first_not_of(
"3210") == 4u);
1520 CHECK(s012345.first_not_of(
"01234") == 5u);
1521 CHECK(s012345.first_not_of(
"43210") == 5u);
1524 CHECK(s012345.first_not_of(
'5') == 0u);
1525 CHECK(s012345.first_not_of(
"5") == 0u);
1526 CHECK(s012345.first_not_of(
"45") == 0u);
1527 CHECK(s012345.first_not_of(
"54") == 0u);
1528 CHECK(s012345.first_not_of(
"345") == 0u);
1529 CHECK(s012345.first_not_of(
"543") == 0u);
1530 CHECK(s012345.first_not_of(
"2345") == 0u);
1531 CHECK(s012345.first_not_of(
"5432") == 0u);
1532 CHECK(s012345.first_not_of(
"12345") == 0u);
1533 CHECK(s012345.first_not_of(
"54321") == 0u);
1536 CHECK(s012345.last_not_of(
'a') == 5u);
1537 CHECK(s012345.last_not_of(
"ab") == 5u);
1538 CHECK(s012345.last_not_of(
'5') == 4u);
1539 CHECK(s012345.last_not_of(
"5") == 4u);
1540 CHECK(s012345.last_not_of(
"45") == 3u);
1541 CHECK(s012345.last_not_of(
"54") == 3u);
1542 CHECK(s012345.last_not_of(
"345") == 2u);
1543 CHECK(s012345.last_not_of(
"543") == 2u);
1544 CHECK(s012345.last_not_of(
"2345") == 1u);
1545 CHECK(s012345.last_not_of(
"5432") == 1u);
1546 CHECK(s012345.last_not_of(
"12345") == 0u);
1547 CHECK(s012345.last_not_of(
"54321") == 0u);
1550 CHECK(s012345.last_not_of(
'0') == 5u);
1551 CHECK(s012345.last_not_of(
"0") == 5u);
1552 CHECK(s012345.last_not_of(
"01") == 5u);
1553 CHECK(s012345.last_not_of(
"10") == 5u);
1554 CHECK(s012345.last_not_of(
"012") == 5u);
1555 CHECK(s012345.last_not_of(
"210") == 5u);
1556 CHECK(s012345.last_not_of(
"0123") == 5u);
1557 CHECK(s012345.last_not_of(
"3210") == 5u);
1558 CHECK(s012345.last_not_of(
"01234") == 5u);
1559 CHECK(s012345.last_not_of(
"43210") == 5u);
1566 CHECK(ryml::csubstr(
"foo bar").first_non_empty_span() ==
"foo");
1567 CHECK(ryml::csubstr(
" foo bar").first_non_empty_span() ==
"foo");
1568 CHECK(ryml::csubstr(
"\n \r \t foo bar").first_non_empty_span() ==
"foo");
1569 CHECK(ryml::csubstr(
"\n \r \t foo\n\r\t bar").first_non_empty_span() ==
"foo");
1570 CHECK(ryml::csubstr(
"\n \r \t foo\n\r\t bar").first_non_empty_span() ==
"foo");
1571 CHECK(ryml::csubstr(
",\n \r \t foo\n\r\t bar").first_non_empty_span() ==
",");
1575 CHECK(ryml::csubstr(
"1234 asdkjh").first_uint_span() ==
"1234");
1576 CHECK(ryml::csubstr(
"1234\rasdkjh").first_uint_span() ==
"1234");
1577 CHECK(ryml::csubstr(
"1234\tasdkjh").first_uint_span() ==
"1234");
1578 CHECK(ryml::csubstr(
"1234\nasdkjh").first_uint_span() ==
"1234");
1579 CHECK(ryml::csubstr(
"1234]asdkjh").first_uint_span() ==
"1234");
1580 CHECK(ryml::csubstr(
"1234)asdkjh").first_uint_span() ==
"1234");
1581 CHECK(ryml::csubstr(
"1234gasdkjh").first_uint_span() ==
"");
1585 CHECK(ryml::csubstr(
"-1234 asdkjh").first_int_span() ==
"-1234");
1586 CHECK(ryml::csubstr(
"-1234\rasdkjh").first_int_span() ==
"-1234");
1587 CHECK(ryml::csubstr(
"-1234\tasdkjh").first_int_span() ==
"-1234");
1588 CHECK(ryml::csubstr(
"-1234\nasdkjh").first_int_span() ==
"-1234");
1589 CHECK(ryml::csubstr(
"-1234]asdkjh").first_int_span() ==
"-1234");
1590 CHECK(ryml::csubstr(
"-1234)asdkjh").first_int_span() ==
"-1234");
1591 CHECK(ryml::csubstr(
"-1234gasdkjh").first_int_span() ==
"");
1595 CHECK(ryml::csubstr(
"-1234 asdkjh").first_real_span() ==
"-1234");
1596 CHECK(ryml::csubstr(
"-1234\rasdkjh").first_real_span() ==
"-1234");
1597 CHECK(ryml::csubstr(
"-1234\tasdkjh").first_real_span() ==
"-1234");
1598 CHECK(ryml::csubstr(
"-1234\nasdkjh").first_real_span() ==
"-1234");
1599 CHECK(ryml::csubstr(
"-1234]asdkjh").first_real_span() ==
"-1234");
1600 CHECK(ryml::csubstr(
"-1234)asdkjh").first_real_span() ==
"-1234");
1601 CHECK(ryml::csubstr(
"-1234gasdkjh").first_real_span() ==
"");
1602 CHECK(ryml::csubstr(
"1.234 asdkjh").first_real_span() ==
"1.234");
1603 CHECK(ryml::csubstr(
"1.234e+5 asdkjh").first_real_span() ==
"1.234e+5");
1604 CHECK(ryml::csubstr(
"1.234e-5 asdkjh").first_real_span() ==
"1.234e-5");
1605 CHECK(ryml::csubstr(
"1.234 asdkjh").first_real_span() ==
"1.234");
1606 CHECK(ryml::csubstr(
"1.234e+5 asdkjh").first_real_span() ==
"1.234e+5");
1607 CHECK(ryml::csubstr(
"1.234e-5 asdkjh").first_real_span() ==
"1.234e-5");
1608 CHECK(ryml::csubstr(
"-1.234 asdkjh").first_real_span() ==
"-1.234");
1609 CHECK(ryml::csubstr(
"-1.234e+5 asdkjh").first_real_span() ==
"-1.234e+5");
1610 CHECK(ryml::csubstr(
"-1.234e-5 asdkjh").first_real_span() ==
"-1.234e-5");
1612 CHECK(ryml::csubstr(
"0x1.e8480p+19 asdkjh").first_real_span() ==
"0x1.e8480p+19");
1613 CHECK(ryml::csubstr(
"0x1.e8480p-19 asdkjh").first_real_span() ==
"0x1.e8480p-19");
1614 CHECK(ryml::csubstr(
"-0x1.e8480p+19 asdkjh").first_real_span() ==
"-0x1.e8480p+19");
1615 CHECK(ryml::csubstr(
"-0x1.e8480p-19 asdkjh").first_real_span() ==
"-0x1.e8480p-19");
1616 CHECK(ryml::csubstr(
"+0x1.e8480p+19 asdkjh").first_real_span() ==
"+0x1.e8480p+19");
1617 CHECK(ryml::csubstr(
"+0x1.e8480p-19 asdkjh").first_real_span() ==
"+0x1.e8480p-19");
1619 CHECK(ryml::csubstr(
"0b101.011p+19 asdkjh").first_real_span() ==
"0b101.011p+19");
1620 CHECK(ryml::csubstr(
"0b101.011p-19 asdkjh").first_real_span() ==
"0b101.011p-19");
1621 CHECK(ryml::csubstr(
"-0b101.011p+19 asdkjh").first_real_span() ==
"-0b101.011p+19");
1622 CHECK(ryml::csubstr(
"-0b101.011p-19 asdkjh").first_real_span() ==
"-0b101.011p-19");
1623 CHECK(ryml::csubstr(
"+0b101.011p+19 asdkjh").first_real_span() ==
"+0b101.011p+19");
1624 CHECK(ryml::csubstr(
"+0b101.011p-19 asdkjh").first_real_span() ==
"+0b101.011p-19");
1626 CHECK(ryml::csubstr(
"0o173.045p+19 asdkjh").first_real_span() ==
"0o173.045p+19");
1627 CHECK(ryml::csubstr(
"0o173.045p-19 asdkjh").first_real_span() ==
"0o173.045p-19");
1628 CHECK(ryml::csubstr(
"-0o173.045p+19 asdkjh").first_real_span() ==
"-0o173.045p+19");
1629 CHECK(ryml::csubstr(
"-0o173.045p-19 asdkjh").first_real_span() ==
"-0o173.045p-19");
1630 CHECK(ryml::csubstr(
"+0o173.045p+19 asdkjh").first_real_span() ==
"+0o173.045p+19");
1631 CHECK(ryml::csubstr(
"+0o173.045p-19 asdkjh").first_real_span() ==
"+0o173.045p-19");
1637 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").basename() ==
"file.tar.gz");
1638 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").dirname() ==
"/path/to/");
1639 CHECK(ryml::csubstr(
"C:\\path\\to\\file.tar.gz").basename(
'\\') ==
"file.tar.gz");
1640 CHECK(ryml::csubstr(
"C:\\path\\to\\file.tar.gz").dirname(
'\\') ==
"C:\\path\\to\\");
1641 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").extshort() ==
"gz");
1642 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").extlong() ==
"tar.gz");
1643 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extshort() ==
"/path/to/file.tar");
1644 CHECK(ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extlong() ==
"/path/to/file");
1649 using namespace ryml;
1650 csubstr parts[] = {
"aa",
"bb",
"cc",
"dd",
"ee",
"ff"};
1653 for(csubstr part : csubstr(
"aa/bb/cc/dd/ee/ff").split(
'/'))
1654 CHECK(part == parts[count++]);
1659 for(csubstr part : csubstr(
"aa.bb.cc.dd.ee.ff").split(
'.'))
1660 CHECK(part == parts[count++]);
1665 for(csubstr part : csubstr(
"aa-bb-cc-dd-ee-ff").split(
'-'))
1666 CHECK(part == parts[count++]);
1675 const bool skip_empty =
true;
1677 CHECK(ryml::csubstr(
"0/1/2" ). pop_left(
'/' ) ==
"0" );
1678 CHECK(ryml::csubstr(
"/0/1/2" ). pop_left(
'/' ) ==
"" );
1679 CHECK(ryml::csubstr(
"//0/1/2" ). pop_left(
'/' ) ==
"" );
1680 CHECK(ryml::csubstr(
"0/1/2" ). pop_left(
'/', skip_empty) ==
"0" );
1681 CHECK(ryml::csubstr(
"/0/1/2" ). pop_left(
'/', skip_empty) ==
"/0" );
1682 CHECK(ryml::csubstr(
"//0/1/2" ). pop_left(
'/', skip_empty) ==
"//0" );
1684 CHECK(ryml::csubstr(
"0/1/2" ).gpop_left(
'/' ) ==
"0/1" );
1685 CHECK(ryml::csubstr(
"/0/1/2" ).gpop_left(
'/' ) ==
"/0/1" );
1686 CHECK(ryml::csubstr(
"//0/1/2" ).gpop_left(
'/' ) ==
"//0/1" );
1687 CHECK(ryml::csubstr(
"0/1/2/" ).gpop_left(
'/' ) ==
"0/1/2");
1688 CHECK(ryml::csubstr(
"/0/1/2/" ).gpop_left(
'/' ) ==
"/0/1/2");
1689 CHECK(ryml::csubstr(
"//0/1/2/" ).gpop_left(
'/' ) ==
"//0/1/2");
1690 CHECK(ryml::csubstr(
"0/1/2//" ).gpop_left(
'/' ) ==
"0/1/2/");
1691 CHECK(ryml::csubstr(
"/0/1/2//" ).gpop_left(
'/' ) ==
"/0/1/2/");
1692 CHECK(ryml::csubstr(
"//0/1/2//" ).gpop_left(
'/' ) ==
"//0/1/2/");
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" );
1697 CHECK(ryml::csubstr(
"/0/1/2/" ).gpop_left(
'/', skip_empty) ==
"/0/1" );
1698 CHECK(ryml::csubstr(
"//0/1/2/" ).gpop_left(
'/', skip_empty) ==
"//0/1" );
1699 CHECK(ryml::csubstr(
"0/1/2//" ).gpop_left(
'/', skip_empty) ==
"0/1" );
1700 CHECK(ryml::csubstr(
"/0/1/2//" ).gpop_left(
'/', skip_empty) ==
"/0/1" );
1701 CHECK(ryml::csubstr(
"//0/1/2//" ).gpop_left(
'/', skip_empty) ==
"//0/1" );
1703 CHECK(ryml::csubstr(
"0/1/2" ). pop_right(
'/' ) ==
"2" );
1704 CHECK(ryml::csubstr(
"0/1/2/" ). pop_right(
'/' ) ==
"" );
1705 CHECK(ryml::csubstr(
"0/1/2//" ). pop_right(
'/' ) ==
"" );
1706 CHECK(ryml::csubstr(
"0/1/2" ). pop_right(
'/', skip_empty) ==
"2" );
1707 CHECK(ryml::csubstr(
"0/1/2/" ). pop_right(
'/', skip_empty) ==
"2/" );
1708 CHECK(ryml::csubstr(
"0/1/2//" ). pop_right(
'/', skip_empty) ==
"2//" );
1710 CHECK(ryml::csubstr(
"0/1/2" ).gpop_right(
'/' ) ==
"1/2");
1711 CHECK(ryml::csubstr(
"0/1/2/" ).gpop_right(
'/' ) ==
"1/2/" );
1712 CHECK(ryml::csubstr(
"0/1/2//" ).gpop_right(
'/' ) ==
"1/2//" );
1713 CHECK(ryml::csubstr(
"/0/1/2" ).gpop_right(
'/' ) ==
"0/1/2");
1714 CHECK(ryml::csubstr(
"/0/1/2/" ).gpop_right(
'/' ) ==
"0/1/2/" );
1715 CHECK(ryml::csubstr(
"/0/1/2//" ).gpop_right(
'/' ) ==
"0/1/2//" );
1716 CHECK(ryml::csubstr(
"//0/1/2" ).gpop_right(
'/' ) ==
"/0/1/2");
1717 CHECK(ryml::csubstr(
"//0/1/2/" ).gpop_right(
'/' ) ==
"/0/1/2/" );
1718 CHECK(ryml::csubstr(
"//0/1/2//" ).gpop_right(
'/' ) ==
"/0/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");
1723 CHECK(ryml::csubstr(
"/0/1/2/" ).gpop_right(
'/', skip_empty) ==
"1/2/" );
1724 CHECK(ryml::csubstr(
"/0/1/2//" ).gpop_right(
'/', skip_empty) ==
"1/2//" );
1725 CHECK(ryml::csubstr(
"//0/1/2" ).gpop_right(
'/', skip_empty) ==
"1/2");
1726 CHECK(ryml::csubstr(
"//0/1/2/" ).gpop_right(
'/', skip_empty) ==
"1/2/" );
1727 CHECK(ryml::csubstr(
"//0/1/2//" ).gpop_right(
'/', skip_empty) ==
"1/2//" );
1750 const char filename[] =
"ryml_example.yml";
1759 std::string contents = file_get_contents<std::string>(filename);
1761 CHECK(tree[
"foo"].val() ==
"1");
1762 CHECK(tree[
"bar"][0].val() ==
"2");
1763 CHECK(tree[
"bar"][1].val() ==
"3");
1768 std::vector<char> contents = file_get_contents<std::vector<char>>(filename);
1770 CHECK(tree[
"foo"].val() ==
"1");
1771 CHECK(tree[
"bar"][0].val() ==
"2");
1772 CHECK(tree[
"bar"][1].val() ==
"3");
1793 char src[] =
"{foo: 1, bar: [2, 3]}";
1794 ryml::substr srcview = src;
1799 CHECK(root[
"foo"].is_keyval());
1801 CHECK(root[
"foo"].val() ==
"1");
1802 CHECK(root[
"bar"].is_seq());
1803 CHECK(root[
"bar"].has_key());
1805 CHECK(root[
"bar"][0].val() ==
"2");
1806 CHECK(root[
"bar"][1].val() ==
"3");
1809 int foo = 0, bar0 = 0, bar1 = 0;
1811 root[
"bar"][0] >> bar0;
1812 root[
"bar"][1] >> bar1;
1818 CHECK(root[
"foo"].val().data() == src + strlen(
"{foo: "));
1819 CHECK(root[
"foo"].val().begin() == src + strlen(
"{foo: "));
1820 CHECK(root[
"foo"].val().end() == src + strlen(
"{foo: 1"));
1821 CHECK(root[
"foo"].val().is_sub(srcview));
1822 CHECK(root[
"bar"][0].val().data() == src + strlen(
"{foo: 1, bar: ["));
1823 CHECK(root[
"bar"][0].val().begin() == src + strlen(
"{foo: 1, bar: ["));
1824 CHECK(root[
"bar"][0].val().end() == src + strlen(
"{foo: 1, bar: [2"));
1825 CHECK(root[
"bar"][0].val().is_sub(srcview));
1826 CHECK(root[
"bar"][1].val().data() == src + strlen(
"{foo: 1, bar: [2, "));
1827 CHECK(root[
"bar"][1].val().begin() == src + strlen(
"{foo: 1, bar: [2, "));
1828 CHECK(root[
"bar"][1].val().end() == src + strlen(
"{foo: 1, bar: [2, 3"));
1829 CHECK(root[
"bar"][1].val().is_sub(srcview));
1833 ryml::csubstr csrcview = srcview;
1851 CHECK(root[
"foo"].is_keyval());
1853 CHECK(root[
"foo"].val() ==
"1");
1854 CHECK(root[
"bar"].is_seq());
1855 CHECK(root[
"bar"].has_key());
1857 CHECK(root[
"bar"][0].val() ==
"2");
1858 CHECK(root[
"bar"][1].val() ==
"3");
1861 int foo = 0, bar0 = 0, bar1 = 0;
1863 root[
"bar"][0] >> bar0;
1864 root[
"bar"][1] >> bar1;
1872 char src[] =
"{foo: is it really true}";
1873 ryml::substr srcview = src;
1879 ryml::csubstr csrcview = srcview;
1881 CHECK(tree[
"foo"].val() ==
"is it really true");
1900 ryml::csubstr yaml = R
"(foo: 1
1908 CHECK(root["foo"].is_keyval());
1910 CHECK(root[
"foo"].val() ==
"1");
1911 CHECK(root[
"bar"].is_seq());
1912 CHECK(root[
"bar"].has_key());
1914 CHECK(root[
"bar"][0].val() ==
"2");
1915 CHECK(root[
"bar"][1].val() ==
"3");
1916 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(foo: 1
1922 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(foo: 1
1928 CHECK(root["foo2"].is_keyval());
1929 CHECK(root[
"foo2"].
key() ==
"foo2");
1930 CHECK(root[
"foo2"].val() ==
"12");
1931 CHECK(root[
"bar2"].is_seq());
1932 CHECK(root[
"bar2"].has_key());
1933 CHECK(root[
"bar2"].
key() ==
"bar2");
1934 CHECK(root[
"bar2"][0].val() ==
"22");
1935 CHECK(root[
"bar2"][1].val() ==
"32");
1941 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
"- a\n- b\n- {x0: 1,x1: 2}\n");
1943 CHECK(root[0].val() ==
"a");
1944 CHECK(root[1].val() ==
"b");
1945 CHECK(root[2].is_map());
1946 CHECK(root[2][
"x0"].val() ==
"1");
1947 CHECK(root[2][
"x1"].val() ==
"2");
1952 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- a
1955 - champagne: Dom Perignon
1959 CHECK(root[0].val() == "a");
1960 CHECK(root[1].val() ==
"b");
1961 CHECK(root[2].is_map());
1962 CHECK(root[2][
"x0"].val() ==
"1");
1963 CHECK(root[2][
"x1"].val() ==
"2");
1964 CHECK(root[3].is_map());
1965 CHECK(root[3][
"champagne"].val() ==
"Dom Perignon");
1966 CHECK(root[3][
"coffee"].val() ==
"Arabica");
1976 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- a
1979 - champagne: Dom Perignon
1982 vinho verde: Soalheiro
1983 vinho tinto: Redoma 2017
1988 always: lots of water
1993 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- a
1996 - champagne: Dom Perignon
1999 vinho verde: Soalheiro
2000 vinho tinto: Redoma 2017
2005 always: lots of water
2014 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- a
2017 - champagne: Dom Perignon
2020 vinho verde: Soalheiro
2021 vinho tinto: Redoma 2017
2027 always: lots of water
2055 ryml::Tree champagnes =
parse_in_arena(&parser,
"champagnes.yml",
"[Dom Perignon, Gosset Grande Reserve, Jacquesson 742]");
2056 CHECK(ryml::emitrs_yaml<std::string>(champagnes) ==
"[Dom Perignon,Gosset Grande Reserve,Jacquesson 742]");
2059 CHECK(ryml::emitrs_yaml<std::string>(beers) ==
"[Rochefort 10,Busch,Leffe Rituel,Kasteel Donker]");
2089 ryml::csubstr champagnes =
"- Dom Perignon\n- Gosset Grande Reserve\n- Jacquesson 742";
2090 ryml::csubstr beers =
"- Rochefort 10\n- Busch\n- Leffe Rituel\n- Kasteel Donker";
2091 ryml::csubstr wines =
"- Soalheiro\n- Niepoort Redoma 2017\n- Vina Esmeralda";
2094 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- Dom Perignon
2095 - Gosset Grande Reserve
2101 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- Dom Perignon
2102 - Gosset Grande Reserve
2113 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(- Soalheiro
2114 - Niepoort Redoma 2017
2129 ray: "a drop of golden sun"
2144 location: a pear tree
2152 std::vector<ryml::csubstr> keys, vals;
2155 keys.emplace_back(n.key());
2156 vals.emplace_back(n.has_val() ? n.val() : ryml::csubstr{});
2158 CHECK(keys[0] ==
"doe");
2159 CHECK(vals[0] ==
"a deer, a female deer");
2160 CHECK(keys[1] ==
"ray");
2161 CHECK(vals[1] ==
"a drop of golden sun");
2162 CHECK(keys[2] ==
"pi");
2163 CHECK(vals[2] ==
"3.14159");
2164 CHECK(keys[3] ==
"xmas");
2165 CHECK(vals[3] ==
"true");
2166 CHECK(root[5].has_key());
2167 CHECK(root[5].is_seq());
2168 CHECK(root[5].
key() ==
"calling-birds");
2169 CHECK(!root[5].has_val());
2171 CHECK(keys[5] ==
"calling-birds");
2172 CHECK(vals[5] ==
"");
2178 ryml::csubstr calling_birds[] = {
"huey",
"dewey",
"louie",
"fred"};
2180 CHECK(n.val() == calling_birds[count++]);
2205 const char a_deer[] =
"a deer, a female deer";
2214 std::string a_drop =
"a drop of golden sun";
2217 root[
"ray"] << a_drop;
2223 CHECK(root[
"ray"].val() ==
"a drop of golden sun");
2228 root[
"french-hens"] << 3;
2237 xmas5[
"calling-birds"] =
"four";
2238 xmas5[
"french-hens"] << 3;
2239 xmas5[
"golden-rings"] << 5;
2241 xmas5[
"partridges"][
"count"] << 1;
2242 xmas5[
"partridges"][
"location"] =
"a pear tree";
2243 xmas5[
"turtle-doves"] =
"two";
2244 root[
"cars"] =
"GTO";
2246 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(doe: 'a deer, a female deer'
2247 ray: a drop of golden sun
2262 location: a pear tree
2277 char buf[] =
"[a, b, c, d]";
2278 ryml::substr yml = buf;
2284 CHECK(root[0].val().is_sub(yml));
2285 CHECK(root[1].val().is_sub(yml));
2286 CHECK(root[2].val().is_sub(yml));
2287 CHECK(root[3].val().is_sub(yml));
2288 CHECK(yml.is_super(root[0].
val()));
2289 CHECK(yml.is_super(root[1].
val()));
2290 CHECK(yml.is_super(root[2].
val()));
2291 CHECK(yml.is_super(root[3].
val()));
2298 ryml::csubstr yml =
"[a, b, c, d]";
2306 ryml::csubstr arena = tree.
arena();
2307 CHECK(root[0].val().is_sub(arena));
2308 CHECK(root[1].val().is_sub(arena));
2309 CHECK(root[2].val().is_sub(arena));
2310 CHECK(root[3].val().is_sub(arena));
2311 CHECK(arena.is_super(root[0].
val()));
2312 CHECK(arena.is_super(root[1].
val()));
2313 CHECK(arena.is_super(root[2].
val()));
2314 CHECK(arena.is_super(root[3].
val()));
2320 char buf[] =
"[a, b, c, d]";
2321 ryml::substr yml = buf;
2328 CHECK(root[2].val() ==
"c");
2329 CHECK(root[2].val().is_sub(yml));
2331 CHECK(root[2].val() ==
"12345");
2337 CHECK(root[3].val() ==
"d");
2338 CHECK(root[3].val().is_sub(yml));
2340 CHECK(root[3].val() ==
"67890");
2348 ryml::csubstr yml =
"[a, b, c, d]";
2356 CHECK(root[2].val() ==
"c");
2358 CHECK(root[2].val() ==
"12345");
2367 CHECK(root[3].val() ==
"67890");
2371 CHECK(tree.
arena() ==
"[a, b, c, d]1234567890");
2378 ryml::csubstr c10 = tree.
to_arena(10101010);
2379 CHECK(c10 ==
"10101010");
2389 CHECK(root[
"a"].val() ==
"2222");
2396 ryml::csubstr mystr =
"Gosset Grande Reserve";
2398 CHECK(!copied.overlaps(mystr));
2399 CHECK(copied == mystr);
2400 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2406 ryml::csubstr mystr =
"Gosset Grande Reserve";
2407 ryml::substr copied = tree.
alloc_arena(mystr.size());
2408 CHECK(!copied.overlaps(mystr));
2409 memcpy(copied.str, mystr.str, mystr.len);
2410 CHECK(copied == mystr);
2411 CHECK(tree.
arena() ==
"{a: b}Gosset Grande Reserve");
2417 CHECK(tree.
arena().size() == strlen(
"{a: b}"));
2420 CHECK(tree.
arena().size() == strlen(
"{a: b}"));
2422 CHECK(tree.
arena().first(12) ==
"{a: b}123456");
2460 CHECK(tree.
to_arena(
double(0.234)) ==
"0.234");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.234");
2470 const float fnan = std::numeric_limits<float >::quiet_NaN();
2471 const double dnan = std::numeric_limits<double>::quiet_NaN();
2472 const float finf = std::numeric_limits<float >::infinity();
2473 const double dinf = std::numeric_limits<double>::infinity();
2474 CHECK(tree.
to_arena( finf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf");
2475 CHECK(tree.
to_arena( dinf) ==
".inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf");
2476 CHECK(tree.
to_arena(-finf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf");
2477 CHECK(tree.
to_arena(-dinf) ==
"-.inf");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf");
2478 CHECK(tree.
to_arena( fnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan");
2479 CHECK(tree.
to_arena( dnan) ==
".nan");
CHECK(tree.
arena() ==
"abcde0101234-45-56-67-70x10.1240.23410truefalse.inf.inf-.inf-.inf.nan.nan");
2483 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wfloat-equal");
2489 tree[
"ninf"] >> f;
CHECK(f == -finf);
2490 tree[
"ninf"] >> d;
CHECK(d == -dinf);
2491 tree[
"pinf"] >> f;
CHECK(f == finf);
2492 tree[
"pinf"] >> d;
CHECK(d == dinf);
2493 tree[
"nan" ] >> f;
CHECK(std::isnan(f));
2494 tree[
"nan" ] >> d;
CHECK(std::isnan(d));
2495 C4_SUPPRESS_WARNING_GCC_CLANG_POP
2508 t[
"val"] >> valu8;
CHECK(valu8 == 2);
2509 t[
"val"] >> vali8;
CHECK(vali8 == 2);
2511 CHECK(ryml::overflows<uint8_t>(t[
"val"].val()));
2512 CHECK(ryml::overflows<int8_t>(t[
"val"].val()));
2513 CHECK( ! ryml::overflows<int16_t>(t[
"val"].val()));
2516 auto checku8 = ryml::fmt::overflow_checked(valu8);
2517 t[
"val"] >> checku8;
2520 auto checki8 = ryml::fmt::overflow_checked(vali8);
2521 t[
"val"] >> checki8;
2540 all_null: [~, null, Null, NULL]
2541 non_null: [nULL, non_null, non null, null it is not]
2545 CHECK(tree[
"plain"].has_val());
2546 CHECK(tree[
"squoted"].has_val());
2547 CHECK(tree[
"dquoted"].has_val());
2548 CHECK(tree[
"literal"].has_val());
2549 CHECK(tree[
"folded"].has_val());
2550 CHECK( ! tree[
"all_null"].has_val());
2551 CHECK( ! tree[
"non_null"].has_val());
2553 CHECK( ! tree[
"plain"].is_container());
2554 CHECK( ! tree[
"squoted"].is_container());
2555 CHECK( ! tree[
"dquoted"].is_container());
2556 CHECK( ! tree[
"literal"].is_container());
2557 CHECK( ! tree[
"folded"].is_container());
2558 CHECK(tree[
"all_null"].is_container());
2559 CHECK(tree[
"non_null"].is_container());
2564 CHECK(tree[
"plain"].val().len == 0);
2565 CHECK(tree[
"squoted"].val().len == 0);
2566 CHECK(tree[
"dquoted"].val().len == 0);
2567 CHECK(tree[
"literal"].val().len == 0);
2568 CHECK(tree[
"folded"].val().len == 0);
2570 CHECK(tree[
"plain"].val().str ==
nullptr);
2571 CHECK(tree[
"squoted"].val().str !=
nullptr);
2572 CHECK(tree[
"dquoted"].val().str !=
nullptr);
2573 CHECK(tree[
"literal"].val().str !=
nullptr);
2574 CHECK(tree[
"folded"].val().str !=
nullptr);
2578 CHECK(tree[
"plain"].val() ==
nullptr);
2579 CHECK(tree[
"squoted"].val() !=
nullptr);
2580 CHECK(tree[
"dquoted"].val() !=
nullptr);
2581 CHECK(tree[
"literal"].val() !=
nullptr);
2582 CHECK(tree[
"folded"].val() !=
nullptr);
2587 CHECK(tree[
"plain"].val_is_null());
2588 CHECK( ! tree[
"squoted"].val_is_null());
2589 CHECK( ! tree[
"dquoted"].val_is_null());
2590 CHECK( ! tree[
"literal"].val_is_null());
2591 CHECK( ! tree[
"folded"].val_is_null());
2596 CHECK(child.val() !=
nullptr);
2597 CHECK(child.val_is_null());
2601 CHECK(child.val() !=
nullptr);
2602 CHECK( ! child.val_is_null());
2613 ryml::csubstr
null = {};
2614 ryml::csubstr nonnull =
"";
2615 ryml::csubstr strnull =
"null";
2616 ryml::csubstr tilde =
"~";
2617 CHECK(
null .len == 0);
CHECK(
null .str ==
nullptr);
CHECK(
null ==
nullptr);
2618 CHECK(nonnull.len == 0);
CHECK(nonnull.str !=
nullptr);
CHECK(nonnull !=
nullptr);
2619 CHECK(strnull.len != 0);
CHECK(strnull.str !=
nullptr);
CHECK(strnull !=
nullptr);
2620 CHECK(tilde .len != 0);
CHECK(tilde .str !=
nullptr);
CHECK(tilde !=
nullptr);
2625 tree[
"empty_null"] <<
null;
CHECK(tree.
arena() ==
"");
2627 tree[
"empty_nonnull"] << nonnull;
CHECK(tree.
arena() ==
"");
2629 tree[
"str_null"] << strnull;
CHECK(tree.
arena() ==
"null");
2631 tree[
"str_tilde"] << tilde;
CHECK(tree.
arena() ==
"null~");
2633 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null:
2643 auto null_if_nullptr = [](ryml::csubstr s) {
2644 return s.str ==
nullptr ?
"null" : s;
2646 tree[
"empty_null"] << null_if_nullptr(
null);
2647 tree[
"empty_nonnull"] << null_if_nullptr(nonnull);
2648 tree[
"str_null"] << null_if_nullptr(strnull);
2649 tree[
"str_tilde"] << null_if_nullptr(tilde);
2651 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null: null
2659 auto null_if_predicate = [](ryml::csubstr s) {
2662 tree[
"empty_null"] << null_if_predicate(
null);
2663 tree[
"empty_nonnull"] << null_if_predicate(nonnull);
2664 tree[
"str_null"] << null_if_predicate(strnull);
2665 tree[
"str_tilde"] << null_if_predicate(tilde);
2667 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null: null
2675 auto tilde_if_predicate = [](ryml::csubstr s) {
2678 tree[
"empty_null"] << tilde_if_predicate(
null);
2679 tree[
"empty_nonnull"] << tilde_if_predicate(nonnull);
2680 tree[
"str_null"] << tilde_if_predicate(strnull);
2681 tree[
"str_tilde"] << tilde_if_predicate(tilde);
2683 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(empty_null: ~
2702 char buf_[256] = {};
2703 ryml::substr buf = buf_;
2704 size_t size =
ryml::format(buf,
"a={} foo {} {} bar {}", 0.1, 10, 11, 12);
2705 CHECK(size == strlen(
"a=0.1 foo 10 11 bar 12"));
2706 CHECK(buf.first(size) ==
"a=0.1 foo 10 11 bar 12");
2709 size =
ryml::format({} ,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12);
2710 CHECK(size ==
ryml::format(buf,
"a={} foo {} {} bar {}",
"this_is_a", 10, 11, 12));
2711 CHECK(size == strlen(
"a=this_is_a foo 10 11 bar 12"));
2713 char smallbuf[8] = {};
2714 size =
ryml::format(smallbuf,
"{} is too large {}",
"this",
"for the buffer");
2715 CHECK(size == strlen(
"this is too large for the buffer"));
2717 CHECK(ryml::substr(smallbuf,
sizeof(smallbuf)) ==
"this is\0");
2721 CHECK(result ==
"b=1, damn it.");
2722 CHECK(result.is_sub(buf));
2740 CHECK(sbuf ==
"and c=2 seems about right");
2741 std::vector<char> vbuf;
2743 CHECK(sbuf ==
"and c=2 seems about right");
2746 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2753 int a = 0, b = 1, c = 2;
2754 ryml::csubstr result =
ryml::format_sub(buf_,
"{} and {} and {}", a, b, c);
2755 CHECK(result ==
"0 and 1 and 2");
2756 int aa = -1, bb = -2, cc = -3;
2757 size_t num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2759 CHECK(num_characters == result.size());
2765 CHECK(result ==
"10 and 20 and 30");
2766 num_characters =
ryml::unformat(result,
"{} and {} and {}", aa, bb, cc);
2768 CHECK(num_characters == result.size());
2776 char buf_[256] = {};
2777 ryml::substr buf = buf_;
2778 size_t size =
ryml::cat(buf,
"a=", 0.1,
"foo", 10, 11,
"bar", 12);
2779 CHECK(size == strlen(
"a=0.1foo1011bar12"));
2780 CHECK(buf.first(size) ==
"a=0.1foo1011bar12");
2785 char smallbuf[8] = {};
2786 size =
ryml::cat(smallbuf,
"this",
" is too large ",
"for the buffer");
2787 CHECK(size == strlen(
"this is too large for the buffer"));
2789 CHECK(ryml::substr(smallbuf,
sizeof(smallbuf)) ==
"this is\0");
2792 ryml::csubstr result =
ryml::cat_sub(buf,
"b=", 1,
", damn it.");
2793 CHECK(result ==
"b=1, damn it.");
2794 CHECK(result.is_sub(buf));
2811 ryml::catrs(&sbuf,
"and c=", 2,
" seems about right");
2812 CHECK(sbuf ==
"and c=2 seems about right");
2813 std::vector<char> vbuf;
2814 ryml::catrs(&vbuf,
"and c=", 2,
" seems about right");
2815 CHECK(sbuf ==
"and c=2 seems about right");
2818 CHECK(sbuf ==
"and c=2 seems about right, and finally d=3 - done");
2825 int a = 0, b = 1, c = 2;
2826 ryml::csubstr result =
ryml::cat_sub(buf_, a,
' ', b,
' ', c);
2827 CHECK(result ==
"0 1 2");
2828 int aa = -1, bb = -2, cc = -3;
2829 char sep1 =
'a', sep2 =
'b';
2830 size_t num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2831 CHECK(num_characters == result.size());
2839 CHECK(result ==
"10 20 30");
2840 num_characters =
ryml::uncat(result, aa, sep1, bb, sep2, cc);
2841 CHECK(num_characters == result.size());
2851 char buf_[256] = {};
2852 ryml::substr buf = buf_;
2854 size_t size =
ryml::catsep(buf,
' ',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2855 CHECK(buf.first(size) ==
"a= 0 b= 1 c= 2 45 67");
2858 size =
ryml::catsep(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
2859 CHECK(buf.first(size) ==
"a=0 and b=1 and c=2 and 45 and 67");
2861 size =
ryml::catsep(buf,
" ... ",
"a=0",
"b=1",
"c=2", 45, 67);
2862 CHECK(buf.first(size) ==
"a=0 ... b=1 ... c=2 ... 45 ... 67");
2864 size =
ryml::catsep(buf,
'/',
"a=", 0,
"b=", 1,
"c=", 2, 45, 67);
2865 CHECK(buf.first(size) ==
"a=/0/b=/1/c=/2/45/67");
2867 size =
ryml::catsep(buf, 888,
"a=0",
"b=1",
"c=2", 45, 67);
2868 CHECK(buf.first(size) ==
"a=0888b=1888c=28884588867");
2874 char smallbuf[8] = {};
2876 CHECK(size == strlen(
"a=0888b=1888c=28884588867"));
2878 CHECK(ryml::substr(smallbuf,
sizeof(smallbuf)) ==
"a=0888b\0");
2881 ryml::csubstr result =
ryml::catsep_sub(buf,
" and ",
"a=0",
"b=1",
"c=2", 45, 67);
2882 CHECK(result ==
"a=0 and b=1 and c=2 and 45 and 67");
2883 CHECK(result.is_sub(buf));
2901 CHECK(sbuf ==
"a=0 and b=1 and c=2 and 45 and 67");
2902 std::vector<char> vbuf;
2908 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");
2913 char buf_[256] = {};
2915 int a = 0, b = 1, c = 2;
2917 CHECK(result ==
"0 1 2");
2918 int aa = -1, bb = -2, cc = -3;
2921 CHECK(num_characters == result.size());
2929 CHECK(result ==
"10 20 30");
2931 CHECK(num_characters == result.size());
2940 using namespace ryml;
2941 char buf_[256] = {};
2960 CHECK(
"3735928559" ==
cat_sub(buf, UINT32_C(0xdeadbeef)));
3084 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wcast-align")
3085 const uint32_t payload[] = {10, 20, 30, 40, UINT32_C(0xdeadbeef)};
3087 csubstr expected = csubstr((
const char *)payload,
sizeof(payload));
3089 CHECK(!actual.overlaps(expected));
3090 CHECK(0 == memcmp(expected.str, actual.str, expected.len));
3092 for(
const uint32_t value : payload)
3095 expected = csubstr((
const char *)&value,
sizeof(value));
3097 CHECK(actual.size() ==
sizeof(uint32_t));
3098 CHECK(!actual.overlaps(expected));
3099 CHECK(0 == memcmp(expected.str, actual.str, expected.len));
3102 CHECK(actual.size() ==
sizeof(uint32_t));
3103 CHECK(!actual.overlaps(expected));
3104 CHECK(0 == memcmp(expected.str, actual.str, expected.len));
3109 CHECK(&result == (uint32_t*)reader.buf);
3110 CHECK(reader.len ==
sizeof(uint32_t));
3111 uncat(actual, reader);
3114 result = *(uint32_t*)reader.buf;
3115 CHECK(result == value);
3117 C4_SUPPRESS_WARNING_GCC_CLANG_POP
3136 struct text_and_base64 { ryml::csubstr text,
base64; };
3137 text_and_base64 cases[] = {
3138 {{
"Love all, trust a few, do wrong to none."}, {
"TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg=="}},
3139 {{
"The fool doth think he is wise, but the wise man knows himself to be a fool."}, {
"VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg=="}},
3140 {{
"Brevity is the soul of wit."}, {
"QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu"}},
3141 {{
"All that glitters is not gold."}, {
"QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu"}},
3144 for(text_and_base64 c : cases)
3147 CHECK(tree[c.text].
val() == c.base64);
3150 for(text_and_base64 c : cases)
3153 CHECK(tree[c.base64].
val() == c.text);
3155 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"('Love all, trust a few, do wrong to none.': TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg==
3156 'The fool doth think he is wise, but the wise man knows himself to be a fool.': VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg==
3157 Brevity is the soul of wit.: QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu
3158 All that glitters is not gold.: QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu
3159 TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg==: 'Love all, trust a few, do wrong to none.'
3160 VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg==: 'The fool doth think he is wise, but the wise man knows himself to be a fool.'
3161 QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu: Brevity is the soul of wit.
3162 QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu: All that glitters is not gold.
3164 char buf1_[128], buf2_[128];
3165 ryml::substr buf1 = buf1_;
3166 ryml::substr buf2 = buf2_;
3167 std::string result = {};
3169 for(
const text_and_base64 c : cases)
3174 CHECK(len <= buf1.len);
3175 CHECK(len <= buf2.len);
3176 CHECK(c.text.len == len);
3177 CHECK(buf1.first(len) == c.text);
3178 CHECK(buf2.first(len) == c.text);
3183 if(len > result.size())
3189 CHECK(result == c.text);
3193 ryml::blob strblob(&result[0], result.size());
3194 CHECK(strblob.buf == result.data());
3195 CHECK(strblob.len == result.size());
3197 if(len > result.size())
3200 strblob = {&result[0], result.
size()};
3201 CHECK(strblob.buf == result.data());
3202 CHECK(strblob.len == result.size());
3206 CHECK(result == c.text);
3211 ryml::csubstr encoded = tree[c.text].
val();
3212 CHECK(encoded == c.base64);
3213 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3214 if(len > result.size())
3217 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3220 CHECK(result == c.text);
3223 for(
const text_and_base64 c : cases)
3228 CHECK(len <= buf1.len);
3229 CHECK(len <= buf2.len);
3230 CHECK(c.text.len == len);
3231 CHECK(buf1.first(len) == c.text);
3232 CHECK(buf2.first(len) == c.text);
3236 if(len > result.size())
3242 CHECK(result == c.text);
3246 ryml::blob strblob = {&result[0], result.size()};
3247 CHECK(strblob.buf == result.data());
3248 CHECK(strblob.len == result.size());
3250 if(len > result.size())
3253 strblob = {&result[0], result.
size()};
3254 CHECK(strblob.buf == result.data());
3255 CHECK(strblob.len == result.size());
3259 CHECK(result == c.text);
3264 ryml::csubstr encoded = tree[c.base64].
key();
3265 CHECK(encoded == c.base64);
3266 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3267 if(len > result.size())
3270 len =
base64_decode(encoded, ryml::blob{&result[0], result.size()});
3273 CHECK(result == c.text);
3277 const uint64_t valin = UINT64_C(0xdeadbeef);
3278 uint64_t valout = 0;
3281 CHECK(len <=
sizeof(valout));
3282 CHECK(valout == UINT64_C(0xdeadbeef));
3286 const uint32_t data_in[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xdeadbeef};
3287 uint32_t data_out[11] = {};
3288 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) != 0);
3291 CHECK(len <=
sizeof(data_out));
3292 CHECK(memcmp(data_in, data_out,
sizeof(data_in)) == 0);
3523 CHECK(v2in.x == v2out.x);
3524 CHECK(v2in.y == v2out.y);
3529 CHECK(v3in.x == v3out.x);
3530 CHECK(v3in.y == v3out.y);
3531 CHECK(v3in.z == v3out.z);
3536 CHECK(v4in.x == v4out.x);
3537 CHECK(v4in.y == v4out.y);
3538 CHECK(v4in.z == v4out.z);
3539 CHECK(v4in.w == v4out.w);
3540 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(v2: '(10,11)'
3542 v4: '(1000,1001,1002,1003)'
3552 CHECK(eov2in.x == pov2out.x);
3553 CHECK(eov2in.y == pov2out.y);
3558 CHECK(eov3in.x == pov3out.x);
3559 CHECK(eov3in.y == pov3out.y);
3560 CHECK(eov3in.z == pov3out.z);
3565 CHECK(eov4in.x == pov4out.x);
3566 CHECK(eov4in.y == pov4out.y);
3567 CHECK(eov4in.z == pov4out.z);
3568 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(v2: '(20,21)'
3622 template<
class K,
class V>
3647 template<
class K,
class V>
3675 template<
class K,
class V>
3680 for(
auto const ch : n)
3683 map->
map_member.emplace(std::make_pair(std::move(k), std::move(v)));
3694 n[
"seq"] >> val->
seq;
3695 n[
"map"] >> val->
map;
3714 {{101, 102, 103, 104, 105, 106, 107}},
3715 {{{1001, 2001}, {1002, 2002}, {1003, 2003}}},
3731 CHECK(mt_in.seq.seq_member.size() > 0);
3733 for(
size_t i = 0; i < mt_in.seq.seq_member.size(); ++i)
3737 CHECK(mt_in.map.map_member.size() > 0);
3739 for(
auto const& kv : mt_in.map.map_member)
3744 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(v2: '(20,21)'
3771 std::string yml_std_string = R
"(- v2: '(20,21)'
3788 v4: '(140,141,142,143)'
3803 v4: '(240,241,242,243)'
3821 std::vector<my_type> vmt;
3823 CHECK(vmt.size() == 3);
3826 CHECK(ryml::emitrs_yaml<std::string>(tree_out) == yml_std_string);
3835 std::vector<double> reference{1.23234412342131234, 2.12323123143434237, 3.67847983572591234};
3839 const double precision_safe = 1.e-14;
3840 const size_t num_digits_safe = 14;
3841 const size_t num_digits_original = 17;
3842 auto get_num_digits = [](ryml::csubstr number){
return number.sub(2).len; };
3848 std::vector<double> output;
3850 CHECK(output.size() == reference.size());
3851 for(
size_t i = 0; i < reference.size(); ++i)
3854 CHECK(fabs(output[i] - reference[i]) < precision_safe);
3863 serialized.
rootref() << reference;
3864 std::cout << serialized;
3866 #if (!C4CORE_HAVE_STD_TOCHARS)
3867 CHECK(ryml::emitrs_yaml<std::string>(serialized) == R
"(- 1.23234
3870 )" || (bool)
"this is indicative; the exact results will vary from platform to platform.");
3871 C4_UNUSED(num_digits_safe);
3873 CHECK((ryml::emitrs_yaml<std::string>(serialized) == R
"(- 1.2323441234213124
3874 - 2.1232312314343424
3875 - 3.6784798357259123
3876 )") || (bool)
"this is indicative; the exact results will vary from platform to platform.");
3880 CHECK(get_num_digits(child.val()) >= num_digits_safe);
3883 CHECK(fabs(out - reference[pos++]) < precision_safe);
3914 auto check_precision = [&](
ryml::Tree serialized){
3915 std::cout << serialized;
3917 CHECK((ryml::emitrs_yaml<std::string>(serialized) == R
"(- 1.23234412342131239
3918 - 2.12323123143434245
3919 - 3.67847983572591231
3920 )") || (bool)
"this is indicative; the exact results will vary from platform to platform.");
3924 CHECK(get_num_digits(child.val()) == num_digits_original);
3927 CHECK(fabs(out - reference[pos++]) < precision_safe);
3936 for(
const double v : reference)
3938 check_precision(serialized);
3947 for(
const double v : reference)
3952 (void)snprintf(tmp,
sizeof(tmp),
"%.18g", v);
3958 check_precision(serialized);
3970 ryml::csubstr ymla =
"- 1\n- 2\n";
3971 ryml::csubstr ymlb = R
"(- a
3975 - champagne: Dom Perignon
3978 vinho verde: Soalheiro
3979 vinho tinto: Redoma 2017
3997 ryml::csubstr output =
ryml::emit_yaml(treea, treea.root_id(), ryml::substr{},
false);
3998 CHECK(output.str ==
nullptr);
3999 CHECK(output.len > 0);
4000 size_t num_needed_chars = output.len;
4001 std::vector<char> buf(num_needed_chars);
4004 CHECK(output == ymla);
4008 output =
ryml::emit_yaml(treeb, treeb.root_id(), ryml::substr{},
false);
4009 CHECK(output.str ==
nullptr);
4010 CHECK(output.len > 0);
4011 CHECK(output.len == ymlb.len);
4012 num_needed_chars = output.len;
4013 buf.resize(num_needed_chars);
4016 CHECK(output == ymlb);
4021 CHECK(output == ymlb);
4025 std::vector<char> another = ryml::emitrs_yaml<std::vector<char>>(treeb);
4029 another = ryml::emitrs_yaml<std::vector<char>>(treeb[3][2]);
4031 vinho verde: Soalheiro
4032 vinho tinto: Redoma 2017
4042 ryml::csubstr output =
ryml::emit_yaml(treea, treea.root_id(), ryml::substr{},
false);
4043 CHECK(output.str ==
nullptr);
4044 CHECK(output.len > 0);
4045 size_t num_needed_chars = output.len;
4047 buf.resize(num_needed_chars);
4050 CHECK(output == ymla);
4054 output =
ryml::emit_yaml(treeb, treeb.root_id(), ryml::substr{},
false);
4055 CHECK(output.str ==
nullptr);
4056 CHECK(output.len > 0);
4057 CHECK(output.len == ymlb.len);
4058 num_needed_chars = output.len;
4059 buf.resize(num_needed_chars);
4062 CHECK(output == ymlb);
4067 CHECK(output == ymlb);
4071 std::string another = ryml::emitrs_yaml<std::string>(treeb);
4075 another = ryml::emitrs_yaml<std::string>(treeb[3][2]);
4077 vinho verde: Soalheiro
4078 vinho tinto: Redoma 2017
4089 ryml::csubstr ymlb = R
"(- a
4093 - champagne: Dom Perignon
4096 vinho verde: Soalheiro
4097 vinho tinto: Redoma 2017
4113 std::stringstream ss;
4121 std::stringstream ss;
4124 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"])");
4129 std::stringstream ss;
4133 vinho verde: Soalheiro
4134 vinho tinto: Redoma 2017
4140 std::stringstream ss;
4143 CHECK(
ryml::to_csubstr(s) == R
"("more": {"vinho verde": "Soalheiro","vinho tinto": "Redoma 2017"})");
4153 ryml::csubstr yml = R
"(- a
4157 - champagne: Dom Perignon
4160 vinho verde: Soalheiro
4161 vinho tinto: Redoma 2017
4177 CHECK(len == yml.len);
4190 - champagne: Dom Perignon
4193 vinho verde: Soalheiro
4194 vinho tinto: Redoma 2017
4207 CHECK(ryml::emitrs_yaml<std::string>(tree[3]["beer"]) == R
"(beer:
4215 CHECK(ryml::emitrs_yaml<std::string>(tree[3]["beer"][0]) ==
"Rochefort 10\n");
4216 CHECK(ryml::emitrs_yaml<std::string>(tree[3][
"beer"][3]) == R
"(- and so
4230 block key: block val
4235 flow map: {flow key: flow val}
4236 flow seq: [flow val, flow val]
4244 CHECK(tree[
"block map"].is_block());
4245 CHECK(tree[
"block seq"].is_block());
4246 CHECK(tree[
"flow map"].is_flow());
4247 CHECK(tree[
"flow seq"].is_flow());
4250 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
4252 block key: block val
4257 flow map: {flow key: flow val}
4258 flow seq: [flow val,flow val]
4273 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
4274 R
"('block map': {block key: block val}
4275 "block seq": [block val 1,block val 2,quoted]
4289 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
4291 block key: block val
4292 "block seq": [block val 1,block val 2,quoted]
4305 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
4307 block key: block val
4325 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
4327 block key: block val
4359 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
4361 'block key': "block val"
4362 'block seq': ["block val 1","block val 2","quoted"]
4364 'flow key': "flow val"
4365 'flow seq': ["flow val","flow val"]
4372 CHECK(ryml::emitrs_yaml<std::string>(tree) ==
4374 'block key': "block val"
4375 'block seq': ["block val 1","block val 2","quoted"]
4377 'flow key': "flow val"
4399 ryml::csubstr json = R
"({
4400 "doe":"a deer, a female deer",
4401 "ray":"a drop of golden sun",
4402 "me":"a name, I call myself",
4403 "far":"a long long way to go"
4413 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"})");
4414 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"})");
4416 std::stringstream ss;
4418 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"})");
4435 CHECK(ryml::emitrs_yaml<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"})");
4440 CHECK(ryml::emitrs_yaml<std::string>(json_tree) ==
4441 R
"("doe": "a deer, a female deer"
4442 "ray": "a drop of golden sun"
4443 "me": "a name, I call myself"
4444 "far": "a long long way to go"
4451 CHECK(ryml::emitrs_yaml<std::string>(json_tree) ==
4452 R
"(doe: 'a deer, a female deer'
4453 ray: a drop of golden sun
4454 me: 'a name, I call myself'
4455 far: a long long way to go
4463 CHECK(ryml::emitrs_yaml<std::string>(json_tree) ==
4464 R
"(doe: 'a deer, a female deer'
4465 ray: 'a drop of golden sun'
4466 me: 'a name, I call myself'
4467 far: 'a long long way to go'
4497 std::string unresolved = R
"(base: &base
4498 name: Everyone has same name
4509 city: East Centerville
4512 &keyref key: &valref val
4515 std::string resolved = R"(base:
4516 name: Everyone has same name
4518 name: Everyone has same name
4521 name: Everyone has same name
4527 city: East Centerville
4533 city: East Centerville
4541 CHECK( ! tree[
"base"].has_key_anchor());
4542 CHECK( tree[
"base"].has_val_anchor());
4543 CHECK( tree[
"base"].val_anchor() ==
"base");
4544 CHECK( tree[
"key"].key_anchor() ==
"keyref");
4545 CHECK( tree[
"key"].val_anchor() ==
"valref");
4546 CHECK( tree[
"*valref"].is_key_ref());
4547 CHECK( tree[
"*valref"].is_val_ref());
4548 CHECK( tree[
"*valref"].key_ref() ==
"valref");
4549 CHECK( tree[
"*valref"].val_ref() ==
"keyref");
4556 CHECK( ! tree[
"base"].has_key_anchor());
4557 CHECK( ! tree[
"base"].has_val_anchor());
4558 CHECK( ! tree[
"base"].has_val_anchor());
4559 CHECK( ! tree[
"key"].has_key_anchor());
4560 CHECK( ! tree[
"key"].has_val_anchor());
4561 CHECK( ! tree[
"val"].is_key_ref());
4562 CHECK( ! tree[
"val"].is_val_ref());
4564 CHECK(tree[
"ship_to"][
"city"].val() ==
"East Centerville");
4565 CHECK(tree[
"ship_to"][
"state"].val() ==
"KS");
4583 t[
"nref"] =
"*vanchor";
4584 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(&kanchor kanchor: 2
4591 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(kanchor: 2
4602 orig: &orig {foo: bar, baz: bat}
4610 t[
"notref"][
"<<"] =
"*orig";
4611 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(orig: &orig {foo: bar,baz: bat}
4613 notcopy: {test: *orig,<<: *orig}
4614 notref: {<<: '*orig'}
4617 CHECK(ryml::emitrs_yaml<std::string>(t) == R"(orig: {foo: bar,baz: bat}
4618 copy: {foo: bar,baz: bat}
4619 notcopy: {test: {foo: bar,baz: bat},foo: bar,baz: bat}
4620 notref: {<<: '*orig'}
4627 orig2: &orig2 {baz: bat}
4628 orig3: &orig3 {and: more}
4636 CHECK(ryml::emitrs_yaml<std::string>(t) == R
"(orig1: &orig1 {foo: bar}
4637 orig2: &orig2 {baz: bat}
4638 orig3: &orig3 {and: more}
4639 copy: {<<: [*orig1,*orig2,*orig3]}
4642 CHECK(ryml::emitrs_yaml<std::string>(t) == R"(orig1: {foo: bar}
4645 copy: {foo: bar,baz: bat,and: more}
4655 const std::string yaml = R
"(--- !!map
4681 CHECK(doc.is_doc());
4683 CHECK(root[0].has_val_tag());
4684 CHECK(root[0].val_tag() ==
"!!map");
4685 CHECK(root[1].val_tag() ==
"!map");
4686 CHECK(root[2].val_tag() ==
"!!seq");
4687 CHECK(root[3].val_tag() ==
"!!str");
4688 CHECK(root[4].val_tag() ==
"!!str");
4689 CHECK(root[5][
"a"].has_key_tag());
4690 CHECK(root[5][
"a"].key_tag() ==
"!!str");
4691 CHECK(root[6].val_tag() ==
"!!set");
4692 CHECK(root[7].val_tag() ==
"!!set");
4693 CHECK(root[8].val_tag() ==
"!!seq");
4694 CHECK(root[8][0].val_tag() ==
"!!int");
4695 CHECK(root[8][1].val_tag() ==
"!!str");
4744 CHECK(ryml::emitrs_yaml<std::string>(normalized_tree) == R
"(--- !!map
4767 CHECK(ryml::emitrs_yaml<std::string>(normalized_tree_long) == R
"(--- !<tag:yaml.org,2002:map>
4772 --- !<tag:yaml.org,2002:seq>
4775 --- !<tag:yaml.org,2002:str> a b
4776 --- !<tag:yaml.org,2002:str> 'a: b'
4778 !<tag:yaml.org,2002:str> a: b
4779 --- !<tag:yaml.org,2002:set>
4782 --- !<tag:yaml.org,2002:set>
4784 --- !<tag:yaml.org,2002:seq>
4785 - !<tag:yaml.org,2002:int> 0
4786 - !<tag:yaml.org,2002:str> 1
4795 const std::string yaml = R
"(
4798 !m!light fluorescent
4805 CHECK(ryml::emitrs_yaml<std::string>(tree) == R"(%TAG !m! !my-
4806 --- !m!light fluorescent
4814 CHECK(ryml::emitrs_yaml<std::string>(tree) == R
"(%TAG !m! !my-
4815 --- !<!my-light> fluorescent
4818 --- !<!meta-light> green
4829 std::string yml = R
"(---
4842 CHECK(ryml::emitrs_yaml<std::string>(tree) == yml);
4853 CHECK(doc.is_doc());
4870 CHECK(stream[0].is_doc());
4871 CHECK(stream[0].is_map());
4872 CHECK(stream[0][
"a"].val() ==
"0");
4873 CHECK(stream[0][
"b"].val() ==
"1");
4882 CHECK(stream[1].is_doc());
4883 CHECK(stream[1].is_map());
4885 CHECK(stream[1][
"d"].val() ==
"3");
4894 CHECK(stream[2].is_doc());
4895 CHECK(stream[2].is_seq());
4896 CHECK(stream[2][0].val() ==
"4");
4897 CHECK(stream[2][1].val() ==
"5");
4898 CHECK(stream[2][2].val() ==
"6");
4899 CHECK(stream[2][3].val() ==
"7");
4918 const std::string expected_json[] = {
4919 R
"({"a": 0,"b": 1})",
4920 R"({"c": 2,"d": 3})",
4929 CHECK(ryml::emitrs_json<std::string>(doc) == expected_json[count++]);
4937 CHECK(ryml::emitrs_json<std::string>(tree, doc_id) == expected_json[count++]);
4974 ryml::Tree tree = ryml::parse_in_arena(
"errorhandler.yml",
"[a: b\n}");
5004 std::vector<char>
memory_pool = std::vector<char>(10u * 1024u);
5014 uintptr_t uptr = (uintptr_t)ptr;
5015 const uintptr_t align =
alignof(max_align_t);
5018 uintptr_t prev = uptr - (uptr % align);
5019 uintptr_t next = prev + align;
5020 uintptr_t corr = next - uptr;
5021 ptr = (
void*)(((
char*)ptr) + corr);
5025 "out of memory! requested=%zu+%zu available=%zu\n",
5030 void free(
void *mem,
size_t len)
5044 static void*
s_allocate(
size_t len,
void* ,
void *this_)
5048 static void s_free(
void *mem,
size_t len,
void *this_)
5109 parser.reserve_stack(10);
5115 parser.reserve_stack(20);
5120 parse_in_arena(&parser,
"", R
"([a, b, c, d, {foo: bar, money: pennys}])", &tree);
5137 struct PerTreeMemoryExample
5139 std::vector<char>
memory_pool = std::vector<char>(10u * 1024u);
5151 cb.
m_allocate = [](
size_t len,
void *,
void *data){
return ((PerTreeMemoryExample*) data)->
allocate(len); };
5152 cb.
m_free = [](
void *mem,
size_t len,
void *data){
return ((PerTreeMemoryExample*) data)->
free(mem, len); };
5163 std::cerr <<
"out of memory! requested=" <<
alloc_size <<
" vs " <<
memory_pool.size() <<
" available" << std::endl;
5169 void free(
void *mem,
size_t len)
5200 PerTreeMemoryExample mrp;
5201 PerTreeMemoryExample mr1;
5202 PerTreeMemoryExample mr2;
5214 ryml::csubstr yml1 =
"{a: b}";
5215 ryml::csubstr yml2 =
"{c: d, e: f, g: [h, i, 0, 1, 2, 3]}";
5221 CHECK(mrp.num_allocs == 0);
5222 CHECK(mr1.alloc_size <= mr2.alloc_size);
5248 CHECK(tree["doe"].val() ==
"a deer, a female deer");
5262 ryml::csubstr yaml = R
"({
5264 foo: [one, [two, three]]
5273 CHECK(parser.options().locations());
5286 parser.reserve_locations(50u);
5295 CHECK(parser.location_contents(loc).begins_with(
"{"));
5302 CHECK(parser.location_contents(loc).begins_with(
"aa"));
5307 loc = tree[
"foo"].
location(parser);
5308 CHECK(parser.location_contents(loc).begins_with(
"foo"));
5312 loc = tree[
"foo"][0].
location(parser);
5313 CHECK(parser.location_contents(loc).begins_with(
"one"));
5317 loc = tree[
"foo"][1].
location(parser);
5318 CHECK(parser.location_contents(loc).begins_with(
"["));
5321 loc = tree[
"foo"][1][0].
location(parser);
5322 CHECK(parser.location_contents(loc).begins_with(
"two"));
5325 loc = tree[
"foo"][1][1].
location(parser);
5326 CHECK(parser.location_contents(loc).begins_with(
"three"));
5340 CHECK(parser.location_contents(loc).begins_with(
"this is a docval"));
5355 - nested first value
5356 - nested second value
5359 nested second: value
5368 CHECK(parser.location_contents(loc).begins_with(
"a new"));
5373 loc = tree2[
"a new"].
location(parser);
5374 CHECK(parser.location_contents(loc).begins_with(
"a new"));
5378 loc = tree2[
"to"].
location(parser);
5379 CHECK(parser.location_contents(loc).begins_with(
"to"));
5384 loc = tree2[
"map with key"].
location(parser);
5385 CHECK(parser.location_contents(loc).begins_with(
"map with key"));
5388 loc = tree2[
"map with key"][
"first"].
location(parser);
5389 CHECK(parser.location_contents(loc).begins_with(
"first"));
5392 loc = tree2[
"map with key"][
"second"].
location(parser);
5393 CHECK(parser.location_contents(loc).begins_with(
"second"));
5397 loc = tree2[
"seq with key"].
location(parser);
5398 CHECK(parser.location_contents(loc).begins_with(
"seq with key"));
5401 loc = tree2[
"seq with key"][0].
location(parser);
5402 CHECK(parser.location_contents(loc).begins_with(
"first value"));
5405 loc = tree2[
"seq with key"][1].
location(parser);
5406 CHECK(parser.location_contents(loc).begins_with(
"second value"));
5410 loc = tree2[
"seq with key"][2].
location(parser);
5411 CHECK(parser.location_contents(loc).begins_with(
"- nested first value"));
5414 loc = tree2[
"seq with key"][2][0].
location(parser);
5415 CHECK(parser.location_contents(loc).begins_with(
"nested first value"));
5419 loc = tree2[
"seq with key"][3].
location(parser);
5420 CHECK(parser.location_contents(loc).begins_with(
"nested first: "));
5423 loc = tree2[
"seq with key"][3][0].
location(parser);
5424 CHECK(parser.location_contents(loc).begins_with(
"nested first: "));
5439 static int num_checks = 0;
5440 static int num_failed_checks = 0;
5444 bool report_check(
int line,
const char *predicate,
bool result)
5447 const char *msg = predicate ?
"OK! " :
"OK!";
5450 ++num_failed_checks;
5451 msg = predicate ?
"ERROR: " :
"ERROR";
5453 std::cout << __FILE__ <<
':' << line <<
": " << msg << (predicate ? predicate :
"") << std::endl;
5460 std::cout <<
"Completed " << num_checks <<
" checks." << std::endl;
5461 if(num_failed_checks)
5462 std::cout <<
"ERROR: " << num_failed_checks <<
'/' << num_checks <<
" checks failed." << std::endl;
5464 std::cout <<
"SUCCESS!" << std::endl;
5465 return num_failed_checks;
5473 static std::jmp_buf s_jmp_env;
5474 static std::string s_jmp_msg;
5481 bool expected_error_occurred =
false;
5488 expected_error_occurred =
true;
5490 return expected_error_occurred;
5512 std::string full_msg = ryml::formatrs<std::string>(
5513 "{}:{}:{} ({}B): ERROR: {}",
5517 throw std::runtime_error(full_msg);
5521 s_jmp_msg = full_msg;
5522 std::longjmp(s_jmp_env, 1);
5550 C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4996)
5552 template<class CharContainer>
5555 std::FILE *fp = std::fopen(filename,
"rb");
5556 RYML_CHECK_MSG(fp !=
nullptr,
"could not open file");
5557 std::fseek(fp, 0, SEEK_END);
5558 long sz = std::ftell(fp);
5559 v->resize(
static_cast<typename CharContainer::size_type
>(sz));
5563 size_t ret = std::fread(&(*v)[0], 1, v->size(), fp);
5564 RYML_CHECK(ret == (
size_t)sz);
5571 template<
class CharContainer>
5580 template<
class CharContainer>
5581 void file_put_contents(
const char *filename, CharContainer
const& v,
const char* access)
5587 void file_put_contents(
const char *filename,
const char *buf,
size_t sz,
const char* access)
5589 std::FILE *fp = std::fopen(filename, access);
5590 RYML_CHECK_MSG(fp !=
nullptr,
"could not open file");
5591 std::fwrite(buf, 1, sz, fp);
5594 C4_SUPPRESS_WARNING_MSVC_POP
5602 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...
void set_style_conditionally(NodeType type_mask, NodeType rem_style_flags, NodeType add_style_flags, bool recurse=false)
void clear_style(bool recurse=false)
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.
void set_val_ref(csubstr val_ref)
This is the main driver of parsing logic: it scans the YAML or JSON source for tokens,...
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.
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
void set_val_ref(id_type node, csubstr ref)
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)
bool in_arena(csubstr s) const
return true if the given substring is part of the tree's string arena
void set_key_style(id_type node, NodeType_e style)
Callbacks const & callbacks() const
void clear_style(id_type node, bool recurse=false)
id_type next_sibling(id_type node) const
ConstNodeRef crootref() const
Get the root as a ConstNodeRef.
csubstr const & key(id_type node) const
void set_style_conditionally(id_type node, NodeType type_mask, NodeType rem_style_flags, NodeType add_style_flags, bool recurse=false)
void set_val_anchor(id_type node, csubstr anchor)
NodeRef docref(id_type i)
get the i-th document of the stream
bool is_doc(id_type node) const
void set_container_style(id_type node, NodeType_e style)
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
void resolve(ReferenceResolver *rr, bool clear_anchors=true)
Resolve references (aliases <- anchors), by forwarding to ReferenceResolver::resolve(); refer to Refe...
bool is_seq(id_type node) const
id_type find_child(id_type node, csubstr const &key) const
Location location(Parser const &p, id_type node) const
Get the location of a node from the parse used to parse this tree.
void set_val_style(id_type node, NodeType_e style)
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
void set_key_anchor(id_type node, csubstr anchor)
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.
@ KEY_DQUO
mark key scalar as double quoted "
@ MAP
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
@ VAL_STYLE
mask of all the scalar styles for val (not container styles!)
@ FLOW_SL
mark container with single-line flow style (seqs as '[val1,val2], maps as '{key: val,...
@ VAL
a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or S...
@ SEQ
a seq: a parent of VAL/SEQ/MAP nodes
@ VAL_SQUO
mark val scalar as single quoted '
@ KEY_STYLE
mask of all the scalar styles for key (not container styles!)
@ VAL_PLAIN
mark val scalar as plain scalar (unquoted, even when multiline)
@ BLOCK
mark container with block style (seqs as '- val ', maps as 'key: val')
@ VAL_DQUO
mark val scalar as double quoted "
@ KEY_SQUO
mark key scalar as single quoted '
@ KEY_LITERAL
mark key scalar as multiline, block literal |
@ KEY_PLAIN
mark key scalar as plain scalar (unquoted, even when multiline)
@ KEY_FOLDED
mark key scalar as multiline, block folded >
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_anchors_and_aliases_create()
demonstrates how to use the API to programatically create anchors and aliases
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_empty_null_values()
Shows how to deal with empty/null values.
void sample_style()
[experimental] how to query/set/modify node style.
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)
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.
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_block() const RYML_NOEXCEPT
Forward to Tree::is_block().
Location location(Parser const &parser) const
bool is_seq() const RYML_NOEXCEPT
Forward to Tree::is_seq().
bool has_val() const RYML_NOEXCEPT
Forward to Tree::has_val().
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_)
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