rapidyaml 0.15.2
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 1144 of file quickstart.cpp.

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