rapidyaml 0.16.0
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
Using csubstr

Functions

void sample_substr ()
 about ryml's string views (from c4core)

Detailed Description

Function Documentation

◆ sample_substr()

void sample_substr ( )

about ryml's string views (from c4core)

demonstrate usage of ryml::substr and ryml::csubstr

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.

See also
Substring: read/write string views

Definition at line 1146 of file quickstart.cpp.

1147{
1148 // substr is a mutable view: pointer and length to a string in memory.
1149 // csubstr is a const-substr (immutable).
1150
1151 // construct from explicit args
1152 {
1153 const char foobar_str[] = "foobar";
1154 auto s = ryml::csubstr(foobar_str, strlen(foobar_str));
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 // construct from a string array
1163 {
1164 const char foobar_str[] = "foobar";
1165 ryml::csubstr s = foobar_str;
1166 CHECK(s == "foobar");
1167 CHECK(s != "foobar0");
1168 CHECK(s.size() == 6); // does not include the terminating \0
1169 CHECK(s.data() == foobar_str);
1170 CHECK(s.size() == s.len);
1171 CHECK(s.data() == s.str);
1172 }
1173 // you can also declare directly in-place from an array:
1174 {
1175 ryml::csubstr s = "foobar";
1176 CHECK(s == "foobar");
1177 CHECK(s != "foobar0");
1178 CHECK(s.size() == 6);
1179 CHECK(s.size() == s.len);
1180 CHECK(s.data() == s.str);
1181 }
1182
1183 // construct from a C-string:
1184 //
1185 // Since the input is only a pointer, the string length can only
1186 // be found with a call to strlen(). To make this cost evident, we
1187 // require calling to_csubstr():
1188 {
1189 const char *foobar_str = "foobar";
1190 ryml::csubstr s = ryml::to_csubstr(foobar_str);
1191 CHECK(s == "foobar");
1192 CHECK(s != "foobar0");
1193 CHECK(s.size() == 6);
1194 CHECK(s.size() == s.len);
1195 CHECK(s.data() == s.str);
1196 }
1197
1198 // construct from a std::string: same approach as above.
1199 // requires inclusion of the <ryml/std/string.hpp> header
1200 // or of the umbrella header <ryml_std.hpp>.
1201 //
1202 // not including <string> in the default header is a deliberate
1203 // design choice to avoid including the heavy std:: allocation
1204 // machinery
1205 {
1206 std::string foobar_str = "foobar";
1207 ryml::csubstr s = ryml::to_csubstr(foobar_str); // defined in <ryml/std/string.hpp>
1208 CHECK(s == "foobar");
1209 CHECK(s != "foobar0");
1210 CHECK(s.size() == 6);
1211 CHECK(s.size() == s.len);
1212 CHECK(s.data() == s.str);
1213 }
1214
1215 // convert substr -> csubstr
1216 {
1217 char buf[] = "foo";
1218 ryml::substr foo = buf;
1219 CHECK(foo.len == 3);
1220 CHECK(foo.data() == buf);
1221 ryml::csubstr cfoo = foo;
1222 CHECK(cfoo.data() == buf);
1223 }
1224 // cannot convert csubstr -> substr:
1225 {
1226 // ryml::substr foo2 = cfoo; // compile error: cannot write to csubstr
1227 }
1228
1229 // construct from char[]/const char[]: mutable vs immutable memory
1230 {
1231 char const foobar_str_ro[] = "foobar"; // ro := read-only
1232 char foobar_str_rw[] = "foobar"; // rw := read-write
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 // csubstr <- read-only memory
1236 {
1237 ryml::csubstr foobar = foobar_str_ro;
1238 CHECK(foobar.data() == foobar_str_ro);
1239 CHECK(foobar.size() == strlen(foobar_str_ro));
1240 CHECK(foobar == "foobar"); // AKA strcmp
1241 }
1242 // csubstr <- read-write memory: you can create an immutable csubstr from mutable memory
1243 {
1244 ryml::csubstr foobar = foobar_str_rw;
1245 CHECK(foobar.data() == foobar_str_rw);
1246 CHECK(foobar.size() == strlen(foobar_str_rw));
1247 CHECK(foobar == "foobar"); // AKA strcmp
1248 }
1249 // substr <- read-write memory.
1250 {
1251 ryml::substr foobar = foobar_str_rw;
1252 CHECK(foobar.data() == foobar_str_rw);
1253 CHECK(foobar.size() == strlen(foobar_str_rw));
1254 CHECK(foobar == "foobar"); // AKA strcmp
1255 }
1256 // substr <- ro is impossible.
1257 {
1258 //ryml::substr foobar = foobar_str_ro; // compile error!
1259 }
1260 }
1261
1262 // construct from char*/const char*: mutable vs immutable memory.
1263 // use to_substr()/to_csubstr()
1264 {
1265 char const* foobar_str_ro = "foobar"; // ro := read-only
1266 char foobar_str_rw_[] = "foobar"; // rw := read-write
1267 char * foobar_str_rw = foobar_str_rw_; // rw := read-write
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 // csubstr <- read-only memory
1271 {
1272 //ryml::csubstr foobar = foobar_str_ro; // compile error: length is not known
1273 ryml::csubstr foobar = ryml::to_csubstr(foobar_str_ro);
1274 CHECK(foobar.data() == foobar_str_ro);
1275 CHECK(foobar.size() == strlen(foobar_str_ro));
1276 CHECK(foobar == "foobar"); // AKA strcmp
1277 }
1278 // csubstr <- read-write memory: you can create an immutable csubstr from mutable memory
1279 {
1280 ryml::csubstr foobar = ryml::to_csubstr(foobar_str_rw);
1281 CHECK(foobar.data() == foobar_str_rw);
1282 CHECK(foobar.size() == strlen(foobar_str_rw));
1283 CHECK(foobar == "foobar"); // AKA strcmp
1284 }
1285 // substr <- read-write memory.
1286 {
1287 ryml::substr foobar = ryml::to_substr(foobar_str_rw);
1288 CHECK(foobar.data() == foobar_str_rw);
1289 CHECK(foobar.size() == strlen(foobar_str_rw));
1290 CHECK(foobar == "foobar"); // AKA strcmp
1291 }
1292 // substr <- read-only is impossible.
1293 {
1294 //ryml::substr foobar = ryml::to_substr(foobar_str_ro); // compile error!
1295 }
1296 }
1297
1298 // substr is mutable, without changing the size:
1299 {
1300 char buf[] = "foobar";
1301 ryml::substr foobar = buf;
1302 CHECK(foobar == "foobar");
1303 foobar[0] = 'F'; CHECK(foobar == "Foobar");
1304 foobar.back() = 'R'; CHECK(foobar == "FoobaR");
1305 foobar.reverse(); CHECK(foobar == "RabooF");
1306 foobar.reverse(); CHECK(foobar == "FoobaR");
1307 foobar.reverse_sub(1, 4); CHECK(foobar == "FabooR");
1308 foobar.reverse_sub(1, 4); CHECK(foobar == "FoobaR");
1309 foobar.reverse_range(2, 5); CHECK(foobar == "FoaboR");
1310 foobar.reverse_range(2, 5); CHECK(foobar == "FoobaR");
1311 foobar.replace('o', '0'); CHECK(foobar == "F00baR");
1312 foobar.replace('a', '_'); CHECK(foobar == "F00b_R");
1313 foobar.replace("_0b", 'a'); CHECK(foobar == "FaaaaR");
1314 foobar.toupper(); CHECK(foobar == "FAAAAR");
1315 foobar.tolower(); CHECK(foobar == "faaaar");
1316 foobar.fill('.'); CHECK(foobar == "......");
1317 // see also:
1318 // - .erase()
1319 // - .replace_all()
1320 }
1321
1322 // sub-views
1323 {
1324 ryml::csubstr s = "fooFOObarBAR";
1325 CHECK(s.len == 12u);
1326 // sub(): <- first,[num]
1327 CHECK(s.sub(0) == "fooFOObarBAR");
1328 CHECK(s.sub(0, 12) == "fooFOObarBAR");
1329 CHECK(s.sub(0, 3) == "foo" );
1330 CHECK(s.sub(3) == "FOObarBAR");
1331 CHECK(s.sub(3, 3) == "FOO" );
1332 CHECK(s.sub(6) == "barBAR");
1333 CHECK(s.sub(6, 3) == "bar" );
1334 CHECK(s.sub(9) == "BAR");
1335 CHECK(s.sub(9, 3) == "BAR");
1336 // first(): <- length
1337 CHECK(s.first(0) == "" );
1338 CHECK(s.first(1) == "f" );
1339 CHECK(s.first(2) != "f" );
1340 CHECK(s.first(2) == "fo" );
1341 CHECK(s.first(3) == "foo");
1342 // last(): <- length
1343 CHECK(s.last(0) == "");
1344 CHECK(s.last(1) == "R");
1345 CHECK(s.last(2) == "AR");
1346 CHECK(s.last(3) == "BAR");
1347 // range(): <- first, last
1348 CHECK(s.range(0, 12) == "fooFOObarBAR");
1349 CHECK(s.range(1, 12) == "ooFOObarBAR");
1350 CHECK(s.range(1, 11) == "ooFOObarBA" );
1351 CHECK(s.range(2, 10) == "oFOObarB" );
1352 CHECK(s.range(3, 9) == "FOObar" );
1353 // offs(): offset from beginning, end
1354 CHECK(s.offs(0, 0) == "fooFOObarBAR");
1355 CHECK(s.offs(1, 0) == "ooFOObarBAR");
1356 CHECK(s.offs(1, 1) == "ooFOObarBA" );
1357 CHECK(s.offs(2, 1) == "oFOObarBA" );
1358 CHECK(s.offs(2, 2) == "oFOObarB" );
1359 CHECK(s.offs(3, 3) == "FOObar" );
1360 // right_of(): <- pos, include_pos
1361 CHECK(s.right_of(0, true) == "fooFOObarBAR");
1362 CHECK(s.right_of(0, false) == "ooFOObarBAR");
1363 CHECK(s.right_of(1, true) == "ooFOObarBAR");
1364 CHECK(s.right_of(1, false) == "oFOObarBAR");
1365 CHECK(s.right_of(2, true) == "oFOObarBAR");
1366 CHECK(s.right_of(2, false) == "FOObarBAR");
1367 CHECK(s.right_of(3, true) == "FOObarBAR");
1368 CHECK(s.right_of(3, false) == "OObarBAR");
1369 // left_of() <- pos, include_pos
1370 CHECK(s.left_of(12, false) == "fooFOObarBAR");
1371 CHECK(s.left_of(11, true) == "fooFOObarBAR");
1372 CHECK(s.left_of(11, false) == "fooFOObarBA" );
1373 CHECK(s.left_of(10, true) == "fooFOObarBA" );
1374 CHECK(s.left_of(10, false) == "fooFOObarB" );
1375 CHECK(s.left_of( 9, true) == "fooFOObarB" );
1376 CHECK(s.left_of( 9, false) == "fooFOObar" );
1377 // left_of(),right_of() <- substr
1378 ryml::csubstr FOO = s.sub(3, 3);
1379 CHECK(s.is_super(FOO)); // required for the following
1380 CHECK(s.left_of(FOO) == "foo");
1381 CHECK(s.right_of(FOO) == "barBAR");
1382 }
1383
1384 // printing a substr/csubstr using printf-like
1385 {
1386 ryml::csubstr s = "some substring";
1387 ryml::csubstr some = s.first(4);
1388 CHECK(some == "some");
1389 CHECK(s == "some substring");
1390 // To print a csubstr using printf(), use the %.*s format specifier:
1391 {
1392 char result[32] = {0};
1393 std::snprintf(result, sizeof(result), "%.*s", (int)some.len, some.str);
1394 printf("~~~%s~~~\n", result);
1395 CHECK(ryml::to_csubstr((const char*)result) == "some");
1396 CHECK(ryml::to_csubstr((const char*)result) == some);
1397 }
1398 // But NOTE: because this is a string view type, in general
1399 // the C-string is NOT zero terminated. So NEVER printf it
1400 // directly, or it will overflow past the end of the given
1401 // substr, with a potential unbounded access. For example,
1402 // this is really bad:
1403 {
1404 char result[32] = {0};
1405 std::snprintf(result, sizeof(result), "%s", some.str); // ERROR! do not print the c-string directly
1406 CHECK(ryml::to_csubstr((const char*)result) == "some substring");
1407 CHECK(ryml::to_csubstr((const char*)result) == s);
1408 }
1409 }
1410
1411 // printing a substr/csubstr using ostreams
1412 {
1413 ryml::csubstr s = "some substring";
1414 ryml::csubstr some = s.first(4);
1415 CHECK(some == "some");
1416 CHECK(s == "some substring");
1417 // simple! just use plain operator<<
1418 {
1419 std::stringstream ss;
1420 ss << s;
1421 CHECK(ss.str() == "some substring"); // as expected
1422 CHECK(ss.str() == s); // as expected
1423 }
1424 // But NOTE: because this is a string view type, in general
1425 // the C-string is NOT zero terminated. So NEVER print it
1426 // directly, or it will overflow past the end of the given
1427 // substr, with a potential unbounded access. For example,
1428 // this is bad:
1429 {
1430 std::stringstream ss;
1431 ss << some.str; // ERROR! do not print the c-string directly
1432 CHECK(ss.str() == "some substring"); // NOT "some"
1433 CHECK(ss.str() == s); // NOT some
1434 }
1435 // this is also bad (the same)
1436 {
1437 std::stringstream ss;
1438 ss << some.data(); // ERROR! do not print the c-string directly
1439 CHECK(ss.str() == "some substring"); // NOT "some"
1440 CHECK(ss.str() == s); // NOT some
1441 }
1442 // this is ok:
1443 {
1444 std::stringstream ss;
1445 ss << some;
1446 CHECK(ss.str() == "some"); // ok
1447 CHECK(ss.str() == some); // ok
1448 }
1449 }
1450
1451 // is_sub(),is_super()
1452 {
1453 ryml::csubstr foobar = "foobar";
1454 ryml::csubstr foo = foobar.first(3);
1455 CHECK(foo.is_sub(foobar));
1456 CHECK(foo.is_sub(foo));
1457 CHECK(!foo.is_super(foobar));
1458 CHECK(!foobar.is_sub(foo));
1459 // identity comparison is true:
1460 CHECK(foo.is_super(foo));
1461 CHECK(foo.is_sub(foo));
1462 CHECK(foobar.is_sub(foobar));
1463 CHECK(foobar.is_super(foobar));
1464 }
1465
1466 // overlaps()
1467 {
1468 ryml::csubstr foobar = "foobar";
1469 ryml::csubstr foo = foobar.first(3);
1470 ryml::csubstr oba = foobar.offs(2, 1);
1471 ryml::csubstr abc = "abc";
1472 CHECK(foobar.overlaps(foo));
1473 CHECK(foobar.overlaps(oba));
1474 CHECK(foo.overlaps(foobar));
1475 CHECK(foo.overlaps(oba));
1476 CHECK(!foo.overlaps(abc));
1477 CHECK(!abc.overlaps(foo));
1478 }
1479
1480 // triml(): trim characters from the left
1481 // trimr(): trim characters from the right
1482 // trim(): trim characters from left AND right
1483 {
1484 CHECK(ryml::csubstr(" \t\n\rcontents without whitespace\t \n\r").trim("\t \n\r") == "contents without whitespace");
1485 ryml::csubstr aaabbb = "aaabbb";
1486 ryml::csubstr aaa___bbb = "aaa___bbb";
1487 // trim a character:
1488 CHECK(aaabbb.triml('a') == aaabbb.last(3)); // bbb
1489 CHECK(aaabbb.trimr('a') == aaabbb);
1490 CHECK(aaabbb.trim ('a') == aaabbb.last(3)); // bbb
1491 CHECK(aaabbb.triml('b') == aaabbb);
1492 CHECK(aaabbb.trimr('b') == aaabbb.first(3)); // aaa
1493 CHECK(aaabbb.trim ('b') == aaabbb.first(3)); // aaa
1494 CHECK(aaabbb.triml('c') == aaabbb);
1495 CHECK(aaabbb.trimr('c') == aaabbb);
1496 CHECK(aaabbb.trim ('c') == aaabbb);
1497 CHECK(aaa___bbb.triml('a') == aaa___bbb.last(6)); // ___bbb
1498 CHECK(aaa___bbb.trimr('a') == aaa___bbb);
1499 CHECK(aaa___bbb.trim ('a') == aaa___bbb.last(6)); // ___bbb
1500 CHECK(aaa___bbb.triml('b') == aaa___bbb);
1501 CHECK(aaa___bbb.trimr('b') == aaa___bbb.first(6)); // aaa___
1502 CHECK(aaa___bbb.trim ('b') == aaa___bbb.first(6)); // aaa___
1503 CHECK(aaa___bbb.triml('c') == aaa___bbb);
1504 CHECK(aaa___bbb.trimr('c') == aaa___bbb);
1505 CHECK(aaa___bbb.trim ('c') == aaa___bbb);
1506 // trim ANY of the characters:
1507 CHECK(aaabbb.triml("ab") == "");
1508 CHECK(aaabbb.trimr("ab") == "");
1509 CHECK(aaabbb.trim ("ab") == "");
1510 CHECK(aaabbb.triml("ba") == "");
1511 CHECK(aaabbb.trimr("ba") == "");
1512 CHECK(aaabbb.trim ("ba") == "");
1513 CHECK(aaabbb.triml("cd") == aaabbb);
1514 CHECK(aaabbb.trimr("cd") == aaabbb);
1515 CHECK(aaabbb.trim ("cd") == aaabbb);
1516 CHECK(aaa___bbb.triml("ab") == aaa___bbb.last(6)); // ___bbb
1517 CHECK(aaa___bbb.triml("ba") == aaa___bbb.last(6)); // ___bbb
1518 CHECK(aaa___bbb.triml("cd") == aaa___bbb);
1519 CHECK(aaa___bbb.trimr("ab") == aaa___bbb.first(6)); // aaa___
1520 CHECK(aaa___bbb.trimr("ba") == aaa___bbb.first(6)); // aaa___
1521 CHECK(aaa___bbb.trimr("cd") == aaa___bbb);
1522 CHECK(aaa___bbb.trim ("ab") == aaa___bbb.range(3, 6)); // ___
1523 CHECK(aaa___bbb.trim ("ba") == aaa___bbb.range(3, 6)); // ___
1524 CHECK(aaa___bbb.trim ("cd") == aaa___bbb);
1525 }
1526
1527 // unquoted():
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 // stripl(): remove pattern from the left
1534 // stripr(): remove pattern from the right
1535 {
1536 ryml::csubstr abc___cba = "abc___cba";
1537 ryml::csubstr abc___abc = "abc___abc";
1538 CHECK(abc___cba.stripl("abc") == abc___cba.last(6)); // ___cba
1539 CHECK(abc___cba.stripr("abc") == abc___cba);
1540 CHECK(abc___cba.stripl("ab") == abc___cba.last(7)); // c___cba
1541 CHECK(abc___cba.stripr("ab") == abc___cba);
1542 CHECK(abc___cba.stripl("a") == abc___cba.last(8)); // bc___cba, same as triml('a')
1543 CHECK(abc___cba.stripr("a") == abc___cba.first(8));
1544 CHECK(abc___abc.stripl("abc") == abc___abc.last(6)); // ___abc
1545 CHECK(abc___abc.stripr("abc") == abc___abc.first(6)); // abc___
1546 CHECK(abc___abc.stripl("ab") == abc___abc.last(7)); // c___cba
1547 CHECK(abc___abc.stripr("ab") == abc___abc);
1548 CHECK(abc___abc.stripl("a") == abc___abc.last(8)); // bc___cba, same as triml('a')
1549 CHECK(abc___abc.stripr("a") == abc___abc);
1550 }
1551
1552 // begins_with()/ends_with()
1553 // begins_with_any()/ends_with_any()
1554 {
1555 ryml::csubstr s = "foobar123";
1556 // char overloads
1557 CHECK(s.begins_with('f'));
1558 CHECK(s.ends_with('3'));
1559 CHECK(!s.ends_with('2'));
1560 CHECK(!s.ends_with('o'));
1561 // char[] overloads
1562 CHECK(s.begins_with("foobar"));
1563 CHECK(s.begins_with("foo"));
1564 CHECK(s.begins_with_any("foo"));
1565 CHECK(!s.begins_with("oof"));
1566 CHECK(s.begins_with_any("oof"));
1567 CHECK(s.ends_with("23"));
1568 CHECK(s.ends_with("123"));
1569 CHECK(s.ends_with_any("123"));
1570 CHECK(!s.ends_with("321"));
1571 CHECK(s.ends_with_any("231"));
1572 }
1573
1574 // select()
1575 {
1576 ryml::csubstr s = "0123456789";
1577 CHECK(s.select('0') == s.sub(0, 1));
1578 CHECK(s.select('1') == s.sub(1, 1));
1579 CHECK(s.select('2') == s.sub(2, 1));
1580 CHECK(s.select('8') == s.sub(8, 1));
1581 CHECK(s.select('9') == s.sub(9, 1));
1582 CHECK(s.select("0123") == s.range(0, 4));
1583 CHECK(s.select("012" ) == s.range(0, 3));
1584 CHECK(s.select("01" ) == s.range(0, 2));
1585 CHECK(s.select("0" ) == s.range(0, 1));
1586 CHECK(s.select( "123") == s.range(1, 4));
1587 CHECK(s.select( "23") == s.range(2, 4));
1588 CHECK(s.select( "3") == s.range(3, 4));
1589 }
1590
1591 // find()
1592 {
1593 ryml::csubstr s012345 = "012345";
1594 // find single characters:
1595 CHECK(s012345.find('a') == ryml::npos);
1596 CHECK(s012345.find('0' ) == 0u);
1597 CHECK(s012345.find('0', 1u) == ryml::npos);
1598 CHECK(s012345.find('1' ) == 1u);
1599 CHECK(s012345.find('1', 2u) == ryml::npos);
1600 CHECK(s012345.find('2' ) == 2u);
1601 CHECK(s012345.find('2', 3u) == ryml::npos);
1602 CHECK(s012345.find('3' ) == 3u);
1603 CHECK(s012345.find('3', 4u) == ryml::npos);
1604 // find patterns
1605 CHECK(s012345.find("ab" ) == ryml::npos);
1606 CHECK(s012345.find("01" ) == 0u);
1607 CHECK(s012345.find("01", 1u) == ryml::npos);
1608 CHECK(s012345.find("12" ) == 1u);
1609 CHECK(s012345.find("12", 2u) == ryml::npos);
1610 CHECK(s012345.find("23" ) == 2u);
1611 CHECK(s012345.find("23", 3u) == ryml::npos);
1612 }
1613
1614 // count(): count the number of occurrences of a character
1615 {
1616 ryml::csubstr buf = "00110022003300440055";
1617 CHECK(buf.count('1' ) == 2u);
1618 CHECK(buf.count('1', 0u) == 2u);
1619 CHECK(buf.count('1', 1u) == 2u);
1620 CHECK(buf.count('1', 2u) == 2u);
1621 CHECK(buf.count('1', 3u) == 1u);
1622 CHECK(buf.count('1', 4u) == 0u);
1623 CHECK(buf.count('1', 5u) == 0u);
1624 CHECK(buf.count('0' ) == 10u);
1625 CHECK(buf.count('0', 0u) == 10u);
1626 CHECK(buf.count('0', 1u) == 9u);
1627 CHECK(buf.count('0', 2u) == 8u);
1628 CHECK(buf.count('0', 3u) == 8u);
1629 CHECK(buf.count('0', 4u) == 8u);
1630 CHECK(buf.count('0', 5u) == 7u);
1631 CHECK(buf.count('0', 6u) == 6u);
1632 CHECK(buf.count('0', 7u) == 6u);
1633 CHECK(buf.count('0', 8u) == 6u);
1634 CHECK(buf.count('0', 9u) == 5u);
1635 CHECK(buf.count('0', 10u) == 4u);
1636 CHECK(buf.count('0', 11u) == 4u);
1637 CHECK(buf.count('0', 12u) == 4u);
1638 CHECK(buf.count('0', 13u) == 3u);
1639 CHECK(buf.count('0', 14u) == 2u);
1640 CHECK(buf.count('0', 15u) == 2u);
1641 CHECK(buf.count('0', 16u) == 2u);
1642 CHECK(buf.count('0', 17u) == 1u);
1643 CHECK(buf.count('0', 18u) == 0u);
1644 CHECK(buf.count('0', 19u) == 0u);
1645 CHECK(buf.count('0', 20u) == 0u);
1646 }
1647
1648 // first_of(),last_of()
1649 {
1650 ryml::csubstr s012345 = "012345";
1651 CHECK(s012345.first_of('a') == ryml::npos);
1652 CHECK(s012345.first_of("ab") == ryml::npos);
1653 CHECK(s012345.first_of('0') == 0u);
1654 CHECK(s012345.first_of("0") == 0u);
1655 CHECK(s012345.first_of("01") == 0u);
1656 CHECK(s012345.first_of("10") == 0u);
1657 CHECK(s012345.first_of("012") == 0u);
1658 CHECK(s012345.first_of("210") == 0u);
1659 CHECK(s012345.first_of("0123") == 0u);
1660 CHECK(s012345.first_of("3210") == 0u);
1661 CHECK(s012345.first_of("01234") == 0u);
1662 CHECK(s012345.first_of("43210") == 0u);
1663 CHECK(s012345.first_of("012345") == 0u);
1664 CHECK(s012345.first_of("543210") == 0u);
1665 CHECK(s012345.first_of('5') == 5u);
1666 CHECK(s012345.first_of("5") == 5u);
1667 CHECK(s012345.first_of("45") == 4u);
1668 CHECK(s012345.first_of("54") == 4u);
1669 CHECK(s012345.first_of("345") == 3u);
1670 CHECK(s012345.first_of("543") == 3u);
1671 CHECK(s012345.first_of("2345") == 2u);
1672 CHECK(s012345.first_of("5432") == 2u);
1673 CHECK(s012345.first_of("12345") == 1u);
1674 CHECK(s012345.first_of("54321") == 1u);
1675 CHECK(s012345.first_of("012345") == 0u);
1676 CHECK(s012345.first_of("543210") == 0u);
1677 CHECK(s012345.first_of('0', 6u) == ryml::npos);
1678 CHECK(s012345.first_of('5', 6u) == ryml::npos);
1679 CHECK(s012345.first_of("012345", 6u) == ryml::npos);
1680 //
1681 CHECK(s012345.last_of('a') == ryml::npos);
1682 CHECK(s012345.last_of("ab") == ryml::npos);
1683 CHECK(s012345.last_of('0') == 0u);
1684 CHECK(s012345.last_of("0") == 0u);
1685 CHECK(s012345.last_of("01") == 1u);
1686 CHECK(s012345.last_of("10") == 1u);
1687 CHECK(s012345.last_of("012") == 2u);
1688 CHECK(s012345.last_of("210") == 2u);
1689 CHECK(s012345.last_of("0123") == 3u);
1690 CHECK(s012345.last_of("3210") == 3u);
1691 CHECK(s012345.last_of("01234") == 4u);
1692 CHECK(s012345.last_of("43210") == 4u);
1693 CHECK(s012345.last_of("012345") == 5u);
1694 CHECK(s012345.last_of("543210") == 5u);
1695 CHECK(s012345.last_of('5') == 5u);
1696 CHECK(s012345.last_of("5") == 5u);
1697 CHECK(s012345.last_of("45") == 5u);
1698 CHECK(s012345.last_of("54") == 5u);
1699 CHECK(s012345.last_of("345") == 5u);
1700 CHECK(s012345.last_of("543") == 5u);
1701 CHECK(s012345.last_of("2345") == 5u);
1702 CHECK(s012345.last_of("5432") == 5u);
1703 CHECK(s012345.last_of("12345") == 5u);
1704 CHECK(s012345.last_of("54321") == 5u);
1705 CHECK(s012345.last_of("012345") == 5u);
1706 CHECK(s012345.last_of("543210") == 5u);
1707 CHECK(s012345.last_of('0', 6u) == 0u);
1708 CHECK(s012345.last_of('5', 6u) == 5u);
1709 CHECK(s012345.last_of("012345", 6u) == 5u);
1710 }
1711
1712 // first_not_of(), last_not_of()
1713 {
1714 ryml::csubstr s012345 = "012345";
1715 CHECK(s012345.first_not_of('a') == 0u);
1716 CHECK(s012345.first_not_of("ab") == 0u);
1717 CHECK(s012345.first_not_of('0') == 1u);
1718 CHECK(s012345.first_not_of("0") == 1u);
1719 CHECK(s012345.first_not_of("01") == 2u);
1720 CHECK(s012345.first_not_of("10") == 2u);
1721 CHECK(s012345.first_not_of("012") == 3u);
1722 CHECK(s012345.first_not_of("210") == 3u);
1723 CHECK(s012345.first_not_of("0123") == 4u);
1724 CHECK(s012345.first_not_of("3210") == 4u);
1725 CHECK(s012345.first_not_of("01234") == 5u);
1726 CHECK(s012345.first_not_of("43210") == 5u);
1727 CHECK(s012345.first_not_of("012345") == ryml::npos);
1728 CHECK(s012345.first_not_of("543210") == ryml::npos);
1729 CHECK(s012345.first_not_of('5') == 0u);
1730 CHECK(s012345.first_not_of("5") == 0u);
1731 CHECK(s012345.first_not_of("45") == 0u);
1732 CHECK(s012345.first_not_of("54") == 0u);
1733 CHECK(s012345.first_not_of("345") == 0u);
1734 CHECK(s012345.first_not_of("543") == 0u);
1735 CHECK(s012345.first_not_of("2345") == 0u);
1736 CHECK(s012345.first_not_of("5432") == 0u);
1737 CHECK(s012345.first_not_of("12345") == 0u);
1738 CHECK(s012345.first_not_of("54321") == 0u);
1739 CHECK(s012345.first_not_of("012345") == ryml::npos);
1740 CHECK(s012345.first_not_of("543210") == ryml::npos);
1741 CHECK(s012345.last_not_of('a') == 5u);
1742 CHECK(s012345.last_not_of("ab") == 5u);
1743 CHECK(s012345.last_not_of('5') == 4u);
1744 CHECK(s012345.last_not_of("5") == 4u);
1745 CHECK(s012345.last_not_of("45") == 3u);
1746 CHECK(s012345.last_not_of("54") == 3u);
1747 CHECK(s012345.last_not_of("345") == 2u);
1748 CHECK(s012345.last_not_of("543") == 2u);
1749 CHECK(s012345.last_not_of("2345") == 1u);
1750 CHECK(s012345.last_not_of("5432") == 1u);
1751 CHECK(s012345.last_not_of("12345") == 0u);
1752 CHECK(s012345.last_not_of("54321") == 0u);
1753 CHECK(s012345.last_not_of("012345") == ryml::npos);
1754 CHECK(s012345.last_not_of("543210") == ryml::npos);
1755 CHECK(s012345.last_not_of('0') == 5u);
1756 CHECK(s012345.last_not_of("0") == 5u);
1757 CHECK(s012345.last_not_of("01") == 5u);
1758 CHECK(s012345.last_not_of("10") == 5u);
1759 CHECK(s012345.last_not_of("012") == 5u);
1760 CHECK(s012345.last_not_of("210") == 5u);
1761 CHECK(s012345.last_not_of("0123") == 5u);
1762 CHECK(s012345.last_not_of("3210") == 5u);
1763 CHECK(s012345.last_not_of("01234") == 5u);
1764 CHECK(s012345.last_not_of("43210") == 5u);
1765 CHECK(s012345.last_not_of("012345") == ryml::npos);
1766 CHECK(s012345.last_not_of("543210") == ryml::npos);
1767 }
1768
1769 // first_non_empty_span()
1770 {
1771 CHECK(ryml::csubstr("foo bar").first_non_empty_span() == "foo");
1772 CHECK(ryml::csubstr(" foo bar").first_non_empty_span() == "foo");
1773 CHECK(ryml::csubstr("\n \r \t foo bar").first_non_empty_span() == "foo");
1774 CHECK(ryml::csubstr("\n \r \t foo\n\r\t bar").first_non_empty_span() == "foo");
1775 CHECK(ryml::csubstr("\n \r \t foo\n\r\t bar").first_non_empty_span() == "foo");
1776 CHECK(ryml::csubstr(",\n \r \t foo\n\r\t bar").first_non_empty_span() == ",");
1777 }
1778 // first_uint_span()
1779 {
1780 CHECK(ryml::csubstr("1234 asdkjh").first_uint_span() == "1234");
1781 CHECK(ryml::csubstr("1234\rasdkjh").first_uint_span() == "1234");
1782 CHECK(ryml::csubstr("1234\tasdkjh").first_uint_span() == "1234");
1783 CHECK(ryml::csubstr("1234\nasdkjh").first_uint_span() == "1234");
1784 CHECK(ryml::csubstr("1234]asdkjh").first_uint_span() == "1234");
1785 CHECK(ryml::csubstr("1234)asdkjh").first_uint_span() == "1234");
1786 CHECK(ryml::csubstr("1234gasdkjh").first_uint_span() == "");
1787 }
1788 // first_int_span()
1789 {
1790 CHECK(ryml::csubstr("-1234 asdkjh").first_int_span() == "-1234");
1791 CHECK(ryml::csubstr("-1234\rasdkjh").first_int_span() == "-1234");
1792 CHECK(ryml::csubstr("-1234\tasdkjh").first_int_span() == "-1234");
1793 CHECK(ryml::csubstr("-1234\nasdkjh").first_int_span() == "-1234");
1794 CHECK(ryml::csubstr("-1234]asdkjh").first_int_span() == "-1234");
1795 CHECK(ryml::csubstr("-1234)asdkjh").first_int_span() == "-1234");
1796 CHECK(ryml::csubstr("-1234gasdkjh").first_int_span() == "");
1797 }
1798 // first_real_span()
1799 {
1800 CHECK(ryml::csubstr("-1234 asdkjh").first_real_span() == "-1234");
1801 CHECK(ryml::csubstr("-1234\rasdkjh").first_real_span() == "-1234");
1802 CHECK(ryml::csubstr("-1234\tasdkjh").first_real_span() == "-1234");
1803 CHECK(ryml::csubstr("-1234\nasdkjh").first_real_span() == "-1234");
1804 CHECK(ryml::csubstr("-1234]asdkjh").first_real_span() == "-1234");
1805 CHECK(ryml::csubstr("-1234)asdkjh").first_real_span() == "-1234");
1806 CHECK(ryml::csubstr("-1234gasdkjh").first_real_span() == "");
1807 CHECK(ryml::csubstr("1.234 asdkjh").first_real_span() == "1.234");
1808 CHECK(ryml::csubstr("1.234e+5 asdkjh").first_real_span() == "1.234e+5");
1809 CHECK(ryml::csubstr("1.234e-5 asdkjh").first_real_span() == "1.234e-5");
1810 CHECK(ryml::csubstr("1.234 asdkjh").first_real_span() == "1.234");
1811 CHECK(ryml::csubstr("1.234e+5 asdkjh").first_real_span() == "1.234e+5");
1812 CHECK(ryml::csubstr("1.234e-5 asdkjh").first_real_span() == "1.234e-5");
1813 CHECK(ryml::csubstr("-1.234 asdkjh").first_real_span() == "-1.234");
1814 CHECK(ryml::csubstr("-1.234e+5 asdkjh").first_real_span() == "-1.234e+5");
1815 CHECK(ryml::csubstr("-1.234e-5 asdkjh").first_real_span() == "-1.234e-5");
1816 // hexadecimal real numbers
1817 CHECK(ryml::csubstr("0x1.e8480p+19 asdkjh").first_real_span() == "0x1.e8480p+19");
1818 CHECK(ryml::csubstr("0x1.e8480p-19 asdkjh").first_real_span() == "0x1.e8480p-19");
1819 CHECK(ryml::csubstr("-0x1.e8480p+19 asdkjh").first_real_span() == "-0x1.e8480p+19");
1820 CHECK(ryml::csubstr("-0x1.e8480p-19 asdkjh").first_real_span() == "-0x1.e8480p-19");
1821 CHECK(ryml::csubstr("+0x1.e8480p+19 asdkjh").first_real_span() == "+0x1.e8480p+19");
1822 CHECK(ryml::csubstr("+0x1.e8480p-19 asdkjh").first_real_span() == "+0x1.e8480p-19");
1823 // binary real numbers
1824 CHECK(ryml::csubstr("0b101.011p+19 asdkjh").first_real_span() == "0b101.011p+19");
1825 CHECK(ryml::csubstr("0b101.011p-19 asdkjh").first_real_span() == "0b101.011p-19");
1826 CHECK(ryml::csubstr("-0b101.011p+19 asdkjh").first_real_span() == "-0b101.011p+19");
1827 CHECK(ryml::csubstr("-0b101.011p-19 asdkjh").first_real_span() == "-0b101.011p-19");
1828 CHECK(ryml::csubstr("+0b101.011p+19 asdkjh").first_real_span() == "+0b101.011p+19");
1829 CHECK(ryml::csubstr("+0b101.011p-19 asdkjh").first_real_span() == "+0b101.011p-19");
1830 // octal real numbers
1831 CHECK(ryml::csubstr("0o173.045p+19 asdkjh").first_real_span() == "0o173.045p+19");
1832 CHECK(ryml::csubstr("0o173.045p-19 asdkjh").first_real_span() == "0o173.045p-19");
1833 CHECK(ryml::csubstr("-0o173.045p+19 asdkjh").first_real_span() == "-0o173.045p+19");
1834 CHECK(ryml::csubstr("-0o173.045p-19 asdkjh").first_real_span() == "-0o173.045p-19");
1835 CHECK(ryml::csubstr("+0o173.045p+19 asdkjh").first_real_span() == "+0o173.045p+19");
1836 CHECK(ryml::csubstr("+0o173.045p-19 asdkjh").first_real_span() == "+0o173.045p-19");
1837 }
1838 // see also is_number()
1839
1840 // basename(), dirname(), extshort(), extlong()
1841 {
1842 CHECK(ryml::csubstr("/path/to/file.tar.gz").basename() == "file.tar.gz");
1843 CHECK(ryml::csubstr("/path/to/file.tar.gz").dirname() == "/path/to/");
1844 CHECK(ryml::csubstr("C:\\path\\to\\file.tar.gz").basename('\\') == "file.tar.gz");
1845 CHECK(ryml::csubstr("C:\\path\\to\\file.tar.gz").dirname('\\') == "C:\\path\\to\\");
1846 CHECK(ryml::csubstr("/path/to/file.tar.gz").extshort() == "gz");
1847 CHECK(ryml::csubstr("/path/to/file.tar.gz").extlong() == "tar.gz");
1848 CHECK(ryml::csubstr("/path/to/file.tar.gz").name_wo_extshort() == "/path/to/file.tar");
1849 CHECK(ryml::csubstr("/path/to/file.tar.gz").name_wo_extlong() == "/path/to/file");
1850 }
1851
1852 // split()
1853 {
1854 using namespace ryml;
1855 csubstr parts[] = {"aa", "bb", "cc", "dd", "ee", "ff"};
1856 {
1857 size_t count = 0;
1858 for(csubstr part : csubstr("aa/bb/cc/dd/ee/ff").split('/'))
1859 CHECK(part == parts[count++]);
1860 CHECK(count == 6u);
1861 }
1862 {
1863 size_t count = 0;
1864 for(csubstr part : csubstr("aa.bb.cc.dd.ee.ff").split('.'))
1865 CHECK(part == parts[count++]);
1866 CHECK(count == 6u);
1867 }
1868 {
1869 size_t count = 0;
1870 for(csubstr part : csubstr("aa-bb-cc-dd-ee-ff").split('-'))
1871 CHECK(part == parts[count++]);
1872 CHECK(count == 6u);
1873 }
1874 // see also next_split()
1875 }
1876
1877 // pop_left(), pop_right() --- non-greedy version
1878 // gpop_left(), gpop_right() --- greedy version
1879 {
1880 const bool skip_empty = true;
1881 // pop_left(): pop the last element from the left
1882 CHECK(ryml::csubstr( "0/1/2" ). pop_left('/' ) == "0" );
1883 CHECK(ryml::csubstr( "/0/1/2" ). pop_left('/' ) == "" );
1884 CHECK(ryml::csubstr("//0/1/2" ). pop_left('/' ) == "" );
1885 CHECK(ryml::csubstr( "0/1/2" ). pop_left('/', skip_empty) == "0" );
1886 CHECK(ryml::csubstr( "/0/1/2" ). pop_left('/', skip_empty) == "/0" );
1887 CHECK(ryml::csubstr("//0/1/2" ). pop_left('/', skip_empty) == "//0" );
1888 // gpop_left(): pop all but the first element (greedy pop)
1889 CHECK(ryml::csubstr( "0/1/2" ).gpop_left('/' ) == "0/1" );
1890 CHECK(ryml::csubstr( "/0/1/2" ).gpop_left('/' ) == "/0/1" );
1891 CHECK(ryml::csubstr("//0/1/2" ).gpop_left('/' ) == "//0/1" );
1892 CHECK(ryml::csubstr( "0/1/2/" ).gpop_left('/' ) == "0/1/2");
1893 CHECK(ryml::csubstr( "/0/1/2/" ).gpop_left('/' ) == "/0/1/2");
1894 CHECK(ryml::csubstr("//0/1/2/" ).gpop_left('/' ) == "//0/1/2");
1895 CHECK(ryml::csubstr( "0/1/2//" ).gpop_left('/' ) == "0/1/2/");
1896 CHECK(ryml::csubstr( "/0/1/2//" ).gpop_left('/' ) == "/0/1/2/");
1897 CHECK(ryml::csubstr("//0/1/2//" ).gpop_left('/' ) == "//0/1/2/");
1898 CHECK(ryml::csubstr( "0/1/2" ).gpop_left('/', skip_empty) == "0/1" );
1899 CHECK(ryml::csubstr( "/0/1/2" ).gpop_left('/', skip_empty) == "/0/1" );
1900 CHECK(ryml::csubstr("//0/1/2" ).gpop_left('/', skip_empty) == "//0/1" );
1901 CHECK(ryml::csubstr( "0/1/2/" ).gpop_left('/', skip_empty) == "0/1" );
1902 CHECK(ryml::csubstr( "/0/1/2/" ).gpop_left('/', skip_empty) == "/0/1" );
1903 CHECK(ryml::csubstr("//0/1/2/" ).gpop_left('/', skip_empty) == "//0/1" );
1904 CHECK(ryml::csubstr( "0/1/2//" ).gpop_left('/', skip_empty) == "0/1" );
1905 CHECK(ryml::csubstr( "/0/1/2//" ).gpop_left('/', skip_empty) == "/0/1" );
1906 CHECK(ryml::csubstr("//0/1/2//" ).gpop_left('/', skip_empty) == "//0/1" );
1907 // pop_right(): pop the last element from the right
1908 CHECK(ryml::csubstr( "0/1/2" ). pop_right('/' ) == "2" );
1909 CHECK(ryml::csubstr( "0/1/2/" ). pop_right('/' ) == "" );
1910 CHECK(ryml::csubstr( "0/1/2//" ). pop_right('/' ) == "" );
1911 CHECK(ryml::csubstr( "0/1/2" ). pop_right('/', skip_empty) == "2" );
1912 CHECK(ryml::csubstr( "0/1/2/" ). pop_right('/', skip_empty) == "2/" );
1913 CHECK(ryml::csubstr( "0/1/2//" ). pop_right('/', skip_empty) == "2//" );
1914 // gpop_right(): pop all but the first element (greedy pop)
1915 CHECK(ryml::csubstr( "0/1/2" ).gpop_right('/' ) == "1/2" );
1916 CHECK(ryml::csubstr( "0/1/2/" ).gpop_right('/' ) == "1/2/" );
1917 CHECK(ryml::csubstr( "0/1/2//" ).gpop_right('/' ) == "1/2//");
1918 CHECK(ryml::csubstr( "/0/1/2" ).gpop_right('/' ) == "0/1/2" );
1919 CHECK(ryml::csubstr( "/0/1/2/" ).gpop_right('/' ) == "0/1/2/" );
1920 CHECK(ryml::csubstr( "/0/1/2//" ).gpop_right('/' ) == "0/1/2//");
1921 CHECK(ryml::csubstr("//0/1/2" ).gpop_right('/' ) == "/0/1/2" );
1922 CHECK(ryml::csubstr("//0/1/2/" ).gpop_right('/' ) == "/0/1/2/" );
1923 CHECK(ryml::csubstr("//0/1/2//" ).gpop_right('/' ) == "/0/1/2//");
1924 CHECK(ryml::csubstr( "0/1/2" ).gpop_right('/', skip_empty) == "1/2" );
1925 CHECK(ryml::csubstr( "0/1/2/" ).gpop_right('/', skip_empty) == "1/2/" );
1926 CHECK(ryml::csubstr( "0/1/2//" ).gpop_right('/', skip_empty) == "1/2//");
1927 CHECK(ryml::csubstr( "/0/1/2" ).gpop_right('/', skip_empty) == "1/2" );
1928 CHECK(ryml::csubstr( "/0/1/2/" ).gpop_right('/', skip_empty) == "1/2/" );
1929 CHECK(ryml::csubstr( "/0/1/2//" ).gpop_right('/', skip_empty) == "1/2//");
1930 CHECK(ryml::csubstr("//0/1/2" ).gpop_right('/', skip_empty) == "1/2" );
1931 CHECK(ryml::csubstr("//0/1/2/" ).gpop_right('/', skip_empty) == "1/2/" );
1932 CHECK(ryml::csubstr("//0/1/2//" ).gpop_right('/', skip_empty) == "1/2//");
1933 }
1934}
#define CHECK(predicate)
a testing assertion, used only in this quickstart
substr to_substr(char(&s)[N]) noexcept
Definition substr.hpp:2376
csubstr to_csubstr(const char(&s)[N]) noexcept
Definition substr.hpp:2380
basic_substring< char > substr
a mutable string view
Definition substr.hpp:2355
basic_substring< const char > csubstr
an immutable string view
Definition substr.hpp:2356
@ npos
a null string position
Definition common.hpp:138
Definition ryml.hpp:6
bool begins_with_any(ro_substr chars) const noexcept
true if the first character of the string is any of the given chars
Definition substr.hpp:883
basic_substring trim(const C c) const
trim the character c left and right
Definition substr.hpp:677
size_t count(const C c, size_t pos=0) const
count the number of occurrences of c
Definition substr.hpp:744
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
Definition substr.hpp:2209
basic_substring range(size_t first, size_t last=npos) const noexcept
return [first,last[.
Definition substr.hpp:519
size_t first_not_of(const C c) const
Definition substr.hpp:993
auto tolower() -> typename std::enable_if< !std::is_const< U >::value, void >::type
convert the string to lower-case
Definition substr.hpp:2139
bool begins_with(const C c) const noexcept
true if the first character of the string is c
Definition substr.hpp:850
basic_substring triml(const C c) const
trim left
Definition substr.hpp:629
size_t last_of(const C c, size_t start=npos) const
Definition substr.hpp:946
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...
Definition substr.hpp:547
auto fill(C val) -> typename std::enable_if< !std::is_const< U >::value, void >::type
fill the entire contents with the given val
Definition substr.hpp:2153
size_t len
the length of the substring
Definition substr.hpp:218
basic_substring last(size_t num) const noexcept
return the last num elements: [len-num,len[
Definition substr.hpp:536
bool ends_with(const C c) const noexcept
true if the last character of the string is c
Definition substr.hpp:894
size_t first_of(const C c, size_t start=0) const
Definition substr.hpp:934
basic_substring stripl(ro_substr pattern) const
remove a pattern from the left
Definition substr.hpp:690
size_t find(const C c, size_t start_pos=0) const
Definition substr.hpp:713
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
Definition substr.hpp:2272
basic_substring stripr(ro_substr pattern) const
remove a pattern from the right
Definition substr.hpp:699
size_t size() const noexcept
Definition substr.hpp:358
bool overlaps(ro_substr const that) const noexcept
true if there is overlap of at least one element between that and *this
Definition substr.hpp:493
basic_substring first(size_t num) const noexcept
return the first num elements: [0,num[
Definition substr.hpp:529
basic_substring left_of(size_t pos) const noexcept
return [0, pos[ .
Definition substr.hpp:556
basic_substring sub(size_t first) const noexcept
return [first,len[
Definition substr.hpp:502
C * data() noexcept
Definition substr.hpp:366
bool ends_with_any(ro_substr chars) const noexcept
true if the last character of the string is any of the given chars
Definition substr.hpp:922
C & back() noexcept
Definition substr.hpp:375
basic_substring trimr(const C c) const
trim the character c from the right
Definition substr.hpp:653
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
Definition substr.hpp:2221
bool is_super(ro_substr const that) const noexcept
true if that is a substring of *this (ie, from the same buffer)
Definition substr.hpp:484
size_t last_not_of(const C c) const
Definition substr.hpp:1014
auto toupper() -> typename std::enable_if< ! std::is_const< U >::value, void >::type
convert the string to upper-case
Definition substr.hpp:2127
C * str
a restricted pointer to the first character of the substring
Definition substr.hpp:216
basic_substring right_of(size_t pos) const noexcept
return [pos+1, len[
Definition substr.hpp:574
bool is_sub(ro_substr const that) const noexcept
true if *this is a substring of that (ie, from the same buffer)
Definition substr.hpp:478
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
Definition substr.hpp:772
auto reverse() -> typename std::enable_if< !std::is_const< U >::value, void >::type
reverse in place
Definition substr.hpp:2199

Referenced by main().