These types are imported from the c4core library into the ryml namespace You may have noticed above the use of a csubstr class. This class is defined in another library, c4core, which is imported by ryml. This is a library I use with my projects consisting of multiplatform low-level utilities. One of these is c4::csubstr (the name comes from "constant substring") which is a non-owning read-only string view, with many methods that make it practical to use (I would certainly argue more practical than std::string). In fact, c4::csubstr and its writeable counterpart c4::substr are the workhorses of the ryml parsing and serialization code.
1147{
1148
1149
1150
1151
1152 {
1153 const char foobar_str[] = "foobar";
1155 CHECK(s ==
"foobar");
1156 CHECK(s.size() == 6);
1157 CHECK(s.data() == foobar_str);
1158 CHECK(s.size() == s.len);
1159 CHECK(s.data() == s.str);
1160 }
1161
1162
1163 {
1164 const char foobar_str[] = "foobar";
1166 CHECK(s ==
"foobar");
1167 CHECK(s !=
"foobar0");
1172 }
1173
1174 {
1176 CHECK(s ==
"foobar");
1177 CHECK(s !=
"foobar0");
1181 }
1182
1183
1184
1185
1186
1187
1188 {
1189 const char *foobar_str = "foobar";
1191 CHECK(s ==
"foobar");
1192 CHECK(s !=
"foobar0");
1196 }
1197
1198
1199
1200
1201
1202
1203
1204
1205 {
1206 std::string foobar_str = "foobar";
1208 CHECK(s ==
"foobar");
1209 CHECK(s !=
"foobar0");
1213 }
1214
1215
1216 {
1217 char buf[] = "foo";
1223 }
1224
1225 {
1226
1227 }
1228
1229
1230 {
1231 char const foobar_str_ro[] = "foobar";
1232 char foobar_str_rw[] = "foobar";
1233 static_assert(std::is_array<decltype(foobar_str_ro)>::value, "this is an array");
1234 static_assert(std::is_array<decltype(foobar_str_rw)>::value, "this is an array");
1235
1236 {
1239 CHECK(foobar.
size() == strlen(foobar_str_ro));
1240 CHECK(foobar ==
"foobar");
1241 }
1242
1243 {
1246 CHECK(foobar.
size() == strlen(foobar_str_rw));
1247 CHECK(foobar ==
"foobar");
1248 }
1249
1250 {
1253 CHECK(foobar.
size() == strlen(foobar_str_rw));
1254 CHECK(foobar ==
"foobar");
1255 }
1256
1257 {
1258
1259 }
1260 }
1261
1262
1263
1264 {
1265 char const* foobar_str_ro = "foobar";
1266 char foobar_str_rw_[] = "foobar";
1267 char * foobar_str_rw = foobar_str_rw_;
1268 static_assert(!std::is_array<decltype(foobar_str_ro)>::value, "this is a decayed pointer");
1269 static_assert(!std::is_array<decltype(foobar_str_rw)>::value, "this is a decayed pointer");
1270
1271 {
1272
1275 CHECK(foobar.
size() == strlen(foobar_str_ro));
1276 CHECK(foobar ==
"foobar");
1277 }
1278
1279 {
1282 CHECK(foobar.
size() == strlen(foobar_str_rw));
1283 CHECK(foobar ==
"foobar");
1284 }
1285
1286 {
1289 CHECK(foobar.
size() == strlen(foobar_str_rw));
1290 CHECK(foobar ==
"foobar");
1291 }
1292
1293 {
1294
1295 }
1296 }
1297
1298
1299 {
1300 char buf[] = "foobar";
1302 CHECK(foobar ==
"foobar");
1303 foobar[0] =
'F';
CHECK(foobar ==
"Foobar");
1304 foobar.
back() =
'R';
CHECK(foobar ==
"FoobaR");
1316 foobar.
fill(
'.');
CHECK(foobar ==
"......");
1317
1318
1319
1320 }
1321
1322
1323 {
1326
1328 CHECK(s.
sub(0, 12) ==
"fooFOObarBAR");
1336
1342
1347
1353
1360
1369
1377
1382 }
1383
1384
1385 {
1388 CHECK(some ==
"some");
1389 CHECK(s ==
"some substring");
1390
1391 {
1392 char result[32] = {0};
1393 std::snprintf(result,
sizeof(result),
"%.*s", (
int)some.
len, some.
str);
1394 printf("~~~%s~~~\n", result);
1397 }
1398
1399
1400
1401
1402
1403 {
1404 char result[32] = {0};
1405 std::snprintf(result,
sizeof(result),
"%s", some.
str);
1408 }
1409 }
1410
1411
1412 {
1415 CHECK(some ==
"some");
1416 CHECK(s ==
"some substring");
1417
1418 {
1419 std::stringstream ss;
1420 ss << s;
1421 CHECK(ss.str() ==
"some substring");
1422 CHECK(ss.str() == s);
1423 }
1424
1425
1426
1427
1428
1429 {
1430 std::stringstream ss;
1432 CHECK(ss.str() ==
"some substring");
1433 CHECK(ss.str() == s);
1434 }
1435
1436 {
1437 std::stringstream ss;
1439 CHECK(ss.str() ==
"some substring");
1440 CHECK(ss.str() == s);
1441 }
1442
1443 {
1444 std::stringstream ss;
1445 ss << some;
1446 CHECK(ss.str() ==
"some");
1447 CHECK(ss.str() == some);
1448 }
1449 }
1450
1451
1452 {
1459
1464 }
1465
1466
1467 {
1478 }
1479
1480
1481
1482
1483 {
1484 CHECK(
ryml::csubstr(
" \t\n\rcontents without whitespace\t \n\r").trim(
"\t \n\r") ==
"contents without whitespace");
1487
1505 CHECK(aaa___bbb.
trim (
'c') == aaa___bbb);
1506
1524 CHECK(aaa___bbb.
trim (
"cd") == aaa___bbb);
1525 }
1526
1527
1528 {
1529 CHECK(
ryml::csubstr(
"'this is is single quoted'" ).unquoted() ==
"this is is single quoted");
1530 CHECK(
ryml::csubstr(
"\"this is is double quoted\"").unquoted() ==
"this is is double quoted");
1531 }
1532
1533
1534
1535 {
1550 }
1551
1552
1553
1554 {
1556
1561
1572 }
1573
1574
1575 {
1589 }
1590
1591
1592 {
1594
1604
1612 }
1613
1614
1615 {
1646 }
1647
1648
1649 {
1680
1710 }
1711
1712
1713 {
1767 }
1768
1769
1770 {
1777 }
1778
1779 {
1787 }
1788
1789 {
1797 }
1798
1799 {
1816
1823
1830
1837 }
1838
1839
1840
1841 {
1848 CHECK(
ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extshort() ==
"/path/to/file.tar");
1850 }
1851
1852
1853 {
1854 using namespace ryml;
1855 csubstr parts[] = {
"aa",
"bb",
"cc",
"dd",
"ee",
"ff"};
1856 {
1857 size_t count = 0;
1859 CHECK(part == parts[count++]);
1861 }
1862 {
1863 size_t count = 0;
1865 CHECK(part == parts[count++]);
1867 }
1868 {
1869 size_t count = 0;
1871 CHECK(part == parts[count++]);
1873 }
1874
1875 }
1876
1877
1878
1879 {
1880 const bool skip_empty = true;
1881
1888
1907
1914
1933 }
1934}
#define CHECK(predicate)
a testing assertion, used only in this quickstart
substr to_substr(char(&s)[N]) noexcept
csubstr to_csubstr(const char(&s)[N]) noexcept
basic_substring< char > substr
a mutable string view
basic_substring< const char > csubstr
an immutable string view
@ npos
a null string position
bool begins_with_any(ro_substr chars) const noexcept
true if the first character of the string is any of the given chars
basic_substring trim(const C c) const
trim the character c left and right
size_t count(const C c, size_t pos=0) const
count the number of occurrences of c
auto reverse_sub(size_t ifirst, size_t num) -> typename std::enable_if< !std::is_const< U >::value, void >::type
revert a subpart in place
basic_substring range(size_t first, size_t last=npos) const noexcept
return [first,last[.
size_t first_not_of(const C c) const
auto tolower() -> typename std::enable_if< !std::is_const< U >::value, void >::type
convert the string to lower-case
bool begins_with(const C c) const noexcept
true if the first character of the string is c
basic_substring triml(const C c) const
trim left
size_t last_of(const C c, size_t start=npos) const
basic_substring offs(size_t left, size_t right) const noexcept
offset from the ends: return [left,len-right[ ; ie, trim a number of characters from the left and rig...
auto fill(C val) -> typename std::enable_if< !std::is_const< U >::value, void >::type
fill the entire contents with the given val
size_t len
the length of the substring
basic_substring last(size_t num) const noexcept
return the last num elements: [len-num,len[
bool ends_with(const C c) const noexcept
true if the last character of the string is c
size_t first_of(const C c, size_t start=0) const
basic_substring stripl(ro_substr pattern) const
remove a pattern from the left
size_t find(const C c, size_t start_pos=0) const
auto replace(C value, C repl, size_t pos=0) -> typename std::enable_if< ! std::is_const< U >::value, size_t >::type
replace every occurrence of character value with the character repl
basic_substring stripr(ro_substr pattern) const
remove a pattern from the right
size_t size() const noexcept
bool overlaps(ro_substr const that) const noexcept
true if there is overlap of at least one element between that and *this
basic_substring first(size_t num) const noexcept
return the first num elements: [0,num[
basic_substring left_of(size_t pos) const noexcept
return [0, pos[ .
basic_substring sub(size_t first) const noexcept
return [first,len[
bool ends_with_any(ro_substr chars) const noexcept
true if the last character of the string is any of the given chars
basic_substring trimr(const C c) const
trim the character c from the right
auto reverse_range(size_t ifirst, size_t ilast) -> typename std::enable_if< !std::is_const< U >::value, void >::type
revert a range in place
bool is_super(ro_substr const that) const noexcept
true if that is a substring of *this (ie, from the same buffer)
size_t last_not_of(const C c) const
auto toupper() -> typename std::enable_if< ! std::is_const< U >::value, void >::type
convert the string to upper-case
C * str
a restricted pointer to the first character of the substring
basic_substring right_of(size_t pos) const noexcept
return [pos+1, len[
bool is_sub(ro_substr const that) const noexcept
true if *this is a substring of that (ie, from the same buffer)
basic_substring select(const C c, size_t pos=0) const
get the substr consisting of the first occurrence of c after pos, or an empty substr if none occurs
auto reverse() -> typename std::enable_if< !std::is_const< U >::value, void >::type
reverse in place