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.
1145{
1146
1147
1148
1149
1150 {
1151 const char foobar_str[] = "foobar";
1153 CHECK(s ==
"foobar");
1154 CHECK(s.size() == 6);
1155 CHECK(s.data() == foobar_str);
1156 CHECK(s.size() == s.len);
1157 CHECK(s.data() == s.str);
1158 }
1159
1160
1161 {
1162 const char foobar_str[] = "foobar";
1164 CHECK(s ==
"foobar");
1165 CHECK(s !=
"foobar0");
1170 }
1171
1172 {
1174 CHECK(s ==
"foobar");
1175 CHECK(s !=
"foobar0");
1179 }
1180
1181
1182
1183
1184
1185
1186 {
1187 const char *foobar_str = "foobar";
1189 CHECK(s ==
"foobar");
1190 CHECK(s !=
"foobar0");
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203 {
1204 std::string foobar_str = "foobar";
1206 CHECK(s ==
"foobar");
1207 CHECK(s !=
"foobar0");
1211 }
1212
1213
1214 {
1215 char buf[] = "foo";
1221 }
1222
1223 {
1224
1225 }
1226
1227
1228 {
1229 char const foobar_str_ro[] = "foobar";
1230 char foobar_str_rw[] = "foobar";
1231 static_assert(std::is_array<decltype(foobar_str_ro)>::value, "this is an array");
1232 static_assert(std::is_array<decltype(foobar_str_rw)>::value, "this is an array");
1233
1234 {
1237 CHECK(foobar.
size() == strlen(foobar_str_ro));
1238 CHECK(foobar ==
"foobar");
1239 }
1240
1241 {
1244 CHECK(foobar.
size() == strlen(foobar_str_rw));
1245 CHECK(foobar ==
"foobar");
1246 }
1247
1248 {
1251 CHECK(foobar.
size() == strlen(foobar_str_rw));
1252 CHECK(foobar ==
"foobar");
1253 }
1254
1255 {
1256
1257 }
1258 }
1259
1260
1261
1262 {
1263 char const* foobar_str_ro = "foobar";
1264 char foobar_str_rw_[] = "foobar";
1265 char * foobar_str_rw = foobar_str_rw_;
1266 static_assert(!std::is_array<decltype(foobar_str_ro)>::value, "this is a decayed pointer");
1267 static_assert(!std::is_array<decltype(foobar_str_rw)>::value, "this is a decayed pointer");
1268
1269 {
1270
1273 CHECK(foobar.
size() == strlen(foobar_str_ro));
1274 CHECK(foobar ==
"foobar");
1275 }
1276
1277 {
1280 CHECK(foobar.
size() == strlen(foobar_str_rw));
1281 CHECK(foobar ==
"foobar");
1282 }
1283
1284 {
1287 CHECK(foobar.
size() == strlen(foobar_str_rw));
1288 CHECK(foobar ==
"foobar");
1289 }
1290
1291 {
1292
1293 }
1294 }
1295
1296
1297 {
1298 char buf[] = "foobar";
1300 CHECK(foobar ==
"foobar");
1301 foobar[0] =
'F';
CHECK(foobar ==
"Foobar");
1302 foobar.
back() =
'R';
CHECK(foobar ==
"FoobaR");
1314 foobar.
fill(
'.');
CHECK(foobar ==
"......");
1315
1316
1317
1318 }
1319
1320
1321 {
1324
1326 CHECK(s.
sub(0, 12) ==
"fooFOObarBAR");
1334
1340
1345
1351
1358
1367
1375
1380 }
1381
1382
1383 {
1386 CHECK(some ==
"some");
1387 CHECK(s ==
"some substring");
1388
1389 {
1390 char result[32] = {0};
1391 std::snprintf(result,
sizeof(result),
"%.*s", (
int)some.
len, some.
str);
1392 printf("~~~%s~~~\n", result);
1395 }
1396
1397
1398
1399
1400
1401 {
1402 char result[32] = {0};
1403 std::snprintf(result,
sizeof(result),
"%s", some.
str);
1406 }
1407 }
1408
1409
1410 {
1413 CHECK(some ==
"some");
1414 CHECK(s ==
"some substring");
1415
1416 {
1417 std::stringstream ss;
1418 ss << s;
1419 CHECK(ss.str() ==
"some substring");
1420 CHECK(ss.str() == s);
1421 }
1422
1423
1424
1425
1426
1427 {
1428 std::stringstream ss;
1430 CHECK(ss.str() ==
"some substring");
1431 CHECK(ss.str() == s);
1432 }
1433
1434 {
1435 std::stringstream ss;
1437 CHECK(ss.str() ==
"some substring");
1438 CHECK(ss.str() == s);
1439 }
1440
1441 {
1442 std::stringstream ss;
1443 ss << some;
1444 CHECK(ss.str() ==
"some");
1445 CHECK(ss.str() == some);
1446 }
1447 }
1448
1449
1450 {
1457
1462 }
1463
1464
1465 {
1476 }
1477
1478
1479
1480
1481 {
1482 CHECK(
ryml::csubstr(
" \t\n\rcontents without whitespace\t \n\r").trim(
"\t \n\r") ==
"contents without whitespace");
1485
1503 CHECK(aaa___bbb.
trim (
'c') == aaa___bbb);
1504
1522 CHECK(aaa___bbb.
trim (
"cd") == aaa___bbb);
1523 }
1524
1525
1526 {
1527 CHECK(
ryml::csubstr(
"'this is is single quoted'" ).unquoted() ==
"this is is single quoted");
1528 CHECK(
ryml::csubstr(
"\"this is is double quoted\"").unquoted() ==
"this is is double quoted");
1529 }
1530
1531
1532
1533 {
1548 }
1549
1550
1551
1552 {
1554
1559
1570 }
1571
1572
1573 {
1587 }
1588
1589
1590 {
1592
1602
1610 }
1611
1612
1613 {
1644 }
1645
1646
1647 {
1678
1708 }
1709
1710
1711 {
1765 }
1766
1767
1768 {
1775 }
1776
1777 {
1785 }
1786
1787 {
1795 }
1796
1797 {
1814
1821
1828
1835 }
1836
1837
1838
1839 {
1846 CHECK(
ryml::csubstr(
"/path/to/file.tar.gz").name_wo_extshort() ==
"/path/to/file.tar");
1848 }
1849
1850
1851 {
1852 using namespace ryml;
1853 csubstr parts[] = {
"aa",
"bb",
"cc",
"dd",
"ee",
"ff"};
1854 {
1855 size_t count = 0;
1857 CHECK(part == parts[count++]);
1859 }
1860 {
1861 size_t count = 0;
1863 CHECK(part == parts[count++]);
1865 }
1866 {
1867 size_t count = 0;
1869 CHECK(part == parts[count++]);
1871 }
1872
1873 }
1874
1875
1876
1877 {
1878 const bool skip_empty = true;
1879
1886
1905
1912
1931 }
1932}
#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