diff --git a/.gitignore b/.gitignore index 259148f..4444e8b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,26 +7,13 @@ *.o *.obj -# Precompiled Headers -*.gch -*.pch - -# Compiled Dynamic libraries -*.so -*.dylib -*.dll - -# Fortran module files -*.mod -*.smod - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib - # Executables *.exe *.out *.app + +# Visual Studio specifics +.vs +x64 +Debug +Release diff --git a/README.md b/README.md index edd5347..e584494 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,105 @@ -# cpp-strings +# Library cpp-strings + [![license](http://img.shields.io/github/license/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=lightblue)](https://github.com/schmouk/cpprandlib/license) [![Latest release](http://img.shields.io/github/release/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=success)](https://github.com/schmouk/cpprandlib/releases) [![code_coverage](https://img.shields.io/badge/code_coverage-100%25-success?style=plastic&labelColor=blueviolet)]() [![tests](https://img.shields.io/badge/tests-passing-success?style=plastic&labelColor=blueviolet)]() + +github repository: [https://github.com/schmouk/pythonic-cpp-strings](https://github.com/schmouk/pythonic-cpp-strings) + What if c++ strings where as easy to use as Python strings? + +Let's just use c++ strings as are Python ones, with same API or as similar API as possible. +Library **cpp-strings** is fully templated. Just download header file `cppstrings.h` and put it anywhere in your project. Notice: all of its stuff is declared and defined in namespace `pcs` - which stands for **P**ythonic **C**++ **S**trings. + +* The templated class `pcs::CppStringT<>` defines all constructors and methods that implement the equivalent of Python strings API. +* Class `pcs::CppString` specializes the templated class with `char` characters. +* Class `pcs::CppWString` specializes the templated class with `wchar_t` characters. + +**cpp-strings** is implemented with the currently most recent c++ standard available with gcc, clang and msvc c++ compilers, i.e. standard **c++20**. + +* directory `cpp-strings` contains the header file `cppstring.h`. +This is the header file to include in your projects. +* directory `cpp-strings-tests` contains the unit-tests file `cpp-strings-tests.cpp` +This file tests all the library stuff. It is a valuable code container with so many examples of use of the library, the classes, the methods and the functions it defines. + +The code has been developed using VS2022 IDE. As such, unitary tests have been coded using Microsoft Visual Studio Cpp Unit Test Framework. The related VS project is provided with this library. + +Notice: no clang, gcc or msvc specific declarations or goodies have been use to code library **cpp-strings**. It should then be compilable with any of these compilers. To be able to use it with your project, just ensure that the c++ standard used with you favorite compiler is **c++20**: +* options `-std=c++20` or `-std=c++latest` for clang and gcc (v. 10 and above), +or option `-std=c++2a` for clang and gcc (v. 9 and earlier); +* options `/std=c++20` or `/std=c++latest` for Visual Studio 2019 and later. + +If you want to run the unitary tests, well, use the last version of Visual Studio (i.e. VS 2022, by July 2025). The Community free version will truly be fine. +The vcproject associated with the unit tests in **cpp-strings** is already configured to use the option flag `/std:c++latest` since the implemented code uses a very few but very useful c++23 goodies. + + +--- +## License + + Library cpp-strings + "What if c++ strings where as easy to use as Python strings?" + + Copyright (C) 2023-2025 Philippe Schmouker + contact - ph (dot) schmouker (at) gmail (dot) com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + +--- +## Intro +The creation of this library has been started with the aim at easing the use of strings in c++. Other projects exist, even aiming also to implement a Python-like strings API, but the only ones we have found were either started but not completed, or were not implementing the whole Python API. + +So, we started to work on **Pythonic c++ strings**. Library **cpp-strings** is now ready. It fully implements the Python API (even with a c++ implementation of *slices*) and it is fully tested with *unitary tests*. + +The implementation of library **cpp-strings** is fully templated and is contained into a single header file: `cpp-strings/cppstrings.h`. To take a whole benefit of it, just add this header file to your project and include it in your own files. It very fastly compiles. That's all! + +Header file `cpp-strings/cppstrings.h` defines: +* templated class `template class pcs::CppStringT` which implements all the stuff about pythonic c++ strings. It inherits from c++ STL class `std::basic_string`, so it gets access to all c++ STL methods, functions and goodies about strings; +* this class is specialized by: `using pcs::CppString> = pcs::CppStringT` for pythonic c++ strings based on `char` characters; +* it is also specialized by: `using pcs::CppWString> = pcs::CppStringT` for pythonic c++ strings based on `wchar_t` characters. + +The unitary tests are provided in directory `cpp-strings-tests/`. File `cpp-strings-tests/cpp-strings-tests.cpp` contains the related code. Tests have been coded using VS2022 IDE and as such, are using the Microsoft Visual Studio Cpp Unit Test Framework. The related VS project can be found in the same directory. It is already configured to create code for Release as well as for Debug configurations, and for 32-bits or 64-bits platforms at your choice. +This `.cpp` file is a great place to see **cpp-strings** code in action. Each structure, class, method, litteral operator and function being unitary tested in here, you should find there many examples of its use for all **cpp-strings** stuff. + + +--- +## Latest Release - Release 1.0 (1.0.0.224) 2025/07 + +The coding of this project started by March 2023 and had been put in standby mode for some months - no time to work on it. The very first release is now availble (since July 2025), as **Release 1.0**. + +This release has been fully tested. Code coverage is 100%. + +Release 1.0 implements all Python strings API but one feature (see below). + +Python *slices* are implemented via c++ `operator()` as declared and defined in the templated class `pcs::CppStringT<>`. Python slices have next specific notation: `[start : stop : step]` and allow the running step by step through range [start, stop) (notice: stop is excluded from the range). Operator `(start, stop, step)` acts the same way while running through the content of pythonic c++ strings. A dedicated base class `Slice` is also provided and can be passed as argument to `operator()`. It is derived in many simpler slices classes, since Python slices may not define either `start`, `stop` or `step` which then get default values (resp. 0, *end-of-sequence*, and 1). + + +### Missing parts in Release 1.0 +Python strings are based on Unicode chars. This is currently not the case for pythonic c++ strings in **cpp-strings**. +Unicode encoding allows for a specific comparison mode on strings, the **casefold** mode. There, Unicode chars are transformed into their lower equivalent char in a standardized manner which is more "agressive" than the simpler lowering method `lower()`. Comparing strings without taking into account the case of their chars is then performed in a far more accurate manner. +This feature is currently NOT implemented in library **cpp-strings**. + +So up to now, if you want to compare pythonic c++ strings from **cpp-strings** on whatever the case is for each of their chars, compare them applying method `.lower()` to both strings. This will do the job for chars and for wchar_t also for a majority of languages (but might fail for very few signs of specific languages in this last case). + +Notice: dealing with Unicode chars and implementing method `casefold()` as it is the case in Python is planned for a next release of library **cpp-strings**. +N.B. "*planned for a next release*" does not imply that a fixed date is planned either. + + +--- +## Documentation + +The **cpp-strings** HTML documentation is available here: [html/index.html](html/index.html). + +It has then been produced with the great utility **doxygen** developed by Vicente Hernando (the doxygen Github repository can be accessed [here](https://github.com/doxygen/doxygen), and the utility can be downloaded from there: [https://www.doxygen.nl/download.html](https://www.doxygen.nl/download.html)). + +This is a short documentation of the library. For some of its part it is a copy of the Python original documentation on strings. For its other part it documents the c++ implementation of **cpp-strings**. + +And remember: to better understand how to use this pythonic c++ strings library, have a look also at [`cpp-strings-tests/cpp-strings-tests.cpp`](cpp-strings-tests/cpp-strings-tests.cpp) to see **cpp-strings** library code in action! diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp new file mode 100644 index 0000000..e0f3236 --- /dev/null +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -0,0 +1,5695 @@ +/** + Library cppstrings + "What if c++ strings where as easy to use as Python strings?" + Unit tests part of the library. + + Copyright (C) 2025 Philippe Schmouker + contact - ph (dot) schmouker (at) gmail (dot) com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "CppUnitTest.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +#include "cppstrings.h" + + +namespace cppstringstests +{ + + //===== PART 1 ============================================ + TEST_CLASS(cppstringstests_PART_1) + { + public: + + TEST_METHOD(_cs) + { + using namespace pcs; + using namespace pcs; + auto abcd = "abcD"_cs; + auto wabcd = L"abcD"_cs; + Assert::AreEqual(abcd.c_str(), pcs::CppString(abcd).c_str()); + Assert::AreEqual(wabcd.c_str(), pcs::CppWString(wabcd).c_str()); + } + + TEST_METHOD(is_alpha) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual((const bool)std::isalpha(ch), pcs::is_alpha(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual((const bool)std::iswalpha(ch), pcs::is_alpha(ch)); + } + + TEST_METHOD(is_ascii) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual(ch < 128, pcs::is_ascii(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual(int(ch) < 128, pcs::is_ascii(ch)); + } + + TEST_METHOD(is_decimal) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual((const bool)std::isdigit(ch), pcs::is_decimal(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual((const bool)std::iswdigit(ch), pcs::is_decimal(ch)); + } + + TEST_METHOD(is_id_continue) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual((const bool)std::isdigit(ch) || (const bool)std::isalpha(ch) || ch == '_', pcs::is_id_continue(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual((const bool)std::iswdigit(ch) || (const bool)std::iswalpha(ch) || ch == L'_', pcs::is_id_continue(ch)); + } + + TEST_METHOD(is_id_start) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual((const bool)std::isalpha(ch) || ch == '_', pcs::is_id_start(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual((const bool)std::iswalpha(ch) || ch == L'_', pcs::is_id_start(ch)); + } + + TEST_METHOD(is_lower) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual((const bool)std::islower(static_cast(ch)), pcs::is_lower(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual((const bool)std::iswlower(ch), pcs::is_lower(ch)); + } + + TEST_METHOD(is_printable) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual((const bool)std::isprint(static_cast(ch)), pcs::is_printable(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual((const bool)std::iswprint(ch), pcs::is_printable(ch)); + } + + TEST_METHOD(is_punctuation) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual((const bool)std::ispunct(static_cast(ch)), pcs::is_punctuation(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual((const bool)std::iswpunct(ch), pcs::is_punctuation(ch)); + } + + TEST_METHOD(is_space) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual((const bool)std::isspace(static_cast(ch)), pcs::is_space(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual((const bool)std::iswspace(ch), pcs::is_space(ch)); + } + + TEST_METHOD(is_upper) + { + for (int ch = 0; ch <= 255; ++ch) + Assert::AreEqual((const bool)std::isupper(static_cast(ch)), pcs::is_upper(char(ch))); + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) + Assert::AreEqual((const bool)std::iswupper(ch), pcs::is_upper(ch)); + } + + TEST_METHOD(swap_case) + { + for (int ch = 0; ch <= 255; ++ch) { + const char sw_ch = pcs::swap_case(static_cast(ch)); + if (std::islower(ch)) + Assert::IsTrue((const bool)std::isupper(static_cast(sw_ch))); + else if (std::isupper(ch)) + Assert::IsTrue((const bool)std::islower(static_cast(sw_ch)), std::format(L"ch {}, sw_ch {}", ch, sw_ch).c_str()); + else + Assert::AreEqual(sw_ch, static_cast(ch)); + } + + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) { + const wchar_t sw_ch = pcs::swap_case(ch); + if (std::islower(ch)) + Assert::IsTrue((const bool)std::isupper(sw_ch)); + else if (std::isupper(ch)) + Assert::IsTrue((const bool)std::islower(sw_ch), std::format(L"ch {}, sw_ch {}", ch, sw_ch).c_str()); + else + Assert::AreEqual(sw_ch, ch); + } + } + + TEST_METHOD(to_lower) + { + for (int ch = 0; ch <= 255; ++ch) { + const char l_ch = pcs::to_lower(static_cast(ch)); + if (std::isupper(ch)) + Assert::IsTrue(std::islower(l_ch)); + else + Assert::AreEqual(l_ch, static_cast(ch)); + } + + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) { + const wchar_t l_ch = pcs::to_lower(ch); + if (std::isupper(ch)) + Assert::IsTrue(std::iswlower(l_ch)); + else + Assert::AreEqual(l_ch, ch); + } + } + + TEST_METHOD(to_upper) + { + for (int ch = 0; ch <= 255; ++ch) { + const char l_ch = pcs::to_upper(static_cast(ch)); + if (std::islower(ch)) + Assert::IsTrue(std::isupper(l_ch)); + else + Assert::AreEqual(l_ch, static_cast(ch)); + } + + for (wchar_t ch = 0; ch < L'\uffff'; ++ch) { + const wchar_t l_ch = pcs::to_upper(ch); + if (std::islower(ch)) + Assert::IsTrue(std::iswupper(l_ch)); + else + Assert::AreEqual(l_ch, ch); + } + } + }; + + + //===== PART 2 ============================================ + TEST_CLASS(cppstringstests_PART_2) + { + public: + + TEST_METHOD(constructor_01) + { + using namespace pcs; + std::map table{ {'a', "b"_cs}, {'b', "a"_cs} }; + Assert::AreEqual("b"_cs.c_str(), table['a'].c_str()); + Assert::AreEqual("a"_cs.c_str(), table['b'].c_str()); + + std::map wtable{ {L'a', L"b"_cs}, {L'b', L"a"_cs} }; + Assert::AreEqual(L"b"_cs.c_str(), wtable['a'].c_str()); + Assert::AreEqual(L"a"_cs.c_str(), wtable['b'].c_str()); + } + + TEST_METHOD(constructor_02) + { + pcs::CppString keys("abcdE"); + pcs::CppString values("ABCDe"); + pcs::CppString::TransTable t(keys, values); + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString('D').c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString('e').c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wt(pcs::CppWString(L"abcdE"), pcs::CppWString(L"ABCDe")); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString(L'D').c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString(L'e').c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_03) + { + pcs::CppString::TransTable t(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wt(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_04) + { + pcs::CppString::TransTable t(pcs::CppString("abc"), { pcs::CppString("AA"), pcs::CppString("BBB"), pcs::CppString("C") }); + Assert::AreEqual(pcs::CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString('z').c_str(), t['z'].c_str()); + + pcs::CppWString::TransTable wt(pcs::CppWString(L"abc"), { pcs::CppWString(L"AA"), pcs::CppWString(L"BBB"), pcs::CppWString(L"C") }); + Assert::AreEqual(pcs::CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L"C").c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString(L'9').c_str(), wt[L'9'].c_str()); + } + + TEST_METHOD(constructor_05) + { + using namespace pcs; + pcs::CppString::TransTable t(pcs::CppString("abc"), { pcs::CppString("AA"), pcs::CppString("BBB"), pcs::CppString("C") }, "dE"_cs); + Assert::AreEqual(pcs::CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('z').c_str(), t['z'].c_str()); + + pcs::CppWString::TransTable wt(pcs::CppWString(L"abc"), { pcs::CppWString(L"AA"), pcs::CppWString(L"BBB"), pcs::CppWString(L"C") }, L"dE"_cs); + Assert::AreEqual(pcs::CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L"C").c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'e').c_str(), wt[L'e'].c_str()); + } + + TEST_METHOD(constructor_06) + { + pcs::CppString::TransTable t("abC", "ABc"); + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(pcs::CppString('c').c_str(), t['c'].c_str()); + + pcs::CppWString::TransTable wt(L"abC", L"ABc"); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(pcs::CppWString(L'c').c_str(), wt[L'c'].c_str()); + } + + TEST_METHOD(constructor_07) + { + pcs::CppString::TransTable t("abc", "ABC", "dE"); + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('e').c_str(), t['e'].c_str()); + + pcs::CppWString::TransTable wt(L"abc", L"ABC", L"dE"); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'A'].c_str()); + } + + TEST_METHOD(constructor_08) + { + std::string keys("abC"); + std::vector values{ "AA", "BBB", "c" }; + pcs::CppString::TransTable t(keys.begin(), keys.end(), values.begin(), values.end()); + Assert::AreEqual(pcs::CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(pcs::CppString('c').c_str(), t['c'].c_str()); + + std::wstring wkeys(L"abC"); + std::vector wvalues{ L"AA", L"BBB", L"c" }; + pcs::CppWString::TransTable wt(wkeys.begin(), wkeys.end(), wvalues.begin(), wvalues.end()); + Assert::AreEqual(pcs::CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(pcs::CppWString(L'c').c_str(), wt[L'c'].c_str()); + } + + TEST_METHOD(constructor_09) + { + std::string keys("abC"); + std::vector values{ "AA", "BBB", "c" }; + std::string not_translated("dE"); + pcs::CppString::TransTable t(keys.begin(), keys.end(), values.begin(), values.end(), not_translated.cbegin(), not_translated.cend()); + Assert::AreEqual(pcs::CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('c').c_str(), t['c'].c_str()); + + std::wstring wkeys(L"abC"); + std::vector wvalues{ L"AA", L"BBB", L"c" }; + std::wstring wnot_translated(L"dE"); + pcs::CppWString::TransTable wt(wkeys.begin(), wkeys.end(), wvalues.begin(), wvalues.end(), wnot_translated.cbegin(), wnot_translated.cend()); + Assert::AreEqual(pcs::CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'c').c_str(), wt[L'c'].c_str()); + } + + TEST_METHOD(constructor_empty) + { + pcs::CppString::TransTable t; + Assert::IsTrue(t.get_table().empty()); + + pcs::CppWString::TransTable wt; + Assert::IsTrue(wt.get_table().empty()); + } + + TEST_METHOD(constructor_copy) + { + pcs::CppString::TransTable ct(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); + pcs::CppString::TransTable t(ct); + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); + pcs::CppWString::TransTable wt(wct); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_move) + { + pcs::CppString::TransTable mt(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); + pcs::CppString::TransTable t(std::move(mt)); + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wmt(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); + pcs::CppWString::TransTable wt(std::move(wmt)); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(assign_copy) + { + pcs::CppString::TransTable ct(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); + pcs::CppString::TransTable t = ct; + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); + pcs::CppWString::TransTable wt = wct; + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(assign_move) + { + pcs::CppString::TransTable mt(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); + pcs::CppString::TransTable t = std::move(mt); + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wmt(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); + pcs::CppWString::TransTable wt = std::move(wmt); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(assign_map) + { + pcs::CppString::TransTable ct(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); + pcs::CppString::TransTable t = ct.get_table(); + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); + pcs::CppWString::TransTable wt = wct.get_table(); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(indexing) + { + pcs::CppString::TransTable t(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); + Assert::AreEqual(pcs::CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(pcs::CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(pcs::CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(pcs::CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(pcs::CppString(',').c_str(), t[','].c_str()); + + pcs::CppWString::TransTable wt(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); + Assert::AreEqual(pcs::CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(pcs::CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(pcs::CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(pcs::CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(pcs::CppWString(L'\n').c_str(), wt[L'\n'].c_str()); + } + }; + + + //===== PART 3 ============================================ + TEST_CLASS(cppstringstests_PART_3) + { + public: + + TEST_METHOD(constructor_empty) + { + pcs::CppString s; + Assert::IsTrue(s.empty()); + + pcs::CppWString ws; + Assert::IsTrue(ws.empty()); + } + + TEST_METHOD(constructor_copy) + { + pcs::CppString cs("ABCde"); + pcs::CppString s(cs); + Assert::AreEqual(cs.c_str(), s.c_str()); + + pcs::CppWString wcs(L"abcDE"); + pcs::CppWString ws(wcs); + Assert::AreEqual(wcs.c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_move) + { + pcs::CppString cs("ABCde"); + pcs::CppString s(std::move(cs)); + Assert::AreEqual(pcs::CppString("ABCde").c_str(), s.c_str()); + + pcs::CppWString wcs(L"abcDE"); + pcs::CppWString ws(std::move(wcs)); + Assert::AreEqual(pcs::CppWString(L"abcDE").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_06) + { + pcs::CppString s(10, '-'); + Assert::AreEqual(std::size_t(10), s.size()); + Assert::AreEqual(pcs::CppString("----------").c_str(), s.c_str()); + + pcs::CppWString ws(8, '='); + Assert::AreEqual(std::size_t(8), ws.size()); + Assert::AreEqual(pcs::CppWString(L"========").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_07) + { + pcs::CppString cs("abcDEfgh"); + pcs::CppString s(cs, 3); + Assert::AreEqual(std::size_t(5), s.size()); + Assert::AreEqual(pcs::CppString("DEfgh").c_str(), s.c_str()); + + pcs::CppWString wcs(L"ABCdefGH"); + pcs::CppWString ws(wcs, 4); + Assert::AreEqual(std::size_t(4), ws.size()); + Assert::AreEqual(pcs::CppWString(L"efGH").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_08) + { + pcs::CppString cs("abcDEfgh"); + pcs::CppString s(cs, 3, 2); + Assert::AreEqual(std::size_t(2), s.size()); + Assert::AreEqual(pcs::CppString("DE").c_str(), s.c_str()); + + pcs::CppWString wcs(L"ABCdefGH"); + pcs::CppWString ws(wcs, 4, 6); + Assert::AreEqual(std::size_t(4), ws.size()); + Assert::AreEqual(pcs::CppWString(L"efGH").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_09) + { + pcs::CppString s("abcDEfgh"); + Assert::AreEqual(std::size_t(8), s.size()); + Assert::AreEqual(pcs::CppString("abcDEfgh").c_str(), s.c_str()); + + pcs::CppWString ws(L"ABCdefGH"); + Assert::AreEqual(std::size_t(8), ws.size()); + Assert::AreEqual(pcs::CppWString(L"ABCdefGH").c_str(), ws.c_str()); + + pcs::CppString s0(nullptr); + Assert::AreEqual(std::size_t(0), s0.size()); + Assert::AreEqual("", s0.c_str()); + + pcs::CppWString ws0(nullptr); + Assert::AreEqual(std::size_t(0), ws0.size()); + Assert::AreEqual(L"", ws0.c_str()); + } + + TEST_METHOD(constructor_10) + { + pcs::CppString s("abcDEfgh", 5); + Assert::AreEqual(std::size_t(5), s.size()); + Assert::AreEqual(pcs::CppString("abcDE").c_str(), s.c_str()); + + pcs::CppWString ws(L"ABCdefGH", 7); + Assert::AreEqual(std::size_t(7), ws.size()); + Assert::AreEqual(pcs::CppWString(L"ABCdefG").c_str(), ws.c_str()); + + pcs::CppString s0(nullptr, 0); + Assert::AreEqual(std::size_t(0), s0.size()); + Assert::AreEqual("", s0.c_str()); + + pcs::CppWString ws0(nullptr, 7); + Assert::AreEqual(std::size_t(7), ws0.size()); + Assert::AreEqual(L"", ws0.c_str()); + } + + TEST_METHOD(constructor_11) + { + pcs::CppString s({ 'a', 'b', 'c', 'D' }); + Assert::AreEqual(std::size_t(4), s.size()); + Assert::AreEqual(pcs::CppString("abcD").c_str(), s.c_str()); + + pcs::CppWString ws({ L'A', L'B', L'C', L'd', L'e' }); + Assert::AreEqual(std::size_t(5), ws.size()); + Assert::AreEqual(pcs::CppWString(L"ABCde").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_12) + { + std::string cs("abcDEfgh"); + pcs::CppString s(cs); + Assert::AreEqual(std::size_t(8), s.size()); + Assert::AreEqual(pcs::CppString("abcDEfgh").c_str(), s.c_str()); + + std::wstring wcs(L"ABCdefGH"); + pcs::CppWString ws(wcs); + Assert::AreEqual(std::size_t(8), ws.size()); + Assert::AreEqual(pcs::CppWString(L"ABCdefGH").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_13) + { + std::string cs("abcDEfgh"); + pcs::CppString s(cs, cs.get_allocator()); + Assert::AreEqual(std::size_t(8), s.size()); + Assert::AreEqual(pcs::CppString("abcDEfgh").c_str(), s.c_str()); + + std::wstring wcs(L"ABCdefGH"); + pcs::CppWString ws(wcs, wcs.get_allocator()); + Assert::AreEqual(std::size_t(8), ws.size()); + Assert::AreEqual(pcs::CppWString(L"ABCdefGH").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_14) + { + std::string cs("abcDEfgh"); + pcs::CppString s(std::move(cs)); + Assert::AreEqual(std::size_t(8), s.size()); + Assert::AreEqual(pcs::CppString("abcDEfgh").c_str(), s.c_str()); + + std::wstring wcs(L"ABCdefGH"); + pcs::CppWString ws(std::move(wcs)); + Assert::AreEqual(std::size_t(8), ws.size()); + Assert::AreEqual(pcs::CppWString(L"ABCdefGH").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_15) + { + std::string cs("abcDEfgh"); + pcs::CppString s(std::move(cs), cs.get_allocator()); + Assert::AreEqual(std::size_t(8), s.size()); + Assert::AreEqual(pcs::CppString("abcDEfgh").c_str(), s.c_str()); + + std::wstring wcs(L"ABCdefGH"); + pcs::CppWString ws(std::move(wcs), wcs.get_allocator()); + Assert::AreEqual(std::size_t(8), ws.size()); + Assert::AreEqual(pcs::CppWString(L"ABCdefGH").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_16) + { + std::string cs("abcDEfgh"); + pcs::CppString s(cs.cbegin(), cs.cend()); + Assert::AreEqual(std::size_t(8), s.size()); + Assert::AreEqual(pcs::CppString("abcDEfgh").c_str(), s.c_str()); + + std::wstring wcs(L"ABCdefGH"); + pcs::CppWString ws(wcs.begin(), wcs.end()); + Assert::AreEqual(std::size_t(8), ws.size()); + Assert::AreEqual(pcs::CppWString(L"ABCdefGH").c_str(), ws.c_str()); + } + + TEST_METHOD(constructor_19) + { + pcs::CppString s('z'); + Assert::AreEqual(std::size_t(1), s.size()); + Assert::AreEqual(pcs::CppString("z").c_str(), s.c_str()); + + pcs::CppWString ws(L'Z'); + Assert::AreEqual(std::size_t(1), ws.size()); + Assert::AreEqual(pcs::CppWString(L"Z").c_str(), ws.c_str()); + } + }; + + + //===== PART 4 ======================================== + TEST_CLASS(cppstringstests_PART_4) + { + public: + + TEST_METHOD(slice_iteration) + { + pcs::CppString txt("aBcDe"); + + { + pcs::Slice slc(0, 5, 1); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::Slice slc(0, 5UL, char(1)); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::Slice slc(0, 11); // Slice here defaults to Slice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::Slice slc(0, 3); // Slice here defaults to Slice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + } + + { + pcs::Slice slc(0); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + ; + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::Slice slc; + + long index{ slc.begin(txt) }; + Assert::AreEqual(long(0), index); + + long k{ 0 }; + for (long index = slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + + k = 0; + for (long index = slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + } + + { + pcs::Slice slc(-1, 0, -1); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(4LL, index); + + long long k{ (long long)txt.size() - 1 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0LL, *slc); + + k = txt.size() - 1; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0LL, *slc); + } + + { + pcs::Slice slc(-2, 1, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(3, index); + + int k{ int(txt.size()) - 2 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(1, *slc); + + k = int(txt.size()) - 2; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(1, *slc); + } + + { + pcs::Slice slc(-2, -3, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(3, index); + + int k{ int(txt.size()) - 2 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(2, *slc); + + k = int(txt.size()) - 2; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(2, *slc); + } + + { + pcs::Slice slc(-4, -2, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(1, index); + + int k{ int(txt.size()) - 4 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(1, *slc); + + k = int(txt.size()) - 4; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(1, *slc); + } + + { + pcs::Slice slc(-4, -2, 1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(1, index); + + int k{ int(txt.size()) - 4 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + + k = int(txt.size()) - 4; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + } + + { + pcs::Slice slc(5, -7, 0); + + int index{ slc.begin(txt) }; + Assert::AreEqual(5, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::Slice slc(5, -7, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(4, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::Slice slc(-11, 7, 1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + } + + TEST_METHOD(startslice_iteration) + { + pcs::CppString txt("aBcDe"); + + { + pcs::StartSlice slc; + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StartSlice slc(0); // Slice here defaults to Slice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StartSlice slc(-1); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(4LL, index); + + long long k{ (long long)txt.size() - 1 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = txt.size() - 1; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StartSlice slc(-2); + + int index{ slc.begin(txt) }; + Assert::AreEqual(3, index); + + int k{ int(txt.size()) - 2 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = int(txt.size()) - 2; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StartSlice slc(-4); + + int index{ slc.begin(txt) }; + Assert::AreEqual(1, index); + + int k{ int(txt.size()) - 4 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = int(txt.size()) - 4; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StartSlice slc(5); + + int index{ slc.begin(txt) }; + Assert::AreEqual(5, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5 , *slc); + } + + { + pcs::StartSlice slc(-11); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + } + + TEST_METHOD(startstepslice_iteration) + { + pcs::CppString txt("aBcDe"); + + { + pcs::StartStepSlice slc(0, 1); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StartStepSlice slc(0, char(1)); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StartStepSlice slc(0, 11); // StartStepSlice here defaults to StartStepSlice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, k += 11) + Assert::AreEqual(*slc, k); + Assert::AreEqual(11, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, k += 11) + Assert::AreEqual(*slc, k); + Assert::AreEqual(11, *slc); + } + + { + pcs::StartStepSlice slc(0, 3); // StartStepSlice here defaults to StartStepSlice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, k += 3) + Assert::AreEqual(*slc, k); + Assert::AreEqual(6, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, k += 3) + Assert::AreEqual(*slc, k); + Assert::AreEqual(6, *slc); + } + + { + pcs::StartStepSlice slc(0); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + ; + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StartStepSlice slc; + + long index{ slc.begin(txt) }; + Assert::AreEqual(long(0), index); + + long k{ 0 }; + for (long index = slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + + k = 0; + for (long index = slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + } + + { + pcs::StartStepSlice slc(-1, -1); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(4LL, index); + + long long k{ (long long)txt.size() - 1 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0LL, *slc); + + k = (long long)txt.size() - 1; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0LL, *slc); + } + + { + pcs::StartStepSlice slc(-2, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(3, index); + + int k{ int(txt.size()) - 2 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = int(txt.size()) - 2; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::StartStepSlice slc(-9, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ int(txt.size()) - 4 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = int(txt.size()) - 4; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::StartStepSlice slc(-4, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(1, index); + + int k{ int(txt.size()) - 4 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = int(txt.size()) - 4; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::StartStepSlice slc(-4, 1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(1, index); + + int k{ int(txt.size()) - 4 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = int(txt.size()) - 4; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StartStepSlice slc(5, -7); + + int index{ slc.begin(txt) }; + Assert::AreEqual(4, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, k -= 7) + Assert::AreEqual(*slc, k); + Assert::AreEqual(-3, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, k -= 7) + Assert::AreEqual(*slc, k); + Assert::AreEqual(-3, *slc); + } + + { + pcs::StartStepSlice slc(5, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(4, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::StartStepSlice slc(-11, 1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + } + + TEST_METHOD(startstopslice_iteration) + { + pcs::CppString txt("aBcDe"); + + { + pcs::StartStopSlice slc(0, 5); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StartStopSlice slc(0, 5UL); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StartStopSlice slc(0, 11); // StartStopSlice here defaults to StartStopSlice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StartStopSlice slc(0, 3); // StartStopSlice here defaults to StartStopSlice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + } + + { + pcs::StartStopSlice slc(0); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + ; + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StartStopSlice slc; + + long index{ slc.begin(txt) }; + Assert::AreEqual(long(0), index); + + long k{ 0 }; + for (long index = slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + + k = 0; + for (long index = slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + } + + { + pcs::StartStopSlice slc(-1, 0); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(4LL, index); + + long long k{ (long long)txt.size() - 1 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(4LL, *slc); + + k = txt.size() - 1; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(4LL, *slc); + } + + { + pcs::StartStopSlice slc(-2, 1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(3, index); + + int k{ int(txt.size()) - 2 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + + k = int(txt.size()) - 2; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + } + + { + pcs::StartStopSlice slc(-2, 3); + + int index{ slc.begin(txt) }; + Assert::AreEqual(3, index); + + int k{ int(txt.size()) - 2 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + + k = int(txt.size()) - 2; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + } + + { + pcs::StartStopSlice slc(-4, -2); + + int index{ slc.begin(txt) }; + Assert::AreEqual(1, index); + + int k{ int(txt.size()) - 4 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(int(txt.size() - 2), *slc); + + k = int(txt.size()) - 4; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(int(txt.size() - 2), *slc); + } + + { + pcs::StartStopSlice slc(5, -7); + + int index{ slc.begin(txt) }; + Assert::AreEqual(5, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StartStopSlice slc(-11, 7); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + } + + TEST_METHOD(stepslice_iteration) + { + pcs::CppString txt("aBcDe"); + + { + pcs::StepSlice slc; + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StepSlice slc(1); // StepSlice here defaults to StepSlice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StepSlice slc(3); // StepSlice here defaults to StepSlice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, k+=3) + Assert::AreEqual(*slc, k); + Assert::AreEqual(6, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, k+=3) + Assert::AreEqual(*slc, k); + Assert::AreEqual(6, *slc); + } + + { + pcs::StepSlice slc(0); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + ; + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::StepSlice slc; + + long index{ slc.begin(txt) }; + Assert::AreEqual(long(0), index); + + long k{ 0 }; + for (long index = slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + + k = 0; + for (long index = slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + } + + { + pcs::StepSlice slc(-1); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(4LL, index); + + long long k{ (long long)txt.size() - 1 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0LL, *slc); + + k = txt.size() - 1; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0LL, *slc); + } + + { + pcs::StepSlice slc(-2); + + int index{ slc.begin(txt) }; + Assert::AreEqual(4, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, k-=2) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, k-=2) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::StepSlice slc(-4); + + int index{ slc.begin(txt) }; + Assert::AreEqual(4, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, k-=4) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, k-=4) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::StepSlice slc(-11); + + int index{ slc.begin(txt) }; + Assert::AreEqual(4, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, k-=11) + Assert::AreEqual(*slc, k); + Assert::AreEqual(-7, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, k-=11) + Assert::AreEqual(*slc, k); + Assert::AreEqual(-7, *slc); + } + } + + TEST_METHOD(stopslice_iteration) + { + pcs::CppString txt("aBcDe"); + + { + pcs::StopSlice slc; + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StopSlice slc(7); // Slice here defaults to Slice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StopSlice slc(-1); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(4LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(4LL, *slc); + } + + { + pcs::StopSlice slc(-2); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + } + + { + pcs::StopSlice slc(-4); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(1, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(1, *slc); + } + + { + pcs::StopSlice slc(5); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StopSlice slc(-11); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + } + + TEST_METHOD(stopstepslice_iteration) + { + pcs::CppString txt("aBcDe"); + + { + pcs::StopStepSlice slc( 5, 1); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StopStepSlice slc(5UL, char(1)); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(0LL, index); + + long long k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5LL, *slc); + } + + { + pcs::StopStepSlice slc(11, 3); // StopStepSlice here defaults to StopStepSlice + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, k+=3) + Assert::AreEqual(*slc, k); + Assert::AreEqual(6, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, k+=3) + Assert::AreEqual(*slc, k); + Assert::AreEqual(6, *slc); + } + + { + pcs::StopStepSlice slc(3, 2); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, k+=2) + Assert::AreEqual(*slc, k); + Assert::AreEqual(4, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, k+=2) + Assert::AreEqual(*slc, k); + Assert::AreEqual(4, *slc); + } + + { + pcs::StopStepSlice slc(7); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + ; + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5, *slc); + } + + { + pcs::StopStepSlice slc; + + long index{ slc.begin(txt) }; + Assert::AreEqual(long(0), index); + + long k{ 0 }; + for (long index = slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + + k = 0; + for (long index = slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(5L, *slc); + } + + { + pcs::StopStepSlice slc(-1, -1); + + long long index{ slc.begin(txt) }; + Assert::AreEqual(4LL, index); + + long long k{ (long long)txt.size() - 1 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(4LL, *slc); + + k = txt.size() - 1; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(4LL, *slc); + } + + { + pcs::StopStepSlice slc(-2, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(4, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + } + + { + pcs::StopStepSlice slc(-4, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(4, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(1, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(1, *slc); + } + + { + pcs::StopStepSlice slc(-2, 1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(3, *slc); + } + + { + pcs::StopStepSlice slc(-7, 0); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, ++k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::StopStepSlice slc(-7, -1); + + int index{ slc.begin(txt) }; + Assert::AreEqual(4, index); + + int k{ 4 }; + for (slc.begin(txt); !slc.end(); slc++, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + + k = 4; + for (slc.begin(txt); !slc.end(); ++slc, --k) + Assert::AreEqual(*slc, k); + Assert::AreEqual(0, *slc); + } + + { + pcs::StopStepSlice slc(7, 2); + + int index{ slc.begin(txt) }; + Assert::AreEqual(0, index); + + int k{ 0 }; + for (slc.begin(txt); !slc.end(); slc++, k+=2) + Assert::AreEqual(*slc, k); + Assert::AreEqual(6, *slc); + + k = 0; + for (slc.begin(txt); !slc.end(); ++slc, k+=2) + Assert::AreEqual(*slc, k); + Assert::AreEqual(6, *slc); + } + + } + + }; + + + //===== PART 5 ======================================== + TEST_CLASS(cppstringstests_PART_5) + { + public: + + TEST_METHOD(capitalize) + { + pcs::CppString s("abc def GHi jKl 032, JHGF/"); + Assert::AreEqual(pcs::CppString("Abc def ghi jkl 032, jhgf/").c_str(), s.capitalize().c_str()); + + s = "capitalize Capitalize. CAPITALIZE"; + Assert::AreEqual(pcs::CppString("Capitalize capitalize. capitalize").c_str(), s.capitalize().c_str()); + + pcs::CppWString ws(L"123AHBl!"); + Assert::AreEqual(pcs::CppWString(L"123ahbl!").c_str(), ws.capitalize().c_str()); + } + + TEST_METHOD(center) + { + pcs::CppString s("zyxwvutsrqp"); + Assert::AreEqual(pcs::CppString(" zyxwvutsrqp ").c_str(), s.center(15).c_str(), L"--1--"); + Assert::AreEqual(pcs::CppString(" zyxwvutsrqp ").c_str(), s.center(14).c_str(), L"--2--"); + Assert::AreEqual(pcs::CppString(" zyxwvutsrqp ").c_str(), s.center(13).c_str(), L"--3--"); + Assert::AreEqual(pcs::CppString("zyxwvutsrqp ").c_str(), s.center(12).c_str(), L"--4--"); + Assert::AreEqual(pcs::CppString("zyxwvutsrqp").c_str(), s.center(11).c_str(), L"--5--"); + Assert::AreEqual(pcs::CppString("zyxwvutsrqp").c_str(), s.center(10).c_str(), L"--6--"); + + pcs::CppWString ws(L"zyxwvutsrqp"); + Assert::AreEqual(pcs::CppWString(L"##zyxwvutsrqp##").c_str(), ws.center(15, L'#').c_str(), L"--11--"); + Assert::AreEqual(pcs::CppWString(L"#zyxwvutsrqp##").c_str(), ws.center(14, L'#').c_str(), L"--12--"); + Assert::AreEqual(pcs::CppWString(L"#zyxwvutsrqp#").c_str(), ws.center(13, L'#').c_str(), L"--13--"); + Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp#").c_str(), ws.center(12, L'#').c_str(), L"--14--"); + Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp").c_str(), ws.center(11, L'#').c_str(), L"--15--"); + Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp").c_str(), ws.center(10, L'#').c_str(), L"--16--"); + } + + TEST_METHOD(contains) + { + using namespace pcs; + pcs::CppString text("Abcd. Efgh ij!"); + for (std::size_t index = 0; index < text.size(); ++index) { + Assert::IsTrue(text.contains(text.substr(index))); + for (std::size_t count = 0; count < text.size() - index; ++count) + Assert::IsTrue(text.contains(text.substr(index, count))); + } + Assert::IsFalse(text.contains("zzz"_cs)); + Assert::IsFalse(text.contains("abc"_cs)); + Assert::IsFalse(text.contains("Abcd. Efgh ij!!"_cs)); + Assert::IsTrue(text.contains(""_cs)); + + pcs::CppWString wtext(L"Abcd. Efgh ij!"); + for (std::size_t index = 0; index < wtext.size(); ++index) { + Assert::IsTrue(wtext.contains(wtext.substr(index))); + for (std::size_t count = 0; count < text.size() - index; ++count) + Assert::IsTrue(wtext.contains(wtext.substr(index, count))); + } + Assert::IsFalse(wtext.contains(L"zzz"_cs)); + Assert::IsFalse(wtext.contains(L"abc"_cs)); + Assert::IsFalse(wtext.contains(L"Abcd. Efgh ij!!"_cs)); + Assert::IsTrue(wtext.contains(L""_cs)); + + for (std::size_t index = 0; index < text.size(); ++index) { + Assert::IsTrue(text.contains(text.substr(index).c_str())); + for (std::size_t count = 0; count < text.size() - index; ++count) + Assert::IsTrue(text.contains(text.substr(index, count).c_str())); + } + Assert::IsFalse(text.contains("z")); + Assert::IsFalse(text.contains("a")); + Assert::IsFalse(text.contains("Abcd. Efgh ij!!")); + Assert::IsTrue(text.contains("")); + Assert::IsTrue(text.contains(nullptr)); + + for (std::size_t index = 0; index < wtext.size(); ++index) { + Assert::IsTrue(wtext.contains(wtext.substr(index).c_str())); + for (std::size_t count = 0; count < text.size() - index; ++count) + Assert::IsTrue(wtext.contains(wtext.substr(index, count).c_str())); + } + Assert::IsFalse(wtext.contains(L"zzz")); + Assert::IsFalse(wtext.contains(L"abc")); + Assert::IsFalse(wtext.contains(L"Abcd. Efgh ij!!")); + Assert::IsTrue(wtext.contains(L"")); + Assert::IsTrue(wtext.contains(nullptr)); + + for (auto const ch : text) + Assert::IsTrue(text.contains(ch)); + Assert::IsFalse(text.contains('z')); + Assert::IsFalse(text.contains('a')); + + for (auto const wch : wtext) + Assert::IsTrue(wtext.contains(wch)); + Assert::IsFalse(wtext.contains(L'z')); + Assert::IsFalse(wtext.contains(L'a')); + } + + TEST_METHOD(contains_n) + { + using namespace pcs; + pcs::CppString text("Abcd. Efgh ij!"); + for (std::size_t index = 0; index < text.size(); ++index) { + Assert::IsTrue(text.contains_n(text.substr(index), index)); + for (std::size_t count = 0; count < text.size() - index; ++count) { + Assert::IsTrue(text.contains_n(text.substr(index, count), index, count)); + Assert::IsTrue(text.contains_n(text.substr(index, count), index, count + 1)); + if (count > 0) + Assert::IsFalse(text.contains_n(text.substr(index, count), index, count - 1)); + } + } + Assert::IsFalse(text.contains_n("zzz"_cs, 0)); + Assert::IsFalse(text.contains_n("abc"_cs, 0)); + Assert::IsFalse(text.contains_n("Abcd. Efgh ij!!"_cs, 0)); + Assert::IsTrue(text.contains_n(""_cs, 6)); + Assert::IsFalse(text.contains_n(". Ef"_cs, 10, 4)); + Assert::IsFalse(text.contains_n(". Ef"_cs, 4, 3)); + + pcs::CppWString wtext(L"Abcd. Efgh ij!"); + for (std::size_t index = 0; index < wtext.size(); ++index) { + Assert::IsTrue(wtext.contains_n(wtext.substr(index), index)); + for (std::size_t count = 0; count < text.size() - index; ++count) { + Assert::IsTrue(wtext.contains_n(wtext.substr(index, count), index, count)); + Assert::IsTrue(wtext.contains_n(wtext.substr(index, count), index, count + 1)); + if (count > 0) + Assert::IsFalse(wtext.contains_n(wtext.substr(index, count), index, count - 1)); + } + } + Assert::IsFalse(wtext.contains_n(L"zzz"_cs, 0)); + Assert::IsFalse(wtext.contains_n(L"abc"_cs, 0)); + Assert::IsFalse(wtext.contains_n(L"Abcd. Efgh ij!!"_cs, 0)); + Assert::IsTrue(wtext.contains_n(L""_cs, 6)); + Assert::IsFalse(wtext.contains_n(L". Ef"_cs, 10, 4)); + Assert::IsFalse(wtext.contains_n(L". Ef"_cs, 4, 3)); + + for (std::size_t index = 0; index < text.size(); ++index) { + Assert::IsTrue(text.contains_n(text.substr(index), index)); + for (std::size_t count = 0; count < text.size() - index; ++count) { + Assert::IsTrue(text.contains_n(text.substr(index, count).c_str(), index, count)); + Assert::IsTrue(text.contains_n(text.substr(index, count).c_str(), index, count + 1)); + if (count > 0) + Assert::IsFalse(text.contains_n(text.substr(index, count).c_str(), index, count - 1)); + } + } + Assert::IsFalse(text.contains_n("z", 0)); + Assert::IsFalse(text.contains_n("a", 0)); + Assert::IsFalse(text.contains_n("Abcd. Efgh ij!!", 0)); + Assert::IsTrue(text.contains_n("", 6)); + Assert::IsTrue(text.contains_n(nullptr, 5)); + Assert::IsFalse(text.contains_n(". Ef", 10, 4)); + Assert::IsFalse(text.contains_n(". Ef", 4, 3)); + + for (std::size_t index = 0; index < text.size(); ++index) { + Assert::IsTrue(wtext.contains_n(wtext.substr(index), index)); + for (std::size_t count = 0; count < wtext.size() - index; ++count) { + Assert::IsTrue(wtext.contains_n(wtext.substr(index, count).c_str(), index, count)); + Assert::IsTrue(wtext.contains_n(wtext.substr(index, count).c_str(), index, count + 1)); + if (count > 0) + Assert::IsFalse(wtext.contains_n(wtext.substr(index, count).c_str(), index, count - 1)); + } + } + Assert::IsFalse(wtext.contains_n(L"z", 0)); + Assert::IsFalse(wtext.contains_n(L"a", 0)); + Assert::IsFalse(wtext.contains_n(L"Abcd. Efgh ij!!", 0)); + Assert::IsTrue(wtext.contains_n(L"", 6)); + Assert::IsTrue(wtext.contains_n(nullptr, 3)); + Assert::IsFalse(wtext.contains_n(L". Ef", 10, 4)); + Assert::IsFalse(wtext.contains_n(L". Ef", 4, 3)); + + for (auto const ch : text) + Assert::IsTrue(text.contains_n(ch, 0)); + Assert::IsFalse(text.contains_n('z', 0, 21)); + Assert::IsFalse(text.contains_n('a', 0)); + + for (auto const wch : wtext) + Assert::IsTrue(wtext.contains_n(wch, 0)); + Assert::IsFalse(wtext.contains_n(L'z', 0)); + Assert::IsFalse(wtext.contains_n(L'a', 0, 21)); + } + + TEST_METHOD(count) + { + pcs::CppString s("abcabcabcdefabca bca bcabca"); + Assert::AreEqual(pcs::CppString::size_type(3), s.count("abca")); + Assert::AreEqual(pcs::CppString::size_type(6), s.count("bca")); + Assert::AreEqual(pcs::CppString::size_type(0), s.count("A")); + Assert::AreEqual(pcs::CppString::size_type(2), s.count("abca", 4)); + Assert::AreEqual(pcs::CppString::size_type(5), s.count("bca", 2)); + Assert::AreEqual(pcs::CppString::size_type(0), s.count("A", 3)); + Assert::AreEqual(pcs::CppString::size_type(1), s.count("abca", 4, s.size() - 5)); + Assert::AreEqual(pcs::CppString::size_type(4), s.count("bca", 2, s.size() - 2)); + Assert::AreEqual(pcs::CppString::size_type(0), s.count("A", 3, s.size() + 4)); + + pcs::CppWString ws(L"abcabcabcdefabca bca bcabca"); + Assert::AreEqual(pcs::CppString::size_type(3), ws.count(L"abca")); + Assert::AreEqual(pcs::CppString::size_type(6), ws.count(L"bca")); + Assert::AreEqual(pcs::CppString::size_type(0), ws.count(L"A")); + Assert::AreEqual(pcs::CppString::size_type(2), ws.count(L"abca", 4)); + Assert::AreEqual(pcs::CppString::size_type(5), ws.count(L"bca", 2)); + Assert::AreEqual(pcs::CppString::size_type(0), ws.count(L"A", 3)); + Assert::AreEqual(pcs::CppString::size_type(1), ws.count(L"abca", 4, s.size() - 5)); + Assert::AreEqual(pcs::CppString::size_type(4), ws.count(L"bca", 2, s.size() - 2)); + Assert::AreEqual(pcs::CppString::size_type(0), ws.count(L"A", 3, s.size() + 4)); + } + + TEST_METHOD(count_n) + { + pcs::CppString s("abcabcabcdefabca bca bcabca"); + const pcs::CppString::size_type len{ s.size() }; + Assert::AreEqual(pcs::CppString::size_type(3), s.count_n("abca", 0, len)); + Assert::AreEqual(pcs::CppString::size_type(6), s.count_n("bca", 0, len)); + Assert::AreEqual(pcs::CppString::size_type(0), s.count_n("A", 0, len)); + Assert::AreEqual(pcs::CppString::size_type(2), s.count_n("abca", 4, len - 4)); + Assert::AreEqual(pcs::CppString::size_type(5), s.count_n("bca", 2, len - 2)); + Assert::AreEqual(pcs::CppString::size_type(0), s.count_n("A", 3, len - 3)); + Assert::AreEqual(pcs::CppString::size_type(1), s.count_n("abca", 4, len - 5)); + Assert::AreEqual(pcs::CppString::size_type(4), s.count_n("bca", 2, len - 3)); + Assert::AreEqual(pcs::CppString::size_type(0), s.count_n("A", 3, len + 4)); + + pcs::CppWString ws(L"abcabcabcdefabca bca bcabca"); + const pcs::CppWString::size_type wlen{ ws.size() }; + Assert::AreEqual(pcs::CppString::size_type(3), ws.count_n(L"abca", 0, wlen)); + Assert::AreEqual(pcs::CppString::size_type(6), ws.count_n(L"bca", 0, wlen)); + Assert::AreEqual(pcs::CppString::size_type(0), ws.count_n(L"A", 0, wlen)); + Assert::AreEqual(pcs::CppString::size_type(2), ws.count_n(L"abca", 4, wlen - 4)); + Assert::AreEqual(pcs::CppString::size_type(5), ws.count_n(L"bca", 2, wlen - 2)); + Assert::AreEqual(pcs::CppString::size_type(0), ws.count_n(L"A", 3, wlen - 3)); + Assert::AreEqual(pcs::CppString::size_type(1), ws.count_n(L"abca", 4, wlen - 5)); + Assert::AreEqual(pcs::CppString::size_type(4), ws.count_n(L"bca", 2, wlen - 3)); + Assert::AreEqual(pcs::CppString::size_type(0), ws.count_n(L"A", 3, wlen + 4)); + } + + TEST_METHOD(endswith) + { + pcs::CppString s("abcabcabcdefabca bca bcabca"); + const pcs::CppString::size_type len{ s.size() }; + Assert::IsTrue(s.endswith("abca")); + Assert::IsFalse(s.endswith("abcabca")); + Assert::IsTrue(s.endswith("abc", len - 1)); + Assert::IsFalse(s.endswith("bcabca", len - 1)); + Assert::IsTrue(s.endswith("abca", len - 4, len)); + Assert::IsFalse(s.endswith("abca", len - 4, len - 2)); + Assert::IsTrue(s.endswith({ "def", "ghi", "abca" }, len - 4, len)); + Assert::IsFalse(s.endswith({ "def", "ghi" }, len - 4, len)); + Assert::IsFalse(s.endswith({ "def", "ghi", "abca" }, len - 4, len - 2)); + + pcs::CppWString ws(L"abcabcabcdefabca bca bcabca"); + const pcs::CppWString::size_type wlen{ ws.size() }; + Assert::IsTrue(ws.endswith(L"abca")); + Assert::IsFalse(ws.endswith(L"abcabca")); + Assert::IsTrue(ws.endswith(L"abc", wlen - 1)); + Assert::IsFalse(ws.endswith(L"bcabca", wlen - 1)); + Assert::IsTrue(ws.endswith(L"abca", wlen - 4, wlen)); + Assert::IsFalse(ws.endswith(L"abca", wlen - 4, wlen - 2)); + Assert::IsTrue(ws.endswith({ L"def", L"ghi", L"abca" }, len - 4, len)); + Assert::IsFalse(ws.endswith({ L"def", L"ghi" }, len - 4, len)); + Assert::IsFalse(ws.endswith({ L"def", L"ghi", L"abca" }, len - 4, len - 2)); + } + + TEST_METHOD(endswith_n) + { + pcs::CppString s("abcabcabcdefabca bca bcabca"); + const pcs::CppString::size_type len{ s.size() }; + Assert::IsTrue(s.endswith_n("abc", len - 1)); + Assert::IsFalse(s.endswith_n("bcabca", len - 1)); + Assert::IsTrue(s.endswith_n("abca", len - 4, 4)); + Assert::IsFalse(s.endswith_n("abca", len - 4, 3)); + Assert::IsTrue(s.endswith_n({ "def", "ghi", "abca" }, len - 4, 4)); + Assert::IsFalse(s.endswith_n({ "def", "ghi" }, len - 4, 4)); + Assert::IsFalse(s.endswith_n({ "def", "ghi", "abca" }, len - 4, 3)); + + pcs::CppWString ws(L"abcabcabcdefabca bca bcabca"); + const pcs::CppWString::size_type wlen{ ws.size() }; + Assert::IsTrue(ws.endswith_n(L"abc", wlen - 1)); + Assert::IsFalse(ws.endswith_n(L"bcabca", wlen - 1)); + Assert::IsTrue(ws.endswith_n(L"abca", wlen - 4, 4)); + Assert::IsFalse(ws.endswith_n(L"abca", wlen - 4, 3)); + Assert::IsTrue(ws.endswith_n({ L"def", L"ghi", L"abca" }, len - 4, 4)); + Assert::IsFalse(ws.endswith_n({ L"def", L"ghi" }, len - 4, 4)); + Assert::IsFalse(ws.endswith_n({ L"def", L"ghi", L"abca" }, len - 4, 3)); + } + + TEST_METHOD(expand_tabs) + { + pcs::CppString s("a\tbc\tdef\tghij\t\r\tk\nl\tm\r\nno\tpqr \ts."); + pcs::CppString ts = s.expand_tabs(4); + Assert::AreEqual(pcs::CppString("a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), ts.c_str()); + ts = s.expand_tabs(3); + Assert::AreEqual(pcs::CppString("a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), ts.c_str()); + ts = s.expand_tabs(2); + Assert::AreEqual(pcs::CppString("a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), ts.c_str()); + ts = s.expand_tabs(1); + Assert::AreEqual(pcs::CppString("a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), ts.c_str()); + + pcs::CppWString ws(L"a\tbc\tdef\tghij\t\r\tk\nl\tm\r\nno\tpqr \ts."); + pcs::CppWString wts = ws.expand_tabs(4); + Assert::AreEqual(pcs::CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); + wts = ws.expand_tabs(3); + Assert::AreEqual(pcs::CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); + wts = ws.expand_tabs(2); + Assert::AreEqual(pcs::CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); + wts = ws.expand_tabs(1); + Assert::AreEqual(pcs::CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); + } + + TEST_METHOD(find) + { + size_t found_pos; + + pcs::CppString test_str{ "ABC0123456789.ABC0123456789." }; + for (int c = 0; c <= 255; ++c) { + char ch{ char(c) }; + Assert::AreEqual(test_str.MyBaseClass::find(ch), test_str.find(ch)); + + found_pos = test_str.substr(2).MyBaseClass::find(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find(ch, 2)); + else + Assert::AreEqual(found_pos, test_str.find(ch, 2) - 2); + + found_pos = test_str.substr(2, 5).MyBaseClass::find(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find(ch, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test_str.find(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + pcs::CppString s(ch); + Assert::AreEqual(test_str.MyBaseClass::find(s), test_str.find(s)); + found_pos = test_str.substr(2).MyBaseClass::find(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find(s, 2)); + else + Assert::AreEqual(found_pos, test_str.find(s, 2) - 2); + + found_pos = test_str.substr(2, 5).MyBaseClass::find(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find(s, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test_str.find(s, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + if (c > 0) { + char str[2]{ ch, 0 }; + Assert::AreEqual(test_str.MyBaseClass::find(str), test_str.find(str)); + + found_pos = test_str.substr(2).MyBaseClass::find(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find(str, 2)); + else + Assert::AreEqual(found_pos, test_str.find(str, 2) - 2); + + found_pos = test_str.substr(2, 5).MyBaseClass::find(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find(str, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test_str.find(str, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + } + } + Assert::AreEqual(size_t(14), test_str.find("A", 1)); + Assert::AreEqual(pcs::CppString::npos, test_str.find("A", 15)); + Assert::AreEqual(size_t(0), test_str.find("")); + Assert::AreEqual(size_t(27), test_str.find(".", 14)); + Assert::AreEqual(pcs::CppString::npos, test_str.find(".", 28)); + Assert::AreEqual(size_t(13), test_str.find(".", 13)); + + pcs::CppWString wtest{ L"ABC0123456789.ABC0123456789." }; + for (int wc = 0; wc <=0xffff; ++wc) { + wchar_t wch{ wchar_t(wc) }; + + found_pos = wtest.substr(2).MyBaseClass::find(wch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find(wch, 2)); + else + Assert::AreEqual(found_pos, wtest.find(wch, 2) - 2); + + found_pos = wtest.substr(2, 5).MyBaseClass::find(wch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find(wch, 2, pcs::CppWString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, wtest.find(wch, 2, pcs::CppWString::size_type(5 + 2 - 1)) - 2); + + pcs::CppWString ws(wch); + Assert::AreEqual(wtest.MyBaseClass::find(ws), wtest.find(ws)); + + found_pos = wtest.substr(2).MyBaseClass::find(ws); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find(ws, 2)); + else + Assert::AreEqual(found_pos, wtest.find(ws, 2) - 2); + + found_pos = wtest.substr(2, 5).MyBaseClass::find(ws); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find(ws, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, wtest.find(ws, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + + if (wc > 0) { + wchar_t wstr[2]{ wch, 0 }; + Assert::AreEqual(wtest.MyBaseClass::find(wstr), wtest.find(wstr)); + + found_pos = wtest.substr(2).MyBaseClass::find(wstr); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find(wstr, 2)); + else + Assert::AreEqual(found_pos, wtest.find(wstr, 2) - 2); + + found_pos = wtest.substr(2, 5).MyBaseClass::find(wstr); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find(wstr, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, wtest.find(wstr, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + } + } + Assert::AreEqual(size_t(14), wtest.find(L"A", 1)); + Assert::AreEqual(pcs::CppString::npos, wtest.find(L"A", 15)); + Assert::AreEqual(size_t(0), wtest.find(L"")); + Assert::AreEqual(size_t(27), wtest.find(L".", 14)); + Assert::AreEqual(pcs::CppString::npos, wtest.find(L".", 28)); + Assert::AreEqual(size_t(13), wtest.find(L".", 13)); + } + + TEST_METHOD(find_n) + { + size_t found_pos; + + pcs::CppString test_str{ "ABC0123456789.ABC0123456789." }; + for (int c = 0; c <= 255; ++c) { + char ch{ char(c) }; + Assert::AreEqual(test_str.MyBaseClass::find(ch), test_str.find_n(ch, size_t(-1))); + + found_pos = test_str.substr(2).MyBaseClass::find(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find_n(ch, 2)); + else + Assert::AreEqual(found_pos, test_str.substr(2).find_n(ch, test_str.size() - 2)); + + found_pos = test_str.substr(2, 5).MyBaseClass::find(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find_n(ch, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test_str.find_n(ch, 2, pcs::CppString::size_type(5)) - 2); + + pcs::CppString s(ch); + Assert::AreEqual(test_str.MyBaseClass::find(s), test_str.find_n(s, size_t(-1))); + found_pos = test_str.substr(2).MyBaseClass::find(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find_n(s, 2)); + else + Assert::AreEqual(found_pos, test_str.substr(2).find_n(s, test_str.size() - 2)); + + found_pos = test_str.substr(2, 5).MyBaseClass::find(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find_n(s, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test_str.find_n(s, 2, pcs::CppString::size_type(5)) - 2); + + if (c > 0) { + char str[2]{ ch, 0 }; + Assert::AreEqual(test_str.MyBaseClass::find(str), test_str.find_n(str, size_t(-1))); + + found_pos = test_str.substr(2).MyBaseClass::find(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find_n(str, test_str.size() - 2)); + else + Assert::AreEqual(found_pos, test_str.substr(2).find_n(str, test_str.size() - 2)); + + found_pos = test_str.substr(2, 5).MyBaseClass::find(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.find_n(str, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test_str.find_n(str, 2, pcs::CppString::size_type(5)) - 2); + } + } + Assert::AreEqual(size_t(14), test_str.find_n("A", 1, test_str.size() - 1)); + Assert::AreEqual(pcs::CppString::npos, test_str.find_n("A", 15, 1)); + Assert::AreEqual(size_t(0), test_str.find_n("", size_t(-1))); + Assert::AreEqual(size_t(27), test_str.find_n(".", 14, test_str.size() - 14)); + Assert::AreEqual(pcs::CppString::npos, test_str.find_n(".", 28, 1)); + Assert::AreEqual(size_t(13), test_str.find_n(".", 13, test_str.size() - 13)); + + pcs::CppWString wtest{ L"ABC0123456789.ABC0123456789." }; + for (int wc = 0; wc <= 0xffff; ++wc) { + wchar_t wch{ wchar_t(wc) }; + Assert::AreEqual(wtest.MyBaseClass::find(wch), wtest.find_n(wch, size_t(-1))); + + found_pos = wtest.substr(2).MyBaseClass::find(wch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find_n(wch, 2)); + else + Assert::AreEqual(found_pos, wtest.substr(2).find_n(wch, wtest.size() - 2)); + + found_pos = wtest.substr(2, 5).MyBaseClass::find(wch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find_n(wch, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, wtest.find_n(wch, 2, pcs::CppString::size_type(5)) - 2); + + pcs::CppWString ws(wch); + Assert::AreEqual(wtest.MyBaseClass::find(ws), wtest.find_n(ws, size_t(-1))); + found_pos = wtest.substr(2).MyBaseClass::find(ws); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find_n(ws, 2)); + else + Assert::AreEqual(found_pos, wtest.substr(2).find_n(ws, wtest.size() - 2)); + + found_pos = wtest.substr(2, 5).MyBaseClass::find(ws); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find_n(ws, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, wtest.find_n(ws, 2, pcs::CppString::size_type(5)) - 2); + + if (wc > 0) { + wchar_t wstr[2]{ wch, 0 }; + Assert::AreEqual(wtest.MyBaseClass::find(wstr), wtest.find_n(wstr, size_t(-1))); + + found_pos = wtest.substr(2).MyBaseClass::find(wstr); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find_n(wstr, wtest.size() - 2)); + else + Assert::AreEqual(found_pos, wtest.substr(2).find_n(wstr, wtest.size() - 2)); + + found_pos = wtest.substr(2, 5).MyBaseClass::find(wstr); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.find_n(wstr, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, wtest.find_n(wstr, 2, pcs::CppString::size_type(5)) - 2); + } + } + Assert::AreEqual(size_t(14), wtest.find_n(L"A", 1, wtest.size() - 1)); + Assert::AreEqual(pcs::CppString::npos, wtest.find_n(L"A", 15, 1)); + Assert::AreEqual(size_t(0), wtest.find_n(L"", size_t(-1))); + Assert::AreEqual(size_t(27), wtest.find_n(L".", 14, wtest.size() - 14)); + Assert::AreEqual(pcs::CppString::npos, wtest.find_n(L".", 28, 1)); + Assert::AreEqual(size_t(13), wtest.find_n(L".", 13, wtest.size() - 13)); + + } + + TEST_METHOD(format) + { + pcs::CppString s; + s.format("{:d}, {:d}, {:s}", 1, 2, "Abc"); + Assert::AreEqual("1, 2, Abc", s.c_str()); + + const int x{ 5 }; + const unsigned long long y{ 6 }; + const double pi{ 3.141592653529 }; + const std::string t{ "abc." }; + Assert::AreEqual("56 3.1415927abc.", (s.format("{}{}{:10.7f}{:s}", x, y, pi, t)).c_str()); + + pcs::CppWString ws; + ws.format(L"{:d}, {:d}, {}", 1, 2, L"Abc"); + Assert::AreEqual(L"1, 2, Abc", ws.c_str()); + + const std::wstring wt{ L"abc." }; + Assert::AreEqual(L"56 3.1415927abc.", (ws.format(L"{}{}{:10.7f}{:s}", x, y, pi, wt)).c_str()); + } + + TEST_METHOD(index_char) + { + using string_type = pcs::CppString; + + string_type test_str{ "ABC0123456789." }; + char ch{ '3' }; + Assert::AreEqual(test_str.MyBaseClass::find(ch), test_str.index(ch)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::find(ch), test_str.index(ch, 2) - 2); + Assert::AreEqual(test_str.substr(2, 5).MyBaseClass::find(ch), test_str.index(ch, 2, string_type::size_type(5 + 2 - 1)) - 2); + try { + const string_type::size_type pos = test_str.index('z'); + Assert::IsTrue(pos != pcs::CppString::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index('z', 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index('z', 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + string_type s(ch); + Assert::AreEqual(test_str.MyBaseClass::find(s), test_str.index(s)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::find(s), test_str.index(s, 2) - 2); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::find(s), test_str.index(s, 3, string_type::size_type(5 + 3 - 1)) - 3); + s = 'z'; + try { + const string_type::size_type pos = test_str.index(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index(s, 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index(s, 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + char str[2]{ ch, 0 }; + Assert::AreEqual(test_str.MyBaseClass::find(str), test_str.index(str)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::find(str), test_str.index(str, 2) - 2); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::find(str), test_str.index(str, 3, string_type::size_type(5 + 3 - 1)) - 3); + str[0] = 'z'; + try { + const string_type::size_type pos = test_str.index(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index(s, 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index(s, 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + + TEST_METHOD(index_wchart) + { + using string_type = pcs::CppWString; + + string_type test_str( L"ABC0123456789." ); + wchar_t ch{ L'3' }; + Assert::AreEqual(test_str.MyBaseClass::find(ch), test_str.index(ch)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::find(ch), test_str.index(ch, 2) - 2); + Assert::AreEqual(test_str.substr(2, 5).MyBaseClass::find(ch), test_str.index(ch, 2, string_type::size_type(5 + 2 - 1)) - 2); + try { + const string_type::size_type pos = test_str.index('z'); + Assert::IsTrue(pos != pcs::CppString::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index('z', 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index('z', 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + string_type s(ch); + Assert::AreEqual(test_str.MyBaseClass::find(s), test_str.index(s)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::find(s), test_str.index(s, 2) - 2); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::find(s), test_str.index(s, 3, string_type::size_type(5 + 3 - 1)) - 3); + s = 'z'; + try { + const string_type::size_type pos = test_str.index(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index(s, 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index(s, 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + wchar_t str[2]{ ch, 0 }; + Assert::AreEqual(test_str.MyBaseClass::find(str), test_str.index(str)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::find(str), test_str.index(str, 2) - 2); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::find(str), test_str.index(str, 3, string_type::size_type(5 + 3 - 1)) - 3); + str[0] = 'z'; + try { + const string_type::size_type pos = test_str.index(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index(s, 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.index(s, 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + + TEST_METHOD(index_n_char) + { + using string_type = pcs::CppString; + + pcs::CppString test_str{ "ABC0123456789." }; + char ch{ '3' }; + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::find(ch), test_str.index_n(ch, 20)); + Assert::AreEqual(test_str.substr(2, 5).MyBaseClass::find(ch), test_str.index_n(ch, 2, 5) - 2); + try { + const string_type::size_type pos = test_str.index_n('z', 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.index_n('z', 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + pcs::CppString s(ch); + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::find(s), test_str.index_n(s, 20)); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::find(s), test_str.index_n(s, 3, 5) - 3); + s = 'z'; + try { + const string_type::size_type pos = test_str.index_n(s, 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.index_n(s, 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + char str[2]{ ch, 0 }; + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::find(str), test_str.index_n(str, 20)); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::find(str), test_str.index_n(str, 3, 5) - 3); + str[0] = 'z'; + try { + const string_type::size_type pos = test_str.index_n(s, 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.index_n(s, 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + + TEST_METHOD(index_n_wchar_t) + { + using string_type = pcs::CppWString; + + string_type test_str{ L"ABC0123456789." }; + wchar_t ch{ L'3'}; + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::find(ch), test_str.index_n(ch, 20)); + Assert::AreEqual(test_str.substr(2, 5).MyBaseClass::find(ch), test_str.index_n(ch, 2, 5) - 2); + try { + const string_type::size_type pos = test_str.index_n('z', 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.index_n('z', 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + string_type s(ch); + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::find(s), test_str.index_n(s, 20)); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::find(s), test_str.index_n(s, 3, 5) - 3); + try { + const string_type::size_type pos = test_str.index_n(s, 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.index_n(s, 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + wchar_t str[2]{ ch, 0 }; + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::find(str), test_str.index_n(str, 20)); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::find(str), test_str.index_n(str, 3, 5) - 3); + str[0] = L'z'; + try { + const string_type::size_type pos = test_str.index_n(s, 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.index_n(s, 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + + TEST_METHOD(isalnum) + { + Assert::IsTrue(pcs::CppString("aA25").isalnum()); + Assert::IsFalse(pcs::CppString("0123456789az,").isalnum()); + Assert::IsTrue(pcs::CppWString(L"aA25").isalnum()); + Assert::IsFalse(pcs::CppWString(L"0123456789az,").isalnum()); + } + + TEST_METHOD(isalpha) + { + Assert::IsFalse(pcs::CppString().isalpha()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(3, ch); + Assert::AreEqual(pcs::is_alpha(ch), s.isalpha()); + } + + Assert::IsFalse(pcs::CppWString().isalpha()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(3, wch); + Assert::AreEqual(pcs::is_alpha(wch), ws.isalpha()); + } + } + + TEST_METHOD(isascii) + { + Assert::IsTrue(pcs::CppString().isascii()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(3, ch); + Assert::AreEqual(pcs::is_ascii(ch), s.isascii()); + } + + Assert::IsTrue(pcs::CppWString().isascii()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(3, wch); + Assert::AreEqual(pcs::is_ascii(wch), ws.isascii()); + } + } + + TEST_METHOD(isdecimal) + { + Assert::IsFalse(pcs::CppString().isdecimal()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(5, ch); + Assert::AreEqual(pcs::is_decimal(ch), s.isdecimal()); + } + + Assert::IsFalse(pcs::CppWString().isdecimal()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(5, wch); + Assert::AreEqual(pcs::is_decimal(wch), ws.isdecimal()); + } + } + + TEST_METHOD(isdigit) + { + Assert::IsFalse(pcs::CppString().isdigit()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(5, ch); + Assert::AreEqual(pcs::is_digit(ch), s.isdigit()); + } + + Assert::IsFalse(pcs::CppWString().isdigit()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(5, wch); + Assert::AreEqual(pcs::is_digit(wch), ws.isdigit()); + } + } + + TEST_METHOD(isidentifier) + { + Assert::IsTrue(pcs::CppString("_").isidentifier()); + Assert::IsTrue(pcs::CppString("A").isidentifier()); + Assert::IsTrue(pcs::CppString("b").isidentifier()); + Assert::IsTrue(pcs::CppString("_abcdefghijklmnopqrstuvwxyz0123456789_").isidentifier()); + Assert::IsTrue(pcs::CppString("abcdefghijklmnopqrstuvwxyz0123456789_").isidentifier()); + Assert::IsTrue(pcs::CppString("abcdefghijklmnopqrstuvwxyz_0123456789").isidentifier()); + Assert::IsTrue(pcs::CppString("_0123456789").isidentifier()); + Assert::IsTrue(pcs::CppString("__").isidentifier()); + Assert::IsFalse(pcs::CppString("_abcdefghijklmnopqrstuvwxyz0123456789.").isidentifier()); + Assert::IsFalse(pcs::CppString("0a").isidentifier()); + + Assert::IsTrue(pcs::CppWString(L"_").isidentifier()); + Assert::IsTrue(pcs::CppWString(L"A").isidentifier()); + Assert::IsTrue(pcs::CppWString(L"b").isidentifier()); + Assert::IsTrue(pcs::CppWString(L"_0123456789abcdefghijklmnopqrstuvwxyz_").isidentifier()); + Assert::IsTrue(pcs::CppWString(L"abcdefghijk0123456789lmnopqrstuvwxyz_").isidentifier()); + Assert::IsTrue(pcs::CppWString(L"abcdefghijk0123456789_lmnopqrstuvwxyz").isidentifier()); + Assert::IsTrue(pcs::CppWString(L"_0123456789").isidentifier()); + Assert::IsTrue(pcs::CppWString(L"__").isidentifier()); + Assert::IsFalse(pcs::CppWString(L"_0123456789abcdefghijklmnopqrstuvwxyz.").isidentifier()); + Assert::IsFalse(pcs::CppWString(L"9z").isidentifier()); + } + + TEST_METHOD(islower) + { + Assert::IsFalse(pcs::CppString().islower()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(5, ch); + Assert::AreEqual(pcs::is_lower(ch), s.islower()); + } + + Assert::IsFalse(pcs::CppWString().islower()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(5, wch); + Assert::AreEqual(pcs::is_lower(wch), ws.islower()); + } + } + + TEST_METHOD(isnumeric) + { + Assert::IsFalse(pcs::CppString().isnumeric()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(5, ch); + Assert::AreEqual(pcs::is_numeric(ch), s.isnumeric()); + } + + Assert::IsFalse(pcs::CppWString().isnumeric()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(5, wch); + Assert::AreEqual(pcs::is_numeric(wch), ws.isnumeric()); + } + } + + TEST_METHOD(isprintable) + { + Assert::IsTrue(pcs::CppString().isprintable()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(5, ch); + Assert::AreEqual(pcs::is_printable(ch), s.isprintable()); + } + + Assert::IsTrue(pcs::CppWString().isprintable()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(5, wch); + Assert::AreEqual(pcs::is_printable(wch), ws.isprintable()); + } + } + + TEST_METHOD(ispunctuation) + { + Assert::IsFalse(pcs::CppString().ispunctuation()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(3, ch); + Assert::IsFalse(s.ispunctuation()); + Assert::AreEqual(pcs::is_punctuation(ch), pcs::CppString(ch).ispunctuation()); + } + + Assert::IsFalse(pcs::CppWString().ispunctuation()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(3, wch); + Assert::IsFalse(ws.ispunctuation()); + Assert::AreEqual(pcs::is_punctuation(wch), pcs::CppWString(wch).ispunctuation()); + } + } + + TEST_METHOD(isspace) + { + Assert::IsFalse(pcs::CppString().isspace()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(5, ch); + Assert::AreEqual(pcs::is_space(ch), s.isspace()); + } + + Assert::IsFalse(pcs::CppWString().isspace()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(5, wch); + Assert::AreEqual(pcs::is_space(wch), ws.isspace()); + } + } + + TEST_METHOD(istitle) + { + pcs::CppString s("abc, defgh ijklm nop. qrs 1 tuvwx2345 = yz!"); + Assert::IsFalse(s.istitle()); + Assert::IsTrue(s.title().istitle()); + + pcs::CppWString ws(L"abc, defgh ijklm nop. qrs 1 tuvwx2345 = yz!"); + Assert::IsFalse(ws.istitle()); + Assert::IsTrue(ws.title().istitle()); + } + + TEST_METHOD(isupper) + { + Assert::IsFalse(pcs::CppString().isupper()); + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(5, ch); + Assert::AreEqual(pcs::is_upper(ch), s.isupper()); + } + + Assert::IsFalse(pcs::CppWString().isupper()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(5, wch); + Assert::AreEqual(pcs::is_upper(wch), ws.isupper()); + } + } + + TEST_METHOD(is_words_sep) + { + Assert::IsFalse(pcs::CppString().is_words_sep()); + for (int c = 32; c <= 255; ++c) { + const char ch{ char(c) }; + pcs::CppString s(5, ch); + Assert::AreEqual(pcs::is_space(ch) || pcs::is_punctuation(ch), s.is_words_sep()); + } + + Assert::IsFalse(pcs::CppWString().is_words_sep()); + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + pcs::CppWString ws(5, wch); + Assert::AreEqual(pcs::is_space(wch) || pcs::is_punctuation(wch), ws.is_words_sep()); + } + } + + TEST_METHOD(join) + { + pcs::CppString s("##"); + std::array arr{ "abcd", "efg" }; + Assert::AreEqual(pcs::CppString("abcd##efg").c_str(), s.join(arr).c_str()); + Assert::AreEqual(pcs::CppString("abcd##efg##123456789").c_str(), s.join(std::array{ "abcd", "efg", "123456789" }).c_str()); + + pcs::CppWString ws(L"##"); + std::array warr{ L"abcd", L"efg" }; + Assert::AreEqual(pcs::CppWString(L"abcd##efg").c_str(), ws.join(warr).c_str()); + Assert::AreEqual(pcs::CppWString(L"abcd##efg##123456789").c_str(), ws.join(std::array{ L"abcd", L"efg", L"123456789" }).c_str()); + + std::vector vec{ "abcd", "efg" }; + Assert::AreEqual(pcs::CppString("abcd##efg").c_str(), s.join(vec).c_str()); + vec.push_back("123456789"); + Assert::AreEqual(pcs::CppString("abcd##efg##123456789").c_str(), s.join(vec).c_str()); + + std::vector wvec{ L"abcd", L"efg" }; + Assert::AreEqual(pcs::CppWString(L"abcd##efg").c_str(), ws.join(wvec).c_str()); + wvec.push_back(L"123456789"); + Assert::AreEqual(pcs::CppWString(L"abcd##efg##123456789").c_str(), ws.join(wvec).c_str()); + + using namespace pcs; + Assert::AreEqual(pcs::CppString("abcd##efg").c_str(), s.join(pcs::CppString("abcd"), pcs::CppString("efg")).c_str()); + Assert::AreEqual(pcs::CppString("abcd##efg##123456789").c_str(), s.join(pcs::CppString("abcd"), pcs::CppString("efg"), pcs::CppString("123456789")).c_str()); + Assert::AreEqual(pcs::CppString("abcd##efg##123456789##0").c_str(), s.join("abcd", "efg", "123456789", "0").c_str()); + Assert::AreEqual(pcs::CppString("abcd# #efg# #123456789# #0").c_str(), "# #"_cs.join("abcd", "efg", "123456789", "0").c_str()); + Assert::AreEqual("abcdE", "##"_cs.join("abcdE").c_str()); + Assert::AreEqual("##", "##"_cs.join().c_str()); + Assert::AreEqual("", "##"_cs.join("").c_str()); + + Assert::AreEqual(pcs::CppWString(L"abcd##efg").c_str(), ws.join(pcs::CppWString(L"abcd"), pcs::CppWString(L"efg")).c_str()); + Assert::AreEqual(pcs::CppWString(L"abcd##efg##123456789").c_str(), ws.join(pcs::CppWString(L"abcd"), pcs::CppWString(L"efg"), pcs::CppWString(L"123456789")).c_str()); + Assert::AreEqual(pcs::CppWString(L"abcd##efg##123456789##0").c_str(), ws.join(L"abcd"_cs, L"efg"_cs, L"123456789"_cs, L"0"_cs).c_str()); + Assert::AreEqual(pcs::CppWString(L"abcd# #efg# #123456789# #0").c_str(), L"# #"_cs.join(L"abcd", L"efg"_cs, L"123456789"_cs, L"0"_cs).c_str()); + Assert::AreEqual(pcs::CppWString(L"abcdE").c_str(), L"##"_cs.join(L"abcdE").c_str()); + Assert::AreEqual(pcs::CppWString(L"##").c_str(), L"##"_cs.join().c_str()); + Assert::AreEqual(pcs::CppWString(L"").c_str(), L"##"_cs.join(L"").c_str()); + } + + TEST_METHOD(ljust) + { + pcs::CppString s("abc"); + Assert::AreEqual("abc", s.ljust(1).c_str()); + Assert::AreEqual("abc", s.ljust(2).c_str()); + Assert::AreEqual("abc", s.ljust(3).c_str()); + Assert::AreEqual(" abc", s.ljust(4).c_str()); + Assert::AreEqual(" abc", s.ljust(5).c_str()); + Assert::AreEqual("abc", s.ljust(1).c_str()); + Assert::AreEqual("abc", s.ljust(2).c_str()); + Assert::AreEqual("abc", s.ljust(3).c_str()); + Assert::AreEqual(".abc", s.ljust(4, '.').c_str()); + Assert::AreEqual("..abc", s.ljust(5, '.').c_str()); + + pcs::CppWString ws(L"abc"); + Assert::AreEqual(L"abc", ws.ljust(1).c_str()); + Assert::AreEqual(L"abc", ws.ljust(2).c_str()); + Assert::AreEqual(L"abc", ws.ljust(3).c_str()); + Assert::AreEqual(L" abc", ws.ljust(4).c_str()); + Assert::AreEqual(L" abc", ws.ljust(5).c_str()); + Assert::AreEqual(L"abc", ws.ljust(1).c_str()); + Assert::AreEqual(L"abc", ws.ljust(2).c_str()); + Assert::AreEqual(L"abc", ws.ljust(3).c_str()); + Assert::AreEqual(L".abc", ws.ljust(4, '.').c_str()); + Assert::AreEqual(L"..abc", ws.ljust(5, '.').c_str()); + } + + TEST_METHOD(lower) + { + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + constexpr int N{ 5 }; + pcs::CppString s(N, ch); + s.lower(); + for (int i=0; i < N; ++i) + Assert::AreEqual(pcs::to_lower(ch), s[i]); + Assert::AreEqual(char(std::tolower(ch)), pcs::CppString::lower(ch)); + } + + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + constexpr int N{ 5 }; + pcs::CppWString ws(N, wch); + ws.lower(); + for (int i = 0; i < N; ++i) + Assert::AreEqual(pcs::to_lower(wch), ws[i]); + Assert::AreEqual(wchar_t(std::tolower(wch)), pcs::CppWString::lower(wch)); + } + + pcs::CppString s(255, '\0'); + for (int i : std::views::iota(0, 256)) + s[i] = pcs::CppString::value_type(i); + pcs::CppString res{ s.lower() }; + for (auto const [cs, cr] : std::views::zip(s, res)) { + if (std::islower(cs)) + Assert::IsTrue(std::islower(cr)); + else if (std::isupper(cs)) + Assert::IsTrue(std::islower(cr)); + else + Assert::AreEqual(cs, cr); + } + + pcs::CppWString ws(0xffff, '\0'); + for (int i : std::views::iota(0, 0x1'0000)) + ws[i] = pcs::CppWString::value_type(i); + pcs::CppWString wres{ ws.lower() }; + for (auto const [wcs, wcr] : std::views::zip(ws, wres)) { + if (std::islower(wcs)) + Assert::IsTrue(std::islower(wcr)); + else if (std::isupper(wcs)) + Assert::IsTrue(std::islower(wcr)); + else + Assert::AreEqual(wcs, wcr); + } + + } + + TEST_METHOD(lstrip) + { + using namespace pcs; + pcs::CppString s("abcd"); + Assert::AreEqual("cd", s.lstrip("baCD").c_str()); + Assert::AreEqual("abcd", s.lstrip("xyz").c_str()); + Assert::AreEqual("abcd", s.lstrip("").c_str()); + Assert::AreEqual("cd", "abbabaabcd"_cs.lstrip("baCD").c_str()); + Assert::AreEqual("cdab", "abbabaabcdab"_cs.lstrip("baCD").c_str()); + Assert::AreEqual("abcd", " abcd"_cs.lstrip().c_str()); + Assert::AreEqual("abcd", " abcd"_cs.lstrip().c_str()); + Assert::AreEqual("abcd", " abcd"_cs.lstrip().c_str()); + Assert::AreEqual("a bcd", " a bcd"_cs.lstrip().c_str()); + Assert::AreEqual("a bcd ", " a bcd "_cs.lstrip().c_str()); + + pcs::CppWString ws(L"abcd"); + Assert::AreEqual(L"cd", ws.lstrip(L"baCD").c_str()); + Assert::AreEqual(L"abcd", ws.lstrip(L"xyz").c_str()); + Assert::AreEqual(L"abcd", ws.lstrip(L"").c_str()); + Assert::AreEqual(L"cd", L"abbabaabcd"_cs.lstrip(L"baCD").c_str()); + Assert::AreEqual(L"cdab", L"abbabaabcdab"_cs.lstrip(L"baCD").c_str()); + Assert::AreEqual(L"abcd", L" abcd"_cs.lstrip().c_str()); + Assert::AreEqual(L"abcd", L" abcd"_cs.lstrip().c_str()); + Assert::AreEqual(L"abcd", L" abcd"_cs.lstrip().c_str()); + Assert::AreEqual(L"a bcd", L" a bcd"_cs.lstrip().c_str()); + Assert::AreEqual(L"a bcd ", L" a bcd "_cs.lstrip().c_str()); + } + + TEST_METHOD(operator_slice) + { + pcs::CppString text("AbcdefGhijklm"); + int text_size{ int(text.size()) }; + + Assert::AreEqual(text(0, text_size).c_str(), text(pcs::Slice()).c_str()); + Assert::AreEqual(text.c_str(), text(0, text_size).c_str()); + Assert::AreEqual(text.c_str(), text(pcs::StartSlice(0)).c_str()); + Assert::AreEqual(text.c_str(), text(pcs::StopSlice(123)).c_str()); + Assert::AreEqual(text.c_str(), text(pcs::StepSlice(1)).c_str()); + Assert::AreEqual(text.c_str(), text(pcs::StartStopSlice(0, 111)).c_str()); + Assert::AreEqual(text.c_str(), text(pcs::StartStepSlice(0, 1)).c_str()); + Assert::AreEqual(text.c_str(), text(pcs::StopStepSlice(text_size, 1)).c_str()); + + Assert::AreEqual("AceGikm", text(pcs::Slice(0, text_size + 2, 2)).c_str()); + Assert::AreEqual("behk", text(pcs::Slice(1, text_size, 3)).c_str()); + + Assert::AreEqual("", text(pcs::Slice(5, 4, 1)).c_str()); + Assert::AreEqual("", text(pcs::Slice(text_size, text_size + 1, 1)).c_str()); + Assert::AreEqual("", text(pcs::Slice(text_size + 2, text_size + 5, 1)).c_str()); + Assert::AreEqual("", text(pcs::Slice(5, 3, 2)).c_str()); + + pcs::CppString reversed_text{ text }; + std::ranges::reverse(reversed_text); + Assert::AreEqual(reversed_text.c_str(), text(text_size, 0, -1).c_str()); + Assert::AreEqual(reversed_text.c_str(), text(pcs::StartStepSlice(text_size, -1)).c_str()); + Assert::AreEqual(reversed_text.c_str(), text(pcs::StopStepSlice(0, -1)).c_str()); + Assert::AreEqual(reversed_text.c_str(), text(pcs::StepSlice(-1)).c_str()); + + Assert::AreEqual("mkiGec", text(pcs::Slice(text_size, 0, -2)).c_str()); + Assert::AreEqual("mjGd", text(pcs::Slice(text_size-1, 1, -3)).c_str()); + + Assert::AreEqual("", text(pcs::Slice(4, 5, -1)).c_str()); + Assert::AreEqual("", text(pcs::Slice(text_size + 1, text_size, -1)).c_str()); + Assert::AreEqual("", text(pcs::Slice(text_size + 5, text_size + 2, -1)).c_str()); + Assert::AreEqual("", text(pcs::Slice(3, 5, -2)).c_str()); + + + pcs::CppWString wtext(L"AbcdefGhijklm"); + text_size = int(wtext.size()); + + Assert::AreEqual(wtext(0, text_size).c_str(), wtext(pcs::Slice()).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(0, text_size).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(pcs::StartSlice(0)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(pcs::StopSlice(123)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(pcs::StepSlice(1)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(pcs::StartStopSlice(0, 111)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(pcs::StartStepSlice(0, 1)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(pcs::StopStepSlice(text_size, 1)).c_str()); + + Assert::AreEqual(L"AceGikm", wtext(pcs::Slice(0, text_size + 2, 2)).c_str()); + Assert::AreEqual(L"behk", wtext(pcs::Slice(1, text_size, 3)).c_str()); + + Assert::AreEqual(L"", wtext(pcs::Slice(5, 4, 1)).c_str()); + Assert::AreEqual(L"", wtext(pcs::Slice(text_size, text_size + 1, 1)).c_str()); + Assert::AreEqual(L"", wtext(pcs::Slice(text_size + 2, text_size + 5, 1)).c_str()); + Assert::AreEqual(L"", wtext(pcs::Slice(5, 3, 2)).c_str()); + + pcs::CppWString wreversed_text{ wtext }; + std::ranges::reverse(wreversed_text); + Assert::AreEqual(wreversed_text.c_str(), wtext(text_size, 0, -1).c_str()); + Assert::AreEqual(wreversed_text.c_str(), wtext(pcs::StartStepSlice(text_size, -1)).c_str()); + Assert::AreEqual(wreversed_text.c_str(), wtext(pcs::StopStepSlice(0, -1)).c_str()); + Assert::AreEqual(wreversed_text.c_str(), wtext(pcs::StepSlice(-1)).c_str()); + + Assert::AreEqual(L"mkiGec", wtext(pcs::Slice(text_size, 0, -2)).c_str()); + Assert::AreEqual(L"mjGd", wtext(pcs::Slice(text_size - 1, 1, -3)).c_str()); + + Assert::AreEqual(L"", wtext(pcs::Slice(4, 5, -1)).c_str()); + Assert::AreEqual(L"", wtext(pcs::Slice(text_size + 1, text_size, -1)).c_str()); + Assert::AreEqual(L"", wtext(pcs::Slice(text_size + 5, text_size + 2, -1)).c_str()); + Assert::AreEqual(L"", wtext(pcs::Slice(3, 5, -2)).c_str()); + } + + TEST_METHOD(operator_times) + { + pcs::CppString text("Abcd,"); + Assert::AreEqual("", (text * -1).c_str()); + Assert::AreEqual("", (text * 0).c_str()); + Assert::AreEqual(text.c_str(), (text * 1).c_str()); + Assert::AreEqual((text + text).c_str(), (text * 2).c_str()); + Assert::AreEqual((text + text + text).c_str(), (text * 3).c_str()); + + pcs::CppWString wtext(L"Abcd,"); + Assert::AreEqual(L"", (wtext * -1).c_str()); + Assert::AreEqual(L"", (wtext * 0).c_str()); + Assert::AreEqual(wtext.c_str(), (wtext * 1).c_str()); + Assert::AreEqual((wtext + wtext).c_str(), (wtext * 2).c_str()); + Assert::AreEqual((wtext + wtext + wtext).c_str(), (wtext * 3).c_str()); + } + + TEST_METHOD(partition) + { + pcs::CppString s("abcd#123efg"); + std::vector res{ s.partition("#123") }; + Assert::AreEqual("abcd", res[0].c_str()); + Assert::AreEqual("#123", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + + s = "abcd#123"; + res = s.partition("#123"); + Assert::AreEqual("abcd", res[0].c_str()); + Assert::AreEqual("#123", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + + res = s.partition("XYZ"); + Assert::AreEqual("abcd#123", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + + using namespace pcs; + res = ""_cs.partition("A"); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + + pcs::CppWString ws(L"abcd#123efg"); + std::vector wres{ ws.partition(L"#123") }; + Assert::AreEqual(L"abcd", wres[0].c_str()); + Assert::AreEqual(L"#123", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + + ws = L"abcd#123"; + wres = ws.partition(L"#123"); + Assert::AreEqual(L"abcd", wres[0].c_str()); + Assert::AreEqual(L"#123", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + + wres = ws.partition(L"XYZ"); + Assert::AreEqual(L"abcd#123", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + + wres = L""_cs.partition(L"A"); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + } + + TEST_METHOD(removeprefix) + { + using namespace pcs; + pcs::CppString s("abcd"); + Assert::AreEqual("cd", s.removeprefix("ab").c_str()); + Assert::AreEqual("abcd", s.removeprefix("ba").c_str()); + Assert::AreEqual("abcd", s.removeprefix("").c_str()); + Assert::AreEqual("abaabcd", "abbabaabcd"_cs.removeprefix("abb").c_str()); + Assert::AreEqual("cdab", "abcdab"_cs.removeprefix("ab").c_str()); + + pcs::CppWString ws(L"abcd"); + Assert::AreEqual(L"cd", ws.removeprefix(L"ab").c_str()); + Assert::AreEqual(L"abcd", ws.removeprefix(L"ba").c_str()); + Assert::AreEqual(L"abcd", ws.removeprefix(L"").c_str()); + Assert::AreEqual(L"abaabcd", L"abbabaabcd"_cs.removeprefix(L"abb").c_str()); + Assert::AreEqual(L"cdab", L"abcdab"_cs.removeprefix(L"ab").c_str()); + } + + TEST_METHOD(removesuffix) + { + using namespace pcs; + pcs::CppString s("abcd"); + Assert::AreEqual("ab", s.removesuffix("cd").c_str()); + Assert::AreEqual("abcd", s.removesuffix("dc").c_str()); + Assert::AreEqual("abcd", s.removesuffix("").c_str()); + Assert::AreEqual("abbaba", "abbabaabcd"_cs.removesuffix("abcd").c_str()); + Assert::AreEqual("abcd", "abcdab"_cs.removesuffix("ab").c_str()); + + pcs::CppWString ws(L"abcd"); + Assert::AreEqual(L"ab", ws.removesuffix(L"cd").c_str()); + Assert::AreEqual(L"abcd", ws.removesuffix(L"dc").c_str()); + Assert::AreEqual(L"abcd", ws.removesuffix(L"").c_str()); + Assert::AreEqual(L"abbaba", L"abbabaabcd"_cs.removesuffix(L"abcd").c_str()); + Assert::AreEqual(L"abcd", L"abcdab"_cs.removesuffix(L"ab").c_str()); + } + + TEST_METHOD(replace) + { + pcs::CppString s("abbaa"); + Assert::AreEqual("abbaa", s.replace("e", "fff").c_str()); + Assert::AreEqual("AAbbAAAA", s.replace("a", "AA").c_str()); + Assert::AreEqual("aBBaa", s.replace("b", "B").c_str()); + + Assert::AreEqual("abbaa", s.replace("e", "fff", 0).c_str()); + Assert::AreEqual("abbaa", s.replace("a", "AA", 0).c_str()); + Assert::AreEqual("abbaa", s.replace("b", "B", 0).c_str()); + + Assert::AreEqual("abbaa", s.replace("e", "fff", 1).c_str()); + Assert::AreEqual("AAbbaa", s.replace("a", "AA", 1).c_str()); + Assert::AreEqual("aBbaa", s.replace("b", "B", 1).c_str()); + + Assert::AreEqual("abbaa", s.replace("e", "fff", 2).c_str()); + Assert::AreEqual("AAbbAAAA", s.replace("a", "AA", 3).c_str()); + Assert::AreEqual("aBBaa", s.replace("b", "B", 5).c_str()); + + pcs::CppWString ws(L"abbaa"); + Assert::AreEqual(L"abbaa", ws.replace(L"e", L"fff").c_str()); + Assert::AreEqual(L"AAbbAAAA", ws.replace(L"a", L"AA").c_str()); + Assert::AreEqual(L"aBBaa", ws.replace(L"b", L"B").c_str()); + + Assert::AreEqual(L"abbaa", ws.replace(L"e", L"fff", 0).c_str()); + Assert::AreEqual(L"abbaa", ws.replace(L"a", L"AA", 0).c_str()); + Assert::AreEqual(L"abbaa", ws.replace(L"b", L"B", 0).c_str()); + + Assert::AreEqual(L"abbaa", ws.replace(L"e", L"fff", 1).c_str()); + Assert::AreEqual(L"AAbbaa", ws.replace(L"a", L"AA", 1).c_str()); + Assert::AreEqual(L"aBbaa", ws.replace(L"b", L"B", 1).c_str()); + + Assert::AreEqual(L"abbaa", ws.replace(L"e", L"fff", 2).c_str()); + Assert::AreEqual(L"AAbbAAAA", ws.replace(L"a", L"AA", 3).c_str()); + Assert::AreEqual(L"aBBaa", ws.replace(L"b", L"B", 5).c_str()); + } + + TEST_METHOD(rfind) + { + size_t found_pos; + + pcs::CppString test_str{ "ABC0123456789." }; + for (int c = 0; c <= 255; ++c) { + char ch{ char(c) }; + Assert::AreEqual(test_str.MyBaseClass::rfind(ch), test_str.rfind(ch)); + + found_pos = test_str.substr(2).MyBaseClass::rfind(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind(ch, 2)); + else + Assert::AreEqual(found_pos, test_str.rfind(ch, 2) - 2); + + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind(ch, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test_str.rfind(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + pcs::CppString s(ch); + Assert::AreEqual(test_str.MyBaseClass::rfind(s), test_str.rfind(s)); + found_pos = test_str.substr(2).MyBaseClass::rfind(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind(s, 2)); + else + Assert::AreEqual(found_pos, test_str.rfind(s, 2) - 2); + + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind(s, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test_str.rfind(s, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + if (c > 0) { + char str[2]{ ch, 0 }; + Assert::AreEqual(test_str.MyBaseClass::rfind(str), test_str.rfind(str)); + + found_pos = test_str.substr(2).MyBaseClass::rfind(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind(str, 2)); + else + Assert::AreEqual(found_pos, test_str.rfind(str, 2) - 2); + + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind(str, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test_str.rfind(str, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + } + } + Assert::AreEqual(pcs::CppString::npos, test_str.rfind("A", 1)); + Assert::AreEqual(test_str.size(), test_str.rfind("")); + Assert::AreEqual(pcs::CppString::npos, test_str.rfind(".", 14)); + Assert::AreEqual(size_t(13), test_str.rfind(".", 13)); + + pcs::CppWString wtest{ L"ABC0123456789." }; + for (int wc = 0; wc <= 0xffff; ++wc) { + wchar_t wch{ wchar_t(wc) }; + + found_pos = wtest.substr(2).MyBaseClass::rfind(wch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind(wch, 2)); + else + Assert::AreEqual(found_pos, wtest.rfind(wch, 2) - 2); + + found_pos = wtest.substr(2, 5).MyBaseClass::rfind(wch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind(wch, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, wtest.rfind(wch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + pcs::CppWString ws(wch); + Assert::AreEqual(wtest.MyBaseClass::rfind(ws), wtest.rfind(ws)); + + found_pos = wtest.substr(2).MyBaseClass::rfind(ws); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind(ws, 2)); + else + Assert::AreEqual(found_pos, wtest.rfind(ws, 2) - 2); + + found_pos = wtest.substr(2, 5).MyBaseClass::rfind(ws); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind(ws, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, wtest.rfind(ws, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + if (wc > 0) { + wchar_t wstr[2]{ wch, 0 }; + Assert::AreEqual(wtest.MyBaseClass::rfind(wstr), wtest.rfind(wstr)); + + found_pos = wtest.substr(2).MyBaseClass::rfind(wstr); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind(wstr, 2)); + else + Assert::AreEqual(found_pos, wtest.rfind(wstr, 2) - 2); + + found_pos = wtest.substr(2, 5).MyBaseClass::rfind(wstr); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind(wstr, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, wtest.rfind(wstr, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + } + } + Assert::AreEqual(pcs::CppString::npos, wtest.rfind(L"A", 1)); + Assert::AreEqual(wtest.size(), wtest.rfind(L"")); + Assert::AreEqual(pcs::CppString::npos, wtest.rfind(L".", 14)); + Assert::AreEqual(size_t(13), wtest.rfind(L".", 13)); + } + + TEST_METHOD(rfind_n) + { + size_t found_pos; + + pcs::CppString test_str{ "ABC0123456789.ABC0123456789." }; + for (int c = 0; c <= 255; ++c) { + char ch{ char(c) }; + Assert::AreEqual(test_str.MyBaseClass::rfind(ch), test_str.rfind_n(ch, size_t(-1))); + + found_pos = test_str.substr(2).MyBaseClass::rfind(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind_n(ch, 2)); + else + Assert::AreEqual(found_pos, test_str.substr(2).rfind_n(ch, test_str.size() - 2)); + + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind_n(ch, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test_str.rfind_n(ch, 2, pcs::CppString::size_type(5)) - 2); + + pcs::CppString s(ch); + Assert::AreEqual(test_str.MyBaseClass::rfind(s), test_str.rfind_n(s, size_t(-1))); + found_pos = test_str.substr(2).MyBaseClass::rfind(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind_n(s, 2)); + else + Assert::AreEqual(found_pos, test_str.substr(2).rfind_n(s, test_str.size() - 2)); + + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind_n(s, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test_str.rfind_n(s, 2, pcs::CppString::size_type(5)) - 2); + + if (c > 0) { + char str[2]{ ch, 0 }; + Assert::AreEqual(test_str.MyBaseClass::rfind(str), test_str.rfind_n(str, size_t(-1))); + + found_pos = test_str.substr(2).MyBaseClass::rfind(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind_n(str, test_str.size() - 2)); + else + Assert::AreEqual(found_pos, test_str.substr(2).rfind_n(str, test_str.size() - 2)); + + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test_str.rfind_n(str, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test_str.rfind_n(str, 2, pcs::CppString::size_type(5)) - 2); + } + } + Assert::AreEqual(size_t(14), test_str.rfind_n("A", 1, test_str.size() - 1)); + Assert::AreEqual(pcs::CppString::npos, test_str.rfind_n("A", 15, 1)); + Assert::AreEqual(size_t(0), test_str.rfind_n("", size_t(-1))); + Assert::AreEqual(size_t(27), test_str.rfind_n(".", 14, test_str.size() - 14)); + Assert::AreEqual(pcs::CppString::npos, test_str.rfind_n(".", 28, 1)); + Assert::AreEqual(size_t(27), test_str.rfind_n(".", 13, test_str.size() - 13)); + + pcs::CppWString wtest{ L"ABC0123456789.ABC0123456789." }; + for (int wc = 0; wc <= 0xffff; ++wc) { + wchar_t wch{ wchar_t(wc) }; + Assert::AreEqual(wtest.MyBaseClass::rfind(wch), wtest.rfind_n(wch, size_t(-1))); + + found_pos = wtest.substr(2).MyBaseClass::rfind(wch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind_n(wch, 2)); + else + Assert::AreEqual(found_pos, wtest.substr(2).rfind_n(wch, wtest.size() - 2)); + + found_pos = wtest.substr(2, 5).MyBaseClass::rfind(wch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind_n(wch, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, wtest.rfind_n(wch, 2, pcs::CppString::size_type(5)) - 2); + + pcs::CppWString ws(wch); + Assert::AreEqual(wtest.MyBaseClass::rfind(ws), wtest.rfind_n(ws, size_t(-1))); + found_pos = wtest.substr(2).MyBaseClass::rfind(ws); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind_n(ws, 2)); + else + Assert::AreEqual(found_pos, wtest.substr(2).rfind_n(ws, wtest.size() - 2)); + + found_pos = wtest.substr(2, 5).MyBaseClass::rfind(ws); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind_n(ws, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, wtest.rfind_n(ws, 2, pcs::CppString::size_type(5)) - 2); + + if (wc > 0) { + wchar_t wstr[2]{ wch, 0 }; + Assert::AreEqual(wtest.MyBaseClass::rfind(wstr), wtest.rfind_n(wstr, size_t(-1))); + + found_pos = wtest.substr(2).MyBaseClass::rfind(wstr); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind_n(wstr, wtest.size() - 2)); + else + Assert::AreEqual(found_pos, wtest.substr(2).rfind_n(wstr, wtest.size() - 2)); + + found_pos = wtest.substr(2, 5).MyBaseClass::rfind(wstr); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, wtest.rfind_n(wstr, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, wtest.rfind_n(wstr, 2, pcs::CppString::size_type(5)) - 2); + } + } + Assert::AreEqual(size_t(14), wtest.rfind_n(L"A", 1, wtest.size() - 1)); + Assert::AreEqual(pcs::CppString::npos, wtest.rfind_n(L"A", 15, 1)); + Assert::AreEqual(size_t(0), wtest.rfind_n(L"", size_t(-1))); + Assert::AreEqual(size_t(27), wtest.rfind_n(L".", 14, wtest.size() - 14)); + Assert::AreEqual(pcs::CppString::npos, wtest.rfind_n(L".", 28, 1)); + Assert::AreEqual(size_t(27), wtest.rfind_n(L".", 13, wtest.size() - 13)); + } + + TEST_METHOD(rindex_char) + { + using string_type = pcs::CppString; + + string_type test_str{ "ABC0123456789." }; + char ch{ '3' }; + Assert::AreEqual(test_str.MyBaseClass::rfind(ch), test_str.rindex(ch)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::rfind(ch), test_str.rindex(ch, 2) - 2); + Assert::AreEqual(test_str.substr(2, 5).MyBaseClass::rfind(ch), test_str.rindex(ch, 2, string_type::size_type(5 + 2 - 1)) - 2); + + try { + const string_type::size_type pos = test_str.rindex('z'); + Assert::IsTrue(pos != pcs::CppString::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex('z', 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex('z', 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + string_type s(ch); + Assert::AreEqual(test_str.MyBaseClass::rfind(s), test_str.rindex(s)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::rfind(s), test_str.rindex(s, 2) - 2); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::rfind(s), test_str.rindex(s, 3, string_type::size_type(5 + 3 - 1)) - 3); + s = 'z'; + try { + const string_type::size_type pos = test_str.rindex(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex(s, 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex(s, 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + char str[2]{ ch, 0 }; + Assert::AreEqual(test_str.MyBaseClass::rfind(str), test_str.rindex(str)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::rfind(str), test_str.rindex(str, 2) - 2); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::rfind(str), test_str.rindex(str, 3, string_type::size_type(5 + 3 - 1)) - 3); + str[0] = 'z'; + try { + const string_type::size_type pos = test_str.rindex(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex(s, 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex(s, 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + + TEST_METHOD(rindex_wchart) + { + using string_type = pcs::CppWString; + + string_type test_str(L"ABC0123456789."); + wchar_t ch{ L'3' }; + Assert::AreEqual(test_str.MyBaseClass::rfind(ch), test_str.rindex(ch)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::rfind(ch), test_str.rindex(ch, 2) - 2); + Assert::AreEqual(test_str.substr(2, 5).MyBaseClass::rfind(ch), test_str.rindex(ch, 2, string_type::size_type(5 + 2 - 1)) - 2); + try { + const string_type::size_type pos = test_str.rindex('z'); + Assert::IsTrue(pos != pcs::CppString::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex('z', 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex('z', 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + string_type s(ch); + Assert::AreEqual(test_str.MyBaseClass::rfind(s), test_str.rindex(s)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::rfind(s), test_str.rindex(s, 2) - 2); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::rfind(s), test_str.rindex(s, 3, string_type::size_type(5 + 3 - 1)) - 3); + s = 'z'; + try { + const string_type::size_type pos = test_str.rindex(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex(s, 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex(s, 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + wchar_t str[2]{ ch, 0 }; + Assert::AreEqual(test_str.MyBaseClass::rfind(str), test_str.rindex(str)); + Assert::AreEqual(test_str.substr(2).MyBaseClass::rfind(str), test_str.rindex(str, 2) - 2); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::rfind(str), test_str.rindex(str, 3, string_type::size_type(5 + 3 - 1)) - 3); + str[0] = 'z'; + try { + const string_type::size_type pos = test_str.rindex(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex(s, 2); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + try { + const string_type::size_type pos = test_str.rindex(s, 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + + TEST_METHOD(rindex_n_char) + { + using string_type = pcs::CppString; + + pcs::CppString test_str{ "ABC0123456789." }; + char ch{ '3' }; + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::rfind(ch), test_str.rindex_n(ch, 20)); + Assert::AreEqual(test_str.substr(2, 5).MyBaseClass::rfind(ch), test_str.rindex_n(ch, 2, 5) - 2); + try { + const string_type::size_type pos = test_str.rindex_n('z', 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.rindex_n('z', 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + pcs::CppString s(ch); + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::rfind(s), test_str.rindex_n(s, 20)); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::rfind(s), test_str.rindex_n(s, 3, 5) - 3); + s = 'z'; + try { + const string_type::size_type pos = test_str.rindex_n(s, 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.rindex_n(s, 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + char str[2]{ ch, 0 }; + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::rfind(str), test_str.rindex_n(str, 20)); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::rfind(str), test_str.rindex_n(str, 3, 5) - 3); + str[0] = 'z'; + try { + const string_type::size_type pos = test_str.rindex_n(s, 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.rindex_n(s, 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + + TEST_METHOD(rindex_n_wchar_t) + { + using string_type = pcs::CppWString; + + string_type test_str{ L"ABC0123456789." }; + wchar_t ch{ L'3' }; + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::rfind(ch), test_str.rindex_n(ch, 20)); + Assert::AreEqual(test_str.substr(2, 5).MyBaseClass::rfind(ch), test_str.rindex_n(ch, 2, 5) - 2); + try { + const string_type::size_type pos = test_str.rindex_n('z', 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.rindex_n('z', 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + string_type s(ch); + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::rfind(s), test_str.rindex_n(s, 20)); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::rfind(s), test_str.rindex_n(s, 3, 5) - 3); + try { + const string_type::size_type pos = test_str.rindex_n(s, 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.rindex_n(s, 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + wchar_t str[2]{ ch, 0 }; + Assert::AreEqual(test_str.substr(0, 20).MyBaseClass::rfind(str), test_str.rindex_n(str, 20)); + Assert::AreEqual(test_str.substr(3, 5).MyBaseClass::rfind(str), test_str.rindex_n(str, 3, 5) - 3); + str[0] = L'z'; + try { + const string_type::size_type pos = test_str.rindex_n(s, 20); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test_str.rindex_n(s, 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + + TEST_METHOD(rjust) + { + pcs::CppString s("abc"); + Assert::AreEqual("abc", s.rjust(1).c_str()); + Assert::AreEqual("abc", s.rjust(2).c_str()); + Assert::AreEqual("abc", s.rjust(3).c_str()); + Assert::AreEqual("abc ", s.rjust(4).c_str()); + Assert::AreEqual("abc ", s.rjust(5).c_str()); + Assert::AreEqual("abc", s.rjust(1).c_str()); + Assert::AreEqual("abc", s.rjust(2).c_str()); + Assert::AreEqual("abc", s.rjust(3).c_str()); + Assert::AreEqual("abc.", s.rjust(4, '.').c_str()); + Assert::AreEqual("abc..", s.rjust(5, '.').c_str()); + + pcs::CppWString ws(L"abc"); + Assert::AreEqual(L"abc", ws.rjust(1).c_str()); + Assert::AreEqual(L"abc", ws.rjust(2).c_str()); + Assert::AreEqual(L"abc", ws.rjust(3).c_str()); + Assert::AreEqual(L"abc ", ws.rjust(4).c_str()); + Assert::AreEqual(L"abc ", ws.rjust(5).c_str()); + Assert::AreEqual(L"abc", ws.rjust(1).c_str()); + Assert::AreEqual(L"abc", ws.rjust(2).c_str()); + Assert::AreEqual(L"abc", ws.rjust(3).c_str()); + Assert::AreEqual(L"abc.", ws.rjust(4, '.').c_str()); + Assert::AreEqual(L"abc..", ws.rjust(5, '.').c_str()); + } + + TEST_METHOD(rpartition) + { + pcs::CppString s("abcd#123efg#123hij"); + std::vector res{ s.rpartition("#123") }; + Assert::AreEqual("abcd#123efg", res[0].c_str()); + Assert::AreEqual("#123", res[1].c_str()); + Assert::AreEqual("hij", res[2].c_str()); + + s = "abcd#123fgh#123"; + res = s.rpartition("#123"); + Assert::AreEqual("abcd#123fgh", res[0].c_str()); + Assert::AreEqual("#123", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + + res = s.rpartition("XYZ"); + Assert::AreEqual("abcd#123fgh#123", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + + using namespace pcs; + res = ""_cs.rpartition("A"); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + + pcs::CppWString ws(L"abcd#123efg#123hij"); + std::vector wres{ ws.rpartition(L"#123") }; + Assert::AreEqual(L"abcd#123efg", wres[0].c_str()); + Assert::AreEqual(L"#123", wres[1].c_str()); + Assert::AreEqual(L"hij", wres[2].c_str()); + + ws = L"abcd#123fgh#123"; + wres = ws.rpartition(L"#123"); + Assert::AreEqual(L"abcd#123fgh", wres[0].c_str()); + Assert::AreEqual(L"#123", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + + wres = ws.rpartition(L"XYZ"); + Assert::AreEqual(L"abcd#123fgh#123", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + + wres = L""_cs.rpartition(L"A"); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + } + + TEST_METHOD(rsplit) + { + pcs::CppString s(" abcd efg hij klmn "); + std::vector res{ s.rsplit() }; + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.rsplit(0); + Assert::AreEqual(pcs::CppString::size_type(1), res.size()); + Assert::AreEqual(" abcd efg hij klmn ", res[0].c_str()); + + res = s.rsplit(1); + Assert::AreEqual(pcs::CppString::size_type(2), res.size()); + Assert::AreEqual(" abcd efg hij klmn ", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + + res = s.rsplit(2); + Assert::AreEqual(pcs::CppString::size_type(3), res.size()); + Assert::AreEqual(" abcd efg hij klmn", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + + res = s.rsplit(3); + Assert::AreEqual(pcs::CppString::size_type(4), res.size()); + Assert::AreEqual(" abcd efg hij", res[0].c_str()); + Assert::AreEqual("klmn", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + + res = s.rsplit(4); + Assert::AreEqual(pcs::CppString::size_type(5), res.size()); + Assert::AreEqual(" abcd efg ", res[0].c_str()); + Assert::AreEqual("hij", res[1].c_str()); + Assert::AreEqual("klmn", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + + res = s.rsplit(5); + Assert::AreEqual(pcs::CppString::size_type(6), res.size()); + Assert::AreEqual(" abcd efg ", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("hij", res[2].c_str()); + Assert::AreEqual("klmn", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + + res = s.rsplit(6); + Assert::AreEqual(pcs::CppString::size_type(7), res.size()); + Assert::AreEqual(" abcd efg", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + Assert::AreEqual("hij", res[3].c_str()); + Assert::AreEqual("klmn", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("", res[6].c_str()); + + res = s.rsplit(7); + Assert::AreEqual(pcs::CppString::size_type(8), res.size()); + Assert::AreEqual(" abcd", res[0].c_str()); + Assert::AreEqual("efg", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("hij", res[4].c_str()); + Assert::AreEqual("klmn", res[5].c_str()); + Assert::AreEqual("", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + + res = s.rsplit(8); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.rsplit(9); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.rsplit(10); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + s = pcs::CppString(5, ' '); //" "_cs; + res = s.rsplit(); + Assert::AreEqual(pcs::CppString::size_type(6), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + + + using namespace pcs; + s = " abcd#123efg#123hij #123#123klmn "_cs; + res = s.rsplit("#123"); + Assert::AreEqual(pcs::CppString::size_type(5), res.size()); + Assert::AreEqual(" abcd", res[0].c_str()); + Assert::AreEqual("efg", res[1].c_str()); + Assert::AreEqual("hij ", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("klmn ", res[4].c_str()); + + s = "#123#123abcd#123123efg#123hij #123#123klmn #123#123"_cs; + res = s.rsplit("#123"); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("123efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.rsplit("#123", 1); + Assert::AreEqual(pcs::CppString::size_type(2), res.size()); + Assert::AreEqual("#123#123abcd#123123efg#123hij #123#123klmn #123", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + + res = s.rsplit("#123", 2); + Assert::AreEqual(pcs::CppString::size_type(3), res.size()); + Assert::AreEqual("#123#123abcd#123123efg#123hij #123#123klmn ", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + + res = s.rsplit("#123", 3); + Assert::AreEqual(pcs::CppString::size_type(4), res.size()); + Assert::AreEqual("#123#123abcd#123123efg#123hij #123", res[0].c_str()); + Assert::AreEqual("klmn ", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + + res = s.rsplit("#123", 4); + Assert::AreEqual(pcs::CppString::size_type(5), res.size()); + Assert::AreEqual("#123#123abcd#123123efg#123hij ", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("klmn ", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + + res = s.rsplit("#123", 5); + Assert::AreEqual(pcs::CppString::size_type(6), res.size()); + Assert::AreEqual("#123#123abcd#123123efg", res[0].c_str()); + Assert::AreEqual("hij ", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + Assert::AreEqual("klmn ", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + + res = s.rsplit("#123", 6); + Assert::AreEqual(pcs::CppString::size_type(7), res.size()); + Assert::AreEqual("#123#123abcd", res[0].c_str()); + Assert::AreEqual("123efg", res[1].c_str()); + Assert::AreEqual("hij ", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("klmn ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("", res[6].c_str()); + + res = s.rsplit("#123", 7); + Assert::AreEqual(pcs::CppString::size_type(8), res.size()); + Assert::AreEqual("#123", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("123efg", res[2].c_str()); + Assert::AreEqual("hij ", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("klmn ", res[5].c_str()); + Assert::AreEqual("", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + + res = s.rsplit("#123", 8); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("123efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.rsplit("#123", 9); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("123efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.rsplit("#123", 10); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("123efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + + pcs::CppWString ws(L" abcd efg hij klmn "); + std::vector wres{ ws.rsplit() }; + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.rsplit(0); + Assert::AreEqual(pcs::CppWString::size_type(1), wres.size()); + Assert::AreEqual(L" abcd efg hij klmn ", wres[0].c_str()); + + wres = ws.rsplit(1); + Assert::AreEqual(pcs::CppWString::size_type(2), wres.size()); + Assert::AreEqual(L" abcd efg hij klmn ", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + + wres = ws.rsplit(2); + Assert::AreEqual(pcs::CppWString::size_type(3), wres.size()); + Assert::AreEqual(L" abcd efg hij klmn", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + + wres = ws.rsplit(3); + Assert::AreEqual(pcs::CppWString::size_type(4), wres.size()); + Assert::AreEqual(L" abcd efg hij", wres[0].c_str()); + Assert::AreEqual(L"klmn", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + + wres = ws.rsplit(4); + Assert::AreEqual(pcs::CppWString::size_type(5), wres.size()); + Assert::AreEqual(L" abcd efg ", wres[0].c_str()); + Assert::AreEqual(L"hij", wres[1].c_str()); + Assert::AreEqual(L"klmn", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + + wres = ws.rsplit(5); + Assert::AreEqual(pcs::CppWString::size_type(6), wres.size()); + Assert::AreEqual(L" abcd efg ", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"hij", wres[2].c_str()); + Assert::AreEqual(L"klmn", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + + wres = ws.rsplit(6); + Assert::AreEqual(pcs::CppWString::size_type(7), wres.size()); + Assert::AreEqual(L" abcd efg", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + Assert::AreEqual(L"hij", wres[3].c_str()); + Assert::AreEqual(L"klmn", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"", wres[6].c_str()); + + wres = ws.rsplit(7); + Assert::AreEqual(pcs::CppWString::size_type(8), wres.size()); + Assert::AreEqual(L" abcd", wres[0].c_str()); + Assert::AreEqual(L"efg", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"hij", wres[4].c_str()); + Assert::AreEqual(L"klmn", wres[5].c_str()); + Assert::AreEqual(L"", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + + wres = ws.rsplit(8); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.rsplit(9); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.rsplit(10); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + ws = pcs::CppWString(5, ' '); //L" "_cs; + wres = ws.rsplit(); + Assert::AreEqual(pcs::CppWString::size_type(6), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + + ws = L" abcd#123efg#123hij #123#123klmn "_cs; + wres = ws.rsplit(L"#123"); + Assert::AreEqual(pcs::CppWString::size_type(5), wres.size()); + Assert::AreEqual(L" abcd", wres[0].c_str()); + Assert::AreEqual(L"efg", wres[1].c_str()); + Assert::AreEqual(L"hij ", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"klmn ", wres[4].c_str()); + + ws = L"#123#123abcd#123123efg#123hij #123#123klmn #123#123"_cs; + wres = ws.rsplit(L"#123"); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"123efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.rsplit(L"#123", 1); + Assert::AreEqual(pcs::CppWString::size_type(2), wres.size()); + Assert::AreEqual(L"#123#123abcd#123123efg#123hij #123#123klmn #123", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + + wres = ws.rsplit(L"#123", 2); + Assert::AreEqual(pcs::CppWString::size_type(3), wres.size()); + Assert::AreEqual(L"#123#123abcd#123123efg#123hij #123#123klmn ", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + + wres = ws.rsplit(L"#123", 3); + Assert::AreEqual(pcs::CppWString::size_type(4), wres.size()); + Assert::AreEqual(L"#123#123abcd#123123efg#123hij #123", wres[0].c_str()); + Assert::AreEqual(L"klmn ", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + + wres = ws.rsplit(L"#123", 4); + Assert::AreEqual(pcs::CppWString::size_type(5), wres.size()); + Assert::AreEqual(L"#123#123abcd#123123efg#123hij ", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"klmn ", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + + wres = ws.rsplit(L"#123", 5); + Assert::AreEqual(pcs::CppWString::size_type(6), wres.size()); + Assert::AreEqual(L"#123#123abcd#123123efg", wres[0].c_str()); + Assert::AreEqual(L"hij ", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + Assert::AreEqual(L"klmn ", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + + wres = ws.rsplit(L"#123", 6); + Assert::AreEqual(pcs::CppWString::size_type(7), wres.size()); + Assert::AreEqual(L"#123#123abcd", wres[0].c_str()); + Assert::AreEqual(L"123efg", wres[1].c_str()); + Assert::AreEqual(L"hij ", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"klmn ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"", wres[6].c_str()); + + wres = ws.rsplit(L"#123", 7); + Assert::AreEqual(pcs::CppWString::size_type(8), wres.size()); + Assert::AreEqual(L"#123", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"123efg", wres[2].c_str()); + Assert::AreEqual(L"hij ", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"klmn ", wres[5].c_str()); + Assert::AreEqual(L"", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + + wres = ws.rsplit(L"#123", 8); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"123efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.rsplit(L"#123", 9); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"123efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.rsplit(L"#123", 10); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"123efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + } + + TEST_METHOD(rstrip) + { + pcs::CppString s(" abcd efg "); + pcs::CppString sres{ s.rstrip() }; + Assert::AreEqual(" abcd efg", sres.c_str()); + + using namespace pcs; + s = " abcd efg hij"_cs; + sres = s.rstrip(); + Assert::AreEqual(" abcd efg hij", sres.c_str()); + + s = ""_cs; + sres = s.rstrip(); + Assert::AreEqual("", sres.c_str()); + + s = " "_cs; + sres = s.rstrip(); + Assert::AreEqual("", sres.c_str()); + + s = "#124abcd#124efg#1241#24#142"_cs; + sres = s.rstrip("#124"); + Assert::AreEqual("#124abcd#124efg", sres.c_str()); + + s = "#124abcd#124efg#124#124hij"_cs; + sres = s.rstrip("#124"); + Assert::AreEqual("#124abcd#124efg#124#124hij", sres.c_str()); + + s = "#124#142#241124#421#"; + sres = s.rstrip("#124"); + Assert::AreEqual("", sres.c_str()); + + pcs::CppWString ws(L" abcd efg "); + pcs::CppWString wsres{ ws.rstrip() }; + Assert::AreEqual(L" abcd efg", wsres.c_str()); + + ws = L" abcd efg hij"_cs; + wsres = ws.rstrip(); + Assert::AreEqual(L" abcd efg hij", wsres.c_str()); + + ws = L""_cs; + wsres = ws.rstrip(); + Assert::AreEqual(L"", wsres.c_str()); + + ws = L" "_cs; + wsres = ws.rstrip(); + Assert::AreEqual(L"", wsres.c_str()); + + ws = L"#124abcd#124efg#124#124#124"_cs; + wsres = ws.rstrip(L"#124"); + Assert::AreEqual(L"#124abcd#124efg", wsres.c_str()); + + ws = L"#124abcd#124efg#124#124hij"_cs; + wsres = ws.rstrip(L"#124"); + Assert::AreEqual(L"#124abcd#124efg#124#124hij", wsres.c_str()); + + ws = L"#124#124#124#124#124"; + wsres = ws.rstrip(L"#124"); + Assert::AreEqual(L"", wsres.c_str()); + } + + TEST_METHOD(split) + { + pcs::CppString s(" abcd efg hij klmn "); + std::vector res{ s.rsplit() }; + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.split(0); + Assert::AreEqual(pcs::CppString::size_type(1), res.size()); + Assert::AreEqual(" abcd efg hij klmn ", res[0].c_str()); + + res = s.split(1); + Assert::AreEqual(pcs::CppString::size_type(2), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd efg hij klmn ", res[1].c_str()); + + res = s.split(2); + Assert::AreEqual(pcs::CppString::size_type(3), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg hij klmn ", res[2].c_str()); + + res = s.split(3); + Assert::AreEqual(pcs::CppString::size_type(4), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual(" hij klmn ", res[3].c_str()); + + res = s.split(4); + Assert::AreEqual(pcs::CppString::size_type(5), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual(" hij klmn ", res[4].c_str()); + + res = s.split(5); + Assert::AreEqual(pcs::CppString::size_type(6), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij klmn ", res[5].c_str()); + + res = s.split(6); + Assert::AreEqual(pcs::CppString::size_type(7), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + + res = s.split(7); + Assert::AreEqual(pcs::CppString::size_type(8), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn", res[6].c_str()); + Assert::AreEqual(" ", res[7].c_str()); + + res = s.split(8); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.split(9); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.split(10); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("abcd", res[1].c_str()); + Assert::AreEqual("efg", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("hij", res[5].c_str()); + Assert::AreEqual("klmn", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + s = pcs::CppString(5, ' '); + res = s.split(); + Assert::AreEqual(pcs::CppString::size_type(6), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + + + using namespace pcs; + s = " abcd#124efg#124hij #124#124klmn "_cs; + res = s.split("#124"); + Assert::AreEqual(" abcd", res[0].c_str()); + Assert::AreEqual("efg", res[1].c_str()); + Assert::AreEqual("hij ", res[2].c_str()); + Assert::AreEqual("", res[3].c_str()); + Assert::AreEqual("klmn ", res[4].c_str()); + + s = "#124#124abcd#124124efg#124hij #124#124klmn #124#124"_cs; + res = s.split("#124"); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("124efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.split("#124", 1); + Assert::AreEqual(pcs::CppString::size_type(2), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("#124abcd#124124efg#124hij #124#124klmn #124#124", res[1].c_str()); + + res = s.split("#124", 2); + Assert::AreEqual(pcs::CppString::size_type(3), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd#124124efg#124hij #124#124klmn #124#124", res[2].c_str()); + + res = s.split("#124", 3); + Assert::AreEqual(pcs::CppString::size_type(4), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("124efg#124hij #124#124klmn #124#124", res[3].c_str()); + + res = s.split("#124", 4); + Assert::AreEqual(pcs::CppString::size_type(5), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("124efg", res[3].c_str()); + Assert::AreEqual("hij #124#124klmn #124#124", res[4].c_str()); + + res = s.split("#124", 5); + Assert::AreEqual(pcs::CppString::size_type(6), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("124efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("#124klmn #124#124", res[5].c_str()); + + res = s.split("#124", 6); + Assert::AreEqual(pcs::CppString::size_type(7), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("124efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn #124#124", res[6].c_str()); + + res = s.split("#124", 7); + Assert::AreEqual(pcs::CppString::size_type(8), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("124efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + Assert::AreEqual("#124", res[7].c_str()); + + res = s.split("#124", 8); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("124efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.split("#124", 9); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("124efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + res = s.split("#124", 10); + Assert::AreEqual(pcs::CppString::size_type(9), res.size()); + Assert::AreEqual("", res[0].c_str()); + Assert::AreEqual("", res[1].c_str()); + Assert::AreEqual("abcd", res[2].c_str()); + Assert::AreEqual("124efg", res[3].c_str()); + Assert::AreEqual("hij ", res[4].c_str()); + Assert::AreEqual("", res[5].c_str()); + Assert::AreEqual("klmn ", res[6].c_str()); + Assert::AreEqual("", res[7].c_str()); + Assert::AreEqual("", res[8].c_str()); + + + pcs::CppWString ws(L" abcd efg hij klmn "); + std::vector wres{ ws.split() }; + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.split(0); + Assert::AreEqual(pcs::CppWString::size_type(1), wres.size()); + Assert::AreEqual(L" abcd efg hij klmn ", wres[0].c_str()); + + wres = ws.split(1); + Assert::AreEqual(pcs::CppWString::size_type(2), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd efg hij klmn ", wres[1].c_str()); + + + wres = ws.split(2); + Assert::AreEqual(pcs::CppWString::size_type(3), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg hij klmn ", wres[2].c_str()); + + wres = ws.split(3); + Assert::AreEqual(pcs::CppWString::size_type(4), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L" hij klmn ", wres[3].c_str()); + + wres = ws.split(4); + Assert::AreEqual(pcs::CppWString::size_type(5), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L" hij klmn ", wres[4].c_str()); + + wres = ws.split(5); + Assert::AreEqual(pcs::CppWString::size_type(6), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij klmn ", wres[5].c_str()); + + wres = ws.split(6); + Assert::AreEqual(pcs::CppWString::size_type(7), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + + wres = ws.split(7); + Assert::AreEqual(pcs::CppWString::size_type(8), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn", wres[6].c_str()); + Assert::AreEqual(L" ", wres[7].c_str()); + + wres = ws.split(8); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.split(9); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.split(10); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"abcd", wres[1].c_str()); + Assert::AreEqual(L"efg", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"hij", wres[5].c_str()); + Assert::AreEqual(L"klmn", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + ws = pcs::CppWString(5, ' '); //L" "_cs; + wres = ws.split(); + Assert::AreEqual(pcs::CppWString::size_type(6), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + + ws = L" abcd#124efg#124hij #124#124klmn "_cs; + wres = ws.split(L"#124"); + Assert::AreEqual(L" abcd", wres[0].c_str()); + Assert::AreEqual(L"efg", wres[1].c_str()); + Assert::AreEqual(L"hij ", wres[2].c_str()); + Assert::AreEqual(L"", wres[3].c_str()); + Assert::AreEqual(L"klmn ", wres[4].c_str()); + + ws = L"#124#124abcd#124124efg#124hij #124#124klmn #124#124"_cs; + wres = ws.split(L"#124"); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"124efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.split(L"#124", 1); + Assert::AreEqual(pcs::CppWString::size_type(2), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"#124abcd#124124efg#124hij #124#124klmn #124#124", wres[1].c_str()); + + wres = ws.split(L"#124", 2); + Assert::AreEqual(pcs::CppWString::size_type(3), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd#124124efg#124hij #124#124klmn #124#124", wres[2].c_str()); + + wres = ws.split(L"#124", 3); + Assert::AreEqual(pcs::CppWString::size_type(4), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"124efg#124hij #124#124klmn #124#124", wres[3].c_str()); + + wres = ws.split(L"#124", 4); + Assert::AreEqual(pcs::CppWString::size_type(5), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"124efg", wres[3].c_str()); + Assert::AreEqual(L"hij #124#124klmn #124#124", wres[4].c_str()); + + wres = ws.split(L"#124", 5); + Assert::AreEqual(pcs::CppWString::size_type(6), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"124efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"#124klmn #124#124", wres[5].c_str()); + + wres = ws.split(L"#124", 6); + Assert::AreEqual(pcs::CppWString::size_type(7), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"124efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn #124#124", wres[6].c_str()); + + wres = ws.split(L"#124", 7); + Assert::AreEqual(pcs::CppWString::size_type(8), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"124efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + Assert::AreEqual(L"#124", wres[7].c_str()); + + wres = ws.split(L"#124", 8); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"124efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.split(L"#124", 9); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"124efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + + wres = ws.split(L"#124", 10); + Assert::AreEqual(pcs::CppWString::size_type(9), wres.size()); + Assert::AreEqual(L"", wres[0].c_str()); + Assert::AreEqual(L"", wres[1].c_str()); + Assert::AreEqual(L"abcd", wres[2].c_str()); + Assert::AreEqual(L"124efg", wres[3].c_str()); + Assert::AreEqual(L"hij ", wres[4].c_str()); + Assert::AreEqual(L"", wres[5].c_str()); + Assert::AreEqual(L"klmn ", wres[6].c_str()); + Assert::AreEqual(L"", wres[7].c_str()); + Assert::AreEqual(L"", wres[8].c_str()); + } + + TEST_METHOD(splitline) + { +#pragma warning(push) +#pragma warning(disable: 4566) // to get no warning when current page code is not compatible with next unicode points + { + pcs::CppString wtext{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r" }; + std::vector lines{ wtext.splitlines() }; + std::vector expected{ "", "abc", "cde", "efg", "ghi", "ijk", "klm", "mno", "", "opq", "qrs", "stu", "uvw", "wxy", "zzz", "." }; + auto exp_it{ expected.cbegin() }; + auto lin_it{ lines.cbegin() }; + for (; lin_it != lines.cend() && exp_it != expected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != lines.cend()); + Assert::IsFalse(exp_it != expected.cend()); + } + + { + pcs::CppString wtext{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r\n" }; + std::vector lines{ wtext.splitlines() }; + std::vector expected{ "", "abc", "cde", "efg", "ghi", "ijk", "klm", "mno", "", "opq", "qrs", "stu", "uvw", "wxy", "zzz", "." }; + auto exp_it{ expected.cbegin() }; + auto lin_it{ lines.cbegin() }; + for (; lin_it != lines.cend() && exp_it != expected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != lines.cend()); + Assert::IsFalse(exp_it != expected.cend()); + } + + { + pcs::CppString wtext{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\n\r" }; + std::vector lines{ wtext.splitlines() }; + std::vector expected{ "", "abc", "cde", "efg", "ghi", "ijk", "klm", "mno", "", "opq", "qrs", "stu", "uvw", "wxy", "zzz", ".", "" }; + auto exp_it{ expected.cbegin() }; + auto lin_it{ lines.cbegin() }; + for (; lin_it != lines.cend() && exp_it != expected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != lines.cend()); + Assert::IsFalse(exp_it != expected.cend()); + } + + { + pcs::CppString wtext{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r" }; + std::vector lines{ wtext.splitlines(true) }; + std::vector expected{ + "\v", "abc\013", "cde\f", "efg\x0c", "ghi\x1c", "ijk\x1d", "klm\x1d", "mno\r\n", + "\n", "opq\r", "qrs\v", "stu\r", "uvw\n", "wxy\r\n", "zzz\x0c", ".\r" + }; + auto exp_it{ expected.cbegin() }; + auto lin_it{ lines.cbegin() }; + for (; lin_it != lines.cend() && exp_it != expected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != lines.cend()); + Assert::IsFalse(exp_it != expected.cend()); + } + + { + pcs::CppString wtext{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r\n" }; + std::vector lines{ wtext.splitlines(true) }; + std::vector expected{ + "\v", "abc\013", "cde\f", "efg\x0c", "ghi\x1c", "ijk\x1d", "klm\x1d", "mno\r\n", + "\n", "opq\r", "qrs\v", "stu\r", "uvw\n", "wxy\r\n", "zzz\x0c", ".\r\n" + }; + auto exp_it{ expected.cbegin() }; + auto lin_it{ lines.cbegin() }; + for (; lin_it != lines.cend() && exp_it != expected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != lines.cend()); + Assert::IsFalse(exp_it != expected.cend()); + } + + { + pcs::CppString wtext{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\n\r" }; + std::vector lines{ wtext.splitlines(true) }; + std::vector expected{ + "\v", "abc\013", "cde\f", "efg\x0c", "ghi\x1c", "ijk\x1d", "klm\x1d", "mno\r\n", + "\n", "opq\r", "qrs\v", "stu\r", "uvw\n", "wxy\r\n", "zzz\x0c", ".\n", "\r" + }; + auto exp_it{ expected.cbegin() }; + auto lin_it{ lines.cbegin() }; + for (; lin_it != lines.cend() && exp_it != expected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != lines.cend()); + Assert::IsFalse(exp_it != expected.cend()); + } + + + { + pcs::CppWString wtext{ L"\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r" }; + std::vector wlines{ wtext.splitlines() }; + std::vector wexpected{ L"", L"abc", L"cde", L"efg", L"ghi", L"ijk", L"klm", L"mno", L"", L"opq", L"qrs", L"stu", L"uvw", L"wxy", L"zzz", L"."}; + auto exp_it{ wexpected.cbegin() }; + auto lin_it{ wlines.cbegin() }; + for (; lin_it != wlines.cend() && exp_it != wexpected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != wlines.cend()); + Assert::IsFalse(exp_it != wexpected.cend()); + } + + { + pcs::CppWString wtext{ L"\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r\n" }; + std::vector wlines{ wtext.splitlines() }; + std::vector wexpected{ L"", L"abc", L"cde", L"efg", L"ghi", L"ijk", L"klm", L"mno", L"", L"opq", L"qrs", L"stu", L"uvw", L"wxy", L"zzz", L"."}; + auto exp_it{ wexpected.cbegin() }; + auto lin_it{ wlines.cbegin() }; + for (; lin_it != wlines.cend() && exp_it != wexpected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != wlines.cend()); + Assert::IsFalse(exp_it != wexpected.cend()); + } + + { + pcs::CppWString wtext{ L"\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\n\r" }; + std::vector wlines{ wtext.splitlines() }; + std::vector wexpected{ L"", L"abc", L"cde", L"efg", L"ghi", L"ijk", L"klm", L"mno", L"", L"opq", L"qrs", L"stu", L"uvw", L"wxy", L"zzz", L".", L""}; + auto exp_it{ wexpected.cbegin() }; + auto lin_it{ wlines.cbegin() }; + for (; lin_it != wlines.cend() && exp_it != wexpected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != wlines.cend()); + Assert::IsFalse(exp_it != wexpected.cend()); + } + + { + pcs::CppWString wtext{ L"\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r" }; + std::vector wlines{ wtext.splitlines(true) }; + std::vector wexpected{ + L"\v", L"abc\013", L"cde\f", L"efg\x0c", L"ghi\x1c", L"ijk\x1d", L"klm\x1d", L"mno\r\n", + L"\n", L"opq\r", L"qrs\v", L"stu\r", L"uvw\n", L"wxy\r\n", L"zzz\x0c", L".\r" + }; + auto exp_it{ wexpected.cbegin() }; + auto lin_it{ wlines.cbegin() }; + for (; lin_it != wlines.cend() && exp_it != wexpected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != wlines.cend()); + Assert::IsFalse(exp_it != wexpected.cend()); + } + + { + pcs::CppWString wtext{ L"\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r\n" }; + std::vector wlines{ wtext.splitlines(true) }; + std::vector wexpected{ + L"\v", L"abc\013", L"cde\f", L"efg\x0c", L"ghi\x1c", L"ijk\x1d", L"klm\x1d", L"mno\r\n", + L"\n", L"opq\r", L"qrs\v", L"stu\r", L"uvw\n", L"wxy\r\n", L"zzz\x0c", L".\r\n" + }; + auto exp_it{ wexpected.cbegin() }; + auto lin_it{ wlines.cbegin() }; + for (; lin_it != wlines.cend() && exp_it != wexpected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != wlines.cend()); + Assert::IsFalse(exp_it != wexpected.cend()); + } + + { + pcs::CppWString wtext{ L"\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\n\r" }; + std::vector wlines{ wtext.splitlines(true) }; + std::vector wexpected{ + L"\v", L"abc\013", L"cde\f", L"efg\x0c", L"ghi\x1c", L"ijk\x1d", L"klm\x1d", L"mno\r\n", + L"\n", L"opq\r", L"qrs\v", L"stu\r", L"uvw\n", L"wxy\r\n", L"zzz\x0c", L".\n", L"\r" + }; + auto exp_it{ wexpected.cbegin() }; + auto lin_it{ wlines.cbegin() }; + for (; lin_it != wlines.cend() && exp_it != wexpected.cend(); ++lin_it, ++exp_it) { + Assert::AreEqual(exp_it->c_str(), lin_it->c_str()); + } + Assert::IsFalse(lin_it != wlines.cend()); + Assert::IsFalse(exp_it != wexpected.cend()); + } + +#pragma warning(pop) + + } + + TEST_METHOD(startswith) + { + pcs::CppString text("Abcdef"); + const size_t len{ text.size() }; + + Assert::IsTrue(text.startswith("A")); + Assert::IsTrue(text.startswith("Ab")); + Assert::IsTrue(text.startswith("Abc")); + Assert::IsTrue(text.startswith("Abcd")); + Assert::IsTrue(text.startswith("Abcde")); + Assert::IsTrue(text.startswith("Abcdef")); + Assert::IsFalse(text.startswith("Abcdefg")); + Assert::IsFalse(text.startswith("a")); + Assert::IsFalse(text.startswith("def")); + + Assert::IsTrue(text.startswith("b", 1)); + Assert::IsTrue(text.startswith("bc", 1)); + Assert::IsTrue(text.startswith("bcd", 1)); + Assert::IsFalse(text.startswith("bcdefg", 1)); + Assert::IsFalse(text.startswith("A", 1)); + Assert::IsFalse(text.startswith("def", 1)); + + Assert::IsTrue(text.startswith("c", 2)); + Assert::IsTrue(text.startswith("cd", 2)); + Assert::IsTrue(text.startswith("cde", 2)); + Assert::IsFalse(text.startswith("cdefg", 2)); + Assert::IsFalse(text.startswith("Ab", 2)); + Assert::IsFalse(text.startswith("def", 2)); + + Assert::IsTrue(text.startswith("d", 3)); + Assert::IsTrue(text.startswith("de", 3)); + Assert::IsTrue(text.startswith("def", 3)); + Assert::IsFalse(text.startswith("defg", 3)); + Assert::IsFalse(text.startswith("Abc", 3)); + Assert::IsFalse(text.startswith("ef", 3)); + + Assert::IsTrue(text.startswith("e", 4)); + Assert::IsTrue(text.startswith("ef", 4)); + Assert::IsFalse(text.startswith("efg", 4)); + Assert::IsFalse(text.startswith("Abcd", 4)); + Assert::IsFalse(text.startswith("f", 4)); + + Assert::IsTrue(text.startswith("f", 5)); + Assert::IsFalse(text.startswith("fg", 5)); + Assert::IsFalse(text.startswith("Abcde", 5)); + Assert::IsFalse(text.startswith("g", 5)); + + Assert::IsTrue(text.startswith("A", 0, 0)); + Assert::IsFalse(text.startswith("b", 0, 0)); + Assert::IsTrue(text.startswith("b", 1, 3)); + Assert::IsTrue(text.startswith("bc", 1, 3)); + Assert::IsTrue(text.startswith("bcd", 1, 3)); + Assert::IsFalse(text.startswith("bcde", 1, 3)); + + Assert::IsTrue(text.startswith("", 5, 2)); + Assert::IsTrue(text.startswith("", 15, 16)); + + Assert::IsTrue(text.startswith({ "ghi", "abca", "Abcd" }, 0, len - 2)); + Assert::IsFalse(text.startswith({ "def", "ghi" }, 0, len - 4)); + Assert::IsFalse(text.startswith({ "def", "ghi", "Abcd" }, 0, len - 4)); + + + pcs::CppWString wtext(L"Abcdef"); + + Assert::IsTrue(wtext.startswith(L"A")); + Assert::IsTrue(wtext.startswith(L"Ab")); + Assert::IsTrue(wtext.startswith(L"Abc")); + Assert::IsTrue(wtext.startswith(L"Abcd")); + Assert::IsTrue(wtext.startswith(L"Abcde")); + Assert::IsTrue(wtext.startswith(L"Abcdef")); + Assert::IsFalse(wtext.startswith(L"Abcdefg")); + Assert::IsFalse(wtext.startswith(L"a")); + Assert::IsFalse(wtext.startswith(L"def")); + + Assert::IsTrue(wtext.startswith(L"b", 1)); + Assert::IsTrue(wtext.startswith(L"bc", 1)); + Assert::IsTrue(wtext.startswith(L"bcd", 1)); + Assert::IsFalse(wtext.startswith(L"bcdefg", 1)); + Assert::IsFalse(wtext.startswith(L"A", 1)); + Assert::IsFalse(wtext.startswith(L"def", 1)); + + Assert::IsTrue(wtext.startswith(L"c", 2)); + Assert::IsTrue(wtext.startswith(L"cd", 2)); + Assert::IsTrue(wtext.startswith(L"cde", 2)); + Assert::IsFalse(wtext.startswith(L"cdefg", 2)); + Assert::IsFalse(wtext.startswith(L"Ab", 2)); + Assert::IsFalse(wtext.startswith(L"def", 2)); + + Assert::IsTrue(wtext.startswith(L"d", 3)); + Assert::IsTrue(wtext.startswith(L"de", 3)); + Assert::IsTrue(wtext.startswith(L"def", 3)); + Assert::IsFalse(wtext.startswith(L"defg", 3)); + Assert::IsFalse(wtext.startswith(L"Abc", 3)); + Assert::IsFalse(wtext.startswith(L"ef", 3)); + + Assert::IsTrue(wtext.startswith(L"e", 4)); + Assert::IsTrue(wtext.startswith(L"ef", 4)); + Assert::IsFalse(wtext.startswith(L"efg", 4)); + Assert::IsFalse(wtext.startswith(L"Abcd", 4)); + Assert::IsFalse(wtext.startswith(L"f", 4)); + + Assert::IsTrue(wtext.startswith(L"f", 5)); + Assert::IsFalse(wtext.startswith(L"fg", 5)); + Assert::IsFalse(wtext.startswith(L"Abcde", 5)); + Assert::IsFalse(wtext.startswith(L"g", 5)); + + Assert::IsTrue(wtext.startswith(L"A", 0, 0)); + Assert::IsFalse(wtext.startswith(L"b", 0, 0)); + Assert::IsTrue(wtext.startswith(L"b", 1, 3)); + Assert::IsTrue(wtext.startswith(L"bc", 1, 3)); + Assert::IsTrue(wtext.startswith(L"bcd", 1, 3)); + Assert::IsFalse(wtext.startswith(L"bcde", 1, 3)); + + Assert::IsTrue(wtext.startswith(L"", 5, 2)); + Assert::IsTrue(wtext.startswith(L"", 15, 16)); + + Assert::IsTrue(wtext.startswith({ L"ghi", L"abca", L"Abcd" }, 0, len - 2)); + Assert::IsFalse(wtext.startswith({ L"def", L"ghi" }, 0, len - 4)); + Assert::IsFalse(wtext.startswith({ L"def", L"ghi", L"Abcd" }, 0, len - 4)); + } + + TEST_METHOD(startswith_n) + { + pcs::CppString text("Abcdef"); + const size_t len{ text.size() }; + + Assert::IsTrue(text.startswith_n("A", 2)); + Assert::IsTrue(text.startswith_n("Ab", 2)); + Assert::IsTrue(text.startswith_n("Abc", 3)); + Assert::IsTrue(text.startswith_n("Abcd", 5)); + Assert::IsTrue(text.startswith_n("Abcde", 5)); + Assert::IsTrue(text.startswith_n("Abcdef", 7)); + Assert::IsFalse(text.startswith_n("Abcdefg", 11)); + Assert::IsFalse(text.startswith_n("a", 2)); + Assert::IsFalse(text.startswith_n("def", len)); + + Assert::IsTrue(text.startswith_n("b", 1, 1)); + Assert::IsTrue(text.startswith_n("bc", 1, 3)); + Assert::IsTrue(text.startswith_n("bcd", 1, 3)); + Assert::IsFalse(text.startswith_n("bcdefg", 1, 5)); + Assert::IsFalse(text.startswith_n("A", 1, 8)); + Assert::IsFalse(text.startswith_n("def", 1, 2)); + + Assert::IsTrue(text.startswith_n("c", 2, 1)); + Assert::IsTrue(text.startswith_n("cd", 2, 2)); + Assert::IsTrue(text.startswith_n("cde", 2, 4)); + Assert::IsFalse(text.startswith_n("cdefg", 2, 6)); + Assert::IsFalse(text.startswith_n("Ab", 2, 2)); + Assert::IsFalse(text.startswith_n("def", 2, 5)); + + Assert::IsTrue(text.startswith_n("d", 3, 2)); + Assert::IsTrue(text.startswith_n("de", 3, 2)); + Assert::IsTrue(text.startswith_n("def", 3, 4)); + Assert::IsFalse(text.startswith_n("defg", 3, 5)); + Assert::IsFalse(text.startswith_n("Abc", 3, 1)); + Assert::IsFalse(text.startswith_n("ef", 3, 2)); + + Assert::IsTrue(text.startswith_n("e", 4, 1)); + Assert::IsTrue(text.startswith_n("ef", 4, 3)); + Assert::IsFalse(text.startswith_n("efg", 4, 5)); + Assert::IsFalse(text.startswith_n("Abcd", 4, 7)); + Assert::IsFalse(text.startswith_n("f", 4, 9)); + + Assert::IsTrue(text.startswith_n("f", 5, 2)); + Assert::IsFalse(text.startswith_n("fg", 5, 1)); + Assert::IsFalse(text.startswith_n("Abcde", 5, 8)); + Assert::IsFalse(text.startswith_n("g", 5, 11)); + + Assert::IsTrue(text.startswith_n("A", 0, 1)); + Assert::IsFalse(text.startswith_n("b", 0, 2)); + Assert::IsTrue(text.startswith_n("b", 1, 3)); + Assert::IsTrue(text.startswith_n("bc", 1, 3)); + Assert::IsTrue(text.startswith_n("bcd", 1, 3)); + Assert::IsFalse(text.startswith_n("bcde", 1, 3)); + + Assert::IsTrue(text.startswith_n("", 5, 2)); + Assert::IsTrue(text.startswith_n("", 15, 16)); + + Assert::IsTrue(text.startswith_n({ "ghi", "abca", "Abcd" }, 0, len - 2)); + Assert::IsFalse(text.startswith_n({ "def", "ghi" }, 0, len - 4)); + Assert::IsFalse(text.startswith_n({ "def", "ghi", "Abcd" }, 0, len - 4)); + + + pcs::CppWString wtext(L"Abcdef"); + const size_t wlen{ wtext.size() }; + + Assert::IsTrue(wtext.startswith_n(L"A", 2)); + Assert::IsTrue(wtext.startswith_n(L"Ab", 2)); + Assert::IsTrue(wtext.startswith_n(L"Abc", 3)); + Assert::IsTrue(wtext.startswith_n(L"Abcd", 5)); + Assert::IsTrue(wtext.startswith_n(L"Abcde", 5)); + Assert::IsTrue(wtext.startswith_n(L"Abcdef", 7)); + Assert::IsFalse(wtext.startswith_n(L"Abcdefg", 11)); + Assert::IsFalse(wtext.startswith_n(L"a", 2)); + Assert::IsFalse(wtext.startswith_n(L"def", wlen)); + + Assert::IsTrue(wtext.startswith_n(L"b", 1, 1)); + Assert::IsTrue(wtext.startswith_n(L"bc", 1, 3)); + Assert::IsTrue(wtext.startswith_n(L"bcd", 1, 3)); + Assert::IsFalse(wtext.startswith_n(L"bcdefg", 1, 5)); + Assert::IsFalse(wtext.startswith_n(L"A", 1, 8)); + Assert::IsFalse(wtext.startswith_n(L"def", 1, 2)); + + Assert::IsTrue(wtext.startswith_n(L"c", 2, 1)); + Assert::IsTrue(wtext.startswith_n(L"cd", 2, 2)); + Assert::IsTrue(wtext.startswith_n(L"cde", 2, 4)); + Assert::IsFalse(wtext.startswith_n(L"cdefg", 2, 6)); + Assert::IsFalse(wtext.startswith_n(L"Ab", 2, 2)); + Assert::IsFalse(wtext.startswith_n(L"def", 2, 5)); + + Assert::IsTrue(wtext.startswith_n(L"d", 3, 2)); + Assert::IsTrue(wtext.startswith_n(L"de", 3, 2)); + Assert::IsTrue(wtext.startswith_n(L"def", 3, 4)); + Assert::IsFalse(wtext.startswith_n(L"defg", 3, 5)); + Assert::IsFalse(wtext.startswith_n(L"Abc", 3, 1)); + Assert::IsFalse(wtext.startswith_n(L"ef", 3, 2)); + + Assert::IsTrue(wtext.startswith_n(L"e", 4, 1)); + Assert::IsTrue(wtext.startswith_n(L"ef", 4, 3)); + Assert::IsFalse(wtext.startswith_n(L"efg", 4, 5)); + Assert::IsFalse(wtext.startswith_n(L"Abcd", 4, 7)); + Assert::IsFalse(wtext.startswith_n(L"f", 4, 9)); + + Assert::IsTrue(wtext.startswith_n(L"f", 5, 2)); + Assert::IsFalse(wtext.startswith_n(L"fg", 5, 1)); + Assert::IsFalse(wtext.startswith_n(L"Abcde", 5, 8)); + Assert::IsFalse(wtext.startswith_n(L"g", 5, 11)); + + Assert::IsTrue(wtext.startswith_n(L"A", 0, 1)); + Assert::IsFalse(wtext.startswith_n(L"b", 0, 2)); + Assert::IsTrue(wtext.startswith_n(L"b", 1, 3)); + Assert::IsTrue(wtext.startswith_n(L"bc", 1, 3)); + Assert::IsTrue(wtext.startswith_n(L"bcd", 1, 3)); + Assert::IsFalse(wtext.startswith_n(L"bcde", 1, 3)); + + Assert::IsTrue(wtext.startswith_n(L"", 5, 2)); + Assert::IsTrue(wtext.startswith_n(L"", 15, 16)); + + Assert::IsTrue(wtext.startswith_n({ L"ghi", L"abca", L"Abcd" }, 0, wlen - 2)); + Assert::IsFalse(wtext.startswith_n({ L"def", L"ghi" }, 0, wlen - 4)); + Assert::IsFalse(wtext.startswith_n({ L"def", L"ghi", L"Abcd" }, 0, wlen - 4)); + } + + TEST_METHOD(strip) + { + pcs::CppString text("abcdefedcbaea"); + + Assert::AreEqual("bcdefedcbae", text.strip("a").c_str()); + Assert::AreEqual("cdefedcbae", text.strip("ba").c_str()); + Assert::AreEqual("defedcbae", text.strip("acb").c_str()); + Assert::AreEqual("efedcbae", text.strip("dacb").c_str()); + Assert::AreEqual("f", text.strip("abcde").c_str()); + Assert::AreEqual("bcdefedcb", text.strip("ea").c_str()); + Assert::AreEqual("cdefedc", text.strip("eba").c_str()); + Assert::AreEqual("abcdefedcbaea", text.strip("ghijZ").c_str()); + Assert::AreEqual("abcdefedcbaea", text.strip("ABc").c_str()); + + pcs::CppWString wtext(L"abcdefedcbaea"); + + Assert::AreEqual(L"bcdefedcbae", wtext.strip(L"a").c_str()); + Assert::AreEqual(L"cdefedcbae", wtext.strip(L"ba").c_str()); + Assert::AreEqual(L"defedcbae", wtext.strip(L"acb").c_str()); + Assert::AreEqual(L"efedcbae", wtext.strip(L"dacb").c_str()); + Assert::AreEqual(L"f", wtext.strip(L"abcde").c_str()); + Assert::AreEqual(L"bcdefedcb", wtext.strip(L"ea").c_str()); + Assert::AreEqual(L"cdefedc", wtext.strip(L"eba").c_str()); + Assert::AreEqual(L"abcdefedcbaea", wtext.strip(L"ghijZ").c_str()); + Assert::AreEqual(L"abcdefedcbaea", wtext.strip(L"ABc").c_str()); + } + + TEST_METHOD(substr) + { + pcs::CppString text("AbcDefGhi"); + + Assert::AreEqual("AbcDefGhi", text.substr(0, 9).c_str()); + Assert::AreEqual("bcDefGhi", text.substr(1, 8).c_str()); + Assert::AreEqual("cDefGhi", text.substr(2, 7).c_str()); + Assert::AreEqual("DefGhi", text.substr(3, 6).c_str()); + Assert::AreEqual("efGhi", text.substr(4, 5).c_str()); + Assert::AreEqual("fGhi", text.substr(5, 4).c_str()); + Assert::AreEqual("Ghi", text.substr(6, 3).c_str()); + Assert::AreEqual("hi", text.substr(7, 2).c_str()); + Assert::AreEqual("i", text.substr(8, 1).c_str()); + Assert::AreEqual("", text.substr(9, 0).c_str()); + + Assert::AreEqual("AbcDefGhi", text.substr(0).c_str()); + Assert::AreEqual("bcDefGhi", text.substr(1).c_str()); + Assert::AreEqual("cDefGhi", text.substr(2).c_str()); + Assert::AreEqual("DefGhi", text.substr(3).c_str()); + Assert::AreEqual("efGhi", text.substr(4).c_str()); + Assert::AreEqual("fGhi", text.substr(5).c_str()); + Assert::AreEqual("Ghi", text.substr(6).c_str()); + Assert::AreEqual("hi", text.substr(7).c_str()); + Assert::AreEqual("i", text.substr(8).c_str()); + Assert::AreEqual("", text.substr(9).c_str()); + + Assert::AreEqual("AbcDefGh", text.substr(0, 8).c_str()); + Assert::AreEqual("bcDefGh", text.substr(1, 7).c_str()); + Assert::AreEqual("cDefG", text.substr(2, 5).c_str()); + Assert::AreEqual("DefGh", text.substr(3, 5).c_str()); + Assert::AreEqual("efGh", text.substr(4, 4).c_str()); + Assert::AreEqual("fG", text.substr(5, 2).c_str()); + Assert::AreEqual("G", text.substr(6, 1).c_str()); + Assert::AreEqual("h", text.substr(7, 1).c_str()); + Assert::AreEqual("i", text.substr(8, 3).c_str()); + Assert::AreEqual("", text.substr(9, 0).c_str()); + + Assert::AreEqual("", text.substr(10, 15).c_str()); + Assert::AreEqual("", text.substr(21).c_str()); + + pcs::CppWString wtext(L"AbcDefGhi"); + + Assert::AreEqual(L"AbcDefGhi", wtext.substr(0, 9).c_str()); + Assert::AreEqual(L"bcDefGhi", wtext.substr(1, 8).c_str()); + Assert::AreEqual(L"cDefGhi", wtext.substr(2, 7).c_str()); + Assert::AreEqual(L"DefGhi", wtext.substr(3, 6).c_str()); + Assert::AreEqual(L"efGhi", wtext.substr(4, 5).c_str()); + Assert::AreEqual(L"fGhi", wtext.substr(5, 4).c_str()); + Assert::AreEqual(L"Ghi", wtext.substr(6, 3).c_str()); + Assert::AreEqual(L"hi", wtext.substr(7, 2).c_str()); + Assert::AreEqual(L"i", wtext.substr(8, 1).c_str()); + Assert::AreEqual(L"", wtext.substr(9, 0).c_str()); + + Assert::AreEqual(L"AbcDefGhi", wtext.substr(0).c_str()); + Assert::AreEqual(L"bcDefGhi", wtext.substr(1).c_str()); + Assert::AreEqual(L"cDefGhi", wtext.substr(2).c_str()); + Assert::AreEqual(L"DefGhi", wtext.substr(3).c_str()); + Assert::AreEqual(L"efGhi", wtext.substr(4).c_str()); + Assert::AreEqual(L"fGhi", wtext.substr(5).c_str()); + Assert::AreEqual(L"Ghi", wtext.substr(6).c_str()); + Assert::AreEqual(L"hi", wtext.substr(7).c_str()); + Assert::AreEqual(L"i", wtext.substr(8).c_str()); + Assert::AreEqual(L"", wtext.substr(9).c_str()); + + Assert::AreEqual(L"AbcDefGh", wtext.substr(0, 8).c_str()); + Assert::AreEqual(L"bcDefGh", wtext.substr(1, 7).c_str()); + Assert::AreEqual(L"cDefG", wtext.substr(2, 5).c_str()); + Assert::AreEqual(L"DefGh", wtext.substr(3, 5).c_str()); + Assert::AreEqual(L"efGh", wtext.substr(4, 4).c_str()); + Assert::AreEqual(L"fG", wtext.substr(5, 2).c_str()); + Assert::AreEqual(L"G", wtext.substr(6, 1).c_str()); + Assert::AreEqual(L"h", wtext.substr(7, 1).c_str()); + Assert::AreEqual(L"i", wtext.substr(8, 3).c_str()); + Assert::AreEqual(L"", wtext.substr(9, 0).c_str()); + + Assert::AreEqual(L"", wtext.substr(10, 15).c_str()); + Assert::AreEqual(L"", wtext.substr(21).c_str()); + } + + TEST_METHOD(swapcase) + { + pcs::CppString s(255, '\0'); + for (int i : std::views::iota(0, 256)) + s[i] = pcs::CppString::value_type(i); + pcs::CppString res{ s.swapcase() }; + for (auto const [s, r] : std::views::zip(s, res)) { + if (std::islower(s)) + Assert::IsTrue(std::isupper(r)); + else if (std::isupper(s)) + Assert::IsTrue(std::islower(r)); + else + Assert::AreEqual(s, r); + } + + pcs::CppWString ws(0xffff, '\0'); + for (int i : std::views::iota(0, 0x1'0000)) + ws[i] = pcs::CppWString::value_type(i); + pcs::CppWString wres{ ws.swapcase() }; + for (auto const [ws, wr] : std::views::zip(ws, wres)) { + if (std::islower(ws)) + Assert::IsTrue(std::isupper(wr)); + else if (std::isupper(ws)) + Assert::IsTrue(std::islower(wr)); + else + Assert::AreEqual(ws, wr); + } + } + + TEST_METHOD(title) + { + pcs::CppString text("to bE TiTlEd - cheCKing,errors, in Case oF aNy fOUNd"); + pcs::CppString expected("To Be Titled - Checking,errors, In Case Of Any Found"); + pcs::CppString res{ text.title() }; + Assert::AreEqual(expected.c_str(), res.c_str()); + + pcs::CppWString wtext(L"to bE TiTlEd - cheCKing,errors, in Case oF aNy fOUNd\u2026\x86"); + pcs::CppWString wexpected(L"To Be Titled - Checking,errors, In Case Of Any Found\u2026\x86"); + pcs::CppWString wres{ wtext.title() }; + Assert::AreEqual(wexpected.c_str(), wres.c_str()); + + } + + TEST_METHOD(translate) + { + pcs::CppString::TransTable trans_table("oizeaslbgOIZEASLG", "012345789012345789"); + pcs::CppString text("This is a big 'Oiseau' that can be seen in 'Le Zoo'"); + pcs::CppString expected("Th15 15 4 819 '01534u' th4t c4n 83 533n 1n '73 200'"); + Assert::AreEqual(expected.c_str(), text.translate(trans_table).c_str()); + + pcs::CppWString::TransTable wtrans_table(L"oizeaslbgOIZEASLG", L"012345789012345789"); + pcs::CppWString wtext(L"This is a big 'Oiseau' that can be seen in 'Le Zoo'"); + pcs::CppWString wexpected(L"Th15 15 4 819 '01534u' th4t c4n 83 533n 1n '73 200'"); + Assert::AreEqual(wexpected.c_str(), wtext.translate(wtrans_table).c_str()); + } + + TEST_METHOD(upper) + { + for (int c = 0; c <= 255; ++c) { + const char ch{ char(c) }; + constexpr int N{ 5 }; + pcs::CppString s(N, ch); + s.upper(); + for (int i = 0; i < N; ++i) + Assert::AreEqual(pcs::to_upper(ch), s[i]); + Assert::AreEqual(char(std::toupper(ch)), pcs::CppString::upper(ch)); + } + + for (int c = 0; c <= 0xffff; ++c) { + const wchar_t wch{ wchar_t(c) }; + constexpr int N{ 5 }; + pcs::CppWString ws(N, wch); + ws.upper(); + for (int i = 0; i < N; ++i) + Assert::AreEqual(pcs::to_upper(wch), ws[i]); + Assert::AreEqual(wchar_t(std::toupper(wch)), pcs::CppWString::upper(wch)); + } + + pcs::CppString s(255, '\0'); + for (int i : std::views::iota(0, 256)) + s[i] = pcs::CppString::value_type(i); + pcs::CppString res{ s.upper() }; + for (auto const [cs, cr] : std::views::zip(s, res)) { + if (std::islower(cs)) + Assert::IsTrue(std::isupper(cr)); + else if (std::isupper(cs)) + Assert::IsTrue(std::isupper(cr)); + else + Assert::AreEqual(cs, cr); + } + + pcs::CppWString ws(0xffff, '\0'); + for (int i : std::views::iota(0, 0x1'0000)) + ws[i] = pcs::CppWString::value_type(i); + pcs::CppWString wres{ ws.upper() }; + for (auto const [wcs, wcr] : std::views::zip(ws, wres)) { + if (std::islower(wcs)) + Assert::IsTrue(std::isupper(wcr)); + else if (std::isupper(wcs)) + Assert::IsTrue(std::isupper(wcr)); + else + Assert::AreEqual(wcs, wcr); + } + + } + + TEST_METHOD(zfill) + { + pcs::CppString s("1.23"); + Assert::AreEqual("1.23", s.zfill(0).c_str()); + Assert::AreEqual("1.23", s.zfill(1).c_str()); + Assert::AreEqual("1.23", s.zfill(2).c_str()); + Assert::AreEqual("1.23", s.zfill(3).c_str()); + Assert::AreEqual("1.23", s.zfill(4).c_str()); + Assert::AreEqual("01.23", s.zfill(5).c_str()); + Assert::AreEqual("001.23", s.zfill(6).c_str()); + + s = '+' + s; + Assert::AreEqual("+1.23", s.zfill(0).c_str()); + Assert::AreEqual("+1.23", s.zfill(1).c_str()); + Assert::AreEqual("+1.23", s.zfill(2).c_str()); + Assert::AreEqual("+1.23", s.zfill(3).c_str()); + Assert::AreEqual("+1.23", s.zfill(4).c_str()); + Assert::AreEqual("+1.23", s.zfill(5).c_str()); + Assert::AreEqual("+01.23", s.zfill(6).c_str()); + Assert::AreEqual("+001.23", s.zfill(7).c_str()); + + s[0] = '-'; + Assert::AreEqual("-1.23", s.zfill(0).c_str()); + Assert::AreEqual("-1.23", s.zfill(1).c_str()); + Assert::AreEqual("-1.23", s.zfill(2).c_str()); + Assert::AreEqual("-1.23", s.zfill(3).c_str()); + Assert::AreEqual("-1.23", s.zfill(4).c_str()); + Assert::AreEqual("-1.23", s.zfill(5).c_str()); + Assert::AreEqual("-01.23", s.zfill(6).c_str()); + Assert::AreEqual("-001.23", s.zfill(7).c_str()); + + s[0] = '*'; + Assert::AreEqual("*1.23", s.zfill(0).c_str()); + Assert::AreEqual("*1.23", s.zfill(1).c_str()); + Assert::AreEqual("*1.23", s.zfill(2).c_str()); + Assert::AreEqual("*1.23", s.zfill(3).c_str()); + Assert::AreEqual("*1.23", s.zfill(4).c_str()); + Assert::AreEqual("*1.23", s.zfill(5).c_str()); + Assert::AreEqual("0*1.23", s.zfill(6).c_str()); + Assert::AreEqual("00*1.23", s.zfill(7).c_str()); + + + pcs::CppWString ws(L"1.23"); + Assert::AreEqual(L"1.23", ws.zfill(0).c_str()); + Assert::AreEqual(L"1.23", ws.zfill(1).c_str()); + Assert::AreEqual(L"1.23", ws.zfill(2).c_str()); + Assert::AreEqual(L"1.23", ws.zfill(3).c_str()); + Assert::AreEqual(L"1.23", ws.zfill(4).c_str()); + Assert::AreEqual(L"01.23", ws.zfill(5).c_str()); + Assert::AreEqual(L"001.23", ws.zfill(6).c_str()); + + ws = L'+' + ws; + Assert::AreEqual(L"+1.23", ws.zfill(0).c_str()); + Assert::AreEqual(L"+1.23", ws.zfill(1).c_str()); + Assert::AreEqual(L"+1.23", ws.zfill(2).c_str()); + Assert::AreEqual(L"+1.23", ws.zfill(3).c_str()); + Assert::AreEqual(L"+1.23", ws.zfill(4).c_str()); + Assert::AreEqual(L"+1.23", ws.zfill(5).c_str()); + Assert::AreEqual(L"+01.23", ws.zfill(6).c_str()); + Assert::AreEqual(L"+001.23", ws.zfill(7).c_str()); + + ws[0] = L'-'; + Assert::AreEqual(L"-1.23", ws.zfill(0).c_str()); + Assert::AreEqual(L"-1.23", ws.zfill(1).c_str()); + Assert::AreEqual(L"-1.23", ws.zfill(2).c_str()); + Assert::AreEqual(L"-1.23", ws.zfill(3).c_str()); + Assert::AreEqual(L"-1.23", ws.zfill(4).c_str()); + Assert::AreEqual(L"-1.23", ws.zfill(5).c_str()); + Assert::AreEqual(L"-01.23", ws.zfill(6).c_str()); + Assert::AreEqual(L"-001.23", ws.zfill(7).c_str()); + + ws[0] = L'*'; + Assert::AreEqual(L"*1.23", ws.zfill(0).c_str()); + Assert::AreEqual(L"*1.23", ws.zfill(1).c_str()); + Assert::AreEqual(L"*1.23", ws.zfill(2).c_str()); + Assert::AreEqual(L"*1.23", ws.zfill(3).c_str()); + Assert::AreEqual(L"*1.23", ws.zfill(4).c_str()); + Assert::AreEqual(L"*1.23", ws.zfill(5).c_str()); + Assert::AreEqual(L"0*1.23", ws.zfill(6).c_str()); + Assert::AreEqual(L"00*1.23", ws.zfill(7).c_str()); + } + + }; +} diff --git a/cpp-strings-tests/cpp-strings-tests.vcxproj b/cpp-strings-tests/cpp-strings-tests.vcxproj new file mode 100644 index 0000000..089d18e --- /dev/null +++ b/cpp-strings-tests/cpp-strings-tests.vcxproj @@ -0,0 +1,188 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + {3B180A14-A496-4E9D-8D9B-57D871C8E005} + Win32Proj + cppstringstests + 10.0 + NativeUnitTestProject + + + + DynamicLibrary + true + v143 + Unicode + false + + + DynamicLibrary + false + v143 + true + Unicode + false + + + DynamicLibrary + true + v143 + Unicode + false + + + DynamicLibrary + false + v143 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + true + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings + _DEBUG;%(PreprocessorDefinitions) + true + + + stdcpplatest + stdclatest + true + false + + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + NotUsing + Level3 + true + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings + WIN32;_DEBUG;%(PreprocessorDefinitions) + true + + + stdcpplatest + stdclatest + true + false + + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + NotUsing + Level3 + true + true + true + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings + WIN32;NDEBUG;%(PreprocessorDefinitions) + true + + + stdcpplatest + stdclatest + true + false + + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + NotUsing + Level3 + true + true + true + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings + NDEBUG;%(PreprocessorDefinitions) + true + + + stdcpplatest + stdclatest + true + false + + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + + + + + \ No newline at end of file diff --git a/cpp-strings-tests/cpp-strings-tests.vcxproj.filters b/cpp-strings-tests/cpp-strings-tests.vcxproj.filters new file mode 100644 index 0000000..bcfea1c --- /dev/null +++ b/cpp-strings-tests/cpp-strings-tests.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/cpp-strings-tests/cpp-strings-tests.vcxproj.user b/cpp-strings-tests/cpp-strings-tests.vcxproj.user new file mode 100644 index 0000000..966b4ff --- /dev/null +++ b/cpp-strings-tests/cpp-strings-tests.vcxproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/cpp-strings/cpp-strings.cfg b/cpp-strings/cpp-strings.cfg new file mode 100644 index 0000000..847ae88 --- /dev/null +++ b/cpp-strings/cpp-strings.cfg @@ -0,0 +1,96 @@ +# Doxyfile 1.14.0 + +# This file describes the settings to be used by the documentation system +# Doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use Doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use Doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "cpp-strings" +PROJECT_NUMBER = "1.0.0" +PROJECT_BRIEF = "Pythonic c++ strings" +OUTPUT_DIRECTORY = + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +ALWAYS_DETAILED_SEC = YES +FULL_PATH_NAMES = NO +BUILTIN_STL_SUPPORT = YES +TIMESTAMP = DATE ##YES ##NO ##DATETIME ## + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +HIDE_UNDOC_NAMESPACES = NO +SORT_BRIEF_DOCS = YES +WARN_NO_PARAMDOC = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ./ ../ +INPUT_ENCODING = UTF-8 +USE_MDFILE_AS_MAINPAGE = ../README.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_DYNAMIC_MENUS = YES +HTML_DYNAMIC_SECTIONS = NO +HTML_CODE_FOLDING = NO ##YES +HTML_COPY_CLIPBOARD = YES +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_TREEVIEW = YES +FULL_SIDEBAR = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO diff --git a/cpp-strings/cpp-strings.sln b/cpp-strings/cpp-strings.sln new file mode 100644 index 0000000..ad5321e --- /dev/null +++ b/cpp-strings/cpp-strings.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33414.496 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpp-strings", "cpp-strings.vcxproj", "{520980FD-2242-443E-89DB-B8E41D9606B5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpp-strings-tests", "..\cpp-strings-tests\cpp-strings-tests.vcxproj", "{3B180A14-A496-4E9D-8D9B-57D871C8E005}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {520980FD-2242-443E-89DB-B8E41D9606B5}.Debug|x64.ActiveCfg = Debug|x64 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Debug|x64.Build.0 = Debug|x64 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Debug|x86.ActiveCfg = Debug|Win32 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Debug|x86.Build.0 = Debug|Win32 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Release|x64.ActiveCfg = Release|x64 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Release|x64.Build.0 = Release|x64 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Release|x86.ActiveCfg = Release|Win32 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Release|x86.Build.0 = Release|Win32 + {3B180A14-A496-4E9D-8D9B-57D871C8E005}.Debug|x64.ActiveCfg = Debug|x64 + {3B180A14-A496-4E9D-8D9B-57D871C8E005}.Debug|x64.Build.0 = Debug|x64 + {3B180A14-A496-4E9D-8D9B-57D871C8E005}.Debug|x86.ActiveCfg = Debug|Win32 + {3B180A14-A496-4E9D-8D9B-57D871C8E005}.Debug|x86.Build.0 = Debug|Win32 + {3B180A14-A496-4E9D-8D9B-57D871C8E005}.Release|x64.ActiveCfg = Release|x64 + {3B180A14-A496-4E9D-8D9B-57D871C8E005}.Release|x64.Build.0 = Release|x64 + {3B180A14-A496-4E9D-8D9B-57D871C8E005}.Release|x86.ActiveCfg = Release|Win32 + {3B180A14-A496-4E9D-8D9B-57D871C8E005}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {ECEA0DAB-2736-4B43-9AEC-7B84A49AFF74} + EndGlobalSection +EndGlobal diff --git a/cpp-strings/cpp-strings.vcxproj b/cpp-strings/cpp-strings.vcxproj new file mode 100644 index 0000000..3245b81 --- /dev/null +++ b/cpp-strings/cpp-strings.vcxproj @@ -0,0 +1,149 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {520980fd-2242-443e-89db-b8e41d9606b5} + cppstrings + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + stdc17 + false + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + stdc17 + false + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + stdc17 + false + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + stdc17 + false + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/cpp-strings/cpp-strings.vcxproj.filters b/cpp-strings/cpp-strings.vcxproj.filters new file mode 100644 index 0000000..0899904 --- /dev/null +++ b/cpp-strings/cpp-strings.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + \ No newline at end of file diff --git a/cpp-strings/cpp-strings.vcxproj.user b/cpp-strings/cpp-strings.vcxproj.user new file mode 100644 index 0000000..966b4ff --- /dev/null +++ b/cpp-strings/cpp-strings.vcxproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h new file mode 100644 index 0000000..e368f9f --- /dev/null +++ b/cpp-strings/cppstrings.h @@ -0,0 +1,2493 @@ +#pragma once +/** + Library cppstrings + "What if c++ strings where as easy to use as Python strings?" + + Copyright (C) 2023-2025 Philippe Schmouker + contact - ph (dot) schmouker (at) gmail (dot) com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +//============================================================= +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace pcs // i.e. "pythonic c++ strings" +{ + //============================================================= + // Forward declarations + + // base class -- not to be directly instantiated, see belowing specializations instead + template< + class CharT, + class TraitsT = std::char_traits, + class AllocatorT = std::allocator + > class CppStringT; + + // specializations of the base class -- these are the ones that should be instantiated by user. + using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' + using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' + + +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4455) // to avoid boring warnings with litteral operators definitions +#endif + + // litteral operators + inline CppString operator""_cs(const char* str, std::size_t len); //!< Forms a CppString literal. + inline CppWString operator""_cs(const wchar_t* str, std::size_t len); //!< Forms a CppWString literal. + + + // slices -- to be used with operator CppStringT::operator(). + template + requires std::is_signed_v + class Slice; //!< Base class for slices, with start, stop and step specified values + + template + requires std::is_signed_v + struct StartSlice; //!< struct of slices with default stop and step values + + template + requires std::is_signed_v + struct StopSlice; //!< struct of slices with default start and step values + + template + requires std::is_signed_v + struct StepSlice; //!< struct of slices with default start and stop values + + template + requires std::is_signed_v + struct StartStopSlice; //!< struct of slices with default step values + + template + requires std::is_signed_v + struct StartStepSlice; //!< struct of slices with default stop values + + template + requires std::is_signed_v + struct StopStepSlice; //!< struct of slices with default start values + + + // chars classifications -- not to be directly called, see respective specializations at the very end of this module. + template + inline const bool is_alpha(const CharT ch) noexcept; //!< Returns true if character ch is alphabetic, or false otherwise. + + template + inline const bool is_ascii(const CharT ch) noexcept; //!< Returns true if character ch gets ASCII code, or false otherwise. + + template + inline const bool is_decimal(const CharT ch) noexcept; //!< Returns true if character is a decimal digit, or false otherwise. + + template + inline const bool is_digit(const CharT ch) noexcept; //!< Returns true if character is a decimal digit, or false otherwise. + + template + inline const bool is_id_continue(const CharT ch) noexcept; //!< Returns true if character is a continuing char for identifiers, or false otherwise. + + template + inline const bool is_id_start(const CharT ch) noexcept; //!< Returns true if character is a starting char for identifiers, or false otherwise. + + template + inline const bool is_lower(const CharT ch) noexcept; //!< Returns true if character is lowercase, or false otherwise. + + template + inline const bool is_numeric(const CharT ch) noexcept; //!< Returns true if character is a decimal digit, or false otherwise. + + template + inline const bool is_printable(const CharT ch) noexcept; //!< Returns true if character ch is printable, or false otherwise. + + template + inline const bool is_punctuation(const CharT ch) noexcept; //!< Returns true if character ch is punctuation, or false otherwise. + + template + inline const bool is_space(const CharT ch) noexcept; //!< Returns true if character ch is white space, or false otherwise. + + template + inline const bool is_upper(const CharT ch) noexcept; //!< Returns true if character is uppercase, or false otherwise. + + template + inline const CharT swap_case(const CharT ch) noexcept; //!< Returns the swapped case form of character ch if it exists, or ch itself otherwise. + + template + inline const CharT to_lower(const CharT ch) noexcept; //!< Returns the lowercase form of character ch if it exists, or ch itself otherwise. + + template + inline const CharT to_upper(const CharT ch) noexcept; //!< Returns the uppercase form of character ch if it exists, or ch itself otherwise. + + + //===== CppStringT<> ====================================== + /** \brief This is the templated base class for all CppString classes. + * + * Users should instantiate any specialization of this base class + * rather than this base class itself: + * - \see CppString for CppStringT. + * - \see CppWString for CppStringT. + * + * This base class inherits from std::basic_string. As such, + * it gets direct access to all public methods of its base class. + * \see https://en.cppreference.com/w/cpp/string/basic_string for a + * full list of such methods, for instance. + * + * You may specialize it by your own with any of the next char types: + * - char8_t (C++20) + * - char16_t (C++11) + * - char32_t (C++11) + * Caution: templated method format() may be difficult to specialize + * with these types --> let us know if you succeed! + */ + template + class CppStringT : public std::basic_string + { + public: + //=== Wrappers ======================================== + using MyBaseClass = std::basic_string; + + using traits_type = MyBaseClass::traits_type; + using value_type = MyBaseClass::value_type; + using allocator_type = MyBaseClass::allocator_type; + using size_type = MyBaseClass::size_type; + using difference_type = MyBaseClass::difference_type; + using reference = MyBaseClass::reference; + using const_reference = MyBaseClass::const_reference; + using pointer = MyBaseClass::pointer; + using const_pointer = MyBaseClass::const_pointer; + using iterator = MyBaseClass::iterator; + using const_iterator = MyBaseClass::const_iterator; + using reverse_iterator = MyBaseClass::reverse_iterator; + using const_reverse_iterator = MyBaseClass::const_reverse_iterator; + + + //=== Translation Table =============================== + /** \brief The internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate. */ + class TransTable + { + public: + //--- wrappers ------------------------------------ + using key_type = CharT; + using value_type = CppStringT; + + //--- Constructors / destructor ------------------- + /** \brief Creates a TransTable from a standard map (#1). */ + inline TransTable(const std::map trans_table) + : m_table{ trans_table } + {} + + /** \brief Creates a TransTable from two strings (#2). + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i-th character in values. + */ + TransTable(const CppStringT& keys, const CppStringT& values) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[k] = CppStringT(*val_it++); + } + + /** \brief Creates a TransTable from three strings (#3). + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i -th character in values. Finally, the characters + * contained in string not_translated are associated in the + * translation table with the empty string. + */ + TransTable(const CppStringT& keys, const CppStringT& values, const CppStringT& not_translated) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[k] = CppStringT(*val_it++); + for (const auto k : not_translated) + m_table[k] = CppStringT(); + } + + /** \brief Creates a TransTable from a string and an initalization list (#4). + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i-th character in values. + */ + inline TransTable(const CppStringT& keys, const std::initializer_list& values) + { + assert(keys.size() == values.size()); + auto val_it = values.begin(); + for (const auto k : keys) + m_table[k] = *val_it++; + } + + /** \brief Creates a TransTable from a string, an initalization list and a string (#5). + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i -th character in values. Finally, the characters + * contained in string not_translated are associated in the + * translation table with the empty string. + */ + inline TransTable(const CppStringT& keys, const std::initializer_list values, const CppStringT& not_translated) + { + assert(keys.size() == values.size()); + auto val_it = values.begin(); + for (const auto k : keys) + m_table[k] = *val_it++; + for (const auto k : not_translated) + m_table[k] = CppStringT(); + } + + /** \brief Creates a TransTable from two pointers to null-terminated lists of characters (#6). + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i-th character in values. + */ + inline TransTable(const CharT* keys, const CharT* values) + { + while (*keys && *values) + m_table[*keys++] = value_type(*values++); + } + + /** \brief Creates a TransTable from three pointers to null-terminated lists of characters (#7). + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i -th entry in values. Finally, the characters contained + * in string not_translated are associated in the translation + * table with the empty string. + */ + inline TransTable(const CharT* keys, const CharT* values, const CharT* not_translated) + { + while (*keys && *values) + m_table[*keys++] = value_type(*values++); + while (*not_translated) + m_table[*not_translated++] = CppStringT(); + } + + /** \brief Creates a TransTable from two containers iterators (#8). + * + * Both containers should have the same size. The i-th + * character in key is associated in the translation + * table with the i-th entry in values. + */ + template + inline TransTable(KeyIt first_key, KeyIt last_key, ValueIt first_value, ValueIt last_value) + { + KeyIt key_it{ first_key }; + ValueIt val_it{ first_value }; + while (key_it != last_key && val_it != last_value) + m_table[*key_it++] = value_type(*val_it++); + } + + /** \brief Creates a TransTable from three containers iterators (#9). + * + * Both containers should have the same size. The i-th + * character in key is associated in the translation table with + * the i -th character in values. Finally, the characters + * contained in string not_translated are associated in the + * translation table with the empty string. + */ + template + inline TransTable(Key1It first_key, Key1It last_key, + ValueIt first_value, ValueIt last_value, + Key2It first_not_translated, Key2It last_not_translated) + { + Key1It key1_it{ first_key }; + ValueIt val_it{ first_value }; + while (key1_it != last_key && val_it != last_value) + m_table[*key1_it++] = value_type(*val_it++); + Key2It key2_it{ first_not_translated }; + while (key2_it != last_not_translated) + m_table[*key2_it++] = CppStringT(); + } + + /** \brief Creates a TransTable from two string views (#10). + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i-th character in values. + */ + /**/ + template + explicit TransTable(const StringViewLike& keys, const StringViewLike& values) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[(*k)[0]] = value_type(*val_it++); + } + + inline TransTable() noexcept = default; //!< Default empty constructor. + inline TransTable(const TransTable&) noexcept = default; //!< Default copy constructor. + inline TransTable(TransTable&&) noexcept = default; //!< Default move constructor. + + inline ~TransTable() noexcept = default; //!< Default descrtuctor + + //--- operators ----------------------------------- + inline TransTable& operator= (const TransTable&) noexcept = default; //!< Default copy assignment + inline TransTable& operator= (TransTable&&) noexcept = default; //!< Default move assignment + + /** \brief Assignment operator with a standard map. */ + inline TransTable& operator= (const std::map& trans_table) noexcept + { + m_table = trans_table; + return *this; + } + + /** \brief Indexing operator. */ + [[nodiscard]] + inline value_type operator[] (const key_type ch) noexcept + { + auto it = m_table.find(ch); + if (it != m_table.end()) [[likely]] { + return it->second; + } + else [[unlikely]] { + return ch; + } + } + + inline std::map& get_table() noexcept //!< for tests purposes + { + return m_table; + } + + private: + std::map m_table{}; // the internal storage of the translation table. Access it via the indexing operator. + + }; + + + //=== Constructors / Destructor ======================= + inline CppStringT() : MyBaseClass() {} // #1 + inline CppStringT(const CppStringT& other) : MyBaseClass(other) {} // #2 + inline CppStringT(const CppStringT& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} // #3 + inline CppStringT(CppStringT&& other) noexcept : MyBaseClass(other) {} // #4 + inline CppStringT(CppStringT&& other, const AllocatorT& alloc) noexcept : MyBaseClass(other, alloc) {} // #5 + inline CppStringT(MyBaseClass::size_type count, CharT ch) : MyBaseClass(count, ch) {} // #6 + inline CppStringT(const CppStringT& other, size_type pos) : MyBaseClass(other, pos) {} // #7 + inline CppStringT(const CppStringT& other, size_type pos, size_type count) noexcept : MyBaseClass(other, pos, count) {} // #8 + inline CppStringT(const CharT* s) // #9 + : MyBaseClass(s ? s : CppStringT().c_str()) + {} + inline CppStringT(const CharT* s, size_type count) // #10 + : MyBaseClass(s ? s : CppStringT().c_str(), count) + {} + inline CppStringT(std::initializer_list ilist) : MyBaseClass(ilist) {} // #11 + + inline CppStringT(const CharT ch) : MyBaseClass(1, ch) {} // #19 + + inline CppStringT(const MyBaseClass& other) : MyBaseClass(other) {} // #12 + inline CppStringT(const MyBaseClass& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} // #13 + inline CppStringT(MyBaseClass&& other) : MyBaseClass(other) {} // #14 + inline CppStringT(MyBaseClass&& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} // #15 + + template + inline CppStringT(InputIt first, InputIt last) : MyBaseClass(first, last) {} // #16 + + template + explicit CppStringT(StringViewLike& svl) : MyBaseClass(svl) {} // #17 + + template + CppStringT(StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} // #18 + + inline ~CppStringT() noexcept = default; + + + //=== Assignment operators ============================ + CppStringT& operator= (const CppStringT&) noexcept = default; //!< Default copy assignment + CppStringT& operator= (CppStringT&&) noexcept = default; //!< Default move assignment + + + //=== Exceptions ====================================== + class NotFoundException : public std::logic_error + { + public: + using MyBaseClass = std::logic_error; + + inline NotFoundException(const std::string& what_arg) : MyBaseClass(what_arg) {} + inline NotFoundException(const char* what_arg) : MyBaseClass(what_arg) {} + }; + + + //=== Methods ========================================= + + //--- capitalize() ------------------------------------ + /** \brief Returns a copy of the string with its first character capitalized and the rest lowercased. */ + inline CppStringT capitalize() noexcept + { + CppStringT res(*this); + if (!res.empty()) [[likely]] { + res.lower(); + res[0] = pcs::to_upper(res[0]); + } + return res; + } + + + //--- center() ---------------------------------------- + /** \brief Returns a copy of the string centered in a string of length width. + * + * Padding is done using the specified fillchar (default is an ASCII space). + * A copy of the original string is returned if width is less than or equal + * to the length of the string. The original string remains unchanged. + */ + [[nodiscard]] + CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept + { + const size_type len{ this->size() }; + if (width <= len) [[unlikely]] + return CppStringT(*this); + + const size_type half{ (width - len) / 2 }; + return CppStringT(half, fillch) + *this + CppStringT(width - half - len, fillch); + } + + + //--- contains() -------------------------------------- + /** \brief Returns true if this string contains the passed string, or false otherwise. + * + * This is a c++ implementation of Python keyword 'in' applied to strings. + */ + [[nodiscard]] + constexpr bool contains(const CppStringT& substr) const noexcept + { + if (substr.empty()) [[unlikely]] + // the empty string is always contained in any string + return true; + +#if (defined(_HAS_CXX23) && _HAS_CXX23) || (!defined(_HAS_CXX23) && __cplusplus >= 202302L) + // c++23 and above already defines this method + return MyBaseClass::contains(substr); +#else + // up to c++20, we have to implement this method + const size_type substr_width{ substr.size() }; + const size_type width{ this->size() }; + + if (substr_width > width) [[unlikely]] + return false; + + for (size_type index = 0; index <= width - substr_width; ++index) [[likely]] { + if (substr == this->substr(index, substr_width)) + return true; + } + + return false; +#endif + } + + + //--- contains_n() ------------------------------------ + /** \brief Returns true if the passed string is found within the slice str[start:start+count-1], or false otherwise. + * + * This is a c++ implementation of Python keyword 'in' applied to Python sliced strings. + */ + [[nodiscard]] + inline constexpr bool contains_n(const CppStringT& sub, const size_type start, const size_type count = -1) const noexcept + { + try { + return this->substr(start, count).contains(sub); + } + catch (...) { + return false; + } + } + + + //--- count() ----------------------------------------- + /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, end]. */ + [[nodiscard]] + constexpr size_type count(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept + { + size_type n = 0; + CppStringT tmp{ this->substr(start, std::min(this->size(), end) - start + 1) }; + + size_type start_{ 0 }; + size_type end_{ tmp.size() }; + + while ((start_ = tmp.find(sub, start_, end_)) != CppStringT::npos) { + start_ += sub.size(); + end_ -= start_; + tmp = tmp.substr(start_, std::min(tmp.size(), end_) + 1); + start_ = 0; + n++; + } + + return n; + } + + + //--- count_n() --------------------------------------- + /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, start+length-1]. */ + [[nodiscard]] + inline constexpr size_type count_n(const CppStringT& sub, const size_type start, const size_type length) const noexcept + { + return count(sub, start, start + length - 1); + } + + /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [0, length-1]. */ + [[nodiscard]] + inline constexpr size_type count_n(const CppStringT& sub, const size_type length) const noexcept + { + return count(sub, 0, length - 1); + } + + + //--- endswith() -------------------------------------- + /** \brief Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops at end position. */ + [[nodiscard]] + inline const bool endswith(const CppStringT& suffix, const size_type start, const size_type end) const noexcept + { + return this->substr(start, end - start + 1).MyBaseClass::ends_with(suffix); + } + + /** \brief Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start of string and stops at end position. */ + [[nodiscard]] + inline const bool endswith(const CppStringT& suffix, const size_type end) const noexcept + { + return this->substr(0, end).MyBaseClass::ends_with(suffix); + } + + /** \brief Returns true if the string ends with the specified suffix, otherwise returns false. Test runs on the whole string. */ + [[nodiscard]] + inline const bool endswith(const CppStringT& suffix) const noexcept + { + return static_cast(MyBaseClass::ends_with(suffix)); + } + + /** \brief Returns true if the string ends with any of the specified suffixes, otherwise returns false. Test begins at start position and stops at end position. */ + [[nodiscard]] + const bool endswith(const std::initializer_list& suffixes, const size_type start, const size_type end) const noexcept + { + if (start > end) [[unlikely]] + return false; + + CppStringT tmp(this->substr(start, end - start + 1)); + for (auto& suffix : suffixes) { + if (tmp.ends_with(suffix)) [[unlikely]] + return true; + } + return false; + } + + + //--- endswith_n() ------------------------------------ + /** \brief Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions. */ + [[nodiscard]] + inline const bool endswith_n(const CppStringT& suffix, const size_type start, const size_type count) const noexcept + { + return endswith(suffix, start, start + count - 1); + } + + /** \brief Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions. */ + [[nodiscard]] + inline const bool endswith_n(const CppStringT& suffix, const size_type count) const noexcept + { + return endswith(suffix, 0, count - 1); + } + + /** \brief Returns true if the string ends with any of the specified suffixes, otherwise returns false. Test begins at start position and stops after count positions. */ + [[nodiscard]] + inline const bool endswith_n(const std::initializer_list& suffixes, const size_type start, const size_type count) const noexcept + { + return endswith(suffixes, start, start + count - 1); + } + + + //--- expand_tabs() ----------------------------------- + /** \brief Returns a copy of the string where all tab characters are replaced by one or more spaces, depending on the current column and the given tab size. */ + [[nodiscard]] + CppStringT expand_tabs(const size_type tabsize = 8) const noexcept + { + const size_type tabsize_{ tabsize == 0 ? 1 : tabsize }; + CppStringT ret{}; + + std::size_t current_pos{ 0 }; + for (const value_type ch : *this) { + if (ch == value_type('\t')) [[unlikely]] { + do { + ret += value_type(' '); + current_pos++; + } while (current_pos % tabsize_ != 0); + } + else if (ch == value_type('\n') || ch == value_type('\r')) [[unlikely]] { + ret += ch; + current_pos = 0; + } + else [[likely]] { + ret += ch; + current_pos++; + } + } + + return ret; + } + + + //--- find() ------------------------------------------ + /** \brief Returns the lowest index in the string where substring sub is found within the slice str[start:end], or -1 (i.e. 'npos') if sub is not found. + * + * Note: this method should be used only if you need to know the position of + * sub. To check if sub is a substring or not, use the method contains(). + * + * CAUTION: empty substrings are considered to be in the string if start and + * end positions are both less than the string size and if start <= end. + * + * \see find_n(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + [[nodiscard]] + constexpr size_type find(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept + { + const size_type end_{ (end == -1) ? this->size() : end }; + + if (start > end_) [[unlikely]] + return CppStringT::npos; + else [[likely]] + return find_n(sub, start, end_ - start + 1); + } + + + //--- find_n() ---------------------------------------- + /** \brief Returns the lowest index in the string where substring sub is found within the slice str[start:start+count-1], or -1 (i.e. 'npos') if sub is not found. + * + * Note: this method should be used only if you need to know the position of + * sub. To check if sub is a substring or not, use the method contains_n(). + * + * CAUTION: empty substrings are considered to be in the string if start and + * end positions are both less than the string size and if start <= end. The + * returned position is 0. + * + * \see find(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + [[nodiscard]] + inline constexpr size_type find_n(const CppStringT& sub, const size_type start, const size_type count) const noexcept + { + constexpr size_type npos{ CppStringT::npos }; + + try { + const CppStringT sub_str{ this->substr(start, count) }; + const size_type found_pos{ sub_str.MyBaseClass::find(sub) }; + + return (found_pos == npos) ? npos : found_pos + start; + } + catch (...) { + return npos; + } + } + + /** \brief Returns the lowest index in the string where substring sub is found within the slice str[0:count-1], or -1 (i.e. 'npos') if sub is not found. + * + * Note: this method should be used only if you need to know the position of + * sub. To check if sub is a substring or not, use the method contains_n(). + * + * CAUTION: empty substrings are considered to be in the string if start and + * end positions are both less than the string size and if start <= end. The + * returned position is 0. + * + * \see find(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + [[nodiscard]] + inline constexpr size_type find_n(const CppStringT& sub, const size_type count) const noexcept + { + return find_n(sub, 0, count); + } + + + //--- format() ---------------------------------------- + /** \brief Formats this string according to c++20 std::format() specification. Returns this string. */ + template + inline CppStringT& format( + const std::basic_format_string...> frmt, + ArgsT&&... args + ) + { + return *this; + } + + template + inline CppStringT& format( //!< specialzation for char's + const std::basic_format_string... > frmt, + ArgsT&&... args + ) + { + return *this = std::vformat(frmt.get(), std::make_format_args(args...)); + } + + template + inline CppStringT& format( //!< specialzation for wchar_t's + const std::basic_format_string... > frmt, + ArgsT&&... args + ) + { + return *this = std::vformat(frmt.get(), std::make_wformat_args(args...)); + } + + + //--- index() ----------------------------------------- + /** \brief Like find(const CppStringT&), but raises NotFoundException when the substring sub is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + [[nodiscard]] + inline constexpr size_type index(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const + { + const size_type ret_value = find(sub, start, end); + if (ret_value == CppStringT::npos) + throw NotFoundException("substring not found in string."); + else + return ret_value; + } + + + //--- index_n() --------------------------------------- + /** \brief Like find_n(sub, start, count), but raises NotFoundException when the substring is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + [[nodiscard]] + inline constexpr size_type index_n(const CppStringT& sub, const size_type start, const size_type count) const + { + return index(sub, start, start + count - 1); + } + + /** \brief Like find_n(sub, count), but raises NotFoundException when the substring is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + [[nodiscard]] + inline constexpr size_type index_n(const CppStringT& sub, const size_type count) const + { + return index(sub, 0, count); + } + + + //--- isalnum() --------------------------------------- + /** \brief Returns true if all characters in the string are alphanumeric and there is at least one character, or false otherwise. */ + [[nodiscard]] + inline const bool isalnum() const noexcept + { + if (this->empty()) [[unlikely]] + return false; + else [[likely]] + return std::all_of( + this->cbegin(), + this->cend(), + [](const value_type ch) { return pcs::is_alpha(ch) || pcs::is_decimal(ch) || pcs::is_digit(ch) || pcs::is_numeric(ch); } + ); + } + + + //--- isalpha() -------------------------------------- + /** \brief Returns true if all characters in the string are alphabetic and there is at least one character, or false otherwise. */ + [[nodiscard]] + inline const bool isalpha() const noexcept + { + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_alpha); + } + + + //--- isascii() --------------------------------------- + /** \brief Returns true if the string is empty or all characters in the string are ASCII, or false otherwise. */ +#if defined(isascii) // may be already defined in header file +#undef isascii +#endif + [[nodiscard]] + inline const bool isascii() const noexcept + { + return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii); + } + + + //--- isdecimal() ------------------------------------- + /** \brief Returns true if all characters in the string are decimal characters and there is at least one character, or false otherwise. + * + * Decimal characters are those that can be used to form numbers in + * base 10, e.g. U+0660, ARABIC-INDIC DIGIT ZERO. Formally a decimal + * character is a character in the Unicode General Category “Nd”. + */ + [[nodiscard]] + inline const bool isdecimal() const noexcept + { + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_decimal); + } + + + //--- isdigit() --------------------------------------- + /** \brief Returns true if all characters in the string are digits and there is at least one character, or false otherwise. + * + * Digits include decimal characters and digits that need special + * handling, such as the compatibility superscript digits. This + * covers digits which cannot be used to form numbers in base 10, + * like the Kharosthi numbers. Formally, a digit is a character + * that has the property value Numeric_Type=Digit or Numeric_Type + * =Decimal. + * + * CAUTION: current implementation of library cpp-strings does + * not implement above algorithm. It just returns the same result + * as 'isdecimal()' which is NOT what Python str library does. + */ + [[nodiscard]] + inline const bool isdigit() const noexcept + { + return isdecimal(); + } + + + //--- isidentifier() ---------------------------------- + /** \brief Returns true if the string is not empty and is a valid identifier according to the language definition, or false otherwise. + * + * CAUTION: the current implementation of this method does not deal with the proper c++ + * defintiion of identifiers (see https://en.cppreference.com/w/cpp/language/identifiers + * and https://www.unicode.org/reports/tr31/#Table_Lexical_Classes_for_Identifiers). + * + * While the specification of identifiers in c++ is this one: + * + * identifier ::= XID_Start XID_Continue* + * XID_Start ::= ID_Start XID_Continue* + * ID_Start ::= + * XID_Continue ::= + * ID_Continue ::= ID_Start | + * + * the currently implemented rule is this simpler one: + * + * identifier ::= ID_Start id_continue* + * id_continue ::= ID_Start | + */ + [[nodiscard]] + inline const bool isidentifier() const noexcept + { + return !this->empty() && pcs::is_id_start((*this)[0]) && (this->size() == 1 || std::all_of(this->cbegin() + 1, this->cend(), pcs::is_id_continue)); + } + + + //--- islower() --------------------------------------- + /** \brief Returns true if all cased characters in the string are lowercase and there is at least one cased character, or false otherwise. */ + [[nodiscard]] + inline const bool islower() const noexcept + { + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_lower); + } + + + //--- isnumeric() ------------------------------------- + /** \brief Returns true if all characters in the string are numeric characters, and there is at least one character, or false otherwise. + * + * CAUTION: current implementation just returns isdecimal() result, + * while the description of isnumeric() should be this one: + * Numeric characters include digit characters, and all characters + * that have the Unicode numeric value property. Formally, numeric + * characters are those with the property value Numeric_Type=Digit, + * Numeric_Type=Decimal or Numeric_Type=Numeric. + */ + [[nodiscard]] + inline const bool isnumeric() const noexcept + { + return isdecimal(); + } + + + //--- isprintable() ----------------------------------- + /** \brief Returns true if all characters in the string are printable or if the string is empty, or false otherwise. + * + * Nonprintable characters are those characters defined in the Unicode + * character database as "Other" or "Separator", excepting the ASCII + * space (0x20) which is considered printable. + */ + [[nodiscard]] + inline const bool isprintable() const noexcept + { + return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_printable); + } + + + //--- ispunctuation() --------------------------------- + /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ + [[nodiscard]] + inline const bool ispunctuation() const noexcept + { + return this->size() == 1 && pcs::is_punctuation((*this)[0]); + } + + + //--- isspace() --------------------------------------- + /** \brief Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise. */ + [[nodiscard]] + inline const bool isspace() const noexcept + { + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_space); + } + + + //--- istitle() --------------------------------------- + /** \brief Returns true if the string is a titlecased string and there is at least one character, or false otherwise. + * + * For instance uppercase characters may only follow uncased + * characters and lowercase characters only cased ones. + * + * CAUTION: current implementation only tests for uppercase + * characters following whitespaces and lowercase characters + * anywhere else. + */ + [[nodiscard]] + inline const bool istitle() const noexcept + { + return !this->empty() && this->title() == *this; + } + + + //--- isupper() --------------------------------------- + /** \brief Returns true if all cased characters in the string are uppercase and there is at least one cased character, or false otherwise. */ + [[nodiscard]] + inline const bool isupper() const noexcept + { + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_upper); + } + + + //--- is_words_sep() ---------------------------------- + /** \brief Returns true if there are only whitespace and punctuation characters in the string and there is at least one character, or false otherwise. */ + [[nodiscard]] + inline const bool is_words_sep() const noexcept + { + return !this->empty() && + std::all_of( + this->cbegin(), + this->cend(), + [](const value_type ch) { return pcs::is_space(ch) || pcs::is_punctuation(ch); } + ); + } + + + //--- join() ------------------------------------------ + /** \brief Returns a string which is the concatenation of the strings in the array parameter. + * + * The separator between elements is the string to which this method is applied. + */ + template + [[nodiscard]] + CppStringT join(const std::array& strs) const noexcept + { + if (strs.empty()) [[unlikely]] + return CppStringT(); + + auto str_it = strs.cbegin(); + CppStringT res{ *str_it++ }; + while (str_it != strs.cend()) [[likely]] + res += *this + *str_it++; + return res; + } + + /** \brief Returns a string which is the concatenation of the strings in the vector parameter. + * + * The separator between elements is the string to which this method is applied. + */ + [[nodiscard]] + CppStringT join(const std::vector& strs) const noexcept + { + if (strs.empty()) [[unlikely]] + return CppStringT(); + + auto str_it = strs.cbegin(); + CppStringT res{ *str_it++ }; + while (str_it != strs.cend()) [[likely]] + res += *this + *str_it++; + return res; + } + + /** \brief Returns a string which is the concatenation of the strings in the parameters list. + * + * The separator between elements is the string to which this method is applied. + */ + template + [[nodiscard]] + inline CppStringT join(const CppStringT& first, const NextCppStringsT&... others) const noexcept + requires (sizeof...(others) > 0) + { + return first + *this + this->join(others...); + } + + /** \brief Single parameter signature. Returns a copy of this parameter. */ + [[nodiscard]] + inline CppStringT join(const CppStringT& s) const noexcept + { + return s; + } + + /** \brief Empty parameters list signature. Returns a copy of current string. */ + [[nodiscard]] + inline const CppStringT join() const noexcept + { + return *this; + } + + + //--- ljust() ----------------------------------------- + /** \brief Returns the string left justified in a string of length width. + * + * Padding is done using the specified fillchar (default is an ASCII space). + * The original string is returned if width is less than or equal to len(s). + */ + [[nodiscard]] + inline CppStringT ljust(const size_type width, const value_type fillch = value_type(' ')) const noexcept + { + if (this->size() >= width) [[unlikely]] + return *this; + else [[likely]] + return CppStringT(width - this->size(), fillch) + *this; + } + + + //--- lower () ----------------------------------------- + /** \brief In-place replaces all characters of the string with their lowercase conversion. Returns a reference to string. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + inline CppStringT& lower() noexcept + { + std::transform( + this->begin(), + this->end(), + this->begin(), + [&](value_type ch) { return this->lower(ch); } + ); + return *this; + } + + /** \brief Returns lowercase conversion of the character. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + [[nodiscard]] + static inline const value_type lower(const value_type ch) noexcept + { + return value_type(std::tolower(ch)); + } + + + //--- lstrip() ---------------------------------------- + /** \brief Returns a copy of the string with leading characters removed. + * + * The passed string specifies the set of characters to be removed. + * The chars argument is not a prefix; rather, all combinations of + * its values are stripped. + * To remove a prefix, rather call method 'removeprefix()'. + */ + [[nodiscard]] + inline CppStringT lstrip(const CppStringT& removedchars) const noexcept + { + for (auto it = this->cbegin(); it != this->cend(); ++it) [[likely]] + if (std::none_of(removedchars.cbegin(), removedchars.cend(), [it](const value_type ch) { return *it == ch; })) [[likely]] + return CppStringT(it, this->cend()); + return CppStringT(); + } + + /** \brief Returns a copy of the string with leading whitespaces removed. */ + [[nodiscard]] + inline CppStringT lstrip() const noexcept + { + for (auto it = this->cbegin(); it != this->cend(); ++it) [[likely]] + if (*it != value_type(' ')) [[unlikely]] + return CppStringT(it, this->cend()); + return CppStringT(); + } + + + //--- operator () ------------------------------------- + /** \brief Generates a new string according to the specified slice. + * + * A slice is a range specified as [start, stop, step]. It may + * also be specified as [start, stop] in which case step = 1, + * or as [stop] in wich case start = 0 and step = 1. + * Values may be negative: negative step means reverse running + * and negative start or stop is relative to the end of the + * string. + * Notice: the stop value specifies an out of bounds index. + * \see class Slice and all its inheriting classes. + */ + template + requires std::is_signed_v + [[nodiscard]] + CppStringT operator() (Slice slice) const noexcept + { + // optimization on 1 by 1 step + if (slice.step() == 1) [[likely]] { + slice.begin(*this); + if (slice.start() < slice.stop()) [[likely]] + return this->substr(size_type(slice.start()), size_type(slice.stop() - slice.start() + 1)); + else [[unlikely]] + return CppStringT(); + } + + CppStringT res{}; + + // optimization on reversed 1 by 1 step + if (slice.step() == -1) { + slice.begin(*this); + if (slice.stop() < slice.start()) [[likely]] { + res = this->substr(size_type(slice.stop()), size_type(slice.start() - slice.stop() + 1)); + std::ranges::reverse(res); // notice: may use vectorization if available + } + return res; + } + + // finally, no trivial optimization -- and naive implementation... + for (slice.begin(*this); !slice.end(); ++slice) + res += (*this)[size_type(*slice)]; + + return res; + } + + /** \brief Generates a new string according to the specified slicing values. */ + [[nodiscard]] + inline CppStringT operator() (const long long start, const long long stop, const long long step = 1) const noexcept + { + Slice slice(start, stop, step); + return (*this)(slice); + } + + + //--- operator * -------------------------------------- + /** \brief Generates a new string with count times the content of this string. */ + [[nodiscard]] + CppStringT operator* (std::int64_t count) const noexcept + { + if (count <= 0) [[unlikely]] + return CppStringT(); + + CppStringT res(*this); + while (--count) [[likely]] + res += *this; + return res; + } + + + //--- partition() ------------------------------------- + /** \brief Splits the string at the first occurrence of sep, and returns a 3-items vector containing the part before the separator, the separator itself, and the part after the separator. + * + * If the separator is not found, returns a 3-items vector + * containing the string itself, followed by two empty strings. + */ + [[nodiscard]] + std::vector partition(const CppStringT& sep) const noexcept + { + const size_type sep_index = find(sep); + if (sep_index == CppStringT::npos) { + const CppStringT empty{}; + return std::vector({ *this, empty, empty }); + } + else { + const size_type third_index = sep_index + sep.size(); + const size_type third_size = this->size() - third_index + 1; + return std::vector({ this->substr(0, sep_index), sep, this->substr(third_index, third_size) }); + } + } + + + //--- removeprefix() ---------------------------------- + /** \brief If the string starts with the prefix string, returns a new string with the prefix removed. Otherwise, returns a copy of the original string. */ + [[nodiscard]] + inline CppStringT removeprefix(const CppStringT& prefix) const noexcept + { + if (this->startswith(prefix)) { + const size_type prefix_length = prefix.size(); + return this->substr(prefix_length, this->size() - prefix_length + 1); + } + else + return *this; + } + + + //--- removesuffix() ---------------------------------- + /** \brief If the string ends with the suffix string, returns a new string with the suffix removed. Otherwise, returns a copy of the original string. */ + [[nodiscard]] + inline CppStringT removesuffix(const CppStringT& suffix) const noexcept + { + if (this->endswith(suffix)) { + const size_type suffix_length = suffix.size(); + return this->substr(0, this->size() - suffix_length); + } + else + return *this; + } + + + //--- replace() --------------------------------------- + /** \brief Returns a copy of the string with first count occurrences of substring 'old' replaced by 'new_'. */ + [[nodiscard]] + CppStringT replace(const CppStringT& old, const CppStringT& new_, size_type count = -1) const noexcept + { + if (old == new_ || old.empty()) [[unlikely]] + return *this; + + CppStringT res{}; + size_type prev_index = 0; + size_type current_index = 0; + while (count > 0 && (current_index = this->find(old, prev_index)) != CppStringT::npos) { + res += this->substr(prev_index, current_index - prev_index) + new_; + prev_index = current_index + 1; + --count; + } + + if (prev_index < this->size()) [[likely]] + res += this->substr(prev_index, this->size() - prev_index); + + return res; + } + + + //--- rfind() ----------------------------------------- + /** \brief Returns the highest index in the string where substring sub is found within the slice str[start:end], or -1 (i.e. 'npos') if sub is not found. + * + * Note that this is an offset from the start of the string, not the end. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains(). + * + * CAUTION: empty substrings are considered to be in the string if start and + * end positions are both less than the string size and if start <= end. The + * returned position is the size of the string. + * + * \see find(), find_n() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + [[nodiscard]] + inline constexpr size_type rfind(const CppStringT& sub, const size_type start, const size_type end) const noexcept + { + if (start > end) [[unlikely]] + return CppStringT::npos; + else if (sub.empty()) [[unlikely]] + return 0; + else [[likely]] { + const size_type found_pos{ this->substr(start, end - start + 1).rfind(sub) }; + return (found_pos == CppStringT::npos) ? CppStringT::npos : found_pos + start; + } + } + + + /** \brief Returns the highest index in the string where substring sub is found starting at start position in string, or -1 (i.e. 'npos') if sub is not found. + * + * Note that this is an offset from the start of the string, not the end. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains(). + * + * CAUTION: empty substrings are considered to be in the string if start and + * end positions are both less than the string size and if start <= end. The + * returned position is the size of the string. + * + * \see find(), find_n() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + [[nodiscard]] + inline constexpr size_type rfind(const CppStringT& sub, const size_type start) const noexcept + { + return rfind(sub, start, this->size() - 1); + } + + + /** \brief Returns the highest index in the string where C-substring sub is found in the whole string, or -1 (i.e. 'npos') if sub is not found. + * + * Note that this is an offset from the start of the string, not the end. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains(). + * + * CAUTION: empty substrings are considered to be in the string if start and + * end positions are both less than the string size and if start <= end. The + * returned position is the size of the string. + * + * \see find(), find_n() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + [[nodiscard]] + inline constexpr size_type rfind(const CppStringT& sub) const noexcept + { + return MyBaseClass::rfind(sub); + } + + + //--- rfind_n() --------------------------------------- + /** \brief Returns the highest index in the string where substring sub is found within the slice str[start:start+count-1], or -1 (i.e. 'npos') if sub is not found. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains_n(). + * + * \see find(), find_n() and rfind(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + [[nodiscard]] + inline constexpr size_type rfind_n(const CppStringT& sub, const size_type start, const size_type count) const noexcept + { + return rfind(sub, start, start + count - 1); + } + + /** \brief Returns the highest index in the string where substring sub is found within the slice str[0:count-1], or -1 (i.e. 'npos') if sub is not found. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains_n(). + * + * \see find(), find_n() and rfind(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + [[nodiscard]] + inline constexpr size_type rfind_n(const CppStringT& sub, const size_type count) const noexcept + { + if (count == 0) [[unlikely]] + return CppStringT::npos; + else [[likely]] + return rfind(sub, 0, count - 1); + } + + + //--- rindex() ---------------------------------------- + /** \brief Like rfind(sub, start, end), but raises NotFoundException when the substring is not found. + * + * \see index(), index_n() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + [[nodiscard]] + inline constexpr size_type rindex(const CppStringT& sub, const size_type start, const size_type end) const + { + const size_type ret_value = rfind(sub, start, end); + if (ret_value == CppStringT::npos) + throw NotFoundException("substring not found in string"); + else + return ret_value; + } + + /** \brief Like rfind(sub, start), but raises NotFoundException when the substring is not found. + * + * \see index(), index_n() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + [[nodiscard]] + inline constexpr size_type rindex(const CppStringT& sub, const size_type start) const + { + return rindex(sub, start, this->size() - 1); + } + + /** \brief Like rfind(sub), but raises NotFoundException when the substring is not found. + * + * \see index(), index_n() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + [[nodiscard]] + inline constexpr size_type rindex(const CppStringT& sub) const + { + return rindex(sub, 0, this->size() - 1); + } + + + //--- rindex_n() -------------------------------------- + /** \brief Like rfind_n(sub, start, count), but raises NotFoundException when the substring is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + [[nodiscard]] + inline constexpr size_type rindex_n(const CppStringT& sub, const size_type start, const size_type count) const + { + return rindex(sub, start, start + count - 1); + } + + /** \brief Like rfind_n(sub, count), but raises NotFoundException when the substring is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + [[nodiscard]] + inline constexpr size_type rindex_n(const CppStringT& sub, const size_type count) const + { + return rindex(sub, 0, count); + } + + + //--- rjust() ----------------------------------------- + /** \brief Returns the string right justified in a string of length width. + * + * Padding is done using the specified fillchar (default is an ASCII space). + * The original string is returned if width is less than or equal to len(s). + */ + [[nodiscard]] + inline CppStringT rjust(const size_type width, const value_type fillch = value_type(' ')) const noexcept + { + if (this->size() >= width) [[unlikely]] + return *this; + else [[likely]] + return *this + CppStringT(width - this->size(), fillch); + } + + + //--- rpartition() ------------------------------------- + /** \brief Splits the string at the last occurrence of sep, and returns a 3-items vector containing the part before the separator, the separator itself, and the part after the separator. + * + * If the separator is not found, returns a 3-items vector + * containing the string itself, followed by two empty strings. + */ + [[nodiscard]] + std::vector rpartition(const CppStringT& sep) const noexcept + { + const size_type sep_index = rfind(sep); + if (sep_index == CppStringT::npos) { + const CppStringT empty{}; + return std::vector({ *this, empty, empty }); + } + else { + const size_type third_index = sep_index + sep.size(); + const size_type third_size = this->size() - third_index + 1; + return std::vector({ this->substr(0, sep_index), sep, this->substr(third_index, third_size) }); + } + } + + + //--- rsplit() ---------------------------------------- + /** \brief Returns a vector of the words in the whole string, as seperated with whitespace strings. + * + * Notice: consecutive whitespaces are each regarded as a + * single separator. So, they each separate empty strings. + */ + [[nodiscard]] + inline std::vector rsplit() noexcept + { + return split(); + } + + /** \brief Returns a vector of the words in the whole string, using sep as the delimiter string. */ + [[nodiscard]] + inline std::vector rsplit(const CppStringT& sep) noexcept + { + return split(sep); + } + + /** \brief Returns a vector of the words in the string, as seperated with whitespace strings. At most maxsplit splits are done, the rightmost ones. */ + [[nodiscard]] + inline std::vector rsplit(const size_type maxsplit) noexcept + { + return rsplit(CppStringT(value_type(' ')), maxsplit); + } + + /** \brief Returns a vector of the words in the string, using sep as the delimiter string. At most maxsplit splits are done, the rightmost ones. */ + [[nodiscard]] + std::vector rsplit(const CppStringT& sep, const size_type maxsplit) noexcept + { + std::vector res{}; + + if (maxsplit == 0) [[unlikely]] { + res.push_back({ *this }); + } + else [[likely]] { + const size_type sep_size{ sep.size() }; + std::vector indexes{}; + CppStringT tmp{ *this }; + size_type count{ maxsplit }; + size_type index{ 0 }; + + while ((index = tmp.rfind(sep)) != CppStringT::npos && count > 0) { + indexes.insert(indexes.begin(), index); + if (index == 0) + break; + tmp = tmp.substr(0, index); + count--; + } + + if (indexes.size() == 0) + res.push_back(*this); + else { + index = 0; + for (const size_type ndx : indexes) { + res.push_back(this->substr(index, ndx - index)); + index = ndx + sep_size; + } + } + res.push_back(this->substr(index, this->size() - index)); + } + + return res; + } + + + //--- rstrip() ---------------------------------------- + /** \brief Returns a copy of the string with trailing characters removed. + * + * The passed string specifies the set of characters to be removed. + * The chars argument is not a prefix; rather, all combinations of + * its values are stripped. + * To remove a suffix, rather call method 'removesuffix()'. + */ + [[nodiscard]] + inline CppStringT rstrip(const CppStringT& removedchars) const noexcept + { + for (auto it = this->crbegin(); it != this->crend(); ++it) + if (std::none_of(removedchars.cbegin(), removedchars.cend(), [it](const value_type ch) { return *it == ch; })) + return CppStringT(this->cbegin(), this->cbegin() + this->size() - (it - this->crbegin())); + return CppStringT(); + } + + /** \brief Returns a copy of the string with trailing whitespaces removed. */ + [[nodiscard]] + inline CppStringT rstrip() const noexcept + { + for (auto it = this->crbegin(); it != this->crend(); ++it) + if (*it != value_type(' ')) + return CppStringT(this->cbegin(), this->cbegin() + this->size() - (it - this->crbegin())); + return CppStringT(); + } + + + //--- split() ----------------------------------------- + /** \brief Returns a vector of the words in the whole string, as seperated with whitespace strings. + * + * Notice: consecutive whitespaces are each regarded as a + * single separator. So, they each separate empty strings. + */ + [[nodiscard]] + inline std::vector split() noexcept + { + std::vector res; + const CppStringT whitespace(value_type(' ')); + for (const auto& word : *this | std::views::split(whitespace)) + res.push_back(CppStringT(word.begin(), word.end())); + return res; + } + + /** \brief Returns a vector of the words in the whole string, using sep as the delimiter string. + * + * Notice: consecutive delimiters are not grouped together and are + * deemed to delimit empty strings (for example, "1,,2".split(",") + * returns {"1", "", "2"}). The sep argument may consist of multiple + * characters (for example, "1<>2<>3".split("<>") returns {"1", "2", + * "3"]). Splitting an empty string with a specified separator + * returns {""}. + */ + [[nodiscard]] + inline std::vector split(const CppStringT& sep) noexcept + { + std::vector res; + for (const auto& word : *this | std::views::split(sep)) + res.push_back(CppStringT(word.begin(), word.end())); + return res; + } + + /** \brief Returns a vector of the words in the string, as seperated with whitespace strings. At most maxsplit splits are done, the leftmost ones. */ + [[nodiscard]] + inline std::vector split(const size_type maxsplit) noexcept + { + return split(CppStringT(value_type(' ')), maxsplit); + } + + /** \brief Returns a vector of the words in the string, using sep as the delimiter string. At most maxsplit splits are done, the leftmost ones. */ + [[nodiscard]] + std::vector split(const CppStringT& sep, const size_type maxsplit) noexcept + { + std::vector res{}; + + if (maxsplit == 0) [[unlikely]] { + res.push_back(*this); + } + else [[likely]] { + const size_type sep_size{ sep.size() }; + std::vector indexes{}; + size_type count{ maxsplit }; + size_type index{ 0 }; + + while ((index = this->find(sep, index)) != CppStringT::npos && count > 0) { + indexes.push_back(index); + if (index == this->size()) + break; + index += sep_size; + count--; + } + + if (indexes.size() == 0) + res.push_back(*this); + else { + index = 0; + for (const size_type ndx : indexes) { + res.push_back(this->substr(index, ndx - index)); + index = ndx + sep_size; + } + } + res.push_back(this->substr(index, this->size() - index)); + } + + return res; + } + + + //--- splitlines() ------------------------------------ + /** \brief Return a list of the lines in the string, breaking at line boundaries. + * + * Line breaks are not included in the resulting list unless keepends is given and true. + * + * This method splits on the following line boundaries. In particular, the boundaries are a superset of universal newlines: + * \n Line Feed + * \r Carriage Return + * \r\n Carriage Return + Line Feed + * \v or \x0b Line Tabulation + * \f or \x0c Form Feed + * \x1c File Separator + * \x1d Group Separator + * \x1e Record Separator + * Next separators values, detected by Python method splitlines(), are currently NOT detected by CppStrings + * \x85 Next Line (C1 Control Code) + * \u2028 Line Separator + * \u2029 Paragraph Separator + */ + [[nodiscard]] + std::vector splitlines(const bool keep_end = false) const noexcept + { + std::vector res{}; + CppStringT current{}; + bool prev_cr = false; + + for (const value_type ch : *this) { + switch (ch) { + case 0x0b: [[unlikely]] // Line Tabulation, \v as well as \x0b and \013 + case 0x0c: [[unlikely]] // Form Feed, \f as well as \x0c and \014 + case 0x1c: [[unlikely]] // File Separator, or \034 + case 0x1d: [[unlikely]] // Group Separator, or \035 + case 0x1e: [[unlikely]] // Record Separator, or \036 + //case L'\u0085': [[unlikely]] // Next Line (C1 Control Code), or \0205 + //case L'\u2028': [[unlikely]] // Line Separator + //case L'\u2029': [[unlikely]] // Paragraph Separator + if (prev_cr) [[unlikely]] { + res.push_back(current); + current.clear(); + } + if (keep_end) [[unlikely]] + current += ch; + res.push_back(current); + current.clear(); + prev_cr = false; + break; + + case value_type('\r'): [[unlikely]] // Line Feed + if (prev_cr) [[unlikely]] { + res.push_back(current); + current.clear(); + } + if (keep_end) [[unlikely]] + current += ch; + prev_cr = true; + break; + + case value_type('\n'): [[unlikely]] // Carriage return + if (keep_end) [[unlikely]] + current += ch; + res.push_back(current); + current.clear(); + prev_cr = false; + break; + + + default: [[likely]] + if (prev_cr) [[unlikely]] { + res.push_back(current); + current.clear(); + prev_cr = false; + } + current += ch; + break; + } + } + + if (prev_cr) [[unlikely]] { + res.push_back(current); + } + + return res; + } + + + //--- startswith() ------------------------------------ + /** \brief Returns true if the string starts with the specified prefix, otherwise returns false. Test begins at start position and stops at end position. */ + [[nodiscard]] + inline const bool startswith(const CppStringT& prefix, const size_type start, const size_type end) const noexcept + { + return this->substr(start, end - start + 1).MyBaseClass::starts_with(prefix); + } + + /** \brief Returns true if the string starts with the specified prefix, otherwise returns false. Test begins at start position and stops at end of string. */ + [[nodiscard]] + inline const bool startswith(const CppStringT& prefix, const size_type start) const noexcept + { + return startswith(prefix, start, this->size() - 1); + } + + /** \brief Returns true if the string starts with the specified prefix, otherwise returns false. Test runs on the whole string. */ + [[nodiscard]] + inline const bool startswith(const CppStringT& prefix) const noexcept + { + return this->starts_with(prefix); + } + + /** \brief Returns true if the string starts with any of the specified prefixes, otherwise returns false. Test begins at start position and stops at end of string. */ + [[nodiscard]] + inline const bool startswith(const std::initializer_list& prefixes, const size_type start, const size_type end) const noexcept + { + if (start > end) + return false; + + CppStringT tmp(this->substr(start, end)); + for (auto& prefix : prefixes) { + if (tmp.starts_with(prefix)) + return true; + } + return false; + } + + + //--- startswith_n() ---------------------------------- + /** \brief Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions. */ + [[nodiscard]] + inline const bool startswith_n(const CppStringT& prefix, const size_type start, const size_type count) const noexcept + { + return this->substr(start, count).MyBaseClass::starts_with(prefix); + } + + /** \brief Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions. */ + [[nodiscard]] + inline const bool startswith_n(const CppStringT& prefix, const size_type count) const noexcept + { + return this->substr(0, count).MyBaseClass::starts_with(prefix); + } + + /** \brief Returns true if the string starts with any of the specified suffixes, otherwise returns false. Test begins at start position and stops after count positions. */ + [[nodiscard]] + inline const bool startswith_n(const std::initializer_list& prefix, const size_type start, const size_type count) const noexcept + { + return startswith(prefix, start, count); + } + + + //--- strip() ----------------------------------------- + /** \brief Returns a copy of the string with the leading and trailing characters removed. + * + * The passed string specifies the set of characters to be removed. + * The chars argument is not a prefix; rather, all combinations of + * its values are stripped. + */ + [[nodiscard]] + inline CppStringT strip(const CppStringT& removedchars) const noexcept + { + return this->rstrip(removedchars).lstrip(removedchars); + } + + /** \brief Returns a copy of the string with the leading and trailing whitespaces removed. */ + [[nodiscard]] + inline CppStringT strip() const noexcept + { + return this->rstrip().lstrip(); + } + + + //--- substr() ---------------------------------------- + /** \brief Returns a copy of the string, starting at index start and ending after count characters. */ + [[nodiscard]] + inline CppStringT substr(const size_type start, const size_type count = -1) const noexcept + { + if (start > this->size()) [[unlikely]] + return CppStringT(); + + const size_type width{ std::min(count, this->size() - start + 1) }; + return CppStringT(MyBaseClass::substr(start, width)); + } + + + //--- swapcase() -------------------------------------- + /** \brief Returns a copy of the string with uppercase characters converted to lowercase and vice versa. + * + * Note that it is not necessarily true that s.swapcase().swapcase() == s. + */ + [[nodiscard]] + inline CppStringT swapcase() const noexcept + { + CppStringT res; + std::ranges::transform(*this, std::back_inserter(res), [](const value_type c) -> value_type { return pcs::swap_case(c); }); + return res; + } + + + //--- title() ----------------------------------------- + /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ + [[nodiscard]] + CppStringT title() const noexcept + { + const CppStringT whitespace(value_type(' ')); + + CppStringT res(*this); + std::vector words = res.split(whitespace); + + for (CppStringT& word : words) + word = word.capitalize(); + + return whitespace.join(words); + } + + + //--- translate() ------------------------------------- + /** \brief Returns a copy of the string in which each character has been mapped through the given translation table. + * + * The table must be of type CppStringT::TransTable. When a character + * to be translated is not available as an entry in the tranlation + * table, it is set as is in the resulting string. + */ + [[nodiscard]] + CppStringT translate(TransTable& table) noexcept + { + CppStringT res{}; + for (auto ch : *this) { + try { res += table[ch]; } + catch (...) { res += ch; } + } + return res; + } + + + //--- upper () ----------------------------------------- + /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + inline CppStringT& upper() noexcept + { + CppStringT res{}; + std::ranges::transform(*this, std::back_inserter(res), [&](const value_type ch) -> value_type { return this->upper(ch); }); + return *this = res; + } + + /** \brief Returns uppercase conversion of the character. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + [[nodiscard]] + static inline const value_type upper(const value_type ch) noexcept + { + return value_type(std::toupper(ch)); + } + + + //--- zfill() ----------------------------------------- + /** \brief Returns a copy of the string left filled with ASCII '0' digits to make a string of length width. + * + * A leading sign prefix ('+'/'-') is handled by inserting the padding + * after the sign character rather than before. The original string is + * returned if width is less than or equal to len(s). + */ + [[nodiscard]] + inline CppStringT zfill(const size_type width) const noexcept + { + if (this->size() >= width) [[unlikely]] + return *this; + + const size_type padding_width = width - this->size(); + if ((*this)[0] == '-' || (*this)[0] == '+') [[unlikely]] + return (*this)[0] + this->substr(1, this->size() - 1).ljust(width - 1, value_type('0')); + else [[likely]] + return this->ljust(width, value_type('0')); + } + + }; + + + //===== litteral operators ============================ + /** \brief Forms a CppString literal. */ + inline CppString operator""_cs(const char* str, std::size_t len) + { + return CppString(CppString::MyBaseClass(str, len)); + } + + /** \brief Forms a CppWString literal. */ + inline CppWString operator""_cs(const wchar_t* str, std::size_t len) + { + return CppWString(CppWString::MyBaseClass(str, len)); + } + + + //===== Slices ======================================== + //--- slices base ------------------------------------- + /** \brief Base class for slices, with start, stop and step specified values. */ + template + requires std::is_signed_v + class Slice + { + public: + static constexpr IntT DEFAULT{ std::numeric_limits::min() }; + + //--- Constructors / Destructor ------------------- + Slice(const IntT start = DEFAULT, const IntT stop = DEFAULT, const IntT step = DEFAULT) noexcept //!< Valued constructor + : _start(start) + , _stop(stop) + , _step(step) + {} + + virtual ~Slice() noexcept = default; //!< Default destructor. + + + //--- iterating ----------------------------------- + template +#if (defined(_HAS_CXX20) && _HAS_CXX20) + requires std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v +#else + requires std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v +#endif + inline const IntT begin(const CppStringT& str) noexcept //!< starts iterating on specified CppString. + { + return _prepare_iterating(IntT(str.size())); + } + + [[nodiscard]] + inline const bool end() const noexcept //!< returns true when iterating is over, or false otherwise. + { + return _step == 0 ? true : _step > 0 ? _index >= _stop : _index <= _stop; + } + + inline Slice operator++() noexcept //!< iterates one step, pre-increment. Caution: index may be out of bounds. Check '!end()' before dereferencing the slice. + { + _index += _step; + return *this; + } + + inline Slice operator++(int) noexcept //!< iterates one step, post-increment. Caution: index may be out of bounds. Check '!end()' before dereferencing the slice. + { + _index += _step; + return *this; + } + + [[nodiscard]] + inline const IntT operator*() noexcept //!< dereferences the slice. + { + return _index; + } + + //--- properties ---------------------------------- + inline IntT start() { return _start; } //!< Returns the start index of this slide + inline IntT stop() { return _stop; } //!< Returns the stop index of this slide + inline IntT step() { return _step; } //!< Returns the step value of this slide + + + private: + IntT _start{ 0 }; + IntT _stop{ DEFAULT }; + IntT _step{ 1 }; + + IntT _index{ 0 }; + + [[nodiscard]] + const IntT _prepare_iterating(const IntT str_size) noexcept + { + if (_start == DEFAULT) { + if (_step < 0 && _step != DEFAULT) [[unlikely]] + _start = str_size - 1; + else [[likely]] + _start = 0; + } + else if (_start < 0) { + _start += str_size; + if (_start < 0) [[unlikely]] + _start = 0; + } + else if (_start >= str_size) { + if (_step < 0 && _step != DEFAULT) + _start = str_size - 1; + } + + if (_stop == DEFAULT) { + if (_step < 0 && _step != DEFAULT) [[unlikely]] + _stop = 0; + else + _stop = str_size; + } + else if (_stop < 0) { + _stop += str_size; + if (_stop < 0) + _stop = 0; + } + else if (_stop > str_size) + _stop = str_size; + + if (_step == DEFAULT) [[likely]] + _step = 1; + if (_step < 0) [[unlikely]] { + if (_start <= _stop) + _step = 0; // will force end() to true + } + else [[unlikely]] { + if (_start >= _stop) + _step = 0; // will force end() to true + } + + return _index = _start; + } + }; + + + /** \brief Class of slices with default stop and step values. */ + template + requires std::is_signed_v + struct StartSlice : public Slice + { + using MyBaseClass = Slice; + + //--- Constructors / Destructor ------------------- + inline StartSlice(const IntT start = MyBaseClass::DEFAULT) noexcept //!< Valued constructor + : MyBaseClass(start, MyBaseClass::DEFAULT, 1) + {} + + virtual ~StartSlice() noexcept = default; //!< Default destructor. + }; + + + /** \brief Class of slices with default start and step values. */ + template + requires std::is_signed_v + struct StopSlice : public Slice + { + using MyBaseClass = Slice; + + //--- Constructors / Destructor ------------------- + inline StopSlice(const IntT stop = MyBaseClass::DEFAULT) noexcept //!< Valued constructor + : MyBaseClass(MyBaseClass::DEFAULT, stop, 1) + {} + + virtual ~StopSlice() noexcept = default; //!< Default destructor. + }; + + + /** \brief Class of slices with default start and stop values. */ + template + requires std::is_signed_v + struct StepSlice : public Slice + { + using MyBaseClass = Slice; + + //--- Constructors / Destructor ------------------- + inline StepSlice(const IntT step = MyBaseClass::DEFAULT) noexcept //!< Valued constructor + : MyBaseClass(MyBaseClass::DEFAULT, MyBaseClass::DEFAULT, step) + {} + + virtual ~StepSlice() noexcept = default; //!< Default destructor. + }; + + + /** \brief Class of slices with default step values. */ + template + requires std::is_signed_v + struct StartStopSlice : public Slice + { + using MyBaseClass = Slice; + + //--- Constructors / Destructor ------------------- + inline StartStopSlice(const IntT start = MyBaseClass::DEFAULT, const IntT stop = MyBaseClass::DEFAULT) noexcept //!< Valued constructor + : MyBaseClass(start, stop, 1) + {} + + virtual ~StartStopSlice() noexcept = default; //!< Default destructor. + }; + + + /** \brief Class of slices with default stop values. */ + template + requires std::is_signed_v + struct StartStepSlice : public Slice + { + using MyBaseClass = Slice; + + //--- Constructors / Destructor ------------------- + inline StartStepSlice(const IntT start = MyBaseClass::DEFAULT, const IntT step = MyBaseClass::DEFAULT) noexcept //!< Valued constructor + : MyBaseClass(start, MyBaseClass::DEFAULT, step) + {} + + virtual ~StartStepSlice() noexcept = default; //!< Default destructor. + + }; + + + /** \brief Class of slices with default start values. */ + template + requires std::is_signed_v + struct StopStepSlice : public Slice + { + using MyBaseClass = Slice; + + //--- Constructors / Destructor ------------------- + inline StopStepSlice(const IntT stop = MyBaseClass::DEFAULT, const IntT step = MyBaseClass::DEFAULT) noexcept //!< Valued constructor + : MyBaseClass(MyBaseClass::DEFAULT, stop, step) + {} + + virtual ~StopStepSlice() noexcept = default; //!< Default destructor. + }; + + + //===== templated chars classes =========================== + //--- is_alpha() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const bool is_alpha(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_alpha(const char ch) noexcept + { + return static_cast(std::isalpha(static_cast(ch))); + } + + /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_alpha(const wchar_t ch) noexcept + { + return static_cast(std::iswalpha(ch)); + } + + + //--- is_ascii() ------------------------------------------ + /** \brief Returns true if character has code point in the range U+0000-U+007F. */ + template + [[nodiscard]] + inline const bool is_ascii(const CharT ch) noexcept + { + return CharT(0x00) <= ch && ch <= CharT(0x7f); + } + + + //--- is_decimal() ---------------------------------------- + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const bool is_decimal(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character is a decimal digit, or false otherwise. */ + template<> + [[nodiscard]] + inline const bool is_decimal(const char ch) noexcept + { + return static_cast(std::isdigit(static_cast(ch))); + } + + /** \brief Returns true if character is a decimal digit, or false otherwise. */ + template<> + [[nodiscard]] + inline const bool is_decimal(const wchar_t ch) noexcept + { + return (const bool)std::iswdigit(ch); + } + + + //--- is_digit() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const bool is_digit(const CharT ch) noexcept + { + return pcs::is_decimal(ch); + } + + /** \brief Returns true if character is a decimal digit, or false otherwise. */ + template<> + [[nodiscard]] + inline const bool is_digit(const char ch) noexcept + { + return pcs::is_decimal(ch); + } + + /** \brief Returns true if character is a decimal digit, or false otherwise. */ + template<> + [[nodiscard]] + inline const bool is_digit(const wchar_t ch) noexcept + { + return pcs::is_decimal(ch); + } + + + //--- is_id_continue() ------------------------------------ + /** \brief Returns true if character is a continuing char for identifiers, or false otherwise. */ + template + [[nodiscard]] + inline const bool is_id_continue(const CharT ch) noexcept + { + return pcs::is_id_start(ch) || pcs::is_decimal(ch); + } + + + //--- is_id_start() --------------------------------------- + /** \brief Returns true if character is a starting char for identifiers, or false otherwise. */ + template + [[nodiscard]] + inline const bool is_id_start(const CharT ch) noexcept + { + return pcs::is_alpha(ch) || ch == CharT('_'); + } + + + //--- is_lower() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const bool is_lower(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_lower(const char ch) noexcept + { + return std::islower(static_cast(ch)); + } + + /** \brief Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_lower(const wchar_t ch) noexcept + { + return std::iswlower(ch); + } + + + //--- is_numeric() ---------------------------------------- + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const bool is_numeric(const CharT ch) noexcept + { + return pcs::is_decimal(ch); + } + + /** \brief Returns true if character is a decimal digit, or false otherwise. */ + template<> + [[nodiscard]] + inline const bool is_numeric(const char ch) noexcept + { + return pcs::is_decimal(ch); + } + + /** \brief Returns true if character is a decimal digit, or false otherwise. */ + template<> + [[nodiscard]] + inline const bool is_numeric(const wchar_t ch) noexcept + { + return pcs::is_decimal(ch); + } + + + //--- is_printable() -------------------------------------- + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const bool is_printable(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character ch is printable, or false otherwise. */ + template<> + [[nodiscard]] + inline const bool is_printable(const char ch) noexcept + { + return static_cast(std::isprint(static_cast(ch))); + } + + /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_printable(const wchar_t ch) noexcept + { + return static_cast(std::iswprint(ch)); + } + + + //--- is_punctuation() ------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const bool is_punctuation(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_punctuation(const char ch) noexcept + { + return static_cast(std::ispunct(static_cast(ch))); + } + + /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_punctuation(const wchar_t ch) noexcept + { + return static_cast(std::iswpunct(ch)); + } + + + //--- is_space() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const bool is_space(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_space(const char ch) noexcept + { + return static_cast(std::isspace(static_cast(ch))); + } + + /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_space(const wchar_t ch) noexcept + { + return static_cast(std::iswspace(ch)); + } + + + //--- is_upper() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const bool is_upper(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character ch is uppercase, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_upper(const char ch) noexcept + { + return static_cast(std::isupper(static_cast(ch))); + } + + /** \brief Returns true if character ch is uppercase, or false otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const bool is_upper(const wchar_t ch) noexcept + { + return static_cast(std::iswupper(ch)); + } + + + //--- swap_case() ----------------------------------------- + /** \brief Returns the swapped case form of character ch if it exists, or ch itself otherwise. */ + template + [[nodiscard]] + inline const CharT swap_case(const CharT ch) noexcept + { + if (pcs::is_lower(ch)) + return pcs::to_upper(ch); + else if (pcs::is_upper(ch)) + return pcs::to_lower(ch); + else + return ch; + } + + + //--- to_lower() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const CharT to_lower(const CharT ch) noexcept + { + return ch; + } + + /** \brief Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const char to_lower(const char ch) noexcept + { + return std::tolower(static_cast(ch)); + } + + /** \brief Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const wchar_t to_lower(const wchar_t ch) noexcept + { + return std::towlower(ch); + } + + + //--- to_upper() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + [[nodiscard]] + inline const CharT to_upper(const CharT ch) noexcept + { + return ch; + } + + /** \brief Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const char to_upper(const char ch) noexcept + { + return std::toupper(static_cast(ch)); + } + + /** \brief Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings. */ + template<> + [[nodiscard]] + inline const wchar_t to_upper(const wchar_t ch) noexcept + { + return std::towupper(ch); + } + +#if defined(_MSC_VER) +# pragma warning(pop) // to avoid boring warnings with litteral operators definitions +#endif + +} // end of namespace pcs // (pythonic c++ strings) diff --git a/cpp-strings/html/annotated.html b/cpp-strings/html/annotated.html new file mode 100644 index 0000000..cccc0e4 --- /dev/null +++ b/cpp-strings/html/annotated.html @@ -0,0 +1,117 @@ + + + + + + + +cpp-strings: Class List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+
[detail level 123]
+ + + + + + + + + + + +
 Npcs
 CCppStringTThis is the templated base class for all CppString classes
 CNotFoundException
 CTransTableThe internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate
 CSliceBase class for slices, with start, stop and step specified values
 CStartSliceBase class for slices, with start, stop and step specified values
 CStartStepSliceStruct of slices with default step values
 CStartStopSliceStruct of slices with default start and stop values
 CStepSliceStruct of slices with default start and step values
 CStopSliceStruct of slices with default stop and step values
 CStopStepSliceStruct of slices with default stop values
+
+
+
+
+ + + + diff --git a/cpp-strings/html/annotated_dup.js b/cpp-strings/html/annotated_dup.js new file mode 100644 index 0000000..328bcbb --- /dev/null +++ b/cpp-strings/html/annotated_dup.js @@ -0,0 +1,13 @@ +var annotated_dup = +[ + [ "pcs", "namespacepcs.html", [ + [ "CppStringT", "classpcs_1_1_cpp_string_t.html", "classpcs_1_1_cpp_string_t" ], + [ "Slice", "classpcs_1_1_slice.html", "classpcs_1_1_slice" ], + [ "StartSlice", "structpcs_1_1_start_slice.html", "structpcs_1_1_start_slice" ], + [ "StartStepSlice", "structpcs_1_1_start_step_slice.html", "structpcs_1_1_start_step_slice" ], + [ "StartStopSlice", "structpcs_1_1_start_stop_slice.html", "structpcs_1_1_start_stop_slice" ], + [ "StepSlice", "structpcs_1_1_step_slice.html", "structpcs_1_1_step_slice" ], + [ "StopSlice", "structpcs_1_1_stop_slice.html", "structpcs_1_1_stop_slice" ], + [ "StopStepSlice", "structpcs_1_1_stop_step_slice.html", "structpcs_1_1_stop_step_slice" ] + ] ] +]; \ No newline at end of file diff --git a/cpp-strings/html/classes.html b/cpp-strings/html/classes.html new file mode 100644 index 0000000..cac03fe --- /dev/null +++ b/cpp-strings/html/classes.html @@ -0,0 +1,117 @@ + + + + + + + +cpp-strings: Class Index + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class Index
+
+ +
+
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t-members.html b/cpp-strings/html/classpcs_1_1_cpp_string_t-members.html new file mode 100644 index 0000000..184420d --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t-members.html @@ -0,0 +1,235 @@ + + + + + + + +cpp-strings: Member List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT > Member List
+
+
+ +

This is the complete list of members for pcs::CppStringT< CharT, TraitsT, AllocatorT >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
allocator_type typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
capitalize() noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
center(const size_type width, const value_type fillch=value_type(' ')) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
const_iterator typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
const_pointer typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
const_reference typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
const_reverse_iterator typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
contains(const CppStringT &substr) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
contains_n(const CppStringT &sub, const size_type start, const size_type count=-1) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
count(const CppStringT &sub, const size_type start=0, const size_type end=-1) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
count_n(const CppStringT &sub, const size_type start, const size_type length) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
count_n(const CppStringT &sub, const size_type length) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT() (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(const CppStringT &other) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(const CppStringT &other, const AllocatorT &alloc) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(CppStringT &&other) noexcept (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(CppStringT &&other, const AllocatorT &alloc) noexcept (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(MyBaseClass::size_type count, CharT ch) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(const CppStringT &other, size_type pos) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(const CppStringT &other, size_type pos, size_type count) noexcept (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(const CharT *s) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(const CharT *s, size_type count) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(std::initializer_list< CharT > ilist) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(const CharT ch) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(const MyBaseClass &other) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(const MyBaseClass &other, const AllocatorT &alloc) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(MyBaseClass &&other) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(MyBaseClass &&other, const AllocatorT &alloc) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(InputIt first, InputIt last) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
CppStringT(StringViewLike &svl) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inlineexplicit
CppStringT(StringViewLike &svl, size_type pos, size_type n) (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
difference_type typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
endswith(const CppStringT &suffix, const size_type start, const size_type end) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
endswith(const CppStringT &suffix, const size_type end) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
endswith(const CppStringT &suffix) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
endswith(const std::initializer_list< CppStringT > &suffixes, const size_type start, const size_type end) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
endswith_n(const CppStringT &suffix, const size_type start, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
endswith_n(const CppStringT &suffix, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
endswith_n(const std::initializer_list< CppStringT > &suffixes, const size_type start, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
expand_tabs(const size_type tabsize=8) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
find(const CppStringT &sub, const size_type start=0, const size_type end=-1) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
find_n(const CppStringT &sub, const size_type start, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
find_n(const CppStringT &sub, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
format(const std::basic_format_string< T, std::type_identity_t< ArgsT >... > frmt, ArgsT &&... args)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
format(const std::basic_format_string< char, std::type_identity_t< ArgsT >... > frmt, ArgsT &&... args)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
format(const std::basic_format_string< wchar_t, std::type_identity_t< ArgsT >... > frmt, ArgsT &&... args)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
index(const CppStringT &sub, const size_type start=0, const size_type end=-1) constpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
index_n(const CppStringT &sub, const size_type start, const size_type count) constpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
index_n(const CppStringT &sub, const size_type count) constpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
is_words_sep() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isalnum() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isalpha() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isascii() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isdecimal() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isdigit() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isidentifier() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
islower() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isnumeric() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isprintable() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
ispunctuation() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isspace() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
istitle() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
isupper() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
iterator typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
join(const std::array< CppStringT, N > &strs) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
join(const std::vector< CppStringT > &strs) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
join(const CppStringT &first, const NextCppStringsT &... others) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
join(const CppStringT &s) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
join() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
ljust(const size_type width, const value_type fillch=value_type(' ')) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
lower() noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
lower(const value_type ch) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inlinestatic
lstrip(const CppStringT &removedchars) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
lstrip() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
MyBaseClass typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
operator()(Slice< IntT > slice) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
operator()(const long long start, const long long stop, const long long step=1) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
operator*(std::int64_t count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
operator=(const CppStringT &) noexcept=defaultpcs::CppStringT< CharT, TraitsT, AllocatorT >
operator=(CppStringT &&) noexcept=defaultpcs::CppStringT< CharT, TraitsT, AllocatorT >
partition(const CppStringT &sep) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
pointer typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
reference typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
removeprefix(const CppStringT &prefix) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
removesuffix(const CppStringT &suffix) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
replace(const CppStringT &old, const CppStringT &new_, size_type count=-1) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
reverse_iterator typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
rfind(const CppStringT &sub, const size_type start, const size_type end) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rfind(const CppStringT &sub, const size_type start) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rfind(const CppStringT &sub) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rfind_n(const CppStringT &sub, const size_type start, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rfind_n(const CppStringT &sub, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rindex(const CppStringT &sub, const size_type start, const size_type end) constpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rindex(const CppStringT &sub, const size_type start) constpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rindex(const CppStringT &sub) constpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rindex_n(const CppStringT &sub, const size_type start, const size_type count) constpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rindex_n(const CppStringT &sub, const size_type count) constpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rjust(const size_type width, const value_type fillch=value_type(' ')) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rpartition(const CppStringT &sep) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rsplit() noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rsplit(const CppStringT &sep) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rsplit(const size_type maxsplit) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rsplit(const CppStringT &sep, const size_type maxsplit) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rstrip(const CppStringT &removedchars) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
rstrip() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
size_type typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
split() noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
split(const CppStringT &sep) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
split(const size_type maxsplit) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
split(const CppStringT &sep, const size_type maxsplit) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
splitlines(const bool keep_end=false) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
startswith(const CppStringT &prefix, const size_type start, const size_type end) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
startswith(const CppStringT &prefix, const size_type start) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
startswith(const CppStringT &prefix) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
startswith(const std::initializer_list< CppStringT > &prefixes, const size_type start, const size_type end) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
startswith_n(const CppStringT &prefix, const size_type start, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
startswith_n(const CppStringT &prefix, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
startswith_n(const std::initializer_list< CppStringT > &prefix, const size_type start, const size_type count) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
strip(const CppStringT &removedchars) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
strip() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
substr(const size_type start, const size_type count=-1) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
swapcase() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
title() const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
traits_type typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
translate(TransTable &table) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
upper() noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
upper(const value_type ch) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inlinestatic
value_type typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >
zfill(const size_type width) const noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >inline
~CppStringT() noexcept=default (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >)pcs::CppStringT< CharT, TraitsT, AllocatorT >inline
+
+
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t.html b/cpp-strings/html/classpcs_1_1_cpp_string_t.html new file mode 100644 index 0000000..b8ec5fe --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t.html @@ -0,0 +1,3645 @@ + + + + + + + +cpp-strings: pcs::CppStringT< CharT, TraitsT, AllocatorT > Class Template Reference + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT > Class Template Reference
+
+
+ +

This is the templated base class for all CppString classes. + More...

+ +

#include <cppstrings.h>

+
+Inheritance diagram for pcs::CppStringT< CharT, TraitsT, AllocatorT >:
+
+
+ +
+ + + + + +

+Classes

class  NotFoundException
class  TransTable
 The internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate. More...
+ + + + + + + + + + + + + + + +

+Public Types

+using allocator_type = MyBaseClass::allocator_type
+using const_iterator = MyBaseClass::const_iterator
+using const_pointer = MyBaseClass::const_pointer
+using const_reference = MyBaseClass::const_reference
+using const_reverse_iterator = MyBaseClass::const_reverse_iterator
+using difference_type = MyBaseClass::difference_type
+using iterator = MyBaseClass::iterator
+using MyBaseClass = std::basic_string<CharT, TraitsT, AllocatorT>
+using pointer = MyBaseClass::pointer
+using reference = MyBaseClass::reference
+using reverse_iterator = MyBaseClass::reverse_iterator
+using size_type = MyBaseClass::size_type
+using traits_type = MyBaseClass::traits_type
+using value_type = MyBaseClass::value_type
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

CppStringT capitalize () noexcept
 Returns a copy of the string with its first character capitalized and the rest lowercased.
CppStringT center (const size_type width, const value_type fillch=value_type(' ')) const noexcept
 Returns a copy of the string centered in a string of length width.
constexpr bool contains (const CppStringT &substr) const noexcept
 Returns true if this string contains the passed string, or false otherwise.
constexpr bool contains_n (const CppStringT &sub, const size_type start, const size_type count=-1) const noexcept
 Returns true if the passed string is found within the slice str[start:start+count-1], or false otherwise.
constexpr size_type count (const CppStringT &sub, const size_type start=0, const size_type end=-1) const noexcept
 Returns the number of non-overlapping occurrences of substring sub in the range [start, end].
constexpr size_type count_n (const CppStringT &sub, const size_type length) const noexcept
 Returns the number of non-overlapping occurrences of substring sub in the range [0, length-1].
constexpr size_type count_n (const CppStringT &sub, const size_type start, const size_type length) const noexcept
 Returns the number of non-overlapping occurrences of substring sub in the range [start, start+length-1].
CppStringT (const CharT *s)
CppStringT (const CharT *s, size_type count)
CppStringT (const CharT ch)
CppStringT (const CppStringT &other)
CppStringT (const CppStringT &other, const AllocatorT &alloc)
CppStringT (const CppStringT &other, size_type pos)
CppStringT (const CppStringT &other, size_type pos, size_type count) noexcept
CppStringT (const MyBaseClass &other)
CppStringT (const MyBaseClass &other, const AllocatorT &alloc)
CppStringT (CppStringT &&other) noexcept
CppStringT (CppStringT &&other, const AllocatorT &alloc) noexcept
+template<class InputIt>
 CppStringT (InputIt first, InputIt last)
CppStringT (MyBaseClass &&other)
CppStringT (MyBaseClass &&other, const AllocatorT &alloc)
CppStringT (MyBaseClass::size_type count, CharT ch)
CppStringT (std::initializer_list< CharT > ilist)
+template<class StringViewLike>
 CppStringT (StringViewLike &svl)
+template<class StringViewLike>
 CppStringT (StringViewLike &svl, size_type pos, size_type n)
const bool endswith (const CppStringT &suffix) const noexcept
 Returns true if the string ends with the specified suffix, otherwise returns false. Test runs on the whole string.
const bool endswith (const CppStringT &suffix, const size_type end) const noexcept
 Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start of string and stops at end position.
const bool endswith (const CppStringT &suffix, const size_type start, const size_type end) const noexcept
 Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops at end position.
const bool endswith (const std::initializer_list< CppStringT > &suffixes, const size_type start, const size_type end) const noexcept
 Returns true if the string ends with any of the specified suffixes, otherwise returns false. Test begins at start position and stops at end position.
const bool endswith_n (const CppStringT &suffix, const size_type count) const noexcept
 Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions.
const bool endswith_n (const CppStringT &suffix, const size_type start, const size_type count) const noexcept
 Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions.
const bool endswith_n (const std::initializer_list< CppStringT > &suffixes, const size_type start, const size_type count) const noexcept
 Returns true if the string ends with any of the specified suffixes, otherwise returns false. Test begins at start position and stops after count positions.
CppStringT expand_tabs (const size_type tabsize=8) const noexcept
 Returns a copy of the string where all tab characters are replaced by one or more spaces, depending on the current column and the given tab size.
constexpr size_type find (const CppStringT &sub, const size_type start=0, const size_type end=-1) const noexcept
 Returns the lowest index in the string where substring sub is found within the slice str[start:end], or -1 (i.e. 'npos') if sub is not found.
constexpr size_type find_n (const CppStringT &sub, const size_type count) const noexcept
 Returns the lowest index in the string where substring sub is found within the slice str[0:count-1], or -1 (i.e. 'npos') if sub is not found.
constexpr size_type find_n (const CppStringT &sub, const size_type start, const size_type count) const noexcept
 Returns the lowest index in the string where substring sub is found within the slice str[start:start+count-1], or -1 (i.e. 'npos') if sub is not found.
template<class... ArgsT>
CppStringTformat (const std::basic_format_string< char, std::type_identity_t< ArgsT >... > frmt, ArgsT &&... args)
template<typename T, class... ArgsT>
CppStringTformat (const std::basic_format_string< T, std::type_identity_t< ArgsT >... > frmt, ArgsT &&... args)
 Formats this string according to c++20 std::format() specification. Returns this string.
template<class... ArgsT>
CppStringTformat (const std::basic_format_string< wchar_t, std::type_identity_t< ArgsT >... > frmt, ArgsT &&... args)
constexpr size_type index (const CppStringT &sub, const size_type start=0, const size_type end=-1) const
 Like find(const CppStringT&), but raises NotFoundException when the substring sub is not found.
constexpr size_type index_n (const CppStringT &sub, const size_type count) const
 Like find_n(sub, count), but raises NotFoundException when the substring is not found.
constexpr size_type index_n (const CppStringT &sub, const size_type start, const size_type count) const
 Like find_n(sub, start, count), but raises NotFoundException when the substring is not found.
const bool is_words_sep () const noexcept
 Returns true if there are only whitespace and punctuation characters in the string and there is at least one character, or false otherwise.
const bool isalnum () const noexcept
 Returns true if all characters in the string are alphanumeric and there is at least one character, or false otherwise.
const bool isalpha () const noexcept
 Returns true if all characters in the string are alphabetic and there is at least one character, or false otherwise.
const bool isascii () const noexcept
 Returns true if the string is empty or all characters in the string are ASCII, or false otherwise.
const bool isdecimal () const noexcept
 Returns true if all characters in the string are decimal characters and there is at least one character, or false otherwise.
const bool isdigit () const noexcept
 Returns true if all characters in the string are digits and there is at least one character, or false otherwise.
const bool isidentifier () const noexcept
 Returns true if the string is not empty and is a valid identifier according to the language definition, or false otherwise.
const bool islower () const noexcept
 Returns true if all cased characters in the string are lowercase and there is at least one cased character, or false otherwise.
const bool isnumeric () const noexcept
 Returns true if all characters in the string are numeric characters, and there is at least one character, or false otherwise.
const bool isprintable () const noexcept
 Returns true if all characters in the string are printable or if the string is empty, or false otherwise.
const bool ispunctuation () const noexcept
 Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set.
const bool isspace () const noexcept
 Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise.
const bool istitle () const noexcept
 Returns true if the string is a titlecased string and there is at least one character, or false otherwise.
const bool isupper () const noexcept
 Returns true if all cased characters in the string are uppercase and there is at least one cased character, or false otherwise.
const CppStringT join () const noexcept
 Empty parameters list signature. Returns a copy of current string.
template<class... NextCppStringsT>
+requires (sizeof...(others) > 0)
CppStringT join (const CppStringT &first, const NextCppStringsT &... others) const noexcept
 Returns a string which is the concatenation of the strings in the parameters list.
CppStringT join (const CppStringT &s) const noexcept
 Single parameter signature. Returns a copy of this parameter.
template<const std::size_t N>
CppStringT join (const std::array< CppStringT, N > &strs) const noexcept
 Returns a string which is the concatenation of the strings in the array parameter.
CppStringT join (const std::vector< CppStringT > &strs) const noexcept
 Returns a string which is the concatenation of the strings in the vector parameter.
CppStringT ljust (const size_type width, const value_type fillch=value_type(' ')) const noexcept
 Returns the string left justified in a string of length width.
CppStringTlower () noexcept
 In-place replaces all characters of the string with their lowercase conversion. Returns a reference to string.
CppStringT lstrip () const noexcept
 Returns a copy of the string with leading whitespaces removed.
CppStringT lstrip (const CppStringT &removedchars) const noexcept
 Returns a copy of the string with leading characters removed.
CppStringT operator() (const long long start, const long long stop, const long long step=1) const noexcept
 Generates a new string according to the specified slicing values.
template<typename IntT>
+requires std::is_signed_v<IntT>
CppStringT operator() (Slice< IntT > slice) const noexcept
 Generates a new string according to the specified slice.
CppStringT operator* (std::int64_t count) const noexcept
 Generates a new string with count times the content of this string.
CppStringToperator= (const CppStringT &) noexcept=default
 Default copy assignment.
CppStringToperator= (CppStringT &&) noexcept=default
 Default move assignment.
std::vector< CppStringTpartition (const CppStringT &sep) const noexcept
 Splits the string at the first occurrence of sep, and returns a 3-items vector containing the part before the separator, the separator itself, and the part after the separator.
CppStringT removeprefix (const CppStringT &prefix) const noexcept
 If the string starts with the prefix string, returns a new string with the prefix removed. Otherwise, returns a copy of the original string.
CppStringT removesuffix (const CppStringT &suffix) const noexcept
 If the string ends with the suffix string, returns a new string with the suffix removed. Otherwise, returns a copy of the original string.
CppStringT replace (const CppStringT &old, const CppStringT &new_, size_type count=-1) const noexcept
 Returns a copy of the string with first count occurrences of substring 'old' replaced by 'new_'.
constexpr size_type rfind (const CppStringT &sub) const noexcept
 Returns the highest index in the string where C-substring sub is found in the whole string, or -1 (i.e. 'npos') if sub is not found.
constexpr size_type rfind (const CppStringT &sub, const size_type start) const noexcept
 Returns the highest index in the string where substring sub is found starting at start position in string, or -1 (i.e. 'npos') if sub is not found.
constexpr size_type rfind (const CppStringT &sub, const size_type start, const size_type end) const noexcept
 Returns the highest index in the string where substring sub is found within the slice str[start:end], or -1 (i.e. 'npos') if sub is not found.
constexpr size_type rfind_n (const CppStringT &sub, const size_type count) const noexcept
 Returns the highest index in the string where substring sub is found within the slice str[0:count-1], or -1 (i.e. 'npos') if sub is not found.
constexpr size_type rfind_n (const CppStringT &sub, const size_type start, const size_type count) const noexcept
 Returns the highest index in the string where substring sub is found within the slice str[start:start+count-1], or -1 (i.e. 'npos') if sub is not found.
constexpr size_type rindex (const CppStringT &sub) const
 Like rfind(sub), but raises NotFoundException when the substring is not found.
constexpr size_type rindex (const CppStringT &sub, const size_type start) const
 Like rfind(sub, start), but raises NotFoundException when the substring is not found.
constexpr size_type rindex (const CppStringT &sub, const size_type start, const size_type end) const
 Like rfind(sub, start, end), but raises NotFoundException when the substring is not found.
constexpr size_type rindex_n (const CppStringT &sub, const size_type count) const
 Like rfind_n(sub, count), but raises NotFoundException when the substring is not found.
constexpr size_type rindex_n (const CppStringT &sub, const size_type start, const size_type count) const
 Like rfind_n(sub, start, count), but raises NotFoundException when the substring is not found.
CppStringT rjust (const size_type width, const value_type fillch=value_type(' ')) const noexcept
 Returns the string right justified in a string of length width.
std::vector< CppStringTrpartition (const CppStringT &sep) const noexcept
 Splits the string at the last occurrence of sep, and returns a 3-items vector containing the part before the separator, the separator itself, and the part after the separator.
std::vector< CppStringTrsplit () noexcept
 Returns a vector of the words in the whole string, as seperated with whitespace strings.
std::vector< CppStringTrsplit (const CppStringT &sep) noexcept
 Returns a vector of the words in the whole string, using sep as the delimiter string.
std::vector< CppStringTrsplit (const CppStringT &sep, const size_type maxsplit) noexcept
 Returns a vector of the words in the string, using sep as the delimiter string. At most maxsplit splits are done, the rightmost ones.
std::vector< CppStringTrsplit (const size_type maxsplit) noexcept
 Returns a vector of the words in the string, as seperated with whitespace strings. At most maxsplit splits are done, the rightmost ones.
CppStringT rstrip () const noexcept
 Returns a copy of the string with trailing whitespaces removed.
CppStringT rstrip (const CppStringT &removedchars) const noexcept
 Returns a copy of the string with trailing characters removed.
std::vector< CppStringTsplit () noexcept
 Returns a vector of the words in the whole string, as seperated with whitespace strings.
std::vector< CppStringTsplit (const CppStringT &sep) noexcept
 Returns a vector of the words in the whole string, using sep as the delimiter string.
std::vector< CppStringTsplit (const CppStringT &sep, const size_type maxsplit) noexcept
 Returns a vector of the words in the string, using sep as the delimiter string. At most maxsplit splits are done, the leftmost ones.
std::vector< CppStringTsplit (const size_type maxsplit) noexcept
 Returns a vector of the words in the string, as seperated with whitespace strings. At most maxsplit splits are done, the leftmost ones.
std::vector< CppStringTsplitlines (const bool keep_end=false) const noexcept
 Return a list of the lines in the string, breaking at line boundaries.
const bool startswith (const CppStringT &prefix) const noexcept
 Returns true if the string starts with the specified prefix, otherwise returns false. Test runs on the whole string.
const bool startswith (const CppStringT &prefix, const size_type start) const noexcept
 Returns true if the string starts with the specified prefix, otherwise returns false. Test begins at start position and stops at end of string.
const bool startswith (const CppStringT &prefix, const size_type start, const size_type end) const noexcept
 Returns true if the string starts with the specified prefix, otherwise returns false. Test begins at start position and stops at end position.
const bool startswith (const std::initializer_list< CppStringT > &prefixes, const size_type start, const size_type end) const noexcept
 Returns true if the string starts with any of the specified prefixes, otherwise returns false. Test begins at start position and stops at end of string.
const bool startswith_n (const CppStringT &prefix, const size_type count) const noexcept
 Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions.
const bool startswith_n (const CppStringT &prefix, const size_type start, const size_type count) const noexcept
 Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions.
const bool startswith_n (const std::initializer_list< CppStringT > &prefix, const size_type start, const size_type count) const noexcept
 Returns true if the string starts with any of the specified suffixes, otherwise returns false. Test begins at start position and stops after count positions.
CppStringT strip () const noexcept
 Returns a copy of the string with the leading and trailing whitespaces removed.
CppStringT strip (const CppStringT &removedchars) const noexcept
 Returns a copy of the string with the leading and trailing characters removed.
CppStringT substr (const size_type start, const size_type count=-1) const noexcept
 Returns a copy of the string, starting at index start and ending after count characters.
CppStringT swapcase () const noexcept
 Returns a copy of the string with uppercase characters converted to lowercase and vice versa.
CppStringT title () const noexcept
 Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase.
CppStringT translate (TransTable &table) noexcept
 Returns a copy of the string in which each character has been mapped through the given translation table.
CppStringTupper () noexcept
 In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string.
CppStringT zfill (const size_type width) const noexcept
 Returns a copy of the string left filled with ASCII '0' digits to make a string of length width.
+ + + + + +

+Static Public Member Functions

static const value_type lower (const value_type ch) noexcept
 Returns lowercase conversion of the character.
static const value_type upper (const value_type ch) noexcept
 Returns uppercase conversion of the character.
+

Detailed Description

+
template<class CharT, class TraitsT, class AllocatorT>
+class pcs::CppStringT< CharT, TraitsT, AllocatorT >

This is the templated base class for all CppString classes.

+

Users should instantiate any specialization of this base class rather than this base class itself:

+

Member Function Documentation

+ +

◆ capitalize()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::capitalize ()
+
+inlinenoexcept
+
+ +

Returns a copy of the string with its first character capitalized and the rest lowercased.

+ +
+
+ +

◆ center()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::center (const size_type width,
const value_type fillch = value_type(' ') ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string centered in a string of length width.

+

Padding is done using the specified fillchar (default is an ASCII space). A copy of the original string is returned if width is less than or equal to the length of the string. The original string remains unchanged.

+ +
+
+ +

◆ contains()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::contains (const CppStringT< CharT, TraitsT, AllocatorT > & substr) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns true if this string contains the passed string, or false otherwise.

+

This is a c++ implementation of Python keyword 'in' applied to strings.

+ +

Referenced by pcs::CppStringT< char >::contains_n().

+ +
+
+ +

◆ contains_n()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::contains_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start,
const size_type count = -1 ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns true if the passed string is found within the slice str[start:start+count-1], or false otherwise.

+

This is a c++ implementation of Python keyword 'in' applied to Python sliced strings.

+ +
+
+ +

◆ count()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::count (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start = 0,
const size_type end = -1 ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the number of non-overlapping occurrences of substring sub in the range [start, end].

+ +

Referenced by pcs::CppStringT< char >::count_n(), and pcs::CppStringT< char >::count_n().

+ +
+
+ +

◆ count_n() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::count_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type length ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the number of non-overlapping occurrences of substring sub in the range [0, length-1].

+ +
+
+ +

◆ count_n() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::count_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start,
const size_type length ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the number of non-overlapping occurrences of substring sub in the range [start, start+length-1].

+ +
+
+ +

◆ endswith() [1/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::endswith (const CppStringT< CharT, TraitsT, AllocatorT > & suffix) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string ends with the specified suffix, otherwise returns false. Test runs on the whole string.

+ +
+
+ +

◆ endswith() [2/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::endswith (const CppStringT< CharT, TraitsT, AllocatorT > & suffix,
const size_type end ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start of string and stops at end position.

+ +
+
+ +

◆ endswith() [3/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::endswith (const CppStringT< CharT, TraitsT, AllocatorT > & suffix,
const size_type start,
const size_type end ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops at end position.

+ +

Referenced by pcs::CppStringT< char >::endswith_n(), pcs::CppStringT< char >::endswith_n(), pcs::CppStringT< char >::endswith_n(), and pcs::CppStringT< char >::removesuffix().

+ +
+
+ +

◆ endswith() [4/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::endswith (const std::initializer_list< CppStringT< CharT, TraitsT, AllocatorT > > & suffixes,
const size_type start,
const size_type end ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string ends with any of the specified suffixes, otherwise returns false. Test begins at start position and stops at end position.

+ +
+
+ +

◆ endswith_n() [1/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::endswith_n (const CppStringT< CharT, TraitsT, AllocatorT > & suffix,
const size_type count ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions.

+ +
+
+ +

◆ endswith_n() [2/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::endswith_n (const CppStringT< CharT, TraitsT, AllocatorT > & suffix,
const size_type start,
const size_type count ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions.

+ +
+
+ +

◆ endswith_n() [3/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::endswith_n (const std::initializer_list< CppStringT< CharT, TraitsT, AllocatorT > > & suffixes,
const size_type start,
const size_type count ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string ends with any of the specified suffixes, otherwise returns false. Test begins at start position and stops after count positions.

+ +
+
+ +

◆ expand_tabs()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::expand_tabs (const size_type tabsize = 8) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string where all tab characters are replaced by one or more spaces, depending on the current column and the given tab size.

+ +
+
+ +

◆ find()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::find (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start = 0,
const size_type end = -1 ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the lowest index in the string where substring sub is found within the slice str[start:end], or -1 (i.e. 'npos') if sub is not found.

+

Note: this method should be used only if you need to know the position of sub. To check if sub is a substring or not, use the method contains().

+

CAUTION: empty substrings are considered to be in the string if start and end positions are both less than the string size and if start <= end.

+
See also
find_n(), rfind() and rfind_n().
+
+index(), index_n(), rindex() and rindex_n().
+ +

Referenced by pcs::CppStringT< char >::count(), pcs::CppStringT< char >::index(), pcs::CppStringT< char >::partition(), pcs::CppStringT< char >::replace(), and pcs::CppStringT< char >::split().

+ +
+
+ +

◆ find_n() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::find_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type count ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the lowest index in the string where substring sub is found within the slice str[0:count-1], or -1 (i.e. 'npos') if sub is not found.

+

Note: this method should be used only if you need to know the position of sub. To check if sub is a substring or not, use the method contains_n().

+

CAUTION: empty substrings are considered to be in the string if start and end positions are both less than the string size and if start <= end. The returned position is 0.

+
See also
find(), rfind() and rfind_n().
+
+index(), index_n(), rindex() and rindex_n().
+ +
+
+ +

◆ find_n() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::find_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start,
const size_type count ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the lowest index in the string where substring sub is found within the slice str[start:start+count-1], or -1 (i.e. 'npos') if sub is not found.

+

Note: this method should be used only if you need to know the position of sub. To check if sub is a substring or not, use the method contains_n().

+

CAUTION: empty substrings are considered to be in the string if start and end positions are both less than the string size and if start <= end. The returned position is 0.

+
See also
find(), rfind() and rfind_n().
+
+index(), index_n(), rindex() and rindex_n().
+ +

Referenced by pcs::CppStringT< char >::find(), and pcs::CppStringT< char >::find_n().

+ +
+
+ +

◆ format() [1/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+
+template<class... ArgsT>
+ + + + + +
+ + + + + + + + + + + +
CppStringT & pcs::CppStringT< CharT, TraitsT, AllocatorT >::format (const std::basic_format_string< char, std::type_identity_t< ArgsT >... > frmt,
ArgsT &&... args )
+
+inline
+
+
Parameters
+ + +
frmtspecialzation for char's
+
+
+ +
+
+ +

◆ format() [2/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+
+template<typename T, class... ArgsT>
+ + + + + +
+ + + + + + + + + + + +
CppStringT & pcs::CppStringT< CharT, TraitsT, AllocatorT >::format (const std::basic_format_string< T, std::type_identity_t< ArgsT >... > frmt,
ArgsT &&... args )
+
+inline
+
+ +

Formats this string according to c++20 std::format() specification. Returns this string.

+ +
+
+ +

◆ format() [3/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+
+template<class... ArgsT>
+ + + + + +
+ + + + + + + + + + + +
CppStringT & pcs::CppStringT< CharT, TraitsT, AllocatorT >::format (const std::basic_format_string< wchar_t, std::type_identity_t< ArgsT >... > frmt,
ArgsT &&... args )
+
+inline
+
+
Parameters
+ + +
frmtspecialzation for wchar_t's
+
+
+ +
+
+ +

◆ index()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::index (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start = 0,
const size_type end = -1 ) const
+
+inlinenodiscardconstexpr
+
+ +

Like find(const CppStringT&), but raises NotFoundException when the substring sub is not found.

+
See also
index_n(), rindex() and rindex_n().
+
+find(), find_n(), rfind() and rfind_n().
+ +

Referenced by pcs::CppStringT< char >::index_n(), and pcs::CppStringT< char >::index_n().

+ +
+
+ +

◆ index_n() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::index_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type count ) const
+
+inlinenodiscardconstexpr
+
+ +

Like find_n(sub, count), but raises NotFoundException when the substring is not found.

+
See also
index_n(), rindex() and rindex_n().
+
+find(), find_n(), rfind() and rfind_n().
+ +
+
+ +

◆ index_n() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::index_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start,
const size_type count ) const
+
+inlinenodiscardconstexpr
+
+ +

Like find_n(sub, start, count), but raises NotFoundException when the substring is not found.

+
See also
index_n(), rindex() and rindex_n().
+
+find(), find_n(), rfind() and rfind_n().
+ +
+
+ +

◆ is_words_sep()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::is_words_sep () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if there are only whitespace and punctuation characters in the string and there is at least one character, or false otherwise.

+ +
+
+ +

◆ isalnum()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isalnum () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if all characters in the string are alphanumeric and there is at least one character, or false otherwise.

+ +
+
+ +

◆ isalpha()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isalpha () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if all characters in the string are alphabetic and there is at least one character, or false otherwise.

+ +
+
+ +

◆ isascii()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isascii () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string is empty or all characters in the string are ASCII, or false otherwise.

+ +
+
+ +

◆ isdecimal()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isdecimal () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if all characters in the string are decimal characters and there is at least one character, or false otherwise.

+

Decimal characters are those that can be used to form numbers in base 10, e.g. U+0660, ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in the Unicode General Category “Nd”.

+ +

Referenced by pcs::CppStringT< char >::isdigit(), and pcs::CppStringT< char >::isnumeric().

+ +
+
+ +

◆ isdigit()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isdigit () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if all characters in the string are digits and there is at least one character, or false otherwise.

+

Digits include decimal characters and digits that need special handling, such as the compatibility superscript digits. This covers digits which cannot be used to form numbers in base 10, like the Kharosthi numbers. Formally, a digit is a character that has the property value Numeric_Type=Digit or Numeric_Type =Decimal.

+

CAUTION: current implementation of library cpp-strings does not implement above algorithm. It just returns the same result as 'isdecimal()' which is NOT what Python str library does.

+ +
+
+ +

◆ isidentifier()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isidentifier () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string is not empty and is a valid identifier according to the language definition, or false otherwise.

+

CAUTION: the current implementation of this method does not deal with the proper c++ defintiion of identifiers (see https://en.cppreference.com/w/cpp/language/identifiers and https://www.unicode.org/reports/tr31/#Table_Lexical_Classes_for_Identifiers).

+

While the specification of identifiers in c++ is this one:

+

identifier ::= XID_Start XID_Continue* XID_Start ::= ID_Start XID_Continue* ID_Start ::= <characters derived from the Unicode General_Category of uppercase letters, lowercase letters, titlecase letters, modifier letters, other letters, letter numbers, plus Other_ID_Start, minus Pattern_Syntax and Pattern_White_Space code points> XID_Continue ::= <characters derived from ID_Continue as per Unicode specs Section 5.1, NFKC Modifications (https://www.unicode.org/reports/tr31/#NFKC_Modifications)> ID_Continue ::= ID_Start | <characters having the Unicode General_Category of nonspacing marks, spacing combining marks, decimal number, connector punctuation, plus Other_ID_Continue, minus Pattern_Syntax and Pattern_White_Space code points>

+

the currently implemented rule is this simpler one:

+

identifier ::= ID_Start id_continue* id_continue ::= ID_Start | <decimal number>

+ +
+
+ +

◆ islower()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::islower () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if all cased characters in the string are lowercase and there is at least one cased character, or false otherwise.

+ +
+
+ +

◆ isnumeric()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isnumeric () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if all characters in the string are numeric characters, and there is at least one character, or false otherwise.

+

CAUTION: current implementation just returns isdecimal() result, while the description of isnumeric() should be this one: Numeric characters include digit characters, and all characters that have the Unicode numeric value property. Formally, numeric characters are those with the property value Numeric_Type=Digit, Numeric_Type=Decimal or Numeric_Type=Numeric.

+ +
+
+ +

◆ isprintable()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isprintable () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if all characters in the string are printable or if the string is empty, or false otherwise.

+

Nonprintable characters are those characters defined in the Unicode character database as "Other" or "Separator", excepting the ASCII space (0x20) which is considered printable.

+ +
+
+ +

◆ ispunctuation()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::ispunctuation () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set.

+ +
+
+ +

◆ isspace()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isspace () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise.

+ +
+
+ +

◆ istitle()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::istitle () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string is a titlecased string and there is at least one character, or false otherwise.

+

For instance uppercase characters may only follow uncased characters and lowercase characters only cased ones.

+

CAUTION: current implementation only tests for uppercase characters following whitespaces and lowercase characters anywhere else.

+ +
+
+ +

◆ isupper()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::isupper () const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if all cased characters in the string are uppercase and there is at least one cased character, or false otherwise.

+ +
+
+ +

◆ join() [1/5]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::join () const
+
+inlinenodiscardnoexcept
+
+ +

Empty parameters list signature. Returns a copy of current string.

+ +

Referenced by pcs::CppStringT< char >::join().

+ +
+
+ +

◆ join() [2/5]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+
+template<class... NextCppStringsT>
+requires (sizeof...(others) > 0)
+ + + + + +
+ + + + + + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::join (const CppStringT< CharT, TraitsT, AllocatorT > & first,
const NextCppStringsT &... others ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a string which is the concatenation of the strings in the parameters list.

+

The separator between elements is the string to which this method is applied.

+ +
+
+ +

◆ join() [3/5]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::join (const CppStringT< CharT, TraitsT, AllocatorT > & s) const
+
+inlinenodiscardnoexcept
+
+ +

Single parameter signature. Returns a copy of this parameter.

+ +
+
+ +

◆ join() [4/5]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+
+template<const std::size_t N>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::join (const std::array< CppStringT< CharT, TraitsT, AllocatorT >, N > & strs) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a string which is the concatenation of the strings in the array parameter.

+

The separator between elements is the string to which this method is applied.

+ +

Referenced by pcs::CppStringT< char >::title().

+ +
+
+ +

◆ join() [5/5]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::join (const std::vector< CppStringT< CharT, TraitsT, AllocatorT > > & strs) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a string which is the concatenation of the strings in the vector parameter.

+

The separator between elements is the string to which this method is applied.

+ +
+
+ +

◆ ljust()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::ljust (const size_type width,
const value_type fillch = value_type(' ') ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns the string left justified in a string of length width.

+

Padding is done using the specified fillchar (default is an ASCII space). The original string is returned if width is less than or equal to len(s).

+ +

Referenced by pcs::CppStringT< char >::zfill().

+ +
+
+ +

◆ lower() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT & pcs::CppStringT< CharT, TraitsT, AllocatorT >::lower ()
+
+inlinenoexcept
+
+ +

In-place replaces all characters of the string with their lowercase conversion. Returns a reference to string.

+

Notice: uses the currently set std::locale, which is the "C" one by default or any other one as previously set by the user.

+ +

Referenced by pcs::CppStringT< char >::capitalize(), and pcs::CppStringT< char >::lower().

+ +
+
+ +

◆ lower() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const value_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::lower (const value_type ch)
+
+inlinestaticnodiscardnoexcept
+
+ +

Returns lowercase conversion of the character.

+

Notice: uses the currently set std::locale, which is the "C" one by default or any other one as previously set by the user.

+ +
+
+ +

◆ lstrip() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::lstrip () const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string with leading whitespaces removed.

+ +
+
+ +

◆ lstrip() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::lstrip (const CppStringT< CharT, TraitsT, AllocatorT > & removedchars) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string with leading characters removed.

+

The passed string specifies the set of characters to be removed. The chars argument is not a prefix; rather, all combinations of its values are stripped. To remove a prefix, rather call method 'removeprefix()'.

+ +

Referenced by pcs::CppStringT< char >::strip(), and pcs::CppStringT< char >::strip().

+ +
+
+ +

◆ operator()() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::operator() (const long long start,
const long long stop,
const long long step = 1 ) const
+
+inlinenodiscardnoexcept
+
+ +

Generates a new string according to the specified slicing values.

+ +
+
+ +

◆ operator()() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+
+template<typename IntT>
+requires std::is_signed_v<IntT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::operator() (Slice< IntT > slice) const
+
+inlinenodiscardnoexcept
+
+ +

Generates a new string according to the specified slice.

+

A slice is a range specified as [start, stop, step]. It may also be specified as [start, stop] in which case step = 1, or as [stop] in wich case start = 0 and step = 1. Values may be negative: negative step means reverse running and negative start or stop is relative to the end of the string. Notice: the stop value specifies an out of bounds index.

See also
class Slice and all its inheriting classes.
+ +
+
+ +

◆ operator*()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::operator* (std::int64_t count) const
+
+inlinenodiscardnoexcept
+
+ +

Generates a new string with count times the content of this string.

+ +
+
+ +

◆ operator=() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT & pcs::CppStringT< CharT, TraitsT, AllocatorT >::operator= (const CppStringT< CharT, TraitsT, AllocatorT > & )
+
+defaultnoexcept
+
+ +

Default copy assignment.

+ +
+
+ +

◆ operator=() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT & pcs::CppStringT< CharT, TraitsT, AllocatorT >::operator= (CppStringT< CharT, TraitsT, AllocatorT > && )
+
+defaultnoexcept
+
+ +

Default move assignment.

+ +
+
+ +

◆ partition()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::partition (const CppStringT< CharT, TraitsT, AllocatorT > & sep) const
+
+inlinenodiscardnoexcept
+
+ +

Splits the string at the first occurrence of sep, and returns a 3-items vector containing the part before the separator, the separator itself, and the part after the separator.

+

If the separator is not found, returns a 3-items vector containing the string itself, followed by two empty strings.

+ +
+
+ +

◆ removeprefix()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::removeprefix (const CppStringT< CharT, TraitsT, AllocatorT > & prefix) const
+
+inlinenodiscardnoexcept
+
+ +

If the string starts with the prefix string, returns a new string with the prefix removed. Otherwise, returns a copy of the original string.

+ +
+
+ +

◆ removesuffix()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::removesuffix (const CppStringT< CharT, TraitsT, AllocatorT > & suffix) const
+
+inlinenodiscardnoexcept
+
+ +

If the string ends with the suffix string, returns a new string with the suffix removed. Otherwise, returns a copy of the original string.

+ +
+
+ +

◆ replace()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::replace (const CppStringT< CharT, TraitsT, AllocatorT > & old,
const CppStringT< CharT, TraitsT, AllocatorT > & new_,
size_type count = -1 ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string with first count occurrences of substring 'old' replaced by 'new_'.

+ +
+
+ +

◆ rfind() [1/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rfind (const CppStringT< CharT, TraitsT, AllocatorT > & sub) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the highest index in the string where C-substring sub is found in the whole string, or -1 (i.e. 'npos') if sub is not found.

+

Note that this is an offset from the start of the string, not the end.

+

Note: this method should be used only if you need to know the position of sub. To check if sub is a substring or not, use the method contains().

+

CAUTION: empty substrings are considered to be in the string if start and end positions are both less than the string size and if start <= end. The returned position is the size of the string.

+
See also
find(), find_n() and rfind_n().
+
+index(), index_n(), rindex() and rindex_n().
+ +
+
+ +

◆ rfind() [2/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rfind (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the highest index in the string where substring sub is found starting at start position in string, or -1 (i.e. 'npos') if sub is not found.

+

Note that this is an offset from the start of the string, not the end.

+

Note: this method should be used only if you need to know the position of sub. To check if sub is a substring or not, use the method contains().

+

CAUTION: empty substrings are considered to be in the string if start and end positions are both less than the string size and if start <= end. The returned position is the size of the string.

+
See also
find(), find_n() and rfind_n().
+
+index(), index_n(), rindex() and rindex_n().
+ +
+
+ +

◆ rfind() [3/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rfind (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start,
const size_type end ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the highest index in the string where substring sub is found within the slice str[start:end], or -1 (i.e. 'npos') if sub is not found.

+

Note that this is an offset from the start of the string, not the end.

+

Note: this method should be used only if you need to know the position of sub. To check if sub is a substring or not, use the method contains().

+

CAUTION: empty substrings are considered to be in the string if start and end positions are both less than the string size and if start <= end. The returned position is the size of the string.

+
See also
find(), find_n() and rfind_n().
+
+index(), index_n(), rindex() and rindex_n().
+ +

Referenced by pcs::CppStringT< char >::rfind(), pcs::CppStringT< char >::rfind(), pcs::CppStringT< char >::rfind_n(), pcs::CppStringT< char >::rfind_n(), pcs::CppStringT< char >::rindex(), pcs::CppStringT< char >::rpartition(), and pcs::CppStringT< char >::rsplit().

+ +
+
+ +

◆ rfind_n() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rfind_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type count ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the highest index in the string where substring sub is found within the slice str[0:count-1], or -1 (i.e. 'npos') if sub is not found.

+

Note: this method should be used only if you need to know the position of sub. To check if sub is a substring or not, use the method contains_n().

+
See also
find(), find_n() and rfind().
+
+index(), index_n(), rindex() and rindex_n().
+ +
+
+ +

◆ rfind_n() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rfind_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start,
const size_type count ) const
+
+inlinenodiscardconstexprnoexcept
+
+ +

Returns the highest index in the string where substring sub is found within the slice str[start:start+count-1], or -1 (i.e. 'npos') if sub is not found.

+

Note: this method should be used only if you need to know the position of sub. To check if sub is a substring or not, use the method contains_n().

+
See also
find(), find_n() and rfind().
+
+index(), index_n(), rindex() and rindex_n().
+ +
+
+ +

◆ rindex() [1/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rindex (const CppStringT< CharT, TraitsT, AllocatorT > & sub) const
+
+inlinenodiscardconstexpr
+
+ +

Like rfind(sub), but raises NotFoundException when the substring is not found.

+
See also
index(), index_n() and rindex_n().
+
+find(), find_n(), rfind() and rfind_n().
+ +
+
+ +

◆ rindex() [2/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rindex (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start ) const
+
+inlinenodiscardconstexpr
+
+ +

Like rfind(sub, start), but raises NotFoundException when the substring is not found.

+
See also
index(), index_n() and rindex_n().
+
+find(), find_n(), rfind() and rfind_n().
+ +
+
+ +

◆ rindex() [3/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rindex (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start,
const size_type end ) const
+
+inlinenodiscardconstexpr
+
+ +

Like rfind(sub, start, end), but raises NotFoundException when the substring is not found.

+
See also
index(), index_n() and rindex_n().
+
+find(), find_n(), rfind() and rfind_n().
+ +

Referenced by pcs::CppStringT< char >::rindex(), pcs::CppStringT< char >::rindex(), pcs::CppStringT< char >::rindex_n(), and pcs::CppStringT< char >::rindex_n().

+ +
+
+ +

◆ rindex_n() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rindex_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type count ) const
+
+inlinenodiscardconstexpr
+
+ +

Like rfind_n(sub, count), but raises NotFoundException when the substring is not found.

+
See also
index_n(), rindex() and rindex_n().
+
+find(), find_n(), rfind() and rfind_n().
+ +
+
+ +

◆ rindex_n() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
size_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::rindex_n (const CppStringT< CharT, TraitsT, AllocatorT > & sub,
const size_type start,
const size_type count ) const
+
+inlinenodiscardconstexpr
+
+ +

Like rfind_n(sub, start, count), but raises NotFoundException when the substring is not found.

+
See also
index_n(), rindex() and rindex_n().
+
+find(), find_n(), rfind() and rfind_n().
+ +
+
+ +

◆ rjust()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::rjust (const size_type width,
const value_type fillch = value_type(' ') ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns the string right justified in a string of length width.

+

Padding is done using the specified fillchar (default is an ASCII space). The original string is returned if width is less than or equal to len(s).

+ +
+
+ +

◆ rpartition()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::rpartition (const CppStringT< CharT, TraitsT, AllocatorT > & sep) const
+
+inlinenodiscardnoexcept
+
+ +

Splits the string at the last occurrence of sep, and returns a 3-items vector containing the part before the separator, the separator itself, and the part after the separator.

+

If the separator is not found, returns a 3-items vector containing the string itself, followed by two empty strings.

+ +
+
+ +

◆ rsplit() [1/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::rsplit ()
+
+inlinenodiscardnoexcept
+
+ +

Returns a vector of the words in the whole string, as seperated with whitespace strings.

+

Notice: consecutive whitespaces are each regarded as a single separator. So, they each separate empty strings.

+ +

Referenced by pcs::CppStringT< char >::rsplit().

+ +
+
+ +

◆ rsplit() [2/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::rsplit (const CppStringT< CharT, TraitsT, AllocatorT > & sep)
+
+inlinenodiscardnoexcept
+
+ +

Returns a vector of the words in the whole string, using sep as the delimiter string.

+ +
+
+ +

◆ rsplit() [3/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::rsplit (const CppStringT< CharT, TraitsT, AllocatorT > & sep,
const size_type maxsplit )
+
+inlinenodiscardnoexcept
+
+ +

Returns a vector of the words in the string, using sep as the delimiter string. At most maxsplit splits are done, the rightmost ones.

+ +
+
+ +

◆ rsplit() [4/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::rsplit (const size_type maxsplit)
+
+inlinenodiscardnoexcept
+
+ +

Returns a vector of the words in the string, as seperated with whitespace strings. At most maxsplit splits are done, the rightmost ones.

+ +
+
+ +

◆ rstrip() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::rstrip () const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string with trailing whitespaces removed.

+ +

Referenced by pcs::CppStringT< char >::strip(), and pcs::CppStringT< char >::strip().

+ +
+
+ +

◆ rstrip() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::rstrip (const CppStringT< CharT, TraitsT, AllocatorT > & removedchars) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string with trailing characters removed.

+

The passed string specifies the set of characters to be removed. The chars argument is not a prefix; rather, all combinations of its values are stripped. To remove a suffix, rather call method 'removesuffix()'.

+ +
+
+ +

◆ split() [1/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::split ()
+
+inlinenodiscardnoexcept
+
+ +

Returns a vector of the words in the whole string, as seperated with whitespace strings.

+

Notice: consecutive whitespaces are each regarded as a single separator. So, they each separate empty strings.

+ +

Referenced by pcs::CppStringT< char >::rsplit(), pcs::CppStringT< char >::rsplit(), pcs::CppStringT< char >::split(), and pcs::CppStringT< char >::title().

+ +
+
+ +

◆ split() [2/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::split (const CppStringT< CharT, TraitsT, AllocatorT > & sep)
+
+inlinenodiscardnoexcept
+
+ +

Returns a vector of the words in the whole string, using sep as the delimiter string.

+

Notice: consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, "1,,2".split(",") returns {"1", "", "2"}). The sep argument may consist of multiple characters (for example, "1<>2<>3".split("<>") returns {"1", "2", "3"]). Splitting an empty string with a specified separator returns {""}.

+ +
+
+ +

◆ split() [3/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::split (const CppStringT< CharT, TraitsT, AllocatorT > & sep,
const size_type maxsplit )
+
+inlinenodiscardnoexcept
+
+ +

Returns a vector of the words in the string, using sep as the delimiter string. At most maxsplit splits are done, the leftmost ones.

+ +
+
+ +

◆ split() [4/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::split (const size_type maxsplit)
+
+inlinenodiscardnoexcept
+
+ +

Returns a vector of the words in the string, as seperated with whitespace strings. At most maxsplit splits are done, the leftmost ones.

+ +
+
+ +

◆ splitlines()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::vector< CppStringT > pcs::CppStringT< CharT, TraitsT, AllocatorT >::splitlines (const bool keep_end = false) const
+
+inlinenodiscardnoexcept
+
+ +

Return a list of the lines in the string, breaking at line boundaries.

+

Line breaks are not included in the resulting list unless keepends is given and true.

+

This method splits on the following line boundaries. In particular, the boundaries are a superset of universal newlines:
+ Line Feed \r Carriage Return \r
+ Carriage Return + Line Feed \v or \x0b Line Tabulation \f or \x0c Form Feed \x1c File Separator \x1d Group Separator \x1e Record Separator Next separators values, detected by Python method splitlines(), are currently NOT detected by CppStrings \x85 Next Line (C1 Control Code) \u2028 Line Separator \u2029 Paragraph Separator

+ +
+
+ +

◆ startswith() [1/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::startswith (const CppStringT< CharT, TraitsT, AllocatorT > & prefix) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string starts with the specified prefix, otherwise returns false. Test runs on the whole string.

+ +
+
+ +

◆ startswith() [2/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::startswith (const CppStringT< CharT, TraitsT, AllocatorT > & prefix,
const size_type start ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string starts with the specified prefix, otherwise returns false. Test begins at start position and stops at end of string.

+ +
+
+ +

◆ startswith() [3/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::startswith (const CppStringT< CharT, TraitsT, AllocatorT > & prefix,
const size_type start,
const size_type end ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string starts with the specified prefix, otherwise returns false. Test begins at start position and stops at end position.

+ +

Referenced by pcs::CppStringT< char >::removeprefix(), pcs::CppStringT< char >::startswith(), and pcs::CppStringT< char >::startswith_n().

+ +
+
+ +

◆ startswith() [4/4]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::startswith (const std::initializer_list< CppStringT< CharT, TraitsT, AllocatorT > > & prefixes,
const size_type start,
const size_type end ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string starts with any of the specified prefixes, otherwise returns false. Test begins at start position and stops at end of string.

+ +
+
+ +

◆ startswith_n() [1/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::startswith_n (const CppStringT< CharT, TraitsT, AllocatorT > & prefix,
const size_type count ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions.

+ +
+
+ +

◆ startswith_n() [2/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::startswith_n (const CppStringT< CharT, TraitsT, AllocatorT > & prefix,
const size_type start,
const size_type count ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions.

+ +
+
+ +

◆ startswith_n() [3/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
const bool pcs::CppStringT< CharT, TraitsT, AllocatorT >::startswith_n (const std::initializer_list< CppStringT< CharT, TraitsT, AllocatorT > > & prefix,
const size_type start,
const size_type count ) const
+
+inlinenodiscardnoexcept
+
+ +

Returns true if the string starts with any of the specified suffixes, otherwise returns false. Test begins at start position and stops after count positions.

+ +
+
+ +

◆ strip() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::strip () const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string with the leading and trailing whitespaces removed.

+ +
+
+ +

◆ strip() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::strip (const CppStringT< CharT, TraitsT, AllocatorT > & removedchars) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string with the leading and trailing characters removed.

+

The passed string specifies the set of characters to be removed. The chars argument is not a prefix; rather, all combinations of its values are stripped.

+ +
+
+ +

◆ substr()

+ + + +

◆ swapcase()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::swapcase () const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string with uppercase characters converted to lowercase and vice versa.

+

Note that it is not necessarily true that s.swapcase().swapcase() == s.

+ +
+
+ +

◆ title()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::title () const
+
+inlinenodiscardnoexcept
+
+ +

Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase.

+ +

Referenced by pcs::CppStringT< char >::istitle().

+ +
+
+ +

◆ translate()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::translate (TransTable & table)
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string in which each character has been mapped through the given translation table.

+

The table must be of type CppStringT::TransTable. When a character to be translated is not available as an entry in the tranlation table, it is set as is in the resulting string.

+ +
+
+ +

◆ upper() [1/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT & pcs::CppStringT< CharT, TraitsT, AllocatorT >::upper ()
+
+inlinenoexcept
+
+ +

In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string.

+

Notice: uses the currently set std::locale, which is the "C" one by default or any other one as previously set by the user.

+ +

Referenced by pcs::CppStringT< char >::upper().

+ +
+
+ +

◆ upper() [2/2]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
const value_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::upper (const value_type ch)
+
+inlinestaticnodiscardnoexcept
+
+ +

Returns uppercase conversion of the character.

+

Notice: uses the currently set std::locale, which is the "C" one by default or any other one as previously set by the user.

+ +
+
+ +

◆ zfill()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
CppStringT pcs::CppStringT< CharT, TraitsT, AllocatorT >::zfill (const size_type width) const
+
+inlinenodiscardnoexcept
+
+ +

Returns a copy of the string left filled with ASCII '0' digits to make a string of length width.

+

A leading sign prefix ('+'/'-') is handled by inserting the padding after the sign character rather than before. The original string is returned if width is less than or equal to len(s).

+ +
+
+
The documentation for this class was generated from the following file: +
+
+ +
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t.js b/cpp-strings/html/classpcs_1_1_cpp_string_t.js new file mode 100644 index 0000000..7ed5049 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t.js @@ -0,0 +1,99 @@ +var classpcs_1_1_cpp_string_t = +[ + [ "NotFoundException", "classpcs_1_1_cpp_string_t_1_1_not_found_exception.html", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html", "classpcs_1_1_cpp_string_t_1_1_trans_table" ], + [ "capitalize", "classpcs_1_1_cpp_string_t.html#a48a00cca031b9c29d1912508e120a5f6", null ], + [ "center", "classpcs_1_1_cpp_string_t.html#af18311d8608e71627bc85f96581e4dd3", null ], + [ "contains", "classpcs_1_1_cpp_string_t.html#a0674e29327353aabf83d0e207fed31ed", null ], + [ "contains_n", "classpcs_1_1_cpp_string_t.html#a031b05f290f589b2df52bb84252c27c7", null ], + [ "count", "classpcs_1_1_cpp_string_t.html#a7beda74b4d5092845a970d51d01fe4bf", null ], + [ "count_n", "classpcs_1_1_cpp_string_t.html#a59839e3b5a186c2554224dbf4528c1b4", null ], + [ "count_n", "classpcs_1_1_cpp_string_t.html#a76f97d56e1713182d5e85d58cd445d10", null ], + [ "endswith", "classpcs_1_1_cpp_string_t.html#a3e9da0bfa54e84420e81668f6ce7f52c", null ], + [ "endswith", "classpcs_1_1_cpp_string_t.html#a6b23210d7d5eb07c9f942d62cc76b05e", null ], + [ "endswith", "classpcs_1_1_cpp_string_t.html#a42f1e87d7f1903536ee79aa058d5c867", null ], + [ "endswith", "classpcs_1_1_cpp_string_t.html#a87b25fce2a05421efd718c599a784a09", null ], + [ "endswith_n", "classpcs_1_1_cpp_string_t.html#a619935926ef961883e9bbd92b2fc23bd", null ], + [ "endswith_n", "classpcs_1_1_cpp_string_t.html#a7eca5636b598c6fc107452ddd04a2f17", null ], + [ "endswith_n", "classpcs_1_1_cpp_string_t.html#a4fd91047ab0126c823aa391a699e03bf", null ], + [ "expand_tabs", "classpcs_1_1_cpp_string_t.html#a2cc04d5062162ff5f7b6111d6f1e78e8", null ], + [ "find", "classpcs_1_1_cpp_string_t.html#a24c4b7a0f713373cb3287d92289562ad", null ], + [ "find_n", "classpcs_1_1_cpp_string_t.html#a6b0bc87b284120d0d3bfc685984997c0", null ], + [ "find_n", "classpcs_1_1_cpp_string_t.html#ac4c9351bb52eb9a62fa7fb2e2d5f054d", null ], + [ "format", "classpcs_1_1_cpp_string_t.html#a1a89389b38fd6af3ea8db3489dd82f70", null ], + [ "format", "classpcs_1_1_cpp_string_t.html#a5caecc371bf390272283ceb7a15c6c1d", null ], + [ "format", "classpcs_1_1_cpp_string_t.html#a944e066f3a863c354a5613a6eda17374", null ], + [ "index", "classpcs_1_1_cpp_string_t.html#a277a2b8a3b93951ccb94b6bf39daa582", null ], + [ "index_n", "classpcs_1_1_cpp_string_t.html#a19a51054b824add817f30c5ff03effe7", null ], + [ "index_n", "classpcs_1_1_cpp_string_t.html#aee94d4b52483021051b168e776b18569", null ], + [ "is_words_sep", "classpcs_1_1_cpp_string_t.html#a7565e4f2958e485ee2b0815be1faa0fa", null ], + [ "isalnum", "classpcs_1_1_cpp_string_t.html#a8fdf96ffee524d5b795c4aad26ece6ae", null ], + [ "isalpha", "classpcs_1_1_cpp_string_t.html#a447b7c58b4be1cdcba3aedf189acbce7", null ], + [ "isascii", "classpcs_1_1_cpp_string_t.html#a710631f31d4c63c2117e8f4804fad3f2", null ], + [ "isdecimal", "classpcs_1_1_cpp_string_t.html#a0b9d8a55419274e7cfd9badb4df704e3", null ], + [ "isdigit", "classpcs_1_1_cpp_string_t.html#a21316d00180377a3f48910a6c4c43b9c", null ], + [ "isidentifier", "classpcs_1_1_cpp_string_t.html#a91f72d425dbb4c53a066338d30683246", null ], + [ "islower", "classpcs_1_1_cpp_string_t.html#ae4ff448bb92e6499c0a76f7d8e11126c", null ], + [ "isnumeric", "classpcs_1_1_cpp_string_t.html#a578176ed20fd8da965afbcae1d99dd59", null ], + [ "isprintable", "classpcs_1_1_cpp_string_t.html#a6257a1832da550d4be32e9f272e51265", null ], + [ "ispunctuation", "classpcs_1_1_cpp_string_t.html#a2842f3a067fdc674709bed048d64e12d", null ], + [ "isspace", "classpcs_1_1_cpp_string_t.html#a959a8f56bb536f2474ffc649a7ad3290", null ], + [ "istitle", "classpcs_1_1_cpp_string_t.html#ad72611f339c2b9027a72fa26f25748c3", null ], + [ "isupper", "classpcs_1_1_cpp_string_t.html#af2784cbe9655bb8e23fe90375d79e69c", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#aa3523b858357399995e4fb9ec796c96c", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#a545d669bb9296b5695b01ac8680bf3f4", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#a30860a043574996d85c80e49ef618594", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#ac1b427d4cc4c2aed8252b3526b63f1b1", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#a9eed3f6c5e09f98f3d5916cc5b3a4311", null ], + [ "ljust", "classpcs_1_1_cpp_string_t.html#aed96c44c384cab45342122cd7e2f02eb", null ], + [ "lower", "classpcs_1_1_cpp_string_t.html#ad5c765eaa85cb4a3e7a914d55a6a5175", null ], + [ "lstrip", "classpcs_1_1_cpp_string_t.html#ac1ad3018d38f291e6debad8d2de92be1", null ], + [ "lstrip", "classpcs_1_1_cpp_string_t.html#aee6e48d5b478d5bab239f54523d23c15", null ], + [ "operator()", "classpcs_1_1_cpp_string_t.html#a0daec57ccab4601f46e9d1c258407765", null ], + [ "operator()", "classpcs_1_1_cpp_string_t.html#a1fa8862a5f306553d6f0dae7e76fce83", null ], + [ "operator*", "classpcs_1_1_cpp_string_t.html#a0995f5b5a01af3f4a749949e23d0d780", null ], + [ "operator=", "classpcs_1_1_cpp_string_t.html#a30e26a3082ad50d01c7d0d98cb9e9c37", null ], + [ "operator=", "classpcs_1_1_cpp_string_t.html#a810a3a27ee7396f9c472648978327a76", null ], + [ "partition", "classpcs_1_1_cpp_string_t.html#ac5f88b0fc1f33cda23c30cb1f3bc560f", null ], + [ "removeprefix", "classpcs_1_1_cpp_string_t.html#a058704b7f4538ec9e1798c5348d37c7a", null ], + [ "removesuffix", "classpcs_1_1_cpp_string_t.html#ad6a8dc124ab8b7cab1cb328240763ed0", null ], + [ "replace", "classpcs_1_1_cpp_string_t.html#ad4f39683db649aa8a65907268c499f02", null ], + [ "rfind", "classpcs_1_1_cpp_string_t.html#ac00bb6f7d74bfdde0d4cc247e78ab20e", null ], + [ "rfind", "classpcs_1_1_cpp_string_t.html#a9f43f20029596abc1362d1242e68e5db", null ], + [ "rfind", "classpcs_1_1_cpp_string_t.html#af363308ba741b267641e1aa35669d603", null ], + [ "rfind_n", "classpcs_1_1_cpp_string_t.html#a790f663f51dfe6e9e15d4f5f025bf107", null ], + [ "rfind_n", "classpcs_1_1_cpp_string_t.html#a519a292eb3f0790d54a59a201f2d6410", null ], + [ "rindex", "classpcs_1_1_cpp_string_t.html#a546105cc9a8a9d493979c30607092cf1", null ], + [ "rindex", "classpcs_1_1_cpp_string_t.html#a2baca0ddff848de56a7b867f68d3efab", null ], + [ "rindex", "classpcs_1_1_cpp_string_t.html#a6693ec49258c6ac80a7875b3ebf3c916", null ], + [ "rindex_n", "classpcs_1_1_cpp_string_t.html#ac3079cbecbdf4151e66f602f39ece836", null ], + [ "rindex_n", "classpcs_1_1_cpp_string_t.html#afc08a4e91b93710838c8f0d6234e057e", null ], + [ "rjust", "classpcs_1_1_cpp_string_t.html#a61fd4215938ec9f0fce1f885d6bb4a2b", null ], + [ "rpartition", "classpcs_1_1_cpp_string_t.html#a61674ee4e97038d82ea7ecc30b1761f6", null ], + [ "rsplit", "classpcs_1_1_cpp_string_t.html#a8111cd357773d304fbb496571d7ee6be", null ], + [ "rsplit", "classpcs_1_1_cpp_string_t.html#a0419f46de6fa532372f3b97b4927ebab", null ], + [ "rsplit", "classpcs_1_1_cpp_string_t.html#ab0ace502f0b3026fefd2942a1e8a0456", null ], + [ "rsplit", "classpcs_1_1_cpp_string_t.html#a3aa66706e268bd570a0084d70dff5cde", null ], + [ "rstrip", "classpcs_1_1_cpp_string_t.html#a86f8c78b2eeb3541fb6b56b4f4ac237b", null ], + [ "rstrip", "classpcs_1_1_cpp_string_t.html#a89e850d45d6dec167e763cf748a06971", null ], + [ "split", "classpcs_1_1_cpp_string_t.html#a7ca47096b03baa0091c3b0349d210931", null ], + [ "split", "classpcs_1_1_cpp_string_t.html#acf4d923cfed55cfd90cf12651ce0ac3d", null ], + [ "split", "classpcs_1_1_cpp_string_t.html#a55a3fa32de834f644ac28d7c2495fa77", null ], + [ "split", "classpcs_1_1_cpp_string_t.html#a8fa2afe84d7fc26f96bbd55f4266df2a", null ], + [ "splitlines", "classpcs_1_1_cpp_string_t.html#a0bd53df14569c307b5ca50a2e1e62960", null ], + [ "startswith", "classpcs_1_1_cpp_string_t.html#ae2f755ae7903586a2086b7b7f943d96e", null ], + [ "startswith", "classpcs_1_1_cpp_string_t.html#ad2cfcc7bd22736ebd9f91f04e6a42f8c", null ], + [ "startswith", "classpcs_1_1_cpp_string_t.html#a5a131c385a01ccc5410d4cffa55cf700", null ], + [ "startswith", "classpcs_1_1_cpp_string_t.html#a326eb96e19c3559a84af86ff1bf54aa4", null ], + [ "startswith_n", "classpcs_1_1_cpp_string_t.html#ae0865e2c7f8a4871804bf71c1c982dc6", null ], + [ "startswith_n", "classpcs_1_1_cpp_string_t.html#a3b7955f9c7f9452a6a025caaaf0e6d73", null ], + [ "startswith_n", "classpcs_1_1_cpp_string_t.html#ab2b293c5f1b55af52ceb75b8f7e4d42e", null ], + [ "strip", "classpcs_1_1_cpp_string_t.html#a12bc043347f555b4701e0c70d972058d", null ], + [ "strip", "classpcs_1_1_cpp_string_t.html#a02919129cdf158e75eae1e9815a071bf", null ], + [ "substr", "classpcs_1_1_cpp_string_t.html#a9debc70420a3fbc7722e3111aeccd819", null ], + [ "swapcase", "classpcs_1_1_cpp_string_t.html#a6ab02b4d1c8093a5dfc089a45427f63c", null ], + [ "title", "classpcs_1_1_cpp_string_t.html#a179634aafb049e8604ca78f813684a28", null ], + [ "translate", "classpcs_1_1_cpp_string_t.html#a2a8c1e78b93da9a0abe471c7a8d85090", null ], + [ "upper", "classpcs_1_1_cpp_string_t.html#a689d2de98f28d131bb0c8b3c87f2f120", null ], + [ "zfill", "classpcs_1_1_cpp_string_t.html#ad3d2b94f37325096205e399b95e9fc5d", null ] +]; \ No newline at end of file diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t.png b/cpp-strings/html/classpcs_1_1_cpp_string_t.png new file mode 100644 index 0000000..ce95fd5 Binary files /dev/null and b/cpp-strings/html/classpcs_1_1_cpp_string_t.png differ diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception-members.html b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception-members.html new file mode 100644 index 0000000..96404b2 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception-members.html @@ -0,0 +1,108 @@ + + + + + + + +cpp-strings: Member List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException Member List
+
+ +
+
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.html b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.html new file mode 100644 index 0000000..a96dad0 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.html @@ -0,0 +1,132 @@ + + + + + + + +cpp-strings: pcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException Class Reference + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException Class Reference
+
+
+
+Inheritance diagram for pcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException:
+
+
+ +
+ + + +

+Public Types

+using MyBaseClass = std::logic_error
+ + + +

+Public Member Functions

NotFoundException (const char *what_arg)
NotFoundException (const std::string &what_arg)
+
The documentation for this class was generated from the following file: +
+
+ +
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.png b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.png new file mode 100644 index 0000000..55751e8 Binary files /dev/null and b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.png differ diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table-members.html b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table-members.html new file mode 100644 index 0000000..19c9850 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table-members.html @@ -0,0 +1,126 @@ + + + + + + + +cpp-strings: Member List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable Member List
+
+
+ +

This is the complete list of members for pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + +
get_table() noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
key_type typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable
operator=(const TransTable &) noexcept=defaultpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
operator=(TransTable &&) noexcept=defaultpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
operator=(const std::map< key_type, value_type > &trans_table) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
operator[](const key_type ch) noexceptpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(const std::map< key_type, value_type > trans_table)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(const CppStringT &keys, const CppStringT &values)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(const CppStringT &keys, const CppStringT &values, const CppStringT &not_translated)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(const CppStringT &keys, const std::initializer_list< CppStringT > &values)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(const CppStringT &keys, const std::initializer_list< CppStringT > values, const CppStringT &not_translated)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(const CharT *keys, const CharT *values)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(const CharT *keys, const CharT *values, const CharT *not_translated)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(KeyIt first_key, KeyIt last_key, ValueIt first_value, ValueIt last_value)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(Key1It first_key, Key1It last_key, ValueIt first_value, ValueIt last_value, Key2It first_not_translated, Key2It last_not_translated)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(const StringViewLike &keys, const StringViewLike &values)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinlineexplicit
TransTable() noexcept=defaultpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(const TransTable &) noexcept=defaultpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
TransTable(TransTable &&) noexcept=defaultpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
value_type typedef (defined in pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable)pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable
~TransTable() noexcept=defaultpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableinline
+
+
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table.html b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table.html new file mode 100644 index 0000000..b013f68 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table.html @@ -0,0 +1,836 @@ + + + + + + + +cpp-strings: pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable Class Reference + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable Class Reference
+
+
+ +

The internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate. + More...

+ +

#include <cppstrings.h>

+ + + + +

+Public Types

+using key_type = CharT
+using value_type = CppStringT
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

std::map< typename key_type, typename value_type > & get_table () noexcept
 < for tests purposes
TransTableoperator= (const std::map< key_type, value_type > &trans_table) noexcept
 Assignment operator with a standard map.
TransTableoperator= (const TransTable &) noexcept=default
 Default copy assignment.
TransTableoperator= (TransTable &&) noexcept=default
 Default move assignment.
value_type operator[] (const key_type ch) noexcept
 Indexing operator.
 TransTable () noexcept=default
 Default empty constructor.
 TransTable (const CharT *keys, const CharT *values)
 Creates a TransTable from two pointers to null-terminated lists of characters (#6).
 TransTable (const CharT *keys, const CharT *values, const CharT *not_translated)
 Creates a TransTable from three pointers to null-terminated lists of characters (#7).
 TransTable (const CppStringT &keys, const CppStringT &values)
 Creates a TransTable from two strings (#2).
 TransTable (const CppStringT &keys, const CppStringT &values, const CppStringT &not_translated)
 Creates a TransTable from three strings (#3).
 TransTable (const CppStringT &keys, const std::initializer_list< CppStringT > &values)
 Creates a TransTable from a string and an initalization list (#4).
 TransTable (const CppStringT &keys, const std::initializer_list< CppStringT > values, const CppStringT &not_translated)
 Creates a TransTable from a string, an initalization list and a string (#5).
 TransTable (const std::map< key_type, value_type > trans_table)
 Creates a TransTable from a standard map (#1).
template<class StringViewLike>
 TransTable (const StringViewLike &keys, const StringViewLike &values)
 Creates a TransTable from two string views (#10).
 TransTable (const TransTable &) noexcept=default
 Default copy constructor.
template<class Key1It, class ValueIt, class Key2It>
 TransTable (Key1It first_key, Key1It last_key, ValueIt first_value, ValueIt last_value, Key2It first_not_translated, Key2It last_not_translated)
 Creates a TransTable from three containers iterators (#9).
template<class KeyIt, class ValueIt>
 TransTable (KeyIt first_key, KeyIt last_key, ValueIt first_value, ValueIt last_value)
 Creates a TransTable from two containers iterators (#8).
 TransTable (TransTable &&) noexcept=default
 Default move constructor.
 ~TransTable () noexcept=default
 Default descrtuctor.
+

Detailed Description

+
template<class CharT, class TraitsT, class AllocatorT>
+class pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable

The internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate.

+

Constructor & Destructor Documentation

+ +

◆ TransTable() [1/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (const std::map< key_type, value_type > trans_table)
+
+inline
+
+ +

Creates a TransTable from a standard map (#1).

+ +

Referenced by operator=(), operator=(), operator=(), TransTable(), TransTable(), and ~TransTable().

+ +
+
+ +

◆ TransTable() [2/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (const CppStringT & keys,
const CppStringT & values )
+
+inline
+
+ +

Creates a TransTable from two strings (#2).

+

Parameters keys and values must have the same size. The i-th character in key is associated in the translation table with the i-th character in values.

+ +
+
+ +

◆ TransTable() [3/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (const CppStringT & keys,
const CppStringT & values,
const CppStringT & not_translated )
+
+inline
+
+ +

Creates a TransTable from three strings (#3).

+

Parameters keys and values must have the same size. The i-th character in key is associated in the translation table with the i -th character in values. Finally, the characters contained in string not_translated are associated in the translation table with the empty string.

+ +
+
+ +

◆ TransTable() [4/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (const CppStringT & keys,
const std::initializer_list< CppStringT > & values )
+
+inline
+
+ +

Creates a TransTable from a string and an initalization list (#4).

+

Parameters keys and values must have the same size. The i-th character in key is associated in the translation table with the i-th character in values.

+ +
+
+ +

◆ TransTable() [5/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (const CppStringT & keys,
const std::initializer_list< CppStringT > values,
const CppStringT & not_translated )
+
+inline
+
+ +

Creates a TransTable from a string, an initalization list and a string (#5).

+

Parameters keys and values must have the same size. The i-th character in key is associated in the translation table with the i -th character in values. Finally, the characters contained in string not_translated are associated in the translation table with the empty string.

+ +
+
+ +

◆ TransTable() [6/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (const CharT * keys,
const CharT * values )
+
+inline
+
+ +

Creates a TransTable from two pointers to null-terminated lists of characters (#6).

+

Parameters keys and values must have the same size. The i-th character in key is associated in the translation table with the i-th character in values.

+ +
+
+ +

◆ TransTable() [7/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (const CharT * keys,
const CharT * values,
const CharT * not_translated )
+
+inline
+
+ +

Creates a TransTable from three pointers to null-terminated lists of characters (#7).

+

Parameters keys and values must have the same size. The i-th character in key is associated in the translation table with the i -th entry in values. Finally, the characters contained in string not_translated are associated in the translation table with the empty string.

+ +
+
+ +

◆ TransTable() [8/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+
+template<class KeyIt, class ValueIt>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (KeyIt first_key,
KeyIt last_key,
ValueIt first_value,
ValueIt last_value )
+
+inline
+
+ +

Creates a TransTable from two containers iterators (#8).

+

Both containers should have the same size. The i-th character in key is associated in the translation table with the i-th entry in values.

+ +
+
+ +

◆ TransTable() [9/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+
+template<class Key1It, class ValueIt, class Key2It>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (Key1It first_key,
Key1It last_key,
ValueIt first_value,
ValueIt last_value,
Key2It first_not_translated,
Key2It last_not_translated )
+
+inline
+
+ +

Creates a TransTable from three containers iterators (#9).

+

Both containers should have the same size. The i-th character in key is associated in the translation table with the i -th character in values. Finally, the characters contained in string not_translated are associated in the translation table with the empty string.

+ +
+
+ +

◆ TransTable() [10/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+
+template<class StringViewLike>
+ + + + + +
+ + + + + + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (const StringViewLike & keys,
const StringViewLike & values )
+
+inlineexplicit
+
+ +

Creates a TransTable from two string views (#10).

+

Parameters keys and values must have the same size. The i-th character in key is associated in the translation table with the i-th character in values.

+ +
+
+ +

◆ TransTable() [11/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable ()
+
+inlinedefaultnoexcept
+
+ +

Default empty constructor.

+ +
+
+ +

◆ TransTable() [12/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (const TransTable & )
+
+inlinedefaultnoexcept
+
+ +

Default copy constructor.

+ +

References TransTable().

+ +
+
+ +

◆ TransTable() [13/13]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::TransTable (TransTable && )
+
+inlinedefaultnoexcept
+
+ +

Default move constructor.

+ +

References TransTable().

+ +
+
+ +

◆ ~TransTable()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::~TransTable ()
+
+inlinedefaultnoexcept
+
+ +

Default descrtuctor.

+ +

References TransTable().

+ +
+
+

Member Function Documentation

+ +

◆ get_table()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
std::map< typename key_type, typename value_type > & pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::get_table ()
+
+inlinenoexcept
+
+ +

< for tests purposes

+ +
+
+ +

◆ operator=() [1/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
TransTable & pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::operator= (const std::map< key_type, value_type > & trans_table)
+
+inlinenoexcept
+
+ +

Assignment operator with a standard map.

+ +

References TransTable().

+ +
+
+ +

◆ operator=() [2/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
TransTable & pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::operator= (const TransTable & )
+
+inlinedefaultnoexcept
+
+ +

Default copy assignment.

+ +

References TransTable().

+ +
+
+ +

◆ operator=() [3/3]

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
TransTable & pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::operator= (TransTable && )
+
+inlinedefaultnoexcept
+
+ +

Default move assignment.

+ +

References TransTable().

+ +
+
+ +

◆ operator[]()

+ +
+
+
+template<class CharT, class TraitsT, class AllocatorT>
+ + + + + +
+ + + + + + + +
value_type pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable::operator[] (const key_type ch)
+
+inlinenodiscardnoexcept
+
+ +

Indexing operator.

+ +
+
+
The documentation for this class was generated from the following file: +
+
+ +
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table.js b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table.js new file mode 100644 index 0000000..0e992a7 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table.js @@ -0,0 +1,22 @@ +var classpcs_1_1_cpp_string_t_1_1_trans_table = +[ + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a1fea49a165ebb7cda36c1bfdcbe95ee0", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a5efa34c2e8b016458388693a7ab8f590", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#aa99c6a9fafac1361cd8a0fc4578fa084", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#aae6cedd7e9c8409e76787c910476813e", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#abf0efc2e493b5c0347327b7c1f175ed8", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a9d7651fe71544575150ebc08022cb885", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a78d8ac95a740d405c761c73166c9b787", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a551b96c6c0ab2bf9183de0bfcc6770a2", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a1c10bb78e74942f88247cde65a03d557", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a21791e46266edb8eea13876559b352a2", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a7da38829b171a7a9147b43086e067454", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a69a3ab2775d7e6537528a3eba3c4134a", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#aa9182c3323cdba7f6dd30bfa56ebb8fe", null ], + [ "~TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#abbbcd9cf0c3ac0a364864f734363dd4c", null ], + [ "get_table", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#ab7a09175127849e20aa8aa5b999b4413", null ], + [ "operator=", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a4f1dd7fb1ede54aa662c808eb84cda41", null ], + [ "operator=", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#addccd32880c403ee20a6a8423d8d3f8b", null ], + [ "operator=", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a3efc5aab74f3a0594a9e88562d57867d", null ], + [ "operator[]", "classpcs_1_1_cpp_string_t_1_1_trans_table.html#a90ac2a729fc715870e7f32ea9c6536f9", null ] +]; \ No newline at end of file diff --git a/cpp-strings/html/classpcs_1_1_slice-members.html b/cpp-strings/html/classpcs_1_1_slice-members.html new file mode 100644 index 0000000..b6e1a5f --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_slice-members.html @@ -0,0 +1,116 @@ + + + + + + + +cpp-strings: Member List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::Slice< IntT > Member List
+
+
+ +

This is the complete list of members for pcs::Slice< IntT >, including all inherited members.

+ + + + + + + + + + + + +
begin(const CppStringT< CharT > &str) noexceptpcs::Slice< IntT >inline
DEFAULT (defined in pcs::Slice< IntT >)pcs::Slice< IntT >static
end() const noexceptpcs::Slice< IntT >inline
operator*() noexceptpcs::Slice< IntT >inline
operator++() noexceptpcs::Slice< IntT >inline
operator++(int) noexceptpcs::Slice< IntT >inline
Slice(const IntT start=DEFAULT, const IntT stop=DEFAULT, const IntT step=DEFAULT) noexceptpcs::Slice< IntT >inline
start()pcs::Slice< IntT >inline
step()pcs::Slice< IntT >inline
stop()pcs::Slice< IntT >inline
~Slice() noexcept=defaultpcs::Slice< IntT >virtual
+
+
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_slice.html b/cpp-strings/html/classpcs_1_1_slice.html new file mode 100644 index 0000000..3bbc794 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_slice.html @@ -0,0 +1,485 @@ + + + + + + + +cpp-strings: pcs::Slice< IntT > Class Template Reference + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::Slice< IntT > Class Template Reference
+
+
+ +

Base class for slices, with start, stop and step specified values. + More...

+ +

#include <cppstrings.h>

+
+Inheritance diagram for pcs::Slice< IntT >:
+
+
+ + +pcs::StartSlice< IntT > +pcs::StartStepSlice< IntT > +pcs::StartStopSlice< IntT > +pcs::StepSlice< IntT > +pcs::StopSlice< IntT > +pcs::StopStepSlice< IntT > + +
+ + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

template<typename CharT = char>
+requires std::is_same_v<CharT, char> || std::is_same_v<CharT, char16_t> || std::is_same_v<CharT, char32_t> || std::is_same_v<CharT, wchar_t>
const IntT begin (const CppStringT< CharT > &str) noexcept
 < starts iterating on specified CppString.
const bool end () const noexcept
 < returns true when iterating is over, or false otherwise.
const IntT operator* () noexcept
 < dereferences the slice.
Slice operator++ () noexcept
 < iterates one step, pre-increment. Caution: index may be out of bounds. Check '!end()' before dereferencing the slice.
Slice operator++ (int) noexcept
 < iterates one step, post-increment. Caution: index may be out of bounds. Check '!end()' before dereferencing the slice.
 Slice (const IntT start=DEFAULT, const IntT stop=DEFAULT, const IntT step=DEFAULT) noexcept
 < Valued constructor
IntT start ()
 Returns the start index of this slide.
IntT step ()
 Returns the step value of this slide.
IntT stop ()
 Returns the stop index of this slide.
virtual ~Slice () noexcept=default
 Default destructor.
+ + +

+Static Public Attributes

+static constexpr IntT DEFAULT { std::numeric_limits<IntT>::min() }
+

Detailed Description

+
template<typename IntT>
+requires std::is_signed_v<IntT>
+class pcs::Slice< IntT >

Base class for slices, with start, stop and step specified values.

+

Constructor & Destructor Documentation

+ +

◆ Slice()

+ +
+
+
+template<typename IntT>
+ + + + + +
+ + + + + + + + + + + + + + + + +
pcs::Slice< IntT >::Slice (const IntT start = DEFAULT,
const IntT stop = DEFAULT,
const IntT step = DEFAULT )
+
+inlinenoexcept
+
+ +

< Valued constructor

+ +

References start(), step(), and stop().

+ +

Referenced by operator++(), and operator++().

+ +
+
+ +

◆ ~Slice()

+ +
+
+
+template<typename IntT>
+ + + + + +
+ + + + + + + +
virtual pcs::Slice< IntT >::~Slice ()
+
+virtualdefaultnoexcept
+
+ +

Default destructor.

+ +
+
+

Member Function Documentation

+ +

◆ begin()

+ +
+
+
+template<typename IntT>
+
+template<typename CharT = char>
+requires std::is_same_v<CharT, char> || std::is_same_v<CharT, char16_t> || std::is_same_v<CharT, char32_t> || std::is_same_v<CharT, wchar_t>
+ + + + + +
+ + + + + + + +
const IntT pcs::Slice< IntT >::begin (const CppStringT< CharT > & str)
+
+inlinenoexcept
+
+ +

< starts iterating on specified CppString.

+ +
+
+ +

◆ end()

+ +
+
+
+template<typename IntT>
+ + + + + +
+ + + + + + + +
const bool pcs::Slice< IntT >::end () const
+
+inlinenodiscardnoexcept
+
+ +

< returns true when iterating is over, or false otherwise.

+ +
+
+ +

◆ operator*()

+ +
+
+
+template<typename IntT>
+ + + + + +
+ + + + + + + +
const IntT pcs::Slice< IntT >::operator* ()
+
+inlinenodiscardnoexcept
+
+ +

< dereferences the slice.

+ +
+
+ +

◆ operator++() [1/2]

+ +
+
+
+template<typename IntT>
+ + + + + +
+ + + + + + + +
Slice pcs::Slice< IntT >::operator++ ()
+
+inlinenoexcept
+
+ +

< iterates one step, pre-increment. Caution: index may be out of bounds. Check '!end()' before dereferencing the slice.

+ +

References Slice().

+ +
+
+ +

◆ operator++() [2/2]

+ +
+
+
+template<typename IntT>
+ + + + + +
+ + + + + + + +
Slice pcs::Slice< IntT >::operator++ (int )
+
+inlinenoexcept
+
+ +

< iterates one step, post-increment. Caution: index may be out of bounds. Check '!end()' before dereferencing the slice.

+ +

References Slice().

+ +
+
+ +

◆ start()

+ +
+
+
+template<typename IntT>
+ + + + + +
+ + + + + + + +
IntT pcs::Slice< IntT >::start ()
+
+inline
+
+
+ +

◆ step()

+ +
+
+
+template<typename IntT>
+ + + + + +
+ + + + + + + +
IntT pcs::Slice< IntT >::step ()
+
+inline
+
+
+ +

◆ stop()

+ +
+
+
+template<typename IntT>
+ + + + + +
+ + + + + + + +
IntT pcs::Slice< IntT >::stop ()
+
+inline
+
+
+
The documentation for this class was generated from the following file: +
+
+ +
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_slice.js b/cpp-strings/html/classpcs_1_1_slice.js new file mode 100644 index 0000000..e725231 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_slice.js @@ -0,0 +1,13 @@ +var classpcs_1_1_slice = +[ + [ "Slice", "classpcs_1_1_slice.html#ab51c3b03351e495729545f2fdaebb888", null ], + [ "~Slice", "classpcs_1_1_slice.html#abdb6694913ed37cf4efc5d85e990c7b5", null ], + [ "begin", "classpcs_1_1_slice.html#ab55cf50ae2018337b942e7b9e08e3e6d", null ], + [ "end", "classpcs_1_1_slice.html#aee5b0e0110ef1ee32763da9b2386b59c", null ], + [ "operator*", "classpcs_1_1_slice.html#afa6b7dc85e796da20dd5933d49400996", null ], + [ "operator++", "classpcs_1_1_slice.html#a79edb1eb4e6bce136f730d82f7afeaff", null ], + [ "operator++", "classpcs_1_1_slice.html#aa3e4bcf5cfd5917cc10e0641030984c2", null ], + [ "start", "classpcs_1_1_slice.html#a5280a9d6974217c94de5d9027e10d4e1", null ], + [ "step", "classpcs_1_1_slice.html#a55f046a5343a6ea1bbff8686d2e72d78", null ], + [ "stop", "classpcs_1_1_slice.html#a0fed0ac66885187eb64d1982e0461916", null ] +]; \ No newline at end of file diff --git a/cpp-strings/html/classpcs_1_1_slice.png b/cpp-strings/html/classpcs_1_1_slice.png new file mode 100644 index 0000000..85e73c3 Binary files /dev/null and b/cpp-strings/html/classpcs_1_1_slice.png differ diff --git a/cpp-strings/html/clipboard.js b/cpp-strings/html/clipboard.js new file mode 100644 index 0000000..9da9f3c --- /dev/null +++ b/cpp-strings/html/clipboard.js @@ -0,0 +1,61 @@ +/** + +The code below is based on the Doxygen Awesome project, see +https://github.com/jothepro/doxygen-awesome-css + +MIT License + +Copyright (c) 2021 - 2022 jothepro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +let clipboard_title = "Copy to clipboard" +let clipboard_icon = `` +let clipboard_successIcon = `` +let clipboard_successDuration = 1000 + +$(function() { + if(navigator.clipboard) { + const fragments = document.getElementsByClassName("fragment") + for(const fragment of fragments) { + const clipboard_div = document.createElement("div") + clipboard_div.classList.add("clipboard") + clipboard_div.innerHTML = clipboard_icon + clipboard_div.title = clipboard_title + $(clipboard_div).click(function() { + const content = this.parentNode.cloneNode(true) + // filter out line number and folded fragments from file listings + content.querySelectorAll(".lineno, .ttc, .foldclosed").forEach((node) => { node.remove() }) + let text = content.textContent + // remove trailing newlines and trailing spaces from empty lines + text = text.replace(/^\s*\n/gm,'\n').replace(/\n*$/,'') + navigator.clipboard.writeText(text); + this.classList.add("success") + this.innerHTML = clipboard_successIcon + window.setTimeout(() => { // switch back to normal icon after timeout + this.classList.remove("success") + this.innerHTML = clipboard_icon + }, clipboard_successDuration); + }) + fragment.insertBefore(clipboard_div, fragment.firstChild) + } + } +}) diff --git a/cpp-strings/html/cookie.js b/cpp-strings/html/cookie.js new file mode 100644 index 0000000..53ad21d --- /dev/null +++ b/cpp-strings/html/cookie.js @@ -0,0 +1,58 @@ +/*! + Cookie helper functions + Copyright (c) 2023 Dimitri van Heesch + Released under MIT license. +*/ +let Cookie = { + cookie_namespace: 'doxygen_', + + readSetting(cookie,defVal) { + if (window.chrome) { + const val = localStorage.getItem(this.cookie_namespace+cookie) || + sessionStorage.getItem(this.cookie_namespace+cookie); + if (val) return val; + } else { + let myCookie = this.cookie_namespace+cookie+"="; + if (document.cookie) { + const index = document.cookie.indexOf(myCookie); + if (index != -1) { + const valStart = index + myCookie.length; + let valEnd = document.cookie.indexOf(";", valStart); + if (valEnd == -1) { + valEnd = document.cookie.length; + } + return document.cookie.substring(valStart, valEnd); + } + } + } + return defVal; + }, + + writeSetting(cookie,val,days=10*365) { // default days='forever', 0=session cookie, -1=delete + if (window.chrome) { + if (days==0) { + sessionStorage.setItem(this.cookie_namespace+cookie,val); + } else { + localStorage.setItem(this.cookie_namespace+cookie,val); + } + } else { + let date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + const expiration = days!=0 ? "expires="+date.toGMTString()+";" : ""; + document.cookie = this.cookie_namespace + cookie + "=" + + val + "; SameSite=Lax;" + expiration + "path=/"; + } + }, + + eraseSetting(cookie) { + if (window.chrome) { + if (localStorage.getItem(this.cookie_namespace+cookie)) { + localStorage.removeItem(this.cookie_namespace+cookie); + } else if (sessionStorage.getItem(this.cookie_namespace+cookie)) { + sessionStorage.removeItem(this.cookie_namespace+cookie); + } + } else { + this.writeSetting(cookie,'',-1); + } + }, +} diff --git a/cpp-strings/html/cppstrings_8h_source.html b/cpp-strings/html/cppstrings_8h_source.html new file mode 100644 index 0000000..6f058ee --- /dev/null +++ b/cpp-strings/html/cppstrings_8h_source.html @@ -0,0 +1,2231 @@ + + + + + + + +cpp-strings: cppstrings.h Source File + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
cppstrings.h
+
+
+
1#pragma once
+
22
+
23//=============================================================
+
24#include <algorithm>
+
25#include <array>
+
26#include <cassert>
+
27#include <cctype>
+
28#include <cwctype>
+
29#include <format>
+
30#include <limits>
+
31#include <map>
+
32#include <ranges>
+
33#include <span>
+
34#include <stdexcept>
+
35#include <type_traits>
+
36#include <vector>
+
37
+
38
+
39
+
40namespace pcs // i.e. "pythonic c++ strings"
+
41{
+
42 //=============================================================
+
43 // Forward declarations
+
44
+
45 // base class -- not to be directly instantiated, see belowing specializations instead
+
46 template<
+
47 class CharT,
+
48 class TraitsT = std::char_traits<CharT>,
+
49 class AllocatorT = std::allocator<CharT>
+
50 > class CppStringT;
+
51
+
52 // specializations of the base class -- these are the ones that should be instantiated by user.
+ + +
55
+
56
+
57#if defined(_MSC_VER)
+
58# pragma warning(push)
+
59# pragma warning(disable: 4455) // to avoid boring warnings with litteral operators definitions
+
60#endif
+
61
+
62 // litteral operators
+
63 inline CppString operator""_cs(const char* str, std::size_t len);
+
64 inline CppWString operator""_cs(const wchar_t* str, std::size_t len);
+
65
+
66
+
67 // slices -- to be used with operator CppStringT::operator().
+
68 template<typename IntT = std::int64_t>
+
69 requires std::is_signed_v<IntT>
+
70 class Slice;
+
71
+
72 template<typename IntT = std::int64_t>
+
73 requires std::is_signed_v<IntT>
+
74 struct StartSlice;
+
75
+
76 template<typename IntT = std::int64_t>
+
77 requires std::is_signed_v<IntT>
+
78 struct StopSlice;
+
79
+
80 template<typename IntT = std::int64_t>
+
81 requires std::is_signed_v<IntT>
+
82 struct StepSlice;
+
83
+
84 template<typename IntT = std::int64_t>
+
85 requires std::is_signed_v<IntT>
+
86 struct StartStopSlice;
+
87
+
88 template<typename IntT = std::int64_t>
+
89 requires std::is_signed_v<IntT>
+
90 struct StartStepSlice;
+
91
+
92 template<typename IntT = std::int64_t>
+
93 requires std::is_signed_v<IntT>
+
94 struct StopStepSlice;
+
95
+
96
+
97 // chars classifications -- not to be directly called, see respective specializations at the very end of this module.
+
98 template<class CharT>
+
99 inline const bool is_alpha(const CharT ch) noexcept;
+
100
+
101 template<class CharT>
+
102 inline const bool is_ascii(const CharT ch) noexcept;
+
103
+
104 template<class CharT>
+
105 inline const bool is_decimal(const CharT ch) noexcept;
+
106
+
107 template<class CharT>
+
108 inline const bool is_digit(const CharT ch) noexcept;
+
109
+
110 template<class CharT>
+
111 inline const bool is_id_continue(const CharT ch) noexcept;
+
112
+
113 template<class CharT>
+
114 inline const bool is_id_start(const CharT ch) noexcept;
+
115
+
116 template<class CharT>
+
117 inline const bool is_lower(const CharT ch) noexcept;
+
118
+
119 template<class CharT>
+
120 inline const bool is_numeric(const CharT ch) noexcept;
+
121
+
122 template<class CharT>
+
123 inline const bool is_printable(const CharT ch) noexcept;
+
124
+
125 template<class CharT>
+
126 inline const bool is_punctuation(const CharT ch) noexcept;
+
127
+
128 template<class CharT>
+
129 inline const bool is_space(const CharT ch) noexcept;
+
130
+
131 template<class CharT>
+
132 inline const bool is_upper(const CharT ch) noexcept;
+
133
+
134 template<class CharT>
+
135 inline const CharT swap_case(const CharT ch) noexcept;
+
136
+
137 template<class CharT>
+
138 inline const CharT to_lower(const CharT ch) noexcept;
+
139
+
140 template<class CharT>
+
141 inline const CharT to_upper(const CharT ch) noexcept;
+
142
+
143
+
144 //===== CppStringT<> ======================================
+
164 template<class CharT, class TraitsT, class AllocatorT>
+
165 class CppStringT : public std::basic_string<CharT, TraitsT, AllocatorT>
+
166 {
+
167 public:
+
168 //=== Wrappers ========================================
+
169 using MyBaseClass = std::basic_string<CharT, TraitsT, AllocatorT>;
+
170
+
171 using traits_type = MyBaseClass::traits_type;
+
172 using value_type = MyBaseClass::value_type;
+
173 using allocator_type = MyBaseClass::allocator_type;
+
174 using size_type = MyBaseClass::size_type;
+
175 using difference_type = MyBaseClass::difference_type;
+
176 using reference = MyBaseClass::reference;
+
177 using const_reference = MyBaseClass::const_reference;
+
178 using pointer = MyBaseClass::pointer;
+
179 using const_pointer = MyBaseClass::const_pointer;
+
180 using iterator = MyBaseClass::iterator;
+
181 using const_iterator = MyBaseClass::const_iterator;
+
182 using reverse_iterator = MyBaseClass::reverse_iterator;
+
183 using const_reverse_iterator = MyBaseClass::const_reverse_iterator;
+
184
+
185
+
186 //=== Translation Table ===============================
+ +
189 {
+
190 public:
+
191 //--- wrappers ------------------------------------
+
192 using key_type = CharT;
+
193 using value_type = CppStringT;
+
194
+
195 //--- Constructors / destructor -------------------
+
197 inline TransTable(const std::map<key_type, value_type> trans_table)
+
198 : m_table{ trans_table }
+
199 {}
+
200
+
207 TransTable(const CppStringT& keys, const CppStringT& values)
+
208 {
+
209 assert(keys.size() == values.size());
+
210 auto val_it = values.cbegin();
+
211 for (const auto k : keys)
+
212 m_table[k] = CppStringT(*val_it++);
+
213 }
+
214
+
223 TransTable(const CppStringT& keys, const CppStringT& values, const CppStringT& not_translated)
+
224 {
+
225 assert(keys.size() == values.size());
+
226 auto val_it = values.cbegin();
+
227 for (const auto k : keys)
+
228 m_table[k] = CppStringT(*val_it++);
+
229 for (const auto k : not_translated)
+
230 m_table[k] = CppStringT();
+
231 }
+
232
+
239 inline TransTable(const CppStringT& keys, const std::initializer_list<CppStringT>& values)
+
240 {
+
241 assert(keys.size() == values.size());
+
242 auto val_it = values.begin();
+
243 for (const auto k : keys)
+
244 m_table[k] = *val_it++;
+
245 }
+
246
+
255 inline TransTable(const CppStringT& keys, const std::initializer_list<CppStringT> values, const CppStringT& not_translated)
+
256 {
+
257 assert(keys.size() == values.size());
+
258 auto val_it = values.begin();
+
259 for (const auto k : keys)
+
260 m_table[k] = *val_it++;
+
261 for (const auto k : not_translated)
+
262 m_table[k] = CppStringT();
+
263 }
+
264
+
271 inline TransTable(const CharT* keys, const CharT* values)
+
272 {
+
273 while (*keys && *values)
+
274 m_table[*keys++] = value_type(*values++);
+
275 }
+
276
+
285 inline TransTable(const CharT* keys, const CharT* values, const CharT* not_translated)
+
286 {
+
287 while (*keys && *values)
+
288 m_table[*keys++] = value_type(*values++);
+
289 while (*not_translated)
+
290 m_table[*not_translated++] = CppStringT();
+
291 }
+
292
+
299 template<class KeyIt, class ValueIt>
+
300 inline TransTable(KeyIt first_key, KeyIt last_key, ValueIt first_value, ValueIt last_value)
+
301 {
+
302 KeyIt key_it{ first_key };
+
303 ValueIt val_it{ first_value };
+
304 while (key_it != last_key && val_it != last_value)
+
305 m_table[*key_it++] = value_type(*val_it++);
+
306 }
+
307
+
316 template<class Key1It, class ValueIt, class Key2It>
+
317 inline TransTable(Key1It first_key, Key1It last_key,
+
318 ValueIt first_value, ValueIt last_value,
+
319 Key2It first_not_translated, Key2It last_not_translated)
+
320 {
+
321 Key1It key1_it{ first_key };
+
322 ValueIt val_it{ first_value };
+
323 while (key1_it != last_key && val_it != last_value)
+
324 m_table[*key1_it++] = value_type(*val_it++);
+
325 Key2It key2_it{ first_not_translated };
+
326 while (key2_it != last_not_translated)
+
327 m_table[*key2_it++] = CppStringT();
+
328 }
+
329
+
336 /**/
+
337 template<class StringViewLike>
+
338 explicit TransTable(const StringViewLike& keys, const StringViewLike& values)
+
339 {
+
340 assert(keys.size() == values.size());
+
341 auto val_it = values.cbegin();
+
342 for (const auto k : keys)
+
343 m_table[(*k)[0]] = value_type(*val_it++);
+
344 }
+
345
+
346 inline TransTable() noexcept = default;
+
347 inline TransTable(const TransTable&) noexcept = default;
+
348 inline TransTable(TransTable&&) noexcept = default;
+
349
+
350 inline ~TransTable() noexcept = default;
+
351
+
352 //--- operators -----------------------------------
+
353 inline TransTable& operator= (const TransTable&) noexcept = default;
+
354 inline TransTable& operator= (TransTable&&) noexcept = default;
+
355
+
357 inline TransTable& operator= (const std::map<key_type, value_type>& trans_table) noexcept
+
358 {
+
359 m_table = trans_table;
+
360 return *this;
+
361 }
+
362
+
364 [[nodiscard]]
+
365 inline value_type operator[] (const key_type ch) noexcept
+
366 {
+
367 auto it = m_table.find(ch);
+
368 if (it != m_table.end()) [[likely]] {
+
369 return it->second;
+
370 }
+
371 else [[unlikely]] {
+
372 return ch;
+
373 }
+
374 }
+
375
+
376 inline std::map<typename key_type, typename value_type>& get_table() noexcept
+
377 {
+
378 return m_table;
+
379 }
+
380
+
381 private:
+
382 std::map<typename key_type, typename value_type> m_table{}; // the internal storage of the translation table. Access it via the indexing operator.
+
383
+
384 };
+
385
+
386
+
387 //=== Constructors / Destructor =======================
+
388 inline CppStringT() : MyBaseClass() {} // #1
+
389 inline CppStringT(const CppStringT& other) : MyBaseClass(other) {} // #2
+
390 inline CppStringT(const CppStringT& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} // #3
+
391 inline CppStringT(CppStringT&& other) noexcept : MyBaseClass(other) {} // #4
+
392 inline CppStringT(CppStringT&& other, const AllocatorT& alloc) noexcept : MyBaseClass(other, alloc) {} // #5
+
393 inline CppStringT(MyBaseClass::size_type count, CharT ch) : MyBaseClass(count, ch) {} // #6
+
394 inline CppStringT(const CppStringT& other, size_type pos) : MyBaseClass(other, pos) {} // #7
+
395 inline CppStringT(const CppStringT& other, size_type pos, size_type count) noexcept : MyBaseClass(other, pos, count) {} // #8
+
396 inline CppStringT(const CharT* s) // #9
+
397 : MyBaseClass(s ? s : CppStringT().c_str())
+
398 {}
+
399 inline CppStringT(const CharT* s, size_type count) // #10
+
400 : MyBaseClass(s ? s : CppStringT().c_str(), count)
+
401 {}
+
402 inline CppStringT(std::initializer_list<CharT> ilist) : MyBaseClass(ilist) {} // #11
+
403
+
404 inline CppStringT(const CharT ch) : MyBaseClass(1, ch) {} // #19
+
405
+
406 inline CppStringT(const MyBaseClass& other) : MyBaseClass(other) {} // #12
+
407 inline CppStringT(const MyBaseClass& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} // #13
+
408 inline CppStringT(MyBaseClass&& other) : MyBaseClass(other) {} // #14
+
409 inline CppStringT(MyBaseClass&& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} // #15
+
410
+
411 template<class InputIt>
+
412 inline CppStringT(InputIt first, InputIt last) : MyBaseClass(first, last) {} // #16
+
413
+
414 template<class StringViewLike>
+
415 explicit CppStringT(StringViewLike& svl) : MyBaseClass(svl) {} // #17
+
416
+
417 template<class StringViewLike>
+
418 CppStringT(StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} // #18
+
419
+
420 inline ~CppStringT() noexcept = default;
+
421
+
422
+
423 //=== Assignment operators ============================
+
424 CppStringT& operator= (const CppStringT&) noexcept = default;
+
425 CppStringT& operator= (CppStringT&&) noexcept = default;
+
426
+
427
+
428 //=== Exceptions ======================================
+
429 class NotFoundException : public std::logic_error
+
430 {
+
431 public:
+
432 using MyBaseClass = std::logic_error;
+
433
+
434 inline NotFoundException(const std::string& what_arg) : MyBaseClass(what_arg) {}
+
435 inline NotFoundException(const char* what_arg) : MyBaseClass(what_arg) {}
+
436 };
+
437
+
438
+
439 //=== Methods =========================================
+
440
+
441 //--- capitalize() ------------------------------------
+
443 inline CppStringT capitalize() noexcept
+
444 {
+
445 CppStringT res(*this);
+
446 if (!res.empty()) [[likely]] {
+
447 res.lower();
+
448 res[0] = pcs::to_upper(res[0]);
+
449 }
+
450 return res;
+
451 }
+
452
+
453
+
454 //--- center() ----------------------------------------
+
461 [[nodiscard]]
+
462 CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept
+
463 {
+
464 const size_type len{ this->size() };
+
465 if (width <= len) [[unlikely]]
+
466 return CppStringT(*this);
+
467
+
468 const size_type half{ (width - len) / 2 };
+
469 return CppStringT(half, fillch) + *this + CppStringT(width - half - len, fillch);
+
470 }
+
471
+
472
+
473 //--- contains() --------------------------------------
+
478 [[nodiscard]]
+
479 constexpr bool contains(const CppStringT& substr) const noexcept
+
480 {
+
481 if (substr.empty()) [[unlikely]]
+
482 // the empty string is always contained in any string
+
483 return true;
+
484
+
485#if (defined(_HAS_CXX23) && _HAS_CXX23) || (!defined(_HAS_CXX23) && __cplusplus >= 202302L)
+
486 // c++23 and above already defines this method
+
487 return MyBaseClass::contains(substr);
+
488#else
+
489 // up to c++20, we have to implement this method
+
490 const size_type substr_width{ substr.size() };
+
491 const size_type width{ this->size() };
+
492
+
493 if (substr_width > width) [[unlikely]]
+
494 return false;
+
495
+
496 for (size_type index = 0; index <= width - substr_width; ++index) [[likely]] {
+
497 if (substr == this->substr(index, substr_width))
+
498 return true;
+
499 }
+
500
+
501 return false;
+
502#endif
+
503 }
+
504
+
505
+
506 //--- contains_n() ------------------------------------
+
511 [[nodiscard]]
+
512 inline constexpr bool contains_n(const CppStringT& sub, const size_type start, const size_type count = -1) const noexcept
+
513 {
+
514 try {
+
515 return this->substr(start, count).contains(sub);
+
516 }
+
517 catch (...) {
+
518 return false;
+
519 }
+
520 }
+
521
+
522
+
523 //--- count() -----------------------------------------
+
525 [[nodiscard]]
+
526 constexpr size_type count(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept
+
527 {
+
528 size_type n = 0;
+
529 CppStringT tmp{ this->substr(start, std::min(this->size(), end) - start + 1) };
+
530
+
531 size_type start_{ 0 };
+
532 size_type end_{ tmp.size() };
+
533
+
534 while ((start_ = tmp.find(sub, start_, end_)) != CppStringT::npos) {
+
535 start_ += sub.size();
+
536 end_ -= start_;
+
537 tmp = tmp.substr(start_, std::min(tmp.size(), end_) + 1);
+
538 start_ = 0;
+
539 n++;
+
540 }
+
541
+
542 return n;
+
543 }
+
544
+
545
+
546 //--- count_n() ---------------------------------------
+
548 [[nodiscard]]
+
549 inline constexpr size_type count_n(const CppStringT& sub, const size_type start, const size_type length) const noexcept
+
550 {
+
551 return count(sub, start, start + length - 1);
+
552 }
+
553
+
555 [[nodiscard]]
+
556 inline constexpr size_type count_n(const CppStringT& sub, const size_type length) const noexcept
+
557 {
+
558 return count(sub, 0, length - 1);
+
559 }
+
560
+
561
+
562 //--- endswith() --------------------------------------
+
564 [[nodiscard]]
+
565 inline const bool endswith(const CppStringT& suffix, const size_type start, const size_type end) const noexcept
+
566 {
+
567 return this->substr(start, end - start + 1).MyBaseClass::ends_with(suffix);
+
568 }
+
569
+
571 [[nodiscard]]
+
572 inline const bool endswith(const CppStringT& suffix, const size_type end) const noexcept
+
573 {
+
574 return this->substr(0, end).MyBaseClass::ends_with(suffix);
+
575 }
+
576
+
578 [[nodiscard]]
+
579 inline const bool endswith(const CppStringT& suffix) const noexcept
+
580 {
+
581 return static_cast<const bool>(MyBaseClass::ends_with(suffix));
+
582 }
+
583
+
585 [[nodiscard]]
+
586 const bool endswith(const std::initializer_list<CppStringT>& suffixes, const size_type start, const size_type end) const noexcept
+
587 {
+
588 if (start > end) [[unlikely]]
+
589 return false;
+
590
+
591 CppStringT tmp(this->substr(start, end - start + 1));
+
592 for (auto& suffix : suffixes) {
+
593 if (tmp.ends_with(suffix)) [[unlikely]]
+
594 return true;
+
595 }
+
596 return false;
+
597 }
+
598
+
599
+
600 //--- endswith_n() ------------------------------------
+
602 [[nodiscard]]
+
603 inline const bool endswith_n(const CppStringT& suffix, const size_type start, const size_type count) const noexcept
+
604 {
+
605 return endswith(suffix, start, start + count - 1);
+
606 }
+
607
+
609 [[nodiscard]]
+
610 inline const bool endswith_n(const CppStringT& suffix, const size_type count) const noexcept
+
611 {
+
612 return endswith(suffix, 0, count - 1);
+
613 }
+
614
+
616 [[nodiscard]]
+
617 inline const bool endswith_n(const std::initializer_list<CppStringT>& suffixes, const size_type start, const size_type count) const noexcept
+
618 {
+
619 return endswith(suffixes, start, start + count - 1);
+
620 }
+
621
+
622
+
623 //--- expand_tabs() -----------------------------------
+
625 [[nodiscard]]
+
626 CppStringT expand_tabs(const size_type tabsize = 8) const noexcept
+
627 {
+
628 const size_type tabsize_{ tabsize == 0 ? 1 : tabsize };
+
629 CppStringT ret{};
+
630
+
631 std::size_t current_pos{ 0 };
+
632 for (const value_type ch : *this) {
+
633 if (ch == value_type('\t')) [[unlikely]] {
+
634 do {
+
635 ret += value_type(' ');
+
636 current_pos++;
+
637 } while (current_pos % tabsize_ != 0);
+
638 }
+
639 else if (ch == value_type('\n') || ch == value_type('\r')) [[unlikely]] {
+
640 ret += ch;
+
641 current_pos = 0;
+
642 }
+
643 else [[likely]] {
+
644 ret += ch;
+
645 current_pos++;
+
646 }
+
647 }
+
648
+
649 return ret;
+
650 }
+
651
+
652
+
653 //--- find() ------------------------------------------
+
665 [[nodiscard]]
+
666 constexpr size_type find(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept
+
667 {
+
668 const size_type end_{ (end == -1) ? this->size() : end };
+
669
+
670 if (start > end_) [[unlikely]]
+
671 return CppStringT::npos;
+
672 else [[likely]]
+
673 return find_n(sub, start, end_ - start + 1);
+
674 }
+
675
+
676
+
677 //--- find_n() ----------------------------------------
+
690 [[nodiscard]]
+
691 inline constexpr size_type find_n(const CppStringT& sub, const size_type start, const size_type count) const noexcept
+
692 {
+
693 constexpr size_type npos{ CppStringT::npos };
+
694
+
695 try {
+
696 const CppStringT sub_str{ this->substr(start, count) };
+
697 const size_type found_pos{ sub_str.MyBaseClass::find(sub) };
+
698
+
699 return (found_pos == npos) ? npos : found_pos + start;
+
700 }
+
701 catch (...) {
+
702 return npos;
+
703 }
+
704 }
+
705
+
718 [[nodiscard]]
+
719 inline constexpr size_type find_n(const CppStringT& sub, const size_type count) const noexcept
+
720 {
+
721 return find_n(sub, 0, count);
+
722 }
+
723
+
724
+
725 //--- format() ----------------------------------------
+
727 template<typename T, class... ArgsT>
+
728 inline CppStringT& format(
+
729 const std::basic_format_string<T, std::type_identity_t<ArgsT>...> frmt,
+
730 ArgsT&&... args
+
731 )
+
732 {
+
733 return *this;
+
734 }
+
735
+
736 template<class... ArgsT>
+
737 inline CppStringT& format(
+
738 const std::basic_format_string<char , std::type_identity_t<ArgsT>... > frmt,
+
739 ArgsT&&... args
+
740 )
+
741 {
+
742 return *this = std::vformat(frmt.get(), std::make_format_args(args...));
+
743 }
+
744
+
745 template<class... ArgsT>
+
746 inline CppStringT& format(
+
747 const std::basic_format_string<wchar_t, std::type_identity_t<ArgsT>... > frmt,
+
748 ArgsT&&... args
+
749 )
+
750 {
+
751 return *this = std::vformat(frmt.get(), std::make_wformat_args(args...));
+
752 }
+
753
+
754
+
755 //--- index() -----------------------------------------
+
761 [[nodiscard]]
+
762 inline constexpr size_type index(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const
+
763 {
+
764 const size_type ret_value = find(sub, start, end);
+
765 if (ret_value == CppStringT::npos)
+
766 throw NotFoundException("substring not found in string.");
+
767 else
+
768 return ret_value;
+
769 }
+
770
+
771
+
772 //--- index_n() ---------------------------------------
+
778 [[nodiscard]]
+
779 inline constexpr size_type index_n(const CppStringT& sub, const size_type start, const size_type count) const
+
780 {
+
781 return index(sub, start, start + count - 1);
+
782 }
+
783
+
789 [[nodiscard]]
+
790 inline constexpr size_type index_n(const CppStringT& sub, const size_type count) const
+
791 {
+
792 return index(sub, 0, count);
+
793 }
+
794
+
795
+
796 //--- isalnum() ---------------------------------------
+
798 [[nodiscard]]
+
799 inline const bool isalnum() const noexcept
+
800 {
+
801 if (this->empty()) [[unlikely]]
+
802 return false;
+
803 else [[likely]]
+
804 return std::all_of(
+
805 this->cbegin(),
+
806 this->cend(),
+
807 [](const value_type ch) { return pcs::is_alpha(ch) || pcs::is_decimal(ch) || pcs::is_digit(ch) || pcs::is_numeric(ch); }
+
808 );
+
809 }
+
810
+
811
+
812 //--- isalpha() --------------------------------------
+
814 [[nodiscard]]
+
815 inline const bool isalpha() const noexcept
+
816 {
+
817 return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_alpha<value_type>);
+
818 }
+
819
+
820
+
821 //--- isascii() ---------------------------------------
+
823#if defined(isascii) // may be already defined in header file <ctype.h>
+
824#undef isascii
+
825#endif
+
826 [[nodiscard]]
+
827 inline const bool isascii() const noexcept
+
828 {
+
829 return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii<value_type>);
+
830 }
+
831
+
832
+
833 //--- isdecimal() -------------------------------------
+
840 [[nodiscard]]
+
841 inline const bool isdecimal() const noexcept
+
842 {
+
843 return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_decimal<value_type>);
+
844 }
+
845
+
846
+
847 //--- isdigit() ---------------------------------------
+
861 [[nodiscard]]
+
862 inline const bool isdigit() const noexcept
+
863 {
+
864 return isdecimal();
+
865 }
+
866
+
867
+
868 //--- isidentifier() ----------------------------------
+
888 [[nodiscard]]
+
889 inline const bool isidentifier() const noexcept
+
890 {
+
891 return !this->empty() && pcs::is_id_start((*this)[0]) && (this->size() == 1 || std::all_of(this->cbegin() + 1, this->cend(), pcs::is_id_continue<value_type>));
+
892 }
+
893
+
894
+
895 //--- islower() ---------------------------------------
+
897 [[nodiscard]]
+
898 inline const bool islower() const noexcept
+
899 {
+
900 return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_lower<value_type>);
+
901 }
+
902
+
903
+
904 //--- isnumeric() -------------------------------------
+
914 [[nodiscard]]
+
915 inline const bool isnumeric() const noexcept
+
916 {
+
917 return isdecimal();
+
918 }
+
919
+
920
+
921 //--- isprintable() -----------------------------------
+
928 [[nodiscard]]
+
929 inline const bool isprintable() const noexcept
+
930 {
+
931 return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_printable<value_type>);
+
932 }
+
933
+
934
+
935 //--- ispunctuation() ---------------------------------
+
937 [[nodiscard]]
+
938 inline const bool ispunctuation() const noexcept
+
939 {
+
940 return this->size() == 1 && pcs::is_punctuation((*this)[0]);
+
941 }
+
942
+
943
+
944 //--- isspace() ---------------------------------------
+
946 [[nodiscard]]
+
947 inline const bool isspace() const noexcept
+
948 {
+
949 return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_space<value_type>);
+
950 }
+
951
+
952
+
953 //--- istitle() ---------------------------------------
+
963 [[nodiscard]]
+
964 inline const bool istitle() const noexcept
+
965 {
+
966 return !this->empty() && this->title() == *this;
+
967 }
+
968
+
969
+
970 //--- isupper() ---------------------------------------
+
972 [[nodiscard]]
+
973 inline const bool isupper() const noexcept
+
974 {
+
975 return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_upper<value_type>);
+
976 }
+
977
+
978
+
979 //--- is_words_sep() ----------------------------------
+
981 [[nodiscard]]
+
982 inline const bool is_words_sep() const noexcept
+
983 {
+
984 return !this->empty() &&
+
985 std::all_of(
+
986 this->cbegin(),
+
987 this->cend(),
+
988 [](const value_type ch) { return pcs::is_space(ch) || pcs::is_punctuation(ch); }
+
989 );
+
990 }
+
991
+
992
+
993 //--- join() ------------------------------------------
+
998 template<const std::size_t N>
+
999 [[nodiscard]]
+
1000 CppStringT join(const std::array<CppStringT, N>& strs) const noexcept
+
1001 {
+
1002 if (strs.empty()) [[unlikely]]
+
1003 return CppStringT();
+
1004
+
1005 auto str_it = strs.cbegin();
+
1006 CppStringT res{ *str_it++ };
+
1007 while (str_it != strs.cend()) [[likely]]
+
1008 res += *this + *str_it++;
+
1009 return res;
+
1010 }
+
1011
+
1016 [[nodiscard]]
+
1017 CppStringT join(const std::vector<CppStringT>& strs) const noexcept
+
1018 {
+
1019 if (strs.empty()) [[unlikely]]
+
1020 return CppStringT();
+
1021
+
1022 auto str_it = strs.cbegin();
+
1023 CppStringT res{ *str_it++ };
+
1024 while (str_it != strs.cend()) [[likely]]
+
1025 res += *this + *str_it++;
+
1026 return res;
+
1027 }
+
1028
+
1033 template<class... NextCppStringsT>
+
1034 [[nodiscard]]
+
1035 inline CppStringT join(const CppStringT& first, const NextCppStringsT&... others) const noexcept
+
1036 requires (sizeof...(others) > 0)
+
1037 {
+
1038 return first + *this + this->join(others...);
+
1039 }
+
1040
+
1042 [[nodiscard]]
+
1043 inline CppStringT join(const CppStringT& s) const noexcept
+
1044 {
+
1045 return s;
+
1046 }
+
1047
+
1049 [[nodiscard]]
+
1050 inline const CppStringT join() const noexcept
+
1051 {
+
1052 return *this;
+
1053 }
+
1054
+
1055
+
1056 //--- ljust() -----------------------------------------
+
1062 [[nodiscard]]
+
1063 inline CppStringT ljust(const size_type width, const value_type fillch = value_type(' ')) const noexcept
+
1064 {
+
1065 if (this->size() >= width) [[unlikely]]
+
1066 return *this;
+
1067 else [[likely]]
+
1068 return CppStringT(width - this->size(), fillch) + *this;
+
1069 }
+
1070
+
1071
+
1072 //--- lower () -----------------------------------------
+
1078 inline CppStringT& lower() noexcept
+
1079 {
+
1080 std::transform(
+
1081 this->begin(),
+
1082 this->end(),
+
1083 this->begin(),
+
1084 [&](value_type ch) { return this->lower(ch); }
+
1085 );
+
1086 return *this;
+
1087 }
+
1088
+
1094 [[nodiscard]]
+
1095 static inline const value_type lower(const value_type ch) noexcept
+
1096 {
+
1097 return value_type(std::tolower(ch));
+
1098 }
+
1099
+
1100
+
1101 //--- lstrip() ----------------------------------------
+
1109 [[nodiscard]]
+
1110 inline CppStringT lstrip(const CppStringT& removedchars) const noexcept
+
1111 {
+
1112 for (auto it = this->cbegin(); it != this->cend(); ++it) [[likely]]
+
1113 if (std::none_of(removedchars.cbegin(), removedchars.cend(), [it](const value_type ch) { return *it == ch; })) [[likely]]
+
1114 return CppStringT(it, this->cend());
+
1115 return CppStringT();
+
1116 }
+
1117
+
1119 [[nodiscard]]
+
1120 inline CppStringT lstrip() const noexcept
+
1121 {
+
1122 for (auto it = this->cbegin(); it != this->cend(); ++it) [[likely]]
+
1123 if (*it != value_type(' ')) [[unlikely]]
+
1124 return CppStringT(it, this->cend());
+
1125 return CppStringT();
+
1126 }
+
1127
+
1128
+
1129 //--- operator () -------------------------------------
+
1141 template<typename IntT>
+
1142 requires std::is_signed_v<IntT>
+
1143 [[nodiscard]]
+
1144 CppStringT operator() (Slice<IntT> slice) const noexcept
+
1145 {
+
1146 // optimization on 1 by 1 step
+
1147 if (slice.step() == 1) [[likely]] {
+
1148 slice.begin(*this);
+
1149 if (slice.start() < slice.stop()) [[likely]]
+
1150 return this->substr(size_type(slice.start()), size_type(slice.stop() - slice.start() + 1));
+
1151 else [[unlikely]]
+
1152 return CppStringT();
+
1153 }
+
1154
+
1155 CppStringT res{};
+
1156
+
1157 // optimization on reversed 1 by 1 step
+
1158 if (slice.step() == -1) {
+
1159 slice.begin(*this);
+
1160 if (slice.stop() < slice.start()) [[likely]] {
+
1161 res = this->substr(size_type(slice.stop()), size_type(slice.start() - slice.stop() + 1));
+
1162 std::ranges::reverse(res); // notice: may use vectorization if available
+
1163 }
+
1164 return res;
+
1165 }
+
1166
+
1167 // finally, no trivial optimization -- and naive implementation...
+
1168 for (slice.begin(*this); !slice.end(); ++slice)
+
1169 res += (*this)[size_type(*slice)];
+
1170
+
1171 return res;
+
1172 }
+
1173
+
1175 [[nodiscard]]
+
1176 inline CppStringT operator() (const long long start, const long long stop, const long long step = 1) const noexcept
+
1177 {
+
1178 Slice<long long> slice(start, stop, step);
+
1179 return (*this)(slice);
+
1180 }
+
1181
+
1182
+
1183 //--- operator * --------------------------------------
+
1185 [[nodiscard]]
+
1186 CppStringT operator* (std::int64_t count) const noexcept
+
1187 {
+
1188 if (count <= 0) [[unlikely]]
+
1189 return CppStringT();
+
1190
+
1191 CppStringT res(*this);
+
1192 while (--count) [[likely]]
+
1193 res += *this;
+
1194 return res;
+
1195 }
+
1196
+
1197
+
1198 //--- partition() -------------------------------------
+
1204 [[nodiscard]]
+
1205 std::vector<CppStringT> partition(const CppStringT& sep) const noexcept
+
1206 {
+
1207 const size_type sep_index = find(sep);
+
1208 if (sep_index == CppStringT::npos) {
+
1209 const CppStringT empty{};
+
1210 return std::vector<CppStringT>({ *this, empty, empty });
+
1211 }
+
1212 else {
+
1213 const size_type third_index = sep_index + sep.size();
+
1214 const size_type third_size = this->size() - third_index + 1;
+
1215 return std::vector<CppStringT>({ this->substr(0, sep_index), sep, this->substr(third_index, third_size) });
+
1216 }
+
1217 }
+
1218
+
1219
+
1220 //--- removeprefix() ----------------------------------
+
1222 [[nodiscard]]
+
1223 inline CppStringT removeprefix(const CppStringT& prefix) const noexcept
+
1224 {
+
1225 if (this->startswith(prefix)) {
+
1226 const size_type prefix_length = prefix.size();
+
1227 return this->substr(prefix_length, this->size() - prefix_length + 1);
+
1228 }
+
1229 else
+
1230 return *this;
+
1231 }
+
1232
+
1233
+
1234 //--- removesuffix() ----------------------------------
+
1236 [[nodiscard]]
+
1237 inline CppStringT removesuffix(const CppStringT& suffix) const noexcept
+
1238 {
+
1239 if (this->endswith(suffix)) {
+
1240 const size_type suffix_length = suffix.size();
+
1241 return this->substr(0, this->size() - suffix_length);
+
1242 }
+
1243 else
+
1244 return *this;
+
1245 }
+
1246
+
1247
+
1248 //--- replace() ---------------------------------------
+
1250 [[nodiscard]]
+
1251 CppStringT replace(const CppStringT& old, const CppStringT& new_, size_type count = -1) const noexcept
+
1252 {
+
1253 if (old == new_ || old.empty()) [[unlikely]]
+
1254 return *this;
+
1255
+
1256 CppStringT res{};
+
1257 size_type prev_index = 0;
+
1258 size_type current_index = 0;
+
1259 while (count > 0 && (current_index = this->find(old, prev_index)) != CppStringT::npos) {
+
1260 res += this->substr(prev_index, current_index - prev_index) + new_;
+
1261 prev_index = current_index + 1;
+
1262 --count;
+
1263 }
+
1264
+
1265 if (prev_index < this->size()) [[likely]]
+
1266 res += this->substr(prev_index, this->size() - prev_index);
+
1267
+
1268 return res;
+
1269 }
+
1270
+
1271
+
1272 //--- rfind() -----------------------------------------
+
1287 [[nodiscard]]
+
1288 inline constexpr size_type rfind(const CppStringT& sub, const size_type start, const size_type end) const noexcept
+
1289 {
+
1290 if (start > end) [[unlikely]]
+
1291 return CppStringT::npos;
+
1292 else if (sub.empty()) [[unlikely]]
+
1293 return 0;
+
1294 else [[likely]] {
+
1295 const size_type found_pos{ this->substr(start, end - start + 1).rfind(sub) };
+
1296 return (found_pos == CppStringT::npos) ? CppStringT::npos : found_pos + start;
+
1297 }
+
1298 }
+
1299
+
1300
+
1315 [[nodiscard]]
+
1316 inline constexpr size_type rfind(const CppStringT& sub, const size_type start) const noexcept
+
1317 {
+
1318 return rfind(sub, start, this->size() - 1);
+
1319 }
+
1320
+
1321
+
1336 [[nodiscard]]
+
1337 inline constexpr size_type rfind(const CppStringT& sub) const noexcept
+
1338 {
+
1339 return MyBaseClass::rfind(sub);
+
1340 }
+
1341
+
1342
+
1343 //--- rfind_n() ---------------------------------------
+
1352 [[nodiscard]]
+
1353 inline constexpr size_type rfind_n(const CppStringT& sub, const size_type start, const size_type count) const noexcept
+
1354 {
+
1355 return rfind(sub, start, start + count - 1);
+
1356 }
+
1357
+
1366 [[nodiscard]]
+
1367 inline constexpr size_type rfind_n(const CppStringT& sub, const size_type count) const noexcept
+
1368 {
+
1369 if (count == 0) [[unlikely]]
+
1370 return CppStringT::npos;
+
1371 else [[likely]]
+
1372 return rfind(sub, 0, count - 1);
+
1373 }
+
1374
+
1375
+
1376 //--- rindex() ----------------------------------------
+
1382 [[nodiscard]]
+
1383 inline constexpr size_type rindex(const CppStringT& sub, const size_type start, const size_type end) const
+
1384 {
+
1385 const size_type ret_value = rfind(sub, start, end);
+
1386 if (ret_value == CppStringT::npos)
+
1387 throw NotFoundException("substring not found in string");
+
1388 else
+
1389 return ret_value;
+
1390 }
+
1391
+
1397 [[nodiscard]]
+
1398 inline constexpr size_type rindex(const CppStringT& sub, const size_type start) const
+
1399 {
+
1400 return rindex(sub, start, this->size() - 1);
+
1401 }
+
1402
+
1408 [[nodiscard]]
+
1409 inline constexpr size_type rindex(const CppStringT& sub) const
+
1410 {
+
1411 return rindex(sub, 0, this->size() - 1);
+
1412 }
+
1413
+
1414
+
1415 //--- rindex_n() --------------------------------------
+
1421 [[nodiscard]]
+
1422 inline constexpr size_type rindex_n(const CppStringT& sub, const size_type start, const size_type count) const
+
1423 {
+
1424 return rindex(sub, start, start + count - 1);
+
1425 }
+
1426
+
1432 [[nodiscard]]
+
1433 inline constexpr size_type rindex_n(const CppStringT& sub, const size_type count) const
+
1434 {
+
1435 return rindex(sub, 0, count);
+
1436 }
+
1437
+
1438
+
1439 //--- rjust() -----------------------------------------
+
1445 [[nodiscard]]
+
1446 inline CppStringT rjust(const size_type width, const value_type fillch = value_type(' ')) const noexcept
+
1447 {
+
1448 if (this->size() >= width) [[unlikely]]
+
1449 return *this;
+
1450 else [[likely]]
+
1451 return *this + CppStringT(width - this->size(), fillch);
+
1452 }
+
1453
+
1454
+
1455 //--- rpartition() -------------------------------------
+
1461 [[nodiscard]]
+
1462 std::vector<CppStringT> rpartition(const CppStringT& sep) const noexcept
+
1463 {
+
1464 const size_type sep_index = rfind(sep);
+
1465 if (sep_index == CppStringT::npos) {
+
1466 const CppStringT empty{};
+
1467 return std::vector<CppStringT>({ *this, empty, empty });
+
1468 }
+
1469 else {
+
1470 const size_type third_index = sep_index + sep.size();
+
1471 const size_type third_size = this->size() - third_index + 1;
+
1472 return std::vector<CppStringT>({ this->substr(0, sep_index), sep, this->substr(third_index, third_size) });
+
1473 }
+
1474 }
+
1475
+
1476
+
1477 //--- rsplit() ----------------------------------------
+
1483 [[nodiscard]]
+
1484 inline std::vector<CppStringT> rsplit() noexcept
+
1485 {
+
1486 return split();
+
1487 }
+
1488
+
1490 [[nodiscard]]
+
1491 inline std::vector<CppStringT> rsplit(const CppStringT& sep) noexcept
+
1492 {
+
1493 return split(sep);
+
1494 }
+
1495
+
1497 [[nodiscard]]
+
1498 inline std::vector<CppStringT> rsplit(const size_type maxsplit) noexcept
+
1499 {
+
1500 return rsplit(CppStringT(value_type(' ')), maxsplit);
+
1501 }
+
1502
+
1504 [[nodiscard]]
+
1505 std::vector<CppStringT> rsplit(const CppStringT& sep, const size_type maxsplit) noexcept
+
1506 {
+
1507 std::vector<CppStringT> res{};
+
1508
+
1509 if (maxsplit == 0) [[unlikely]] {
+
1510 res.push_back({ *this });
+
1511 }
+
1512 else [[likely]] {
+
1513 const size_type sep_size{ sep.size() };
+
1514 std::vector<size_type> indexes{};
+
1515 CppStringT tmp{ *this };
+
1516 size_type count{ maxsplit };
+
1517 size_type index{ 0 };
+
1518
+
1519 while ((index = tmp.rfind(sep)) != CppStringT::npos && count > 0) {
+
1520 indexes.insert(indexes.begin(), index);
+
1521 if (index == 0)
+
1522 break;
+
1523 tmp = tmp.substr(0, index);
+
1524 count--;
+
1525 }
+
1526
+
1527 if (indexes.size() == 0)
+
1528 res.push_back(*this);
+
1529 else {
+
1530 index = 0;
+
1531 for (const size_type ndx : indexes) {
+
1532 res.push_back(this->substr(index, ndx - index));
+
1533 index = ndx + sep_size;
+
1534 }
+
1535 }
+
1536 res.push_back(this->substr(index, this->size() - index));
+
1537 }
+
1538
+
1539 return res;
+
1540 }
+
1541
+
1542
+
1543 //--- rstrip() ----------------------------------------
+
1551 [[nodiscard]]
+
1552 inline CppStringT rstrip(const CppStringT& removedchars) const noexcept
+
1553 {
+
1554 for (auto it = this->crbegin(); it != this->crend(); ++it)
+
1555 if (std::none_of(removedchars.cbegin(), removedchars.cend(), [it](const value_type ch) { return *it == ch; }))
+
1556 return CppStringT(this->cbegin(), this->cbegin() + this->size() - (it - this->crbegin()));
+
1557 return CppStringT();
+
1558 }
+
1559
+
1561 [[nodiscard]]
+
1562 inline CppStringT rstrip() const noexcept
+
1563 {
+
1564 for (auto it = this->crbegin(); it != this->crend(); ++it)
+
1565 if (*it != value_type(' '))
+
1566 return CppStringT(this->cbegin(), this->cbegin() + this->size() - (it - this->crbegin()));
+
1567 return CppStringT();
+
1568 }
+
1569
+
1570
+
1571 //--- split() -----------------------------------------
+
1577 [[nodiscard]]
+
1578 inline std::vector<CppStringT> split() noexcept
+
1579 {
+
1580 std::vector<CppStringT> res;
+
1581 const CppStringT whitespace(value_type(' '));
+
1582 for (const auto& word : *this | std::views::split(whitespace))
+
1583 res.push_back(CppStringT(word.begin(), word.end()));
+
1584 return res;
+
1585 }
+
1586
+
1596 [[nodiscard]]
+
1597 inline std::vector<CppStringT> split(const CppStringT& sep) noexcept
+
1598 {
+
1599 std::vector<CppStringT> res;
+
1600 for (const auto& word : *this | std::views::split(sep))
+
1601 res.push_back(CppStringT(word.begin(), word.end()));
+
1602 return res;
+
1603 }
+
1604
+
1606 [[nodiscard]]
+
1607 inline std::vector<CppStringT> split(const size_type maxsplit) noexcept
+
1608 {
+
1609 return split(CppStringT(value_type(' ')), maxsplit);
+
1610 }
+
1611
+
1613 [[nodiscard]]
+
1614 std::vector<CppStringT> split(const CppStringT& sep, const size_type maxsplit) noexcept
+
1615 {
+
1616 std::vector<CppStringT> res{};
+
1617
+
1618 if (maxsplit == 0) [[unlikely]] {
+
1619 res.push_back(*this);
+
1620 }
+
1621 else [[likely]] {
+
1622 const size_type sep_size{ sep.size() };
+
1623 std::vector<size_type> indexes{};
+
1624 size_type count{ maxsplit };
+
1625 size_type index{ 0 };
+
1626
+
1627 while ((index = this->find(sep, index)) != CppStringT::npos && count > 0) {
+
1628 indexes.push_back(index);
+
1629 if (index == this->size())
+
1630 break;
+
1631 index += sep_size;
+
1632 count--;
+
1633 }
+
1634
+
1635 if (indexes.size() == 0)
+
1636 res.push_back(*this);
+
1637 else {
+
1638 index = 0;
+
1639 for (const size_type ndx : indexes) {
+
1640 res.push_back(this->substr(index, ndx - index));
+
1641 index = ndx + sep_size;
+
1642 }
+
1643 }
+
1644 res.push_back(this->substr(index, this->size() - index));
+
1645 }
+
1646
+
1647 return res;
+
1648 }
+
1649
+
1650
+
1651 //--- splitlines() ------------------------------------
+
1670 [[nodiscard]]
+
1671 std::vector<CppStringT> splitlines(const bool keep_end = false) const noexcept
+
1672 {
+
1673 std::vector<CppStringT> res{};
+
1674 CppStringT current{};
+
1675 bool prev_cr = false;
+
1676
+
1677 for (const value_type ch : *this) {
+
1678 switch (ch) {
+
1679 case 0x0b: [[unlikely]] // Line Tabulation, \v as well as \x0b and \013
+
1680 case 0x0c: [[unlikely]] // Form Feed, \f as well as \x0c and \014
+
1681 case 0x1c: [[unlikely]] // File Separator, or \034
+
1682 case 0x1d: [[unlikely]] // Group Separator, or \035
+
1683 case 0x1e: [[unlikely]] // Record Separator, or \036
+
1684 //case L'\u0085': [[unlikely]] // Next Line (C1 Control Code), or \0205
+
1685 //case L'\u2028': [[unlikely]] // Line Separator
+
1686 //case L'\u2029': [[unlikely]] // Paragraph Separator
+
1687 if (prev_cr) [[unlikely]] {
+
1688 res.push_back(current);
+
1689 current.clear();
+
1690 }
+
1691 if (keep_end) [[unlikely]]
+
1692 current += ch;
+
1693 res.push_back(current);
+
1694 current.clear();
+
1695 prev_cr = false;
+
1696 break;
+
1697
+
1698 case value_type('\r'): [[unlikely]] // Line Feed
+
1699 if (prev_cr) [[unlikely]] {
+
1700 res.push_back(current);
+
1701 current.clear();
+
1702 }
+
1703 if (keep_end) [[unlikely]]
+
1704 current += ch;
+
1705 prev_cr = true;
+
1706 break;
+
1707
+
1708 case value_type('\n'): [[unlikely]] // Carriage return
+
1709 if (keep_end) [[unlikely]]
+
1710 current += ch;
+
1711 res.push_back(current);
+
1712 current.clear();
+
1713 prev_cr = false;
+
1714 break;
+
1715
+
1716
+
1717 default: [[likely]]
+
1718 if (prev_cr) [[unlikely]] {
+
1719 res.push_back(current);
+
1720 current.clear();
+
1721 prev_cr = false;
+
1722 }
+
1723 current += ch;
+
1724 break;
+
1725 }
+
1726 }
+
1727
+
1728 if (prev_cr) [[unlikely]] {
+
1729 res.push_back(current);
+
1730 }
+
1731
+
1732 return res;
+
1733 }
+
1734
+
1735
+
1736 //--- startswith() ------------------------------------
+
1738 [[nodiscard]]
+
1739 inline const bool startswith(const CppStringT& prefix, const size_type start, const size_type end) const noexcept
+
1740 {
+
1741 return this->substr(start, end - start + 1).MyBaseClass::starts_with(prefix);
+
1742 }
+
1743
+
1745 [[nodiscard]]
+
1746 inline const bool startswith(const CppStringT& prefix, const size_type start) const noexcept
+
1747 {
+
1748 return startswith(prefix, start, this->size() - 1);
+
1749 }
+
1750
+
1752 [[nodiscard]]
+
1753 inline const bool startswith(const CppStringT& prefix) const noexcept
+
1754 {
+
1755 return this->starts_with(prefix);
+
1756 }
+
1757
+
1759 [[nodiscard]]
+
1760 inline const bool startswith(const std::initializer_list<CppStringT>& prefixes, const size_type start, const size_type end) const noexcept
+
1761 {
+
1762 if (start > end)
+
1763 return false;
+
1764
+
1765 CppStringT tmp(this->substr(start, end));
+
1766 for (auto& prefix : prefixes) {
+
1767 if (tmp.starts_with(prefix))
+
1768 return true;
+
1769 }
+
1770 return false;
+
1771 }
+
1772
+
1773
+
1774 //--- startswith_n() ----------------------------------
+
1776 [[nodiscard]]
+
1777 inline const bool startswith_n(const CppStringT& prefix, const size_type start, const size_type count) const noexcept
+
1778 {
+
1779 return this->substr(start, count).MyBaseClass::starts_with(prefix);
+
1780 }
+
1781
+
1783 [[nodiscard]]
+
1784 inline const bool startswith_n(const CppStringT& prefix, const size_type count) const noexcept
+
1785 {
+
1786 return this->substr(0, count).MyBaseClass::starts_with(prefix);
+
1787 }
+
1788
+
1790 [[nodiscard]]
+
1791 inline const bool startswith_n(const std::initializer_list<CppStringT>& prefix, const size_type start, const size_type count) const noexcept
+
1792 {
+
1793 return startswith(prefix, start, count);
+
1794 }
+
1795
+
1796
+
1797 //--- strip() -----------------------------------------
+
1804 [[nodiscard]]
+
1805 inline CppStringT strip(const CppStringT& removedchars) const noexcept
+
1806 {
+
1807 return this->rstrip(removedchars).lstrip(removedchars);
+
1808 }
+
1809
+
1811 [[nodiscard]]
+
1812 inline CppStringT strip() const noexcept
+
1813 {
+
1814 return this->rstrip().lstrip();
+
1815 }
+
1816
+
1817
+
1818 //--- substr() ----------------------------------------
+
1820 [[nodiscard]]
+
1821 inline CppStringT substr(const size_type start, const size_type count = -1) const noexcept
+
1822 {
+
1823 if (start > this->size()) [[unlikely]]
+
1824 return CppStringT();
+
1825
+
1826 const size_type width{ std::min(count, this->size() - start + 1) };
+
1827 return CppStringT(MyBaseClass::substr(start, width));
+
1828 }
+
1829
+
1830
+
1831 //--- swapcase() --------------------------------------
+
1836 [[nodiscard]]
+
1837 inline CppStringT swapcase() const noexcept
+
1838 {
+
1839 CppStringT res;
+
1840 std::ranges::transform(*this, std::back_inserter(res), [](const value_type c) -> value_type { return pcs::swap_case(c); });
+
1841 return res;
+
1842 }
+
1843
+
1844
+
1845 //--- title() -----------------------------------------
+
1847 [[nodiscard]]
+
1848 CppStringT title() const noexcept
+
1849 {
+
1850 const CppStringT whitespace(value_type(' '));
+
1851
+
1852 CppStringT res(*this);
+
1853 std::vector<CppStringT> words = res.split(whitespace);
+
1854
+
1855 for (CppStringT& word : words)
+
1856 word = word.capitalize();
+
1857
+
1858 return whitespace.join(words);
+
1859 }
+
1860
+
1861
+
1862 //--- translate() -------------------------------------
+
1869 [[nodiscard]]
+
1870 CppStringT translate(TransTable& table) noexcept
+
1871 {
+
1872 CppStringT res{};
+
1873 for (auto ch : *this) {
+
1874 try { res += table[ch]; }
+
1875 catch (...) { res += ch; }
+
1876 }
+
1877 return res;
+
1878 }
+
1879
+
1880
+
1881 //--- upper () -----------------------------------------
+
1887 inline CppStringT& upper() noexcept
+
1888 {
+
1889 CppStringT res{};
+
1890 std::ranges::transform(*this, std::back_inserter(res), [&](const value_type ch) -> value_type { return this->upper(ch); });
+
1891 return *this = res;
+
1892 }
+
1893
+
1899 [[nodiscard]]
+
1900 static inline const value_type upper(const value_type ch) noexcept
+
1901 {
+
1902 return value_type(std::toupper(ch));
+
1903 }
+
1904
+
1905
+
1906 //--- zfill() -----------------------------------------
+
1913 [[nodiscard]]
+
1914 inline CppStringT zfill(const size_type width) const noexcept
+
1915 {
+
1916 if (this->size() >= width) [[unlikely]]
+
1917 return *this;
+
1918
+
1919 const size_type padding_width = width - this->size();
+
1920 if ((*this)[0] == '-' || (*this)[0] == '+') [[unlikely]]
+
1921 return (*this)[0] + this->substr(1, this->size() - 1).ljust(width - 1, value_type('0'));
+
1922 else [[likely]]
+
1923 return this->ljust(width, value_type('0'));
+
1924 }
+
1925
+
1926 };
+
1927
+
1928
+
1929 //===== litteral operators ============================
+
1931 inline CppString operator""_cs(const char* str, std::size_t len)
+
1932 {
+
1933 return CppString(CppString::MyBaseClass(str, len));
+
1934 }
+
1935
+
1937 inline CppWString operator""_cs(const wchar_t* str, std::size_t len)
+
1938 {
+
1939 return CppWString(CppWString::MyBaseClass(str, len));
+
1940 }
+
1941
+
1942
+
1943 //===== Slices ========================================
+
1944 //--- slices base -------------------------------------
+
1946 template<typename IntT>
+
1947 requires std::is_signed_v<IntT>
+
1948 class Slice
+
1949 {
+
1950 public:
+
1951 static constexpr IntT DEFAULT{ std::numeric_limits<IntT>::min() };
+
1952
+
1953 //--- Constructors / Destructor -------------------
+
1954 Slice(const IntT start = DEFAULT, const IntT stop = DEFAULT, const IntT step = DEFAULT) noexcept
+
1955 : _start(start)
+
1956 , _stop(stop)
+
1957 , _step(step)
+
1958 {}
+
1959
+
1960 virtual ~Slice() noexcept = default;
+
1961
+
1962
+
1963 //--- iterating -----------------------------------
+
1964 template<typename CharT = char>
+
1965#if (defined(_HAS_CXX20) && _HAS_CXX20)
+
1966 requires std::is_same_v<CharT, char> || std::is_same_v<CharT, char8_t> || std::is_same_v<CharT, char16_t> || std::is_same_v<CharT, char32_t> || std::is_same_v<CharT, wchar_t>
+
1967#else
+
1968 requires std::is_same_v<CharT, char> || std::is_same_v<CharT, char16_t> || std::is_same_v<CharT, char32_t> || std::is_same_v<CharT, wchar_t>
+
1969#endif
+
1970 inline const IntT begin(const CppStringT<CharT>& str) noexcept
+
1971 {
+
1972 return _prepare_iterating(IntT(str.size()));
+
1973 }
+
1974
+
1975 [[nodiscard]]
+
1976 inline const bool end() const noexcept
+
1977 {
+
1978 return _step == 0 ? true : _step > 0 ? _index >= _stop : _index <= _stop;
+
1979 }
+
1980
+
1981 inline Slice operator++() noexcept
+
1982 {
+
1983 _index += _step;
+
1984 return *this;
+
1985 }
+
1986
+
1987 inline Slice operator++(int) noexcept
+
1988 {
+
1989 _index += _step;
+
1990 return *this;
+
1991 }
+
1992
+
1993 [[nodiscard]]
+
1994 inline const IntT operator*() noexcept
+
1995 {
+
1996 return _index;
+
1997 }
+
1998
+
1999 //--- properties ----------------------------------
+
2000 inline IntT start() { return _start; }
+
2001 inline IntT stop() { return _stop; }
+
2002 inline IntT step() { return _step; }
+
2003
+
2004
+
2005 private:
+
2006 IntT _start{ 0 };
+
2007 IntT _stop{ DEFAULT };
+
2008 IntT _step{ 1 };
+
2009
+
2010 IntT _index{ 0 };
+
2011
+
2012 [[nodiscard]]
+
2013 const IntT _prepare_iterating(const IntT str_size) noexcept
+
2014 {
+
2015 if (_start == DEFAULT) {
+
2016 if (_step < 0 && _step != DEFAULT) [[unlikely]]
+
2017 _start = str_size - 1;
+
2018 else [[likely]]
+
2019 _start = 0;
+
2020 }
+
2021 else if (_start < 0) {
+
2022 _start += str_size;
+
2023 if (_start < 0) [[unlikely]]
+
2024 _start = 0;
+
2025 }
+
2026 else if (_start >= str_size) {
+
2027 if (_step < 0 && _step != DEFAULT)
+
2028 _start = str_size - 1;
+
2029 }
+
2030
+
2031 if (_stop == DEFAULT) {
+
2032 if (_step < 0 && _step != DEFAULT) [[unlikely]]
+
2033 _stop = 0;
+
2034 else
+
2035 _stop = str_size;
+
2036 }
+
2037 else if (_stop < 0) {
+
2038 _stop += str_size;
+
2039 if (_stop < 0)
+
2040 _stop = 0;
+
2041 }
+
2042 else if (_stop > str_size)
+
2043 _stop = str_size;
+
2044
+
2045 if (_step == DEFAULT) [[likely]]
+
2046 _step = 1;
+
2047 if (_step < 0) [[unlikely]] {
+
2048 if (_start <= _stop)
+
2049 _step = 0; // will force end() to true
+
2050 }
+
2051 else [[unlikely]] {
+
2052 if (_start >= _stop)
+
2053 _step = 0; // will force end() to true
+
2054 }
+
2055
+
2056 return _index = _start;
+
2057 }
+
2058 };
+
2059
+
2060
+
2062 template<typename IntT>
+
2063 requires std::is_signed_v<IntT>
+
2064 struct StartSlice : public Slice<IntT>
+
2065 {
+
2066 using MyBaseClass = Slice<IntT>;
+
2067
+
2068 //--- Constructors / Destructor -------------------
+
2069 inline StartSlice(const IntT start = MyBaseClass::DEFAULT) noexcept
+
2070 : MyBaseClass(start, MyBaseClass::DEFAULT, 1)
+
2071 {}
+
2072
+
2073 virtual ~StartSlice() noexcept = default;
+
2074 };
+
2075
+
2076
+
2078 template<typename IntT>
+
2079 requires std::is_signed_v<IntT>
+
2080 struct StopSlice : public Slice<IntT>
+
2081 {
+
2082 using MyBaseClass = Slice<IntT>;
+
2083
+
2084 //--- Constructors / Destructor -------------------
+
2085 inline StopSlice(const IntT stop = MyBaseClass::DEFAULT) noexcept
+
2086 : MyBaseClass(MyBaseClass::DEFAULT, stop, 1)
+
2087 {}
+
2088
+
2089 virtual ~StopSlice() noexcept = default;
+
2090 };
+
2091
+
2092
+
2094 template<typename IntT>
+
2095 requires std::is_signed_v<IntT>
+
2096 struct StepSlice : public Slice<IntT>
+
2097 {
+
2098 using MyBaseClass = Slice<IntT>;
+
2099
+
2100 //--- Constructors / Destructor -------------------
+
2101 inline StepSlice(const IntT step = MyBaseClass::DEFAULT) noexcept
+
2102 : MyBaseClass(MyBaseClass::DEFAULT, MyBaseClass::DEFAULT, step)
+
2103 {}
+
2104
+
2105 virtual ~StepSlice() noexcept = default;
+
2106 };
+
2107
+
2108
+
2110 template<typename IntT>
+
2111 requires std::is_signed_v<IntT>
+
2112 struct StartStopSlice : public Slice<IntT>
+
2113 {
+
2114 using MyBaseClass = Slice<IntT>;
+
2115
+
2116 //--- Constructors / Destructor -------------------
+
2117 inline StartStopSlice(const IntT start = MyBaseClass::DEFAULT, const IntT stop = MyBaseClass::DEFAULT) noexcept
+
2118 : MyBaseClass(start, stop, 1)
+
2119 {}
+
2120
+
2121 virtual ~StartStopSlice() noexcept = default;
+
2122 };
+
2123
+
2124
+
2126 template<typename IntT>
+
2127 requires std::is_signed_v<IntT>
+
2128 struct StartStepSlice : public Slice<IntT>
+
2129 {
+
2130 using MyBaseClass = Slice<IntT>;
+
2131
+
2132 //--- Constructors / Destructor -------------------
+
2133 inline StartStepSlice(const IntT start = MyBaseClass::DEFAULT, const IntT step = MyBaseClass::DEFAULT) noexcept
+
2134 : MyBaseClass(start, MyBaseClass::DEFAULT, step)
+
2135 {}
+
2136
+
2137 virtual ~StartStepSlice() noexcept = default;
+
2138
+
2139 };
+
2140
+
2141
+
2143 template<typename IntT>
+
2144 requires std::is_signed_v<IntT>
+
2145 struct StopStepSlice : public Slice<IntT>
+
2146 {
+
2147 using MyBaseClass = Slice<IntT>;
+
2148
+
2149 //--- Constructors / Destructor -------------------
+
2150 inline StopStepSlice(const IntT stop = MyBaseClass::DEFAULT, const IntT step = MyBaseClass::DEFAULT) noexcept
+
2151 : MyBaseClass(MyBaseClass::DEFAULT, stop, step)
+
2152 {}
+
2153
+
2154 virtual ~StopStepSlice() noexcept = default;
+
2155 };
+
2156
+
2157
+
2158 //===== templated chars classes ===========================
+
2159 //--- is_alpha() ------------------------------------------
+
2161 template<class CharT>
+
2162 [[nodiscard]]
+
2163 inline const bool is_alpha(const CharT ch) noexcept
+
2164 {
+
2165 return false;
+
2166 }
+
2167
+
2169 template<>
+
2170 [[nodiscard]]
+
2171 inline const bool is_alpha<char>(const char ch) noexcept
+
2172 {
+
2173 return static_cast<const bool>(std::isalpha(static_cast<unsigned char>(ch)));
+
2174 }
+
2175
+
2177 template<>
+
2178 [[nodiscard]]
+
2179 inline const bool is_alpha<wchar_t>(const wchar_t ch) noexcept
+
2180 {
+
2181 return static_cast<const bool>(std::iswalpha(ch));
+
2182 }
+
2183
+
2184
+
2185 //--- is_ascii() ------------------------------------------
+
2187 template<class CharT>
+
2188 [[nodiscard]]
+
2189 inline const bool is_ascii(const CharT ch) noexcept
+
2190 {
+
2191 return CharT(0x00) <= ch && ch <= CharT(0x7f);
+
2192 }
+
2193
+
2194
+
2195 //--- is_decimal() ----------------------------------------
+
2197 template<class CharT>
+
2198 [[nodiscard]]
+
2199 inline const bool is_decimal(const CharT ch) noexcept
+
2200 {
+
2201 return false;
+
2202 }
+
2203
+
2205 template<>
+
2206 [[nodiscard]]
+
2207 inline const bool is_decimal<char>(const char ch) noexcept
+
2208 {
+
2209 return static_cast<const bool>(std::isdigit(static_cast<unsigned char>(ch)));
+
2210 }
+
2211
+
2213 template<>
+
2214 [[nodiscard]]
+
2215 inline const bool is_decimal<wchar_t>(const wchar_t ch) noexcept
+
2216 {
+
2217 return (const bool)std::iswdigit(ch);
+
2218 }
+
2219
+
2220
+
2221 //--- is_digit() ------------------------------------------
+
2223 template<class CharT>
+
2224 [[nodiscard]]
+
2225 inline const bool is_digit(const CharT ch) noexcept
+
2226 {
+
2227 return pcs::is_decimal(ch);
+
2228 }
+
2229
+
2231 template<>
+
2232 [[nodiscard]]
+
2233 inline const bool is_digit<char>(const char ch) noexcept
+
2234 {
+
2235 return pcs::is_decimal(ch);
+
2236 }
+
2237
+
2239 template<>
+
2240 [[nodiscard]]
+
2241 inline const bool is_digit<wchar_t>(const wchar_t ch) noexcept
+
2242 {
+
2243 return pcs::is_decimal(ch);
+
2244 }
+
2245
+
2246
+
2247 //--- is_id_continue() ------------------------------------
+
2249 template<class CharT>
+
2250 [[nodiscard]]
+
2251 inline const bool is_id_continue(const CharT ch) noexcept
+
2252 {
+
2253 return pcs::is_id_start(ch) || pcs::is_decimal(ch);
+
2254 }
+
2255
+
2256
+
2257 //--- is_id_start() ---------------------------------------
+
2259 template<class CharT>
+
2260 [[nodiscard]]
+
2261 inline const bool is_id_start(const CharT ch) noexcept
+
2262 {
+
2263 return pcs::is_alpha(ch) || ch == CharT('_');
+
2264 }
+
2265
+
2266
+
2267 //--- is_lower() ------------------------------------------
+
2269 template<class CharT>
+
2270 [[nodiscard]]
+
2271 inline const bool is_lower(const CharT ch) noexcept
+
2272 {
+
2273 return false;
+
2274 }
+
2275
+
2277 template<>
+
2278 [[nodiscard]]
+
2279 inline const bool is_lower<char>(const char ch) noexcept
+
2280 {
+
2281 return std::islower(static_cast<unsigned char>(ch));
+
2282 }
+
2283
+
2285 template<>
+
2286 [[nodiscard]]
+
2287 inline const bool is_lower<wchar_t>(const wchar_t ch) noexcept
+
2288 {
+
2289 return std::iswlower(ch);
+
2290 }
+
2291
+
2292
+
2293 //--- is_numeric() ----------------------------------------
+
2295 template<class CharT>
+
2296 [[nodiscard]]
+
2297 inline const bool is_numeric(const CharT ch) noexcept
+
2298 {
+
2299 return pcs::is_decimal(ch);
+
2300 }
+
2301
+
2303 template<>
+
2304 [[nodiscard]]
+
2305 inline const bool is_numeric<char>(const char ch) noexcept
+
2306 {
+
2307 return pcs::is_decimal(ch);
+
2308 }
+
2309
+
2311 template<>
+
2312 [[nodiscard]]
+
2313 inline const bool is_numeric<wchar_t>(const wchar_t ch) noexcept
+
2314 {
+
2315 return pcs::is_decimal(ch);
+
2316 }
+
2317
+
2318
+
2319 //--- is_printable() --------------------------------------
+
2321 template<class CharT>
+
2322 [[nodiscard]]
+
2323 inline const bool is_printable(const CharT ch) noexcept
+
2324 {
+
2325 return false;
+
2326 }
+
2327
+
2329 template<>
+
2330 [[nodiscard]]
+
2331 inline const bool is_printable<char>(const char ch) noexcept
+
2332 {
+
2333 return static_cast<const bool>(std::isprint(static_cast<unsigned char>(ch)));
+
2334 }
+
2335
+
2337 template<>
+
2338 [[nodiscard]]
+
2339 inline const bool is_printable<wchar_t>(const wchar_t ch) noexcept
+
2340 {
+
2341 return static_cast<const bool>(std::iswprint(ch));
+
2342 }
+
2343
+
2344
+
2345 //--- is_punctuation() ------------------------------------
+
2347 template<class CharT>
+
2348 [[nodiscard]]
+
2349 inline const bool is_punctuation(const CharT ch) noexcept
+
2350 {
+
2351 return false;
+
2352 }
+
2353
+
2355 template<>
+
2356 [[nodiscard]]
+
2357 inline const bool is_punctuation<char>(const char ch) noexcept
+
2358 {
+
2359 return static_cast<const bool>(std::ispunct(static_cast<unsigned char>(ch)));
+
2360 }
+
2361
+
2363 template<>
+
2364 [[nodiscard]]
+
2365 inline const bool is_punctuation<wchar_t>(const wchar_t ch) noexcept
+
2366 {
+
2367 return static_cast<const bool>(std::iswpunct(ch));
+
2368 }
+
2369
+
2370
+
2371 //--- is_space() ------------------------------------------
+
2373 template<class CharT>
+
2374 [[nodiscard]]
+
2375 inline const bool is_space(const CharT ch) noexcept
+
2376 {
+
2377 return false;
+
2378 }
+
2379
+
2381 template<>
+
2382 [[nodiscard]]
+
2383 inline const bool is_space<char>(const char ch) noexcept
+
2384 {
+
2385 return static_cast<const bool>(std::isspace(static_cast<unsigned char>(ch)));
+
2386 }
+
2387
+
2389 template<>
+
2390 [[nodiscard]]
+
2391 inline const bool is_space<wchar_t>(const wchar_t ch) noexcept
+
2392 {
+
2393 return static_cast<const bool>(std::iswspace(ch));
+
2394 }
+
2395
+
2396
+
2397 //--- is_upper() ------------------------------------------
+
2399 template<class CharT>
+
2400 [[nodiscard]]
+
2401 inline const bool is_upper(const CharT ch) noexcept
+
2402 {
+
2403 return false;
+
2404 }
+
2405
+
2407 template<>
+
2408 [[nodiscard]]
+
2409 inline const bool is_upper<char>(const char ch) noexcept
+
2410 {
+
2411 return static_cast<const bool>(std::isupper(static_cast<unsigned char>(ch)));
+
2412 }
+
2413
+
2415 template<>
+
2416 [[nodiscard]]
+
2417 inline const bool is_upper<wchar_t>(const wchar_t ch) noexcept
+
2418 {
+
2419 return static_cast<const bool>(std::iswupper(ch));
+
2420 }
+
2421
+
2422
+
2423 //--- swap_case() -----------------------------------------
+
2425 template<class CharT>
+
2426 [[nodiscard]]
+
2427 inline const CharT swap_case(const CharT ch) noexcept
+
2428 {
+
2429 if (pcs::is_lower(ch))
+
2430 return pcs::to_upper(ch);
+
2431 else if (pcs::is_upper(ch))
+
2432 return pcs::to_lower(ch);
+
2433 else
+
2434 return ch;
+
2435 }
+
2436
+
2437
+
2438 //--- to_lower() ------------------------------------------
+
2440 template<class CharT>
+
2441 [[nodiscard]]
+
2442 inline const CharT to_lower(const CharT ch) noexcept
+
2443 {
+
2444 return ch;
+
2445 }
+
2446
+
2448 template<>
+
2449 [[nodiscard]]
+
2450 inline const char to_lower<char>(const char ch) noexcept
+
2451 {
+
2452 return std::tolower(static_cast<unsigned char>(ch));
+
2453 }
+
2454
+
2456 template<>
+
2457 [[nodiscard]]
+
2458 inline const wchar_t to_lower<wchar_t>(const wchar_t ch) noexcept
+
2459 {
+
2460 return std::towlower(ch);
+
2461 }
+
2462
+
2463
+
2464 //--- to_upper() ------------------------------------------
+
2466 template<class CharT>
+
2467 [[nodiscard]]
+
2468 inline const CharT to_upper(const CharT ch) noexcept
+
2469 {
+
2470 return ch;
+
2471 }
+
2472
+
2474 template<>
+
2475 [[nodiscard]]
+
2476 inline const char to_upper<char>(const char ch) noexcept
+
2477 {
+
2478 return std::toupper(static_cast<unsigned char>(ch));
+
2479 }
+
2480
+
2482 template<>
+
2483 [[nodiscard]]
+
2484 inline const wchar_t to_upper<wchar_t>(const wchar_t ch) noexcept
+
2485 {
+
2486 return std::towupper(ch);
+
2487 }
+
2488
+
2489#if defined(_MSC_VER)
+
2490# pragma warning(pop) // to avoid boring warnings with litteral operators definitions
+
2491#endif
+
2492
+
2493} // end of namespace pcs // (pythonic c++ strings)
+
TransTable(Key1It first_key, Key1It last_key, ValueIt first_value, ValueIt last_value, Key2It first_not_translated, Key2It last_not_translated)
Creates a TransTable from three containers iterators (#9).
Definition cppstrings.h:317
+
TransTable(const std::map< key_type, value_type > trans_table)
Creates a TransTable from a standard map (#1).
Definition cppstrings.h:197
+
TransTable(const StringViewLike &keys, const StringViewLike &values)
Creates a TransTable from two string views (#10).
Definition cppstrings.h:338
+
TransTable(KeyIt first_key, KeyIt last_key, ValueIt first_value, ValueIt last_value)
Creates a TransTable from two containers iterators (#8).
Definition cppstrings.h:300
+
TransTable(const CppStringT &keys, const CppStringT &values)
Creates a TransTable from two strings (#2).
Definition cppstrings.h:207
+
TransTable(const CharT *keys, const CharT *values, const CharT *not_translated)
Creates a TransTable from three pointers to null-terminated lists of characters (#7).
Definition cppstrings.h:285
+
TransTable() noexcept=default
Default empty constructor.
+
value_type operator[](const key_type ch) noexcept
Indexing operator.
Definition cppstrings.h:365
+
TransTable(const CharT *keys, const CharT *values)
Creates a TransTable from two pointers to null-terminated lists of characters (#6).
Definition cppstrings.h:271
+
TransTable(const CppStringT &keys, const CppStringT &values, const CppStringT &not_translated)
Creates a TransTable from three strings (#3).
Definition cppstrings.h:223
+
TransTable(const CppStringT &keys, const std::initializer_list< CppStringT > &values)
Creates a TransTable from a string and an initalization list (#4).
Definition cppstrings.h:239
+
std::map< typename key_type, typename value_type > & get_table() noexcept
< for tests purposes
Definition cppstrings.h:376
+
TransTable(const CppStringT &keys, const std::initializer_list< CppStringT > values, const CppStringT &not_translated)
Creates a TransTable from a string, an initalization list and a string (#5).
Definition cppstrings.h:255
+
This is the templated base class for all CppString classes.
Definition cppstrings.h:166
+
CppStringT strip(const CppStringT &removedchars) const noexcept
Returns a copy of the string with the leading and trailing characters removed.
Definition cppstrings.h:1805
+
constexpr bool contains_n(const CppStringT &sub, const size_type start, const size_type count=-1) const noexcept
Returns true if the passed string is found within the slice str[start:start+count-1],...
Definition cppstrings.h:512
+
std::vector< CppStringT > rsplit(const CppStringT &sep) noexcept
Returns a vector of the words in the whole string, using sep as the delimiter string.
Definition cppstrings.h:1491
+
CppStringT removeprefix(const CppStringT &prefix) const noexcept
If the string starts with the prefix string, returns a new string with the prefix removed....
Definition cppstrings.h:1223
+
constexpr bool contains(const CppStringT &substr) const noexcept
Returns true if this string contains the passed string, or false otherwise.
Definition cppstrings.h:479
+
CppStringT operator*(std::int64_t count) const noexcept
Generates a new string with count times the content of this string.
Definition cppstrings.h:1186
+
const bool isdecimal() const noexcept
Returns true if all characters in the string are decimal characters and there is at least one charact...
Definition cppstrings.h:841
+
std::vector< CppStringT > splitlines(const bool keep_end=false) const noexcept
Return a list of the lines in the string, breaking at line boundaries.
Definition cppstrings.h:1671
+
CppStringT strip() const noexcept
Returns a copy of the string with the leading and trailing whitespaces removed.
Definition cppstrings.h:1812
+
CppStringT title() const noexcept
Returns a titlecased copy of the string where words start with an uppercase character and the remaini...
Definition cppstrings.h:1848
+
constexpr size_type index_n(const CppStringT &sub, const size_type count) const
Like find_n(sub, count), but raises NotFoundException when the substring is not found.
Definition cppstrings.h:790
+
CppStringT & format(const std::basic_format_string< char, std::type_identity_t< ArgsT >... > frmt, ArgsT &&... args)
Definition cppstrings.h:737
+
CppStringT operator()(Slice< IntT > slice) const noexcept
Generates a new string according to the specified slice.
Definition cppstrings.h:1144
+
const bool isdigit() const noexcept
Returns true if all characters in the string are digits and there is at least one character,...
Definition cppstrings.h:862
+
constexpr size_type find(const CppStringT &sub, const size_type start=0, const size_type end=-1) const noexcept
Returns the lowest index in the string where substring sub is found within the slice str[start:end],...
Definition cppstrings.h:666
+
constexpr size_type index(const CppStringT &sub, const size_type start=0, const size_type end=-1) const
Definition cppstrings.h:762
+
const bool ispunctuation() const noexcept
Returns true if the string contains only one character and if this character belongs to the ASCII pun...
Definition cppstrings.h:938
+
CppStringT translate(TransTable &table) noexcept
Returns a copy of the string in which each character has been mapped through the given translation ta...
Definition cppstrings.h:1870
+
constexpr size_type rindex(const CppStringT &sub, const size_type start) const
Like rfind(sub, start), but raises NotFoundException when the substring is not found.
Definition cppstrings.h:1398
+
CppStringT expand_tabs(const size_type tabsize=8) const noexcept
Returns a copy of the string where all tab characters are replaced by one or more spaces,...
Definition cppstrings.h:626
+
CppStringT join(const CppStringT &s) const noexcept
Single parameter signature. Returns a copy of this parameter.
Definition cppstrings.h:1043
+
const bool startswith(const std::initializer_list< CppStringT > &prefixes, const size_type start, const size_type end) const noexcept
Returns true if the string starts with any of the specified prefixes, otherwise returns false....
Definition cppstrings.h:1760
+
std::vector< CppStringT > rsplit(const size_type maxsplit) noexcept
Returns a vector of the words in the string, as seperated with whitespace strings....
Definition cppstrings.h:1498
+
const bool startswith_n(const CppStringT &prefix, const size_type start, const size_type count) const noexcept
Returns true if the string starts with the specified suffix, otherwise returns false....
Definition cppstrings.h:1777
+
const bool endswith(const CppStringT &suffix) const noexcept
Returns true if the string ends with the specified suffix, otherwise returns false....
Definition cppstrings.h:579
+
const bool endswith(const CppStringT &suffix, const size_type start, const size_type end) const noexcept
Returns true if the string ends with the specified suffix, otherwise returns false....
Definition cppstrings.h:565
+
const bool isalpha() const noexcept
Returns true if all characters in the string are alphabetic and there is at least one character,...
Definition cppstrings.h:815
+
CppStringT capitalize() noexcept
Returns a copy of the string with its first character capitalized and the rest lowercased.
Definition cppstrings.h:443
+
const bool endswith_n(const std::initializer_list< CppStringT > &suffixes, const size_type start, const size_type count) const noexcept
Returns true if the string ends with any of the specified suffixes, otherwise returns false....
Definition cppstrings.h:617
+
constexpr size_type rfind_n(const CppStringT &sub, const size_type start, const size_type count) const noexcept
Returns the highest index in the string where substring sub is found within the slice str[start:start...
Definition cppstrings.h:1353
+
CppStringT join(const CppStringT &first, const NextCppStringsT &... others) const noexcept
Returns a string which is the concatenation of the strings in the parameters list.
Definition cppstrings.h:1035
+
constexpr size_type rindex(const CppStringT &sub) const
Like rfind(sub), but raises NotFoundException when the substring is not found.
Definition cppstrings.h:1409
+
std::vector< CppStringT > split(const CppStringT &sep, const size_type maxsplit) noexcept
Returns a vector of the words in the string, using sep as the delimiter string. At most maxsplit spli...
Definition cppstrings.h:1614
+
const bool isnumeric() const noexcept
Returns true if all characters in the string are numeric characters, and there is at least one charac...
Definition cppstrings.h:915
+
constexpr size_type count_n(const CppStringT &sub, const size_type length) const noexcept
Returns the number of non-overlapping occurrences of substring sub in the range [0,...
Definition cppstrings.h:556
+
const bool startswith(const CppStringT &prefix, const size_type start, const size_type end) const noexcept
Returns true if the string starts with the specified prefix, otherwise returns false....
Definition cppstrings.h:1739
+
CppStringT & format(const std::basic_format_string< T, std::type_identity_t< ArgsT >... > frmt, ArgsT &&... args)
Formats this string according to c++20 std::format() specification. Returns this string.
Definition cppstrings.h:728
+
std::vector< CppStringT > rpartition(const CppStringT &sep) const noexcept
Splits the string at the last occurrence of sep, and returns a 3-items vector containing the part bef...
Definition cppstrings.h:1462
+
const bool endswith_n(const CppStringT &suffix, const size_type count) const noexcept
Returns true if the string ends with the specified suffix, otherwise returns false....
Definition cppstrings.h:610
+
CppStringT rjust(const size_type width, const value_type fillch=value_type(' ')) const noexcept
Returns the string right justified in a string of length width.
Definition cppstrings.h:1446
+
const bool isprintable() const noexcept
Returns true if all characters in the string are printable or if the string is empty,...
Definition cppstrings.h:929
+
constexpr size_type rindex(const CppStringT &sub, const size_type start, const size_type end) const
Like rfind(sub, start, end), but raises NotFoundException when the substring is not found.
Definition cppstrings.h:1383
+
CppStringT & upper() noexcept
In-place replaces all characters of the string with their uppercase conversion. Returns a reference t...
Definition cppstrings.h:1887
+
CppStringT swapcase() const noexcept
Returns a copy of the string with uppercase characters converted to lowercase and vice versa.
Definition cppstrings.h:1837
+
constexpr size_type find_n(const CppStringT &sub, const size_type count) const noexcept
Returns the lowest index in the string where substring sub is found within the slice str[0:count-1],...
Definition cppstrings.h:719
+
static const value_type lower(const value_type ch) noexcept
Returns lowercase conversion of the character.
Definition cppstrings.h:1095
+
const bool endswith(const CppStringT &suffix, const size_type end) const noexcept
Returns true if the string ends with the specified suffix, otherwise returns false....
Definition cppstrings.h:572
+
const bool isascii() const noexcept
Returns true if the string is empty or all characters in the string are ASCII, or false otherwise.
Definition cppstrings.h:827
+
const bool is_words_sep() const noexcept
Returns true if there are only whitespace and punctuation characters in the string and there is at le...
Definition cppstrings.h:982
+
constexpr size_type count_n(const CppStringT &sub, const size_type start, const size_type length) const noexcept
Returns the number of non-overlapping occurrences of substring sub in the range [start,...
Definition cppstrings.h:549
+
constexpr size_type rfind_n(const CppStringT &sub, const size_type count) const noexcept
Returns the highest index in the string where substring sub is found within the slice str[0:count-1],...
Definition cppstrings.h:1367
+
constexpr size_type count(const CppStringT &sub, const size_type start=0, const size_type end=-1) const noexcept
Returns the number of non-overlapping occurrences of substring sub in the range [start,...
Definition cppstrings.h:526
+
std::vector< CppStringT > split() noexcept
Returns a vector of the words in the whole string, as seperated with whitespace strings.
Definition cppstrings.h:1578
+
const bool endswith_n(const CppStringT &suffix, const size_type start, const size_type count) const noexcept
Returns true if the string ends with the specified suffix, otherwise returns false....
Definition cppstrings.h:603
+
std::vector< CppStringT > rsplit() noexcept
Returns a vector of the words in the whole string, as seperated with whitespace strings.
Definition cppstrings.h:1484
+
CppStringT rstrip() const noexcept
Returns a copy of the string with trailing whitespaces removed.
Definition cppstrings.h:1562
+
const bool endswith(const std::initializer_list< CppStringT > &suffixes, const size_type start, const size_type end) const noexcept
Returns true if the string ends with any of the specified suffixes, otherwise returns false....
Definition cppstrings.h:586
+
CppStringT rstrip(const CppStringT &removedchars) const noexcept
Returns a copy of the string with trailing characters removed.
Definition cppstrings.h:1552
+
std::vector< CppStringT > split(const size_type maxsplit) noexcept
Returns a vector of the words in the string, as seperated with whitespace strings....
Definition cppstrings.h:1607
+
const bool isalnum() const noexcept
Returns true if all characters in the string are alphanumeric and there is at least one character,...
Definition cppstrings.h:799
+
const bool isidentifier() const noexcept
Returns true if the string is not empty and is a valid identifier according to the language definitio...
Definition cppstrings.h:889
+
CppStringT & format(const std::basic_format_string< wchar_t, std::type_identity_t< ArgsT >... > frmt, ArgsT &&... args)
Definition cppstrings.h:746
+
const bool isspace() const noexcept
Returns true if there are only whitespace characters in the string and there is at least one characte...
Definition cppstrings.h:947
+
CppStringT substr(const size_type start, const size_type count=-1) const noexcept
Definition cppstrings.h:1821
+
CppStringT join(const std::vector< CppStringT > &strs) const noexcept
Returns a string which is the concatenation of the strings in the vector parameter.
Definition cppstrings.h:1017
+
constexpr size_type rfind(const CppStringT &sub, const size_type start) const noexcept
Returns the highest index in the string where substring sub is found starting at start position in st...
Definition cppstrings.h:1316
+
const CppStringT join() const noexcept
Empty parameters list signature. Returns a copy of current string.
Definition cppstrings.h:1050
+
std::vector< CppStringT > rsplit(const CppStringT &sep, const size_type maxsplit) noexcept
Returns a vector of the words in the string, using sep as the delimiter string. At most maxsplit spli...
Definition cppstrings.h:1505
+
const bool startswith_n(const std::initializer_list< CppStringT > &prefix, const size_type start, const size_type count) const noexcept
Returns true if the string starts with any of the specified suffixes, otherwise returns false....
Definition cppstrings.h:1791
+
constexpr size_type rfind(const CppStringT &sub) const noexcept
Returns the highest index in the string where C-substring sub is found in the whole string,...
Definition cppstrings.h:1337
+
CppStringT lstrip() const noexcept
Returns a copy of the string with leading whitespaces removed.
Definition cppstrings.h:1120
+
CppStringT join(const std::array< CppStringT, N > &strs) const noexcept
Returns a string which is the concatenation of the strings in the array parameter.
Definition cppstrings.h:1000
+
constexpr size_type rindex_n(const CppStringT &sub, const size_type count) const
Like rfind_n(sub, count), but raises NotFoundException when the substring is not found.
Definition cppstrings.h:1433
+
constexpr size_type find_n(const CppStringT &sub, const size_type start, const size_type count) const noexcept
Returns the lowest index in the string where substring sub is found within the slice str[start:start+...
Definition cppstrings.h:691
+
std::vector< CppStringT > partition(const CppStringT &sep) const noexcept
Splits the string at the first occurrence of sep, and returns a 3-items vector containing the part be...
Definition cppstrings.h:1205
+
std::vector< CppStringT > split(const CppStringT &sep) noexcept
Returns a vector of the words in the whole string, using sep as the delimiter string.
Definition cppstrings.h:1597
+
const bool startswith(const CppStringT &prefix, const size_type start) const noexcept
Returns true if the string starts with the specified prefix, otherwise returns false....
Definition cppstrings.h:1746
+
CppStringT zfill(const size_type width) const noexcept
Returns a copy of the string left filled with ASCII '0' digits to make a string of length width.
Definition cppstrings.h:1914
+
CppStringT replace(const CppStringT &old, const CppStringT &new_, size_type count=-1) const noexcept
Returns a copy of the string with first count occurrences of substring 'old' replaced by 'new_'.
Definition cppstrings.h:1251
+
CppStringT & lower() noexcept
In-place replaces all characters of the string with their lowercase conversion. Returns a reference t...
Definition cppstrings.h:1078
+
CppStringT removesuffix(const CppStringT &suffix) const noexcept
If the string ends with the suffix string, returns a new string with the suffix removed....
Definition cppstrings.h:1237
+
const bool istitle() const noexcept
Returns true if the string is a titlecased string and there is at least one character,...
Definition cppstrings.h:964
+
const bool startswith_n(const CppStringT &prefix, const size_type count) const noexcept
Returns true if the string starts with the specified suffix, otherwise returns false....
Definition cppstrings.h:1784
+
const bool startswith(const CppStringT &prefix) const noexcept
Returns true if the string starts with the specified prefix, otherwise returns false....
Definition cppstrings.h:1753
+
const bool islower() const noexcept
Returns true if all cased characters in the string are lowercase and there is at least one cased char...
Definition cppstrings.h:898
+
CppStringT ljust(const size_type width, const value_type fillch=value_type(' ')) const noexcept
Returns the string left justified in a string of length width.
Definition cppstrings.h:1063
+
CppStringT lstrip(const CppStringT &removedchars) const noexcept
Returns a copy of the string with leading characters removed.
Definition cppstrings.h:1110
+
constexpr size_type index_n(const CppStringT &sub, const size_type start, const size_type count) const
Like find_n(sub, start, count), but raises NotFoundException when the substring is not found.
Definition cppstrings.h:779
+
CppStringT center(const size_type width, const value_type fillch=value_type(' ')) const noexcept
Returns a copy of the string centered in a string of length width.
Definition cppstrings.h:462
+
const bool isupper() const noexcept
Returns true if all cased characters in the string are uppercase and there is at least one cased char...
Definition cppstrings.h:973
+
constexpr size_type rfind(const CppStringT &sub, const size_type start, const size_type end) const noexcept
Returns the highest index in the string where substring sub is found within the slice str[start:end],...
Definition cppstrings.h:1288
+
static const value_type upper(const value_type ch) noexcept
Returns uppercase conversion of the character.
Definition cppstrings.h:1900
+
constexpr size_type rindex_n(const CppStringT &sub, const size_type start, const size_type count) const
Like rfind_n(sub, start, count), but raises NotFoundException when the substring is not found.
Definition cppstrings.h:1422
+
Base class for slices, with start, stop and step specified values.
Definition cppstrings.h:1949
+
IntT stop()
Returns the stop index of this slide.
Definition cppstrings.h:2001
+
IntT start()
Returns the start index of this slide.
Definition cppstrings.h:2000
+
IntT step()
Returns the step value of this slide.
Definition cppstrings.h:2002
+
Slice operator++() noexcept
< iterates one step, pre-increment. Caution: index may be out of bounds. Check '!end()' before derefe...
Definition cppstrings.h:1981
+
Slice operator++(int) noexcept
< iterates one step, post-increment. Caution: index may be out of bounds. Check '!...
Definition cppstrings.h:1987
+
Slice(const IntT start=DEFAULT, const IntT stop=DEFAULT, const IntT step=DEFAULT) noexcept
< Valued constructor
Definition cppstrings.h:1954
+
const IntT begin(const CppStringT< CharT > &str) noexcept
< starts iterating on specified CppString.
Definition cppstrings.h:1970
+
virtual ~Slice() noexcept=default
Default destructor.
+
const bool end() const noexcept
< returns true when iterating is over, or false otherwise.
Definition cppstrings.h:1976
+
const IntT operator*() noexcept
< dereferences the slice.
Definition cppstrings.h:1994
+
Definition cppstrings.h:41
+
const bool is_digit< wchar_t >(const wchar_t ch) noexcept
Returns true if character is a decimal digit, or false otherwise.
Definition cppstrings.h:2241
+
const bool is_punctuation(const CharT ch) noexcept
Returns true if character ch is punctuation, or false otherwise.
Definition cppstrings.h:2349
+
const bool is_alpha< wchar_t >(const wchar_t ch) noexcept
Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settin...
Definition cppstrings.h:2179
+
CppStringT< char > CppString
Specialization of basic class with template argument 'char'.
Definition cppstrings.h:53
+
const bool is_printable< char >(const char ch) noexcept
Returns true if character ch is printable, or false otherwise.
Definition cppstrings.h:2331
+
const bool is_numeric< char >(const char ch) noexcept
Returns true if character is a decimal digit, or false otherwise.
Definition cppstrings.h:2305
+
const bool is_decimal< char >(const char ch) noexcept
Returns true if character is a decimal digit, or false otherwise.
Definition cppstrings.h:2207
+
const bool is_lower< char >(const char ch) noexcept
Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale setting...
Definition cppstrings.h:2279
+
const bool is_printable< wchar_t >(const wchar_t ch) noexcept
Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale setti...
Definition cppstrings.h:2339
+
const bool is_punctuation< wchar_t >(const wchar_t ch) noexcept
Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale setti...
Definition cppstrings.h:2365
+
const bool is_alpha(const CharT ch) noexcept
struct of slices with default start values
Definition cppstrings.h:2163
+
const char to_lower< char >(const char ch) noexcept
Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the curr...
Definition cppstrings.h:2450
+
const bool is_printable(const CharT ch) noexcept
Returns true if character ch is printable, or false otherwise.
Definition cppstrings.h:2323
+
const bool is_digit(const CharT ch) noexcept
Returns true if character is a decimal digit, or false otherwise.
Definition cppstrings.h:2225
+
const bool is_space< wchar_t >(const wchar_t ch) noexcept
Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settin...
Definition cppstrings.h:2391
+
const CharT to_upper(const CharT ch) noexcept
Returns the uppercase form of character ch if it exists, or ch itself otherwise.
Definition cppstrings.h:2468
+
const bool is_decimal< wchar_t >(const wchar_t ch) noexcept
Returns true if character is a decimal digit, or false otherwise.
Definition cppstrings.h:2215
+
const bool is_space< char >(const char ch) noexcept
Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settin...
Definition cppstrings.h:2383
+
CppStringT< wchar_t > CppWString
Specialization of basic class with template argument 'wchar_t'.
Definition cppstrings.h:54
+
const bool is_upper(const CharT ch) noexcept
Returns true if character is uppercase, or false otherwise.
Definition cppstrings.h:2401
+
const CharT to_lower(const CharT ch) noexcept
Returns the lowercase form of character ch if it exists, or ch itself otherwise.
Definition cppstrings.h:2442
+
const bool is_decimal(const CharT ch) noexcept
Returns true if character is a decimal digit, or false otherwise.
Definition cppstrings.h:2199
+
const bool is_punctuation< char >(const char ch) noexcept
Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale setti...
Definition cppstrings.h:2357
+
const wchar_t to_upper< wchar_t >(const wchar_t ch) noexcept
Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the curr...
Definition cppstrings.h:2484
+
const wchar_t to_lower< wchar_t >(const wchar_t ch) noexcept
Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the curr...
Definition cppstrings.h:2458
+
const bool is_upper< wchar_t >(const wchar_t ch) noexcept
Returns true if character ch is uppercase, or false otherwise. Conforms to the current locale setting...
Definition cppstrings.h:2417
+
const char to_upper< char >(const char ch) noexcept
Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the curr...
Definition cppstrings.h:2476
+
const bool is_id_start(const CharT ch) noexcept
Returns true if character is a starting char for identifiers, or false otherwise.
Definition cppstrings.h:2261
+
const bool is_upper< char >(const char ch) noexcept
Returns true if character ch is uppercase, or false otherwise. Conforms to the current locale setting...
Definition cppstrings.h:2409
+
const CharT swap_case(const CharT ch) noexcept
Returns the swapped case form of character ch if it exists, or ch itself otherwise.
Definition cppstrings.h:2427
+
const bool is_ascii(const CharT ch) noexcept
Returns true if character ch gets ASCII code, or false otherwise.
Definition cppstrings.h:2189
+
const bool is_numeric< wchar_t >(const wchar_t ch) noexcept
Returns true if character is a decimal digit, or false otherwise.
Definition cppstrings.h:2313
+
const bool is_lower< wchar_t >(const wchar_t ch) noexcept
Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale setting...
Definition cppstrings.h:2287
+
const bool is_alpha< char >(const char ch) noexcept
Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settin...
Definition cppstrings.h:2171
+
const bool is_lower(const CharT ch) noexcept
Returns true if character is lowercase, or false otherwise.
Definition cppstrings.h:2271
+
const bool is_id_continue(const CharT ch) noexcept
Returns true if character is a continuing char for identifiers, or false otherwise.
Definition cppstrings.h:2251
+
const bool is_space(const CharT ch) noexcept
Returns true if character ch is white space, or false otherwise.
Definition cppstrings.h:2375
+
const bool is_numeric(const CharT ch) noexcept
Returns true if character is a decimal digit, or false otherwise.
Definition cppstrings.h:2297
+
const bool is_digit< char >(const char ch) noexcept
Returns true if character is a decimal digit, or false otherwise.
Definition cppstrings.h:2233
+
Base class for slices, with start, stop and step specified values.
Definition cppstrings.h:2065
+
virtual ~StartSlice() noexcept=default
Default destructor.
+
StartSlice(const IntT start=MyBaseClass::DEFAULT) noexcept
< Valued constructor
Definition cppstrings.h:2069
+
struct of slices with default step values
Definition cppstrings.h:2129
+
StartStepSlice(const IntT start=MyBaseClass::DEFAULT, const IntT step=MyBaseClass::DEFAULT) noexcept
< Valued constructor
Definition cppstrings.h:2133
+
virtual ~StartStepSlice() noexcept=default
Default destructor.
+
struct of slices with default start and stop values
Definition cppstrings.h:2113
+
StartStopSlice(const IntT start=MyBaseClass::DEFAULT, const IntT stop=MyBaseClass::DEFAULT) noexcept
< Valued constructor
Definition cppstrings.h:2117
+
virtual ~StartStopSlice() noexcept=default
Default destructor.
+
struct of slices with default start and step values
Definition cppstrings.h:2097
+
virtual ~StepSlice() noexcept=default
Default destructor.
+
StepSlice(const IntT step=MyBaseClass::DEFAULT) noexcept
< Valued constructor
Definition cppstrings.h:2101
+
struct of slices with default stop and step values
Definition cppstrings.h:2081
+
virtual ~StopSlice() noexcept=default
Default destructor.
+
StopSlice(const IntT stop=MyBaseClass::DEFAULT) noexcept
< Valued constructor
Definition cppstrings.h:2085
+
struct of slices with default stop values
Definition cppstrings.h:2146
+
StopStepSlice(const IntT stop=MyBaseClass::DEFAULT, const IntT step=MyBaseClass::DEFAULT) noexcept
< Valued constructor
Definition cppstrings.h:2150
+
virtual ~StopStepSlice() noexcept=default
Default destructor.
+
+
+
+ + + + diff --git a/cpp-strings/html/doxygen.css b/cpp-strings/html/doxygen.css new file mode 100644 index 0000000..df33d6b --- /dev/null +++ b/cpp-strings/html/doxygen.css @@ -0,0 +1,2468 @@ +/* The standard CSS for doxygen 1.14.0*/ + +html { +/* page base colors */ +--page-background-color: white; +--page-foreground-color: black; +--page-link-color: #3D578C; +--page-visited-link-color: #3D578C; +--page-external-link-color: #334975; + +/* index */ +--index-odd-item-bg-color: #F8F9FC; +--index-even-item-bg-color: white; +--index-header-color: black; +--index-separator-color: #A0A0A0; + +/* header */ +--header-background-color: #F9FAFC; +--header-separator-color: #C4CFE5; +--group-header-separator-color: #D9E0EE; +--group-header-color: #354C7B; +--inherit-header-color: gray; + +--footer-foreground-color: #2A3D61; +--footer-logo-width: 75px; +--citation-label-color: #334975; +--glow-color: cyan; + +--title-background-color: white; +--title-separator-color: #C4CFE5; +--directory-separator-color: #9CAFD4; +--separator-color: #4A6AAA; + +--blockquote-background-color: #F7F8FB; +--blockquote-border-color: #9CAFD4; + +--scrollbar-thumb-color: #C4CFE5; +--scrollbar-background-color: #F9FAFC; + +--icon-background-color: #728DC1; +--icon-foreground-color: white; +/* +--icon-doc-image: url('doc.svg'); +--icon-folder-open-image: url('folderopen.svg'); +--icon-folder-closed-image: url('folderclosed.svg');*/ +--icon-folder-open-fill-color: #C4CFE5; +--icon-folder-fill-color: #D8DFEE; +--icon-folder-border-color: #4665A2; +--icon-doc-fill-color: #D8DFEE; +--icon-doc-border-color: #4665A2; + +/* brief member declaration list */ +--memdecl-background-color: #F9FAFC; +--memdecl-separator-color: #DEE4F0; +--memdecl-foreground-color: #555; +--memdecl-template-color: #4665A2; +--memdecl-border-color: #D5DDEC; + +/* detailed member list */ +--memdef-border-color: #A8B8D9; +--memdef-title-background-color: #E2E8F2; +--memdef-proto-background-color: #EEF1F7; +--memdef-proto-text-color: #253555; +--memdef-doc-background-color: white; +--memdef-param-name-color: #602020; +--memdef-template-color: #4665A2; + +/* tables */ +--table-cell-border-color: #2D4068; +--table-header-background-color: #374F7F; +--table-header-foreground-color: #FFFFFF; + +/* labels */ +--label-background-color: #728DC1; +--label-left-top-border-color: #5373B4; +--label-right-bottom-border-color: #C4CFE5; +--label-foreground-color: white; + +/** navigation bar/tree/menu */ +--nav-background-color: #F9FAFC; +--nav-foreground-color: #364D7C; +--nav-border-color: #C4CFE5; +--nav-breadcrumb-separator-color: #C4CFE5; +--nav-breadcrumb-active-bg: #EEF1F7; +--nav-breadcrumb-color: #354C7B; +--nav-breadcrumb-border-color: #E1E7F2; +--nav-splitbar-bg-color: #DCE2EF; +--nav-splitbar-handle-color: #9CAFD4; +--nav-font-size-level1: 13px; +--nav-font-size-level2: 10px; +--nav-font-size-level3: 9px; +--nav-text-normal-color: #283A5D; +--nav-text-hover-color: white; +--nav-text-active-color: white; +--nav-menu-button-color: #364D7C; +--nav-menu-background-color: white; +--nav-menu-foreground-color: #555555; +--nav-menu-active-bg: #DCE2EF; +--nav-menu-active-color: #9CAFD4; +--nav-menu-toggle-color: rgba(255, 255, 255, 0.5); +--nav-arrow-color: #B6C4DF; +--nav-arrow-selected-color: #90A5CE; + +/* sync icon */ +--sync-icon-border-color: #C4CFE5; +--sync-icon-background-color: #F9FAFC; +--sync-icon-selected-background-color: #EEF1F7; +--sync-icon-color: #C4CFE5; +--sync-icon-selected-color: #6884BD; + +/* table of contents */ +--toc-background-color: #F4F6FA; +--toc-border-color: #D8DFEE; +--toc-header-color: #4665A2; +--toc-down-arrow-image: url("data:image/svg+xml;utf8,&%238595;"); + +/** search field */ +--search-background-color: white; +--search-foreground-color: #909090; +--search-active-color: black; +--search-filter-background-color: rgba(255,255,255,.7); +--search-filter-backdrop-filter: blur(4px); +--search-filter-foreground-color: black; +--search-filter-border-color: rgba(150,150,150,.4); +--search-filter-highlight-text-color: white; +--search-filter-highlight-bg-color: #3D578C; +--search-results-foreground-color: #425E97; +--search-results-background-color: rgba(255,255,255,.8); +--search-results-backdrop-filter: blur(4px); +--search-results-border-color: rgba(150,150,150,.4); +--search-box-border-color: #B6C4DF; +--search-close-icon-bg-color: #A0A0A0; +--search-close-icon-fg-color: white; + +/** code fragments */ +--code-keyword-color: #008000; +--code-type-keyword-color: #604020; +--code-flow-keyword-color: #E08000; +--code-comment-color: #800000; +--code-preprocessor-color: #806020; +--code-string-literal-color: #002080; +--code-char-literal-color: #008080; +--code-xml-cdata-color: black; +--code-vhdl-digit-color: #FF00FF; +--code-vhdl-char-color: #000000; +--code-vhdl-keyword-color: #700070; +--code-vhdl-logic-color: #FF0000; +--code-link-color: #4665A2; +--code-external-link-color: #4665A2; +--fragment-foreground-color: black; +--fragment-background-color: #FBFCFD; +--fragment-border-color: #C4CFE5; +--fragment-lineno-border-color: #00FF00; +--fragment-lineno-background-color: #E8E8E8; +--fragment-lineno-foreground-color: black; +--fragment-lineno-link-fg-color: #4665A2; +--fragment-lineno-link-bg-color: #D8D8D8; +--fragment-lineno-link-hover-fg-color: #4665A2; +--fragment-lineno-link-hover-bg-color: #C8C8C8; +--fragment-copy-ok-color: #2EC82E; +--tooltip-foreground-color: black; +--tooltip-background-color: rgba(255,255,255,0.8); +--tooltip-arrow-background-color: white; +--tooltip-border-color: rgba(150,150,150,0.7); +--tooltip-backdrop-filter: blur(3px); +--tooltip-doc-color: grey; +--tooltip-declaration-color: #006318; +--tooltip-link-color: #4665A2; +--tooltip-shadow: 0 4px 8px 0 rgba(0,0,0,.25); +--fold-line-color: #808080; + +/** font-family */ +--font-family-normal: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; +--font-family-monospace: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; +--font-family-nav: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +--font-family-title: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; +--font-family-toc: Verdana,'DejaVu Sans',Geneva,sans-serif; +--font-family-search: Arial,Verdana,sans-serif; +--font-family-icon: Arial,Helvetica; +--font-family-tooltip: Roboto,sans-serif; + +/** special sections */ +--warning-color-bg: #f8d1cc; +--warning-color-hl: #b61825; +--warning-color-text: #75070f; +--note-color-bg: #faf3d8; +--note-color-hl: #f3a600; +--note-color-text: #5f4204; +--todo-color-bg: #e4f3ff; +--todo-color-hl: #1879C4; +--todo-color-text: #274a5c; +--test-color-bg: #e8e8ff; +--test-color-hl: #3939C4; +--test-color-text: #1a1a5c; +--deprecated-color-bg: #ecf0f3; +--deprecated-color-hl: #5b6269; +--deprecated-color-text: #43454a; +--bug-color-bg: #e4dafd; +--bug-color-hl: #5b2bdd; +--bug-color-text: #2a0d72; +--invariant-color-bg: #d8f1e3; +--invariant-color-hl: #44b86f; +--invariant-color-text: #265532; +} + +@media (prefers-color-scheme: dark) { + html:not(.dark-mode) { + color-scheme: dark; + +/* page base colors */ +--page-background-color: black; +--page-foreground-color: #C9D1D9; +--page-link-color: #90A5CE; +--page-visited-link-color: #90A5CE; +--page-external-link-color: #A3B4D7; + +/* index */ +--index-odd-item-bg-color: #0B101A; +--index-even-item-bg-color: black; +--index-header-color: #C4CFE5; +--index-separator-color: #334975; + +/* header */ +--header-background-color: #070B11; +--header-separator-color: #141C2E; +--group-header-separator-color: #1D2A43; +--group-header-color: #90A5CE; +--inherit-header-color: #A0A0A0; + +--footer-foreground-color: #5B7AB7; +--footer-logo-width: 60px; +--citation-label-color: #90A5CE; +--glow-color: cyan; + +--title-background-color: #090D16; +--title-separator-color: #212F4B; +--directory-separator-color: #283A5D; +--separator-color: #283A5D; + +--blockquote-background-color: #101826; +--blockquote-border-color: #283A5D; + +--scrollbar-thumb-color: #2C3F65; +--scrollbar-background-color: #070B11; + +--icon-background-color: #334975; +--icon-foreground-color: #C4CFE5; +--icon-folder-open-fill-color: #4665A2; +--icon-folder-fill-color: #5373B4; +--icon-folder-border-color: #C4CFE5; +--icon-doc-fill-color: #6884BD; +--icon-doc-border-color: #C4CFE5; + +/* brief member declaration list */ +--memdecl-background-color: #0B101A; +--memdecl-separator-color: #2C3F65; +--memdecl-foreground-color: #BBB; +--memdecl-template-color: #7C95C6; +--memdecl-border-color: #233250; + +/* detailed member list */ +--memdef-border-color: #233250; +--memdef-title-background-color: #1B2840; +--memdef-proto-background-color: #19243A; +--memdef-proto-text-color: #9DB0D4; +--memdef-doc-background-color: black; +--memdef-param-name-color: #D28757; +--memdef-template-color: #7C95C6; + +/* tables */ +--table-cell-border-color: #283A5D; +--table-header-background-color: #283A5D; +--table-header-foreground-color: #C4CFE5; + +/* labels */ +--label-background-color: #354C7B; +--label-left-top-border-color: #4665A2; +--label-right-bottom-border-color: #283A5D; +--label-foreground-color: #CCCCCC; + +/** navigation bar/tree/menu */ +--nav-background-color: #101826; +--nav-foreground-color: #364D7C; +--nav-border-color: #212F4B; +--nav-breadcrumb-separator-color: #212F4B; +--nav-breadcrumb-active-bg: #1D2A43; +--nav-breadcrumb-color: #90A5CE; +--nav-breadcrumb-border-color: #2A3D61; +--nav-splitbar-bg-color: #283A5D; +--nav-splitbar-handle-color: #4665A2; +--nav-font-size-level1: 13px; +--nav-font-size-level2: 10px; +--nav-font-size-level3: 9px; +--nav-text-normal-color: #B6C4DF; +--nav-text-hover-color: #DCE2EF; +--nav-text-active-color: #DCE2EF; +--nav-menu-button-color: #B6C4DF; +--nav-menu-background-color: #05070C; +--nav-menu-foreground-color: #BBBBBB; +--nav-menu-active-bg: #1D2A43; +--nav-menu-active-color: #C9D3E7; +--nav-menu-toggle-color: rgba(255, 255, 255, 0.2); +--nav-arrow-color: #4665A2; +--nav-arrow-selected-color: #6884BD; + +/* sync icon */ +--sync-icon-border-color: #212F4B; +--sync-icon-background-color: #101826; +--sync-icon-selected-background-color: #1D2A43; +--sync-icon-color: #4665A2; +--sync-icon-selected-color: #5373B4; + +/* table of contents */ +--toc-background-color: #151E30; +--toc-border-color: #202E4A; +--toc-header-color: #A3B4D7; +--toc-down-arrow-image: url("data:image/svg+xml;utf8,&%238595;"); + +/** search field */ +--search-background-color: black; +--search-foreground-color: #C5C5C5; +--search-active-color: #F5F5F5; +--search-filter-background-color: #101826; +--search-filter-foreground-color: #90A5CE; +--search-filter-backdrop-filter: none; +--search-filter-border-color: #7C95C6; +--search-filter-highlight-text-color: #BCC9E2; +--search-filter-highlight-bg-color: #283A5D; +--search-results-background-color: black; +--search-results-foreground-color: #90A5CE; +--search-results-backdrop-filter: none; +--search-results-border-color: #334975; +--search-box-border-color: #334975; +--search-close-icon-bg-color: #909090; +--search-close-icon-fg-color: black; + +/** code fragments */ +--code-keyword-color: #CC99CD; +--code-type-keyword-color: #AB99CD; +--code-flow-keyword-color: #E08000; +--code-comment-color: #717790; +--code-preprocessor-color: #65CABE; +--code-string-literal-color: #7EC699; +--code-char-literal-color: #00E0F0; +--code-xml-cdata-color: #C9D1D9; +--code-vhdl-digit-color: #FF00FF; +--code-vhdl-char-color: #C0C0C0; +--code-vhdl-keyword-color: #CF53C9; +--code-vhdl-logic-color: #FF0000; +--code-link-color: #79C0FF; +--code-external-link-color: #79C0FF; +--fragment-foreground-color: #C9D1D9; +--fragment-background-color: #090D16; +--fragment-border-color: #30363D; +--fragment-lineno-border-color: #30363D; +--fragment-lineno-background-color: black; +--fragment-lineno-foreground-color: #6E7681; +--fragment-lineno-link-fg-color: #6E7681; +--fragment-lineno-link-bg-color: #303030; +--fragment-lineno-link-hover-fg-color: #8E96A1; +--fragment-lineno-link-hover-bg-color: #505050; +--fragment-copy-ok-color: #0EA80E; +--tooltip-foreground-color: #C9D1D9; +--tooltip-background-color: #202020; +--tooltip-arrow-background-color: #202020; +--tooltip-backdrop-filter: none; +--tooltip-border-color: #C9D1D9; +--tooltip-doc-color: #D9E1E9; +--tooltip-declaration-color: #20C348; +--tooltip-link-color: #79C0FF; +--tooltip-shadow: none; +--fold-line-color: #808080; + +/** font-family */ +--font-family-normal: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; +--font-family-monospace: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; +--font-family-nav: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +--font-family-title: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; +--font-family-toc: Verdana,'DejaVu Sans',Geneva,sans-serif; +--font-family-search: Arial,Verdana,sans-serif; +--font-family-icon: Arial,Helvetica; +--font-family-tooltip: Roboto,sans-serif; + +/** special sections */ +--warning-color-bg: #2e1917; +--warning-color-hl: #ad2617; +--warning-color-text: #f5b1aa; +--note-color-bg: #3b2e04; +--note-color-hl: #f1b602; +--note-color-text: #ceb670; +--todo-color-bg: #163750; +--todo-color-hl: #1982D2; +--todo-color-text: #dcf0fa; +--test-color-bg: #121258; +--test-color-hl: #4242cf; +--test-color-text: #c0c0da; +--deprecated-color-bg: #2e323b; +--deprecated-color-hl: #738396; +--deprecated-color-text: #abb0bd; +--bug-color-bg: #2a2536; +--bug-color-hl: #7661b3; +--bug-color-text: #ae9ed6; +--invariant-color-bg: #303a35; +--invariant-color-hl: #76ce96; +--invariant-color-text: #cceed5; +}} +body { + background-color: var(--page-background-color); + color: var(--page-foreground-color); +} + +body, table, div, p, dl { + font-weight: 400; + font-size: 14px; + font-family: var(--font-family-normal); + line-height: 22px; +} + +body.resizing { + user-select: none; + -webkit-user-select: none; +} + +#doc-content { + scrollbar-width: thin; +} + +/* @group Heading Levels */ + +.title { + font-family: var(--font-family-normal); + line-height: 28px; + font-size: 160%; + font-weight: 400; + margin: 10px 2px; +} + +h1.groupheader { + font-size: 150%; +} + +h2.groupheader { + box-shadow: 12px 0 var(--page-background-color), + -12px 0 var(--page-background-color), + 12px 1px var(--group-header-separator-color), + -12px 1px var(--group-header-separator-color); + color: var(--group-header-color); + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +td h2.groupheader { + box-shadow: 13px 0 var(--page-background-color), + -13px 0 var(--page-background-color), + 13px 1px var(--group-header-separator-color), + -13px 1px var(--group-header-separator-color); +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px var(--glow-color); +} + +dt { + font-weight: bold; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +th p.starttd, th p.intertd, th p.endtd { + font-size: 100%; + font-weight: 700; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +p.interli { +} + +p.interdd { +} + +p.intertd { +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.navtab { + margin-right: 6px; + padding-right: 6px; + text-align: right; + line-height: 110%; + background-color: var(--nav-background-color); +} + +div.navtab table { + border-spacing: 0; +} + +td.navtab { + padding-right: 6px; + padding-left: 6px; +} + +td.navtabHL { + padding-right: 6px; + padding-left: 6px; + border-radius: 0 6px 6px 0; + background-color: var(--nav-menu-active-bg); +} + +div.qindex{ + text-align: center; + width: 100%; + line-height: 140%; + font-size: 130%; + color: var(--index-separator-color); +} + +#main-menu a:focus { + outline: auto; + z-index: 10; + position: relative; +} + +dt.alphachar{ + font-size: 180%; + font-weight: bold; +} + +.alphachar a{ + color: var(--index-header-color); +} + +.alphachar a:hover, .alphachar a:visited{ + text-decoration: none; +} + +.classindex dl { + padding: 25px; + column-count:1 +} + +.classindex dd { + display:inline-block; + margin-left: 50px; + width: 90%; + line-height: 1.15em; +} + +.classindex dl.even { + background-color: var(--index-even-item-bg-color); +} + +.classindex dl.odd { + background-color: var(--index-odd-item-bg-color); +} + +@media(min-width: 1120px) { + .classindex dl { + column-count:2 + } +} + +@media(min-width: 1320px) { + .classindex dl { + column-count:3 + } +} + + +/* @group Link Styling */ + +a { + color: var(--page-link-color); + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: var(--page-visited-link-color); +} + +span.label a:hover { + text-decoration: none; + background: linear-gradient(to bottom, transparent 0,transparent calc(100% - 1px), currentColor 100%); +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.el, a.el:visited, a.code, a.code:visited, a.line, a.line:visited { + color: var(--page-link-color); +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: var(--page-external-link-color); +} + +a.code.hl_class { /* style for links to class names in code snippets */ } +a.code.hl_struct { /* style for links to struct names in code snippets */ } +a.code.hl_union { /* style for links to union names in code snippets */ } +a.code.hl_interface { /* style for links to interface names in code snippets */ } +a.code.hl_protocol { /* style for links to protocol names in code snippets */ } +a.code.hl_category { /* style for links to category names in code snippets */ } +a.code.hl_exception { /* style for links to exception names in code snippets */ } +a.code.hl_service { /* style for links to service names in code snippets */ } +a.code.hl_singleton { /* style for links to singleton names in code snippets */ } +a.code.hl_concept { /* style for links to concept names in code snippets */ } +a.code.hl_namespace { /* style for links to namespace names in code snippets */ } +a.code.hl_package { /* style for links to package names in code snippets */ } +a.code.hl_define { /* style for links to macro names in code snippets */ } +a.code.hl_function { /* style for links to function names in code snippets */ } +a.code.hl_variable { /* style for links to variable names in code snippets */ } +a.code.hl_typedef { /* style for links to typedef names in code snippets */ } +a.code.hl_enumvalue { /* style for links to enum value names in code snippets */ } +a.code.hl_enumeration { /* style for links to enumeration names in code snippets */ } +a.code.hl_signal { /* style for links to Qt signal names in code snippets */ } +a.code.hl_slot { /* style for links to Qt slot names in code snippets */ } +a.code.hl_friend { /* style for links to friend names in code snippets */ } +a.code.hl_dcop { /* style for links to KDE3 DCOP names in code snippets */ } +a.code.hl_property { /* style for links to property names in code snippets */ } +a.code.hl_event { /* style for links to event names in code snippets */ } +a.code.hl_sequence { /* style for links to sequence names in code snippets */ } +a.code.hl_dictionary { /* style for links to dictionary names in code snippets */ } + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +ul.check { + list-style:none; + text-indent: -16px; + padding-left: 38px; +} +li.unchecked:before { + content: "\2610\A0"; +} +li.checked:before { + content: "\2611\A0"; +} + +ol { + text-indent: 0px; +} + +ul { + text-indent: 0px; + overflow: visible; +} + +ul.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; + column-count: 3; + list-style-type: none; +} + +#side-nav ul { + overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */ +} + +#main-nav ul { + overflow: visible; /* reset ul rule for the navigation bar drop down lists */ +} + +.fragment { + text-align: left; + direction: ltr; + overflow-x: auto; + overflow-y: hidden; + position: relative; + min-height: 12px; + margin: 10px 0px; + padding: 10px 10px; + border: 1px solid var(--fragment-border-color); + border-radius: 4px; + background-color: var(--fragment-background-color); + color: var(--fragment-foreground-color); +} + +pre.fragment { + word-wrap: break-word; + font-size: 10pt; + line-height: 125%; + font-family: var(--font-family-monospace); +} + +span.tt { + white-space: pre; + font-family: var(--font-family-monospace); +} + +.clipboard { + width: 24px; + height: 24px; + right: 5px; + top: 5px; + opacity: 0; + position: absolute; + display: inline; + overflow: hidden; + justify-content: center; + align-items: center; + cursor: pointer; +} + +.clipboard.success { + border: 1px solid var(--fragment-foreground-color); + border-radius: 4px; +} + +.fragment:hover .clipboard, .clipboard.success { + opacity: .4; +} + +.clipboard:hover, .clipboard.success { + opacity: 1 !important; +} + +.clipboard:active:not([class~=success]) svg { + transform: scale(.91); +} + +.clipboard.success svg { + fill: var(--fragment-copy-ok-color); +} + +.clipboard.success { + border-color: var(--fragment-copy-ok-color); +} + +div.line { + font-family: var(--font-family-monospace); + font-size: 13px; + min-height: 13px; + line-height: 1.2; + text-wrap: wrap; + word-break: break-all; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -62px; + padding-left: 62px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line:after { + content:"\000A"; + white-space: pre; +} + +div.line.glow { + background-color: var(--glow-color); + box-shadow: 0 0 10px var(--glow-color); +} + +span.fold { + display: inline-block; + width: 12px; + height: 12px; + margin-left: 4px; + margin-right: 1px; +} + +span.foldnone { + display: inline-block; + position: relative; + cursor: pointer; + user-select: none; +} + +span.fold.plus, span.fold.minus { + width: 10px; + height: 10px; + background-color: var(--fragment-background-color); + position: relative; + border: 1px solid var(--fold-line-color); + margin-right: 1px; +} + +span.fold.plus::before, span.fold.minus::before { + content: ''; + position: absolute; + background-color: var(--fold-line-color); +} + +span.fold.plus::before { + width: 2px; + height: 6px; + top: 2px; + left: 4px; +} + +span.fold.plus::after { + content: ''; + position: absolute; + width: 6px; + height: 2px; + top: 4px; + left: 2px; + background-color: var(--fold-line-color); +} + +span.fold.minus::before { + width: 6px; + height: 2px; + top: 4px; + left: 2px; +} + +span.lineno { + padding-right: 4px; + margin-right: 9px; + text-align: right; + border-right: 2px solid var(--fragment-lineno-border-color); + color: var(--fragment-lineno-foreground-color); + background-color: var(--fragment-lineno-background-color); + white-space: pre; +} +span.lineno a, span.lineno a:visited { + color: var(--fragment-lineno-link-fg-color); + background-color: var(--fragment-lineno-link-bg-color); +} + +span.lineno a:hover { + color: var(--fragment-lineno-link-hover-fg-color); + background-color: var(--fragment-lineno-link-hover-bg-color); +} + +.lineno { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + box-shadow: 13px 0 var(--page-background-color), + -13px 0 var(--page-background-color), + 13px 1px var(--group-header-separator-color), + -13px 1px var(--group-header-separator-color); + color: var(--group-header-color); + font-size: 110%; + font-weight: 500; + margin-left: 0px; + margin-top: 0em; + margin-bottom: 6px; + padding-top: 8px; + padding-bottom: 4px; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + color: var(--page-foreground-color); + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 12px; +} + +p.formulaDsp { + text-align: center; +} + +img.dark-mode-visible { + display: none; +} +img.light-mode-visible { + display: none; +} + +img.formulaInl, img.inline { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; + width: var(--footer-logo-width); +} + +.compoundTemplParams { + color: var(--memdecl-template-color); + font-size: 80%; + line-height: 120%; +} + +/* @group Code Colorization */ + +span.keyword { + color: var(--code-keyword-color); +} + +span.keywordtype { + color: var(--code-type-keyword-color); +} + +span.keywordflow { + color: var(--code-flow-keyword-color); +} + +span.comment { + color: var(--code-comment-color); +} + +span.preprocessor { + color: var(--code-preprocessor-color); +} + +span.stringliteral { + color: var(--code-string-literal-color); +} + +span.charliteral { + color: var(--code-char-literal-color); +} + +span.xmlcdata { + color: var(--code-xml-cdata-color); +} + +span.vhdldigit { + color: var(--code-vhdl-digit-color); +} + +span.vhdlchar { + color: var(--code-vhdl-char-color); +} + +span.vhdlkeyword { + color: var(--code-vhdl-keyword-color); +} + +span.vhdllogic { + color: var(--code-vhdl-logic-color); +} + +blockquote { + background-color: var(--blockquote-background-color); + border-left: 2px solid var(--blockquote-border-color); + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid var(--table-cell-border-color); +} + +th.dirtab { + background-color: var(--table-header-background-color); + color: var(--table-header-foreground-color); + font-weight: bold; +} + +hr { + border: none; + margin-top: 16px; + margin-bottom: 16px; + height: 1px; + box-shadow: 13px 0 var(--page-background-color), + -13px 0 var(--page-background-color), + 13px 1px var(--group-header-separator-color), + -13px 1px var(--group-header-separator-color); +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: var(--glow-color); + box-shadow: 0 0 15px var(--glow-color); +} + +.memberdecls tr[class^='memitem'] { + font-family: var(--font-family-monospace); +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight { + padding-top: 2px; + padding-bottom: 2px; +} + +.memTemplParams { + padding-left: 10px; + padding-top: 5px; +} + +.memItemLeft, .memItemRight, .memTemplParams { + background-color: var(--memdecl-background-color); +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: var(--memdecl-foreground-color); +} + +tr[class^='memdesc'] { + box-shadow: inset 0px 1px 3px 0px rgba(0,0,0,.075); +} + +.mdescLeft { + border-left: 1px solid var(--memdecl-border-color); + border-bottom: 1px solid var(--memdecl-border-color); +} + +.mdescRight { + border-right: 1px solid var(--memdecl-border-color); + border-bottom: 1px solid var(--memdecl-border-color); +} + +.memTemplParams { + color: var(--memdecl-template-color); + white-space: nowrap; + font-size: 80%; + border-left: 1px solid var(--memdecl-border-color); + border-right: 1px solid var(--memdecl-border-color); +} + +td.ititle { + border: 1px solid var(--memdecl-border-color); + border-top-left-radius: 4px; + border-top-right-radius: 4px; + padding-left: 10px; +} + +tr:not(:first-child) > td.ititle { + border-top: 0; + border-radius: 0; +} + +.memItemLeft { + white-space: nowrap; + border-left: 1px solid var(--memdecl-border-color); + border-bottom: 1px solid var(--memdecl-border-color); + padding-left: 10px; + transition: none; +} + +.memItemRight { + width: 100%; + border-right: 1px solid var(--memdecl-border-color); + border-bottom: 1px solid var(--memdecl-border-color); + padding-right: 10px; + transition: none; +} + +tr.heading + tr[class^='memitem'] td.memItemLeft, +tr.groupHeader + tr[class^='memitem'] td.memItemLeft, +tr.inherit_header + tr[class^='memitem'] td.memItemLeft { + border-top: 1px solid var(--memdecl-border-color); + border-top-left-radius: 4px; +} + +tr.heading + tr[class^='memitem'] td.memItemRight, +tr.groupHeader + tr[class^='memitem'] td.memItemRight, +tr.inherit_header + tr[class^='memitem'] td.memItemRight { + border-top: 1px solid var(--memdecl-border-color); + border-top-right-radius: 4px; +} + +tr.heading + tr[class^='memitem'] td.memTemplParams, +tr.heading + tr td.ititle, +tr.groupHeader + tr[class^='memitem'] td.memTemplParams, +tr.groupHeader + tr td.ititle, +tr.inherit_header + tr[class^='memitem'] td.memTemplParams { + border-top: 1px solid var(--memdecl-border-color); + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +table.memberdecls tr:last-child td.memItemLeft, +table.memberdecls tr:last-child td.mdescLeft, +table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemLeft, +table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemLeft, +table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescLeft, +table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescLeft { + border-bottom-left-radius: 4px; +} + +table.memberdecls tr:last-child td.memItemRight, +table.memberdecls tr:last-child td.mdescRight, +table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemRight, +table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemRight, +table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescRight, +table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescRight { + border-bottom-right-radius: 4px; +} + +tr.template .memItemLeft, tr.template .memItemRight { + border-top: none; + padding-top: 0; +} + + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtitle { + padding: 8px; + border-top: 1px solid var(--memdef-border-color); + border-left: 1px solid var(--memdef-border-color); + border-right: 1px solid var(--memdef-border-color); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-color: var(--memdef-proto-background-color); + line-height: 1.25; + font-family: var(--font-family-monospace); + font-weight: 500; + font-size: 16px; + float:left; + box-shadow: 0 10px 0 -1px var(--memdef-proto-background-color), + 0 2px 8px 0 rgba(0,0,0,.075); + position: relative; +} + +.memtitle:after { + content: ''; + display: block; + background: var(--memdef-proto-background-color); + height: 10px; + bottom: -10px; + left: 0px; + right: -14px; + position: absolute; + border-top-right-radius: 6px; +} + +.permalink +{ + font-family: var(--font-family-monospace); + font-weight: 500; + line-height: 1.25; + font-size: 16px; + display: inline-block; + vertical-align: middle; +} + +.memtemplate { + font-size: 80%; + color: var(--memdef-template-color); + font-family: var(--font-family-monospace); + font-weight: normal; + margin-left: 9px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + display: table !important; + width: 100%; + box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); + border-radius: 4px; +} + +.memitem.glow { + box-shadow: 0 0 15px var(--glow-color); +} + +.memname { + font-family: var(--font-family-monospace); + font-size: 13px; + font-weight: 400; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid var(--memdef-border-color); + border-left: 1px solid var(--memdef-border-color); + border-right: 1px solid var(--memdef-border-color); + padding: 6px 0px 6px 0px; + color: var(--memdef-proto-text-color); + font-weight: bold; + background-color: var(--memdef-proto-background-color); + border-top-right-radius: 4px; + border-bottom: 1px solid var(--memdef-border-color); +} + +.overload { + font-family: var(--font-family-monospace); + font-size: 65%; +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid var(--memdef-border-color); + border-left: 1px solid var(--memdef-border-color); + border-right: 1px solid var(--memdef-border-color); + padding: 6px 10px 2px 10px; + border-top-width: 0; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; + padding: 0px; + padding-bottom: 1px; +} + +.paramname { + white-space: nowrap; + padding: 0px; + padding-bottom: 1px; + margin-left: 2px; +} + +.paramname em { + color: var(--memdef-param-name-color); + font-style: normal; + margin-right: 1px; +} + +.paramname .paramdefval { + font-family: var(--font-family-monospace); +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname, .tparams .paramname, .exception .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype, .tparams .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir, .tparams .paramdir { + font-family: var(--font-family-monospace); + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: var(--label-background-color); + border-top:1px solid var(--label-left-top-border-color); + border-left:1px solid var(--label-left-top-border-color); + border-right:1px solid var(--label-right-bottom-border-color); + border-bottom:1px solid var(--label-right-bottom-border-color); + text-shadow: none; + color: var(--label-foreground-color); + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.odd { + padding-left: 6px; + background-color: var(--index-odd-item-bg-color); +} + +.directory tr.even { + padding-left: 6px; + background-color: var(--index-even-item-bg-color); +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: var(--page-link-color); +} + +.arrow { + color: var(--nav-background-color); + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 14px; + transition: opacity 0.3s ease; +} + +span.arrowhead { + position: relative; + padding: 0; + margin: 0 0 0 2px; + display: inline-block; + width: 5px; + height: 5px; + border-right: 2px solid var(--nav-arrow-color); + border-bottom: 2px solid var(--nav-arrow-color); + transform: rotate(-45deg); + transition: transform 0.3s ease; +} + +span.arrowhead.opened { + transform: rotate(45deg); +} + +.selected span.arrowhead { + border-right: 2px solid var(--nav-arrow-selected-color); + border-bottom: 2px solid var(--nav-arrow-selected-color); +} + +.icon { + font-family: var(--font-family-icon); + line-height: normal; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: var(--icon-background-color); + color: var(--icon-foreground-color); + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfolder { + width: 24px; + height: 18px; + margin-top: 6px; + vertical-align:top; + display: inline-block; + position: relative; +} + +.icondoc { + width: 24px; + height: 18px; + margin-top: 3px; + vertical-align:top; + display: inline-block; + position: relative; +} + +.folder-icon { + width: 16px; + height: 11px; + background-color: var(--icon-folder-fill-color); + border: 1px solid var(--icon-folder-border-color); + border-radius: 0 2px 2px 2px; + position: relative; + box-sizing: content-box; +} + +.folder-icon::after { + content: ''; + position: absolute; + top: 2px; + left: -1px; + width: 16px; + height: 7px; + background-color: var(--icon-folder-open-fill-color); + border: 1px solid var(--icon-folder-border-color); + border-radius: 7px 7px 2px 2px; + transform-origin: top left; + opacity: 0; + transition: all 0.3s linear; +} + +.folder-icon::before { + content: ''; + position: absolute; + top: -3px; + left: -1px; + width: 6px; + height: 2px; + background-color: var(--icon-folder-fill-color); + border-top: 1px solid var(--icon-folder-border-color); + border-left: 1px solid var(--icon-folder-border-color); + border-right: 1px solid var(--icon-folder-border-color); + border-radius: 2px 2px 0 0; +} + +.folder-icon.open::after { + top: 3px; + opacity: 1; +} + +.doc-icon { + left: 6px; + width: 12px; + height: 16px; + background-color: var(--icon-doc-border-color); + clip-path: polygon(0 0, 66% 0, 100% 25%, 100% 100%, 0 100%); + position: relative; + display: inline-block; +} +.doc-icon::before { + content: ""; + left: 1px; + top: 1px; + width: 10px; + height: 14px; + background-color: var(--icon-doc-fill-color); + clip-path: polygon(0 0, 66% 0, 100% 25%, 100% 100%, 0 100%); + position: absolute; + box-sizing: border-box; +} +.doc-icon::after { + content: ""; + left: 7px; + top: 0px; + width: 3px; + height: 3px; + background-color: transparent; + position: absolute; + border: 1px solid var(--icon-doc-border-color); +} + + + + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +span.dynarrow { + position: relative; + display: inline-block; + width: 12px; + bottom: 1px; +} + +address { + font-style: normal; + color: var(--footer-foreground-color); +} + +table.doxtable caption { + caption-side: top; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid var(--table-cell-border-color); + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: var(--table-header-background-color); + color: var(--table-header-foreground-color); + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + margin-bottom: 10px; + border: 1px solid var(--memdef-border-color); + border-spacing: 0px; + border-radius: 4px; + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fieldinit { + white-space: nowrap; + border-right: 1px solid var(--memdef-border-color); + border-bottom: 1px solid var(--memdef-border-color); + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fieldinit { + padding-top: 3px; + text-align: right; +} + + +.fieldtable td.fielddoc { + border-bottom: 1px solid var(--memdef-border-color); +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-color: var(--memdef-title-background-color); + font-size: 90%; + color: var(--memdef-proto-text-color); + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + font-weight: 400; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid var(--memdef-border-color); +} + +/* ----------- navigation breadcrumb styling ----------- */ + +#nav-path ul { + height: 30px; + line-height: 30px; + color: var(--nav-text-normal-color); + overflow: hidden; + margin: 0px; + padding-left: 4px; + background-image: none; + background: var(--page-background-color); + border-bottom: 1px solid var(--nav-breadcrumb-separator-color); + font-size: var(--nav-font-size-level1); + font-family: var(--font-family-nav); + position: relative; + z-index: 100; +} + +#main-nav { + border-bottom: 1px solid var(--nav-border-color); +} + +.navpath li { + list-style-type:none; + float:left; + color: var(--nav-foreground-color); +} + +.navpath li.footer { + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + font-size: 8pt; + color: var(--footer-foreground-color); +} + +#nav-path li.navelem { + background-image: none; + display: flex; + align-items: center; + padding-left: 15px; +} + +.navpath li.navelem a { + text-shadow: none; + display: inline-block; + color: var(--nav-breadcrumb-color); + position: relative; + top: 0px; + height: 30px; + margin-right: -20px; +} + +#nav-path li.navelem:after { + content: ''; + display: inline-block; + position: relative; + top: 0; + right: -15px; + width: 30px; + height: 30px; + transform: scaleX(0.5) scale(0.707) rotate(45deg); + z-index: 10; + background: var(--page-background-color); + box-shadow: 2px -2px 0 2px var(--nav-breadcrumb-separator-color); + border-radius: 0 5px 0 50px; +} + +#nav-path li.navelem:first-child { + margin-left: -6px; +} + +#nav-path li.navelem:hover, +#nav-path li.navelem:hover:after { + background-color: var(--nav-breadcrumb-active-bg); +} + +/* ---------------------- */ + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +table.classindex +{ + margin: 10px; + white-space: nowrap; + margin-left: 3%; + margin-right: 3%; + width: 94%; + border: 0; + border-spacing: 0; + padding: 0; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + margin: 0px; + background-color: var(--header-background-color); + border-bottom: 1px solid var(--header-separator-color); +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl { + padding: 0 0 0 0; +} + +dl.bug dt a, dl.deprecated dt a, dl.todo dt a, dl.test a { + font-weight: bold !important; +} + +dl.warning, dl.attention, dl.important, dl.note, dl.deprecated, dl.bug, +dl.invariant, dl.pre, dl.post, dl.todo, dl.test, dl.remark { + padding: 10px; + margin: 10px 0px; + overflow: hidden; + margin-left: 0; + border-radius: 4px; +} + +dl.section dd { + margin-bottom: 2px; +} + +dl.warning, dl.attention, dl.important { + background: var(--warning-color-bg); + border-left: 8px solid var(--warning-color-hl); + color: var(--warning-color-text); +} + +dl.warning dt, dl.attention dt, dl.important dt { + color: var(--warning-color-hl); +} + +dl.note, dl.remark { + background: var(--note-color-bg); + border-left: 8px solid var(--note-color-hl); + color: var(--note-color-text); +} + +dl.note dt, dl.remark dt { + color: var(--note-color-hl); +} + +dl.todo { + background: var(--todo-color-bg); + border-left: 8px solid var(--todo-color-hl); + color: var(--todo-color-text); +} + +dl.todo dt { + color: var(--todo-color-hl); +} + +dl.test { + background: var(--test-color-bg); + border-left: 8px solid var(--test-color-hl); + color: var(--test-color-text); +} + +dl.test dt { + color: var(--test-color-hl); +} + +dl.bug dt a { + color: var(--bug-color-hl) !important; +} + +dl.bug { + background: var(--bug-color-bg); + border-left: 8px solid var(--bug-color-hl); + color: var(--bug-color-text); +} + +dl.bug dt a { + color: var(--bug-color-hl) !important; +} + +dl.deprecated { + background: var(--deprecated-color-bg); + border-left: 8px solid var(--deprecated-color-hl); + color: var(--deprecated-color-text); +} + +dl.deprecated dt a { + color: var(--deprecated-color-hl) !important; +} + +dl.note dd, dl.warning dd, dl.pre dd, dl.post dd, +dl.remark dd, dl.attention dd, dl.important dd, dl.invariant dd, +dl.bug dd, dl.deprecated dd, dl.todo dd, dl.test dd { + margin-inline-start: 0px; +} + +dl.invariant, dl.pre, dl.post { + background: var(--invariant-color-bg); + border-left: 8px solid var(--invariant-color-hl); + color: var(--invariant-color-text); +} + +dl.invariant dt, dl.pre dt, dl.post dt { + color: var(--invariant-color-hl); +} + + +#projectrow +{ + height: 56px; +} + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectalign +{ + vertical-align: middle; + padding-left: 0.5em; +} + +#projectname +{ + font-size: 200%; + font-family: var(--font-family-title); + margin: 0; + padding: 0; +} + +#side-nav #projectname +{ + font-size: 130%; +} + +#projectbrief +{ + font-size: 90%; + font-family: var(--font-family-title); + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font-size: 50%; + font-family: var(--font-family-title); + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0 0 0 5px; + margin: 0px; + border-bottom: 1px solid var(--title-separator-color); + background-color: var(--title-background-color); +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.plantumlgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:var(--citation-label-color); + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; + text-align:right; + width:52px; +} + +dl.citelist dd { + margin:2px 0 2px 72px; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: var(--toc-background-color); + border: 1px solid var(--toc-border-color); + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 8px 10px 10px; + width: 200px; +} + +div.toc li { + background: var(--toc-down-arrow-image) no-repeat scroll 0 5px transparent; + font: 10px/1.2 var(--font-family-toc); + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 var(--font-family-toc); + color: var(--toc-header-color); + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li[class^='level'] { + margin-left: 15px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.empty { + background-image: none; + margin-top: 0px; +} + +span.emoji { + /* font family used at the site: https://unicode.org/emoji/charts/full-emoji-list.html + * font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort; + */ +} + +span.obfuscator { + display: none; +} + +.inherit_header { + font-weight: 400; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0 2px 0; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 12px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + color: var(--tooltip-foreground-color); + background-color: var(--tooltip-background-color); + backdrop-filter: var(--tooltip-backdrop-filter); + -webkit-backdrop-filter: var(--tooltip-backdrop-filter); + border: 1px solid var(--tooltip-border-color); + border-radius: 4px; + box-shadow: var(--tooltip-shadow); + display: none; + font-size: smaller; + max-width: 80%; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: var(--tooltip-doc-color); + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip a { + color: var(--tooltip-link-color); +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: var(--tooltip-declaration-color); +} + +#powerTip div { + margin: 0px; + padding: 0px; + font-size: 12px; + font-family: var(--font-family-tooltip); + line-height: 16px; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: var(--tooltip-arrow-background-color); + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before, #powerTip.ne:before, #powerTip.nw:before { + border-top-color: var(--tooltip-border-color); + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: var(--tooltip-arrow-background-color); + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: var(--tooltip-border-color); + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: var(--tooltip-border-color); + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: var(--tooltip-border-color); + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: var(--tooltip-border-color); + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: var(--tooltip-border-color); + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + +/* @group Markdown */ + +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid var(--table-cell-border-color); + padding: 3px 7px 2px; +} + +table.markdownTable tr { +} + +th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { + background-color: var(--table-header-background-color); + color: var(--table-header-foreground-color); + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft, td.markdownTableBodyLeft { + text-align: left +} + +th.markdownTableHeadRight, td.markdownTableBodyRight { + text-align: right +} + +th.markdownTableHeadCenter, td.markdownTableBodyCenter { + text-align: center +} + +tt, code, kbd +{ + display: inline-block; +} +tt, code, kbd +{ + vertical-align: top; +} +/* @end */ + +u { + text-decoration: underline; +} + +details>summary { + list-style-type: none; +} + +details > summary::-webkit-details-marker { + display: none; +} + +details>summary::before { + content: "\25ba"; + padding-right:4px; + font-size: 80%; +} + +details[open]>summary::before { + content: "\25bc"; + padding-right:4px; + font-size: 80%; +} + + +html { +--timestamp: 'Wed Jul 16 2025' +} +span.timestamp { content: ' '; } +span.timestamp:before { content: var(--timestamp); } + +:root { + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-background-color); +} + +::-webkit-scrollbar { + background-color: var(--scrollbar-background-color); + height: 12px; + width: 12px; +} +::-webkit-scrollbar-thumb { + border-radius: 6px; + box-shadow: inset 0 0 12px 12px var(--scrollbar-thumb-color); + border: solid 2px transparent; +} +::-webkit-scrollbar-corner { + background-color: var(--scrollbar-background-color); +} + diff --git a/cpp-strings/html/doxygen.svg b/cpp-strings/html/doxygen.svg new file mode 100644 index 0000000..79a7635 --- /dev/null +++ b/cpp-strings/html/doxygen.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp-strings/html/doxygen_crawl.html b/cpp-strings/html/doxygen_crawl.html new file mode 100644 index 0000000..63ae5ec --- /dev/null +++ b/cpp-strings/html/doxygen_crawl.html @@ -0,0 +1,227 @@ + + + +Validator / crawler helper + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp-strings/html/dynsections.js b/cpp-strings/html/dynsections.js new file mode 100644 index 0000000..0e15bd4 --- /dev/null +++ b/cpp-strings/html/dynsections.js @@ -0,0 +1,191 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ + +function toggleVisibility(linkObj) { + return dynsection.toggleVisibility(linkObj); +} + +let dynsection = { + // helper function + updateStripes : function() { + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); + $('table.directory tr'). + removeClass('odd').filter(':visible:odd').addClass('odd'); + }, + + toggleVisibility : function(linkObj) { + const base = $(linkObj).attr('id'); + const summary = $('#'+base+'-summary'); + const content = $('#'+base+'-content'); + const trigger = $('#'+base+'-trigger'); + const src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.slideUp('fast'); + summary.show(); + $(linkObj).find('.arrowhead').addClass('closed').removeClass('opened'); + } else { + content.slideDown('fast'); + summary.hide(); + $(linkObj).find('.arrowhead').removeClass('closed').addClass('opened'); + } + return false; + }, + + toggleLevel : function(level) { + $('table.directory tr').each(function() { + const l = this.id.split('_').length-1; + const i = $('#img'+this.id.substring(3)); + const a = $('#arr'+this.id.substring(3)); + if (l
'); + // add vertical lines to other rows + $('span[class=lineno]').not(':eq(0)').append(''); + // add toggle controls to lines with fold divs + $('div[class=foldopen]').each(function() { + // extract specific id to use + const id = $(this).attr('id').replace('foldopen',''); + // extract start and end foldable fragment attributes + const start = $(this).attr('data-start'); + const end = $(this).attr('data-end'); + // replace normal fold span with controls for the first line of a foldable fragment + $(this).find('span[class=fold]:first').replaceWith(''); + // append div for folded (closed) representation + $(this).after(''); + // extract the first line from the "open" section to represent closed content + const line = $(this).children().first().clone(); + // remove any glow that might still be active on the original line + $(line).removeClass('glow'); + if (start) { + // if line already ends with a start marker (e.g. trailing {), remove it + $(line).html($(line).html().replace(new RegExp('\\s*'+start+'\\s*$','g'),'')); + } + // replace minus with plus symbol + $(line).find('span[class=fold]').addClass('plus').removeClass('minus'); + // append ellipsis + $(line).append(' '+start+''+end); + // insert constructed line into closed div + $('#foldclosed'+id).html(line); + }); + }, +}; +/* @license-end */ diff --git a/cpp-strings/html/files.html b/cpp-strings/html/files.html new file mode 100644 index 0000000..c18cd38 --- /dev/null +++ b/cpp-strings/html/files.html @@ -0,0 +1,107 @@ + + + + + + + +cpp-strings: File List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+ + +
 
cppstrings.h
+
+
+
+
+ + + + diff --git a/cpp-strings/html/files_dup.js b/cpp-strings/html/files_dup.js new file mode 100644 index 0000000..0546064 --- /dev/null +++ b/cpp-strings/html/files_dup.js @@ -0,0 +1,4 @@ +var files_dup = +[ + [ "cppstrings.h", "cppstrings_8h_source.html", null ] +]; \ No newline at end of file diff --git a/cpp-strings/html/functions.html b/cpp-strings/html/functions.html new file mode 100644 index 0000000..e99d012 --- /dev/null +++ b/cpp-strings/html/functions.html @@ -0,0 +1,245 @@ + + + + + + + +cpp-strings: Class Members + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- b -

+ + +

- c -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- i -

+ + +

- j -

+ + +

- l -

+ + +

- o -

+ + +

- p -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+ + +

- u -

+ + +

- z -

+ + +

- ~ -

+
+
+
+ + + + diff --git a/cpp-strings/html/functions_func.html b/cpp-strings/html/functions_func.html new file mode 100644 index 0000000..ebc9f5d --- /dev/null +++ b/cpp-strings/html/functions_func.html @@ -0,0 +1,245 @@ + + + + + + + +cpp-strings: Class Members - Functions + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all documented functions with links to the class documentation for each member:
+ +

- b -

+ + +

- c -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- i -

+ + +

- j -

+ + +

- l -

+ + +

- o -

+ + +

- p -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+ + +

- u -

+ + +

- z -

+ + +

- ~ -

+
+
+
+ + + + diff --git a/cpp-strings/html/hierarchy.html b/cpp-strings/html/hierarchy.html new file mode 100644 index 0000000..07a5967 --- /dev/null +++ b/cpp-strings/html/hierarchy.html @@ -0,0 +1,121 @@ + + + + + + + +cpp-strings: Class Hierarchy + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class Hierarchy
+
+
+
This inheritance list is sorted roughly, but not completely, alphabetically:
+
[detail level 123]
+ + + + + + + + + + + + + + + +
 Cstd::basic_string< Char >STL class
 Cpcs::CppStringT< char >
 Cpcs::CppStringT< wchar_t >
 Cpcs::CppStringT< CharT, TraitsT, AllocatorT >This is the templated base class for all CppString classes
 Cstd::exceptionSTL class
 Cstd::logic_errorSTL class
 Cpcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException
 Cpcs::Slice< IntT >Base class for slices, with start, stop and step specified values
 Cpcs::StartSlice< IntT >Base class for slices, with start, stop and step specified values
 Cpcs::StartStepSlice< IntT >Struct of slices with default step values
 Cpcs::StartStopSlice< IntT >Struct of slices with default start and stop values
 Cpcs::StepSlice< IntT >Struct of slices with default start and step values
 Cpcs::StopSlice< IntT >Struct of slices with default stop and step values
 Cpcs::StopStepSlice< IntT >Struct of slices with default stop values
 Cpcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTableThe internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate
+
+
+
+
+ + + + diff --git a/cpp-strings/html/hierarchy.js b/cpp-strings/html/hierarchy.js new file mode 100644 index 0000000..252d447 --- /dev/null +++ b/cpp-strings/html/hierarchy.js @@ -0,0 +1,22 @@ +var hierarchy = +[ + [ "std::basic_string< Char >", null, [ + [ "pcs::CppStringT< char >", "classpcs_1_1_cpp_string_t.html", null ], + [ "pcs::CppStringT< wchar_t >", "classpcs_1_1_cpp_string_t.html", null ], + [ "pcs::CppStringT< CharT, TraitsT, AllocatorT >", "classpcs_1_1_cpp_string_t.html", null ] + ] ], + [ "std::exception", null, [ + [ "std::logic_error", null, [ + [ "pcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException", "classpcs_1_1_cpp_string_t_1_1_not_found_exception.html", null ] + ] ] + ] ], + [ "pcs::Slice< IntT >", "classpcs_1_1_slice.html", [ + [ "pcs::StartSlice< IntT >", "structpcs_1_1_start_slice.html", null ], + [ "pcs::StartStepSlice< IntT >", "structpcs_1_1_start_step_slice.html", null ], + [ "pcs::StartStopSlice< IntT >", "structpcs_1_1_start_stop_slice.html", null ], + [ "pcs::StepSlice< IntT >", "structpcs_1_1_step_slice.html", null ], + [ "pcs::StopSlice< IntT >", "structpcs_1_1_stop_slice.html", null ], + [ "pcs::StopStepSlice< IntT >", "structpcs_1_1_stop_step_slice.html", null ] + ] ], + [ "pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html", null ] +]; \ No newline at end of file diff --git a/cpp-strings/html/index.html b/cpp-strings/html/index.html new file mode 100644 index 0000000..ecd46c6 --- /dev/null +++ b/cpp-strings/html/index.html @@ -0,0 +1,169 @@ + + + + + + + +cpp-strings: Library cpp-string + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Library cpp-string
+
+
+

+

license Latest release code_coverage tests

+

What if c++ strings where as easy to use as Python strings?

+

Let's just use c++ strings as are Python ones, with same API or as similar API as possible.
+ Library cpp-strings is fully templated. Just download header file cppstrings.h and put it anywhere in your project. Notice: all of its stuff is declared and defined in namespace pcs - which stands for P**ythonic **C++ **S**trings.

+
    +
  • The templated class pcs::CppStringT<> defines all constructors and methods that implement the equivalent of Python strings API.
    +
  • +
  • Class pcs::CppString specializes the templated class with char characters.
  • +
  • Class pcs::CppWString specializes the templated class with wchar_t characters.
  • +
+

cpp-strings is implemented with the currently most recent c++ standard available with gcc, clang and msvc c++ compilers, i.e. standard c++20.

+
    +
  • directory cpp-strings contains the header file cppstring.h.
    + This is the header file to include in your projects.
  • +
  • directory cpp-strings-tests contains the unit test file cpp-strings-tests.cpp
    + This file tests all the library stuff. It is a valuable code container with so many examples of use of the library, the classes, the methods and the functions it defines.
  • +
+

The code has been developed using VS2022 IDE. As such, unitary tests have been coded using Microsoft Visual Studio Cpp Unit Test Framework. The related VS project is provided with this library.

+

Notice: no clang, gcc or msvc specific declarations or goodies have been use to code library cpp-strings. It should then be compilable with any of these compilers. To be able to use it with your project, just ensure that the c++ standard used with you favorite compiler is c++20:

    +
  • options -std=c++20 or -std=c++latest for clang and gcc (v. 10 and above),
    + or option -std=c++2a for clang and gcc (v. 9 and earlier);
  • +
  • options /std=c++20 or /std=c++latest for Visual Studio 2019 and later.
  • +
+

If you want to run the unitary tests, well, use the last version of Visual Studio (i.e. VS 2022, by July 2025). The Community free version will truly be fine.
+ The vcproject associated with the unit tests in cpp-strings is already configured to use the option flag /std:c++latest since the implemented code uses a very few but very useful c++23 goodies.

+
+

+License

+
Library cpp-strings
+"What if c++ strings where as easy to use as Python strings?"
+
+Copyright (C) 2023-2025 Philippe Schmouker
+contact - ph (dot) schmouker (at) gmail (dot) com
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation,  either version 3  of the License,  or
+(at your option) any later version.
+
+This program is distributed in the hope  that  it  will  be  useful,
+but  WITHOUT  ANY  WARRANTY;  without  even  the implied warranty of
+MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE.  See  the
+GNU General Public License for more details.
+
+You should have received a copy  of  the  GNU General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+

+

+Intro

+

The creation of this library has been started with the aim at easing the use of strings in c++. Other projects exist, even aiming also to implement a Python-like strings API, but the only ones we have found were either started but not completed, or were not implementing the whole Python API.

+

So, we started to work on Pythonic c++ strings. Library cpp-strings is now ready. It fully implements the Python API (even with a c++ implementation of slices) and it is fully tested with unitary tests.

+

The implementation of library cpp-strings is fully templated and is contained into a single header file: cpp-strings/cppstrings.h. To take a whole benefit of it, just add this header file to your project and include it in your own files. It very fastly compiles. That's all!

+

Header file cpp-strings/cppstrings.h defines:

    +
  • templated class template<typename CharT> class pcs::CppStringT which implements all the stuff about pythonic c++ strings. It inherits from c++ STL class std::basic_string<CharT>, so it gets access to all c++ STL methods, functions and goodies about strings;
  • +
  • this class is specialized by using pcs::CppString> = pcs::CppStringT<char> for pythonic c++ strings based on char characters;
  • +
  • it is also specialized by using pcs::CppWString> = pcs::CppStringT<wchar_t> for pythonic c++ strings based on wchar_t characters.
  • +
+

The unitary tests are provided in directory cpp-strings-tests/. File cpp-strings-tests.cpp contains the related code. They has been coded using VS2022 IDE and as such, are using the Microsoft Visual Studio Cpp Unit Test Framework. The related VS project can be found in the same directory. It is already configured to create code for Release as well as for Debug configurations, and for 32-bits or 64-bits platforms at your choice.
+ This .cpp file is a great place to see cpp-strings code in action. Each structure, class, method, litteral operator and function being unitary tested, you should find there many examples of their use for all cpp-strings stuff.

+
+

+Latest Release - Release 1.0 (1.0.0.224) 2025/07

+

The coding of this project started by March 2023 and had been put in standby mode for some months. The very first release is now availble (since July 2025), as Release 1.0.

+

This release has been fully tested. It implements all Python strings API but one feature (see below). Python slices are implemented via c++ operator() as declared and defined in the templated class pcs::CppStringT<>. Python slices have next specific notation: [start : stop : step] and allow the running through range [start, stop) (notice: stop is excluded from the range) step by step. Operator (start, stop, step) acts the same way while running through the content of c++ strings.

+
+ +
+
+
+ + + + diff --git a/cpp-strings/html/index.js b/cpp-strings/html/index.js new file mode 100644 index 0000000..d7dba3d --- /dev/null +++ b/cpp-strings/html/index.js @@ -0,0 +1,6 @@ +var index = +[ + [ "License", "index.html#autotoc_md2", null ], + [ "Intro", "index.html#autotoc_md3", null ], + [ "Latest Release - Release 1.0 (1.0.0.224) 2025/07", "index.html#autotoc_md5", null ] +]; \ No newline at end of file diff --git a/cpp-strings/html/jquery.js b/cpp-strings/html/jquery.js new file mode 100644 index 0000000..875ada7 --- /dev/null +++ b/cpp-strings/html/jquery.js @@ -0,0 +1,204 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e} +var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp( +"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType +}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c +)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){ +return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll( +":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id") +)&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push( +"\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test( +a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null, +null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne +).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for( +var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n; +return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0, +r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r] +,C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each( +function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r, +"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})} +),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each( +"blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=y(e||this.defaultElement||this)[0],this.element=y(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=y(),this.hoverable=y(),this.focusable=y(),this.classesElementLookup={},e!==this&&(y.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t +){t.target===e&&this.destroy()}}),this.document=y(e.style?e.ownerDocument:e.document||e),this.window=y(this.document[0].defaultView||this.document[0].parentWindow)),this.options=y.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:y.noop,_create:y.noop,_init:y.noop,destroy:function(){var i=this;this._destroy(),y.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:y.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return y.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t +]=y.widget.extend({},this.options[t]),n=0;n
"),i=e.children()[0];return y("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i}, +getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthx(D(s),D(n))?o.important="horizontal":o.important="vertical",p.using.call(this,t,o)}),h.offset(y.extend(l,{using:t}))})},y.ui.position={fit:{left:function(t,e){var i=e.within, +s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,h=s-o,a=o+e.collisionWidth-n-s;e.collisionWidth>n?0n?0=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),y.ui.plugin={add:function(t,e,i){var s,n=y.ui[t].prototype;for(s in i)n.plugins[s]=n.plugins[s]||[],n.plugins[s].push([e,i[s]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;n").css({overflow:"hidden",position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})), +this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,t={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(t),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(t),this._proportionallyResize()),this._setupHandles(),e.autoHide&&y(this.element).on("mouseenter",function(){e.disabled||(i._removeClass("ui-resizable-autohide"),i._handles.show())}).on("mouseleave",function(){e.disabled||i.resizing||(i._addClass("ui-resizable-autohide"),i._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy(),this._addedHandles.remove();function t(t){y(t +).removeData("resizable").removeData("ui-resizable").off(".resizable")}var e;return this.elementIsWrapper&&(t(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;case"aspectRatio":this._aspectRatio=!!e}},_setupHandles:function(){var t,e,i,s,n,o=this.options,h=this;if(this.handles=o.handles||(y(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=y(),this._addedHandles=y(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),i=this.handles.split( +","),this.handles={},e=0;e"),this._addClass(n,"ui-resizable-handle "+s),n.css({zIndex:o.zIndex}),this.handles[t]=".ui-resizable-"+t,this.element.children(this.handles[t]).length||(this.element.append(n),this._addedHandles=this._addedHandles.add(n));this._renderAxis=function(t){var e,i,s;for(e in t=t||this.element,this.handles)this.handles[e].constructor===String?this.handles[e]=this.element.children(this.handles[e]).first().show():(this.handles[e].jquery||this.handles[e].nodeType)&&(this.handles[e]=y(this.handles[e]),this._on(this.handles[e],{mousedown:h._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(i=y(this.handles[e],this.element),s=/sw|ne|nw|se|n|s/.test(e)?i.outerHeight():i.outerWidth(),i=["padding",/ne|nw|n/.test(e)?"Top":/se|sw|s/.test(e)?"Bottom":/^e$/.test(e)?"Right":"Left"].join(""),t.css(i,s),this._proportionallyResize()),this._handles=this._handles.add( +this.handles[e])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){h.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),h.axis=n&&n[1]?n[1]:"se")}),o.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._addedHandles.remove()},_mouseCapture:function(t){var e,i,s=!1;for(e in this.handles)(i=y(this.handles[e])[0])!==t.target&&!y.contains(i,t.target)||(s=!0);return!this.options.disabled&&s},_mouseStart:function(t){var e,i,s=this.options,n=this.element;return this.resizing=!0,this._renderProxy(),e=this._num(this.helper.css("left")),i=this._num(this.helper.css("top")),s.containment&&(e+=y(s.containment).scrollLeft()||0,i+=y(s.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:e,top:i},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{ +width:n.width(),height:n.height()},this.originalSize=this._helper?{width:n.outerWidth(),height:n.outerHeight()}:{width:n.width(),height:n.height()},this.sizeDiff={width:n.outerWidth()-n.width(),height:n.outerHeight()-n.height()},this.originalPosition={left:e,top:i},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof s.aspectRatio?s.aspectRatio:this.originalSize.width/this.originalSize.height||1,s=y(".ui-resizable-"+this.axis).css("cursor"),y("body").css("cursor","auto"===s?this.axis+"-resize":s),this._addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var e=this.originalMousePosition,i=this.axis,s=t.pageX-e.left||0,e=t.pageY-e.top||0,i=this._change[i];return this._updatePrevProperties(),i&&(e=i.apply(this,[t,s,e]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(e=this._updateRatio(e,t)),e=this._respectSize(e,t),this._updateCache(e),this._propagate("resize",t),e=this._applyChanges(), +!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),y.isEmptyObject(e)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges())),!1},_mouseStop:function(t){this.resizing=!1;var e,i,s,n=this.options,o=this;return this._helper&&(s=(e=(i=this._proportionallyResizeElements).length&&/textarea/i.test(i[0].nodeName))&&this._hasScroll(i[0],"left")?0:o.sizeDiff.height,i=e?0:o.sizeDiff.width,e={width:o.helper.width()-i,height:o.helper.height()-s},i=parseFloat(o.element.css("left"))+(o.position.left-o.originalPosition.left)||null,s=parseFloat(o.element.css("top"))+(o.position.top-o.originalPosition.top)||null,n.animate||this.element.css(y.extend(e,{top:s,left:i})),o.helper.height(o.size.height),o.helper.width(o.size.width),this._helper&&!n.animate&&this._proportionallyResize()),y("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){ +this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s=this.options,n={minWidth:this._isNumber(s.minWidth)?s.minWidth:0,maxWidth:this._isNumber(s.maxWidth)?s.maxWidth:1/0,minHeight:this._isNumber(s.minHeight)?s.minHeight:0,maxHeight:this._isNumber(s.maxHeight)?s.maxHeight:1/0};(this._aspectRatio||t)&&(e=n.minHeight*this.aspectRatio,i=n.minWidth/this.aspectRatio,s=n.maxHeight*this.aspectRatio,t=n.maxWidth/this.aspectRatio,e>n.minWidth&&(n.minWidth=e),i>n.minHeight&&(n.minHeight=i),st.width,h=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,a=this.originalPosition.left+this.originalSize.width,r=this.originalPosition.top+this.originalSize.height +,l=/sw|nw|w/.test(i),i=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),h&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=a-e.minWidth),s&&l&&(t.left=a-e.maxWidth),h&&i&&(t.top=r-e.minHeight),n&&i&&(t.top=r-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];e<4;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;e").css({overflow:"hidden"}),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++e.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize;return{left:this.originalPosition.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize;return{top:this.originalPosition.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(t,e,i){return y.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},sw:function(t,e, +i){return y.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,e,i]))},ne:function(t,e,i){return y.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},nw:function(t,e,i){return y.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,e,i]))}},_propagate:function(t,e){y.ui.plugin.call(this,t,[e,this.ui()]),"resize"!==t&&this._trigger(t,e,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),y.ui.plugin.add("resizable","animate",{stop:function(e){var i=y(this).resizable("instance"),t=i.options,s=i._proportionallyResizeElements,n=s.length&&/textarea/i.test(s[0].nodeName),o=n&&i._hasScroll(s[0],"left")?0:i.sizeDiff.height,h=n?0:i.sizeDiff.width,n={width:i.size.width-h,height:i.size.height-o},h=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left +)||null,o=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(y.extend(n,o&&h?{top:o,left:h}:{}),{duration:t.animateDuration,easing:t.animateEasing,step:function(){var t={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};s&&s.length&&y(s[0]).css({width:t.width,height:t.height}),i._updateCache(t),i._propagate("resize",e)}})}}),y.ui.plugin.add("resizable","containment",{start:function(){var i,s,n=y(this).resizable("instance"),t=n.options,e=n.element,o=t.containment,h=o instanceof y?o.get(0):/parent/.test(o)?e.parent().get(0):o;h&&(n.containerElement=y(h),/document/.test(o)||o===document?(n.containerOffset={left:0,top:0},n.containerPosition={left:0,top:0},n.parentData={element:y(document),left:0,top:0,width:y(document).width(),height:y(document).height()||document.body.parentNode.scrollHeight}):(i=y(h),s=[],y(["Top","Right","Left","Bottom"]).each(function(t,e +){s[t]=n._num(i.css("padding"+e))}),n.containerOffset=i.offset(),n.containerPosition=i.position(),n.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},t=n.containerOffset,e=n.containerSize.height,o=n.containerSize.width,o=n._hasScroll(h,"left")?h.scrollWidth:o,e=n._hasScroll(h)?h.scrollHeight:e,n.parentData={element:h,left:t.left,top:t.top,width:o,height:e}))},resize:function(t){var e=y(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.position,o=e._aspectRatio||t.shiftKey,h={top:0,left:0},a=e.containerElement,t=!0;a[0]!==document&&/static/.test(a.css("position"))&&(h=s),n.left<(e._helper?s.left:0)&&(e.size.width=e.size.width+(e._helper?e.position.left-s.left:e.position.left-h.left),o&&(e.size.height=e.size.width/e.aspectRatio,t=!1),e.position.left=i.helper?s.left:0),n.top<(e._helper?s.top:0)&&(e.size.height=e.size.height+(e._helper?e.position.top-s.top:e.position.top),o&&(e.size.width=e.size.height*e.aspectRatio,t=!1),e.position.top=e._helper?s.top:0), +i=e.containerElement.get(0)===e.element.parent().get(0),n=/relative|absolute/.test(e.containerElement.css("position")),i&&n?(e.offset.left=e.parentData.left+e.position.left,e.offset.top=e.parentData.top+e.position.top):(e.offset.left=e.element.offset().left,e.offset.top=e.element.offset().top),n=Math.abs(e.sizeDiff.width+(e._helper?e.offset.left-h.left:e.offset.left-s.left)),s=Math.abs(e.sizeDiff.height+(e._helper?e.offset.top-h.top:e.offset.top-s.top)),n+e.size.width>=e.parentData.width&&(e.size.width=e.parentData.width-n,o&&(e.size.height=e.size.width/e.aspectRatio,t=!1)),s+e.size.height>=e.parentData.height&&(e.size.height=e.parentData.height-s,o&&(e.size.width=e.size.height*e.aspectRatio,t=!1)),t||(e.position.left=e.prevPosition.left,e.position.top=e.prevPosition.top,e.size.width=e.prevSize.width,e.size.height=e.prevSize.height)},stop:function(){var t=y(this).resizable("instance"),e=t.options,i=t.containerOffset,s=t.containerPosition,n=t.containerElement,o=y(t.helper),h=o.offset(),a=o.outerWidth( +)-t.sizeDiff.width,o=o.outerHeight()-t.sizeDiff.height;t._helper&&!e.animate&&/relative/.test(n.css("position"))&&y(this).css({left:h.left-s.left-i.left,width:a,height:o}),t._helper&&!e.animate&&/static/.test(n.css("position"))&&y(this).css({left:h.left-s.left-i.left,width:a,height:o})}}),y.ui.plugin.add("resizable","alsoResize",{start:function(){var t=y(this).resizable("instance").options;y(t.alsoResize).each(function(){var t=y(this);t.data("ui-resizable-alsoresize",{width:parseFloat(t.width()),height:parseFloat(t.height()),left:parseFloat(t.css("left")),top:parseFloat(t.css("top"))})})},resize:function(t,i){var e=y(this).resizable("instance"),s=e.options,n=e.originalSize,o=e.originalPosition,h={height:e.size.height-n.height||0,width:e.size.width-n.width||0,top:e.position.top-o.top||0,left:e.position.left-o.left||0};y(s.alsoResize).each(function(){var t=y(this),s=y(this).data("ui-resizable-alsoresize"),n={},e=t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];y.each(e, +function(t,e){var i=(s[e]||0)+(h[e]||0);i&&0<=i&&(n[e]=i||null)}),t.css(n)})},stop:function(){y(this).removeData("ui-resizable-alsoresize")}}),y.ui.plugin.add("resizable","ghost",{start:function(){var t=y(this).resizable("instance"),e=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}),t._addClass(t.ghost,"ui-resizable-ghost"),!1!==y.uiBackCompat&&"string"==typeof t.options.ghost&&t.ghost.addClass(this.options.ghost),t.ghost.appendTo(t.helper)},resize:function(){var t=y(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=y(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),y.ui.plugin.add("resizable","grid",{resize:function(){var t,e=y(this).resizable("instance"),i=e.options,s=e.size,n=e.originalSize,o=e.originalPosition,h=e.axis,a="number"==typeof i.grid?[i.grid,i.grid]:i.grid,r=a[0 +]||1,l=a[1]||1,u=Math.round((s.width-n.width)/r)*r,p=Math.round((s.height-n.height)/l)*l,d=n.width+u,c=n.height+p,f=i.maxWidth&&i.maxWidthd,s=i.minHeight&&i.minHeight>c;i.grid=a,m&&(d+=r),s&&(c+=l),f&&(d-=r),g&&(c-=l),/^(se|s|e)$/.test(h)?(e.size.width=d,e.size.height=c):/^(ne)$/.test(h)?(e.size.width=d,e.size.height=c,e.position.top=o.top-p):/^(sw)$/.test(h)?(e.size.width=d,e.size.height=c,e.position.left=o.left-u):((c-l<=0||d-r<=0)&&(t=e._getPaddingPlusBorderDimensions(this)),0=f[g]?0:Math.min(f[g],n));!a&&1-1){ +targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se", +"n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if( +session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)} +closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if( +session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE, +function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset); +tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList, +finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight())); +return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")} +function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(), +elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight, +viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.topviewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.leftviewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b, +"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); +/*! SmartMenus jQuery Plugin - v1.1.0 - September 17, 2017 + * http://www.smartmenus.org/ + * Copyright Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(require("jquery")):t(jQuery)})(function($){function initMouseDetection(t){var e=".smartmenus_mouse";if(mouseDetectionEnabled||t)mouseDetectionEnabled&&t&&($(document).off(e),mouseDetectionEnabled=!1);else{var i=!0,s=null,o={mousemove:function(t){var e={x:t.pageX,y:t.pageY,timeStamp:(new Date).getTime()};if(s){var o=Math.abs(s.x-e.x),a=Math.abs(s.y-e.y);if((o>0||a>0)&&2>=o&&2>=a&&300>=e.timeStamp-s.timeStamp&&(mouse=!0,i)){var n=$(t.target).closest("a");n.is("a")&&$.each(menuTrees,function(){return $.contains(this.$root[0],n[0])?(this.itemEnter({currentTarget:n[0]}),!1):void 0}),i=!1}}s=e}};o[touchEvents?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut"]=function(t){isTouchEvent(t.originalEvent)&&(mouse=!1)},$(document).on(getEventsNS(o,e)), +mouseDetectionEnabled=!0}}function isTouchEvent(t){return!/^(4|mouse)$/.test(t.pointerType)}function getEventsNS(t,e){e||(e="");var i={};for(var s in t)i[s.split(" ").join(e+" ")+e]=t[s];return i}var menuTrees=[],mouse=!1,touchEvents="ontouchstart"in window,mouseDetectionEnabled=!1,requestAnimationFrame=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},cancelAnimationFrame=window.cancelAnimationFrame||function(t){clearTimeout(t)},canAnimate=!!$.fn.animate;return $.SmartMenus=function(t,e){this.$root=$(t),this.opts=e,this.rootId="",this.accessIdPrefix="",this.$subArrow=null,this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.idInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.$touchScrollingSub=null,this.cssTransforms3d="perspective"in t.style||"webkitPerspective"in t.style,this.wasCollapsible=!1,this.init()},$.extend( +$.SmartMenus,{hideAll:function(){$.each(menuTrees,function(){this.menuHideAll()})},destroy:function(){for(;menuTrees.length;)menuTrees[0].destroy();initMouseDetection(!0)},prototype:{init:function(t){var e=this;if(!t){menuTrees.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.accessIdPrefix="sm-"+this.rootId+"-",this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var i=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).on(getEventsNS({"mouseover focusin":$.proxy(this.rootOver,this),"mouseout focusout":$.proxy(this.rootOut,this),keydown:$.proxy(this.rootKeyDown,this)},i)).on(getEventsNS({mouseenter:$.proxy(this.itemEnter,this),mouseleave:$.proxy(this.itemLeave,this),mousedown:$.proxy(this.itemDown,this),focus:$.proxy(this.itemFocus,this),blur:$.proxy(this.itemBlur,this),click:$.proxy(this.itemClick,this)},i),"a"),i+=this.rootId,this.opts.hideOnClick&&$(document).on(getEventsNS({touchstart:$.proxy( +this.docTouchStart,this),touchmove:$.proxy(this.docTouchMove,this),touchend:$.proxy(this.docTouchEnd,this),click:$.proxy(this.docClick,this)},i)),$(window).on(getEventsNS({"resize orientationchange":$.proxy(this.winResize,this)},i)),this.opts.subIndicators&&(this.$subArrow=$("").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),initMouseDetection()}if(this.$firstSub=this.$root.find("ul").each(function(){e.menuInit($(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var s=/(index|default)\.[^#\?\/]*/i,o=/#.*/,a=window.location.href.replace(s,""),n=a.replace(o,"");this.$root.find("a").each(function(){var t=this.href.replace(s,""),i=$(this);(t==a||t==n)&&(i.addClass("current"),e.opts.markCurrentTree&&i.parentsUntil("[data-smartmenus-id]","ul").each(function(){$(this).dataSM("parent-a").addClass("current")}))})}this.wasCollapsible=this.isCollapsible()},destroy:function(t){if(!t){var e=".smartmenus";this.$root.removeData( +"smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").off(e),e+=this.rootId,$(document).off(e),$(window).off(e),this.opts.subIndicators&&(this.$subArrow=null)}this.menuHideAll();var i=this;this.$root.find("ul").each(function(){var t=$(this);t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.dataSM("shown-before")&&((i.opts.subMenusMinWidth||i.opts.subMenusMaxWidth)&&t.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),0==(t.attr("id")||"").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded"),this.$root.find("a.has-submenu").each(function(){var t=$(this);0==t.attr("id" +).indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),t||(this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),menuTrees.splice($.inArray(this,menuTrees),1))},disable:function(t){if(!this.disabled){if(this.menuHideAll(),!t&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=$('
').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(t){return this.$touchScrollingSub?( +this.$touchScrollingSub=null,void 0):((this.visibleSubMenus.length&&!$.contains(this.$root[0],t.target)||$(t.target).closest("a").length)&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&$.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var t=this;this.hideTimeout=setTimeout(function(){t.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var e=t.originalEvent.touches[0];this.lastTouch.x2=e.pageX,this.lastTouch.y2=e.pageY}},docTouchStart:function(t){var e=t.originalEvent.touches[0];this.lastTouch={x1:e.pageX,y1:e.pageY,target:e.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(t){for( +var e=$(t).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,e){var i;"none"==t.css("display")&&(i={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(e?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=e?t[0].offsetHeight:t[0].offsetWidth),i&&t.hide().css(i),o},getStartZIndex:function(t){var e=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(e)&&(e=parseInt(this.$root.css("z-index"))),isNaN(e)?1:e},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var e=t?"Height":"Width",i=document.documentElement["client"+e],s=window["inner"+e];return s&&(i=Math.min(i,s)),i},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){ +return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"inline"!=this.$firstLink.css("display")},isFixed:function(){var t="fixed"==this.$root.css("position");return t||this.$root.parentsUntil("body").each(function(){return"fixed"==$(this).css("position")?(t=!0,!1):void 0}),t},isLinkInMegaMenu:function(t){return $(this.getClosestMenu(t[0])).hasClass("mega-menu")},isTouchMode:function(){return!mouse||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(t,e){var i=t.closest("ul"),s=i.dataSM("level");if(s>1&&(!this.activatedItems[s-2]||this.activatedItems[s-2][0]!=i.dataSM("parent-a")[0])){var o=this;$(i.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(i).each(function(){o.itemActivate($(this).dataSM("parent-a"))})}if(( +!this.isCollapsible()||e)&&this.menuHideSubMenus(this.activatedItems[s-1]&&this.activatedItems[s-1][0]==t[0]?s:s-1),this.activatedItems[s-1]=t,this.$root.triggerHandler("activate.smapi",t[0])!==!1){var a=t.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==e.closest("ul")[0])return this.$touchScrollingSub=null,t.stopPropagation(),!1;if(this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var i=$(t.target).is(".sub-arrow"),s=e.dataSM("sub"),o=s?2==s.dataSM("level"):!1,a=this.isCollapsible(),n=/toggle$/.test(this.opts.collapsibleBehavior),r=/link$/.test(this.opts.collapsibleBehavior),h=/^accordion/.test(this.opts.collapsibleBehavior);if(s&&!s.is(":visible")){if((!r||!a||i)&&(this.opts.showOnClick&&o&&( +this.clickActivated=!0),this.itemActivate(e,h),s.is(":visible")))return this.focusActivated=!0,!1}else if(a&&(n||i))return this.itemActivate(e,h),this.menuHide(s),n&&(this.focusActivated=!1),!1;return this.opts.showOnClick&&o||e.hasClass("disabled")||this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}},itemDown:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var i=this;this.showTimeout=setTimeout(function(){i.itemActivate(e)},this.opts.showOnClick&&1==e.closest("ul").dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(!this.focusActivated||this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0 +]||this.itemActivate(e,!0),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(canAnimate&&t.stop(!0,!0),"none"!=t.css("display"))){var e=function(){t.css("z-index","")};this.isCollapsible()?canAnimate&&this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,e):t.hide(this.opts.collapsibleHideDuration,e):canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,t,e):t.hide(this.opts.hideDuration,e),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).off(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass( +"highlighted").attr("aria-expanded","false"),t.attr({"aria-expanded":"false","aria-hidden":"true"});var i=t.dataSM("level");this.activatedItems.splice(i-1,1),this.visibleSubMenus.splice($.inArray(t,this.visibleSubMenus),1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);for(var t=this.opts.isPopup?1:0,e=this.visibleSubMenus.length-1;e>=t;e--)this.menuHide(this.visibleSubMenus[e]);this.opts.isPopup&&(canAnimate&&this.$root.stop(!0,!0),this.$root.is(":visible")&&(canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration))),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(t){for(var e=this.activatedItems.length-1;e>=t;e--){var i=this.activatedItems[e].dataSM("sub");i&&this.menuHide(i)}},menuInit:function(t){if(!t.dataSM("in-mega")){ +t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var e=2,i=t[0];(i=i.parentNode.parentNode)!=this.$root[0];)e++;var s=t.prevAll("a").eq(-1);s.length||(s=t.prevAll().find("a").eq(-1)),s.addClass("has-submenu").dataSM("sub",t),t.dataSM("parent-a",s).dataSM("level",e).parent().dataSM("sub",t);var o=s.attr("id")||this.accessIdPrefix+ ++this.idInc,a=t.attr("id")||this.accessIdPrefix+ ++this.idInc;s.attr({id:o,"aria-haspopup":"true","aria-controls":a,"aria-expanded":"false"}),t.attr({id:a,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"}),this.opts.subIndicators&&s[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(t){var e,i,s=t.dataSM("parent-a"),o=s.closest("li"),a=o.parent(),n=t.dataSM("level"),r=this.getWidth(t),h=this.getHeight(t),u=s.offset(),l=u.left,c=u.top,d=this.getWidth(s),m=this.getHeight(s),p=$(window),f=p.scrollLeft(),v=p.scrollTop(),b=this.getViewportWidth(),S=this.getViewportHeight(),g=a.parent().is("[data-sm-horizontal-sub]" +)||2==n&&!a.hasClass("sm-vertical"),M=this.opts.rightToLeftSubMenus&&!o.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&o.is("[data-sm-reverse]"),w=2==n?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,T=2==n?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(g?(e=M?d-r-w:w,i=this.opts.bottomToTopSubMenus?-h-T:m+T):(e=M?w-r:d-w,i=this.opts.bottomToTopSubMenus?m-T-h:T),this.opts.keepInViewport){var y=l+e,I=c+i;if(M&&f>y?e=g?f-y+e:d-w:!M&&y+r>f+b&&(e=g?f+b-r-y+e:w-r),g||(S>h&&I+h>v+S?i+=v+S-h-I:(h>=S||v>I)&&(i+=v-I)),g&&(I+h>v+S+.49||v>I)||!g&&h>S+.49){var x=this;t.dataSM("scroll-arrows")||t.dataSM("scroll-arrows",$([$('')[0],$('')[0]]).on({mouseenter:function(){t.dataSM("scroll").up=$(this).hasClass("scroll-up"),x.menuScroll(t)},mouseleave:function(e){x.menuScrollStop(t),x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(t){ +t.preventDefault()}}).insertAfter(t));var A=".smartmenus_scroll";if(t.dataSM("scroll",{y:this.cssTransforms3d?0:i-m,step:1,itemH:m,subH:h,arrowDownH:this.getHeight(t.dataSM("scroll-arrows").eq(1))}).on(getEventsNS({mouseover:function(e){x.menuScrollOver(t,e)},mouseout:function(e){x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(e){x.menuScrollMousewheel(t,e)}},A)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(t.css("border-left-width"))||0),width:r-(parseInt(t.css("border-left-width"))||0)-(parseInt(t.css("border-right-width"))||0),zIndex:t.css("z-index")}).eq(g&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()){var C={};C[touchEvents?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp"]=function(e){x.menuScrollTouch(t,e)},t.css({"touch-action":"none","-ms-touch-action":"none"}).on(getEventsNS(C,A))}}}t.css({top:"auto",left:"0",marginLeft:e,marginTop:i-m})},menuScroll:function(t,e,i){var s,o=t.dataSM("scroll"), +a=t.dataSM("scroll-arrows"),n=o.up?o.upEnd:o.downEnd;if(!e&&o.momentum){if(o.momentum*=.92,s=o.momentum,.5>s)return this.menuScrollStop(t),void 0}else s=i||(e||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var r=t.dataSM("level");if(this.activatedItems[r-1]&&this.activatedItems[r-1].dataSM("sub")&&this.activatedItems[r-1].dataSM("sub").is(":visible")&&this.menuHideSubMenus(r-1),o.y=o.up&&o.y>=n||!o.up&&n>=o.y?o.y:Math.abs(n-o.y)>s?o.y+(o.up?s:-s):n,t.css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+o.y+"px, 0)",transform:"translate3d(0, "+o.y+"px, 0)"}:{marginTop:o.y}),mouse&&(o.up&&o.y>o.downEnd||!o.up&&o.y0;t.dataSM("scroll-arrows").eq(i?0:1).is(":visible")&&(t.dataSM("scroll").up=i,this.menuScroll(t,!0))}e.preventDefault()},menuScrollOut:function(t,e){mouse&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(t[0]==e.relatedTarget||$.contains(t[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==t[0]||t.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,e){if(mouse&&!/^scroll-(up|down)/.test(e.target.className)&&this.getClosestMenu(e.target)==t[0]){this.menuScrollRefreshData(t);var i=t.dataSM("scroll"),s=$(window).scrollTop()-t.dataSM("parent-a").offset().top-i.itemH;t.dataSM("scroll-arrows").eq(0).css("margin-top",s).end().eq(1).css("margin-top",s+this.getViewportHeight()-i.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(t){var e=t.dataSM("scroll"),i=$(window).scrollTop()-t.dataSM("parent-a").offset().top-e.itemH;this.cssTransforms3d&&(i=-(parseFloat(t.css("margin-top"))-i)),$.extend(e,{upEnd:i, +downEnd:i+this.getViewportHeight()-e.subH})},menuScrollStop:function(t){return this.scrollTimeout?(cancelAnimationFrame(this.scrollTimeout),this.scrollTimeout=0,t.dataSM("scroll").step=1,!0):void 0},menuScrollTouch:function(t,e){if(e=e.originalEvent,isTouchEvent(e)){var i=this.getTouchPoint(e);if(this.getClosestMenu(i.target)==t[0]){var s=t.dataSM("scroll");if(/(start|down)$/i.test(e.type))this.menuScrollStop(t)?(e.preventDefault(),this.$touchScrollingSub=t):this.$touchScrollingSub=null,this.menuScrollRefreshData(t),$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp});else if(/move$/i.test(e.type)){var o=void 0!==s.touchY?s.touchY:s.touchStartY;if(void 0!==o&&o!=i.pageY){this.$touchScrollingSub=t;var a=i.pageY>o;void 0!==s.up&&s.up!=a&&$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp}),$.extend(s,{up:a,touchY:i.pageY}),this.menuScroll(t,!0,Math.abs(i.pageY-o))}e.preventDefault()}else void 0!==s.touchY&&((s.momentum=15*Math.pow(Math.abs(i.pageY-s.touchStartY)/(e.timeStamp-s.touchStartTime),2) +)&&(this.menuScrollStop(t),this.menuScroll(t),e.preventDefault()),delete s.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(t.dataSM("shown-before",!0),canAnimate&&t.stop(!0,!0),!t.is(":visible"))){var e=t.dataSM("parent-a"),i=this.isCollapsible();if((this.opts.keepHighlighted||i)&&e.addClass("highlighted"),i)t.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""});else{if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var s=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),s>this.getWidth(t +)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t)}var o=function(){t.css("overflow","")};i?canAnimate&&this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,o):t.show(this.opts.collapsibleShowDuration,o):canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,t,o):t.show(this.opts.showDuration,o),e.attr("aria-expanded","true"),t.attr({"aria-expanded":"true","aria-hidden":"false"}),this.visibleSubMenus.push(t),this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,e){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.$root.dataSM("shown-before",!0), +canAnimate&&this.$root.stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:e});var i=this,s=function(){i.$root.css("overflow","")};canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(!0),this.init(!0)},rootKeyDown:function(t){if(this.handleEvents())switch(t.keyCode){case 27:var e=this.activatedItems[0];if(e){this.menuHideAll(),e[0].focus();var i=e.dataSM("sub");i&&this.menuHide(i)}break;case 32:var s=$(t.target);if(s.is("a")&&this.handleItemEvents(s)){var i=s.dataSM("sub");i&&!i.is(":visible")&&(this.itemClick({currentTarget:t.target}),t.preventDefault())}}},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},this.opts.hideTimeout)}}, +rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents()){if(!("onorientationchange"in window)||"orientationchange"==t.type){var e=this.isCollapsible();this.wasCollapsible&&e||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll()),this.wasCollapsible=e}}else if(this.$disableOverlay){var i=this.$root.offset();this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),$.fn.dataSM=function(t,e){return e?this.data(t+"_smartmenus",e):this.data(t+"_smartmenus")},$.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},$.fn.smartmenus=function(options){if("string"==typeof options){var args=arguments,method=options;return Array.prototype.shift.call(args),this.each(function(){var t=$(this).data("smartmenus");t&&t[method]&&t[method].apply(t,args)})} +return this.each(function(){var dataOpts=$(this).data("sm-options")||null;if(dataOpts)try{dataOpts=eval("("+dataOpts+")")}catch(e){dataOpts=null,alert('ERROR\n\nSmartMenus jQuery init:\nInvalid "data-sm-options" attribute value syntax.')}new $.SmartMenus(this,$.extend({},$.fn.smartmenus.defaults,options,dataOpts))})},$.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"append",subIndicatorsText:"",scrollStep:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,e){t.fadeOut(200,e)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,e){t.slideDown(200,e)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,e){t.slideUp(200,e)},showOnClick:!1,hideOnClick:!0,noMouseOver:!1,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1, +bottomToTopSubMenus:!1,collapsibleBehavior:"default"},$}); diff --git a/cpp-strings/html/menu.js b/cpp-strings/html/menu.js new file mode 100644 index 0000000..15f9c52 --- /dev/null +++ b/cpp-strings/html/menu.js @@ -0,0 +1,131 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ +function initMenu(relPath,searchEnabled,serverSide,searchPage,search,treeview) { + function makeTree(data,relPath) { + let result=''; + if ('children' in data) { + result+='
    '; + for (let i in data.children) { + let url; + const link = data.children[i].url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + } else { + url = relPath+link; + } + result+='
  • '+ + data.children[i].text+''+ + makeTree(data.children[i],relPath)+'
  • '; + } + result+='
'; + } + return result; + } + let searchBoxHtml; + if (searchEnabled) { + if (serverSide) { + searchBoxHtml='
'+ + '
'+ + '
'+ + ''+ + '
'+ + '
'+ + '
'+ + '
'; + } else { + searchBoxHtml='
'+ + ''+ + ''+ + ''+ + ''+ + ''+ + '
'+ + '
'+ + '
'; + } + } + + $('#main-nav').before('
'+ + ''+ + ''+ + '
'); + $('#main-nav').append(makeTree(menudata,relPath)); + $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu'); + $('#main-menu').append('
  • '); + const $mainMenuState = $('#main-menu-state'); + let prevWidth = 0; + if ($mainMenuState.length) { + const initResizableIfExists = function() { + if (typeof initResizable==='function') initResizable(treeview); + } + // animate mobile menu + $mainMenuState.change(function() { + const $menu = $('#main-menu'); + let options = { duration: 250, step: initResizableIfExists }; + if (this.checked) { + options['complete'] = () => $menu.css('display', 'block'); + $menu.hide().slideDown(options); + } else { + options['complete'] = () => $menu.css('display', 'none'); + $menu.show().slideUp(options); + } + }); + // set default menu visibility + const resetState = function() { + const $menu = $('#main-menu'); + const newWidth = $(window).outerWidth(); + if (newWidth!=prevWidth) { + if ($(window).outerWidth()<768) { + $mainMenuState.prop('checked',false); $menu.hide(); + $('#searchBoxPos1').html(searchBoxHtml); + $('#searchBoxPos2').hide(); + } else { + $menu.show(); + $('#searchBoxPos1').empty(); + $('#searchBoxPos2').html(searchBoxHtml); + $('#searchBoxPos2').show(); + } + if (typeof searchBox!=='undefined') { + searchBox.CloseResultsWindow(); + } + prevWidth = newWidth; + } + } + $(window).ready(function() { resetState(); initResizableIfExists(); }); + $(window).resize(resetState); + } + $('#main-menu').smartmenus(); +} +/* @license-end */ diff --git a/cpp-strings/html/menudata.js b/cpp-strings/html/menudata.js new file mode 100644 index 0000000..2d950f2 --- /dev/null +++ b/cpp-strings/html/menudata.js @@ -0,0 +1,82 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file +*/ +var menudata={children:[ +{text:"Main Page",url:"index.html"}, +{text:"Namespaces",url:"namespaces.html",children:[ +{text:"Namespace List",url:"namespaces.html"}, +{text:"Namespace Members",url:"namespacemembers.html",children:[ +{text:"All",url:"namespacemembers.html",children:[ +{text:"c",url:"namespacemembers.html#index_c"}, +{text:"i",url:"namespacemembers.html#index_i"}, +{text:"o",url:"namespacemembers.html#index_o"}, +{text:"s",url:"namespacemembers.html#index_s"}, +{text:"t",url:"namespacemembers.html#index_t"}]}, +{text:"Functions",url:"namespacemembers_func.html",children:[ +{text:"i",url:"namespacemembers_func.html#index_i"}, +{text:"o",url:"namespacemembers_func.html#index_o"}, +{text:"s",url:"namespacemembers_func.html#index_s"}, +{text:"t",url:"namespacemembers_func.html#index_t"}]}, +{text:"Typedefs",url:"namespacemembers_type.html"}]}]}, +{text:"Classes",url:"annotated.html",children:[ +{text:"Class List",url:"annotated.html"}, +{text:"Class Index",url:"classes.html"}, +{text:"Class Hierarchy",url:"hierarchy.html"}, +{text:"Class Members",url:"functions.html",children:[ +{text:"All",url:"functions.html",children:[ +{text:"b",url:"functions.html#index_b"}, +{text:"c",url:"functions.html#index_c"}, +{text:"e",url:"functions.html#index_e"}, +{text:"f",url:"functions.html#index_f"}, +{text:"g",url:"functions.html#index_g"}, +{text:"i",url:"functions.html#index_i"}, +{text:"j",url:"functions.html#index_j"}, +{text:"l",url:"functions.html#index_l"}, +{text:"o",url:"functions.html#index_o"}, +{text:"p",url:"functions.html#index_p"}, +{text:"r",url:"functions.html#index_r"}, +{text:"s",url:"functions.html#index_s"}, +{text:"t",url:"functions.html#index_t"}, +{text:"u",url:"functions.html#index_u"}, +{text:"z",url:"functions.html#index_z"}, +{text:"~",url:"functions.html#index__7E"}]}, +{text:"Functions",url:"functions_func.html",children:[ +{text:"b",url:"functions_func.html#index_b"}, +{text:"c",url:"functions_func.html#index_c"}, +{text:"e",url:"functions_func.html#index_e"}, +{text:"f",url:"functions_func.html#index_f"}, +{text:"g",url:"functions_func.html#index_g"}, +{text:"i",url:"functions_func.html#index_i"}, +{text:"j",url:"functions_func.html#index_j"}, +{text:"l",url:"functions_func.html#index_l"}, +{text:"o",url:"functions_func.html#index_o"}, +{text:"p",url:"functions_func.html#index_p"}, +{text:"r",url:"functions_func.html#index_r"}, +{text:"s",url:"functions_func.html#index_s"}, +{text:"t",url:"functions_func.html#index_t"}, +{text:"u",url:"functions_func.html#index_u"}, +{text:"z",url:"functions_func.html#index_z"}, +{text:"~",url:"functions_func.html#index__7E"}]}]}]}, +{text:"Files",url:"files.html",children:[ +{text:"File List",url:"files.html"}]}]} diff --git a/cpp-strings/html/namespacemembers.html b/cpp-strings/html/namespacemembers.html new file mode 100644 index 0000000..e29a627 --- /dev/null +++ b/cpp-strings/html/namespacemembers.html @@ -0,0 +1,159 @@ + + + + + + + +cpp-strings: Namespace Members + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    cpp-strings 1.0.0 +
    +
    Pythonic c++ strings
    +
    +
    + + + + + + + +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    Here is a list of all documented namespace members with links to the namespaces they belong to:
    + +

    - c -

      +
    • CppString : pcs
    • +
    • CppWString : pcs
    • +
    + + +

    - i -

      +
    • is_alpha() : pcs
    • +
    • is_alpha< char >() : pcs
    • +
    • is_alpha< wchar_t >() : pcs
    • +
    • is_ascii() : pcs
    • +
    • is_decimal() : pcs
    • +
    • is_decimal< char >() : pcs
    • +
    • is_decimal< wchar_t >() : pcs
    • +
    • is_digit() : pcs
    • +
    • is_digit< char >() : pcs
    • +
    • is_digit< wchar_t >() : pcs
    • +
    • is_id_continue() : pcs
    • +
    • is_id_start() : pcs
    • +
    • is_lower() : pcs
    • +
    • is_lower< char >() : pcs
    • +
    • is_lower< wchar_t >() : pcs
    • +
    • is_numeric() : pcs
    • +
    • is_numeric< char >() : pcs
    • +
    • is_numeric< wchar_t >() : pcs
    • +
    • is_printable() : pcs
    • +
    • is_printable< char >() : pcs
    • +
    • is_printable< wchar_t >() : pcs
    • +
    • is_punctuation() : pcs
    • +
    • is_punctuation< char >() : pcs
    • +
    • is_punctuation< wchar_t >() : pcs
    • +
    • is_space() : pcs
    • +
    • is_space< char >() : pcs
    • +
    • is_space< wchar_t >() : pcs
    • +
    • is_upper() : pcs
    • +
    • is_upper< char >() : pcs
    • +
    • is_upper< wchar_t >() : pcs
    • +
    + + +

    - o -

      +
    • operator""_cs() : pcs
    • +
    + + +

    - s -

      +
    • swap_case() : pcs
    • +
    + + +

    - t -

      +
    • to_lower() : pcs
    • +
    • to_lower< char >() : pcs
    • +
    • to_lower< wchar_t >() : pcs
    • +
    • to_upper() : pcs
    • +
    • to_upper< char >() : pcs
    • +
    • to_upper< wchar_t >() : pcs
    • +
    +
    +
    +
    + + + + diff --git a/cpp-strings/html/namespacemembers_func.html b/cpp-strings/html/namespacemembers_func.html new file mode 100644 index 0000000..99524ea --- /dev/null +++ b/cpp-strings/html/namespacemembers_func.html @@ -0,0 +1,153 @@ + + + + + + + +cpp-strings: Namespace Members + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    cpp-strings 1.0.0 +
    +
    Pythonic c++ strings
    +
    +
    + + + + + + + +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    Here is a list of all documented namespace functions with links to the namespaces they belong to:
    + +

    - i -

      +
    • is_alpha() : pcs
    • +
    • is_alpha< char >() : pcs
    • +
    • is_alpha< wchar_t >() : pcs
    • +
    • is_ascii() : pcs
    • +
    • is_decimal() : pcs
    • +
    • is_decimal< char >() : pcs
    • +
    • is_decimal< wchar_t >() : pcs
    • +
    • is_digit() : pcs
    • +
    • is_digit< char >() : pcs
    • +
    • is_digit< wchar_t >() : pcs
    • +
    • is_id_continue() : pcs
    • +
    • is_id_start() : pcs
    • +
    • is_lower() : pcs
    • +
    • is_lower< char >() : pcs
    • +
    • is_lower< wchar_t >() : pcs
    • +
    • is_numeric() : pcs
    • +
    • is_numeric< char >() : pcs
    • +
    • is_numeric< wchar_t >() : pcs
    • +
    • is_printable() : pcs
    • +
    • is_printable< char >() : pcs
    • +
    • is_printable< wchar_t >() : pcs
    • +
    • is_punctuation() : pcs
    • +
    • is_punctuation< char >() : pcs
    • +
    • is_punctuation< wchar_t >() : pcs
    • +
    • is_space() : pcs
    • +
    • is_space< char >() : pcs
    • +
    • is_space< wchar_t >() : pcs
    • +
    • is_upper() : pcs
    • +
    • is_upper< char >() : pcs
    • +
    • is_upper< wchar_t >() : pcs
    • +
    + + +

    - o -

      +
    • operator""_cs() : pcs
    • +
    + + +

    - s -

      +
    • swap_case() : pcs
    • +
    + + +

    - t -

      +
    • to_lower() : pcs
    • +
    • to_lower< char >() : pcs
    • +
    • to_lower< wchar_t >() : pcs
    • +
    • to_upper() : pcs
    • +
    • to_upper< char >() : pcs
    • +
    • to_upper< wchar_t >() : pcs
    • +
    +
    +
    +
    + + + + diff --git a/cpp-strings/html/namespacemembers_type.html b/cpp-strings/html/namespacemembers_type.html new file mode 100644 index 0000000..d66a60f --- /dev/null +++ b/cpp-strings/html/namespacemembers_type.html @@ -0,0 +1,103 @@ + + + + + + + +cpp-strings: Namespace Members + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    cpp-strings 1.0.0 +
    +
    Pythonic c++ strings
    +
    +
    + + + + + + + +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    Here is a list of all documented namespace typedefs with links to the namespaces they belong to:
      +
    • CppString : pcs
    • +
    • CppWString : pcs
    • +
    +
    +
    +
    + + + + diff --git a/cpp-strings/html/namespacepcs.html b/cpp-strings/html/namespacepcs.html new file mode 100644 index 0000000..c490840 --- /dev/null +++ b/cpp-strings/html/namespacepcs.html @@ -0,0 +1,1493 @@ + + + + + + + +cpp-strings: pcs Namespace Reference + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    cpp-strings 1.0.0 +
    +
    Pythonic c++ strings
    +
    +
    + + + + + + + +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    pcs Namespace Reference
    +
    +
    + + + + + + + + + + + + + + + + + + +

    +Classes

    class  CppStringT
     This is the templated base class for all CppString classes. More...
    class  Slice
     Base class for slices, with start, stop and step specified values. More...
    struct  StartSlice
     Base class for slices, with start, stop and step specified values. More...
    struct  StartStepSlice
     struct of slices with default step values More...
    struct  StartStopSlice
     struct of slices with default start and stop values More...
    struct  StepSlice
     struct of slices with default start and step values More...
    struct  StopSlice
     struct of slices with default stop and step values More...
    struct  StopStepSlice
     struct of slices with default stop values More...
    + + + + + +

    +Typedefs

    using CppString = CppStringT<char>
     Specialization of basic class with template argument 'char'.
    using CppWString = CppStringT<wchar_t>
     Specialization of basic class with template argument 'wchar_t'.
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Functions

    template<class CharT>
    const bool is_alpha (const CharT ch) noexcept
     struct of slices with default start values
    template<>
    const bool is_alpha< char > (const char ch) noexcept
     Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings.
    template<>
    const bool is_alpha< wchar_t > (const wchar_t ch) noexcept
     Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings.
    template<class CharT>
    const bool is_ascii (const CharT ch) noexcept
     Returns true if character ch gets ASCII code, or false otherwise.
    template<class CharT>
    const bool is_decimal (const CharT ch) noexcept
     Returns true if character is a decimal digit, or false otherwise.
    template<>
    const bool is_decimal< char > (const char ch) noexcept
     Returns true if character is a decimal digit, or false otherwise.
    template<>
    const bool is_decimal< wchar_t > (const wchar_t ch) noexcept
     Returns true if character is a decimal digit, or false otherwise.
    template<class CharT>
    const bool is_digit (const CharT ch) noexcept
     Returns true if character is a decimal digit, or false otherwise.
    template<>
    const bool is_digit< char > (const char ch) noexcept
     Returns true if character is a decimal digit, or false otherwise.
    template<>
    const bool is_digit< wchar_t > (const wchar_t ch) noexcept
     Returns true if character is a decimal digit, or false otherwise.
    template<class CharT>
    const bool is_id_continue (const CharT ch) noexcept
     Returns true if character is a continuing char for identifiers, or false otherwise.
    template<class CharT>
    const bool is_id_start (const CharT ch) noexcept
     Returns true if character is a starting char for identifiers, or false otherwise.
    template<class CharT>
    const bool is_lower (const CharT ch) noexcept
     Returns true if character is lowercase, or false otherwise.
    template<>
    const bool is_lower< char > (const char ch) noexcept
     Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale settings.
    template<>
    const bool is_lower< wchar_t > (const wchar_t ch) noexcept
     Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale settings.
    template<class CharT>
    const bool is_numeric (const CharT ch) noexcept
     Returns true if character is a decimal digit, or false otherwise.
    template<>
    const bool is_numeric< char > (const char ch) noexcept
     Returns true if character is a decimal digit, or false otherwise.
    template<>
    const bool is_numeric< wchar_t > (const wchar_t ch) noexcept
     Returns true if character is a decimal digit, or false otherwise.
    template<class CharT>
    const bool is_printable (const CharT ch) noexcept
     Returns true if character ch is printable, or false otherwise.
    template<>
    const bool is_printable< char > (const char ch) noexcept
     Returns true if character ch is printable, or false otherwise.
    template<>
    const bool is_printable< wchar_t > (const wchar_t ch) noexcept
     Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings.
    template<class CharT>
    const bool is_punctuation (const CharT ch) noexcept
     Returns true if character ch is punctuation, or false otherwise.
    template<>
    const bool is_punctuation< char > (const char ch) noexcept
     Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings.
    template<>
    const bool is_punctuation< wchar_t > (const wchar_t ch) noexcept
     Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings.
    template<class CharT>
    const bool is_space (const CharT ch) noexcept
     Returns true if character ch is white space, or false otherwise.
    template<>
    const bool is_space< char > (const char ch) noexcept
     Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings.
    template<>
    const bool is_space< wchar_t > (const wchar_t ch) noexcept
     Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings.
    template<class CharT>
    const bool is_upper (const CharT ch) noexcept
     Returns true if character is uppercase, or false otherwise.
    template<>
    const bool is_upper< char > (const char ch) noexcept
     Returns true if character ch is uppercase, or false otherwise. Conforms to the current locale settings.
    template<>
    const bool is_upper< wchar_t > (const wchar_t ch) noexcept
     Returns true if character ch is uppercase, or false otherwise. Conforms to the current locale settings.
    CppString operator""_cs (const char *str, std::size_t len)
     Forms a CppString literal.
    CppWString operator""_cs (const wchar_t *str, std::size_t len)
     Forms a CppWString literal.
    template<class CharT>
    const CharT swap_case (const CharT ch) noexcept
     Returns the swapped case form of character ch if it exists, or ch itself otherwise.
    template<class CharT>
    const CharT to_lower (const CharT ch) noexcept
     Returns the lowercase form of character ch if it exists, or ch itself otherwise.
    template<>
    const char to_lower< char > (const char ch) noexcept
     Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings.
    template<>
    const wchar_t to_lower< wchar_t > (const wchar_t ch) noexcept
     Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings.
    template<class CharT>
    const CharT to_upper (const CharT ch) noexcept
     Returns the uppercase form of character ch if it exists, or ch itself otherwise.
    template<>
    const char to_upper< char > (const char ch) noexcept
     Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings.
    template<>
    const wchar_t to_upper< wchar_t > (const wchar_t ch) noexcept
     Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings.
    +

    Detailed Description

    +

    Library cppstrings "What if c++ strings where as easy to use as Python strings?"

    +

    Copyright (C) 2023-2025 Philippe Schmouker contact - ph (dot) schmouker (at) gmail (dot) com

    +

    This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

    +

    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

    +

    You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

    +

    Typedef Documentation

    + +

    ◆ CppString

    + +
    +
    + + + + +
    using pcs::CppString = CppStringT<char>
    +
    + +

    Specialization of basic class with template argument 'char'.

    + +
    +
    + +

    ◆ CppWString

    + +
    +
    + + + + +
    using pcs::CppWString = CppStringT<wchar_t>
    +
    + +

    Specialization of basic class with template argument 'wchar_t'.

    + +
    +
    +

    Function Documentation

    + +

    ◆ is_alpha()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_alpha (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    struct of slices with default start values

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    +

    Returns true if character ch is alphabetic, or false otherwise.

    + +

    References is_alpha().

    + +

    Referenced by is_alpha(), is_id_start(), pcs::CppStringT< char >::isalnum(), and pcs::CppStringT< char >::isalpha().

    + +
    +
    + +

    ◆ is_alpha< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_alpha< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_alpha< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_alpha< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_ascii()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_ascii (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch gets ASCII code, or false otherwise.

    +

    Returns true if character has code point in the range U+0000-U+007F.

    + +

    Referenced by pcs::CppStringT< char >::isascii().

    + +
    +
    + +

    ◆ is_decimal()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_decimal (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a decimal digit, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    Referenced by is_digit(), is_digit< char >(), is_digit< wchar_t >(), is_id_continue(), is_numeric(), is_numeric< char >(), is_numeric< wchar_t >(), pcs::CppStringT< char >::isalnum(), and pcs::CppStringT< char >::isdecimal().

    + +
    +
    + +

    ◆ is_decimal< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_decimal< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a decimal digit, or false otherwise.

    + +
    +
    + +

    ◆ is_decimal< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_decimal< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a decimal digit, or false otherwise.

    + +
    +
    + +

    ◆ is_digit()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_digit (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a decimal digit, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    References is_decimal().

    + +

    Referenced by pcs::CppStringT< char >::isalnum().

    + +
    +
    + +

    ◆ is_digit< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_digit< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a decimal digit, or false otherwise.

    + +

    References is_decimal().

    + +
    +
    + +

    ◆ is_digit< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_digit< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a decimal digit, or false otherwise.

    + +

    References is_decimal().

    + +
    +
    + +

    ◆ is_id_continue()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_id_continue (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a continuing char for identifiers, or false otherwise.

    + +

    References is_decimal(), and is_id_start().

    + +

    Referenced by pcs::CppStringT< char >::isidentifier().

    + +
    +
    + +

    ◆ is_id_start()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_id_start (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a starting char for identifiers, or false otherwise.

    + +

    References is_alpha().

    + +

    Referenced by is_id_continue(), and pcs::CppStringT< char >::isidentifier().

    + +
    +
    + +

    ◆ is_lower()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_lower (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is lowercase, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    Referenced by pcs::CppStringT< char >::islower(), and swap_case().

    + +
    +
    + +

    ◆ is_lower< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_lower< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_lower< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_lower< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_numeric()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_numeric (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a decimal digit, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    References is_decimal().

    + +

    Referenced by pcs::CppStringT< char >::isalnum().

    + +
    +
    + +

    ◆ is_numeric< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_numeric< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a decimal digit, or false otherwise.

    + +

    References is_decimal().

    + +
    +
    + +

    ◆ is_numeric< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_numeric< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is a decimal digit, or false otherwise.

    + +

    References is_decimal().

    + +
    +
    + +

    ◆ is_printable()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_printable (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is printable, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    Referenced by pcs::CppStringT< char >::isprintable().

    + +
    +
    + +

    ◆ is_printable< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_printable< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is printable, or false otherwise.

    + +
    +
    + +

    ◆ is_printable< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_printable< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_punctuation()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_punctuation (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is punctuation, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    Referenced by pcs::CppStringT< char >::is_words_sep(), and pcs::CppStringT< char >::ispunctuation().

    + +
    +
    + +

    ◆ is_punctuation< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_punctuation< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_punctuation< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_punctuation< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_space()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_space (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is white space, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    Referenced by pcs::CppStringT< char >::is_words_sep(), and pcs::CppStringT< char >::isspace().

    + +
    +
    + +

    ◆ is_space< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_space< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_space< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_space< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_upper()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_upper (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character is uppercase, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    Referenced by pcs::CppStringT< char >::isupper(), and swap_case().

    + +
    +
    + +

    ◆ is_upper< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_upper< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is uppercase, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ is_upper< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const bool pcs::is_upper< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns true if character ch is uppercase, or false otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ operator""_cs() [1/2]

    + +
    +
    + + + + + +
    + + + + + + + + + + + +
    CppString pcs::operator""_cs (const char * str,
    std::size_t len )
    +
    +inline
    +
    + +

    Forms a CppString literal.

    + +
    +
    + +

    ◆ operator""_cs() [2/2]

    + +
    +
    + + + + + +
    + + + + + + + + + + + +
    CppWString pcs::operator""_cs (const wchar_t * str,
    std::size_t len )
    +
    +inline
    +
    + +

    Forms a CppWString literal.

    + +
    +
    + +

    ◆ swap_case()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const CharT pcs::swap_case (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns the swapped case form of character ch if it exists, or ch itself otherwise.

    + +

    References is_lower(), is_upper(), to_lower(), and to_upper().

    + +

    Referenced by pcs::CppStringT< char >::swapcase().

    + +
    +
    + +

    ◆ to_lower()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const CharT pcs::to_lower (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns the lowercase form of character ch if it exists, or ch itself otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    Referenced by swap_case().

    + +
    +
    + +

    ◆ to_lower< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const char pcs::to_lower< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ to_lower< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const wchar_t pcs::to_lower< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ to_upper()

    + +
    +
    +
    +template<class CharT>
    + + + + + +
    + + + + + + + +
    const CharT pcs::to_upper (const CharT ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns the uppercase form of character ch if it exists, or ch itself otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    Referenced by pcs::CppStringT< char >::capitalize(), and swap_case().

    + +
    +
    + +

    ◆ to_upper< char >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const char pcs::to_upper< char > (const char ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings.

    + +
    +
    + +

    ◆ to_upper< wchar_t >()

    + +
    +
    +
    +template<>
    + + + + + +
    + + + + + + + +
    const wchar_t pcs::to_upper< wchar_t > (const wchar_t ch)
    +
    +inlinenodiscardnoexcept
    +
    + +

    Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings.

    + +
    +
    +
    +
    + +
    + + + + diff --git a/cpp-strings/html/namespacepcs.js b/cpp-strings/html/namespacepcs.js new file mode 100644 index 0000000..9151eae --- /dev/null +++ b/cpp-strings/html/namespacepcs.js @@ -0,0 +1,52 @@ +var namespacepcs = +[ + [ "CppStringT", "classpcs_1_1_cpp_string_t.html", "classpcs_1_1_cpp_string_t" ], + [ "Slice", "classpcs_1_1_slice.html", "classpcs_1_1_slice" ], + [ "StartSlice", "structpcs_1_1_start_slice.html", "structpcs_1_1_start_slice" ], + [ "StartStepSlice", "structpcs_1_1_start_step_slice.html", "structpcs_1_1_start_step_slice" ], + [ "StartStopSlice", "structpcs_1_1_start_stop_slice.html", "structpcs_1_1_start_stop_slice" ], + [ "StepSlice", "structpcs_1_1_step_slice.html", "structpcs_1_1_step_slice" ], + [ "StopSlice", "structpcs_1_1_stop_slice.html", "structpcs_1_1_stop_slice" ], + [ "StopStepSlice", "structpcs_1_1_stop_step_slice.html", "structpcs_1_1_stop_step_slice" ], + [ "CppString", "namespacepcs.html#a08d21c458d61442667df24212920d0d9", null ], + [ "CppWString", "namespacepcs.html#a79a822cea8e301fd51d2ed51dff57286", null ], + [ "is_alpha", "namespacepcs.html#a40bc3d234e3c737f34d267151ca62014", null ], + [ "is_alpha< char >", "namespacepcs.html#ade5b26313fc856bb882109d6945629b8", null ], + [ "is_alpha< wchar_t >", "namespacepcs.html#a069625790af3ecf05a424c2c53eabfc0", null ], + [ "is_ascii", "namespacepcs.html#ac7822fd0c570f69d597936a24c38ba2a", null ], + [ "is_decimal", "namespacepcs.html#a9f0ba4e85fc273fad1a8b489f3be7fa8", null ], + [ "is_decimal< char >", "namespacepcs.html#a28f77929d599a862403a4471f6b73fc3", null ], + [ "is_decimal< wchar_t >", "namespacepcs.html#a60a2017b25d3d06b83e72f5ed5a93d09", null ], + [ "is_digit", "namespacepcs.html#a52b12f8beb4ab7d8b819ca24180e08d1", null ], + [ "is_digit< char >", "namespacepcs.html#af7c58514e3378a219904f22eb22e9072", null ], + [ "is_digit< wchar_t >", "namespacepcs.html#a01c6093b1a8ef52114f799635ff930d5", null ], + [ "is_id_continue", "namespacepcs.html#aef0240331a343bb1ad13eb613ca93fa4", null ], + [ "is_id_start", "namespacepcs.html#abfda7874fe5b1f72c1c5a9a04d5c7e42", null ], + [ "is_lower", "namespacepcs.html#aedd570e9ffa0572d56fce5085594bdbb", null ], + [ "is_lower< char >", "namespacepcs.html#a29893984c95e53a6efe01f74c2dcc03a", null ], + [ "is_lower< wchar_t >", "namespacepcs.html#ad1d1b13c16ce784055e93af9fa34fb5c", null ], + [ "is_numeric", "namespacepcs.html#af1b60c1081e8bc3b4cd91fbe240e9b87", null ], + [ "is_numeric< char >", "namespacepcs.html#a242e3c28e3d47d19d70ab70d83e74d35", null ], + [ "is_numeric< wchar_t >", "namespacepcs.html#acab7e7bb1ffd6e4ea1a8300b05478647", null ], + [ "is_printable", "namespacepcs.html#a51cd6883557ab31a1e0c8e7b5ab27351", null ], + [ "is_printable< char >", "namespacepcs.html#a1cd19ec212e3ada992a8effb8d5d872d", null ], + [ "is_printable< wchar_t >", "namespacepcs.html#a30ed0cd7942d081369f78a49a029d8b1", null ], + [ "is_punctuation", "namespacepcs.html#a02d340dd9c510eda0fbfed07a08d0792", null ], + [ "is_punctuation< char >", "namespacepcs.html#aa36d34c2227cde5856e8d61fa6e4af58", null ], + [ "is_punctuation< wchar_t >", "namespacepcs.html#a363e2bac9c403a623c5a410f7113edd3", null ], + [ "is_space", "namespacepcs.html#af089ceadbeaab27e12ad7f7edaaec72a", null ], + [ "is_space< char >", "namespacepcs.html#a714cfa835ef4db5180309829ee8e27a9", null ], + [ "is_space< wchar_t >", "namespacepcs.html#a57a765c6eb624107a2176a56cf2220a7", null ], + [ "is_upper", "namespacepcs.html#a8cb1cd0a1e39d92893eb7d22145f5d65", null ], + [ "is_upper< char >", "namespacepcs.html#ac25d471fa1d838401335776ad4b6ead1", null ], + [ "is_upper< wchar_t >", "namespacepcs.html#ab5077443809e9e4eb7bfa463728f398a", null ], + [ "operator\"\"_cs", "namespacepcs.html#afb8dd890fe893aba3264ac7df4fe7124", null ], + [ "operator\"\"_cs", "namespacepcs.html#acb7395de8ef88696d0c8c9772e172118", null ], + [ "swap_case", "namespacepcs.html#ac6e0b881e35c04e9b5bbe6e8b17ee1a7", null ], + [ "to_lower", "namespacepcs.html#a965f285db4253ce86ed59fccc2e8be61", null ], + [ "to_lower< char >", "namespacepcs.html#a4c4164fedd9cb659873a980fa855f4a2", null ], + [ "to_lower< wchar_t >", "namespacepcs.html#ab097a99126055ab4c843eb6efb573bb1", null ], + [ "to_upper", "namespacepcs.html#a607c82cc94f2b6473d8391334eed8c14", null ], + [ "to_upper< char >", "namespacepcs.html#ab823c7be920affd05f96a6ad8b99accf", null ], + [ "to_upper< wchar_t >", "namespacepcs.html#aaf8dcc64819cbf8631fc63e0dd522811", null ] +]; \ No newline at end of file diff --git a/cpp-strings/html/namespaces.html b/cpp-strings/html/namespaces.html new file mode 100644 index 0000000..9d8281c --- /dev/null +++ b/cpp-strings/html/namespaces.html @@ -0,0 +1,107 @@ + + + + + + + +cpp-strings: Namespace List + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    cpp-strings 1.0.0 +
    +
    Pythonic c++ strings
    +
    +
    + + + + + + + +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    Namespace List
    +
    +
    +
    Here is a list of all documented namespaces with brief descriptions:
    + + +
     Npcs
    +
    +
    +
    +
    + + + + diff --git a/cpp-strings/html/namespaces_dup.js b/cpp-strings/html/namespaces_dup.js new file mode 100644 index 0000000..2c93f11 --- /dev/null +++ b/cpp-strings/html/namespaces_dup.js @@ -0,0 +1,4 @@ +var namespaces_dup = +[ + [ "pcs", "namespacepcs.html", "namespacepcs" ] +]; \ No newline at end of file diff --git a/cpp-strings/html/navtree.css b/cpp-strings/html/navtree.css new file mode 100644 index 0000000..0ea3a07 --- /dev/null +++ b/cpp-strings/html/navtree.css @@ -0,0 +1,327 @@ +#nav-tree .children_ul { + margin:0; + padding:4px; +} + +#nav-tree ul { + list-style:none outside none; + margin:0px; + padding:0px; +} + +#nav-tree li { + white-space:nowrap; + margin:0; + padding:0; +} + +#nav-tree .plus { + margin:0px; +} + +#nav-tree .selected { + position: relative; + background-color: var(--nav-menu-active-bg); + border-radius: 0 6px 6px 0; + /*margin-right: 5px;*/ +} + +#nav-tree img { + margin:0px; + padding:0px; + border:0px; + vertical-align: middle; +} + +#nav-tree a { + text-decoration:none; + padding:0px; + margin:0px; +} + +#nav-tree .label { + margin:0px; + padding:0px; + font: 12px var(--font-family-nav); + line-height: 22px; +} + +#nav-tree .label a { + padding:2px; +} + +#nav-tree .selected a { + text-decoration:none; + color:var(--page-link-color); +} + +#nav-tree .children_ul { + margin:0px; + padding:0px; +} + +#nav-tree .item { + margin: 0 6px 0 -5px; + padding: 0 0 0 5px; + height: 22px; +} + +#nav-tree { + padding: 0px 0px; + font-size:14px; + overflow:auto; +} + +#doc-content { + overflow:auto; + display:block; + padding:0px; + margin:0px; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#side-nav { + padding:0 6px 0 0; + margin: 0px; + display:block; + position: absolute; + left: 0px; + overflow : hidden; +} + +.ui-resizable .ui-resizable-handle { + display:block; +} + +.ui-resizable-e { + transition: opacity 0.5s ease; + background-color: var(--nav-splitbar-bg-color); + opacity:0; + cursor:col-resize; + height:100%; + right:0; + top:0; + width:6px; + position: relative; +} + +.ui-resizable-e:after { + content: ''; + display: block; + top: 50%; + left: 1px; + width: 2px; + height: 15px; + border-left: 1px solid var(--nav-splitbar-handle-color); + border-right: 1px solid var(--nav-splitbar-handle-color); + position: absolute; +} + +.ui-resizable-e:hover { + opacity: 1; +} + +.ui-resizable-handle { + display:none; + font-size:0.1px; + position:absolute; + z-index:1; +} + +#nav-tree-contents { + margin: 6px 0px 0px 0px; +} + +#nav-tree { + background-color: var(--nav-background-color); + -webkit-overflow-scrolling : touch; /* iOS 5+ */ + scrollbar-width: thin; + border-right: 1px solid var(--nav-border-color); + padding-left: 5px; +} + +#nav-sync { + position:absolute; + top:0px; + right:0px; + z-index:1; +} + +#nav-sync img { + opacity:0.3; +} + +div.nav-sync-icon { + position: relative; + width: 24px; + height: 17px; + left: -6px; + top: -1px; + opacity: 0.7; + display: inline-block; + background-color: var(--sync-icon-background-color); + border: 1px solid var(--sync-icon-border-color); + box-sizing: content-box; +} + +div.nav-sync-icon:hover { + background-color: var(--sync-icon-selected-background-color); + opacity: 1.0; +} + +div.nav-sync-icon.active:after { + content: ''; + background-color: var(--sync-icon-background-color); + border-top: 2px solid var(--sync-icon-color); + position: absolute; + width: 16px; + height: 0px; + top: 7px; + left: 4px; +} + +div.nav-sync-icon.active:hover:after { + border-top: 2px solid var(--sync-icon-selected-color); +} + +span.sync-icon-left { + position: absolute; + padding: 0; + margin: 0; + top: 3px; + left: 4px; + display: inline-block; + width: 8px; + height: 8px; + border-left: 2px solid var(--sync-icon-color); + border-top: 2px solid var(--sync-icon-color); + transform: rotate(-45deg); +} + +span.sync-icon-right { + position: absolute; + padding: 0; + margin: 0; + top: 3px; + left: 10px; + display: inline-block; + width: 8px; + height: 8px; + border-right: 2px solid var(--sync-icon-color); + border-bottom: 2px solid var(--sync-icon-color); + transform: rotate(-45deg); +} + +div.nav-sync-icon:hover span.sync-icon-left { + border-left: 2px solid var(--sync-icon-selected-color); + border-top: 2px solid var(--sync-icon-selected-color); +} + +div.nav-sync-icon:hover span.sync-icon-right { + border-right: 2px solid var(--sync-icon-selected-color); + border-bottom: 2px solid var(--sync-icon-selected-color); +} + +#nav-path ul { + border-top: 1px solid var(--nav-breadcrumb-separator-color); +} + +@media print +{ + #nav-tree { display: none; } + div.ui-resizable-handle { display: none; position: relative; } +} + +/*---------------------------*/ +#container { + display: grid; + grid-template-columns: auto auto; + overflow: hidden; +} + +#page-nav { + background: var(--nav-background-color); + display: block; + width: 250px; + box-sizing: content-box; + position: relative; + border-left: 1px solid var(--nav-border-color); +} + +#page-nav-tree { + display: inline-block; +} + +#page-nav-resize-handle { + transition: opacity 0.5s ease; + background-color: var(--nav-splitbar-bg-color); + opacity:0; + cursor:col-resize; + height:100%; + right:0; + top:0; + width:6px; + position: relative; + z-index: 1; + user-select: none; +} + +#page-nav-resize-handle:after { + content: ''; + display: block; + top: 50%; + left: 1px; + width: 2px; + height: 15px; + border-left: 1px solid var(--nav-splitbar-handle-color); + border-right: 1px solid var(--nav-splitbar-handle-color); + position: absolute; +} + +#page-nav-resize-handle.dragging, +#page-nav-resize-handle:hover { + opacity: 1; +} + +#page-nav-contents { + padding: 0; + margin: 0; + display: block; + top: 0; + left: 0; + height: 100%; + width: 100%; + position: absolute; + overflow: auto; + scrollbar-width: thin; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +ul.page-outline, +ul.page-outline ul { + text-indent: 0; + list-style: none outside none; + padding: 0 0 0 4px; +} + +ul.page-outline { + margin: 0 4px 4px 6px; +} + +ul.page-outline div.item { + font: 12px var(--font-family-nav); + line-height: 22px; +} + +ul.page-outline li { + white-space: nowrap; +} + +ul.page-outline li.vis { + background-color: var(--nav-breadcrumb-active-bg); +} + +#container.resizing { + cursor: col-resize; + user-select: none; +} diff --git a/cpp-strings/html/navtree.js b/cpp-strings/html/navtree.js new file mode 100644 index 0000000..4fcf6e3 --- /dev/null +++ b/cpp-strings/html/navtree.js @@ -0,0 +1,899 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ + +function initNavTree(toroot,relpath,allMembersFile) { + let navTreeSubIndices = []; + const ARROW_DOWN = ''; + const ARROW_RIGHT = ''; + const NAVPATH_COOKIE_NAME = ''+'navpath'; + const fullSidebar = typeof page_layout!=='undefined' && page_layout==1; + + function getScrollBarWidth () { + let outer = $('
    ').css({visibility: 'hidden', width: 100, overflow: 'scroll', scrollbarWidth: 'thin'}).appendTo('body'); + let widthWithScroll = $('
    ').css({width: '100%'}).appendTo(outer).outerWidth(); + outer.remove(); + return 100 - widthWithScroll; + } + const scrollbarWidth = getScrollBarWidth(); + + function adjustSyncIconPosition() { + if (!fullSidebar) { + const nt = document.getElementById("nav-tree"); + const hasVerticalScrollbar = nt.scrollHeight > nt.clientHeight; + $("#nav-sync").css({right:parseInt(hasVerticalScrollbar?scrollbarWidth:0)}); + } + } + + const getData = function(varName) { + const i = varName.lastIndexOf('/'); + const n = i>=0 ? varName.substring(i+1) : varName; + const e = n.replace(/-/g,'_'); + return window[e]; + } + + const stripPath = function(uri) { + return uri.substring(uri.lastIndexOf('/')+1); + } + + const stripPath2 = function(uri) { + const i = uri.lastIndexOf('/'); + const s = uri.substring(i+1); + const m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/); + return m ? uri.substring(i-6) : s; + } + + const hashValue = function() { + return $(location).attr('hash').substring(1).replace(/[^\w-]/g,''); + } + + const hashUrl = function() { + return '#'+hashValue(); + } + + const pathName = function() { + return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;()]/g, ''); + } + + const storeLink = function(link) { + if (!$("#nav-sync").hasClass('sync')) { + Cookie.writeSetting(NAVPATH_COOKIE_NAME,link,0); + } + } + + const deleteLink = function() { + Cookie.eraseSetting(NAVPATH_COOKIE_NAME); + } + + const cachedLink = function() { + return Cookie.readSetting(NAVPATH_COOKIE_NAME,''); + } + + const getScript = function(scriptName,func) { + const head = document.getElementsByTagName("head")[0]; + const script = document.createElement('script'); + script.id = scriptName; + script.type = 'text/javascript'; + script.onload = function() { func(); adjustSyncIconPosition(); } + script.src = scriptName+'.js'; + head.appendChild(script); + } + + const createIndent = function(o,domNode,node) { + let level=-1; + let n = node; + while (n.parentNode) { level++; n=n.parentNode; } + if (node.childrenData) { + const imgNode = document.createElement("span"); + imgNode.className = 'arrow'; + imgNode.style.paddingLeft=(16*level).toString()+'px'; + imgNode.innerHTML=ARROW_RIGHT; + node.plus_img = imgNode; + node.expandToggle = document.createElement("a"); + node.expandToggle.href = "javascript:void(0)"; + node.expandToggle.onclick = function() { + if (node.expanded) { + $(node.getChildrenUL()).slideUp("fast",adjustSyncIconPosition); + $(node.plus_img.childNodes[0]).removeClass('opened').addClass('closed'); + node.expanded = false; + } else { + expandNode(o, node, false, true); + } + } + node.expandToggle.appendChild(imgNode); + domNode.appendChild(node.expandToggle); + } else { + let span = document.createElement("span"); + span.className = 'arrow'; + span.style.width = 16*(level+1)+'px'; + span.innerHTML = ' '; + domNode.appendChild(span); + } + } + + let animationInProgress = false; + + const gotoAnchor = function(anchor,aname) { + let pos, docContent = $('#doc-content'); + let ancParent = $(anchor.parent()); + if (ancParent.hasClass('memItemLeft') || ancParent.hasClass('memtitle') || + ancParent.hasClass('fieldname') || ancParent.hasClass('fieldtype') || + ancParent.is(':header')) { + pos = ancParent.offset().top; + } else if (anchor.position()) { + pos = anchor.offset().top; + } + if (pos) { + const dcOffset = docContent.offset().top; + const dcHeight = docContent.height(); + const dcScrHeight = docContent[0].scrollHeight + const dcScrTop = docContent.scrollTop(); + let dist = Math.abs(Math.min(pos-dcOffset,dcScrHeight-dcHeight-dcScrTop)); + animationInProgress = true; + docContent.animate({ + scrollTop: pos + dcScrTop - dcOffset + },Math.max(50,Math.min(500,dist)),function() { + animationInProgress=false; + if (anchor.parent().attr('class')=='memItemLeft') { + let rows = $('.memberdecls tr[class$="'+hashValue()+'"]'); + glowEffect(rows.children(),300); // member without details + } else if (anchor.parent().attr('class')=='fieldname') { + glowEffect(anchor.parent().parent(),1000); // enum value + } else if (anchor.parent().attr('class')=='fieldtype') { + glowEffect(anchor.parent().parent(),1000); // struct field + } else if (anchor.parent().is(":header")) { + glowEffect(anchor.parent(),1000); // section header + } else { + glowEffect(anchor.next(),1000); // normal member + } + }); + } + } + + function htmlToNode(html) { + const template = document.createElement('template'); + template.innerHTML = html; + const nNodes = template.content.childNodes.length; + if (nNodes !== 1) { + throw new Error(`html parameter must represent a single node; got ${nNodes}. `); + } + return template.content.firstChild; + } + + const newNode = function(o, po, text, link, childrenData, lastNode) { + const node = { + children : [], + childrenData : childrenData, + depth : po.depth + 1, + relpath : po.relpath, + isLast : lastNode, + li : document.createElement("li"), + parentNode : po, + itemDiv : document.createElement("div"), + labelSpan : document.createElement("span"), + expanded : false, + childrenUL : null, + getChildrenUL : function() { + if (!this.childrenUL) { + this.childrenUL = document.createElement("ul"); + this.childrenUL.className = "children_ul"; + this.childrenUL.style.display = "none"; + this.li.appendChild(node.childrenUL); + } + return node.childrenUL; + }, + }; + + node.itemDiv.className = "item"; + node.labelSpan.className = "label"; + createIndent(o,node.itemDiv,node); + node.itemDiv.appendChild(node.labelSpan); + node.li.appendChild(node.itemDiv); + + const a = document.createElement("a"); + node.labelSpan.appendChild(a); + po.getChildrenUL().appendChild(node.li); + a.appendChild(htmlToNode(''+text+'')); + if (link) { + let url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + link = url; + } else { + url = node.relpath+link; + } + a.className = stripPath(link.replace('#',':')); + if (link.indexOf('#')!=-1) { + const aname = '#'+link.split('#')[1]; + const srcPage = stripPath(pathName()); + const targetPage = stripPath(link.split('#')[0]); + a.href = srcPage!=targetPage ? url : aname; + a.onclick = function() { + storeLink(link); + aPPar = $(a).parent().parent(); + if (!aPPar.hasClass('selected')) { + $('.item').removeClass('selected'); + $('.item').removeAttr('id'); + aPPar.addClass('selected'); + aPPar.attr('id','selected'); + } + const anchor = $(aname); + gotoAnchor(anchor,aname); + }; + } else { + a.href = url; + a.onclick = () => storeLink(link); + } + } else if (childrenData != null) { + a.className = "nolink"; + a.href = "javascript:void(0)"; + a.onclick = node.expandToggle.onclick; + } + return node; + } + + const showRoot = function() { + const headerHeight = $("#top").height(); + const footerHeight = $("#nav-path").height(); + const windowHeight = $(window).height() - headerHeight - footerHeight; + (function() { // retry until we can scroll to the selected item + try { + const navtree=$('#nav-tree'); + navtree.scrollTo('#selected',100,{offset:-windowHeight/2}); + } catch (err) { + setTimeout(arguments.callee, 0); + } + })(); + } + + const expandNode = function(o, node, imm, setFocus) { + if (node.childrenData && !node.expanded) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + expandNode(o, node, imm, setFocus); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).slideDown("fast",adjustSyncIconPosition); + $(node.plus_img.childNodes[0]).addClass('opened').removeClass('closed'); + node.expanded = true; + if (setFocus) { + $(node.expandToggle).focus(); + } + } + } + } + + const glowEffect = function(n,duration) { + n.addClass('glow').delay(duration).queue(function(next) { + $(this).removeClass('glow');next(); + }); + } + + const highlightAnchor = function() { + const aname = hashUrl(); + const anchor = $(aname); + gotoAnchor(anchor,aname); + } + + const selectAndHighlight = function(hash,n) { + let a; + if (hash) { + const link=stripPath(pathName())+':'+hash.substring(1); + a=$('.item a[class$="'+link+'"]'); + } + if (a && a.length) { + a.parent().parent().addClass('selected'); + a.parent().parent().attr('id','selected'); + highlightAnchor(); + } else if (n) { + $(n.itemDiv).addClass('selected'); + $(n.itemDiv).attr('id','selected'); + } + let topOffset=5; + if ($('#nav-tree-contents .item:first').hasClass('selected')) { + topOffset+=25; + } + showRoot(); + } + + const showNode = function(o, node, index, hash) { + if (node && node.childrenData) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + showNode(o,node,index,hash); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).css({'display':'block'}); + $(node.plus_img.childNodes[0]).removeClass('closed').addClass('opened'); + node.expanded = true; + const n = node.children[o.breadcrumbs[index]]; + if (index+10) { // try root page without hash as fallback + gotoUrl(o,root,'',relpath); + } else { + o.breadcrumbs = $.extend(true, [], nti); + if (!o.breadcrumbs && root!=NAVTREE[0][1]) { // fallback: show index + navTo(o,NAVTREE[0][1],"",relpath); + $('.item').removeClass('selected'); + $('.item').removeAttr('id'); + } + if (o.breadcrumbs) { + o.breadcrumbs.unshift(0); // add 0 for root node + showNode(o, o.node, 0, hash); + } + } + } + + const gotoUrl = function(o,root,hash,relpath) { + const url=root+hash; + let i=-1; + while (NAVTREEINDEX[i+1]<=url) i++; + if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath) + } else { + getScript(relpath+'navtreeindex'+i,function() { + navTreeSubIndices[i] = window['NAVTREEINDEX'+i]; + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath); + } + }); + } + } + + const navTo = function(o,root,hash,relpath) { + const link = cachedLink(); + if (link) { + const parts = link.split('#'); + root = parts[0]; + hash = parts.length>1 ? '#'+parts[1].replace(/[^\w-]/g,'') : ''; + } + if (hash.match(/^#l\d+$/)) { + const anchor=$('a[name='+hash.substring(1)+']'); + glowEffect(anchor.parent(),1000); // line number + hash=''; // strip line number anchors + } + gotoUrl(o,root,hash,relpath); + } + + const showSyncOff = function(n,relpath) { + n.html(''); + } + + const showSyncOn = function(n,relpath) { + n.html(''); + } + + const o = { + toroot : toroot, + node : { + childrenData : NAVTREE, + children : [], + childrenUL : document.createElement("ul"), + getChildrenUL : function() { return this.childrenUL }, + li : document.getElementById("nav-tree-contents"), + depth : 0, + relpath : relpath, + expanded : false, + isLast : true, + plus_img : document.createElement("span"), + }, + }; + o.node.li.appendChild(o.node.childrenUL); + o.node.plus_img.className = 'arrow'; + o.node.plus_img.innerHTML = ARROW_RIGHT; + + const navSync = $('#nav-sync'); + if (cachedLink()) { + showSyncOff(navSync,relpath); + navSync.removeClass('sync'); + } else { + showSyncOn(navSync,relpath); + } + + navSync.click(() => { + const navSync = $('#nav-sync'); + if (navSync.hasClass('sync')) { + navSync.removeClass('sync'); + showSyncOff(navSync,relpath); + storeLink(stripPath2(pathName())+hashUrl()); + } else { + navSync.addClass('sync'); + showSyncOn(navSync,relpath); + deleteLink(); + } + }); + + navTo(o,toroot,hashUrl(),relpath); + showRoot(); + + $(window).bind('hashchange', () => { + if (!animationInProgress) { + if (window.location.hash && window.location.hash.length>1) { + let a; + if ($(location).attr('hash')) { + const clslink=stripPath(pathName())+':'+hashValue(); + a=$('.item a[class$="'+clslink.replace(/ try to keep right panel width + const shrinkLeft = Math.min(deficit, leftPanelWidth-minPanelWidth); + leftPanelWidth -= shrinkLeft; + const remainingDeficit = deficit - shrinkLeft; + const shrinkRight = Math.min(remainingDeficit, rightPanelWidth-minPanelWidth); + rightPanelWidth -= shrinkRight; + } else { // dragging right handle -> try to keep left panel width + const shrinkRight = Math.min(deficit, rightPanelWidth-minPanelWidth); + rightPanelWidth -= shrinkRight; + const remainingDeficit = deficit - shrinkRight; + const shrinkLeft = Math.min(remainingDeficit, leftPanelWidth-minPanelWidth); + leftPanelWidth -= shrinkLeft; + } + } else { + rightPanelWidth = pagenav.length ? Math.max(minPanelWidth,rightPanelWidth) : 0; + leftPanelWidth = Math.max(minPanelWidth,leftPanelWidth); + } + return { leftPanelWidth, rightPanelWidth } + } + + function updateWidths(sidenavWidth,pagenavWidth,dragLeft) + { + const widths = constrainPanelWidths(sidenavWidth,pagenavWidth,dragLeft); + const widthStr = parseInt(widths.leftPanelWidth)+"px"; + content.css({marginLeft:widthStr}); + if (fullSidebar) { + footer.css({marginLeft:widthStr}); + if (mainnav) { + mainnav.css({marginLeft:widthStr}); + } + } + sidenav.css({width:widthStr}); + if (pagenav.length) { + container.css({gridTemplateColumns:'auto '+parseInt(widths.rightPanelWidth)+'px'}); + pagenav.css({width:parseInt(widths.rightPanelWidth-1)+'px'}); + } + return widths; + } + + function resizeWidth(dragLeft) { + const sidenavWidth = $(sidenav).outerWidth()-barWidth; + const pagenavWidth = pagenav.length ? $(pagenav).outerWidth() : 0; + const widths = updateWidths(sidenavWidth,pagenavWidth,dragLeft); + Cookie.writeSetting(RESIZE_COOKIE_NAME,widths.leftPanelWidth-barWidth); + if (pagenav.length) { + Cookie.writeSetting(PAGENAV_COOKIE_NAME,widths.rightPanelWidth); + } + } + + function restoreWidth(sidenavWidth,pagenavWidth) { + updateWidths(sidenavWidth,pagenavWidth,false); + showHideNavBar(); + } + + function resizeHeight() { + const headerHeight = header.outerHeight(); + const windowHeight = $(window).height(); + let contentHeight; + const footerHeight = footer.outerHeight(); + let navtreeHeight,sideNavHeight; + if (!fullSidebar) { + contentHeight = windowHeight - headerHeight - footerHeight - 1; + navtreeHeight = contentHeight; + sideNavHeight = contentHeight; + } else if (fullSidebar) { + contentHeight = windowHeight - footerHeight - 1; + navtreeHeight = windowHeight - headerHeight - 1; + sideNavHeight = windowHeight - 1; + if (mainnav) { + contentHeight -= mainnav.outerHeight(); + } + } + navtree.css({height:navtreeHeight + "px"}); + sidenav.css({height:sideNavHeight + "px"}); + content.css({height:contentHeight + "px"}); + resizeWidth(false); + showHideNavBar(); + if (location.hash.slice(1)) { + (document.getElementById(location.hash.slice(1))||document.body).scrollIntoView(); + } + } + + header = $("#top"); + content = $("#doc-content"); + footer = $("#nav-path"); + sidenav = $("#side-nav"); + if (document.getElementById('main-nav')) { + mainnav = $("#main-nav"); + } + navtree = $("#nav-tree"); + pagenav = $("#page-nav"); + container = $("#container"); + $(".side-nav-resizable").resizable({resize: function(e, ui) { resizeWidth(true); } }); + $(sidenav).resizable({ minWidth: 0 }); + if (pagenav.length) { + pagehandle = $("#page-nav-resize-handle"); + pagehandle.on('mousedown touchstart',function(e) { + $('body').addClass('resizing'); + pagehandle.addClass('dragging'); + $(document).on('mousemove touchmove',function(e) { + const clientX = e.clientX || e.originalEvent.touches[0].clientX; + let pagenavWidth = container[0].offsetWidth-clientX+barWidth/2; + const sidenavWidth = sidenav.width(); + const widths = constrainPanelWidths(sidenavWidth,pagenavWidth,false); + container.css({gridTemplateColumns:'auto '+parseInt(widths.rightPanelWidth)+'px'}); + pagenav.css({width:parseInt(widths.rightPanelWidth-1)+'px'}); + content.css({marginLeft:parseInt(widths.leftPanelWidth)+'px'}); + Cookie.writeSetting(PAGENAV_COOKIE_NAME,pagenavWidth); + }); + $(document).on('mouseup touchend', function(e) { + $('body').removeClass('resizing'); + pagehandle.removeClass('dragging'); + $(document).off('mousemove mouseup touchmove touchend'); + }); + }); + } else { + container.css({gridTemplateColumns:'auto'}); + } + const width = parseInt(Cookie.readSetting(RESIZE_COOKIE_NAME,250)); + const pagenavWidth = parseInt(Cookie.readSetting(PAGENAV_COOKIE_NAME,250)); + if (width) { restoreWidth(width+barWidth,pagenavWidth); } else { resizeWidth(); } + const url = location.href; + const i=url.indexOf("#"); + if (i>=0) window.location.hash=url.substr(i); + const _preventDefault = function(evt) { evt.preventDefault(); }; + $("#splitbar").bind("dragstart", _preventDefault).bind("selectstart", _preventDefault); + $(window).ready(function() { + let lastWidth = -1; + let lastHeight = -1; + $(window).resize(function() { + const newWidth = $(this).width(), newHeight = $(this).height(); + if (newWidth!=lastWidth || newHeight!=lastHeight) { + resizeHeight(); + navtree_trampoline.updateContentTop(); + lastWidth = newWidth; + lastHeight = newHeight; + } + }); + resizeHeight(); + lastWidth = $(window).width(); + lastHeight = $(window).height(); + content.scroll(function() { + navtree_trampoline.updateContentTop(); + }); + }); + } + + + function initPageToc() { + const topMapping = []; + const toc_contents = $('#page-nav-contents'); + const content=$('