From 090b04c3b3fc7cca8b8cb5927f08657c0805a5cb Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 00:08:15 +0100 Subject: [PATCH 001/137] #77 - Create a unit test solution in a new branch dev/tests Added numbering on constructors, used for naming issues for tests. --- cpp-strings/cppstrings.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 051abbd..77e21b2 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -66,10 +66,10 @@ namespace pcs // i.e. "pythonic c++ strings" 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_id_continue(const CharT ch) noexcept; //!< Returns true if character is a continuing char for identifiers, or false otherwise. + 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_decimal(const CharT ch) noexcept; //!< Returns true if character is a decimal digit, or false otherwise. + 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. @@ -151,12 +151,12 @@ namespace pcs // i.e. "pythonic c++ strings" using value_type = CppStringT; //--- Constructors / destructor ------------------- - /** \brief Creates a TransTable from a standard map. */ + /** \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. + /** \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 @@ -170,7 +170,7 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[k] = value_type(*val_it++); } - /** \brief Creates a TransTable from three strings. + /** \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 @@ -188,7 +188,7 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[k] = CppStringT(); } - /** \brief Creates a TransTable from two initalization lists. + /** \brief Creates a TransTable from two initalization lists (#4). * * Parameters keys and values must have the same size. The i-th * character in key is associated in the translation table with @@ -203,7 +203,7 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[(*k)[0]] = *val_it++; } - /** \brief Creates a TransTable from three initalization lists. + /** \brief Creates a TransTable from three initalization lists (#5). * * Parameters keys and values must have the same size. The i-th * character in key is associated in the translation table with @@ -223,7 +223,7 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[k] = CppStringT(); } - /** \brief Creates a TransTable from two pointers to null-terminated lists of characters. + /** \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 @@ -235,7 +235,7 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[*keys++] = value_type(*values++); } - /** \brief Creates a TransTable from three pointers to null-terminated lists of characters. + /** \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 @@ -251,7 +251,7 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[*not_translated++] = CppStringT(); } - /** \brief Creates a TransTable from two containers iterators. + /** \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 @@ -266,7 +266,7 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[*key_it++] = value_type(*val_it++); } - /** \brief Creates a TransTable from three containers iterators. + /** \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 From 0bddd1f235527cdd99bb0f3a058e1cbae122ca28 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 15:22:18 +0100 Subject: [PATCH 002/137] #77 - Create a unit test solution in a new branch dev/tests Completed. --- cpp-strings-tests/cpp-strings-tests.cpp | 18 ++ cpp-strings-tests/cpp-strings-tests.vcxproj | 181 ++++++++++++++++++ .../cpp-strings-tests.vcxproj.filters | 30 +++ .../cpp-strings-tests.vcxproj.user | 6 + cpp-strings-tests/pch.cpp | 5 + cpp-strings-tests/pch.h | 12 ++ cpp-strings/cpp-strings.sln | 10 + cpp-strings/cpp-strings.vcxproj | 2 + cpp-strings/cppstrings.h | 42 ++-- 9 files changed, 285 insertions(+), 21 deletions(-) create mode 100644 cpp-strings-tests/cpp-strings-tests.cpp create mode 100644 cpp-strings-tests/cpp-strings-tests.vcxproj create mode 100644 cpp-strings-tests/cpp-strings-tests.vcxproj.filters create mode 100644 cpp-strings-tests/cpp-strings-tests.vcxproj.user create mode 100644 cpp-strings-tests/pch.cpp create mode 100644 cpp-strings-tests/pch.h diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp new file mode 100644 index 0000000..31351b5 --- /dev/null +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -0,0 +1,18 @@ +#include "pch.h" +#include "CppUnitTest.h" + +#include "cppstrings.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace cppstringstests +{ + TEST_CLASS(cppstringstests) + { + public: + + TEST_METHOD(TestMethod1) + { + } + }; +} diff --git a/cpp-strings-tests/cpp-strings-tests.vcxproj b/cpp-strings-tests/cpp-strings-tests.vcxproj new file mode 100644 index 0000000..8665d37 --- /dev/null +++ b/cpp-strings-tests/cpp-strings-tests.vcxproj @@ -0,0 +1,181 @@ + + + + + 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 + + + + Use + Level3 + true + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings;%(AdditionalIncludeDirectories) + _DEBUG;%(PreprocessorDefinitions) + true + pch.h + stdcpplatest + stdc17 + true + true + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Use + Level3 + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;%(PreprocessorDefinitions) + true + pch.h + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Use + Level3 + true + true + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Use + Level3 + true + true + true + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings;%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions) + true + pch.h + stdcpplatest + stdc17 + true + true + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + + Create + Create + Create + Create + + + + + + + + + \ 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..2a7903f --- /dev/null +++ b/cpp-strings-tests/cpp-strings-tests.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {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 + + + Source Files + + + + + Header 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-tests/pch.cpp b/cpp-strings-tests/pch.cpp new file mode 100644 index 0000000..64b7eef --- /dev/null +++ b/cpp-strings-tests/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" + +// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/cpp-strings-tests/pch.h b/cpp-strings-tests/pch.h new file mode 100644 index 0000000..9d715b0 --- /dev/null +++ b/cpp-strings-tests/pch.h @@ -0,0 +1,12 @@ +// pch.h: This is a precompiled header file. +// Files listed below are compiled only once, improving build performance for future builds. +// This also affects IntelliSense performance, including code completion and many code browsing features. +// However, files listed here are ALL re-compiled if any one of them is updated between builds. +// Do not add files here that you will be updating frequently as this negates the performance advantage. + +#ifndef PCH_H +#define PCH_H + +// add headers that you want to pre-compile here + +#endif //PCH_H diff --git a/cpp-strings/cpp-strings.sln b/cpp-strings/cpp-strings.sln index c5029ce..ad5321e 100644 --- a/cpp-strings/cpp-strings.sln +++ b/cpp-strings/cpp-strings.sln @@ -5,6 +5,8 @@ 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 @@ -21,6 +23,14 @@ Global {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 diff --git a/cpp-strings/cpp-strings.vcxproj b/cpp-strings/cpp-strings.vcxproj index 7fe9606..add61c9 100644 --- a/cpp-strings/cpp-strings.vcxproj +++ b/cpp-strings/cpp-strings.vcxproj @@ -107,6 +107,7 @@ stdcpplatest stdc17 true + true Console @@ -124,6 +125,7 @@ stdcpplatest stdc17 true + true Console diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 77e21b2..2d53983 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -288,7 +288,7 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[*key_it++] = CppStringT(); } - /** \brief Creates a TransTable from two string views. + /** \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 @@ -303,7 +303,7 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[(*k)[0]] = value_type(*val_it++); } - /** \brief Creates a TransTable from three string views. + /** \brief Creates a TransTable from three string views (#11). * * Parameters keys and values must have the same size. The i-th * character in key is associated in the translation table with @@ -353,31 +353,31 @@ namespace pcs // i.e. "pythonic c++ strings" //=== Constructors / Destructor =================== - inline CppStringT() : MyBaseClass() {} - inline CppStringT(const CppStringT& other) : MyBaseClass(other) {} - inline CppStringT(const CppStringT& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} - inline CppStringT(CppStringT&& other) : MyBaseClass(other) {} - inline CppStringT(CppStringT&& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} - inline CppStringT(MyBaseClass::size_type count, CharT ch) : MyBaseClass(count, ch) {} - inline CppStringT(const CppStringT& other, size_type pos) : MyBaseClass(other, pos) {} - inline CppStringT(const CppStringT& other, size_type pos, size_type count) noexcept : MyBaseClass(other, pos, count) {} - inline CppStringT(const CharT* s) : MyBaseClass(s) {} - inline CppStringT(const CharT* s, size_type count) : MyBaseClass(s, count) {} - inline CppStringT(std::initializer_list ilist) : MyBaseClass(ilist) {} - - inline CppStringT(const MyBaseClass& other) : MyBaseClass(other) {} - inline CppStringT(const MyBaseClass& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} - inline CppStringT(MyBaseClass&& other) : MyBaseClass(other) {} - inline CppStringT(MyBaseClass&& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} + 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) : MyBaseClass(other) {} // #4 + inline CppStringT(CppStringT&& other, const AllocatorT& alloc) : 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) : MyBaseClass(s) {} // #9 + inline CppStringT(const CharT* s, size_type count) : MyBaseClass(s, count) {} // #10 + inline CppStringT(std::initializer_list ilist) : MyBaseClass(ilist) {} // #11 + + 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) {} + inline CppStringT(InputIt first, InputIt last) : MyBaseClass(first, last) {} // #16 template - explicit CppStringT(const StringViewLike& svl) : MyBaseClass(svl) {} + explicit CppStringT(const StringViewLike& svl) : MyBaseClass(svl) {} // #17 template - CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} + CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} // #18 inline ~CppStringT() = default; From 516d82445c89e5db046374e3639676896563d0ae Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 16:00:49 +0100 Subject: [PATCH 003/137] #78 - Test pcs::is_alpha() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 9 ++++++++- cpp-strings/cppstrings.h | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 31351b5..31d01b5 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -3,6 +3,9 @@ #include "cppstrings.h" +#include + + using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace cppstringstests @@ -11,8 +14,12 @@ namespace cppstringstests { public: - TEST_METHOD(TestMethod1) + 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)); } }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 2d53983..2c86f93 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1719,12 +1719,12 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> inline const bool is_alpha(const char ch) noexcept - { return std::isalpha(static_cast(ch)); } + { return (const bool)std::isalpha(static_cast(ch)); } /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> inline const bool is_alpha(const wchar_t ch) noexcept - { return std::iswalpha(ch); } + { return (const bool)std::iswalpha(ch); } //--- is_ascii() ------------------------------------------ From 11e0bb79c354fd7f6465bcfe32df0e24fb9fcb34 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 16:03:40 +0100 Subject: [PATCH 004/137] #79 - Test pcs::is_ascii() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 31d01b5..842ef7e 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -10,7 +10,8 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace cppstringstests { - TEST_CLASS(cppstringstests) + //=== templated chars classes tests ====================== + TEST_CLASS(cppstringstests_PART_1) { public: @@ -21,5 +22,13 @@ namespace cppstringstests 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)); + } }; } From 23f2290ec929b1ec6dab97841b127500badd5688 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 16:12:07 +0100 Subject: [PATCH 005/137] #80 - Test pcs::is_decimal() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 8 ++++++++ cpp-strings/cppstrings.h | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 842ef7e..fc98992 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -30,5 +30,13 @@ namespace cppstringstests 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)); + } }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 2c86f93..133a17e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1719,12 +1719,12 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> inline const bool is_alpha(const char ch) noexcept - { return (const bool)std::isalpha(static_cast(ch)); } + { 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<> inline const bool is_alpha(const wchar_t ch) noexcept - { return (const bool)std::iswalpha(ch); } + { return static_cast(std::iswalpha(ch)); } //--- is_ascii() ------------------------------------------ @@ -1743,12 +1743,12 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if character is a decimal digit, or false otherwise. */ template<> inline const bool is_decimal(const char ch) noexcept - { return std::isdigit(static_cast(ch)); } + { return static_cast(std::isdigit(static_cast(ch))); } /** \brief Returns true if character is a decimal digit, or false otherwise. */ template<> inline const bool is_decimal(const wchar_t ch) noexcept - { return std::iswdigit(ch); } + { return (const bool)std::iswdigit(ch); } //--- is_id_continue() ------------------------------------ From b4f6791a050b69bb39e45976c7fab5d2af20e968 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 16:16:01 +0100 Subject: [PATCH 006/137] #81 - Test pcs::is_id_continue() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index fc98992..0dd5696 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -38,5 +38,14 @@ namespace cppstringstests 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)); + } + }; } From 7964acee57ed51aaba138565801c742d692aa2b8 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 16:18:25 +0100 Subject: [PATCH 007/137] #82 - Test pcs::is_id_start() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 0dd5696..5a94bb3 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -47,5 +47,13 @@ namespace cppstringstests 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)); + } + }; } From 6edec7a9feab46767fb55375b923e7817fbd2702 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 17:01:07 +0100 Subject: [PATCH 008/137] #83 - Test pcs::is_lower() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 5a94bb3..3d7667d 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -55,5 +55,12 @@ namespace cppstringstests 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)); + } }; } From aa1229375d60f1fe7524800be8b1730b3a6bfd50 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 17:09:27 +0100 Subject: [PATCH 009/137] 84 - Test pcs::is_printable() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 9 +++++++++ cpp-strings/cppstrings.h | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 3d7667d..ef34874 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -62,5 +62,14 @@ namespace cppstringstests 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)); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 133a17e..5934675 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1798,14 +1798,14 @@ namespace pcs // i.e. "pythonic c++ strings" template<> inline const bool is_printable(const char ch) noexcept { - return std::isprint(static_cast(ch)); + 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<> inline const bool is_printable(const wchar_t ch) noexcept { - return std::iswprint(ch); + return static_cast(std::iswprint(ch)); } From d0a6f1cd26b9cdcab39af28db6a08916471f7571 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 17:10:47 +0100 Subject: [PATCH 010/137] #85 - Test pcs::is_punctuation() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index ef34874..c5fa194 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -71,5 +71,13 @@ namespace cppstringstests 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)); + } + }; } From 0eacd20c8846c1d9e172842a13ce762837a1f2b6 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 17:12:16 +0100 Subject: [PATCH 011/137] #86 - Test pcs::is_space() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index c5fa194..5d11b81 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -79,5 +79,13 @@ namespace cppstringstests 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)); + } + }; } From 0575557d4e7c630be08558796c18c07d0dcd2c4d Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 17:14:26 +0100 Subject: [PATCH 012/137] #87 - Test pcs::is_upper() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 7 +++++++ cpp-strings/cppstrings.h | 12 ++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 5d11b81..7d8fef7 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -87,5 +87,12 @@ namespace cppstringstests 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)); + } }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 5934675..e12e924 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1818,12 +1818,12 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ template<> inline const bool is_punctuation(const char ch) noexcept - { return std::ispunct(static_cast(ch)); } + { 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<> inline const bool is_punctuation(const wchar_t ch) noexcept - { return std::iswpunct(ch); } + { return static_cast(std::iswpunct(ch)); } //--- is_space() ------------------------------------------ @@ -1835,12 +1835,12 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> inline const bool is_space(const char ch) noexcept - { return std::isspace(static_cast(ch)); } + { 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<> inline const bool is_space(const wchar_t ch) noexcept - { return std::iswspace(ch); } + { return static_cast(std::iswspace(ch)); } //--- is_upper() ------------------------------------------ @@ -1855,14 +1855,14 @@ namespace pcs // i.e. "pythonic c++ strings" template<> inline const bool is_upper(const char ch) noexcept { - return std::isupper(static_cast(ch)); + 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<> inline const bool is_upper(const wchar_t ch) noexcept { - return std::iswupper(ch); + return static_cast(std::iswupper(ch)); } From 2d6e5cd37a304c0bfa7bb9aab08c4e0169ca04e3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 17:49:31 +0100 Subject: [PATCH 013/137] #88 - Test pcs::swap_case() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 7d8fef7..25b2345 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -94,5 +94,29 @@ namespace cppstringstests 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); + } + } + }; } From 060d0e6e4b1c04784cf0fa929d7abae04ac1f088 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 17:55:48 +0100 Subject: [PATCH 014/137] #89 - Test pcs::to_lower() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 25b2345..0344af1 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -118,5 +118,24 @@ namespace cppstringstests } } + 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); + } + } + }; } From d4d697be8a720280c6d09b00057c32bda5ca5062 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 17:58:59 +0100 Subject: [PATCH 015/137] #90 - Test pcs::to_upper() for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 0344af1..da90802 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -137,5 +137,24 @@ namespace cppstringstests } } + 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); + } + } + }; } From 37f45bef1bc521c8f1efa667288392beee2ed038 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 19:31:59 +0100 Subject: [PATCH 016/137] #91 - Test pcs::operator""cs for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index da90802..308502f 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -156,5 +156,14 @@ namespace cppstringstests } } + TEST_METHOD(_cs) + { + using namespace pcs; + auto abcd = "abcD"cs; + auto wabcd = L"abcD"cs; + Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); + Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); + } + }; } From 435385fc119f247d74e3834ca118b2d6cba7c6a3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 19:33:33 +0100 Subject: [PATCH 017/137] #92 - Test pcs::operator""csv for char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 308502f..b8cbf0f 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -165,5 +165,14 @@ namespace cppstringstests Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); } + TEST_METHOD(_csv) + { + using namespace pcs; + auto abcd = "abcD"csv; + auto wabcd = L"abcD"csv; + Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); + Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); + } + }; } From 345ed73bdf9e41694e06e8a3d8b397925c345108 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 19:57:16 +0100 Subject: [PATCH 018/137] #93 - Test CppStringT::TransTable constructor #1 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 171 ++--------------------- cpp-strings-tests/pch.cpp | 176 ++++++++++++++++++++++++ cpp-strings-tests/pch.h | 3 + 3 files changed, 190 insertions(+), 160 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index b8cbf0f..0d97b35 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -1,177 +1,28 @@ #include "pch.h" #include "CppUnitTest.h" -#include "cppstrings.h" +using namespace Microsoft::VisualStudio::CppUnitTestFramework; -#include +#include "cppstrings.h" +using namespace pcs; -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - namespace cppstringstests { //=== templated chars classes tests ====================== - TEST_CLASS(cppstringstests_PART_1) + TEST_CLASS(cppstringstests_PART_2) { public: - TEST_METHOD(is_alpha) + TEST_METHOD(constructor_01) { - 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)); - } + 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()); - 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); - } - } - - TEST_METHOD(_cs) - { - using namespace pcs; - auto abcd = "abcD"cs; - auto wabcd = L"abcD"cs; - Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); - Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); - } - - TEST_METHOD(_csv) - { - using namespace pcs; - auto abcd = "abcD"csv; - auto wabcd = L"abcD"csv; - Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); - Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).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()); } }; diff --git a/cpp-strings-tests/pch.cpp b/cpp-strings-tests/pch.cpp index 64b7eef..14001e8 100644 --- a/cpp-strings-tests/pch.cpp +++ b/cpp-strings-tests/pch.cpp @@ -3,3 +3,179 @@ #include "pch.h" // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. + + +#include "cppstrings.h" + +#include + +namespace cppstringstests +{ + + //===== PART 1 ============================================ + TEST_CLASS(cppstringstests_PART_1) + { + public: + + 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); + } + } + + TEST_METHOD(_cs) + { + using namespace pcs; + auto abcd = "abcD"cs; + auto wabcd = L"abcD"cs; + Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); + Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); + } + + TEST_METHOD(_csv) + { + using namespace pcs; + auto abcd = "abcD"csv; + auto wabcd = L"abcD"csv; + Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); + Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); + } + + }; + +} \ No newline at end of file diff --git a/cpp-strings-tests/pch.h b/cpp-strings-tests/pch.h index 9d715b0..70c7d10 100644 --- a/cpp-strings-tests/pch.h +++ b/cpp-strings-tests/pch.h @@ -8,5 +8,8 @@ #define PCH_H // add headers that you want to pre-compile here +#include "CppUnitTest.h" +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + #endif //PCH_H From 166e6e218fef1c947b74f302d4d9b562e858e863 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 00:01:14 +0100 Subject: [PATCH 019/137] #94 - Test CppStringT::TransTable constructor #2 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 12 ++++++++++ cpp-strings/cppstrings.h | 31 ++++++++++++++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 0d97b35..2f7f916 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -25,5 +25,17 @@ namespace cppstringstests Assert::AreEqual(L"a"cs.c_str(), wtable['b'].c_str()); } + TEST_METHOD(constructor_02) + { + CppString keys("abcdE"); + CppString values("ABCDe"); + pcs::CppString::TransTable t(keys, values); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString('D').c_str(), t['d'].c_str()); + Assert::AreEqual(CppString('e').c_str(), t['E'].c_str()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index e12e924..8d11e73 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -167,7 +167,8 @@ namespace pcs // i.e. "pythonic c++ strings" assert(keys.size() == values.size()); auto val_it = values.cbegin(); for (const auto k : keys) - m_table[k] = value_type(*val_it++); + m_table[k] = CppStringT(*val_it++); + //m_table[k] = value_type(*val_it++); } /** \brief Creates a TransTable from three strings (#3). @@ -339,8 +340,8 @@ namespace pcs // i.e. "pythonic c++ strings" return *this; } - /** \biref Indexing operator. */ - inline CppStringT operator[] (const key_type ch) const noexcept + /** \brief Indexing operator. */ + inline CppStringT operator[] (const key_type ch) noexcept { try { return m_table[ch]; @@ -349,10 +350,13 @@ namespace pcs // i.e. "pythonic c++ strings" return CppStringT(); } } + + private: + std::map m_table{}; // the internal storage of the translation table. Access it via the indexing operator. }; - //=== Constructors / Destructor =================== + //=== 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 @@ -365,6 +369,8 @@ namespace pcs // i.e. "pythonic c++ strings" inline CppStringT(const CharT* s, size_type count) : MyBaseClass(s, count) {} // #10 inline CppStringT(std::initializer_list ilist) : MyBaseClass(ilist) {} // #11 + inline CppStringT(const CharT ch) : MyBaseClass(&ch, 1) {} // #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 @@ -379,7 +385,12 @@ namespace pcs // i.e. "pythonic c++ strings" template CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} // #18 - inline ~CppStringT() = default; + inline ~CppStringT() noexcept = default; + + + //=== Assignment operators ============================ + CppStringT& operator= (const CppStringT&) noexcept = default; //!< Default copy assignment + CppStringT& operator= (CppStringT&&) noexcept = default; //!< Default move assignment //=== Exceptions ====================================== @@ -1676,10 +1687,6 @@ namespace pcs // i.e. "pythonic c++ strings" return this->ljust(padding_width, value_type('0')); } - - private: - std::map m_table{}; // the itnernal storage of the translation table. Access it via the indexing operator. - }; @@ -1693,7 +1700,8 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Forms a CppString view literal. */ inline const CppString operator""csv(const char* str, std::size_t len) { - return CppString(CppString::MyStringView(str, len)); + //return CppString(CppString::MyStringView(str, len)); + return CppString(str, len); } /** \brief Forms a CppWString literal. */ @@ -1705,7 +1713,8 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Forms a CppWString view literal. */ inline const CppWString operator""csv(const wchar_t* str, std::size_t len) { - return CppWString(CppWString::MyStringView(str, len)); + //return CppWString(CppWString::MyStringView(str, len)); + return CppWString(str, len); } From 151260cfeff6aa392db84a8243b08355f59f02c3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 00:24:26 +0100 Subject: [PATCH 020/137] #95 - Test CppStringT::TransTable constructor #3 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 28 +++++++++++++++++++++++++ cpp-strings/cppstrings.h | 12 +++++------ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 2f7f916..de26379 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -35,6 +35,34 @@ namespace cppstringstests Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); Assert::AreEqual(CppString('D').c_str(), t['d'].c_str()); Assert::AreEqual(CppString('e').c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abcdE"), CppWString(L"ABCDe")); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString(L'D').c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString(L'e').c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_03) + { + pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); } }; diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 8d11e73..bbf6a41 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -168,7 +168,6 @@ namespace pcs // i.e. "pythonic c++ strings" auto val_it = values.cbegin(); for (const auto k : keys) m_table[k] = CppStringT(*val_it++); - //m_table[k] = value_type(*val_it++); } /** \brief Creates a TransTable from three strings (#3). @@ -184,7 +183,7 @@ namespace pcs // i.e. "pythonic c++ strings" assert(keys.size() == values.size()); auto val_it = values.cbegin(); for (const auto k : keys) - m_table[k] = value_type(*val_it++); + m_table[k] = CppStringT(*val_it++); for (const auto k : not_translated) m_table[k] = CppStringT(); } @@ -343,11 +342,12 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Indexing operator. */ inline CppStringT operator[] (const key_type ch) noexcept { - try { - return m_table[ch]; + auto it = m_table.find(ch); + if (it != m_table.end()) { + return it->second; } - catch (...) { - return CppStringT(); + else { + return CppStringT(ch); } } From 7f12c488b1b9d5f4d8a22334b8d2fb9322c1df48 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 00:32:52 +0100 Subject: [PATCH 021/137] #96 - Test CppStringT::TransTable constructor #4 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 16 ++++++++++++++++ cpp-strings/cppstrings.h | 11 +++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index de26379..8362b37 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -65,5 +65,21 @@ namespace cppstringstests Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); } + TEST_METHOD(constructor_04) + { + pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }); + Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }); + Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString(L'9').c_str(), wt[L'9'].c_str()); + } + + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index bbf6a41..b8ddf35 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -188,22 +188,21 @@ namespace pcs // i.e. "pythonic c++ strings" m_table[k] = CppStringT(); } - /** \brief Creates a TransTable from two initalization lists (#4). + /** \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 std::initializer_list keys, - const std::initializer_list values) + inline TransTable(const CppStringT& keys, const std::initializer_list& values) { assert(keys.size() == values.size()); - auto val_it = values.cbegin(); + auto val_it = values.begin(); for (const auto k : keys) - m_table[(*k)[0]] = *val_it++; + m_table[k] = *val_it++; } - /** \brief Creates a TransTable from three initalization lists (#5). + /** \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 From 61cdb2e7da3e0734cf6f608bf6858e9200ecea66 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 00:36:52 +0100 Subject: [PATCH 022/137] #97 - Test CppStringT::TransTable constructor #5 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 19 +++++++++++++++++++ cpp-strings/cppstrings.h | 8 +++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 8362b37..4b3ec9c 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -80,6 +80,25 @@ namespace cppstringstests Assert::AreEqual(CppWString(L'9').c_str(), wt[L'9'].c_str()); } + TEST_METHOD(constructor_05) + { + pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }, "dE"cs); + Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }, L"dE"cs); + Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'e').c_str(), wt[L'e'].c_str()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index b8ddf35..332ec16 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -210,14 +210,12 @@ namespace pcs // i.e. "pythonic c++ strings" * contained in string not_translated are associated in the * translation table with the empty string. */ - inline TransTable(const std::initializer_list keys, - const std::initializer_list values, - const CppStringT& not_translated) + inline TransTable(const CppStringT& keys, const std::initializer_list values, const CppStringT& not_translated) { assert(keys.size() == values.size()); - auto val_it = values.cbegin(); + auto val_it = values.begin(); for (const auto k : keys) - m_table[(*k)[0]] = *val_it++; + m_table[k] = *val_it++; for (const auto k : not_translated) m_table[k] = CppStringT(); } From 59d8d800adee1e0988d2a92f86232a9b1efb3e9b Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 00:40:14 +0100 Subject: [PATCH 023/137] #98 - Test CppStringT::TransTable constructor #6 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 4b3ec9c..a550b73 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -99,6 +99,21 @@ namespace cppstringstests Assert::AreEqual(CppWString(L'e').c_str(), wt[L'e'].c_str()); } + TEST_METHOD(constructor_06) + { + pcs::CppString::TransTable t("abC", "ABc"); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['c'].c_str()); + + pcs::CppWString::TransTable wt(L"abC", L"ABc"); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); + } + }; } From adde769172548bb2f65d9ae118d23a9c9b5d12b9 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 00:42:34 +0100 Subject: [PATCH 024/137] #99 - Test CppStringT::TransTable constructor #7 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index a550b73..68345c5 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -114,6 +114,25 @@ namespace cppstringstests Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); } + TEST_METHOD(constructor_07) + { + pcs::CppString::TransTable t("abc", "ABC", "dE"); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('e').c_str(), t['e'].c_str()); + + pcs::CppWString::TransTable wt(L"abc", L"ABC", L"dE"); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'A'].c_str()); + } + }; } From 6e166c8e203caed5b63749c66dbfe43f5aee2b5e Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 01:09:51 +0100 Subject: [PATCH 025/137] #100 - Test CppStringT::TransTable constructor #8 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 19 +++++++++++++++++++ cpp-strings/cppstrings.h | 12 ++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 68345c5..315550a 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -133,6 +133,25 @@ namespace cppstringstests Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 332ec16..b4d2582 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -236,9 +236,9 @@ namespace pcs // i.e. "pythonic c++ strings" * * 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. + * 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) { @@ -250,9 +250,9 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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 character in values. + * 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) From de72dc61dafee02dbd4a308f9ec2b87d0b476e7f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 06:17:52 +0100 Subject: [PATCH 026/137] #101 - Test CppStringT::TransTable constructor #9 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 25 +++++++++++++++++++++++++ cpp-strings/cppstrings.h | 20 ++++++++++---------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 315550a..4e0a990 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -152,6 +152,31 @@ namespace cppstringstests Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index b4d2582..56cf2e1 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -271,18 +271,18 @@ namespace pcs // i.e. "pythonic c++ strings" * contained in string not_translated are associated in the * translation table with the empty string. */ - template - inline TransTable(KeyIt first_key, KeyIt last_key, - ValueIt first_value, ValueIt last_value, - KeyIt first_not_translated, KeyIt last_not_translated) + template + inline TransTable(Key1It first_key, Key1It last_key, + ValueIt first_value, ValueIt last_value, + Key2It first_not_translated, Key2It last_not_translated) { - KeyIt key_it{ first_key }; + Key1It key1_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++); - key_it = first_not_translated; - while (key_it != last_not_translated) - m_table[*key_it++] = CppStringT(); + 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). From e861148faf64bbf91f12938fd56410ef5ba6b16f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 06:36:09 +0100 Subject: [PATCH 027/137] #104 - Test CppStringT::TransTable empty constructor with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 8 ++++++++ cpp-strings/cppstrings.h | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 4e0a990..2070dfd 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -177,6 +177,14 @@ namespace cppstringstests Assert::AreEqual(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()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 56cf2e1..4ba964d 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -291,6 +291,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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) { @@ -299,6 +300,7 @@ namespace pcs // i.e. "pythonic c++ strings" for (const auto k : keys) m_table[(*k)[0]] = value_type(*val_it++); } + /**/ /** \brief Creates a TransTable from three string views (#11). * @@ -308,6 +310,7 @@ namespace pcs // i.e. "pythonic c++ strings" * contained in string not_translated are associated in the * translation table with the empty string. */ + /** / template TransTable(const StringViewLike& keys, const StringViewLike& values, const StringViewLike& not_translated) { @@ -318,6 +321,7 @@ namespace pcs // i.e. "pythonic c++ strings" for (const auto k : not_translated) m_table[k] = CppStringT(); } + /**/ inline TransTable() noexcept = default; //!< Default empty constructor. inline TransTable(const TransTable&) noexcept = default; //!< Default copy constructor. @@ -348,6 +352,11 @@ namespace pcs // i.e. "pythonic c++ strings" } } + 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. }; From 4d1fa4dcc6f8725e4a75b62059932687b97b3990 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 10:50:52 +0100 Subject: [PATCH 028/137] #105 - Test CppStringT::TransTable copy constructor with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 21 +++++++++++++++++++++ cpp-strings-tests/pch.h | 1 + 2 files changed, 22 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 2070dfd..c4377ee 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -181,10 +181,31 @@ namespace cppstringstests { 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(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t(ct); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt(wct); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } }; } diff --git a/cpp-strings-tests/pch.h b/cpp-strings-tests/pch.h index 70c7d10..4417be9 100644 --- a/cpp-strings-tests/pch.h +++ b/cpp-strings-tests/pch.h @@ -11,5 +11,6 @@ #include "CppUnitTest.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; +#include #endif //PCH_H From 320109ecac69c61bc89fa9eb415b1e9bcaeea579 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 10:52:37 +0100 Subject: [PATCH 029/137] #106 - Test CppStringT::TransTable move constructor with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index c4377ee..6f557b6 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -207,5 +207,26 @@ namespace cppstringstests Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); } + TEST_METHOD(constructor_move) + { + pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t(std::move(ct)); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt(std::move(wct)); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + }; } From 8a94ae4afc96b4118d514046097477b061e660b4 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 10:54:31 +0100 Subject: [PATCH 030/137] #107 - Test CppStringT::TransTable copy assignment with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 6f557b6..ad2c39d 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -228,5 +228,25 @@ namespace cppstringstests Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); } + TEST_METHOD(assign_copy) + { + pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t = ct; + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt = wct; + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } }; } From 755de7849db302a8bb52abcf127cf40a4157a50a Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 10:56:42 +0100 Subject: [PATCH 031/137] #108 - Test CppStringT::TransTable move assignment with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 30 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index ad2c39d..6d3e016 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -209,8 +209,8 @@ namespace cppstringstests TEST_METHOD(constructor_move) { - pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t(std::move(ct)); + pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t(std::move(mt)); Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); @@ -218,8 +218,8 @@ namespace cppstringstests Assert::AreEqual(CppString().c_str(), t['E'].c_str()); Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt(std::move(wct)); + pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt(std::move(wmt)); Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); @@ -248,5 +248,27 @@ namespace cppstringstests Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); } + + TEST_METHOD(assign_move) + { + pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t = std::move(mt); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt = std::move(wmt); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + }; } From e67fa5a4cd2c876a676bbadc24a2d475749f6b58 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 10:58:47 +0100 Subject: [PATCH 032/137] #109 - Test CppStringT::TransTable std::map-assignment with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 6d3e016..d37143e 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -270,5 +270,26 @@ namespace cppstringstests Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); } + TEST_METHOD(assign_map) + { + pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t = ct.get_table(); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt = wct.get_table(); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + }; } From b9efdfe61c11d1cd3e5cac9e869150ffee304c4e Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:03:35 +0100 Subject: [PATCH 033/137] #110 - Test CppStringT::TransTable::operator[] with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d37143e..1970c25 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -291,5 +291,23 @@ namespace cppstringstests Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); } + TEST_METHOD(indexing) + { + pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString(',').c_str(), t[','].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'\n').c_str(), wt[L'\n'].c_str()); + } }; } From 31399dd3461754f681dafbfd74c64fbc83040a39 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:12:15 +0100 Subject: [PATCH 034/137] #111 - Test CppStringT empty constructor with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 296 +---------------------- cpp-strings-tests/pch.cpp | 307 ++++++++++++++++++++++++ 2 files changed, 312 insertions(+), 291 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 1970c25..4550f2f 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -9,305 +9,19 @@ using namespace pcs; namespace cppstringstests { - //=== templated chars classes tests ====================== - TEST_CLASS(cppstringstests_PART_2) + TEST_CLASS(cppstringstests_PART_3) { public: - TEST_METHOD(constructor_01) - { - 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) - { - CppString keys("abcdE"); - CppString values("ABCDe"); - pcs::CppString::TransTable t(keys, values); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString('D').c_str(), t['d'].c_str()); - Assert::AreEqual(CppString('e').c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abcdE"), CppWString(L"ABCDe")); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString(L'D').c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString(L'e').c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(constructor_03) - { - pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(constructor_04) - { - pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }); - Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }); - Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString(L'9').c_str(), wt[L'9'].c_str()); - } - - TEST_METHOD(constructor_05) - { - pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }, "dE"cs); - Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }, L"dE"cs); - Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'e').c_str(), wt[L'e'].c_str()); - } - - TEST_METHOD(constructor_06) - { - pcs::CppString::TransTable t("abC", "ABc"); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['c'].c_str()); - - pcs::CppWString::TransTable wt(L"abC", L"ABc"); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); - } - - TEST_METHOD(constructor_07) - { - pcs::CppString::TransTable t("abc", "ABC", "dE"); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('e').c_str(), t['e'].c_str()); - - pcs::CppWString::TransTable wt(L"abc", L"ABC", L"dE"); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); - Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); - Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(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::CppString s; + Assert::IsTrue(s.empty()); - pcs::CppWString::TransTable wt; - Assert::IsTrue(wt.get_table().empty()); + pcs::CppWString ws; + Assert::IsTrue(ws.empty()); } - TEST_METHOD(constructor_copy) - { - pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t(ct); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt(wct); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(constructor_move) - { - pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t(std::move(mt)); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt(std::move(wmt)); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(assign_copy) - { - pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t = ct; - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt = wct; - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(assign_move) - { - pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t = std::move(mt); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt = std::move(wmt); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(assign_map) - { - pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t = ct.get_table(); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt = wct.get_table(); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(indexing) - { - pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString(',').c_str(), t[','].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'\n').c_str(), wt[L'\n'].c_str()); - } }; } diff --git a/cpp-strings-tests/pch.cpp b/cpp-strings-tests/pch.cpp index 14001e8..06d53af 100644 --- a/cpp-strings-tests/pch.cpp +++ b/cpp-strings-tests/pch.cpp @@ -6,6 +6,7 @@ #include "cppstrings.h" +using namespace pcs; #include @@ -175,7 +176,313 @@ namespace cppstringstests Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); } + }; + + + //===== PART 2 ============================================ + TEST_CLASS(cppstringstests_PART_2) + { + public: + + TEST_METHOD(constructor_01) + { + 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) + { + CppString keys("abcdE"); + CppString values("ABCDe"); + pcs::CppString::TransTable t(keys, values); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString('D').c_str(), t['d'].c_str()); + Assert::AreEqual(CppString('e').c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abcdE"), CppWString(L"ABCDe")); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString(L'D').c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString(L'e').c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_03) + { + pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_04) + { + pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }); + Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }); + Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString(L'9').c_str(), wt[L'9'].c_str()); + } + + TEST_METHOD(constructor_05) + { + pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }, "dE"cs); + Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }, L"dE"cs); + Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'e').c_str(), wt[L'e'].c_str()); + } + + TEST_METHOD(constructor_06) + { + pcs::CppString::TransTable t("abC", "ABc"); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['c'].c_str()); + pcs::CppWString::TransTable wt(L"abC", L"ABc"); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); + } + + TEST_METHOD(constructor_07) + { + pcs::CppString::TransTable t("abc", "ABC", "dE"); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('e').c_str(), t['e'].c_str()); + + pcs::CppWString::TransTable wt(L"abc", L"ABC", L"dE"); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(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(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t(ct); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt(wct); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_move) + { + pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t(std::move(mt)); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt(std::move(wmt)); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(assign_copy) + { + pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t = ct; + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt = wct; + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(assign_move) + { + pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t = std::move(mt); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt = std::move(wmt); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(assign_map) + { + pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t = ct.get_table(); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt = wct.get_table(); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(indexing) + { + pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString(',').c_str(), t[','].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'\n').c_str(), wt[L'\n'].c_str()); + } }; + + //===== PART 3 ============================================ + + } \ No newline at end of file From 8b862ac5c40faded6e49e718b565b6fd5f290104 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:15:15 +0100 Subject: [PATCH 035/137] #112 - Test CppStringT copy constructor with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 4550f2f..e61731e 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -22,6 +22,16 @@ namespace cppstringstests 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()); + } }; } From 8ada1a97fad8e69efa5a3ff9f3cd3028b5124288 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:16:56 +0100 Subject: [PATCH 036/137] #113 - Test CppStringT move constructor with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index e61731e..0ffb0c0 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -33,5 +33,16 @@ namespace cppstringstests 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()); + } + }; } From f39c9aafed41fb43df6f30583da027c15d29c160 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:22:29 +0100 Subject: [PATCH 037/137] #114 - Test CppStringT constructor #6 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 0ffb0c0..68d1652 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -44,5 +44,15 @@ namespace cppstringstests 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()); + } }; } From ab90c70166761582988a71d4227a55d9ec0d80b4 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:33:07 +0100 Subject: [PATCH 038/137] #115 - Test CppStringT constructor #7 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 14 ++++++++++++++ cpp-strings/cppstrings.h | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 68d1652..5d2ceec 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -54,5 +54,19 @@ namespace cppstringstests 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()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 4ba964d..382e7ab 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -366,8 +366,8 @@ namespace pcs // i.e. "pythonic c++ strings" 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) : MyBaseClass(other) {} // #4 - inline CppStringT(CppStringT&& other, const AllocatorT& alloc) : MyBaseClass(other, alloc) {} // #5 + 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 From 8893fd5762fe2b4c39d2393c5878cf7e3270c726 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:35:02 +0100 Subject: [PATCH 039/137] #116 - Test CppStringT constructor #8 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 5d2ceec..d8265a4 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -65,8 +65,20 @@ namespace cppstringstests 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()); + 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()); + } }; } From c6268ecec07068bd3385638f7e471c44c19f01ca Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:36:51 +0100 Subject: [PATCH 040/137] #117 - Test CppStringT constructor #9 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d8265a4..f79e447 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -80,5 +80,18 @@ namespace cppstringstests 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()); + } + + }; } From fb662fc51090c93d2e05a7c0dcd9e20cf8915a2e Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:38:47 +0100 Subject: [PATCH 041/137] #118 - Test CppStringT constructor #10 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index f79e447..2fcd286 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -92,6 +92,17 @@ namespace cppstringstests Assert::AreEqual(pcs::CppWString(L"ABCdefGH").c_str(), ws.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()); + } + }; } From ceebe190a7d69829e5a7b370db3d255539bbacba Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:41:03 +0100 Subject: [PATCH 042/137] #119 - Test CppStringT constructor #11 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 2fcd286..358ad65 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -103,6 +103,17 @@ namespace cppstringstests Assert::AreEqual(pcs::CppWString(L"ABCdefG").c_str(), ws.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()); + } + }; } From b02b5163b8103955f6d3179b6e034c9584bcde01 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:43:54 +0100 Subject: [PATCH 043/137] #120 - Test CppStringT constructor #12 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 358ad65..c9032ba 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -114,6 +114,18 @@ namespace cppstringstests 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()); + } }; } From cf190aa12b9b512a6b81d1638df3b85e5699b8bb Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 11:51:22 +0100 Subject: [PATCH 044/137] #121 - Test CppStringT constructor #13 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index c9032ba..2c7a9c3 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -127,5 +127,18 @@ namespace cppstringstests 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()); + } + }; } From 6c41fdefaa4737e3127d77e3f3f2d19fe364e055 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 18:01:11 +0100 Subject: [PATCH 045/137] #122 - Test CppStringT constructor #14 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 2c7a9c3..31bd769 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -140,5 +140,33 @@ namespace cppstringstests 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(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()); + } + /**/ + }; } From 487b5ccff1a9dd18f0a429d86d6ec4a8a4f85855 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 18:02:36 +0100 Subject: [PATCH 046/137] #123 - Test CppStringT constructor #15 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 31bd769..a623048 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -153,20 +153,18 @@ namespace cppstringstests Assert::AreEqual(pcs::CppWString(L"ABCdefGH").c_str(), ws.c_str()); } - /** / TEST_METHOD(constructor_15) { std::string cs("abcDEfgh"); - pcs::CppString s(cs, cs.get_allocator()); + 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(wcs, wcs.get_allocator()); + 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()); } - /**/ }; } From 401945c338b9c0b923a61d55843d1864810baa44 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 18:04:43 +0100 Subject: [PATCH 047/137] #124 - Test CppStringT constructor #16 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index a623048..82630ce 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -166,5 +166,17 @@ namespace cppstringstests 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()); + } }; } From e53011dc7ab6d7a2a84364297988f1f02758cdd3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 18:14:26 +0100 Subject: [PATCH 048/137] #179 - Test CppStringT constructor #19 with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 82630ce..11156a4 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -178,5 +178,17 @@ namespace cppstringstests 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()); + } + }; } From b1c2abc9e2307f20465a8302594d97726ca7c2cb Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 18:32:09 +0100 Subject: [PATCH 049/137] #127 - Test CppStringT::capitalize() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 180 ++--------------------- cpp-strings-tests/pch.cpp | 184 ++++++++++++++++++++++++ cpp-strings/cppstrings.h | 15 +- 3 files changed, 200 insertions(+), 179 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 11156a4..51b3956 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -9,186 +9,22 @@ using namespace pcs; namespace cppstringstests { - TEST_CLASS(cppstringstests_PART_3) + TEST_CLASS(cppstringstests_PART_4) { public: - TEST_METHOD(constructor_empty) + TEST_METHOD(capitalize) { - pcs::CppString s; - Assert::IsTrue(s.empty()); + 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()); - 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()); - } - - 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()); + s = "capitalize Capitalize. CAPITALIZE"; + Assert::AreEqual(pcs::CppString("Capitalize capitalize. capitalize").c_str(), s.capitalize().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::CppWString ws(L"123AHBl!"); + Assert::AreEqual(pcs::CppWString(L"123ahbl!").c_str(), ws.capitalize().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()); - } }; } diff --git a/cpp-strings-tests/pch.cpp b/cpp-strings-tests/pch.cpp index 06d53af..24020cd 100644 --- a/cpp-strings-tests/pch.cpp +++ b/cpp-strings-tests/pch.cpp @@ -483,6 +483,190 @@ namespace cppstringstests //===== 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()); + } + + 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()); + } + + 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 ======================================== + } \ No newline at end of file diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 382e7ab..0a9c420 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -413,14 +413,15 @@ namespace pcs // i.e. "pythonic c++ strings" //=== Methods ========================================= //--- capitalize() ------------------------------------ - /** \brief In-place modifies the string with its first character capitalized and the rest lowercased. Returns a reference to the string*/ - inline CppStringT& capitalize() noexcept + /** \brief Returns a copy of the string with its first character capitalized and the rest lowercased. */ + inline CppStringT capitalize() noexcept { - if (!this->empty()) { - this->lower(); - (*this)[0] = pcs::to_upper((*this)[0]); + CppStringT res(*this); + if (!res.empty()) { + res.lower(); + res[0] = pcs::to_upper(res[0]); } - return *this; + return res; } @@ -863,7 +864,7 @@ namespace pcs // i.e. "pythonic c++ strings" { std::transform(this->begin(), this->end(), this->begin(), - [](value_type ch) { return this->lower(ch); }); + [&](value_type ch) { return this->lower(ch); }); return *this; } From 9814e6dccd9518c237c49d0c2b228cce6cffa554 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 18:43:23 +0100 Subject: [PATCH 050/137] #128 - Test CppStringT::center() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 19 +++++++++++++++++++ cpp-strings/cppstrings.h | 13 +++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 51b3956..e102a77 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -25,6 +25,25 @@ namespace cppstringstests 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).c_str(), L"--1--"); + Assert::AreEqual(pcs::CppWString(L" zyxwvutsrqp ").c_str(), ws.center(14).c_str(), L"--2--"); + Assert::AreEqual(pcs::CppWString(L" zyxwvutsrqp ").c_str(), ws.center(13).c_str(), L"--3--"); + Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp ").c_str(), ws.center(12).c_str(), L"--4--"); + Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp").c_str(), ws.center(11).c_str(), L"--5--"); + Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp").c_str(), ws.center(10).c_str(), L"--6--"); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 0a9c420..144917e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -375,7 +375,7 @@ namespace pcs // i.e. "pythonic c++ strings" inline CppStringT(const CharT* s, size_type count) : MyBaseClass(s, count) {} // #10 inline CppStringT(std::initializer_list ilist) : MyBaseClass(ilist) {} // #11 - inline CppStringT(const CharT ch) : MyBaseClass(&ch, 1) {} // #19 + 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 @@ -426,7 +426,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- center() ---------------------------------------- - /** \brief Returns the string centered in a string of length width. + /** \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 @@ -434,11 +434,12 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept { - const size_type l{ this->size() }; - if (l <= width) + const size_type len{ this->size() }; + if (width <= len) return CppStringT(*this); - const size_type half{ (width - l) / 2 }; - return CppStringT(fillch, half) + *this + CppStringT(fillch, width - half - l); + + const size_type half{ (width - len) / 2 }; + return CppStringT(half, fillch) + *this + CppStringT(width - half - len, fillch); } From a54feb60a9581c39ef95c6df9424f7c3203a3c0e Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 22:47:47 +0100 Subject: [PATCH 051/137] #129 - Test CppStringT::count() with char and wchar_t Tested. Fixed bugs. --- cpp-strings-tests/cpp-strings-tests.cpp | 37 +++++++++++++++++++++---- cpp-strings/cppstrings.h | 34 +++++++++++++++-------- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index e102a77..9538733 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -36,12 +36,37 @@ namespace cppstringstests 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).c_str(), L"--1--"); - Assert::AreEqual(pcs::CppWString(L" zyxwvutsrqp ").c_str(), ws.center(14).c_str(), L"--2--"); - Assert::AreEqual(pcs::CppWString(L" zyxwvutsrqp ").c_str(), ws.center(13).c_str(), L"--3--"); - Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp ").c_str(), ws.center(12).c_str(), L"--4--"); - Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp").c_str(), ws.center(11).c_str(), L"--5--"); - Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp").c_str(), ws.center(10).c_str(), L"--6--"); + 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(count) + { + pcs::CppString s("abcabcabcdefabca bca bcabca"); + Assert::AreEqual(3ULL, s.count("abca")); + Assert::AreEqual(6ULL, s.count("bca")); + Assert::AreEqual(0ULL, s.count("A")); + Assert::AreEqual(2ULL, s.count("abca", 4)); + Assert::AreEqual(5ULL, s.count("bca", 2)); + Assert::AreEqual(0ULL, s.count("A", 3)); + Assert::AreEqual(1ULL, s.count("abca", 4, s.size() - 5)); + Assert::AreEqual(4ULL, s.count("bca", 2, s.size() - 2)); + Assert::AreEqual(0ULL, s.count("A", 3, s.size() + 4)); + + pcs::CppWString ws(L"abcabcabcdefabca bca bcabca"); + Assert::AreEqual(3ULL, ws.count(L"abca")); + Assert::AreEqual(6ULL, ws.count(L"bca")); + Assert::AreEqual(0ULL, ws.count(L"A")); + Assert::AreEqual(2ULL, ws.count(L"abca", 4)); + Assert::AreEqual(5ULL, ws.count(L"bca", 2)); + Assert::AreEqual(0ULL, ws.count(L"A", 3)); + Assert::AreEqual(1ULL, ws.count(L"abca", 4, s.size() - 5)); + Assert::AreEqual(4ULL, ws.count(L"bca", 2, s.size() - 2)); + Assert::AreEqual(0ULL, ws.count(L"A", 3, s.size() + 4)); } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 144917e..50c4b0c 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -432,7 +432,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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. */ - inline CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept + CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept { const size_type len{ this->size() }; if (width <= len) @@ -445,15 +445,21 @@ namespace pcs // i.e. "pythonic c++ strings" //--- count() ----------------------------------------- /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, end]. */ - inline constexpr size_type count(const CppStringT& sub, const size_type start = 0, const size_type end = 0) const noexcept + constexpr size_type count(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept { - const size_type length{ this->size() }; - const size_type end_{ (end == 0) ? length : end }; - size_type n = 0; - size_type start_ = start; - while ((start_ = find(sub, start_, end_)) != CppStringT::npos) + 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; } @@ -568,12 +574,15 @@ namespace pcs // i.e. "pythonic c++ strings" * \see find_n(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). */ - inline constexpr size_type find(const CppStringT& sub, const size_type start, const size_type end) const noexcept + inline constexpr size_type find(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept { - if (start > end) + size_type start_{ start }; + const size_type end_{ (end == -1) ? this->size() : end }; + + if (start_ > end_) return CppStringT::npos; else - return find_n(sub, start, end - start + 1); + return find_n(sub, start_, end_ - start_ + 1); } @@ -589,7 +598,8 @@ namespace pcs // i.e. "pythonic c++ strings" inline constexpr size_type find_n(const CppStringT& sub, const size_type start, const size_type count) const noexcept { try { - return this->substr(start, count).find(sub); + CppStringT part{ this->substr(start, count) }; + return part.MyBaseClass::find(sub); } catch (...) { return CppStringT::npos; @@ -1584,7 +1594,7 @@ namespace pcs // i.e. "pythonic c++ strings" { if (start > this->size()) return *this; - const size_type width = std::min(count, this->size() - start); + const size_type width = std::min(count, this->size() - start + 1); return CppStringT(MyBaseClass::substr(start, width)); } From 97f6bb1c75b3ce04640fdf3ee0d8ebfd7b4a51ab Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 22:53:20 +0100 Subject: [PATCH 052/137] #130 - Test CppStringT::count_n() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 9538733..0776dac 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -69,6 +69,33 @@ namespace cppstringstests Assert::AreEqual(0ULL, 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(3ULL, s.count_n("abca", 0, len)); + Assert::AreEqual(6ULL, s.count_n("bca", 0, len)); + Assert::AreEqual(0ULL, s.count_n("A", 0, len)); + Assert::AreEqual(2ULL, s.count_n("abca", 4, len - 4)); + Assert::AreEqual(5ULL, s.count_n("bca", 2, len - 2)); + Assert::AreEqual(0ULL, s.count_n("A", 3, len - 3)); + Assert::AreEqual(1ULL, s.count_n("abca", 4, len - 5)); + Assert::AreEqual(4ULL, s.count_n("bca", 2, len - 3)); + Assert::AreEqual(0ULL, s.count_n("A", 3, len + 4)); + + pcs::CppWString ws(L"abcabcabcdefabca bca bcabca"); + const pcs::CppWString::size_type wlen{ ws.size() }; + Assert::AreEqual(3ULL, ws.count_n(L"abca", 0, wlen)); + Assert::AreEqual(6ULL, ws.count_n(L"bca", 0, wlen)); + Assert::AreEqual(0ULL, ws.count_n(L"A", 0, wlen)); + Assert::AreEqual(2ULL, ws.count_n(L"abca", 4, wlen - 4)); + Assert::AreEqual(5ULL, ws.count_n(L"bca", 2, wlen - 2)); + Assert::AreEqual(0ULL, ws.count_n(L"A", 3, wlen - 3)); + Assert::AreEqual(1ULL, ws.count_n(L"abca", 4, wlen - 5)); + Assert::AreEqual(4ULL, ws.count_n(L"bca", 2, wlen - 3)); + Assert::AreEqual(0ULL, ws.count_n(L"A", 3, wlen + 4)); + } + }; } From 33b1083f75d840ac37e804926979508ac8c28fde Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 19 Mar 2023 23:16:59 +0100 Subject: [PATCH 053/137] #131 - Test CppStringT::ends_with() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 21 +++++++++++++++++++++ cpp-strings/cppstrings.h | 12 ++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 0776dac..0568095 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -96,6 +96,27 @@ namespace cppstringstests Assert::AreEqual(0ULL, 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, 3)); + + 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, 3)); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 50c4b0c..77aa98c 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -483,19 +483,19 @@ namespace pcs // i.e. "pythonic c++ strings" /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops at end position. */ inline const bool endswith(const CppStringT& suffix, const size_type start, const size_type end) const noexcept { - return endswith(std::span{ suffix }, start, end); + return this->substr(start, end).MyBaseClass::ends_with(suffix); } - /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops at end of string. */ - inline const bool endswith(const CppStringT& suffix, const size_type start) 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. */ + inline const bool endswith(const CppStringT& suffix, const size_type end) const noexcept { - return endswith(std::span{ suffix }, start, this->size() - 1); + return this->substr(0, end).MyBaseClass::ends_with(suffix); } /** Returns true if the string ends with the specified suffix, otherwise returns false. Test runs on the whole string. */ inline const bool endswith(const CppStringT& suffix) const noexcept { - return this->ends_with(suffix); + return static_cast(MyBaseClass::ends_with(suffix)); } /** Returns true if the string ends with any of the specified suffixes, otherwise returns false. Test begins at start position and stops at end of string. */ @@ -504,7 +504,7 @@ namespace pcs // i.e. "pythonic c++ strings" if (start > end) return false; else - return std::any_of(suffixes.cbegin(), suffixes.cend(), this->substr(start, end).ends_with); + return std::any_of(suffixes.cbegin(), suffixes.cend(), this->substr(start, end).MyBaseClass::ends_with); /* for (auto& suffix : suffixes) { if (this->substr(start, end).ends_with(suffix)) From ef16d4594fa3d0d6fbb5cd59e7fca09284da7428 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 20 Mar 2023 00:29:04 +0100 Subject: [PATCH 054/137] #132 - Test CppStringT::ends_with_n() with char and wchar_t Tested. Fixed `endswith()`. --- cpp-strings-tests/cpp-strings-tests.cpp | 33 +++++++++++++++++++++++-- cpp-strings/cppstrings.h | 21 +++++++--------- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 0568095..6bc8fc1 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -105,7 +105,10 @@ namespace cppstringstests 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, 3)); + 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() }; @@ -114,7 +117,33 @@ namespace cppstringstests 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, 3)); + 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)); } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 77aa98c..e0c3cf4 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -483,7 +483,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops at end position. */ inline const bool endswith(const CppStringT& suffix, const size_type start, const size_type end) const noexcept { - return this->substr(start, end).MyBaseClass::ends_with(suffix); + return this->substr(start, end - start + 1).MyBaseClass::ends_with(suffix); } /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start of string and stops at end position. */ @@ -498,21 +498,18 @@ namespace pcs // i.e. "pythonic c++ strings" return static_cast(MyBaseClass::ends_with(suffix)); } - /** Returns true if the string ends with any of the specified suffixes, otherwise returns false. Test begins at start position and stops at end of string. */ - inline const bool endswith(const std::span& 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(const std::initializer_list& suffixes, const size_type start, const size_type end) const noexcept { if (start > end) return false; - else - return std::any_of(suffixes.cbegin(), suffixes.cend(), this->substr(start, end).MyBaseClass::ends_with); - /* + + CppStringT tmp(this->substr(start, end - start + 1)); for (auto& suffix : suffixes) { - if (this->substr(start, end).ends_with(suffix)) + if (tmp.ends_with(suffix)) return true; } - return false; - */ } @@ -520,17 +517,17 @@ namespace pcs // i.e. "pythonic c++ strings" /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions. */ inline const bool endswith_n(const CppStringT& suffix, const size_type start, const size_type count) const noexcept { - return endswith(std::span{ suffix }, start, start + count - 1); + return endswith(suffix, start, start + count - 1); } /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions. */ inline const bool endswith_n(const CppStringT& suffix, const size_type count) const noexcept { - return endswith(std::span{ suffix }, 0, count - 1); + return endswith(suffix, 0, count - 1); } /** 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. */ - inline const bool endswith_n(const std::span& suffixes, const size_type start, const size_type count) const noexcept + 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); } From acd45ac88747b450dee5a3a0e9403c00e1d5fd58 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 20 Mar 2023 00:41:25 +0100 Subject: [PATCH 055/137] #133 - Test CppStringT::expand_tabs() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 6bc8fc1..c97c965 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -146,6 +146,28 @@ namespace cppstringstests 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(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(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(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(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(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(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(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(CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); + } }; } From fb4586d9e0f49130c805fd71581219e22122fbe5 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 20 Mar 2023 08:06:22 +0100 Subject: [PATCH 056/137] #186 - Implement new signatures for method CppStringT::find() Completed. --- cpp-strings/cppstrings.h | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index e0c3cf4..3334733 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -566,12 +566,12 @@ namespace pcs // i.e. "pythonic c++ strings" /** 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_n(). + * sub. To check if sub is a substring or not, use the method contains(). * * \see find_n(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). */ - inline constexpr size_type find(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept + constexpr size_type find(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept { size_type start_{ start }; const size_type end_{ (end == -1) ? this->size() : end }; @@ -582,6 +582,35 @@ namespace pcs // i.e. "pythonic c++ strings" return find_n(sub, start_, end_ - start_ + 1); } + /** Returns the lowest index in the string where character ch is found within the slice str[start:end], or -1 (i.e. 'npos') if ch 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(). + * + * \see find_n(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type find(const CharT ch, const size_type start = 0, const size_type end = -1) const noexcept + { + return find(CppStringT(ch), start, end); + } + + /** Returns the lowest index in the string where null-terminated string 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(). + * + * \see find_n(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type find(const CharT* sub, const size_type start = 0, const size_type end = -1) const noexcept + { + if (sub == nullptr) + return CppStringT::npos; + else + return find(CppStringT(sub), start, end); + } + //--- find_n() ---------------------------------------- /** 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. From 1c6ce39a554006acd8c291772423fc0626ba83f9 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 20 Mar 2023 08:16:50 +0100 Subject: [PATCH 057/137] #187 - Implement new signatures for CppStringT::find_n() Completed. --- cpp-strings/cppstrings.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 3334733..692d7b2 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -645,6 +645,35 @@ namespace pcs // i.e. "pythonic c++ strings" return find_n(sub, 0, count); } + /** Returns the lowest index in the string where character ch is found within the slice str[start:start+count-1], or -1 (i.e. 'npos') if ch 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(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type find_n(const CharT ch, const size_type start, const size_type count) const noexcept + { + return find_n(CppStringT(ch), start, count); + } + + /** Returns the lowest index in the string where null-terminated 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(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type find_n(const CharT* sub, const size_type count) const noexcept + { + if (sub == nullptr) + return CppStringT::npos; + else + return find_n(CppStringT(sub), 0, count); + } + //--- index() ----------------------------------------- /** Like find(), but raises NotFoundException when the substring is not found. From 63bcf2a2fc4d2ba0e5bafb92941aa5e2b984cd92 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 20 Mar 2023 08:23:16 +0100 Subject: [PATCH 058/137] #187 - Implement new signatures for CppStringT::find_n() Completd. --- cpp-strings/cppstrings.h | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 692d7b2..0b1124b 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -658,7 +658,7 @@ namespace pcs // i.e. "pythonic c++ strings" return find_n(CppStringT(ch), start, count); } - /** Returns the lowest index in the string where null-terminated substring sub is found within the slice str[0:count-1], or -1 (i.e. 'npos') if sub is not found. + /** Returns the lowest index in the string where character ch is found within the slice str[0:count-1], or -1 (i.e. 'npos') if ch 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(). @@ -666,12 +666,38 @@ namespace pcs // i.e. "pythonic c++ strings" * \see find(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). */ - inline constexpr size_type find_n(const CharT* sub, const size_type count) const noexcept + inline constexpr size_type find_n(const CharT ch, const size_type count) const noexcept + { + return find_n(CppStringT(ch), 0, count); + } + + /** Returns the lowest index in the string where null-terminated 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(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type find_n(const CharT* sub, const size_type start, const size_type count) const noexcept { if (sub == nullptr) return CppStringT::npos; else - return find_n(CppStringT(sub), 0, count); + return find_n(CppStringT(sub), start, count); + } + + /** Returns the lowest index in the string where null-terminated 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(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type find_n(const CharT* sub, const size_type count) const noexcept + { + return find_n(sub, 0, count); } From cc418b237fa69645a99cc20e72bb5843901c4ef5 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 20 Mar 2023 13:12:32 +0100 Subject: [PATCH 059/137] #134 - Test CppStringT::find() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 39 +++++++++++++++++++++++++ cpp-strings/cppstrings.h | 22 ++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index c97c965..304f799 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -169,5 +169,44 @@ namespace cppstringstests Assert::AreEqual(CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); } + TEST_METHOD(find) + { + pcs::CppString test{ "ABC0123456789." }; + for (int c = 0; c <= 255; ++c) { + char ch{ char(c) }; + Assert::AreEqual(test.MyBaseClass::find(ch), test.find(ch)); + Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.find(ch, 2)); + Assert::AreEqual(test.substr(2,5).MyBaseClass::find(ch), test.find(ch, 2, 5+2-1)); + + CppString s(ch); + Assert::AreEqual(test.MyBaseClass::find(s), test.find(s)); + Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.find(s,2)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.find(s, 3, 5+3-1)); + + char str[2]{ ch, 0 }; + Assert::AreEqual(test.MyBaseClass::find(str), test.find(str)); + Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.find(str, 2)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.find(str, 3, 5+3-1)); + } + + pcs::CppWString wtest{ L"ABC0123456789." }; + for (int wc = 0; wc <=0xffff; ++wc) { + wchar_t wch{ wchar_t(wc) }; + Assert::AreEqual(wtest.MyBaseClass::find(wch), wtest.find(wch)); + Assert::AreEqual(wtest.substr(2).MyBaseClass::find(wch), wtest.find(wch, 2)); + Assert::AreEqual(wtest.substr(2, 5).MyBaseClass::find(wch), wtest.find(wch, 2, 5 + 2 - 1)); + + CppWString ws(wch); + Assert::AreEqual(wtest.MyBaseClass::find(ws), wtest.find(ws)); + Assert::AreEqual(wtest.substr(2).MyBaseClass::find(ws), wtest.find(ws, 2)); + Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(ws), wtest.find(ws, 3, 5 + 3 - 1)); + + wchar_t wstr[2]{ wch, 0 }; + Assert::AreEqual(wtest.MyBaseClass::find(wstr), wtest.find(wstr)); + Assert::AreEqual(wtest.substr(2).MyBaseClass::find(wstr), wtest.find(wstr, 2)); + Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(wstr), wtest.find(wstr, 3, 5 + 3 - 1)); + } + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 0b1124b..70a7fc3 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -568,6 +568,9 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * * \see find_n(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). */ @@ -587,6 +590,9 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * * \see find_n(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). */ @@ -599,6 +605,9 @@ namespace pcs // i.e. "pythonic c++ strings" * * 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 then the string size and if start <= end. * * \see find_n(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). @@ -618,6 +627,9 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * * \see find(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). */ @@ -637,6 +649,9 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * * \see find(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). */ @@ -650,6 +665,9 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * * \see find(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). */ @@ -1670,8 +1688,8 @@ namespace pcs // i.e. "pythonic c++ strings" //--- substr() ---------------------------------------- - /** \brief Returns acopy of the string, starting at index start and ending after count characters. */ - inline CppStringT substr(const size_type start, const size_type count) const noexcept + /** \brief Returns a copy of the string, starting at index start and ending after count characters. */ + inline CppStringT substr(const size_type start, const size_type count=-1) const noexcept { if (start > this->size()) return *this; From 7636c39544b9987864c4275ecd4e582ec6510888 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 20 Mar 2023 23:54:51 +0100 Subject: [PATCH 060/137] #135 - Test CppStringT::find_n() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 304f799..8cacf35 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -208,5 +208,43 @@ namespace cppstringstests } } + TEST_METHOD(find_n) + { + pcs::CppString test{ "ABC0123456789." }; + for (int c = 0; c <= 255; ++c) { + char ch{ char(c) }; + Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.find_n(ch, 2, -1)); + Assert::AreEqual(test.substr(0, 2).MyBaseClass::find(ch), test.find_n(ch, 2)); + Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.find_n(ch, 2, 5)); + + CppString s(ch); + Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.find_n(s, 2, -1)); + Assert::AreEqual(test.substr(0, 2).MyBaseClass::find(s), test.find_n(s, 2)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.find_n(s, 3, 5)); + + char str[2]{ ch, 0 }; + Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.find_n(str, 2, -1)); + Assert::AreEqual(test.substr(0, 2).MyBaseClass::find(str), test.find_n(str, 2)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.find_n(str, 3, 5)); + } + + pcs::CppWString wtest{ L"ABC0123456789." }; + for (int wc = 0; wc <= 0xffff; ++wc) { + wchar_t wch{ wchar_t(wc) }; + Assert::AreEqual(wtest.substr(2).MyBaseClass::find(wch), wtest.find_n(wch, 2, -1)); + Assert::AreEqual(wtest.substr(0, 2).MyBaseClass::find(wch), wtest.find_n(wch, 2)); + Assert::AreEqual(wtest.substr(2, 5).MyBaseClass::find(wch), wtest.find_n(wch, 2, 5)); + + CppWString ws(wch); + Assert::AreEqual(wtest.substr(2).MyBaseClass::find(ws), wtest.find_n(ws, 2, -1)); + Assert::AreEqual(wtest.substr(0, 2).MyBaseClass::find(ws), wtest.find_n(ws, 2)); + Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(ws), wtest.find_n(ws, 3, 5)); + + wchar_t wstr[2]{ wch, 0 }; + Assert::AreEqual(wtest.substr(2).MyBaseClass::find(wstr), wtest.find_n(wstr, 2, -1)); + Assert::AreEqual(wtest.substr(0, 2).MyBaseClass::find(wstr), wtest.find_n(wstr, 2)); + Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(wstr), wtest.find_n(wstr, 3, 5)); + } + } }; } From 403a87c07daa5a78f5cb72f406f1e6f6940cd906 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 21 Mar 2023 13:28:01 +0100 Subject: [PATCH 061/137] #190 - Implement new signatures for method CppStringT::index() Completed. --- cpp-strings/cppstrings.h | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 70a7fc3..b1a9e62 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -720,12 +720,12 @@ namespace pcs // i.e. "pythonic c++ strings" //--- index() ----------------------------------------- - /** Like find(), but raises NotFoundException when the substring is not found. + /** 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(). */ - inline constexpr size_type index(const CppStringT& sub, const size_type start, const size_type end) const + 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 (size_type == CppStringT::npos) @@ -734,6 +734,34 @@ namespace pcs // i.e. "pythonic c++ strings" return ret_value; } + /** Like find(const CharT), but raises NotFoundException when character ch is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + inline constexpr size_type index(const CharT ch, const size_type start = 0, const size_type end = -1) const + { + const size_type ret_value = find(ch, start, end); + if (size_type == CppStringT::npos) + throw NotFoundException(std::format("character \"{}\" not found in string \"{}\"", ch, this->c_str())); + else + return ret_value; + } + + /** Like find(const CharT*), 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(). + */ + inline constexpr size_type index(const CharT* sub, const size_type start = 0, const size_type end = -1) const + { + const size_type ret_value = find(sub, start, end); + if (size_type == CppStringT::npos) + throw NotFoundException(std::format("character \"{}\" not found in string \"{}\"", sub, this->c_str())); + else + return ret_value; + } + //--- index_n() --------------------------------------- /** Like find_n(sub, start, count), but raises NotFoundException when the substring is not found. From e9bbcddbae354b1ebfa463f00e9c18f3b651fb1f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 21 Mar 2023 14:33:46 +0100 Subject: [PATCH 062/137] #136 - Test CppStringT::index() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 137 ++++++++++++++++++++++++ cpp-strings/cppstrings.h | 15 +-- 2 files changed, 146 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 8cacf35..3c1aa61 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -246,5 +246,142 @@ namespace cppstringstests Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(wstr), wtest.find_n(wstr, 3, 5)); } } + + TEST_METHOD(index_char) + { + using string_type = pcs::CppString; + + string_type test{ "ABC0123456789." }; + char ch{ '3' }; + Assert::AreEqual(test.MyBaseClass::find(ch), test.index(ch)); + Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.index(ch, 2)); + Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index(ch, 2, string_type::size_type(5 + 2 - 1))); + try { + const string_type::size_type pos = test.index('z'); + Assert::IsTrue(pos != pcs::CppString::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test.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.index('z', 2, 5+2-1); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + string_type s(ch); + Assert::AreEqual(test.MyBaseClass::find(s), test.index(s)); + Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.index(s, 2)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index(s, 3, string_type::size_type(5 + 3 - 1))); + s = 'z'; + try { + const string_type::size_type pos = test.index(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test.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.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.MyBaseClass::find(str), test.index(str)); + Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.index(str, 2)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index(str, 3, string_type::size_type(5 + 3 - 1))); + str[0] = 'z'; + try { + const string_type::size_type pos = test.index(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test.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.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( L"ABC0123456789." ); + wchar_t ch{ L'3' }; + Assert::AreEqual(test.MyBaseClass::find(ch), test.index(ch)); + Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.index(ch, 2)); + Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index(ch, 2, string_type::size_type(5 + 2 - 1))); + try { + const string_type::size_type pos = test.index('z'); + Assert::IsTrue(pos != pcs::CppString::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test.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.index('z', 2, 5 + 2 - 1); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + string_type s(ch); + Assert::AreEqual(test.MyBaseClass::find(s), test.index(s)); + Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.index(s, 2)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index(s, 3, string_type::size_type(5 + 3 - 1))); + s = 'z'; + try { + const string_type::size_type pos = test.index(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test.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.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.MyBaseClass::find(str), test.index(str)); + Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.index(str, 2)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index(str, 3, string_type::size_type(5 + 3 - 1))); + str[0] = 'z'; + try { + const string_type::size_type pos = test.index(s); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + try { + const string_type::size_type pos = test.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.index(s, 2, string_type::size_type(5 + 2 - 1)); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index b1a9e62..ba0b4fb 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -728,8 +728,9 @@ namespace pcs // i.e. "pythonic c++ strings" 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 (size_type == CppStringT::npos) - throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); + if (ret_value == CppStringT::npos) + throw NotFoundException("substring not found in string."); + //throw NotFoundException(CppStringT(std::format("substring \"{}\" not found in string \"{}\"", sub.c_str(), this->c_str()).c_str())); else return ret_value; } @@ -742,8 +743,9 @@ namespace pcs // i.e. "pythonic c++ strings" inline constexpr size_type index(const CharT ch, const size_type start = 0, const size_type end = -1) const { const size_type ret_value = find(ch, start, end); - if (size_type == CppStringT::npos) - throw NotFoundException(std::format("character \"{}\" not found in string \"{}\"", ch, this->c_str())); + if (ret_value == CppStringT::npos) + throw NotFoundException("char not found in string."); + //throw NotFoundException(CppStringT(std::format("character \"{}\" not found in string \"{}\"", CppStringT(ch).c_str(), this->c_str()).c_str())); else return ret_value; } @@ -756,8 +758,9 @@ namespace pcs // i.e. "pythonic c++ strings" inline constexpr size_type index(const CharT* sub, const size_type start = 0, const size_type end = -1) const { const size_type ret_value = find(sub, start, end); - if (size_type == CppStringT::npos) - throw NotFoundException(std::format("character \"{}\" not found in string \"{}\"", sub, this->c_str())); + if (ret_value == CppStringT::npos) + throw NotFoundException("substring not found in string"); + //throw NotFoundException(CppStringT(std::format("substring \"{}\" not found in string \"{}\"", CppStringT(sub).c_str(), this->c_str()).c_str())); else return ret_value; } From 951d497fa382bdca005f475d5ca21dc99580a88d Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 21 Mar 2023 18:38:04 +0100 Subject: [PATCH 063/137] #191 - Implement new signatures for method CppStringT::index_n() Completed. --- cpp-strings/cppstrings.h | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index ba0b4fb..05d5d2c 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -787,6 +787,46 @@ namespace pcs // i.e. "pythonic c++ strings" return index(sub, 0, count); } + /** Like find_n(sub, start, count), but raises NotFoundException when the character is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + inline constexpr size_type index_n(const CharT ch, const size_type start, const size_type count) const + { + return index(ch, start, start + count - 1); + } + + /** Like find_n(sub, count), but raises NotFoundException when the character is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + inline constexpr size_type index_n(const CharT ch, const size_type count) const + { + return index(ch, 0, count); + } + + /** Like find_n(sub, start, count), but raises NotFoundException when the null-terminated substring is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + inline constexpr size_type index_n(const CharT* sub, const size_type start, const size_type count) const + { + return index(sub, start, start + count - 1); + } + + /** Like find_n(sub, count), but raises NotFoundException when the null-terminated substring is not found. + * + * \see index_n(), rindex() and rindex_n(). + * \see find(), find_n(), rfind() and rfind_n(). + */ + inline constexpr size_type index_n(const CharT* 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. */ From a12477b17ada46d3ea6fda9a81ca8ac662681f40 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 00:00:15 +0100 Subject: [PATCH 064/137] #137 - Test CppStringT::index_n() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 100 ++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 3c1aa61..4c52519 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -383,5 +383,105 @@ namespace cppstringstests catch (const string_type::NotFoundException e) { /* ok case! */ } } + TEST_METHOD(index_n_char) + { + using string_type = pcs::CppString; + + pcs::CppString test{ "ABC0123456789." }; + char ch{ '3' }; + Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(ch), test.index_n(ch, 20)); + Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index_n(ch, 2, 5)); + try { + const string_type::size_type pos = test.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.index_n('z', 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + + CppString s(ch); + Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(s), test.index_n(s, 20)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index_n(s, 3, 5)); + s = 'z'; + try { + const string_type::size_type pos = test.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.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.substr(0, 20).MyBaseClass::find(str), test.index_n(str, 20)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index_n(str, 3, 5)); + str[0] = 'z'; + try { + const string_type::size_type pos = test.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.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{ L"ABC0123456789." }; + wchar_t ch{ L'3'}; + Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(ch), test.index_n(ch, 20)); + Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index_n(ch, 2, 5)); + try { + const string_type::size_type pos = test.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.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.substr(0, 20).MyBaseClass::find(s), test.index_n(s, 20)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index_n(s, 3, 5)); + try { + const string_type::size_type pos = test.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.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.substr(0, 20).MyBaseClass::find(str), test.index_n(str, 20)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index_n(str, 3, 5)); + str[0] = L'z'; + try { + const string_type::size_type pos = test.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.index_n(s, 2, 5); + Assert::IsTrue(pos != string_type::npos); + } + catch (const string_type::NotFoundException e) { /* ok case! */ } + } + }; } From 4ec3564655d6b4a954ee863243c8c88254b1b177 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 00:22:51 +0100 Subject: [PATCH 065/137] #138 - Test CppStringT::isalnum() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 9 +++- cpp-strings/cppstrings.h | 63 ++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 4c52519..c75cf00 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -433,7 +433,6 @@ namespace cppstringstests catch (const string_type::NotFoundException e) { /* ok case! */ } } - TEST_METHOD(index_n_wchar_t) { using string_type = pcs::CppWString; @@ -483,5 +482,13 @@ namespace cppstringstests catch (const string_type::NotFoundException e) { /* ok case! */ } } + TEST_METHOD(is_alnum) + { + 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()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 05d5d2c..c4c2209 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -68,6 +68,9 @@ namespace pcs // i.e. "pythonic c++ strings" 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. @@ -77,6 +80,9 @@ namespace pcs // i.e. "pythonic c++ strings" 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. @@ -832,7 +838,16 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if all characters in the string are alphanumeric and there is at least one character, or false otherwise. */ inline const bool isalnum() const noexcept { - return this->isalpha() || this->isdecimal() || this->isdigit() || this->isnumeric(); + if (this->empty()) + return false; + /* + for (auto ch : *this) + if (!(pcs::is_alpha(ch) || pcs::is_decimal(ch) || pcs::is_digit(ch) || pcs::is_numeric(ch))) + return false; + return true; + */ + return std::all_of(this->cbegin(), this->cend(), + [](const CharT ch) { return pcs::is_alpha(ch) || pcs::is_decimal(ch) || pcs::is_digit(ch) || pcs::is_numeric(ch); }); } @@ -1948,6 +1963,29 @@ namespace pcs // i.e. "pythonic c++ strings" { return (const bool)std::iswdigit(ch); } + //--- is_digit() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + 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<> + 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<> + 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 @@ -1985,6 +2023,29 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- is_numeric() ---------------------------------------- + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + 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<> + 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<> + 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 From 3fdad29f4757ce501d5fa90f6c2fd8284ee75eb8 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 00:41:56 +0100 Subject: [PATCH 066/137] #139 - Test CppStringT::isalpha() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 17 +++++++++++++++++ cpp-strings/cppstrings.h | 24 +++++++++--------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index c75cf00..30e68ea 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -490,5 +490,22 @@ namespace cppstringstests Assert::IsFalse(pcs::CppWString(L"0123456789az,").isalnum()); } + TEST_METHOD(is_alpha) + { + Assert::IsFalse(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(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()); + } + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index c4c2209..1b9f190 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -840,14 +840,8 @@ namespace pcs // i.e. "pythonic c++ strings" { if (this->empty()) return false; - /* - for (auto ch : *this) - if (!(pcs::is_alpha(ch) || pcs::is_decimal(ch) || pcs::is_digit(ch) || pcs::is_numeric(ch))) - return false; - return true; - */ return std::all_of(this->cbegin(), this->cend(), - [](const CharT ch) { return pcs::is_alpha(ch) || pcs::is_decimal(ch) || pcs::is_digit(ch) || pcs::is_numeric(ch); }); + [](const value_type ch) { return pcs::is_alpha(ch) || pcs::is_decimal(ch) || pcs::is_digit(ch) || pcs::is_numeric(ch); }); } @@ -855,7 +849,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if all characters in the string are alphabetic and there is at least one character, or false otherwise. */ inline const bool isalpha() const noexcept { - return !this->empty() && std::all_of(this->cbegin(), this->cend(), [](const value_type ch) { return pcs::is_alpha(ch); }); + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_alpha); } @@ -866,7 +860,7 @@ namespace pcs // i.e. "pythonic c++ strings" #endif inline const bool isascii() const noexcept { - return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii); + return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii); } @@ -879,7 +873,7 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline const bool isdecimal() const noexcept { - return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_decimal); + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_decimal); } @@ -925,7 +919,7 @@ namespace pcs // i.e. "pythonic c++ strings" */ 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)); + return !this->empty() && pcs::is_id_start((*this)[0]) && (this->size() == 1 || std::all_of(this->cbegin() + 1, this->cend(), pcs::is_id_continue)); } @@ -933,7 +927,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if all cased characters in the string are lowercase and there is at least one cased character, or false otherwise. */ inline const bool islower() const noexcept { - return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_lower); + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_lower); } @@ -962,7 +956,7 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline const bool isprintable() const noexcept { - return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_printable); + return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_printable); } @@ -978,7 +972,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise. */ inline const bool isspace() const noexcept { - return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_space); + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_space); } @@ -998,7 +992,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if all cased characters in the string are uppercase and there is at least one cased character, or false otherwise. */ inline const bool isupper() const noexcept { - return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_upper); + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_upper); } From 4dc817f879cf619b73141f11bb6d2e407c4cd741 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 00:44:25 +0100 Subject: [PATCH 067/137] #140 - Test CppStringT::isascii() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 30e68ea..d8941df 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -482,7 +482,7 @@ namespace cppstringstests catch (const string_type::NotFoundException e) { /* ok case! */ } } - TEST_METHOD(is_alnum) + TEST_METHOD(isalnum) { Assert::IsTrue(pcs::CppString("aA25").isalnum()); Assert::IsFalse(pcs::CppString("0123456789az,").isalnum()); @@ -490,7 +490,7 @@ namespace cppstringstests Assert::IsFalse(pcs::CppWString(L"0123456789az,").isalnum()); } - TEST_METHOD(is_alpha) + TEST_METHOD(isalpha) { Assert::IsFalse(CppString().isalpha()); for (int c = 0; c <= 255; ++c) { @@ -507,5 +507,22 @@ namespace cppstringstests } } + TEST_METHOD(isascii) + { + Assert::IsTrue(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(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()); + } + } + }; } From f4588b82e6e4ee387251c04bf01bfa6cd1a8e551 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 00:46:33 +0100 Subject: [PATCH 068/137] #141 - Test CppStringT::isdecimal() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d8941df..d70ea18 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -524,5 +524,22 @@ namespace cppstringstests } } + TEST_METHOD(isdecimal) + { + Assert::IsFalse(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(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()); + } + } + }; } From b981f6aab5c06ffefaefe19b9810bc4529e56a42 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 00:47:43 +0100 Subject: [PATCH 069/137] #142 - Test CppStringT::isdigit() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d70ea18..f0728ef 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -541,5 +541,22 @@ namespace cppstringstests } } + TEST_METHOD(isdigit) + { + Assert::IsFalse(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(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_digit(wch), ws.isdigit()); + } + } + }; } From 2c3c035ea37c6acfe8b66bd40e09c4607628dc53 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 00:49:07 +0100 Subject: [PATCH 070/137] #145 - Test CppStringT::isnumeric() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index f0728ef..b669c48 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -550,7 +550,7 @@ namespace cppstringstests Assert::AreEqual(pcs::is_digit(ch), s.isdigit()); } - Assert::IsFalse(CppWString().isdecimal()); + Assert::IsFalse(CppWString().isdigit()); for (int c = 0; c <= 0xffff; ++c) { const wchar_t wch{ wchar_t(c) }; pcs::CppWString ws(5, wch); @@ -558,5 +558,22 @@ namespace cppstringstests } } + TEST_METHOD(isnumeric) + { + Assert::IsFalse(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(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()); + } + } + }; } From 177811d4f11d438a127ffb4e1cdbbc1979365197 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 10:40:04 +0100 Subject: [PATCH 071/137] #143 - Test CppStringT::isidentifier() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index b669c48..91de2f2 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -558,6 +558,29 @@ namespace cppstringstests } } + 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("_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"_0123456789").isidentifier()); + Assert::IsTrue(pcs::CppWString(L"__").isidentifier()); + Assert::IsFalse(pcs::CppWString(L"_0123456789abcdefghijklmnopqrstuvwxyz.").isidentifier()); + Assert::IsFalse(pcs::CppWString(L"9z").isidentifier()); + } + TEST_METHOD(isnumeric) { Assert::IsFalse(CppString().isnumeric()); From 365319f86ab91991a20dadfb51914ddeb3354609 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 10:42:21 +0100 Subject: [PATCH 072/137] #144 - Test CppStringT::islower() with char and wchar_t Tested --- cpp-strings-tests/cpp-strings-tests.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 91de2f2..ddddf1e 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -581,6 +581,23 @@ namespace cppstringstests Assert::IsFalse(pcs::CppWString(L"9z").isidentifier()); } + TEST_METHOD(islower) + { + Assert::IsFalse(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(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(CppString().isnumeric()); From 33f809f233a20b21c8155267df8d6d9c3742b559 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 10:44:17 +0100 Subject: [PATCH 073/137] #146 - Test CppStringT::isprintable() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index ddddf1e..e5eec84 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -615,5 +615,23 @@ namespace cppstringstests } } + TEST_METHOD(isprintable) + { + Assert::IsTrue(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(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()); + } + } + + }; } From 740ee0f88125e1ae1a0c025c793f2854058989e0 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 10:48:10 +0100 Subject: [PATCH 074/137] #147 - Test CppStringT::ispunctuation() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index e5eec84..b4133cc 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -632,6 +632,24 @@ namespace cppstringstests } } + TEST_METHOD(ispunctuation) + { + Assert::IsFalse(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), CppString(ch).ispunctuation()); + } + + Assert::IsFalse(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), CppWString(wch).ispunctuation()); + } + } }; } From 7ca47c779e064f5573d64f4d8c6d101c6344f847 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 10:50:19 +0100 Subject: [PATCH 075/137] #148 - Test CppStringT::isspace() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index b4133cc..897c83f 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -651,5 +651,21 @@ namespace cppstringstests } } + TEST_METHOD(isspace) + { + Assert::IsFalse(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(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()); + } + } }; } From b1c0e4cf35f09e9de4b2e322d46698c3d5793c66 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 11:41:00 +0100 Subject: [PATCH 076/137] #149 - Test CppStringT::istitle() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 13 +++++++ cpp-strings/cppstrings.h | 50 ++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 897c83f..abb8f5c 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -667,5 +667,18 @@ namespace cppstringstests 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()); + } + + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 1b9f190..97db259 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -22,6 +22,7 @@ //============================================================= #include +#include #include #include #include @@ -392,10 +393,10 @@ namespace pcs // i.e. "pythonic c++ strings" inline CppStringT(InputIt first, InputIt last) : MyBaseClass(first, last) {} // #16 template - explicit CppStringT(const StringViewLike& svl) : MyBaseClass(svl) {} // #17 + explicit CppStringT(StringViewLike& svl) : MyBaseClass(svl) {} // #17 template - CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} // #18 + CppStringT(StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} // #18 inline ~CppStringT() noexcept = default; @@ -981,10 +982,14 @@ namespace pcs // i.e. "pythonic c++ strings" * * 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. */ inline const bool istitle() const noexcept { - return !this->empty && this->title() == *this; + return !this->empty() && this->title() == *this; } @@ -1005,6 +1010,39 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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 + inline CppStringT join(const std::array& strs) const noexcept + { + auto str_it = strs.cbegin(); + if (str_it == strs.cend()) + return CppStringT(); + + CppStringT res{ *str_it++ }; + while (str_it != strs.cend()) + 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. + */ + CppStringT join(const std::vector& strs) const noexcept + { + auto str_it = strs.cbegin(); + if (str_it == strs.cend()) + return CppStringT(); + + CppStringT res{ *str_it++ }; + while (str_it != strs.cend()) + 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. @@ -1537,7 +1575,7 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline std::vector split(const CppStringT& sep) const noexcept { - std::vector res; + std::vector res; for (const auto& word : *this | std::views::split(sep)) res.push_back(CppStringT(word.begin(), word.end())); return res; @@ -1800,13 +1838,13 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ CppStringT title() const noexcept { - constexpr CppStringT whitespace(value_type(' ')); + const CppStringT whitespace(value_type(' ')); CppStringT res(*this); std::vector words = res.split(whitespace); for (CppStringT& word : words) - word.capitalize(); + word = word.capitalize(); return whitespace.join(words); } From 474642e03fdcbd99a5fe9738e50787c31be0fe8b Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 11:43:19 +0100 Subject: [PATCH 077/137] #150 - Test CppStringT::isupper() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index abb8f5c..590419d 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -679,6 +679,22 @@ namespace cppstringstests Assert::IsTrue(ws.title().istitle()); } + TEST_METHOD(isupper) + { + Assert::IsFalse(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(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()); + } + } }; } From 43f92f7eeb6f2a2b869b6c3cb9f36d97adc5ae2f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 22 Mar 2023 19:18:12 +0100 Subject: [PATCH 078/137] #151 - Test CppStringT::is_words_sep() with char and wchar_t Tested. --- cpp-strings-tests/cpp-strings-tests.cpp | 19 +++++++++++++++++++ cpp-strings/cppstrings.h | 3 ++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 590419d..3ea4b74 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -696,5 +696,24 @@ namespace cppstringstests } } + TEST_METHOD(is_words_sep) + { + Assert::IsFalse(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(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()); + } + } + + + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 97db259..6358022 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1005,7 +1005,8 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if there are only whitespace and punctuation characters in the string and there is at least one character, or false otherwise. */ inline const bool is_words_sep() const noexcept { - return isspace() || ispunctuation(); + return !this->empty() && std::all_of(this->cbegin(), this->cend(), + [](const value_type ch){ return pcs::is_space(ch) || pcs::is_punctuation(ch); }); } From aba3db6764d6c66e4dd80048b2b4f9bf993441c4 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 12 May 2023 22:53:36 +0200 Subject: [PATCH 079/137] #152 - Test `CppStringT::join()` with `char` and `wchar_t` Completed. Fixed bugs. --- cpp-strings-tests/cpp-strings-tests.cpp | 40 +++++++++++++++++++++++++ cpp-strings-tests/pch.cpp | 1 + cpp-strings/cppstrings.h | 28 ++++++++--------- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 3ea4b74..63f02e4 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -713,6 +713,46 @@ namespace cppstringstests } } + 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()); + + 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"# #"csv.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()); + + } + }; diff --git a/cpp-strings-tests/pch.cpp b/cpp-strings-tests/pch.cpp index 24020cd..f87cdfe 100644 --- a/cpp-strings-tests/pch.cpp +++ b/cpp-strings-tests/pch.cpp @@ -665,6 +665,7 @@ namespace cppstringstests } }; + //===== PART 4 ======================================== diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 6358022..5e4b4f6 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -54,10 +54,10 @@ namespace pcs // i.e. "pythonic c++ strings" // litteral operators #pragma warning(disable: 4455) - inline const CppString operator""cs(const char* str, std::size_t len); //!< Forms a CppString literal. - inline const CppString operator""csv(const char* str, std::size_t len); //!< Forms a CppString view literal. - inline const CppWString operator""cs(const wchar_t* str, std::size_t len); //!< Forms a CppWString literal. - inline const CppWString operator""csv(const wchar_t* str, std::size_t len); //!< Forms a CppWString view literal. + inline CppString operator""cs(const char* str, std::size_t len); //!< Forms a CppString literal. + inline CppString operator""csv(const char* str, std::size_t len); //!< Forms a CppString view literal. + inline CppWString operator""cs(const wchar_t* str, std::size_t len); //!< Forms a CppWString literal. + inline CppWString operator""csv(const wchar_t* str, std::size_t len); //!< Forms a CppWString view literal. // chars classifications -- not to be directly called, see respective specializations at the very end of this module. template @@ -1016,12 +1016,12 @@ namespace pcs // i.e. "pythonic c++ strings" * The separator between elements is the string to which this method is applied. */ template - inline CppStringT join(const std::array& strs) const noexcept + CppStringT join(const std::array& strs) const noexcept { - auto str_it = strs.cbegin(); - if (str_it == strs.cend()) + if (strs.empty()) return CppStringT(); + auto str_it = strs.cbegin(); CppStringT res{ *str_it++ }; while (str_it != strs.cend()) res += *this + *str_it++; @@ -1034,10 +1034,10 @@ namespace pcs // i.e. "pythonic c++ strings" */ CppStringT join(const std::vector& strs) const noexcept { - auto str_it = strs.cbegin(); - if (str_it == strs.cend()) + if (strs.empty()) return CppStringT(); + auto str_it = strs.cbegin(); CppStringT res{ *str_it++ }; while (str_it != strs.cend()) res += *this + *str_it++; @@ -1056,7 +1056,7 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \brief Single parameter signature. Returns a copy of this parameter. */ - inline const CppStringT join(const CppStringT& s) const noexcept + inline CppStringT join(const CppStringT& s) const noexcept { return s; } @@ -1928,26 +1928,26 @@ namespace pcs // i.e. "pythonic c++ strings" //===== litteral operators ============================ /** \brief Forms a CppString literal. */ - inline const CppString operator""cs(const char* str, std::size_t len) + inline CppString operator""cs(const char* str, std::size_t len) { return CppString(CppString::MyBaseClass(str, len)); } /** \brief Forms a CppString view literal. */ - inline const CppString operator""csv(const char* str, std::size_t len) + inline CppString operator""csv(const char* str, std::size_t len) { //return CppString(CppString::MyStringView(str, len)); return CppString(str, len); } /** \brief Forms a CppWString literal. */ - inline const CppWString operator""cs(const wchar_t* str, std::size_t len) + inline CppWString operator""cs(const wchar_t* str, std::size_t len) { return CppWString(CppWString::MyBaseClass(str, len)); } /** \brief Forms a CppWString view literal. */ - inline const CppWString operator""csv(const wchar_t* str, std::size_t len) + inline CppWString operator""csv(const wchar_t* str, std::size_t len) { //return CppWString(CppWString::MyStringView(str, len)); return CppWString(str, len); From 383adcd9b27b4ab87cf009b2def3dc1554a32d7f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 12 May 2023 23:14:14 +0200 Subject: [PATCH 080/137] #153 - Test CppStringT::ljust() with char and wchar_t Completed. --- cpp-strings-tests/cpp-strings-tests.cpp | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 63f02e4..a300a89 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -750,9 +750,34 @@ namespace cppstringstests 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()); + } }; From 78c5ebcd9808e355d315f9a65752a66babdbc0df Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 12 May 2023 23:23:12 +0200 Subject: [PATCH 081/137] #154 - Test CppStringT::lower() with char and wchar_t Completed. --- cpp-strings-tests/cpp-strings-tests.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index a300a89..5fe3829 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -779,6 +779,27 @@ namespace cppstringstests 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]); + } + + 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]); + } + } + }; } From c7a867bc00a6daa08484f3c401c8274f5f093fab Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 13 May 2023 11:55:24 +0200 Subject: [PATCH 082/137] #155 - Test CppStringT::lstrip() with char and wchar_t Completed. Fixed a bug. --- cpp-strings-tests/cpp-strings-tests.cpp | 28 +++++++++++++++++++++++++ cpp-strings/cppstrings.h | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 5fe3829..01fe47b 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -788,6 +788,7 @@ namespace cppstringstests 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) { @@ -797,9 +798,36 @@ namespace cppstringstests 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)); } } + TEST_METHOD(lstrip) + { + 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()); + } }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 5e4b4f6..219df8b 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1119,7 +1119,7 @@ namespace pcs // i.e. "pythonic c++ strings" inline CppStringT lstrip(const CppStringT& prefix) const noexcept { for (auto it = this->cbegin(); it != this->cend(); ++it) - if (std::none_of(prefix.cbegin(), prefix.cend(), [it](const value_type ch) { *it == ch; })) + if (std::none_of(prefix.cbegin(), prefix.cend(), [it](const value_type ch) { return *it == ch; })) return CppStringT(it, this->cend()); return CppStringT(); } From 98a85fb0d3b01937018f88e70f6852db623c23a9 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 13 May 2023 12:04:41 +0200 Subject: [PATCH 083/137] #156 - Test CppStringT::partition() with char and wchar_t Completed. Fixed a typo. --- cpp-strings-tests/cpp-strings-tests.cpp | 47 +++++++++++++++++++++++++ cpp-strings/cppstrings.h | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 01fe47b..f0b161f 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -829,5 +829,52 @@ namespace cppstringstests Assert::AreEqual(L"a bcd ", L" a bcd "cs.lstrip().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()); + + 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()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 219df8b..3b02b2b 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1135,7 +1135,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- partition() ------------------------------------- - /** Split 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. + /** 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. From e85bfc93e209a11e2d32448e8bdaaf5f79dd09f6 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 13 May 2023 12:09:30 +0200 Subject: [PATCH 084/137] #157 - Test CppStringT::removeprefix() with char and wchar_t Completed. --- cpp-strings-tests/cpp-strings-tests.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index f0b161f..d7e7873 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -876,5 +876,22 @@ namespace cppstringstests Assert::AreEqual(L"", wres[2].c_str()); } + TEST_METHOD(removeprefix) + { + 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()); + } + }; } From 6faba8d6ca93170da6a86453a3adf5bb28fa911a Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 13 May 2023 12:14:06 +0200 Subject: [PATCH 085/137] #158 - Test CppStringT::removesuffix() with char and wchar_t Completed. Fixed a bug on size of substring. --- cpp-strings-tests/cpp-strings-tests.cpp | 17 +++++++++++++++++ cpp-strings/cppstrings.h | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d7e7873..51d77ef 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -893,5 +893,22 @@ namespace cppstringstests Assert::AreEqual(L"cdab", L"abcdab"cs.removeprefix(L"ab").c_str()); } + + TEST_METHOD(removesuffix) + { + 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()); + } }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 3b02b2b..810934e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1174,7 +1174,7 @@ namespace pcs // i.e. "pythonic c++ strings" { if (this->endswith(suffix)) { const size_type suffix_length = suffix.size(); - return this->substr(0, this->size() - suffix_length + 1); + return this->substr(0, this->size() - suffix_length); } else return *this; From 56b7326ded9d4ceb9dcffc3c67771dc9d69889ca Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 27 Nov 2023 22:25:20 +0100 Subject: [PATCH 086/137] #159 - Test CppStringT::replace() with char and wchar_t Tested and validated; Fixed a few bugs, notably within methods find() and find_n() and within tests of find() and find_n()! --- cpp-strings-tests/cpp-strings-tests.cpp | 148 +++++++++++++++++++++--- cpp-strings/cppstrings.h | 55 +++------ 2 files changed, 149 insertions(+), 54 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 51d77ef..8f934a8 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -171,45 +171,119 @@ namespace cppstringstests TEST_METHOD(find) { + size_t found_pos; + pcs::CppString test{ "ABC0123456789." }; for (int c = 0; c <= 255; ++c) { char ch{ char(c) }; Assert::AreEqual(test.MyBaseClass::find(ch), test.find(ch)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.find(ch, 2)); - Assert::AreEqual(test.substr(2,5).MyBaseClass::find(ch), test.find(ch, 2, 5+2-1)); + + found_pos = test.substr(2).MyBaseClass::find(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find(ch, 2)); + else + Assert::AreEqual(found_pos, test.find(ch, 2) - 2); + + found_pos = test.substr(2, 5).MyBaseClass::find(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find(ch, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test.find(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); CppString s(ch); Assert::AreEqual(test.MyBaseClass::find(s), test.find(s)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.find(s,2)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.find(s, 3, 5+3-1)); - - char str[2]{ ch, 0 }; - Assert::AreEqual(test.MyBaseClass::find(str), test.find(str)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.find(str, 2)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.find(str, 3, 5+3-1)); + found_pos = test.substr(2).MyBaseClass::find(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find(s, 2)); + else + Assert::AreEqual(found_pos, test.find(s, 2) - 2); + + found_pos = test.substr(2, 5).MyBaseClass::find(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find(s, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test.find(s, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + if (c > 0) { + char str[2]{ ch, 0 }; + Assert::AreEqual(test.MyBaseClass::find(str), test.find(str)); + + found_pos = test.substr(2).MyBaseClass::find(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find(str, 2)); + else + Assert::AreEqual(found_pos, test.find(str, 2) - 2); + + found_pos = test.substr(2, 5).MyBaseClass::find(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find(str, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test.find(str, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + } } + Assert::AreEqual(pcs::CppString::npos, test.find("A", 1)); + Assert::AreEqual(size_t(0), test.find("")); + Assert::AreEqual(pcs::CppString::npos, test.find(".", 14)); + Assert::AreEqual(size_t(13), test.find(".", 13)); pcs::CppWString wtest{ L"ABC0123456789." }; for (int wc = 0; wc <=0xffff; ++wc) { wchar_t wch{ wchar_t(wc) }; - Assert::AreEqual(wtest.MyBaseClass::find(wch), wtest.find(wch)); - Assert::AreEqual(wtest.substr(2).MyBaseClass::find(wch), wtest.find(wch, 2)); - Assert::AreEqual(wtest.substr(2, 5).MyBaseClass::find(wch), wtest.find(wch, 2, 5 + 2 - 1)); + + 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); CppWString ws(wch); Assert::AreEqual(wtest.MyBaseClass::find(ws), wtest.find(ws)); - Assert::AreEqual(wtest.substr(2).MyBaseClass::find(ws), wtest.find(ws, 2)); - Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(ws), wtest.find(ws, 3, 5 + 3 - 1)); - wchar_t wstr[2]{ wch, 0 }; - Assert::AreEqual(wtest.MyBaseClass::find(wstr), wtest.find(wstr)); - Assert::AreEqual(wtest.substr(2).MyBaseClass::find(wstr), wtest.find(wstr, 2)); - Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(wstr), wtest.find(wstr, 3, 5 + 3 - 1)); + 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(pcs::CppString::npos, wtest.find(L"A", 1)); + Assert::AreEqual(size_t(0), wtest.find(L"")); + Assert::AreEqual(pcs::CppString::npos, wtest.find(L".", 14)); + Assert::AreEqual(size_t(13), wtest.find(L".", 13)); } TEST_METHOD(find_n) { + // notice: find_n() is fully tested via TEST_METHOD(find) pcs::CppString test{ "ABC0123456789." }; for (int c = 0; c <= 255; ++c) { char ch{ char(c) }; @@ -910,5 +984,43 @@ namespace cppstringstests 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()); + } }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 810934e..ed4fc35 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -583,13 +583,12 @@ namespace pcs // i.e. "pythonic c++ strings" */ constexpr size_type find(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept { - size_type start_{ start }; const size_type end_{ (end == -1) ? this->size() : end }; - if (start_ > end_) + if (start > end_) return CppStringT::npos; else - return find_n(sub, start_, end_ - start_ + 1); + return find_n(sub, start, end_ - start + 1); } /** Returns the lowest index in the string where character ch is found within the slice str[start:end], or -1 (i.e. 'npos') if ch is not found. @@ -642,12 +641,16 @@ namespace pcs // i.e. "pythonic c++ strings" */ 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 { - CppStringT part{ this->substr(start, count) }; - return part.MyBaseClass::find(sub); + 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 CppStringT::npos; + return npos; } } @@ -1049,7 +1052,7 @@ namespace pcs // i.e. "pythonic c++ strings" * The separator between elements is the string to which this method is applied. */ template - inline CppStringT join(const CppStringT& first, const NextCppStringsT... others) const noexcept + inline CppStringT join(const CppStringT& first, const NextCppStringsT&... others) const noexcept requires (sizeof...(others) > 0) { return first + *this + this->join(others...); @@ -1182,43 +1185,23 @@ namespace pcs // i.e. "pythonic c++ strings" //--- replace() --------------------------------------- - /** \brief Returns a copy of the string with all occurrences of substring old replaced by new. */ - CppStringT replace(const CppStringT& old, const CppStringT& new_) const noexcept - { - if (!this->contains(old)) - return *this; - - CppStringT res{}; - size_type last_index = 0; - size_type current_index = 0; - while ((current_index = this->find(old)) != CppStringT::npos) { - res += this->substr(last_index, current_index - last_index) + new_; - last_index = current_index; - } - - if (last_index != this->size()) - res += this->substr(last_index, this->size - last_index); - - return res; - } - - /** \brief Returns a copy of the string with first count occurrences of substring old replaced by new. */ - CppStringT replace(const CppStringT& old, const CppStringT& new_, size_type count) const noexcept + /** \brief Returns a copy of the string with first count occurrences of substring 'old' replaced by 'new_'. */ + CppStringT replace(const CppStringT& old, const CppStringT& new_, size_type count = -1) const noexcept { - if (!this->contains(old) || count == 0) + if (old == new_ || old.empty()) return *this; CppStringT res{}; - size_type last_index = 0; + size_type prev_index = 0; size_type current_index = 0; - while (count > 0 && (current_index = this->find(old)) != CppStringT::npos) { - res += this->substr(last_index, current_index - last_index) + new_; - last_index = current_index; + 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 (last_index != this->size()) - res += this->substr(last_index, this->size - last_index); + if (prev_index < this->size()) + res += this->substr(prev_index, this->size() - prev_index); return res; } From 2c30532a8178f9365ea3076a5741ac65537bf785 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 28 Nov 2023 18:44:24 +0100 Subject: [PATCH 087/137] #160 - Test CppStringT::rfind() with char and wchar_t Tests completed. --- cpp-strings-tests/cpp-strings-tests.cpp | 115 +++++++++++++++++++++++- cpp-strings/cppstrings.h | 36 ++++++-- 2 files changed, 140 insertions(+), 11 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 8f934a8..67e9651 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -967,7 +967,6 @@ namespace cppstringstests Assert::AreEqual(L"cdab", L"abcdab"cs.removeprefix(L"ab").c_str()); } - TEST_METHOD(removesuffix) { pcs::CppString s("abcd"); @@ -985,7 +984,6 @@ namespace cppstringstests Assert::AreEqual(L"abcd", L"abcdab"cs.removesuffix(L"ab").c_str()); } - TEST_METHOD(replace) { pcs::CppString s("abbaa"); @@ -1022,5 +1020,118 @@ namespace cppstringstests 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{ "ABC0123456789." }; + for (int c = 0; c <= 255; ++c) { + char ch{ char(c) }; + Assert::AreEqual(test.MyBaseClass::rfind(ch), test.rfind(ch)); + + found_pos = test.substr(2).MyBaseClass::rfind(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind(ch, 2)); + else + Assert::AreEqual(found_pos, test.rfind(ch, 2) - 2); + + found_pos = test.substr(2, 5).MyBaseClass::rfind(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind(ch, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test.rfind(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + CppString s(ch); + Assert::AreEqual(test.MyBaseClass::rfind(s), test.rfind(s)); + found_pos = test.substr(2).MyBaseClass::rfind(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind(s, 2)); + else + Assert::AreEqual(found_pos, test.rfind(s, 2) - 2); + + found_pos = test.substr(2, 5).MyBaseClass::rfind(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind(s, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test.rfind(s, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + + if (c > 0) { + char str[2]{ ch, 0 }; + Assert::AreEqual(test.MyBaseClass::rfind(str), test.rfind(str)); + + found_pos = test.substr(2).MyBaseClass::rfind(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind(str, 2)); + else + Assert::AreEqual(found_pos, test.rfind(str, 2) - 2); + + found_pos = test.substr(2, 5).MyBaseClass::rfind(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind(str, 2, pcs::CppString::size_type(5 + 2 - 1))); + else + Assert::AreEqual(found_pos, test.rfind(str, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + } + } + Assert::AreEqual(pcs::CppString::npos, test.rfind("A", 1)); + Assert::AreEqual(test.size(), test.rfind("")); + Assert::AreEqual(pcs::CppString::npos, test.rfind(".", 14)); + Assert::AreEqual(size_t(13), test.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); + + 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)); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index ed4fc35..17fab5b 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -576,7 +576,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * 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(). @@ -597,7 +597,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * 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(). @@ -613,7 +613,8 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * end positions are both less than the string size and if start <= end. The + * returned position is 0. * * \see find_n(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). @@ -634,7 +635,8 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * 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(). @@ -660,7 +662,8 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * 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(). @@ -676,7 +679,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 then the string size and if start <= end. + * end positions are both less than the string size and if start <= end. * * \see find(), rfind() and rfind_n(). * \see index(), index_n(), rindex() and rindex_n(). @@ -1215,6 +1218,10 @@ namespace pcs // i.e. "pythonic c++ strings" * 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(). */ @@ -1222,10 +1229,13 @@ namespace pcs // i.e. "pythonic c++ strings" { if (start > end) return CppStringT::npos; - else - return this->substr(start, end - start + 1).rfind(sub); + else { + const size_type found_pos{ this->substr(start, end - start + 1).rfind(sub) }; + return (found_pos == CppStringT::npos) ? CppStringT::npos : found_pos + start; + } } + /** 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. @@ -1233,12 +1243,16 @@ namespace pcs // i.e. "pythonic c++ strings" * 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(). */ inline constexpr size_type rfind(const CppStringT& sub, const size_type start) const noexcept { - return rfind(sub, start, this->size() - start + 1); + return rfind(sub, start, this->size() - 1); } /** Returns the highest index in the string where substring sub is found in the whole string, or -1 (i.e. 'npos') if sub is not found. @@ -1248,6 +1262,10 @@ namespace pcs // i.e. "pythonic c++ strings" * 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(). */ From 6ff8a0f264f84501cca5c818ce00cc1a3d024287 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 2 Dec 2023 18:33:11 +0100 Subject: [PATCH 088/137] #196 - Extend and fix tests on find() and index() methods Completed; Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 191 +++++++++++++++++++----- cpp-strings/cppstrings.h | 2 +- 2 files changed, 152 insertions(+), 41 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 67e9651..0f4143b 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -173,7 +173,7 @@ namespace cppstringstests { size_t found_pos; - pcs::CppString test{ "ABC0123456789." }; + pcs::CppString test{ "ABC0123456789.ABC0123456789." }; for (int c = 0; c <= 255; ++c) { char ch{ char(c) }; Assert::AreEqual(test.MyBaseClass::find(ch), test.find(ch)); @@ -221,12 +221,14 @@ namespace cppstringstests Assert::AreEqual(found_pos, test.find(str, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); } } - Assert::AreEqual(pcs::CppString::npos, test.find("A", 1)); + Assert::AreEqual(size_t(14), test.find("A", 1)); + Assert::AreEqual(pcs::CppString::npos, test.find("A", 15)); Assert::AreEqual(size_t(0), test.find("")); - Assert::AreEqual(pcs::CppString::npos, test.find(".", 14)); + Assert::AreEqual(size_t(27), test.find(".", 14)); + Assert::AreEqual(pcs::CppString::npos, test.find(".", 28)); Assert::AreEqual(size_t(13), test.find(".", 13)); - pcs::CppWString wtest{ L"ABC0123456789." }; + pcs::CppWString wtest{ L"ABC0123456789.ABC0123456789." }; for (int wc = 0; wc <=0xffff; ++wc) { wchar_t wch{ wchar_t(wc) }; @@ -275,34 +277,76 @@ namespace cppstringstests Assert::AreEqual(found_pos, wtest.find(wstr, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); } } - Assert::AreEqual(pcs::CppString::npos, wtest.find(L"A", 1)); + 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(pcs::CppString::npos, wtest.find(L".", 14)); + 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) { - // notice: find_n() is fully tested via TEST_METHOD(find) - pcs::CppString test{ "ABC0123456789." }; + size_t found_pos; + + pcs::CppString test{ "ABC0123456789.ABC0123456789." }; for (int c = 0; c <= 255; ++c) { char ch{ char(c) }; - Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.find_n(ch, 2, -1)); - Assert::AreEqual(test.substr(0, 2).MyBaseClass::find(ch), test.find_n(ch, 2)); - Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.find_n(ch, 2, 5)); + Assert::AreEqual(test.MyBaseClass::find(ch), test.find_n(ch, size_t(-1))); + + found_pos = test.substr(2).MyBaseClass::find(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find_n(ch, 2)); + else + Assert::AreEqual(found_pos, test.substr(2).find_n(ch, test.size() - 2)); + + found_pos = test.substr(2, 5).MyBaseClass::find(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find_n(ch, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test.find_n(ch, 2, pcs::CppString::size_type(5)) - 2); CppString s(ch); - Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.find_n(s, 2, -1)); - Assert::AreEqual(test.substr(0, 2).MyBaseClass::find(s), test.find_n(s, 2)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.find_n(s, 3, 5)); - - char str[2]{ ch, 0 }; - Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.find_n(str, 2, -1)); - Assert::AreEqual(test.substr(0, 2).MyBaseClass::find(str), test.find_n(str, 2)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.find_n(str, 3, 5)); + Assert::AreEqual(test.MyBaseClass::find(s), test.find_n(s, size_t(-1))); + found_pos = test.substr(2).MyBaseClass::find(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find_n(s, 2)); + else + Assert::AreEqual(found_pos, test.substr(2).find_n(s, test.size() - 2)); + + found_pos = test.substr(2, 5).MyBaseClass::find(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find_n(s, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test.find_n(s, 2, pcs::CppString::size_type(5)) - 2); + + if (c > 0) { + char str[2]{ ch, 0 }; + Assert::AreEqual(test.MyBaseClass::find(str), test.find_n(str, size_t(-1))); + + found_pos = test.substr(2).MyBaseClass::find(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find_n(str, test.size() - 2)); + else + Assert::AreEqual(found_pos, test.substr(2).find_n(str, test.size() - 2)); + + found_pos = test.substr(2, 5).MyBaseClass::find(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.find_n(str, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test.find_n(str, 2, pcs::CppString::size_type(5)) - 2); + } } + Assert::AreEqual(size_t(14), test.find_n("A", 1, test.size() - 1)); + Assert::AreEqual(pcs::CppString::npos, test.find_n("A", 15, 1)); + Assert::AreEqual(size_t(0), test.find_n("", size_t(-1))); + Assert::AreEqual(size_t(27), test.find_n(".", 14, test.size() - 14)); + Assert::AreEqual(pcs::CppString::npos, test.find_n(".", 28, 1)); + Assert::AreEqual(size_t(13), test.find_n(".", 13, test.size() - 13)); - pcs::CppWString wtest{ L"ABC0123456789." }; + + /* + pcs::CppWString wtest{L"ABC0123456789.ABC0123456789."}; for (int wc = 0; wc <= 0xffff; ++wc) { wchar_t wch{ wchar_t(wc) }; Assert::AreEqual(wtest.substr(2).MyBaseClass::find(wch), wtest.find_n(wch, 2, -1)); @@ -319,6 +363,62 @@ namespace cppstringstests Assert::AreEqual(wtest.substr(0, 2).MyBaseClass::find(wstr), wtest.find_n(wstr, 2)); Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(wstr), wtest.find_n(wstr, 3, 5)); } + */ + 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); + + 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(index_char) @@ -328,18 +428,20 @@ namespace cppstringstests string_type test{ "ABC0123456789." }; char ch{ '3' }; Assert::AreEqual(test.MyBaseClass::find(ch), test.index(ch)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.index(ch, 2)); - Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index(ch, 2, string_type::size_type(5 + 2 - 1))); + Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.index(ch, 2) - 2); + Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index(ch, 2, string_type::size_type(5 + 2 - 1)) - 2); try { const string_type::size_type pos = test.index('z'); Assert::IsTrue(pos != pcs::CppString::npos); } catch (const string_type::NotFoundException e) { /* ok case! */ } + try { const string_type::size_type pos = test.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.index('z', 2, 5+2-1); Assert::IsTrue(pos != string_type::npos); @@ -348,19 +450,21 @@ namespace cppstringstests string_type s(ch); Assert::AreEqual(test.MyBaseClass::find(s), test.index(s)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.index(s, 2)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index(s, 3, string_type::size_type(5 + 3 - 1))); + Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.index(s, 2) - 2); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index(s, 3, string_type::size_type(5 + 3 - 1)) - 3); s = 'z'; try { const string_type::size_type pos = test.index(s); Assert::IsTrue(pos != string_type::npos); } catch (const string_type::NotFoundException e) { /* ok case! */ } + try { const string_type::size_type pos = test.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.index(s, 2, string_type::size_type(5 + 2 - 1)); Assert::IsTrue(pos != string_type::npos); @@ -369,19 +473,21 @@ namespace cppstringstests char str[2]{ ch, 0 }; Assert::AreEqual(test.MyBaseClass::find(str), test.index(str)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.index(str, 2)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index(str, 3, string_type::size_type(5 + 3 - 1))); + Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.index(str, 2) - 2); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index(str, 3, string_type::size_type(5 + 3 - 1)) - 3); str[0] = 'z'; try { const string_type::size_type pos = test.index(s); Assert::IsTrue(pos != string_type::npos); } catch (const string_type::NotFoundException e) { /* ok case! */ } + try { const string_type::size_type pos = test.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.index(s, 2, string_type::size_type(5 + 2 - 1)); Assert::IsTrue(pos != string_type::npos); @@ -396,39 +502,43 @@ namespace cppstringstests string_type test( L"ABC0123456789." ); wchar_t ch{ L'3' }; Assert::AreEqual(test.MyBaseClass::find(ch), test.index(ch)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.index(ch, 2)); - Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index(ch, 2, string_type::size_type(5 + 2 - 1))); + Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.index(ch, 2) - 2); + Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index(ch, 2, string_type::size_type(5 + 2 - 1)) - 2); try { const string_type::size_type pos = test.index('z'); Assert::IsTrue(pos != pcs::CppString::npos); } catch (const string_type::NotFoundException e) { /* ok case! */ } + try { const string_type::size_type pos = test.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.index('z', 2, 5 + 2 - 1); + const string_type::size_type pos = test.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.MyBaseClass::find(s), test.index(s)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.index(s, 2)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index(s, 3, string_type::size_type(5 + 3 - 1))); + Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.index(s, 2) - 2); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index(s, 3, string_type::size_type(5 + 3 - 1)) - 3); s = 'z'; try { const string_type::size_type pos = test.index(s); Assert::IsTrue(pos != string_type::npos); } catch (const string_type::NotFoundException e) { /* ok case! */ } + try { const string_type::size_type pos = test.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.index(s, 2, string_type::size_type(5 + 2 - 1)); Assert::IsTrue(pos != string_type::npos); @@ -437,19 +547,21 @@ namespace cppstringstests wchar_t str[2]{ ch, 0 }; Assert::AreEqual(test.MyBaseClass::find(str), test.index(str)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.index(str, 2)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index(str, 3, string_type::size_type(5 + 3 - 1))); + Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.index(str, 2) - 2); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index(str, 3, string_type::size_type(5 + 3 - 1)) - 3); str[0] = 'z'; try { const string_type::size_type pos = test.index(s); Assert::IsTrue(pos != string_type::npos); } catch (const string_type::NotFoundException e) { /* ok case! */ } + try { const string_type::size_type pos = test.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.index(s, 2, string_type::size_type(5 + 2 - 1)); Assert::IsTrue(pos != string_type::npos); @@ -464,7 +576,7 @@ namespace cppstringstests pcs::CppString test{ "ABC0123456789." }; char ch{ '3' }; Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(ch), test.index_n(ch, 20)); - Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index_n(ch, 2, 5)); + Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index_n(ch, 2, 5) - 2); try { const string_type::size_type pos = test.index_n('z', 20); Assert::IsTrue(pos != string_type::npos); @@ -478,7 +590,7 @@ namespace cppstringstests CppString s(ch); Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(s), test.index_n(s, 20)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index_n(s, 3, 5)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index_n(s, 3, 5) - 3); s = 'z'; try { const string_type::size_type pos = test.index_n(s, 20); @@ -493,7 +605,7 @@ namespace cppstringstests char str[2]{ ch, 0 }; Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(str), test.index_n(str, 20)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index_n(str, 3, 5)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index_n(str, 3, 5) - 3); str[0] = 'z'; try { const string_type::size_type pos = test.index_n(s, 20); @@ -514,7 +626,7 @@ namespace cppstringstests string_type test{ L"ABC0123456789." }; wchar_t ch{ L'3'}; Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(ch), test.index_n(ch, 20)); - Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index_n(ch, 2, 5)); + Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index_n(ch, 2, 5) - 2); try { const string_type::size_type pos = test.index_n('z', 20); Assert::IsTrue(pos != string_type::npos); @@ -528,7 +640,7 @@ namespace cppstringstests string_type s(ch); Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(s), test.index_n(s, 20)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index_n(s, 3, 5)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index_n(s, 3, 5) - 3); try { const string_type::size_type pos = test.index_n(s, 20); Assert::IsTrue(pos != string_type::npos); @@ -542,7 +654,7 @@ namespace cppstringstests wchar_t str[2]{ ch, 0 }; Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(str), test.index_n(str, 20)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index_n(str, 3, 5)); + Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index_n(str, 3, 5) - 3); str[0] = L'z'; try { const string_type::size_type pos = test.index_n(s, 20); @@ -1132,6 +1244,5 @@ namespace cppstringstests Assert::AreEqual(pcs::CppString::npos, wtest.rfind(L".", 14)); Assert::AreEqual(size_t(13), wtest.rfind(L".", 13)); } - }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 17fab5b..fe5de79 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1312,7 +1312,7 @@ namespace pcs // i.e. "pythonic c++ strings" 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 (size_type == CppStringT::npos) + if (ret_value == CppStringT::npos) throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); else return ret_value; From cbcaae591572a76b9f558dc2e2ef7340f0241035 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 5 Dec 2023 13:10:01 +0100 Subject: [PATCH 089/137] #161 - Test CppStringT::rfind_n() with char and wchar_t Completed. --- cpp-strings-tests/cpp-strings-tests.cpp | 137 ++++++++++++++++++++---- cpp-strings/cppstrings.h | 7 +- 2 files changed, 122 insertions(+), 22 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 0f4143b..fba46fa 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -344,26 +344,6 @@ namespace cppstringstests Assert::AreEqual(pcs::CppString::npos, test.find_n(".", 28, 1)); Assert::AreEqual(size_t(13), test.find_n(".", 13, test.size() - 13)); - - /* - pcs::CppWString wtest{L"ABC0123456789.ABC0123456789."}; - for (int wc = 0; wc <= 0xffff; ++wc) { - wchar_t wch{ wchar_t(wc) }; - Assert::AreEqual(wtest.substr(2).MyBaseClass::find(wch), wtest.find_n(wch, 2, -1)); - Assert::AreEqual(wtest.substr(0, 2).MyBaseClass::find(wch), wtest.find_n(wch, 2)); - Assert::AreEqual(wtest.substr(2, 5).MyBaseClass::find(wch), wtest.find_n(wch, 2, 5)); - - CppWString ws(wch); - Assert::AreEqual(wtest.substr(2).MyBaseClass::find(ws), wtest.find_n(ws, 2, -1)); - Assert::AreEqual(wtest.substr(0, 2).MyBaseClass::find(ws), wtest.find_n(ws, 2)); - Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(ws), wtest.find_n(ws, 3, 5)); - - wchar_t wstr[2]{ wch, 0 }; - Assert::AreEqual(wtest.substr(2).MyBaseClass::find(wstr), wtest.find_n(wstr, 2, -1)); - Assert::AreEqual(wtest.substr(0, 2).MyBaseClass::find(wstr), wtest.find_n(wstr, 2)); - Assert::AreEqual(wtest.substr(3, 5).MyBaseClass::find(wstr), wtest.find_n(wstr, 3, 5)); - } - */ pcs::CppWString wtest{ L"ABC0123456789.ABC0123456789." }; for (int wc = 0; wc <= 0xffff; ++wc) { wchar_t wch{ wchar_t(wc) }; @@ -1221,7 +1201,6 @@ namespace cppstringstests 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)); @@ -1244,5 +1223,121 @@ namespace cppstringstests 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{ "ABC0123456789.ABC0123456789." }; + for (int c = 0; c <= 255; ++c) { + char ch{ char(c) }; + Assert::AreEqual(test.MyBaseClass::rfind(ch), test.rfind_n(ch, size_t(-1))); + + found_pos = test.substr(2).MyBaseClass::rfind(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind_n(ch, 2)); + else + Assert::AreEqual(found_pos, test.substr(2).rfind_n(ch, test.size() - 2)); + + found_pos = test.substr(2, 5).MyBaseClass::rfind(ch); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind_n(ch, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test.rfind_n(ch, 2, pcs::CppString::size_type(5)) - 2); + + CppString s(ch); + Assert::AreEqual(test.MyBaseClass::rfind(s), test.rfind_n(s, size_t(-1))); + found_pos = test.substr(2).MyBaseClass::rfind(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind_n(s, 2)); + else + Assert::AreEqual(found_pos, test.substr(2).rfind_n(s, test.size() - 2)); + + found_pos = test.substr(2, 5).MyBaseClass::rfind(s); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind_n(s, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test.rfind_n(s, 2, pcs::CppString::size_type(5)) - 2); + + if (c > 0) { + char str[2]{ ch, 0 }; + Assert::AreEqual(test.MyBaseClass::rfind(str), test.rfind_n(str, size_t(-1))); + + found_pos = test.substr(2).MyBaseClass::rfind(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind_n(str, test.size() - 2)); + else + Assert::AreEqual(found_pos, test.substr(2).rfind_n(str, test.size() - 2)); + + found_pos = test.substr(2, 5).MyBaseClass::rfind(str); + if (found_pos == pcs::CppString::npos) + Assert::AreEqual(found_pos, test.rfind_n(str, 2, pcs::CppString::size_type(5))); + else + Assert::AreEqual(found_pos, test.rfind_n(str, 2, pcs::CppString::size_type(5)) - 2); + } + } + Assert::AreEqual(size_t(14), test.rfind_n("A", 1, test.size() - 1)); + Assert::AreEqual(pcs::CppString::npos, test.rfind_n("A", 15, 1)); + Assert::AreEqual(size_t(0), test.rfind_n("", size_t(-1))); + Assert::AreEqual(size_t(27), test.rfind_n(".", 14, test.size() - 14)); + Assert::AreEqual(pcs::CppString::npos, test.rfind_n(".", 28, 1)); + Assert::AreEqual(size_t(27), test.rfind_n(".", 13, test.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); + + 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)); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index fe5de79..d3f10cf 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1229,6 +1229,8 @@ namespace pcs // i.e. "pythonic c++ strings" { if (start > end) return CppStringT::npos; + else if (sub.empty()) + return 0; else { const size_type found_pos{ this->substr(start, end - start + 1).rfind(sub) }; return (found_pos == CppStringT::npos) ? CppStringT::npos : found_pos + start; @@ -1299,7 +1301,10 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline constexpr size_type rfind_n(const CppStringT& sub, const size_type count) const noexcept { - return rfind(sub, 0, count); + if (count == 0) + return CppStringT::npos; + else + return rfind(sub, 0, count - 1); } From db2e4083d03c0a6f951ce472a6893188597bf6ca Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 7 Jul 2025 20:09:07 +0200 Subject: [PATCH 090/137] #199-refactor tests Modified structure. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 1008 ++++++++++++++--- cpp-strings-tests/cpp-strings-tests.vcxproj | 49 +- .../cpp-strings-tests.vcxproj.filters | 8 - cpp-strings-tests/pch.cpp | 673 ----------- cpp-strings-tests/pch.h | 16 - 5 files changed, 860 insertions(+), 894 deletions(-) delete mode 100644 cpp-strings-tests/pch.cpp delete mode 100644 cpp-strings-tests/pch.h diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index fba46fa..d8a9bfa 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -1,4 +1,3 @@ -#include "pch.h" #include "CppUnitTest.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -9,10 +8,665 @@ using namespace pcs; namespace cppstringstests { + + //===== PART 1 ============================================ + TEST_CLASS(cppstringstests_PART_1) + { + public: + + TEST_METHOD(_cs) + { + using namespace pcs; + auto abcd = "abcD"cs; + auto wabcd = L"abcD"cs; + Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); + Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); + } + + TEST_METHOD(_csv) + { + using namespace pcs; + auto abcd = "abcD"csv; + auto wabcd = L"abcD"csv; + Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); + Assert::AreEqual(wabcd.c_str(), 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) + { + 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) + { + CppString keys("abcdE"); + CppString values("ABCDe"); + pcs::CppString::TransTable t(keys, values); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString('D').c_str(), t['d'].c_str()); + Assert::AreEqual(CppString('e').c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abcdE"), CppWString(L"ABCDe")); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString(L'D').c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString(L'e').c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_03) + { + pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_04) + { + pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }); + Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }); + Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString(L'9').c_str(), wt[L'9'].c_str()); + } + + TEST_METHOD(constructor_05) + { + pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }, "dE"cs); + Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }, L"dE"cs); + Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'e').c_str(), wt[L'e'].c_str()); + } + + TEST_METHOD(constructor_06) + { + pcs::CppString::TransTable t("abC", "ABc"); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['c'].c_str()); + + pcs::CppWString::TransTable wt(L"abC", L"ABc"); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); + } + + TEST_METHOD(constructor_07) + { + pcs::CppString::TransTable t("abc", "ABC", "dE"); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('e').c_str(), t['e'].c_str()); + + pcs::CppWString::TransTable wt(L"abc", L"ABC", L"dE"); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); + Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(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(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t(ct); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt(wct); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(constructor_move) + { + pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t(std::move(mt)); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt(std::move(wmt)); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(assign_copy) + { + pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t = ct; + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt = wct; + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(assign_move) + { + pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t = std::move(mt); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt = std::move(wmt); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(assign_map) + { + pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable t = ct.get_table(); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); + + pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + pcs::CppWString::TransTable wt = wct.get_table(); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + } + + TEST_METHOD(indexing) + { + pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); + Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); + Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); + Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); + Assert::AreEqual(CppString().c_str(), t['d'].c_str()); + Assert::AreEqual(CppString().c_str(), t['E'].c_str()); + Assert::AreEqual(CppString(',').c_str(), t[','].c_str()); + + pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); + Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); + Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); + Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); + Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); + Assert::AreEqual(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()); + } + + 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()); + } + + 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(capitalize) { pcs::CppString s("abc def GHi jKl 032, JHGF/"); @@ -173,60 +827,60 @@ namespace cppstringstests { size_t found_pos; - pcs::CppString test{ "ABC0123456789.ABC0123456789." }; + pcs::CppString test_str{ "ABC0123456789.ABC0123456789." }; for (int c = 0; c <= 255; ++c) { char ch{ char(c) }; - Assert::AreEqual(test.MyBaseClass::find(ch), test.find(ch)); + Assert::AreEqual(test_str.MyBaseClass::find(ch), test_str.find(ch)); - found_pos = test.substr(2).MyBaseClass::find(ch); + found_pos = test_str.substr(2).MyBaseClass::find(ch); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find(ch, 2)); + Assert::AreEqual(found_pos, test_str.find(ch, 2)); else - Assert::AreEqual(found_pos, test.find(ch, 2) - 2); + Assert::AreEqual(found_pos, test_str.find(ch, 2) - 2); - found_pos = test.substr(2, 5).MyBaseClass::find(ch); + found_pos = test_str.substr(2, 5).MyBaseClass::find(ch); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find(ch, 2, pcs::CppString::size_type(5 + 2 - 1))); + Assert::AreEqual(found_pos, test_str.find(ch, 2, pcs::CppString::size_type(5 + 2 - 1))); else - Assert::AreEqual(found_pos, test.find(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + Assert::AreEqual(found_pos, test_str.find(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); CppString s(ch); - Assert::AreEqual(test.MyBaseClass::find(s), test.find(s)); - found_pos = test.substr(2).MyBaseClass::find(s); + 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.find(s, 2)); + Assert::AreEqual(found_pos, test_str.find(s, 2)); else - Assert::AreEqual(found_pos, test.find(s, 2) - 2); + Assert::AreEqual(found_pos, test_str.find(s, 2) - 2); - found_pos = test.substr(2, 5).MyBaseClass::find(s); + found_pos = test_str.substr(2, 5).MyBaseClass::find(s); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find(s, 2, pcs::CppString::size_type(5 + 2 - 1))); + Assert::AreEqual(found_pos, test_str.find(s, 2, pcs::CppString::size_type(5 + 2 - 1))); else - Assert::AreEqual(found_pos, test.find(s, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + 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.MyBaseClass::find(str), test.find(str)); + Assert::AreEqual(test_str.MyBaseClass::find(str), test_str.find(str)); - found_pos = test.substr(2).MyBaseClass::find(str); + found_pos = test_str.substr(2).MyBaseClass::find(str); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find(str, 2)); + Assert::AreEqual(found_pos, test_str.find(str, 2)); else - Assert::AreEqual(found_pos, test.find(str, 2) - 2); + Assert::AreEqual(found_pos, test_str.find(str, 2) - 2); - found_pos = test.substr(2, 5).MyBaseClass::find(str); + found_pos = test_str.substr(2, 5).MyBaseClass::find(str); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find(str, 2, pcs::CppString::size_type(5 + 2 - 1))); + Assert::AreEqual(found_pos, test_str.find(str, 2, pcs::CppString::size_type(5 + 2 - 1))); else - Assert::AreEqual(found_pos, test.find(str, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + Assert::AreEqual(found_pos, test_str.find(str, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); } } - Assert::AreEqual(size_t(14), test.find("A", 1)); - Assert::AreEqual(pcs::CppString::npos, test.find("A", 15)); - Assert::AreEqual(size_t(0), test.find("")); - Assert::AreEqual(size_t(27), test.find(".", 14)); - Assert::AreEqual(pcs::CppString::npos, test.find(".", 28)); - Assert::AreEqual(size_t(13), test.find(".", 13)); + 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) { @@ -289,60 +943,60 @@ namespace cppstringstests { size_t found_pos; - pcs::CppString test{ "ABC0123456789.ABC0123456789." }; + pcs::CppString test_str{ "ABC0123456789.ABC0123456789." }; for (int c = 0; c <= 255; ++c) { char ch{ char(c) }; - Assert::AreEqual(test.MyBaseClass::find(ch), test.find_n(ch, size_t(-1))); + Assert::AreEqual(test_str.MyBaseClass::find(ch), test_str.find_n(ch, size_t(-1))); - found_pos = test.substr(2).MyBaseClass::find(ch); + found_pos = test_str.substr(2).MyBaseClass::find(ch); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find_n(ch, 2)); + Assert::AreEqual(found_pos, test_str.find_n(ch, 2)); else - Assert::AreEqual(found_pos, test.substr(2).find_n(ch, test.size() - 2)); + Assert::AreEqual(found_pos, test_str.substr(2).find_n(ch, test_str.size() - 2)); - found_pos = test.substr(2, 5).MyBaseClass::find(ch); + found_pos = test_str.substr(2, 5).MyBaseClass::find(ch); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find_n(ch, 2, pcs::CppString::size_type(5))); + Assert::AreEqual(found_pos, test_str.find_n(ch, 2, pcs::CppString::size_type(5))); else - Assert::AreEqual(found_pos, test.find_n(ch, 2, pcs::CppString::size_type(5)) - 2); + Assert::AreEqual(found_pos, test_str.find_n(ch, 2, pcs::CppString::size_type(5)) - 2); CppString s(ch); - Assert::AreEqual(test.MyBaseClass::find(s), test.find_n(s, size_t(-1))); - found_pos = test.substr(2).MyBaseClass::find(s); + 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.find_n(s, 2)); + Assert::AreEqual(found_pos, test_str.find_n(s, 2)); else - Assert::AreEqual(found_pos, test.substr(2).find_n(s, test.size() - 2)); + Assert::AreEqual(found_pos, test_str.substr(2).find_n(s, test_str.size() - 2)); - found_pos = test.substr(2, 5).MyBaseClass::find(s); + found_pos = test_str.substr(2, 5).MyBaseClass::find(s); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find_n(s, 2, pcs::CppString::size_type(5))); + Assert::AreEqual(found_pos, test_str.find_n(s, 2, pcs::CppString::size_type(5))); else - Assert::AreEqual(found_pos, test.find_n(s, 2, pcs::CppString::size_type(5)) - 2); + 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.MyBaseClass::find(str), test.find_n(str, size_t(-1))); + Assert::AreEqual(test_str.MyBaseClass::find(str), test_str.find_n(str, size_t(-1))); - found_pos = test.substr(2).MyBaseClass::find(str); + found_pos = test_str.substr(2).MyBaseClass::find(str); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find_n(str, test.size() - 2)); + Assert::AreEqual(found_pos, test_str.find_n(str, test_str.size() - 2)); else - Assert::AreEqual(found_pos, test.substr(2).find_n(str, test.size() - 2)); + Assert::AreEqual(found_pos, test_str.substr(2).find_n(str, test_str.size() - 2)); - found_pos = test.substr(2, 5).MyBaseClass::find(str); + found_pos = test_str.substr(2, 5).MyBaseClass::find(str); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.find_n(str, 2, pcs::CppString::size_type(5))); + Assert::AreEqual(found_pos, test_str.find_n(str, 2, pcs::CppString::size_type(5))); else - Assert::AreEqual(found_pos, test.find_n(str, 2, pcs::CppString::size_type(5)) - 2); + Assert::AreEqual(found_pos, test_str.find_n(str, 2, pcs::CppString::size_type(5)) - 2); } } - Assert::AreEqual(size_t(14), test.find_n("A", 1, test.size() - 1)); - Assert::AreEqual(pcs::CppString::npos, test.find_n("A", 15, 1)); - Assert::AreEqual(size_t(0), test.find_n("", size_t(-1))); - Assert::AreEqual(size_t(27), test.find_n(".", 14, test.size() - 14)); - Assert::AreEqual(pcs::CppString::npos, test.find_n(".", 28, 1)); - Assert::AreEqual(size_t(13), test.find_n(".", 13, test.size() - 13)); + 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) { @@ -405,71 +1059,71 @@ namespace cppstringstests { using string_type = pcs::CppString; - string_type test{ "ABC0123456789." }; + string_type test_str{ "ABC0123456789." }; char ch{ '3' }; - Assert::AreEqual(test.MyBaseClass::find(ch), test.index(ch)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.index(ch, 2) - 2); - Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index(ch, 2, string_type::size_type(5 + 2 - 1)) - 2); + 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.index('z'); + 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.index('z', 2); + 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.index('z', 2, 5+2-1); + 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.MyBaseClass::find(s), test.index(s)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.index(s, 2) - 2); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index(s, 3, string_type::size_type(5 + 3 - 1)) - 3); + 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.index(s); + 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.index(s, 2); + 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.index(s, 2, string_type::size_type(5 + 2 - 1)); + 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.MyBaseClass::find(str), test.index(str)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.index(str, 2) - 2); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index(str, 3, string_type::size_type(5 + 3 - 1)) - 3); + 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.index(s); + 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.index(s, 2); + 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.index(s, 2, string_type::size_type(5 + 2 - 1)); + 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! */ } @@ -479,71 +1133,71 @@ namespace cppstringstests { using string_type = pcs::CppWString; - string_type test( L"ABC0123456789." ); + string_type test_str( L"ABC0123456789." ); wchar_t ch{ L'3' }; - Assert::AreEqual(test.MyBaseClass::find(ch), test.index(ch)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(ch), test.index(ch, 2) - 2); - Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index(ch, 2, string_type::size_type(5 + 2 - 1)) - 2); + 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.index('z'); + 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.index('z', 2); + 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.index('z', 2, string_type::size_type(5 + 2 - 1)); + 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.MyBaseClass::find(s), test.index(s)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(s), test.index(s, 2) - 2); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index(s, 3, string_type::size_type(5 + 3 - 1)) - 3); + 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.index(s); + 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.index(s, 2); + 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.index(s, 2, string_type::size_type(5 + 2 - 1)); + 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.MyBaseClass::find(str), test.index(str)); - Assert::AreEqual(test.substr(2).MyBaseClass::find(str), test.index(str, 2) - 2); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index(str, 3, string_type::size_type(5 + 3 - 1)) - 3); + 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.index(s); + 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.index(s, 2); + 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.index(s, 2, string_type::size_type(5 + 2 - 1)); + 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! */ } @@ -553,47 +1207,47 @@ namespace cppstringstests { using string_type = pcs::CppString; - pcs::CppString test{ "ABC0123456789." }; + pcs::CppString test_str{ "ABC0123456789." }; char ch{ '3' }; - Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(ch), test.index_n(ch, 20)); - Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index_n(ch, 2, 5) - 2); + 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.index_n('z', 20); + 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.index_n('z', 2, 5); + 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! */ } CppString s(ch); - Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(s), test.index_n(s, 20)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index_n(s, 3, 5) - 3); + 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.index_n(s, 20); + 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.index_n(s, 2, 5); + 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.substr(0, 20).MyBaseClass::find(str), test.index_n(str, 20)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index_n(str, 3, 5) - 3); + 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.index_n(s, 20); + 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.index_n(s, 2, 5); + 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! */ } @@ -603,46 +1257,46 @@ namespace cppstringstests { using string_type = pcs::CppWString; - string_type test{ L"ABC0123456789." }; + string_type test_str{ L"ABC0123456789." }; wchar_t ch{ L'3'}; - Assert::AreEqual(test.substr(0, 20).MyBaseClass::find(ch), test.index_n(ch, 20)); - Assert::AreEqual(test.substr(2, 5).MyBaseClass::find(ch), test.index_n(ch, 2, 5) - 2); + 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.index_n('z', 20); + 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.index_n('z', 2, 5); + 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.substr(0, 20).MyBaseClass::find(s), test.index_n(s, 20)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(s), test.index_n(s, 3, 5) - 3); + 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.index_n(s, 20); + 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.index_n(s, 2, 5); + 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.substr(0, 20).MyBaseClass::find(str), test.index_n(str, 20)); - Assert::AreEqual(test.substr(3, 5).MyBaseClass::find(str), test.index_n(str, 3, 5) - 3); + 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.index_n(s, 20); + 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.index_n(s, 2, 5); + 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! */ } @@ -731,6 +1385,7 @@ namespace cppstringstests 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()); @@ -741,6 +1396,7 @@ namespace cppstringstests 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()); @@ -1117,58 +1773,58 @@ namespace cppstringstests { size_t found_pos; - pcs::CppString test{ "ABC0123456789." }; + pcs::CppString test_str{ "ABC0123456789." }; for (int c = 0; c <= 255; ++c) { char ch{ char(c) }; - Assert::AreEqual(test.MyBaseClass::rfind(ch), test.rfind(ch)); + Assert::AreEqual(test_str.MyBaseClass::rfind(ch), test_str.rfind(ch)); - found_pos = test.substr(2).MyBaseClass::rfind(ch); + found_pos = test_str.substr(2).MyBaseClass::rfind(ch); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind(ch, 2)); + Assert::AreEqual(found_pos, test_str.rfind(ch, 2)); else - Assert::AreEqual(found_pos, test.rfind(ch, 2) - 2); + Assert::AreEqual(found_pos, test_str.rfind(ch, 2) - 2); - found_pos = test.substr(2, 5).MyBaseClass::rfind(ch); + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(ch); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind(ch, 2, pcs::CppString::size_type(5 + 2 - 1))); + Assert::AreEqual(found_pos, test_str.rfind(ch, 2, pcs::CppString::size_type(5 + 2 - 1))); else - Assert::AreEqual(found_pos, test.rfind(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + Assert::AreEqual(found_pos, test_str.rfind(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); CppString s(ch); - Assert::AreEqual(test.MyBaseClass::rfind(s), test.rfind(s)); - found_pos = test.substr(2).MyBaseClass::rfind(s); + 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.rfind(s, 2)); + Assert::AreEqual(found_pos, test_str.rfind(s, 2)); else - Assert::AreEqual(found_pos, test.rfind(s, 2) - 2); + Assert::AreEqual(found_pos, test_str.rfind(s, 2) - 2); - found_pos = test.substr(2, 5).MyBaseClass::rfind(s); + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(s); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind(s, 2, pcs::CppString::size_type(5 + 2 - 1))); + Assert::AreEqual(found_pos, test_str.rfind(s, 2, pcs::CppString::size_type(5 + 2 - 1))); else - Assert::AreEqual(found_pos, test.rfind(s, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + 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.MyBaseClass::rfind(str), test.rfind(str)); + Assert::AreEqual(test_str.MyBaseClass::rfind(str), test_str.rfind(str)); - found_pos = test.substr(2).MyBaseClass::rfind(str); + found_pos = test_str.substr(2).MyBaseClass::rfind(str); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind(str, 2)); + Assert::AreEqual(found_pos, test_str.rfind(str, 2)); else - Assert::AreEqual(found_pos, test.rfind(str, 2) - 2); + Assert::AreEqual(found_pos, test_str.rfind(str, 2) - 2); - found_pos = test.substr(2, 5).MyBaseClass::rfind(str); + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(str); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind(str, 2, pcs::CppString::size_type(5 + 2 - 1))); + Assert::AreEqual(found_pos, test_str.rfind(str, 2, pcs::CppString::size_type(5 + 2 - 1))); else - Assert::AreEqual(found_pos, test.rfind(str, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); + Assert::AreEqual(found_pos, test_str.rfind(str, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); } } - Assert::AreEqual(pcs::CppString::npos, test.rfind("A", 1)); - Assert::AreEqual(test.size(), test.rfind("")); - Assert::AreEqual(pcs::CppString::npos, test.rfind(".", 14)); - Assert::AreEqual(size_t(13), test.rfind(".", 13)); + 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) { @@ -1228,60 +1884,60 @@ namespace cppstringstests { size_t found_pos; - pcs::CppString test{ "ABC0123456789.ABC0123456789." }; + pcs::CppString test_str{ "ABC0123456789.ABC0123456789." }; for (int c = 0; c <= 255; ++c) { char ch{ char(c) }; - Assert::AreEqual(test.MyBaseClass::rfind(ch), test.rfind_n(ch, size_t(-1))); + Assert::AreEqual(test_str.MyBaseClass::rfind(ch), test_str.rfind_n(ch, size_t(-1))); - found_pos = test.substr(2).MyBaseClass::rfind(ch); + found_pos = test_str.substr(2).MyBaseClass::rfind(ch); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind_n(ch, 2)); + Assert::AreEqual(found_pos, test_str.rfind_n(ch, 2)); else - Assert::AreEqual(found_pos, test.substr(2).rfind_n(ch, test.size() - 2)); + Assert::AreEqual(found_pos, test_str.substr(2).rfind_n(ch, test_str.size() - 2)); - found_pos = test.substr(2, 5).MyBaseClass::rfind(ch); + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(ch); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind_n(ch, 2, pcs::CppString::size_type(5))); + Assert::AreEqual(found_pos, test_str.rfind_n(ch, 2, pcs::CppString::size_type(5))); else - Assert::AreEqual(found_pos, test.rfind_n(ch, 2, pcs::CppString::size_type(5)) - 2); + Assert::AreEqual(found_pos, test_str.rfind_n(ch, 2, pcs::CppString::size_type(5)) - 2); CppString s(ch); - Assert::AreEqual(test.MyBaseClass::rfind(s), test.rfind_n(s, size_t(-1))); - found_pos = test.substr(2).MyBaseClass::rfind(s); + 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.rfind_n(s, 2)); + Assert::AreEqual(found_pos, test_str.rfind_n(s, 2)); else - Assert::AreEqual(found_pos, test.substr(2).rfind_n(s, test.size() - 2)); + Assert::AreEqual(found_pos, test_str.substr(2).rfind_n(s, test_str.size() - 2)); - found_pos = test.substr(2, 5).MyBaseClass::rfind(s); + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(s); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind_n(s, 2, pcs::CppString::size_type(5))); + Assert::AreEqual(found_pos, test_str.rfind_n(s, 2, pcs::CppString::size_type(5))); else - Assert::AreEqual(found_pos, test.rfind_n(s, 2, pcs::CppString::size_type(5)) - 2); + 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.MyBaseClass::rfind(str), test.rfind_n(str, size_t(-1))); + Assert::AreEqual(test_str.MyBaseClass::rfind(str), test_str.rfind_n(str, size_t(-1))); - found_pos = test.substr(2).MyBaseClass::rfind(str); + found_pos = test_str.substr(2).MyBaseClass::rfind(str); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind_n(str, test.size() - 2)); + Assert::AreEqual(found_pos, test_str.rfind_n(str, test_str.size() - 2)); else - Assert::AreEqual(found_pos, test.substr(2).rfind_n(str, test.size() - 2)); + Assert::AreEqual(found_pos, test_str.substr(2).rfind_n(str, test_str.size() - 2)); - found_pos = test.substr(2, 5).MyBaseClass::rfind(str); + found_pos = test_str.substr(2, 5).MyBaseClass::rfind(str); if (found_pos == pcs::CppString::npos) - Assert::AreEqual(found_pos, test.rfind_n(str, 2, pcs::CppString::size_type(5))); + Assert::AreEqual(found_pos, test_str.rfind_n(str, 2, pcs::CppString::size_type(5))); else - Assert::AreEqual(found_pos, test.rfind_n(str, 2, pcs::CppString::size_type(5)) - 2); + Assert::AreEqual(found_pos, test_str.rfind_n(str, 2, pcs::CppString::size_type(5)) - 2); } } - Assert::AreEqual(size_t(14), test.rfind_n("A", 1, test.size() - 1)); - Assert::AreEqual(pcs::CppString::npos, test.rfind_n("A", 15, 1)); - Assert::AreEqual(size_t(0), test.rfind_n("", size_t(-1))); - Assert::AreEqual(size_t(27), test.rfind_n(".", 14, test.size() - 14)); - Assert::AreEqual(pcs::CppString::npos, test.rfind_n(".", 28, 1)); - Assert::AreEqual(size_t(27), test.rfind_n(".", 13, test.size() - 13)); + 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) { diff --git a/cpp-strings-tests/cpp-strings-tests.vcxproj b/cpp-strings-tests/cpp-strings-tests.vcxproj index 8665d37..eea3b08 100644 --- a/cpp-strings-tests/cpp-strings-tests.vcxproj +++ b/cpp-strings-tests/cpp-strings-tests.vcxproj @@ -89,17 +89,19 @@ - Use + NotUsing Level3 true $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings;%(AdditionalIncludeDirectories) _DEBUG;%(PreprocessorDefinitions) true - pch.h + + stdcpplatest - stdc17 + stdclatest true - true + false + Windows @@ -108,13 +110,19 @@ - Use + NotUsing Level3 true $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;%(PreprocessorDefinitions) true - pch.h + + + stdcpplatest + stdclatest + true + false + Windows @@ -123,7 +131,7 @@ - Use + NotUsing Level3 true true @@ -131,7 +139,13 @@ $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;%(PreprocessorDefinitions) true - pch.h + + + stdcpplatest + stdclatest + true + false + Windows @@ -142,7 +156,7 @@ - Use + NotUsing Level3 true true @@ -150,11 +164,13 @@ $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings;%(AdditionalIncludeDirectories) NDEBUG;%(PreprocessorDefinitions) true - pch.h + + stdcpplatest - stdc17 + stdclatest true - true + false + Windows @@ -165,15 +181,6 @@ - - Create - Create - Create - Create - - - - diff --git a/cpp-strings-tests/cpp-strings-tests.vcxproj.filters b/cpp-strings-tests/cpp-strings-tests.vcxproj.filters index 2a7903f..bcfea1c 100644 --- a/cpp-strings-tests/cpp-strings-tests.vcxproj.filters +++ b/cpp-strings-tests/cpp-strings-tests.vcxproj.filters @@ -18,13 +18,5 @@ Source Files - - Source Files - - - - - Header Files - \ No newline at end of file diff --git a/cpp-strings-tests/pch.cpp b/cpp-strings-tests/pch.cpp deleted file mode 100644 index f87cdfe..0000000 --- a/cpp-strings-tests/pch.cpp +++ /dev/null @@ -1,673 +0,0 @@ -// pch.cpp: source file corresponding to the pre-compiled header - -#include "pch.h" - -// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. - - -#include "cppstrings.h" -using namespace pcs; - -#include - -namespace cppstringstests -{ - - //===== PART 1 ============================================ - TEST_CLASS(cppstringstests_PART_1) - { - public: - - 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); - } - } - - TEST_METHOD(_cs) - { - using namespace pcs; - auto abcd = "abcD"cs; - auto wabcd = L"abcD"cs; - Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); - Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); - } - - TEST_METHOD(_csv) - { - using namespace pcs; - auto abcd = "abcD"csv; - auto wabcd = L"abcD"csv; - Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); - Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); - } - }; - - - //===== PART 2 ============================================ - TEST_CLASS(cppstringstests_PART_2) - { - public: - - TEST_METHOD(constructor_01) - { - 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) - { - CppString keys("abcdE"); - CppString values("ABCDe"); - pcs::CppString::TransTable t(keys, values); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString('D').c_str(), t['d'].c_str()); - Assert::AreEqual(CppString('e').c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abcdE"), CppWString(L"ABCDe")); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString(L'D').c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString(L'e').c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(constructor_03) - { - pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(constructor_04) - { - pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }); - Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }); - Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString(L'9').c_str(), wt[L'9'].c_str()); - } - - TEST_METHOD(constructor_05) - { - pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }, "dE"cs); - Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }, L"dE"cs); - Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'e').c_str(), wt[L'e'].c_str()); - } - - TEST_METHOD(constructor_06) - { - pcs::CppString::TransTable t("abC", "ABc"); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['c'].c_str()); - - pcs::CppWString::TransTable wt(L"abC", L"ABc"); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); - } - - TEST_METHOD(constructor_07) - { - pcs::CppString::TransTable t("abc", "ABC", "dE"); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('e').c_str(), t['e'].c_str()); - - pcs::CppWString::TransTable wt(L"abc", L"ABC", L"dE"); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); - Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); - Assert::AreEqual(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(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(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(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t(ct); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt(wct); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(constructor_move) - { - pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t(std::move(mt)); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt(std::move(wmt)); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(assign_copy) - { - pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t = ct; - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt = wct; - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(assign_move) - { - pcs::CppString::TransTable mt(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t = std::move(mt); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt = std::move(wmt); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(assign_map) - { - pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); - pcs::CppString::TransTable t = ct.get_table(); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - pcs::CppWString::TransTable wt = wct.get_table(); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); - } - - TEST_METHOD(indexing) - { - pcs::CppString::TransTable t(CppString("abc"), CppString("ABC"), CppString("dE")); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString(',').c_str(), t[','].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(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()); - } - - 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()); - } - - 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 ======================================== - - - -} \ No newline at end of file diff --git a/cpp-strings-tests/pch.h b/cpp-strings-tests/pch.h deleted file mode 100644 index 4417be9..0000000 --- a/cpp-strings-tests/pch.h +++ /dev/null @@ -1,16 +0,0 @@ -// pch.h: This is a precompiled header file. -// Files listed below are compiled only once, improving build performance for future builds. -// This also affects IntelliSense performance, including code completion and many code browsing features. -// However, files listed here are ALL re-compiled if any one of them is updated between builds. -// Do not add files here that you will be updating frequently as this negates the performance advantage. - -#ifndef PCH_H -#define PCH_H - -// add headers that you want to pre-compile here -#include "CppUnitTest.h" -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -#include - -#endif //PCH_H From 866069abd1815b1f7e62f04668d48acb1658e131 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 7 Jul 2025 20:29:06 +0200 Subject: [PATCH 091/137] #162-Test CppStringT::rindex() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 248 ++++++++++++++++++++++++ cpp-strings/cppstrings.h | 3 +- 2 files changed, 250 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d8a9bfa..acae230 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -1995,5 +1995,253 @@ namespace cppstringstests 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! */ } + + 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! */ } + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index d3f10cf..7ce6e9a 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1318,7 +1318,8 @@ namespace pcs // i.e. "pythonic c++ strings" { const size_type ret_value = rfind(sub, start, end); if (ret_value == CppStringT::npos) - throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); + throw NotFoundException("substring not found in string"); + //throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); else return ret_value; } From beafb017f84f1072d0c5794665ab79b4323179b1 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 7 Jul 2025 20:30:58 +0200 Subject: [PATCH 092/137] #163-Test CppStringT::rindex_n() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index acae230..b728725 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2166,7 +2166,7 @@ namespace cppstringstests 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'; + s = 'z'; try { const string_type::size_type pos = test_str.rindex_n(s, 20); Assert::IsTrue(pos != string_type::npos); From 8b5c5b96dceb279d20db1578eef32e61c2b1251a Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 7 Jul 2025 20:31:26 +0200 Subject: [PATCH 093/137] #163-Test CppStringT::rindex_n() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index b728725..acae230 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2166,7 +2166,7 @@ namespace cppstringstests 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'; + s = 'z'; try { const string_type::size_type pos = test_str.rindex_n(s, 20); Assert::IsTrue(pos != string_type::npos); From e3cf5e31d8da9215e5889cd840e2f6e516f253b6 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 7 Jul 2025 22:32:55 +0200 Subject: [PATCH 094/137] #164-Test CppStringT::rjust() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index acae230..9ceeb4f 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2243,5 +2243,32 @@ namespace cppstringstests 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()); + } + }; } From 37d0dc88bba1fa0cb01e127d44eff4a69a09b7dc Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 7 Jul 2025 22:40:29 +0200 Subject: [PATCH 095/137] #164-Test CppStringT::rjust() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 9ceeb4f..2528368 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2270,5 +2270,52 @@ namespace cppstringstests 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()); + + 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()); + } + }; } From 96f452c4d451c9dc12a46644692ea869196ce6df Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 7 Jul 2025 22:41:23 +0200 Subject: [PATCH 096/137] #165-Test CppStringT::rpartition() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 2528368..d4cb882 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2314,7 +2314,7 @@ namespace cppstringstests 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()); + Assert::AreEqual(L"", wres[2].c_str()); } }; From 10628163e98488d8160fae139e3b2ff61da90982 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 7 Jul 2025 22:41:41 +0200 Subject: [PATCH 097/137] #165-Test CppStringT::rpartition() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d4cb882..2528368 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2314,7 +2314,7 @@ namespace cppstringstests 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()); + Assert::AreEqual(L"", wres[2].c_str()); } }; From 80c328868ef76f7d79b421286466f900acddeacf Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 9 Jul 2025 10:32:25 +0200 Subject: [PATCH 098/137] #166-Test CppStringT::rsplit() with char and wchar_t Fixed a few bugs. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 447 ++++++++++++++++++++++++ cpp-strings/cppstrings.h | 103 ++---- 2 files changed, 469 insertions(+), 81 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 2528368..412a82f 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2317,5 +2317,452 @@ namespace cppstringstests 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 = " 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 = 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()); + } }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 7ce6e9a..2868fa8 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1410,95 +1410,37 @@ namespace pcs // i.e. "pythonic c++ strings" * separator, and the result will contain no empty strings at the * start or end if the string has leading or trailing whitespace. * Consequently, splitting an empty string or a string consisting - * of just whitespace with a whitespace separator returns an ampty + * of just whitespace with a whitespace separator returns an empty * vector. */ - inline std::vector rsplit() const noexcept + inline std::vector rsplit() noexcept { return split(); } /** \brief Returns a vector of the words in the whole string, using sep as the delimiter string. */ - inline std::vector rsplit(const CppStringT& sep) const noexcept + 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. */ - std::vector rsplit(const size_type maxsplit) const noexcept + inline std::vector rsplit(const size_type maxsplit) noexcept { - std::vector res{}; - - if (maxsplit == 0) { - res.push_back(*this); - } - else { - const CppStringT whitespace(value_type(' ')); - std::vector all_words{ this->split(whitespace) }; - - size_type count = maxsplit; - auto word_it = all_words.crbegin(); - size_type last_split_index = all_words.size(); - while (count > 0 && word_it != all_words.crend()) { - if (!word_it->empty()) { - res.insert(res.cbegin(), *word_it); - --count; - --last_split_index; - } - word_it++; - } - - size_type chars_count = last_split_index; - while (last_split_index > 0) { - chars_count += all_words[last_split_index].size(); - --last_split_index; - } - if (chars_count > 0) - res.insert(res.cbegin(), this->substr(0, chars_count)); - /* - constexpr CppStringT spc2(" "); - constexpr CppStringT spc(value_type(' ')); - CppStringT tmp = *this; - while (tmp.contains(spc2)) - tmp = tmp.replace(spc2, spc); - - res = tmp->rsplit(spc, maxsplit); - */ - } - - return res; + 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. */ - std::vector rsplit(const CppStringT& sep, const size_type maxsplit) const noexcept + std::vector rsplit(const CppStringT& sep, const size_type maxsplit) noexcept { + const size_type sep_size{ sep.size() }; std::vector res{}; if (maxsplit == 0) { res.push_back({ *this }); } else { - std::vector all_words{ this->split(sep) }; - - size_type count = maxsplit; - auto word_it = all_words.crbegin(); - size_type last_split_index = all_words.size(); - while (count > 0 && word_it != all_words.crend()) { - res.insert(res.cbegin(), *word_it); - --count; - --last_split_index; - word_it++; - } - - size_type chars_count = last_split_index; - while (last_split_index > 0) { - chars_count += all_words[last_split_index].size(); - --last_split_index; - } - if (chars_count > 0) - res.insert(res.cbegin(), this->substr(0, chars_count)); - /* - std::vector indexes{}; + std::vector indexes{}; CppStringT tmp = *this; size_type count = maxsplit; size_type index; @@ -1506,7 +1448,7 @@ namespace pcs // i.e. "pythonic c++ strings" indexes.insert(indexes.begin(), index); if (index == 0) break; - tmp = tmp.substr(0, index-1); + tmp = tmp.substr(0, index); count--; } @@ -1514,12 +1456,12 @@ namespace pcs // i.e. "pythonic c++ strings" res.push_back(*this); else { index = 0; - for (const size_type ndx: indexes) { + for (const size_type ndx : indexes) { res.push_back(this->substr(index, ndx - index)); - index = ndx + 1; + index = ndx + sep_size; + } } - res.push_back(this->substr(index, this->size() - index)); - */ + res.push_back(this->substr(index/* + sep_size - 1*/, this->size() - index)); } return res; @@ -1534,10 +1476,10 @@ namespace pcs // i.e. "pythonic c++ strings" * its values are stripped. * To remove a suffix, rather call method 'removesuffix()'. */ - inline CppStringT rstrip(const CppStringT& prefix) const noexcept + inline CppStringT rstrip(const CppStringT& suffix) const noexcept { for (auto it = this->crbegin(); it != this->crend(); ++it) - if (std::none_of(prefix.cbegin(), prefix.cend(), [it](const value_type ch) { *it == ch; })) + if (std::none_of(suffix.cbegin(), suffix.cend(), [it](const value_type ch) { return *it == ch; })) return CppStringT(this->cbegin(), it); return CppStringT(); } @@ -1562,13 +1504,12 @@ namespace pcs // i.e. "pythonic c++ strings" * of just whitespace with a whitespace separator returns an ampty * vector. */ - inline std::vector split() const noexcept + inline std::vector split() noexcept { - std::vector res; - constexpr CppStringT whitespace(value_type(' ')); + std::vector res; + const CppStringT whitespace(value_type(' ')); for (const auto& word : *this | std::views::split(whitespace)) - if (!word.empty()) - res.push_back(CppStringT(word.begin(), word.end())); + res.push_back(CppStringT(word.begin(), word.end())); return res; } @@ -1581,7 +1522,7 @@ namespace pcs // i.e. "pythonic c++ strings" * "3"]). Splitting an empty string with a specified separator * returns {""}. */ - inline std::vector split(const CppStringT& sep) const noexcept + inline std::vector split(const CppStringT& sep) noexcept { std::vector res; for (const auto& word : *this | std::views::split(sep)) @@ -1590,7 +1531,7 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \brief 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 split(const size_type maxsplit) const noexcept + std::vector split(const size_type maxsplit) noexcept { std::vector res{}; @@ -1623,7 +1564,7 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \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. */ - std::vector split(const CppStringT& sep, const size_type maxsplit) const noexcept + std::vector split(const CppStringT& sep, const size_type maxsplit) noexcept { std::vector res{}; From 19d96880199d96e0e05ae954ff4d812063e61df3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 9 Jul 2025 10:45:25 +0200 Subject: [PATCH 099/137] #166-Test CppStringT::rsplit() with char and wchar_t Fixed erroneous doxygen string. Added related tests. --- cpp-strings-tests/cpp-strings-tests.cpp | 21 +++++++++++++++++++++ cpp-strings/cppstrings.h | 8 ++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 412a82f..4dfbdbb 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2427,6 +2427,17 @@ namespace cppstringstests 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()); + + s = " abcd#123efg#123hij #123#123klmn "cs; res = s.rsplit("#123"); Assert::AreEqual(pcs::CppString::size_type(5), res.size()); @@ -2650,6 +2661,16 @@ namespace cppstringstests 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()); diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 2868fa8..f84e0b8 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1406,12 +1406,8 @@ namespace pcs // i.e. "pythonic c++ strings" //--- rsplit() ---------------------------------------- /** \brief Returns a vector of the words in the whole string, as seperated with whitespace strings. * - * Notice: runs of consecutive whitespace are regarded as a single - * separator, and the result will contain no empty strings at the - * start or end if the string has leading or trailing whitespace. - * Consequently, splitting an empty string or a string consisting - * of just whitespace with a whitespace separator returns an empty - * vector. + * Notice: consecutive whitespaces are each regarded as a + * single separator. So, they each separate empty strings. */ inline std::vector rsplit() noexcept { From f1f476be523ba20ad8ad120b689bf9d7663f9dc1 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 9 Jul 2025 12:20:56 +0200 Subject: [PATCH 100/137] #167-Test CppStringT::rstrip() with char and wchar_t Fixed one bug. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 60 +++++++++++++++++++++++++ cpp-strings/cppstrings.h | 4 +- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 4dfbdbb..5618273 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2785,5 +2785,65 @@ namespace cppstringstests 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()); + + 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#124#124#124"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#124#124#124#124"; + 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()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index f84e0b8..7df4f34 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1476,7 +1476,7 @@ namespace pcs // i.e. "pythonic c++ strings" { for (auto it = this->crbegin(); it != this->crend(); ++it) if (std::none_of(suffix.cbegin(), suffix.cend(), [it](const value_type ch) { return *it == ch; })) - return CppStringT(this->cbegin(), it); + return CppStringT(this->cbegin(), this->cbegin() + this->size() - (it - this->crbegin())); return CppStringT(); } @@ -1485,7 +1485,7 @@ namespace pcs // i.e. "pythonic c++ strings" { for (auto it = this->crbegin(); it != this->crend(); ++it) if (*it != value_type(' ')) - return CppStringT(this->cbegin(), it); + return CppStringT(this->cbegin(), this->cbegin() + this->size() - (it - this->crbegin())); return CppStringT(); } From c892008ca76304d78646a2f52dff68647d27d41f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 9 Jul 2025 14:35:11 +0200 Subject: [PATCH 101/137] #168-Test CppStringT::split() with char and wchar_t Fixed one bug. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 467 ++++++++++++++++++++++++ cpp-strings/cppstrings.h | 75 ++-- 2 files changed, 502 insertions(+), 40 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 5618273..50a9405 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2845,5 +2845,472 @@ namespace cppstringstests 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()); + + + 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()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 7df4f34..bfe0d1b 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1429,17 +1429,18 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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. */ std::vector rsplit(const CppStringT& sep, const size_type maxsplit) noexcept { - const size_type sep_size{ sep.size() }; std::vector res{}; if (maxsplit == 0) { res.push_back({ *this }); } else { + const size_type sep_size{ sep.size() }; std::vector indexes{}; - CppStringT tmp = *this; - size_type count = maxsplit; - size_type index; + 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) @@ -1457,7 +1458,7 @@ namespace pcs // i.e. "pythonic c++ strings" index = ndx + sep_size; } } - res.push_back(this->substr(index/* + sep_size - 1*/, this->size() - index)); + res.push_back(this->substr(index, this->size() - index)); } return res; @@ -1493,12 +1494,8 @@ namespace pcs // i.e. "pythonic c++ strings" //--- split() ----------------------------------------- /** \brief Returns a vector of the words in the whole string, as seperated with whitespace strings. * - * Notice: runs of consecutive whitespace are regarded as a single - * separator, and the result will contain no empty strings at the - * start or end if the string has leading or trailing whitespace. - * Consequently, splitting an empty string or a string consisting - * of just whitespace with a whitespace separator returns an ampty - * vector. + * Notice: consecutive whitespaces are each regarded as a + * single separator. So, they each separate empty strings. */ inline std::vector split() noexcept { @@ -1527,36 +1524,9 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \brief 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 split(const size_type maxsplit) noexcept + inline std::vector split(const size_type maxsplit) noexcept { - std::vector res{}; - - if (maxsplit == 0) { - res.push_back(*this); - } - else { - const CppStringT whitespace(value_type(' ')); - std::vector all_words{ this->split(whitespace) }; - - size_type count = maxsplit; - auto word_it = all_words.cbegin(); - while (count > 0 && word_it != all_words.cend()) { - if (!word_it->empty()) { - res.insert(res.cbegin(), *word_it); - --count; - } - word_it++; - } - - size_type chars_count = 0; - for (auto it = word_it; it != all_words.cend(); ++it) { - chars_count += it->size() + 1; - } - if (chars_count > 0) - res.insert(res.cbegin(), this->substr(this->cbegin() + chars_count - 1, this->cend())); - } - - return res; + 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. */ @@ -1568,6 +1538,30 @@ namespace pcs // i.e. "pythonic c++ strings" res.push_back(*this); } else { + 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)); + /** / const CppStringT whitespace(value_type(' ')); std::vector all_words{ this->split(sep) }; @@ -1585,6 +1579,7 @@ namespace pcs // i.e. "pythonic c++ strings" } if (chars_count > 0) res.insert(res.cbegin(), this->substr(this->cbegin() + chars_count - 1, this->cend())); + /**/ } return res; From 90d839784e99420a7d14c6fa3211982cb6a1eac5 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 10 Jul 2025 12:38:07 +0200 Subject: [PATCH 102/137] #169-Test CppStringT::splitlines() with char and wchar_t Completed. Validated Led to a simplification - makes a difference with Python default behavior with Unicode chars. --- .gitignore | 5 + cpp-strings-tests/cpp-strings-tests.cpp | 255 ++++++++++++++++++++---- cpp-strings/cppstrings.h | 50 ++--- 3 files changed, 240 insertions(+), 70 deletions(-) diff --git a/.gitignore b/.gitignore index 0455c1a..478a1b5 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,8 @@ # Visual Studio specifics .vs x64 +Debug +Release + +# CppStrings specifics +archive diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 50a9405..5fe9a95 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -701,53 +701,53 @@ namespace cppstringstests TEST_METHOD(count) { pcs::CppString s("abcabcabcdefabca bca bcabca"); - Assert::AreEqual(3ULL, s.count("abca")); - Assert::AreEqual(6ULL, s.count("bca")); - Assert::AreEqual(0ULL, s.count("A")); - Assert::AreEqual(2ULL, s.count("abca", 4)); - Assert::AreEqual(5ULL, s.count("bca", 2)); - Assert::AreEqual(0ULL, s.count("A", 3)); - Assert::AreEqual(1ULL, s.count("abca", 4, s.size() - 5)); - Assert::AreEqual(4ULL, s.count("bca", 2, s.size() - 2)); - Assert::AreEqual(0ULL, s.count("A", 3, s.size() + 4)); + 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(3ULL, ws.count(L"abca")); - Assert::AreEqual(6ULL, ws.count(L"bca")); - Assert::AreEqual(0ULL, ws.count(L"A")); - Assert::AreEqual(2ULL, ws.count(L"abca", 4)); - Assert::AreEqual(5ULL, ws.count(L"bca", 2)); - Assert::AreEqual(0ULL, ws.count(L"A", 3)); - Assert::AreEqual(1ULL, ws.count(L"abca", 4, s.size() - 5)); - Assert::AreEqual(4ULL, ws.count(L"bca", 2, s.size() - 2)); - Assert::AreEqual(0ULL, ws.count(L"A", 3, s.size() + 4)); + 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(3ULL, s.count_n("abca", 0, len)); - Assert::AreEqual(6ULL, s.count_n("bca", 0, len)); - Assert::AreEqual(0ULL, s.count_n("A", 0, len)); - Assert::AreEqual(2ULL, s.count_n("abca", 4, len - 4)); - Assert::AreEqual(5ULL, s.count_n("bca", 2, len - 2)); - Assert::AreEqual(0ULL, s.count_n("A", 3, len - 3)); - Assert::AreEqual(1ULL, s.count_n("abca", 4, len - 5)); - Assert::AreEqual(4ULL, s.count_n("bca", 2, len - 3)); - Assert::AreEqual(0ULL, s.count_n("A", 3, len + 4)); + 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(3ULL, ws.count_n(L"abca", 0, wlen)); - Assert::AreEqual(6ULL, ws.count_n(L"bca", 0, wlen)); - Assert::AreEqual(0ULL, ws.count_n(L"A", 0, wlen)); - Assert::AreEqual(2ULL, ws.count_n(L"abca", 4, wlen - 4)); - Assert::AreEqual(5ULL, ws.count_n(L"bca", 2, wlen - 2)); - Assert::AreEqual(0ULL, ws.count_n(L"A", 3, wlen - 3)); - Assert::AreEqual(1ULL, ws.count_n(L"abca", 4, wlen - 5)); - Assert::AreEqual(4ULL, ws.count_n(L"bca", 2, wlen - 3)); - Assert::AreEqual(0ULL, ws.count_n(L"A", 3, wlen + 4)); + 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) @@ -3312,5 +3312,188 @@ namespace cppstringstests 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 + { + CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r" }; + std::vector lines{ text.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()); + } + + { + CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r\n" }; + std::vector lines{ text.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()); + } + + { + CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\n\r" }; + std::vector lines{ text.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()); + } + + { + CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r" }; + std::vector lines{ text.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()); + } + + { + CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r\n" }; + std::vector lines{ text.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()); + } + + { + CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\n\r" }; + std::vector lines{ text.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()); + } + + + { + 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()); + } + + { + 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()); + } + + { + 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()); + } + + { + 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()); + } + + { + 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()); + } + + { + 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) + + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index bfe0d1b..eb15ba5 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1561,25 +1561,6 @@ namespace pcs // i.e. "pythonic c++ strings" } } res.push_back(this->substr(index, this->size() - index)); - /** / - const CppStringT whitespace(value_type(' ')); - std::vector all_words{ this->split(sep) }; - - size_type count = maxsplit; - auto word_it = all_words.cbegin(); - while (count > 0 && word_it != all_words.cend()) { - res.insert(res.cbegin(), *word_it); - --count; - word_it++; - } - - size_type chars_count = 0; - for (auto it = word_it; it != all_words.cend(); ++it) { - chars_count += it->size() + 1; - } - if (chars_count > 0) - res.insert(res.cbegin(), this->substr(this->cbegin() + chars_count - 1, this->cend())); - /**/ } return res; @@ -1600,6 +1581,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \x1c File Separator * \x1d Group Separator * \x1e Record Separator + * Next separators values, detected by Python method splitlines(), are NOT detected with CppStrings * \x85 Next Line (C1 Control Code) * \u2028 Line Separator * \u2029 Paragraph Separator @@ -1610,21 +1592,16 @@ namespace pcs // i.e. "pythonic c++ strings" CppStringT current{}; bool prev_cr = false; - for (const value_type& ch : *this) { + for (const value_type ch : *this) { switch (ch) { - case value_type('\v'): // Line Tabulation - case value_type('\x0b'): // Line Tabulation - case value_type('\f'): // Form Feed - case value_type('\x0c'): // Form Feed - case value_type('\x1c'): // File Separator - case value_type('\x1d'): // Group Separator - case value_type('\x1e'): // Record Separator - case value_type('\x85'): // Next Line (C1 Control Code) -#pragma warning(push) -#pragma warning(disable: 4566) // to get no warning when current page code is not compatible with next unicode points - case value_type('\u2028'): // Line Separator - case value_type('\u2029'): // Paragraph Separator -#pragma warning(pop) + case 0x0b: // Line Tabulation, \v as well as \x0b and \013 + case 0x0c: // Form Feed, \f as well as \x0c and \014 + case 0x1c: // File Separator, or \034 + case 0x1d: // Group Separator, or \035 + case 0x1e: // Record Separator, or \036 + //case L'\u0085': // Next Line (C1 Control Code), or \0205 + //case L'\u2028': // Line Separator + //case L'\u2029': // Paragraph Separator if (prev_cr) { res.push_back(current); current.clear(); @@ -1646,7 +1623,7 @@ namespace pcs // i.e. "pythonic c++ strings" prev_cr = true; break; - case value_type('\n'): // Line Feed + case value_type('\n'): // Carriage return if (keep_end) current += ch; res.push_back(current); @@ -1659,12 +1636,17 @@ namespace pcs // i.e. "pythonic c++ strings" if (prev_cr) { res.push_back(current); current.clear(); + prev_cr = false; } current += ch; break; } } + if (prev_cr) { + res.push_back(current); + } + return res; } From 446cb8ee0322e0877dd9ac9c234f77a5c58bd712 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 10 Jul 2025 12:39:37 +0200 Subject: [PATCH 103/137] #200-modify .ignore and VS projects to compile and test 32-bits platforms Done. --- cpp-strings-tests/cpp-strings-tests.vcxproj | 8 ++++---- cpp-strings/cpp-strings.vcxproj | 8 ++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.vcxproj b/cpp-strings-tests/cpp-strings-tests.vcxproj index eea3b08..089d18e 100644 --- a/cpp-strings-tests/cpp-strings-tests.vcxproj +++ b/cpp-strings-tests/cpp-strings-tests.vcxproj @@ -92,7 +92,7 @@ NotUsing Level3 true - $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings;%(AdditionalIncludeDirectories) + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings _DEBUG;%(PreprocessorDefinitions) true @@ -113,7 +113,7 @@ NotUsing Level3 true - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings WIN32;_DEBUG;%(PreprocessorDefinitions) true @@ -136,7 +136,7 @@ true true true - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings WIN32;NDEBUG;%(PreprocessorDefinitions) true @@ -161,7 +161,7 @@ true true true - $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings;%(AdditionalIncludeDirectories) + $(VCInstallDir)UnitTest\include;$(ProjectDir)..\cpp-strings NDEBUG;%(PreprocessorDefinitions) true diff --git a/cpp-strings/cpp-strings.vcxproj b/cpp-strings/cpp-strings.vcxproj index add61c9..2e1cdf3 100644 --- a/cpp-strings/cpp-strings.vcxproj +++ b/cpp-strings/cpp-strings.vcxproj @@ -76,6 +76,8 @@ true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpplatest + stdclatest Console @@ -90,6 +92,8 @@ true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpplatest + stdclatest Console @@ -105,7 +109,7 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpplatest - stdc17 + stdclatest true true @@ -123,7 +127,7 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpplatest - stdc17 + stdclatest true true From a11502e8bc75fc05db70e9f558c9ef1cfe858c6b Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 10 Jul 2025 17:39:45 +0200 Subject: [PATCH 104/137] #170-Test CppStringT::startswith() with char and wchar_t Completed. Validated. Led to the fixing of code. --- cpp-strings-tests/cpp-strings-tests.cpp | 145 ++++++++++++++++++++++-- cpp-strings/cppstrings.h | 43 +++---- 2 files changed, 155 insertions(+), 33 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 5fe9a95..a75a9cc 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -3317,8 +3317,8 @@ namespace cppstringstests #pragma warning(push) #pragma warning(disable: 4566) // to get no warning when current page code is not compatible with next unicode points { - CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r" }; - std::vector lines{ text.splitlines() }; + 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() }; @@ -3330,8 +3330,8 @@ namespace cppstringstests } { - CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r\n" }; - std::vector lines{ text.splitlines() }; + 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() }; @@ -3343,8 +3343,8 @@ namespace cppstringstests } { - CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\n\r" }; - std::vector lines{ text.splitlines() }; + 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() }; @@ -3356,8 +3356,8 @@ namespace cppstringstests } { - CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r" }; - std::vector lines{ text.splitlines(true) }; + 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" @@ -3372,8 +3372,8 @@ namespace cppstringstests } { - CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\r\n" }; - std::vector lines{ text.splitlines(true) }; + 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" @@ -3388,8 +3388,8 @@ namespace cppstringstests } { - CppString text{ "\vabc\013cde\fefg\x0cghi\x1cijk\x1dklm\x1dmno\r\n\nopq\rqrs\vstu\ruvw\nwxy\r\nzzz\x0c.\n\r" }; - std::vector lines{ text.splitlines(true) }; + 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" @@ -3495,5 +3495,126 @@ namespace cppstringstests } + TEST_METHOD(startswith) + { + 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)); + + + 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)); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index eb15ba5..aaba9cc 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1652,39 +1652,39 @@ namespace pcs // i.e. "pythonic c++ strings" //--- startswith() ------------------------------------ - /** Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at start position and stops at end position. */ - inline const bool startswith(const CppStringT& suffix, 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. */ + inline const bool startswith(const CppStringT& prefix, const size_type start, const size_type end) const noexcept { - return startswith(std::span{ suffix }, start, end); + return this->substr(start, end - start + 1).MyBaseClass::starts_with(prefix); } - /** Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at start position and stops at end of string. */ - inline const bool startswith(const CppStringT& suffix, 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. */ + inline const bool startswith(const CppStringT& prefix, const size_type start) const noexcept { - return startswith(std::span{ suffix }, start, this->size() - 1); + return startswith(prefix, start, this->size() - 1); } - /** Returns true if the string starts with the specified suffix, otherwise returns false. Test runs on the whole string. */ - inline const bool startswith(const CppStringT& suffix) const noexcept + /** Returns true if the string starts with the specified prefix, otherwise returns false. Test runs on the whole string. */ + inline const bool startswith(const CppStringT& prefix) const noexcept { - return this->starts_with(suffix); + return this->starts_with(prefix); } - /** Returns true if the string starts with any of the specified suffixes, otherwise returns false. Test begins at start position and stops at end of string. */ - inline const bool startswith(const std::span& suffixes, 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. */ + inline const bool startswith(const std::initializer_list& prefixes, const size_type start, const size_type end) const noexcept { if (start > end) return false; - else - return std::any_of(suffixes.cbegin(), suffixes.cend(), this->substr(start, end).starts_with); - /* - for (auto& suffix : suffixes) { - if (this->substr(start, end).starts_with(suffix)) + + CppStringT tmp(this->substr(start, end)); + for (auto& prefix : prefixes) { + if (tmp.starts_with(prefix)) return true; } - return false; - */ + + //else + // return std::any_of(prefixes.cbegin(), prefixes.cend(), this->substr(start, end).starts_with); } @@ -1692,7 +1692,8 @@ namespace pcs // i.e. "pythonic c++ strings" /** Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions. */ inline const bool startswith_n(const CppStringT& suffix, const size_type start, const size_type count) const noexcept { - return startswith(std::span{ suffix }, start, start + count - 1); + //return startswith(std::span{ suffix }, start, start + count - 1); + return startswith(std::initializer_list(suffix), start, start + count - 1); } /** Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions. */ @@ -1732,8 +1733,8 @@ namespace pcs // i.e. "pythonic c++ strings" inline CppStringT substr(const size_type start, const size_type count=-1) const noexcept { if (start > this->size()) - return *this; - const size_type width = std::min(count, this->size() - start + 1); + return CppStringT(); + const size_type width{ std::min(count, this->size() - start + 1) }; return CppStringT(MyBaseClass::substr(start, width)); } From 9005fb08dfb6c69527127ac958798e48e394cb90 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 10 Jul 2025 18:49:54 +0200 Subject: [PATCH 105/137] #171-Test CppStringT::startswith_n() with char and wchar_t Completed. Validated. Led to simplification of code. --- cpp-strings-tests/cpp-strings-tests.cpp | 121 ++++++++++++++++++++++++ cpp-strings/cppstrings.h | 13 ++- 2 files changed, 127 insertions(+), 7 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index a75a9cc..d183119 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -3616,5 +3616,126 @@ namespace cppstringstests Assert::IsFalse(wtext.startswith({ L"def", L"ghi", L"Abcd" }, 0, len - 4)); } + TEST_METHOD(startswith_n) + { + 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)); + + + 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)); + } }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index aaba9cc..f142821 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1690,22 +1690,21 @@ namespace pcs // i.e. "pythonic c++ strings" //--- startswith_n() ---------------------------------- /** Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions. */ - inline const bool startswith_n(const CppStringT& suffix, const size_type start, const size_type count) const noexcept + inline const bool startswith_n(const CppStringT& prefix, const size_type start, const size_type count) const noexcept { - //return startswith(std::span{ suffix }, start, start + count - 1); - return startswith(std::initializer_list(suffix), start, start + count - 1); + return this->substr(start, count).MyBaseClass::starts_with(prefix); } /** Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions. */ - inline const bool startswith_n(const CppStringT& suffix, const size_type count) const noexcept + inline const bool startswith_n(const CppStringT& prefix, const size_type count) const noexcept { - return startswith(std::span{ suffix }, 0, count - 1); + return this->substr(0, count).MyBaseClass::starts_with(prefix); } /** 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. */ - inline const bool startswith_n(const std::span& suffixes, const size_type start, const size_type count) const noexcept + inline const bool startswith_n(const std::initializer_list& prefix, const size_type start, const size_type count) const noexcept { - return startswith(suffixes, start, start + count - 1); + return startswith(prefix, start, count); } From 6575060a4baf111653408e17d430809f5bf28227 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 10 Jul 2025 22:52:35 +0200 Subject: [PATCH 106/137] #172-Test CppStringT::strip() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 31 +++++++++++++++++++++++-- cpp-strings/cppstrings.h | 12 +++++----- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d183119..2f888b8 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2804,7 +2804,7 @@ namespace cppstringstests sres = s.rstrip(); Assert::AreEqual("", sres.c_str()); - s = "#124abcd#124efg#124#124#124"cs; + s = "#124abcd#124efg#1241#24#142"cs; sres = s.rstrip("#124"); Assert::AreEqual("#124abcd#124efg", sres.c_str()); @@ -2812,7 +2812,7 @@ namespace cppstringstests sres = s.rstrip("#124"); Assert::AreEqual("#124abcd#124efg#124#124hij", sres.c_str()); - s = "#124#124#124#124#124"; + s = "#124#142#241124#421#"; sres = s.rstrip("#124"); Assert::AreEqual("", sres.c_str()); @@ -3737,5 +3737,32 @@ namespace cppstringstests 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) + { + 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()); + + 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()); + } }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index f142821..1eec8b4 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1122,10 +1122,10 @@ namespace pcs // i.e. "pythonic c++ strings" * its values are stripped. * To remove a prefix, rather call method 'removeprefix()'. */ - inline CppStringT lstrip(const CppStringT& prefix) const noexcept + inline CppStringT lstrip(const CppStringT& removedchars) const noexcept { for (auto it = this->cbegin(); it != this->cend(); ++it) - if (std::none_of(prefix.cbegin(), prefix.cend(), [it](const value_type ch) { return *it == ch; })) + if (std::none_of(removedchars.cbegin(), removedchars.cend(), [it](const value_type ch) { return *it == ch; })) return CppStringT(it, this->cend()); return CppStringT(); } @@ -1473,10 +1473,10 @@ namespace pcs // i.e. "pythonic c++ strings" * its values are stripped. * To remove a suffix, rather call method 'removesuffix()'. */ - inline CppStringT rstrip(const CppStringT& suffix) const noexcept + inline CppStringT rstrip(const CppStringT& removedchars) const noexcept { for (auto it = this->crbegin(); it != this->crend(); ++it) - if (std::none_of(suffix.cbegin(), suffix.cend(), [it](const value_type ch) { return *it == ch; })) + 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(); } @@ -1715,9 +1715,9 @@ namespace pcs // i.e. "pythonic c++ strings" * The chars argument is not a prefix; rather, all combinations of * its values are stripped. */ - inline CppStringT strip(const CppStringT& prefix) const noexcept + inline CppStringT strip(const CppStringT& removedchars) const noexcept { - return this->rstrip(prefix).lstrip(prefix); + return this->rstrip(removedchars).lstrip(removedchars); } /** \brief Returns a copy of the string with the leading and trailing whitespaces removed. */ From 41860e7e5762681c01ceedf09e9a6d03d8e907cb Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 10 Jul 2025 23:08:17 +0200 Subject: [PATCH 107/137] #173-Test CppStringT::substr() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 79 +++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 2f888b8..e5249c9 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -3764,5 +3764,84 @@ namespace cppstringstests Assert::AreEqual(L"abcdefedcbaea", wtext.strip(L"ghijZ").c_str()); Assert::AreEqual(L"abcdefedcbaea", wtext.strip(L"ABc").c_str()); } + + TEST_METHOD(substr) + { + 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()); + + 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()); + } }; } From ce29faf83b4c34fef5a159bcf5dc69822d8e33a0 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 07:38:48 +0200 Subject: [PATCH 108/137] #174-Test CppStringT::swapcase() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 30 +++++++++++++++++++++++++ cpp-strings/cppstrings.h | 7 +----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index e5249c9..53c2032 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -3843,5 +3843,35 @@ namespace cppstringstests Assert::AreEqual(L"", wtext.substr(10, 15).c_str()); Assert::AreEqual(L"", wtext.substr(21).c_str()); } + + TEST_METHOD(swapcase) + { + CppString s(255, '\0'); + for (int i : std::views::iota(0, 256)) + s[i] = CppString::value_type(i); + 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); + } + + CppWString ws(0xffff, '\0'); + for (int i : std::views::iota(0, 0x1'0000)) + ws[i] = CppWString::value_type(i); + 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); + } + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 1eec8b4..fd6c98b 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1745,13 +1745,8 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline CppStringT swapcase() const noexcept { - /* - CppStringT res(*this); - std::transform(this->cbegin(), this->cend(), res.begin(), pcs::swap_case); - return res; - */ CppStringT res; - std::ranges::copy(std::views::transform(*this, pcs::swap_case), std::back_inserter(res)); + std::ranges::transform(*this, std::back_inserter(res), [](const value_type c) -> value_type { return pcs::swap_case(c); }); return res; } From 52404a8ce30b81888b98de3aa4c7c10d8512575a Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 07:49:46 +0200 Subject: [PATCH 109/137] #175-Test CppStringT::title() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 53c2032..d1a9f17 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -3873,5 +3873,18 @@ namespace cppstringstests } } + TEST_METHOD(title) + { + CppString text("to bE TiTlEd - cheCKing,errors, in Case oF aNy fOUNd"); + CppString expected("To Be Titled - Checking,errors, In Case Of Any Found"); + CppString res{ text.title() }; + Assert::AreEqual(expected.c_str(), res.c_str()); + + CppWString wtext(L"to bE TiTlEd - cheCKing,errors, in Case oF aNy fOUNd\u2026\x86"); + CppWString wexpected(L"To Be Titled - Checking,errors, In Case Of Any Found\u2026\x86"); + CppWString wres{ wtext.title() }; + Assert::AreEqual(wexpected.c_str(), wres.c_str()); + + } }; } From f95e30f561fd1b76ea8184ff5302591a3da442f3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 08:45:51 +0200 Subject: [PATCH 110/137] #176-Test CppStringT::translate() with char and wchar_t Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 14 ++++++++++++++ cpp-strings/cppstrings.h | 20 ++++++-------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d1a9f17..d6f7a41 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -3886,5 +3886,19 @@ namespace cppstringstests Assert::AreEqual(wexpected.c_str(), wres.c_str()); } + + TEST_METHOD(translate) + { + CppString::TransTable trans_table("oizeaslbgOIZEASLG", "012345789012345789"); + CppString text("This is a big 'Oiseau' that can be seen in 'Le Zoo'"); + 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()); + + CppWString::TransTable wtrans_table(L"oizeaslbgOIZEASLG", L"012345789012345789"); + CppWString wtext(L"This is a big 'Oiseau' that can be seen in 'Le Zoo'"); + 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()); + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index fd6c98b..e474ca6 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -348,14 +348,15 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \brief Indexing operator. */ - inline CppStringT operator[] (const key_type ch) noexcept + inline value_type operator[] (const key_type ch) noexcept + //inline CppStringT operator[] (const key_type ch) noexcept { auto it = m_table.find(ch); if (it != m_table.end()) { return it->second; } else { - return CppStringT(ch); + return ch; // CppStringT(ch); } } @@ -366,7 +367,8 @@ namespace pcs // i.e. "pythonic c++ strings" private: std::map m_table{}; // the internal storage of the translation table. Access it via the indexing operator. - }; + +}; //=== Constructors / Destructor ======================= @@ -1774,24 +1776,14 @@ namespace pcs // i.e. "pythonic c++ strings" * to be translated is not available as an entry in the tranlation * table, it is set as is in the resulting string. */ - CppStringT translate(const TransTable& table) const noexcept + CppStringT translate(TransTable& table) noexcept { - /* CppStringT res{}; for (auto ch : *this) { try { res += table[ch]; } catch (...) { res += ch; } } return res; - */ - - CppStringT res{}; - auto _translate = [&](auto const ch) { - try { return table[ch]; } - catch (...) { return ch; } - }; - std::ranges::copy(std::views::transform(*this, _translate), std::back_inserter(res)); - return res; } From aa60e6aeee1018bc2eb4a61dab1d3f304d2df6e2 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 09:05:47 +0200 Subject: [PATCH 111/137] #177-Test CppStringT::upper() with char and wchar_t Completed. Validated. Expanded tests of `lower()`as well. --- cpp-strings-tests/cpp-strings-tests.cpp | 77 +++++++++++++++++++++++++ cpp-strings/cppstrings.h | 7 +-- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index d6f7a41..a37839d 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -1622,6 +1622,33 @@ namespace cppstringstests Assert::AreEqual(pcs::to_lower(wch), ws[i]); Assert::AreEqual(wchar_t(std::tolower(wch)), pcs::CppWString::lower(wch)); } + + CppString s(255, '\0'); + for (int i : std::views::iota(0, 256)) + s[i] = CppString::value_type(i); + 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); + } + + CppWString ws(0xffff, '\0'); + for (int i : std::views::iota(0, 0x1'0000)) + ws[i] = CppWString::value_type(i); + 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) @@ -3900,5 +3927,55 @@ namespace cppstringstests 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)); + } + + CppString s(255, '\0'); + for (int i : std::views::iota(0, 256)) + s[i] = CppString::value_type(i); + 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); + } + + CppWString ws(0xffff, '\0'); + for (int i : std::views::iota(0, 0x1'0000)) + ws[i] = CppWString::value_type(i); + 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); + } + + } + }; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index e474ca6..9ab402e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1795,10 +1795,9 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline CppStringT& upper() noexcept { - std::transform(this->begin(), this->end(), - this->begin(), - [](value_type ch) { return this->upper(ch); }); - return *this; + 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. From e3ff5cea46419249381958960064bb768b12aa0e Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 09:27:07 +0200 Subject: [PATCH 112/137] #178-Test CppStringT::zfill() with char and wchar_t Completed. Validated. Notice: fixed erroneous implementation ad erroneous testing of ljust() and rjust()! --- cpp-strings-tests/cpp-strings-tests.cpp | 114 ++++++++++++++++++++---- cpp-strings/cppstrings.h | 8 +- 2 files changed, 102 insertions(+), 20 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index a37839d..07399c3 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -1580,25 +1580,25 @@ namespace cppstringstests 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(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()); + 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(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()); + Assert::AreEqual(L".abc", ws.ljust(4, '.').c_str()); + Assert::AreEqual(L"..abc", ws.ljust(5, '.').c_str()); } TEST_METHOD(lower) @@ -2276,25 +2276,25 @@ namespace cppstringstests 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(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()); + 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(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()); + Assert::AreEqual(L"abc.", ws.rjust(4, '.').c_str()); + Assert::AreEqual(L"abc..", ws.rjust(5, '.').c_str()); } TEST_METHOD(rpartition) @@ -3977,5 +3977,87 @@ namespace cppstringstests } + TEST_METHOD(zfill) + { + 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()); + + + 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/cppstrings.h b/cpp-strings/cppstrings.h index 9ab402e..98b37ed 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1087,7 +1087,7 @@ namespace pcs // i.e. "pythonic c++ strings" if (this->size() >= width) return *this; else - return *this + CppStringT(width - this->size(), fillch); + return CppStringT(width - this->size(), fillch) + *this; } @@ -1380,7 +1380,7 @@ namespace pcs // i.e. "pythonic c++ strings" if (this->size() >= width) return *this; else - return CppStringT(width - this->size(), fillch) + *this; + return *this + CppStringT(width - this->size(), fillch); } @@ -1825,9 +1825,9 @@ namespace pcs // i.e. "pythonic c++ strings" const size_type padding_width = width - this->size(); if ((*this)[0] == '+' || (*this)[0] == '-') - return (*this)[0] + this->substr(1, this->size() - 1).ljust(padding_width, value_type('0')); + return (*this)[0] + this->substr(1, this->size() - 1).ljust(width-1, value_type('0')); else - return this->ljust(padding_width, value_type('0')); + return this->ljust(width, value_type('0')); } }; From 7588cb6eb4f770d466305a6576422fecea6a590c Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 16:15:58 +0200 Subject: [PATCH 113/137] #202-add test on nullptr in CppStringT pointer constructors Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 16 ++++++++++ cpp-strings/cppstrings.h | 40 +++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 07399c3..094c440 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -560,6 +560,14 @@ namespace cppstringstests 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) @@ -571,6 +579,14 @@ namespace cppstringstests 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) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 98b37ed..72df2e6 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -380,8 +380,12 @@ namespace pcs // i.e. "pythonic c++ strings" 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) : MyBaseClass(s) {} // #9 - inline CppStringT(const CharT* s, size_type count) : MyBaseClass(s, count) {} // #10 + 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 @@ -452,6 +456,38 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- contains() -------------------------------------- + /** \brief Returns true if this string contains the passed string or char. + * + * This is the c++ implementation of Python keyword 'in' applied to strings. + */ + const bool contains(const CppStringT& substr) const noexcept + { + if (substr.empty()) + // 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) + return false; + + for (size_type index = 0; index <= width - substr_width; ++index) { + if (substr == this->substr(index, substr_width)) + return true; + } + + return false; +#endif + } + + //--- count() ----------------------------------------- /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, end]. */ constexpr size_type count(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept From 873d6d1f24ba361d6236e23af504a7a5e9be859d Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 18:10:35 +0200 Subject: [PATCH 114/137] #182-Implement method CppStringT::contains() Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 59 +++++++++++++++++++++++++ cpp-strings/cppstrings.h | 28 +++++++++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 094c440..a571772 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -714,6 +714,65 @@ namespace cppstringstests Assert::AreEqual(pcs::CppWString(L"zyxwvutsrqp").c_str(), ws.center(10, L'#').c_str(), L"--16--"); } + TEST_METHOD(contains) + { + 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(count) { pcs::CppString s("abcabcabcdefabca bca bcabca"); diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 72df2e6..7ad797e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -457,7 +457,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- contains() -------------------------------------- - /** \brief Returns true if this string contains the passed string or char. + /** \brief Returns true if this string contains the passed string, or false otherwise. * * This is the c++ implementation of Python keyword 'in' applied to strings. */ @@ -487,6 +487,32 @@ namespace pcs // i.e. "pythonic c++ strings" #endif } + /** \brief Returns true if this string contains the passed C-string, or false otherwise. */ + inline const bool contains(const CharT* substr) const noexcept + { + if (substr == nullptr) + // just to avoid system error on invalid access + 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 + return contains(CppStringT(substr)); +#endif + } + /** \brief Returns true if this string contains the passed char, or false otherwise. */ + const bool contains(const CharT& ch) const noexcept + { +#if (defined(_HAS_CXX23) && _HAS_CXX23) || (!defined(_HAS_CXX23) && __cplusplus >= 202302L) + // c++23 and above already defines this method + return MyBaseClass::contains(ch); +#else + // up to c++20, we have to implement this method + return std::ranges::any_of(*this, [ch](const value_type c) -> bool { return c == ch; }); +#endif + } + //--- count() ----------------------------------------- /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, end]. */ From 60f516346677ea754690d98d127efec457f5476e Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 18:13:03 +0200 Subject: [PATCH 115/137] #184-Test method CppStringT::contains() Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index a571772..7427671 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -738,7 +738,6 @@ namespace cppstringstests 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) @@ -761,7 +760,6 @@ namespace cppstringstests 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')); From c269f628b459b5ce82c733439ddb3c770fcf90f6 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 18:55:32 +0200 Subject: [PATCH 116/137] #183-Implement method CppStringT::contains_n() Done. Still to be tested. --- cpp-strings/cppstrings.h | 46 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 7ad797e..08c71ca 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -461,7 +461,7 @@ namespace pcs // i.e. "pythonic c++ strings" * * This is the c++ implementation of Python keyword 'in' applied to strings. */ - const bool contains(const CppStringT& substr) const noexcept + constexpr bool contains(const CppStringT& substr) const noexcept { if (substr.empty()) // the empty string is always contained in any string @@ -488,7 +488,7 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \brief Returns true if this string contains the passed C-string, or false otherwise. */ - inline const bool contains(const CharT* substr) const noexcept + inline constexpr bool contains(const CharT* substr) const noexcept { if (substr == nullptr) // just to avoid system error on invalid access @@ -501,8 +501,9 @@ namespace pcs // i.e. "pythonic c++ strings" return contains(CppStringT(substr)); #endif } + /** \brief Returns true if this string contains the passed char, or false otherwise. */ - const bool contains(const CharT& ch) const noexcept + inline constexpr bool contains(const CharT& ch) const noexcept { #if (defined(_HAS_CXX23) && _HAS_CXX23) || (!defined(_HAS_CXX23) && __cplusplus >= 202302L) // c++23 and above already defines this method @@ -514,6 +515,45 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- contains_n() ------------------------------------ + /** Returns true if the passed string is found within the slice str[start:start+count-1], or false otherwise. */ + 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; + } + } + + /** Returns true if the passed C-string is found within the slice str[start:start+count-1], or false otherwise. */ + inline constexpr bool contains_n(const CharT* sub, const size_type start, const size_type count = -1) const noexcept + { + if (sub == nullptr) + // just to avoid system error on invalid access + return true; + + try { + return this->substr(start, count).contains(sub); + } + catch (...) { + return false; + } + } + + /** Returns true if the passed char is found within the slice str[start:start+count-1], or false otherwise. */ + inline constexpr bool contains_n(const CharT ch, const size_type start, const size_type count = -1) const noexcept + { + try { + return this->substr(start, count).contains(ch); + } + catch (...) { + return false; + } + } + + //--- count() ----------------------------------------- /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, end]. */ constexpr size_type count(const CppStringT& sub, const size_type start = 0, const size_type end = -1) const noexcept From 016bdfdc1027660208c841efd19bfcd58da02db3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 20:26:33 +0200 Subject: [PATCH 117/137] #183-Implement method CppStringT::contains_n() Modified doxygen comments. --- cpp-strings/cppstrings.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 08c71ca..dcdcd61 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -459,7 +459,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- contains() -------------------------------------- /** \brief Returns true if this string contains the passed string, or false otherwise. * - * This is the c++ implementation of Python keyword 'in' applied to strings. + * This is a c++ implementation of Python keyword 'in' applied to strings. */ constexpr bool contains(const CppStringT& substr) const noexcept { @@ -516,7 +516,10 @@ namespace pcs // i.e. "pythonic c++ strings" //--- contains_n() ------------------------------------ - /** Returns true if the passed string is found within the slice str[start:start+count-1], or false otherwise. */ + /** 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. + */ inline constexpr bool contains_n(const CppStringT& sub, const size_type start, const size_type count = -1) const noexcept { try { From fbde103342eeb333098219200eb93d833c2b78b1 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 20:26:57 +0200 Subject: [PATCH 118/137] #185-Test method CppStringT::contains_n() Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 81 +++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index 7427671..b80fb61 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -771,6 +771,87 @@ namespace cppstringstests Assert::IsFalse(wtext.contains(L'a')); } + TEST_METHOD(contains_n) + { + 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"); From 20c35e803367b6effeca4e077e00d9fee8f2f72c Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 21:12:23 +0200 Subject: [PATCH 119/137] #180-Implement CppStringT::operator* () Completed. Still to be tested. --- cpp-strings/cppstrings.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index dcdcd61..4185ed3 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1247,6 +1247,20 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- operator * -------------------------------------- + /** Generates a new string with count times the content of this string. */ + CppStringT operator* (std::int64_t count) const noexcept + { + if (count <= 0) + return CppStringT(); + + CppStringT res( *this ); + while (--count) + res += *this; + return res; + } + + //--- partition() ------------------------------------- /** 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. * From 155954208be1ebbe8222d78a9533ad82167351b1 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 11 Jul 2025 21:12:50 +0200 Subject: [PATCH 120/137] #181-Test CppStringT::operator* () Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index b80fb61..b7741ac 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -1832,6 +1832,23 @@ namespace cppstringstests Assert::AreEqual(L"a bcd ", L" a bcd "cs.lstrip().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"); From 042fccaa3d9380ee4b98439f720ce98efb7a41d4 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 12 Jul 2025 00:54:40 +0200 Subject: [PATCH 121/137] #203-remove signatures with c-strings and chars Completed. Validated. --- cpp-strings/cppstrings.h | 220 +-------------------------------------- 1 file changed, 2 insertions(+), 218 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 4185ed3..c7389f4 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -487,33 +487,6 @@ namespace pcs // i.e. "pythonic c++ strings" #endif } - /** \brief Returns true if this string contains the passed C-string, or false otherwise. */ - inline constexpr bool contains(const CharT* substr) const noexcept - { - if (substr == nullptr) - // just to avoid system error on invalid access - 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 - return contains(CppStringT(substr)); -#endif - } - - /** \brief Returns true if this string contains the passed char, or false otherwise. */ - inline constexpr bool contains(const CharT& ch) const noexcept - { -#if (defined(_HAS_CXX23) && _HAS_CXX23) || (!defined(_HAS_CXX23) && __cplusplus >= 202302L) - // c++23 and above already defines this method - return MyBaseClass::contains(ch); -#else - // up to c++20, we have to implement this method - return std::ranges::any_of(*this, [ch](const value_type c) -> bool { return c == ch; }); -#endif - } - //--- contains_n() ------------------------------------ /** Returns true if the passed string is found within the slice str[start:start+count-1], or false otherwise. @@ -530,32 +503,6 @@ namespace pcs // i.e. "pythonic c++ strings" } } - /** Returns true if the passed C-string is found within the slice str[start:start+count-1], or false otherwise. */ - inline constexpr bool contains_n(const CharT* sub, const size_type start, const size_type count = -1) const noexcept - { - if (sub == nullptr) - // just to avoid system error on invalid access - return true; - - try { - return this->substr(start, count).contains(sub); - } - catch (...) { - return false; - } - } - - /** Returns true if the passed char is found within the slice str[start:start+count-1], or false otherwise. */ - inline constexpr bool contains_n(const CharT ch, const size_type start, const size_type count = -1) const noexcept - { - try { - return this->substr(start, count).contains(ch); - } - catch (...) { - return false; - } - } - //--- count() ----------------------------------------- /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, end]. */ @@ -698,42 +645,6 @@ namespace pcs // i.e. "pythonic c++ strings" return find_n(sub, start, end_ - start + 1); } - /** Returns the lowest index in the string where character ch is found within the slice str[start:end], or -1 (i.e. 'npos') if ch 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(). - */ - inline constexpr size_type find(const CharT ch, const size_type start = 0, const size_type end = -1) const noexcept - { - return find(CppStringT(ch), start, end); - } - - /** Returns the lowest index in the string where null-terminated string 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. The - * returned position is 0. - * - * \see find_n(), rfind() and rfind_n(). - * \see index(), index_n(), rindex() and rindex_n(). - */ - inline constexpr size_type find(const CharT* sub, const size_type start = 0, const size_type end = -1) const noexcept - { - if (sub == nullptr) - return CppStringT::npos; - else - return find(CppStringT(sub), start, end); - } - //--- find_n() ---------------------------------------- /** 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. @@ -780,64 +691,6 @@ namespace pcs // i.e. "pythonic c++ strings" return find_n(sub, 0, count); } - /** Returns the lowest index in the string where character ch is found within the slice str[start:start+count-1], or -1 (i.e. 'npos') if ch 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. - * - * \see find(), rfind() and rfind_n(). - * \see index(), index_n(), rindex() and rindex_n(). - */ - inline constexpr size_type find_n(const CharT ch, const size_type start, const size_type count) const noexcept - { - return find_n(CppStringT(ch), start, count); - } - - /** Returns the lowest index in the string where character ch is found within the slice str[0:count-1], or -1 (i.e. 'npos') if ch 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(), rfind() and rfind_n(). - * \see index(), index_n(), rindex() and rindex_n(). - */ - inline constexpr size_type find_n(const CharT ch, const size_type count) const noexcept - { - return find_n(CppStringT(ch), 0, count); - } - - /** Returns the lowest index in the string where null-terminated 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(), rfind() and rfind_n(). - * \see index(), index_n(), rindex() and rindex_n(). - */ - inline constexpr size_type find_n(const CharT* sub, const size_type start, const size_type count) const noexcept - { - if (sub == nullptr) - return CppStringT::npos; - else - return find_n(CppStringT(sub), start, count); - } - - /** Returns the lowest index in the string where null-terminated 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(), rfind() and rfind_n(). - * \see index(), index_n(), rindex() and rindex_n(). - */ - inline constexpr size_type find_n(const CharT* sub, const size_type count) const noexcept - { - return find_n(sub, 0, count); - } - //--- index() ----------------------------------------- /** Like find(const CppStringT&), but raises NotFoundException when the substring sub is not found. @@ -855,36 +708,6 @@ namespace pcs // i.e. "pythonic c++ strings" return ret_value; } - /** Like find(const CharT), but raises NotFoundException when character ch is not found. - * - * \see index_n(), rindex() and rindex_n(). - * \see find(), find_n(), rfind() and rfind_n(). - */ - inline constexpr size_type index(const CharT ch, const size_type start = 0, const size_type end = -1) const - { - const size_type ret_value = find(ch, start, end); - if (ret_value == CppStringT::npos) - throw NotFoundException("char not found in string."); - //throw NotFoundException(CppStringT(std::format("character \"{}\" not found in string \"{}\"", CppStringT(ch).c_str(), this->c_str()).c_str())); - else - return ret_value; - } - - /** Like find(const CharT*), 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(). - */ - inline constexpr size_type index(const CharT* 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"); - //throw NotFoundException(CppStringT(std::format("substring \"{}\" not found in string \"{}\"", CppStringT(sub).c_str(), this->c_str()).c_str())); - else - return ret_value; - } - //--- index_n() --------------------------------------- /** Like find_n(sub, start, count), but raises NotFoundException when the substring is not found. @@ -907,46 +730,6 @@ namespace pcs // i.e. "pythonic c++ strings" return index(sub, 0, count); } - /** Like find_n(sub, start, count), but raises NotFoundException when the character is not found. - * - * \see index_n(), rindex() and rindex_n(). - * \see find(), find_n(), rfind() and rfind_n(). - */ - inline constexpr size_type index_n(const CharT ch, const size_type start, const size_type count) const - { - return index(ch, start, start + count - 1); - } - - /** Like find_n(sub, count), but raises NotFoundException when the character is not found. - * - * \see index_n(), rindex() and rindex_n(). - * \see find(), find_n(), rfind() and rfind_n(). - */ - inline constexpr size_type index_n(const CharT ch, const size_type count) const - { - return index(ch, 0, count); - } - - /** Like find_n(sub, start, count), but raises NotFoundException when the null-terminated substring is not found. - * - * \see index_n(), rindex() and rindex_n(). - * \see find(), find_n(), rfind() and rfind_n(). - */ - inline constexpr size_type index_n(const CharT* sub, const size_type start, const size_type count) const - { - return index(sub, start, start + count - 1); - } - - /** Like find_n(sub, count), but raises NotFoundException when the null-terminated substring is not found. - * - * \see index_n(), rindex() and rindex_n(). - * \see find(), find_n(), rfind() and rfind_n(). - */ - inline constexpr size_type index_n(const CharT* 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. */ @@ -1378,7 +1161,8 @@ namespace pcs // i.e. "pythonic c++ strings" return rfind(sub, start, this->size() - 1); } - /** Returns the highest index in the string where substring sub is found in the whole string, or -1 (i.e. 'npos') if sub is not found. + + /** 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. * From 83f468cc40264949d23a701936c9e35f2e21a457 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 12 Jul 2025 19:37:42 +0200 Subject: [PATCH 122/137] #208-implement slices Completed. Compiles. Still to be tested. --- cpp-strings/cppstrings.h | 271 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 267 insertions(+), 4 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index c7389f4..5927c6c 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,37 @@ namespace pcs // i.e. "pythonic c++ strings" using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' + + // 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 + + // litteral operators #pragma warning(disable: 4455) inline CppString operator""cs(const char* str, std::size_t len); //!< Forms a CppString literal. @@ -126,12 +158,12 @@ namespace pcs // i.e. "pythonic c++ strings" * - char32_t (C++11) */ template - class CppStringT : public std::basic_string + class CppStringT : public std::basic_string { public: //=== Wrappers ======================================== - using MyBaseClass = std::basic_string; - using MyStringView = std::basic_string_view; + using MyBaseClass = std::basic_string; + using MyStringView = std::basic_string_view; using traits_type = MyBaseClass::traits_type; using value_type = MyBaseClass::value_type; @@ -1030,8 +1062,75 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- 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. + */ + inline CppStringT operator() (const long stop) const noexcept + { + size_type end{ stop < 0 ? this->size() + stop : stop }; + return this->substr(0, end); + } + + /** \brief Generates a new string according to the specified slice. */ + inline CppStringT operator() (const long start, const long stop) const noexcept + { + const size_type length{ this->size() }; + size_type begin{ start < 0 ? length + start : start }; + size_type end{ stop < 0 ? length + stop : stop }; + + if (begin >= end) + return CppStringT(); + else + return this->substr(begin, end - begin); + } + + /** \brief Generates a new string according to the specified slice. */ + CppStringT operator() (const long start, const long stop, const long step) const noexcept + { + CppStringT res{}; + + const size_type length{ this->size() }; + size_type begin{ start < 0 ? length + start : start }; + size_type end{ stop < 0 ? length + stop : stop }; + + if (step < 0) { + if (begin >= length) + begin = length - 1; + if (end < 0) + end = -1; + + if (begin > end) { + for (size_type i = begin; i > end; i += step) + res += (*this)[i]; + } + } + else if (step > 0) { + if (begin < 0) + begin = 0; + if (end > length) + end = length; + + if (begin < end) { + for (size_type i = begin; i < end; i += step) + res += (*this)[i]; + } + } + + return res; + } + + + //--- operator * -------------------------------------- - /** Generates a new string with count times the content of this string. */ + /** \brief Generates a new string with count times the content of this string. */ CppStringT operator* (std::int64_t count) const noexcept { if (count <= 0) @@ -1736,6 +1835,170 @@ namespace pcs // i.e. "pythonic c++ strings" }; + //===== 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() noexcept = default; //!< Default constructor + + Slice(const IntT start, const IntT stop, const IntT step) noexcept //!< Valued constructor + : _start(start) + , _stop(stop) + , _step(step) + {} + + virtual ~Slice() noexcept = default; //!< Default destructor. + + + //--- iterating ----------------------------------- + inline const IntT begin(const CppString& str) noexcept //!< starts iterating on specified CppString. + { + if (_start == DEFAULT) + _start = 0; + else if (_start < 0) + _start += str.size(); + + if (_stop == DEFAULT) + _stop = str.size(); + else if (_stop < 0) + _stop += str.size(); + + if (_step == DEFAULT) + _step = 1; + + return _index = _start; + } + + 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 const IntT operator++() noexcept //!< iterates one step, pre-increment. Caution: returned index may be out of bounds. Check '!end()' before using its value. + { + return _index += _step; + } + + inline const IntT operator++(int) noexcept //!< iterates one step, post-increment. Caution: returned index may be out of bounds. Check '!end()' before using its value. + { + _index += _step; + return _index - _step; + } + + + private: + IntT _start{ 0 }; + IntT _stop{ DEFAULT }; + IntT _step{ 1 }; + + IntT _index{ 0 }; + }; + + + /** \brief Class of slices with default stop and step values. */ + template + requires std::is_signed_v + struct StartSlice : public Slice + { + //--- Constructors / Destructor ------------------- + StartSlice() noexcept = default; //!< Default constructor + + inline StartSlice(const IntT start) noexcept //!< Valued constructor + : Slice(start, Slice::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 + { + //--- Constructors / Destructor ------------------- + StopSlice() noexcept = default; //!< Default constructor + + inline StopSlice(const IntT stop) noexcept //!< Valued constructor + : Slice(Slice::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 + { + //--- Constructors / Destructor ------------------- + StepSlice() noexcept = default; //!< Default constructor + + inline StepSlice(const IntT step) noexcept //!< Valued constructor + : Slice(Slice::DEFAULT, Slice::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 + { + //--- Constructors / Destructor ------------------- + StartStopSlice() noexcept = default; //!< Default constructor + + inline StartStopSlice(const IntT start, const IntT stop) noexcept //!< Valued constructor + : Slice(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 + { + //--- Constructors / Destructor ------------------- + StartStepSlice() noexcept = default; //!< Default constructor + + inline StartStepSlice(const IntT start, const IntT step) noexcept //!< Valued constructor + : Slice(start, Slice::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 + { + //--- Constructors / Destructor ------------------- + StopStepSlice() noexcept = default; //!< Default constructor + + inline StopStepSlice(const IntT stop, const IntT step) noexcept //!< Valued constructor + : Slice(Slice::DEFAULT, stop, step) + {} + + virtual ~StopStepSlice() noexcept = default; //!< Default destructor. + }; + + //===== litteral operators ============================ /** \brief Forms a CppString literal. */ inline CppString operator""cs(const char* str, std::size_t len) From 43f4bbd1842b0da4f7e89be7252fa8a03ed88ea2 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 12 Jul 2025 19:45:45 +0200 Subject: [PATCH 123/137] #208-implement slices Enhanced. Still to be tested. --- cpp-strings/cppstrings.h | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 5927c6c..7cdf855 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1860,20 +1860,12 @@ namespace pcs // i.e. "pythonic c++ strings" //--- iterating ----------------------------------- inline const IntT begin(const CppString& str) noexcept //!< starts iterating on specified CppString. { - if (_start == DEFAULT) - _start = 0; - else if (_start < 0) - _start += str.size(); - - if (_stop == DEFAULT) - _stop = str.size(); - else if (_stop < 0) - _stop += str.size(); - - if (_step == DEFAULT) - _step = 1; + return _prepare_iterating(IntT(str.size())); + } - return _index = _start; + inline const IntT begin(const CppWString& wstr) noexcept //!< starts iterating on specified CppWString. + { + return _prepare_iterating(IntT(wstr.size())); } inline const bool end() const noexcept //!< returns true when iterating is over, or false otherwise. @@ -1899,6 +1891,24 @@ namespace pcs // i.e. "pythonic c++ strings" IntT _step{ 1 }; IntT _index{ 0 }; + + const IntT _prepare_iterating(const IntT str_size) noexcept + { + if (_start == DEFAULT) + _start = 0; + else if (_start < 0) + _start += str_size; + + if (_stop == DEFAULT) + _stop = str_size; + else if (_stop < 0) + _stop += str_size; + + if (_step == DEFAULT) + _step = 1; + + return _index = _start; + } }; From 3f25a77767d34b8eb6d37f65683bc631b569389b Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 13 Jul 2025 16:08:17 +0200 Subject: [PATCH 124/137] #209-test slices Completed. Validated. A few fixes and added `operator*()`. --- cpp-strings/cppstrings.h | 98 +++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 36 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 7cdf855..d9efc71 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1846,9 +1846,7 @@ namespace pcs // i.e. "pythonic c++ strings" static constexpr IntT DEFAULT{ std::numeric_limits::min()}; //--- Constructors / Destructor ------------------- - Slice() noexcept = default; //!< Default constructor - - Slice(const IntT start, const IntT stop, const IntT step) noexcept //!< Valued constructor + Slice(const IntT start = DEFAULT, const IntT stop = DEFAULT, const IntT step = DEFAULT) noexcept //!< Valued constructor : _start(start) , _stop(stop) , _step(step) @@ -1873,15 +1871,21 @@ namespace pcs // i.e. "pythonic c++ strings" return _step == 0 ? true : _step > 0 ? _index >= _stop : _index <= _stop; } - inline const IntT operator++() noexcept //!< iterates one step, pre-increment. Caution: returned index may be out of bounds. Check '!end()' before using its value. + inline Slice operator++() noexcept //!< iterates one step, pre-increment. Caution: index may be out of bounds. Check '!end()' before dereferencing the slice. { - return _index += _step; + _index += _step; + return *this; } - inline const IntT operator++(int) noexcept //!< iterates one step, post-increment. Caution: returned index may be out of bounds. Check '!end()' before using its value. + 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 _index - _step; + return *this; + } + + inline const IntT operator*() noexcept //!< dereferences the slice. + { + return _index; } @@ -1896,16 +1900,38 @@ namespace pcs // i.e. "pythonic c++ strings" { if (_start == DEFAULT) _start = 0; - else if (_start < 0) + else if (_start < 0) { _start += str_size; - - if (_stop == DEFAULT) - _stop = str_size; - else if (_stop < 0) + if (_start < 0) + _start = 0; + } + else if (_start >= str_size) + _start = str_size - 1; + + if (_stop == DEFAULT) { + if (_step < 0 && _step != DEFAULT) + _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) _step = 1; + if (_step < 0) { + if (_start <= _stop) + _step = 0; // will force end() to true + } + else { + if (_start >= _stop) + _step = 0; // will force end() to true + } return _index = _start; } @@ -1917,11 +1943,11 @@ namespace pcs // i.e. "pythonic c++ strings" requires std::is_signed_v struct StartSlice : public Slice { - //--- Constructors / Destructor ------------------- - StartSlice() noexcept = default; //!< Default constructor + using MyBaseClass = Slice; - inline StartSlice(const IntT start) noexcept //!< Valued constructor - : Slice(start, Slice::DEFAULT, 1) + //--- Constructors / Destructor ------------------- + inline StartSlice(const IntT start = MyBaseClass::DEFAULT) noexcept //!< Valued constructor + : MyBaseClass(start, MyBaseClass::DEFAULT, 1) {} virtual ~StartSlice() noexcept = default; //!< Default destructor. @@ -1933,11 +1959,11 @@ namespace pcs // i.e. "pythonic c++ strings" requires std::is_signed_v struct StopSlice : public Slice { - //--- Constructors / Destructor ------------------- - StopSlice() noexcept = default; //!< Default constructor + using MyBaseClass = Slice; - inline StopSlice(const IntT stop) noexcept //!< Valued constructor - : Slice(Slice::DEFAULT, stop, 1) + //--- Constructors / Destructor ------------------- + inline StopSlice(const IntT stop = MyBaseClass::DEFAULT) noexcept //!< Valued constructor + : MyBaseClass(MyBaseClass::DEFAULT, stop, 1) {} virtual ~StopSlice() noexcept = default; //!< Default destructor. @@ -1949,11 +1975,11 @@ namespace pcs // i.e. "pythonic c++ strings" requires std::is_signed_v struct StepSlice : public Slice { - //--- Constructors / Destructor ------------------- - StepSlice() noexcept = default; //!< Default constructor + using MyBaseClass = Slice; - inline StepSlice(const IntT step) noexcept //!< Valued constructor - : Slice(Slice::DEFAULT, Slice::DEFAULT, step) + //--- Constructors / Destructor ------------------- + inline StepSlice(const IntT step = MyBaseClass::DEFAULT) noexcept //!< Valued constructor + : MyBaseClass(MyBaseClass::DEFAULT, MyBaseClass::DEFAULT, step) {} virtual ~StepSlice() noexcept = default; //!< Default destructor. @@ -1965,11 +1991,11 @@ namespace pcs // i.e. "pythonic c++ strings" requires std::is_signed_v struct StartStopSlice : public Slice { - //--- Constructors / Destructor ------------------- - StartStopSlice() noexcept = default; //!< Default constructor + using MyBaseClass = Slice; - inline StartStopSlice(const IntT start, const IntT stop) noexcept //!< Valued constructor - : Slice(start, stop, 1) + //--- 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. @@ -1981,11 +2007,11 @@ namespace pcs // i.e. "pythonic c++ strings" requires std::is_signed_v struct StartStepSlice : public Slice { - //--- Constructors / Destructor ------------------- - StartStepSlice() noexcept = default; //!< Default constructor + using MyBaseClass = Slice; - inline StartStepSlice(const IntT start, const IntT step) noexcept //!< Valued constructor - : Slice(start, Slice::DEFAULT, step) + //--- 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. @@ -1998,11 +2024,11 @@ namespace pcs // i.e. "pythonic c++ strings" requires std::is_signed_v struct StopStepSlice : public Slice { - //--- Constructors / Destructor ------------------- - StopStepSlice() noexcept = default; //!< Default constructor + using MyBaseClass = Slice; - inline StopStepSlice(const IntT stop, const IntT step) noexcept //!< Valued constructor - : Slice(Slice::DEFAULT, stop, step) + //--- 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. From f512977c81aaf81be0bcf71358289f9eedd7eb86 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 13 Jul 2025 19:30:23 +0200 Subject: [PATCH 125/137] #194-Implement operator () with slices Completed. Still to be tested. --- cpp-strings/cppstrings.h | 98 +++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 51 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index d9efc71..a08b0db 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1072,62 +1072,47 @@ namespace pcs // i.e. "pythonic c++ strings" * 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. */ - inline CppStringT operator() (const long stop) const noexcept - { - size_type end{ stop < 0 ? this->size() + stop : stop }; - return this->substr(0, end); - } - - /** \brief Generates a new string according to the specified slice. */ - inline CppStringT operator() (const long start, const long stop) const noexcept - { - const size_type length{ this->size() }; - size_type begin{ start < 0 ? length + start : start }; - size_type end{ stop < 0 ? length + stop : stop }; - - if (begin >= end) - return CppStringT(); - else - return this->substr(begin, end - begin); - } + template + requires std::is_signed_v + CppStringT operator() (Slice slice) const noexcept + { + // optimization on 1 by 1 step + if (slice.step() == 1) { + slice.begin(*this); + if (slice.start() < slice.stop()) + return this->substr(slice.start(), slice.stop() - slice.start() + 1); + else + return CppStringT(); + } - /** \brief Generates a new string according to the specified slice. */ - CppStringT operator() (const long start, const long stop, const long step) const noexcept - { CppStringT res{}; - const size_type length{ this->size() }; - size_type begin{ start < 0 ? length + start : start }; - size_type end{ stop < 0 ? length + stop : stop }; - - if (step < 0) { - if (begin >= length) - begin = length - 1; - if (end < 0) - end = -1; - - if (begin > end) { - for (size_type i = begin; i > end; i += step) - res += (*this)[i]; - } - } - else if (step > 0) { - if (begin < 0) - begin = 0; - if (end > length) - end = length; - - if (begin < end) { - for (size_type i = begin; i < end; i += step) - res += (*this)[i]; - } + // optimization on reversed 1 by 1 step + if (slice.step() == -1) { + slice.begin(*this); + if (slice.stop() < slice.start()) { + res = this->substr(slice.stop(), 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)[*slice]; + return res; } - + /** \brief Generates a new string according to the specified slicing values. */ + 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. */ @@ -1888,6 +1873,11 @@ namespace pcs // i.e. "pythonic c++ strings" 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 }; @@ -1898,15 +1888,21 @@ namespace pcs // i.e. "pythonic c++ strings" const IntT _prepare_iterating(const IntT str_size) noexcept { - if (_start == DEFAULT) - _start = 0; + if (_start == DEFAULT) { + if (_step < 0 && _step != DEFAULT) + _start = str_size - 1; + else + _start = 0; + } else if (_start < 0) { _start += str_size; if (_start < 0) _start = 0; } - else if (_start >= str_size) - _start = str_size - 1; + else if (_start >= str_size) { + if (_step < 0 && _step != DEFAULT) + _start = str_size - 1; + } if (_stop == DEFAULT) { if (_step < 0 && _step != DEFAULT) From 5aa34896c0cf64321900370b6dccb8112ce21188 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 13 Jul 2025 19:31:21 +0200 Subject: [PATCH 126/137] #195-Test operator () with slices Completed. Validated. Led to a few fixes. --- cpp-strings-tests/cpp-strings-tests.cpp | 1415 +++++++++++++++++++++++ 1 file changed, 1415 insertions(+) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index b7741ac..f653fb8 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -681,6 +681,1347 @@ namespace cppstringstests //===== 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) @@ -1832,6 +3173,80 @@ namespace cppstringstests 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(Slice()).c_str()); + Assert::AreEqual(text.c_str(), text(0, text_size).c_str()); + Assert::AreEqual(text.c_str(), text(StartSlice(0)).c_str()); + Assert::AreEqual(text.c_str(), text(StopSlice(123)).c_str()); + Assert::AreEqual(text.c_str(), text(StepSlice(1)).c_str()); + Assert::AreEqual(text.c_str(), text(StartStopSlice(0, 111)).c_str()); + Assert::AreEqual(text.c_str(), text(StartStepSlice(0, 1)).c_str()); + Assert::AreEqual(text.c_str(), text(StopStepSlice(text_size, 1)).c_str()); + + Assert::AreEqual("AceGikm", text(Slice(0, text_size + 2, 2)).c_str()); + Assert::AreEqual("behk", text(Slice(1, text_size, 3)).c_str()); + + Assert::AreEqual("", text(Slice(5, 4, 1)).c_str()); + Assert::AreEqual("", text(Slice(text_size, text_size + 1, 1)).c_str()); + Assert::AreEqual("", text(Slice(text_size + 2, text_size + 5, 1)).c_str()); + Assert::AreEqual("", text(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(StartStepSlice(text_size, -1)).c_str()); + Assert::AreEqual(reversed_text.c_str(), text(StopStepSlice(0, -1)).c_str()); + Assert::AreEqual(reversed_text.c_str(), text(StepSlice(-1)).c_str()); + + Assert::AreEqual("mkiGec", text(Slice(text_size, 0, -2)).c_str()); + Assert::AreEqual("mjGd", text(Slice(text_size-1, 1, -3)).c_str()); + + Assert::AreEqual("", text(Slice(4, 5, -1)).c_str()); + Assert::AreEqual("", text(Slice(text_size + 1, text_size, -1)).c_str()); + Assert::AreEqual("", text(Slice(text_size + 5, text_size + 2, -1)).c_str()); + Assert::AreEqual("", text(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(Slice()).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(0, text_size).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(StartSlice(0)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(StopSlice(123)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(StepSlice(1)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(StartStopSlice(0, 111)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(StartStepSlice(0, 1)).c_str()); + Assert::AreEqual(wtext.c_str(), wtext(StopStepSlice(text_size, 1)).c_str()); + + Assert::AreEqual(L"AceGikm", wtext(Slice(0, text_size + 2, 2)).c_str()); + Assert::AreEqual(L"behk", wtext(Slice(1, text_size, 3)).c_str()); + + Assert::AreEqual(L"", wtext(Slice(5, 4, 1)).c_str()); + Assert::AreEqual(L"", wtext(Slice(text_size, text_size + 1, 1)).c_str()); + Assert::AreEqual(L"", wtext(Slice(text_size + 2, text_size + 5, 1)).c_str()); + Assert::AreEqual(L"", wtext(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(StartStepSlice(text_size, -1)).c_str()); + Assert::AreEqual(wreversed_text.c_str(), wtext(StopStepSlice(0, -1)).c_str()); + Assert::AreEqual(wreversed_text.c_str(), wtext(StepSlice(-1)).c_str()); + + Assert::AreEqual(L"mkiGec", wtext(Slice(text_size, 0, -2)).c_str()); + Assert::AreEqual(L"mjGd", wtext(Slice(text_size - 1, 1, -3)).c_str()); + + Assert::AreEqual(L"", wtext(Slice(4, 5, -1)).c_str()); + Assert::AreEqual(L"", wtext(Slice(text_size + 1, text_size, -1)).c_str()); + Assert::AreEqual(L"", wtext(Slice(text_size + 5, text_size + 2, -1)).c_str()); + Assert::AreEqual(L"", wtext(Slice(3, 5, -2)).c_str()); + } + TEST_METHOD(operator_times) { pcs::CppString text("Abcd,"); From 96ccdf772f540266c03d7e0344d9d8d54e5fc3ed Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 13 Jul 2025 20:06:23 +0200 Subject: [PATCH 127/137] #210-remove string_views stuff. Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 11 +---------- cpp-strings/cppstrings.h | 26 +++++++------------------ 2 files changed, 8 insertions(+), 29 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index f653fb8..e14959d 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -23,15 +23,6 @@ namespace cppstringstests Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); } - TEST_METHOD(_csv) - { - using namespace pcs; - auto abcd = "abcD"csv; - auto wabcd = L"abcD"csv; - Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); - Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); - } - TEST_METHOD(is_alpha) { for (int ch = 0; ch <= 255; ++ch) @@ -3063,7 +3054,7 @@ namespace cppstringstests 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"# #"csv.join(L"abcd", 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()); diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index a08b0db..deaa5b1 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -32,7 +32,7 @@ #include #include #include -#include +//#include #include #include @@ -85,11 +85,11 @@ namespace pcs // i.e. "pythonic c++ strings" // litteral operators +#pragma warning(push) #pragma warning(disable: 4455) inline CppString operator""cs(const char* str, std::size_t len); //!< Forms a CppString literal. - inline CppString operator""csv(const char* str, std::size_t len); //!< Forms a CppString view literal. inline CppWString operator""cs(const wchar_t* str, std::size_t len); //!< Forms a CppWString literal. - inline CppWString operator""csv(const wchar_t* str, std::size_t len); //!< Forms a CppWString view literal. +#pragma warning(pop) // chars classifications -- not to be directly called, see respective specializations at the very end of this module. template @@ -163,7 +163,6 @@ namespace pcs // i.e. "pythonic c++ strings" public: //=== Wrappers ======================================== using MyBaseClass = std::basic_string; - using MyStringView = std::basic_string_view; using traits_type = MyBaseClass::traits_type; using value_type = MyBaseClass::value_type; @@ -330,7 +329,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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) { @@ -2032,31 +2031,20 @@ namespace pcs // i.e. "pythonic c++ strings" //===== litteral operators ============================ +#pragma warning(push) +#pragma warning(disable: 4455) /** \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 CppString view literal. */ - inline CppString operator""csv(const char* str, std::size_t len) - { - //return CppString(CppString::MyStringView(str, len)); - return CppString(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)); } - - /** \brief Forms a CppWString view literal. */ - inline CppWString operator""csv(const wchar_t* str, std::size_t len) - { - //return CppWString(CppWString::MyStringView(str, len)); - return CppWString(str, len); - } +#pragma warning(pop) //===== templated chars classes =========================== From b3dc949a0bb05c0cf7f6b6368a6072fd332aed6d Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 13 Jul 2025 21:20:05 +0200 Subject: [PATCH 128/137] #211-fix c++ and c standards for every projects, configurations and platforms Done. Validated. Led to a type casting fixing for 32-bits architectures. --- cpp-strings/cppstrings.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index deaa5b1..6902db6 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1081,7 +1081,7 @@ namespace pcs // i.e. "pythonic c++ strings" if (slice.step() == 1) { slice.begin(*this); if (slice.start() < slice.stop()) - return this->substr(slice.start(), slice.stop() - slice.start() + 1); + return this->substr(size_type(slice.start()), size_type(slice.stop() - slice.start() + 1)); else return CppStringT(); } @@ -1092,7 +1092,7 @@ namespace pcs // i.e. "pythonic c++ strings" if (slice.step() == -1) { slice.begin(*this); if (slice.stop() < slice.start()) { - res = this->substr(slice.stop(), slice.start() - slice.stop() + 1); + 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; @@ -1100,7 +1100,7 @@ namespace pcs // i.e. "pythonic c++ strings" // finally, no trivial optimization -- and naive implementation... for (slice.begin(*this); !slice.end(); ++slice) - res += (*this)[*slice]; + res += (*this)[size_type(*slice)]; return res; } From e986ede548e0a6dcdb791ddf4f8184007180779f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 13 Jul 2025 23:55:57 +0200 Subject: [PATCH 129/137] #18-Implement method CppStringT::format() Completed. Not that immediate. Still to be tested. --- cpp-strings/cppstrings.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 6902db6..5bfd105 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -723,6 +723,15 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- format() ---------------------------------------- + /** Formats this string according to c++20 std::format() specification. Returns it (may be discarded). */ + template + inline CppStringT format(const std::format_string frmt, ArgsT&&... args) + { + return *this = std::vformat(frmt.get(), std::make_format_args(args...)); + } + + //--- index() ----------------------------------------- /** Like find(const CppStringT&), but raises NotFoundException when the substring sub is not found. * From 18f4f7d8a4fe517c27ae4c26386d389698061d1f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 15 Jul 2025 19:56:10 +0200 Subject: [PATCH 130/137] #18-Implement method CppStringT::format() Completed. Validated. --- cpp-strings/cppstrings.h | 287 ++++++++++++++++++++++----------------- 1 file changed, 159 insertions(+), 128 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 5bfd105..678c9c4 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -32,13 +32,17 @@ #include #include #include -//#include #include #include namespace pcs // i.e. "pythonic c++ strings" { +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4455) // to avoid boring warnings with litteral operators definitions +#endif + //============================================================= // Forward declarations @@ -85,11 +89,9 @@ namespace pcs // i.e. "pythonic c++ strings" // litteral operators -#pragma warning(push) -#pragma warning(disable: 4455) 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. -#pragma warning(pop) + // chars classifications -- not to be directly called, see respective specializations at the very end of this module. template @@ -141,28 +143,29 @@ namespace pcs // i.e. "pythonic c++ strings" //===== CppStringT<> ====================================== /** \brief This is the templated base class for all CppString classes. * - * Users should instantiate any specialization of this base class + * 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. + * 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: + * 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 MyBaseClass = std::basic_string; using traits_type = MyBaseClass::traits_type; using value_type = MyBaseClass::value_type; @@ -185,7 +188,7 @@ namespace pcs // i.e. "pythonic c++ strings" { public: //--- wrappers ------------------------------------ - using key_type = CharT; + using key_type = CharT; using value_type = CppStringT; //--- Constructors / destructor ------------------- @@ -275,7 +278,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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 + * 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) @@ -311,8 +314,8 @@ namespace pcs // i.e. "pythonic c++ strings" */ template inline TransTable(Key1It first_key, Key1It last_key, - ValueIt first_value, ValueIt last_value, - Key2It first_not_translated, Key2It last_not_translated) + ValueIt first_value, ValueIt last_value, + Key2It first_not_translated, Key2It last_not_translated) { Key1It key1_it{ first_key }; ValueIt val_it{ first_value }; @@ -338,34 +341,12 @@ namespace pcs // i.e. "pythonic c++ strings" for (const auto k : keys) m_table[(*k)[0]] = value_type(*val_it++); } - /**/ - /** \brief Creates a TransTable from three string views (#11). - * - * 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. - */ - /** / - template - TransTable(const StringViewLike& keys, const StringViewLike& values, const StringViewLike& not_translated) - { - assert(keys.size() == values.size()); - auto val_it = values.cbegin(); - for (const auto k : keys) - m_table[k] = value_type(*val_it++); - for (const auto k : not_translated) - m_table[k] = CppStringT(); - } - /**/ - - 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 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 + inline ~TransTable() noexcept = default; //!< Default descrtuctor //--- operators ----------------------------------- inline TransTable& operator= (const TransTable&) noexcept = default; //!< Default copy assignment @@ -380,14 +361,13 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Indexing operator. */ inline value_type operator[] (const key_type ch) noexcept - //inline CppStringT operator[] (const key_type ch) noexcept { auto it = m_table.find(ch); if (it != m_table.end()) { return it->second; } else { - return ch; // CppStringT(ch); + return ch; } } @@ -398,8 +378,8 @@ namespace pcs // i.e. "pythonic c++ strings" private: std::map m_table{}; // the internal storage of the translation table. Access it via the indexing operator. - -}; + + }; //=== Constructors / Destructor ======================= @@ -724,13 +704,34 @@ namespace pcs // i.e. "pythonic c++ strings" //--- format() ---------------------------------------- - /** Formats this string according to c++20 std::format() specification. Returns it (may be discarded). */ + /** 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 CppStringT(); + } + template - inline CppStringT format(const std::format_string frmt, ArgsT&&... args) + 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() ----------------------------------------- /** Like find(const CppStringT&), but raises NotFoundException when the substring sub is not found. @@ -743,7 +744,6 @@ namespace pcs // i.e. "pythonic c++ strings" const size_type ret_value = find(sub, start, end); if (ret_value == CppStringT::npos) throw NotFoundException("substring not found in string."); - //throw NotFoundException(CppStringT(std::format("substring \"{}\" not found in string \"{}\"", sub.c_str(), this->c_str()).c_str())); else return ret_value; } @@ -778,7 +778,7 @@ namespace pcs // i.e. "pythonic c++ strings" if (this->empty()) return false; 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); }); + [](const value_type ch) { return pcs::is_alpha(ch) || pcs::is_decimal(ch) || pcs::is_digit(ch) || pcs::is_numeric(ch); }); } @@ -792,38 +792,38 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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 +#if defined(isascii) // may be already defined in header file +#undef isascii +#endif inline const bool isascii() const noexcept { - return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii); + 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 + * 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”. */ inline const bool isdecimal() const noexcept { - return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_decimal); + 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 + * 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. @@ -838,19 +838,19 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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 + * 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 | */ @@ -873,7 +873,7 @@ namespace pcs // i.e. "pythonic c++ strings" * * CAUTION: current implementation just returns isdecimal() result, * while the description of isnumeric() should be this one: - * Numeric characters include digit characters, and all characters + * 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. @@ -887,8 +887,8 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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 + * Nonprintable characters are those characters defined in the Unicode + * character database as "Other" or "Separator", excepting the ASCII * space (0x20) which is considered printable. */ inline const bool isprintable() const noexcept @@ -916,9 +916,9 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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 + * 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. @@ -942,7 +942,7 @@ namespace pcs // i.e. "pythonic c++ strings" 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); }); + [](const value_type ch) { return pcs::is_space(ch) || pcs::is_punctuation(ch); }); } @@ -980,7 +980,7 @@ namespace pcs // i.e. "pythonic c++ strings" return res; } - /** \brief Returns a string which is the concatenation of the strings in the parameters list. + /** \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. */ @@ -1007,7 +1007,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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). + * 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). */ inline CppStringT ljust(const size_type width, const value_type fillch = value_type(' ')) const noexcept @@ -1028,8 +1028,9 @@ namespace pcs // i.e. "pythonic c++ strings" inline CppStringT& lower() noexcept { std::transform(this->begin(), this->end(), - this->begin(), - [&](value_type ch) { return this->lower(ch); }); + this->begin(), + [&](value_type ch) { return this->lower(ch); } + ); return *this; } @@ -1042,13 +1043,13 @@ namespace pcs // i.e. "pythonic c++ strings" { 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 + * 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()'. */ @@ -1103,14 +1104,14 @@ namespace pcs // i.e. "pythonic c++ strings" if (slice.stop() < slice.start()) { 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; } @@ -1129,7 +1130,7 @@ namespace pcs // i.e. "pythonic c++ strings" if (count <= 0) return CppStringT(); - CppStringT res( *this ); + CppStringT res(*this); while (--count) res += *this; return res; @@ -1140,7 +1141,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** 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. + * containing the string itself, followed by two empty strings. */ std::vector partition(const CppStringT& sep) const noexcept { @@ -1316,7 +1317,6 @@ namespace pcs // i.e. "pythonic c++ strings" const size_type ret_value = rfind(sub, start, end); if (ret_value == CppStringT::npos) throw NotFoundException("substring not found in string"); - //throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); else return ret_value; } @@ -1403,7 +1403,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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 + * Notice: consecutive whitespaces are each regarded as a * single separator. So, they each separate empty strings. */ inline std::vector rsplit() noexcept @@ -1438,7 +1438,7 @@ namespace pcs // i.e. "pythonic c++ strings" size_type count{ maxsplit }; size_type index{ 0 }; - while ((index = tmp.rfind(sep)) != CppStringT::npos && count > 0) { + while ((index = tmp.rfind(sep)) != CppStringT::npos && count > 0) { indexes.insert(indexes.begin(), index); if (index == 0) break; @@ -1506,10 +1506,10 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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 + * 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 {""}. */ inline std::vector split(const CppStringT& sep) noexcept @@ -1578,7 +1578,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \x1c File Separator * \x1d Group Separator * \x1e Record Separator - * Next separators values, detected by Python method splitlines(), are NOT detected with CppStrings + * 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 @@ -1679,9 +1679,6 @@ namespace pcs // i.e. "pythonic c++ strings" return true; } return false; - - //else - // return std::any_of(prefixes.cbegin(), prefixes.cend(), this->substr(start, end).starts_with); } @@ -1726,7 +1723,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- substr() ---------------------------------------- /** \brief Returns a copy of the string, starting at index start and ending after count characters. */ - inline CppStringT substr(const size_type start, const size_type count=-1) const noexcept + inline CppStringT substr(const size_type start, const size_type count = -1) const noexcept { if (start > this->size()) return CppStringT(); @@ -1767,7 +1764,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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 + * 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. */ @@ -1809,8 +1806,8 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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 + * 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). */ inline CppStringT zfill(const size_type width) const noexcept @@ -1820,7 +1817,7 @@ namespace pcs // i.e. "pythonic c++ strings" const size_type padding_width = width - this->size(); if ((*this)[0] == '+' || (*this)[0] == '-') - return (*this)[0] + this->substr(1, this->size() - 1).ljust(width-1, value_type('0')); + return (*this)[0] + this->substr(1, this->size() - 1).ljust(width - 1, value_type('0')); else return this->ljust(width, value_type('0')); } @@ -1836,7 +1833,7 @@ namespace pcs // i.e. "pythonic c++ strings" class Slice { public: - static constexpr IntT DEFAULT{ std::numeric_limits::min()}; + 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 @@ -1849,16 +1846,17 @@ namespace pcs // i.e. "pythonic c++ strings" //--- iterating ----------------------------------- - inline const IntT begin(const CppString& str) noexcept //!< starts iterating on specified CppString. + 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())); } - inline const IntT begin(const CppWString& wstr) noexcept //!< starts iterating on specified CppWString. - { - return _prepare_iterating(IntT(wstr.size())); - } - 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; @@ -1883,8 +1881,8 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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 + 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: @@ -2040,8 +2038,6 @@ namespace pcs // i.e. "pythonic c++ strings" //===== litteral operators ============================ -#pragma warning(push) -#pragma warning(disable: 4455) /** \brief Forms a CppString literal. */ inline CppString operator""cs(const char* str, std::size_t len) { @@ -2053,7 +2049,6 @@ namespace pcs // i.e. "pythonic c++ strings" { return CppWString(CppWString::MyBaseClass(str, len)); } -#pragma warning(pop) //===== templated chars classes =========================== @@ -2061,41 +2056,55 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template inline const bool is_alpha(const CharT ch) noexcept - { return false; } + { + return false; + } /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> inline const bool is_alpha(const char ch) noexcept - { return static_cast(std::isalpha(static_cast(ch))); } + { + 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<> inline const bool is_alpha(const wchar_t ch) noexcept - { return static_cast(std::iswalpha(ch)); } + { + return static_cast(std::iswalpha(ch)); + } //--- is_ascii() ------------------------------------------ /** \brief Returns true if character has code point in the range U+0000-U+007F. */ template inline const bool is_ascii(const CharT ch) noexcept - { return CharT(0x00) <= ch && ch <= CharT(0x7f); } + { + return CharT(0x00) <= ch && ch <= CharT(0x7f); + } //--- is_decimal() ---------------------------------------- /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template inline const bool is_decimal(const CharT ch) noexcept - { return false; } + { + return false; + } /** \brief Returns true if character is a decimal digit, or false otherwise. */ template<> inline const bool is_decimal(const char ch) noexcept - { return static_cast(std::isdigit(static_cast(ch))); } + { + return static_cast(std::isdigit(static_cast(ch))); + } /** \brief Returns true if character is a decimal digit, or false otherwise. */ template<> inline const bool is_decimal(const wchar_t ch) noexcept - { return (const bool)std::iswdigit(ch); } + { + return (const bool)std::iswdigit(ch); + } //--- is_digit() ------------------------------------------ @@ -2125,14 +2134,18 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if character is a continuing char for identifiers, or false otherwise. */ template inline const bool is_id_continue(const CharT ch) noexcept - { return pcs::is_id_start(ch) || pcs::is_decimal(ch); } + { + 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 inline const bool is_id_start(const CharT ch) noexcept - { return pcs::is_alpha(ch) || ch == CharT('_'); } + { + return pcs::is_alpha(ch) || ch == CharT('_'); + } //--- is_lower() ------------------------------------------ @@ -2185,8 +2198,10 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template inline const bool is_printable(const CharT ch) noexcept - { return false; } - + { + return false; + } + /** \brief Returns true if character ch is printable, or false otherwise. */ template<> inline const bool is_printable(const char ch) noexcept @@ -2206,34 +2221,46 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template inline const bool is_punctuation(const CharT ch) noexcept - { return false; } + { + return false; + } /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ template<> inline const bool is_punctuation(const char ch) noexcept - { return static_cast(std::ispunct(static_cast(ch))); } + { + 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<> inline const bool is_punctuation(const wchar_t ch) noexcept - { return static_cast(std::iswpunct(ch)); } + { + return static_cast(std::iswpunct(ch)); + } //--- is_space() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template inline const bool is_space(const CharT ch) noexcept - { return false; } + { + return false; + } /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> inline const bool is_space(const char ch) noexcept - { return static_cast(std::isspace(static_cast(ch))); } + { + 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<> inline const bool is_space(const wchar_t ch) noexcept - { return static_cast(std::iswspace(ch)); } + { + return static_cast(std::iswspace(ch)); + } //--- is_upper() ------------------------------------------ @@ -2319,4 +2346,8 @@ namespace pcs // i.e. "pythonic c++ strings" } +#if defined(_MSC_VER) +# pragma warning(pop) // to avoid boring warnings with litteral operators definitions +#endif + } // end of namespace pcs // (pythonic c++ strings) \ No newline at end of file From bccb85bf424845eb36dae98bad0da3cb5e0ef61c Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 15 Jul 2025 19:57:18 +0200 Subject: [PATCH 131/137] #205-test method CppStringT::format() Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 20 ++++++++++++++++++++ cpp-strings/cppstrings.cpp | 8 +++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index e14959d..ce732e2 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -2541,6 +2541,26 @@ namespace cppstringstests } + 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; diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index 3ec760f..3c330f7 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -29,11 +29,17 @@ using namespace pcs; */ int main() { - CppString s = "-5.1"; + CppString s = "-5.1"cs; CppWString ws{ L"-5.2"cs }; std::cout << ws.isupper() << std::endl; std::cout << s.zfill(10).c_str() << std::endl; + s.format("{} {}", 1, 3.14); + ws.format(L"{} abc", 2); + + std::cout << s.c_str() << " / "; + std::wcout << ws.c_str() << std::endl; + return 0; } From 207421603b7b1a0cd69110a4cb99d56926a670fd Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 15 Jul 2025 20:06:42 +0200 Subject: [PATCH 132/137] #217-set VS project to c++20 and c17 Completed. --- cpp-strings/cpp-strings.vcxproj | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/cpp-strings/cpp-strings.vcxproj b/cpp-strings/cpp-strings.vcxproj index 2e1cdf3..7b32c1d 100644 --- a/cpp-strings/cpp-strings.vcxproj +++ b/cpp-strings/cpp-strings.vcxproj @@ -76,8 +76,9 @@ true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - stdcpplatest - stdclatest + stdcpp20 + stdc17 + false Console @@ -92,8 +93,9 @@ true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - stdcpplatest - stdclatest + stdcpp20 + stdc17 + false Console @@ -108,9 +110,9 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - stdcpplatest - stdclatest - true + stdcpp20 + stdc17 + false true @@ -126,9 +128,9 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - stdcpplatest - stdclatest - true + stdcpp20 + stdc17 + false true @@ -142,6 +144,7 @@ + From 6110a769fb461b01a8e5b8d976cfc5cb35c94f7d Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 15 Jul 2025 23:47:10 +0200 Subject: [PATCH 133/137] #207-Add namespace pcs when missing in tests Completed. Validated. --- cpp-strings-tests/cpp-strings-tests.cpp | 913 ++++++++++++------------ cpp-strings/cppstrings.cpp | 4 +- cpp-strings/cppstrings.h | 52 +- 3 files changed, 491 insertions(+), 478 deletions(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index ce732e2..bb994c2 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -3,7 +3,6 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; #include "cppstrings.h" -using namespace pcs; namespace cppstringstests @@ -17,10 +16,11 @@ namespace cppstringstests TEST_METHOD(_cs) { using namespace pcs; - auto abcd = "abcD"cs; - auto wabcd = L"abcD"cs; - Assert::AreEqual(abcd.c_str(), CppString(abcd).c_str()); - Assert::AreEqual(wabcd.c_str(), CppWString(wabcd).c_str()); + 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) @@ -173,121 +173,123 @@ namespace cppstringstests TEST_METHOD(constructor_01) { - 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()); + 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()); + 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) { - CppString keys("abcdE"); - CppString values("ABCDe"); + pcs::CppString keys("abcdE"); + pcs::CppString values("ABCDe"); pcs::CppString::TransTable t(keys, values); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString('D').c_str(), t['d'].c_str()); - Assert::AreEqual(CppString('e').c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abcdE"), CppWString(L"ABCDe")); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString(L'D').c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString(L'e').c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + 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(CppString("abc"), CppString("ABC"), CppString("dE")); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + 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(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }); - Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }); - Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString(L'9').c_str(), wt[L'9'].c_str()); + 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) { - pcs::CppString::TransTable t(CppString("abc"), { CppString("AA"), CppString("BBB"), CppString("C") }, "dE"cs); - Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('z').c_str(), t['z'].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), { CppWString(L"AA"), CppWString(L"BBB"), CppWString(L"C") }, L"dE"cs); - Assert::AreEqual(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L"C").c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'e').c_str(), wt[L'e'].c_str()); + 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(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['c'].c_str()); + 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(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); + 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(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('e').c_str(), t['e'].c_str()); + 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(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'A'].c_str()); + 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) @@ -295,18 +297,18 @@ namespace cppstringstests std::string keys("abC"); std::vector values{ "AA", "BBB", "c" }; pcs::CppString::TransTable t(keys.begin(), keys.end(), values.begin(), values.end()); - Assert::AreEqual(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['c'].c_str()); + 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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); + 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) @@ -315,23 +317,23 @@ namespace cppstringstests 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(CppString("AA").c_str(), t['a'].c_str()); - Assert::AreEqual(CppString("BBB").c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['C'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('c').c_str(), t['c'].c_str()); + 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(CppWString(L"AA").c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L"BBB").c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'C'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'c').c_str(), wt[L'c'].c_str()); + 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) @@ -345,126 +347,126 @@ namespace cppstringstests TEST_METHOD(constructor_copy) { - pcs::CppString::TransTable ct(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable ct(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); pcs::CppString::TransTable t(ct); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"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 wct(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); pcs::CppWString::TransTable wt(wct); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + 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(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable mt(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); pcs::CppString::TransTable t(std::move(mt)); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"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 wmt(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); pcs::CppWString::TransTable wt(std::move(wmt)); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + 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(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable ct(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); pcs::CppString::TransTable t = ct; - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"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 wct(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); pcs::CppWString::TransTable wt = wct; - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + 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(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable mt(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); pcs::CppString::TransTable t = std::move(mt); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wmt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"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 wmt(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); pcs::CppWString::TransTable wt = std::move(wmt); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + 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(CppString("abc"), CppString("ABC"), CppString("dE")); + pcs::CppString::TransTable ct(pcs::CppString("abc"), pcs::CppString("ABC"), pcs::CppString("dE")); pcs::CppString::TransTable t = ct.get_table(); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString('f').c_str(), t['f'].c_str()); - - pcs::CppWString::TransTable wct(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"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 wct(pcs::CppWString(L"abc"), pcs::CppWString(L"ABC"), pcs::CppWString(L"dE")); pcs::CppWString::TransTable wt = wct.get_table(); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'f').c_str(), wt[L'f'].c_str()); + 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(CppString("abc"), CppString("ABC"), CppString("dE")); - Assert::AreEqual(CppString('A').c_str(), t['a'].c_str()); - Assert::AreEqual(CppString('B').c_str(), t['b'].c_str()); - Assert::AreEqual(CppString('C').c_str(), t['c'].c_str()); - Assert::AreEqual(CppString().c_str(), t['d'].c_str()); - Assert::AreEqual(CppString().c_str(), t['E'].c_str()); - Assert::AreEqual(CppString(',').c_str(), t[','].c_str()); - - pcs::CppWString::TransTable wt(CppWString(L"abc"), CppWString(L"ABC"), CppWString(L"dE")); - Assert::AreEqual(CppWString(L'A').c_str(), wt[L'a'].c_str()); - Assert::AreEqual(CppWString(L'B').c_str(), wt[L'b'].c_str()); - Assert::AreEqual(CppWString(L'C').c_str(), wt[L'c'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'd'].c_str()); - Assert::AreEqual(CppWString().c_str(), wt[L'E'].c_str()); - Assert::AreEqual(CppWString(L'\n').c_str(), wt[L'\n'].c_str()); + 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()); } }; @@ -2048,16 +2050,17 @@ namespace cppstringstests 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)); + 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) { @@ -2065,10 +2068,10 @@ namespace cppstringstests 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)); + 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())); @@ -2105,6 +2108,7 @@ namespace cppstringstests 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)); @@ -2115,12 +2119,12 @@ namespace cppstringstests 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)); + 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) { @@ -2132,12 +2136,12 @@ namespace cppstringstests 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)); + 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)); @@ -2290,23 +2294,23 @@ namespace cppstringstests { 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(CppString("a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), ts.c_str()); + 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(CppString("a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), ts.c_str()); + 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(CppString("a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), ts.c_str()); + 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(CppString("a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), ts.c_str()); + 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(CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); + 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(CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); + 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(CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); + 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(CppWString(L"a bc def ghij \r k\nl m\r\nno pqr s.").c_str(), wts.c_str()); + 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) @@ -2330,7 +2334,7 @@ namespace cppstringstests else Assert::AreEqual(found_pos, test_str.find(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); - CppString s(ch); + 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) @@ -2384,7 +2388,7 @@ namespace cppstringstests else Assert::AreEqual(found_pos, wtest.find(wch, 2, pcs::CppWString::size_type(5 + 2 - 1)) - 2); - CppWString ws(wch); + pcs::CppWString ws(wch); Assert::AreEqual(wtest.MyBaseClass::find(ws), wtest.find(ws)); found_pos = wtest.substr(2).MyBaseClass::find(ws); @@ -2446,7 +2450,7 @@ namespace cppstringstests else Assert::AreEqual(found_pos, test_str.find_n(ch, 2, pcs::CppString::size_type(5)) - 2); - CppString s(ch); + 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) @@ -2501,7 +2505,7 @@ namespace cppstringstests else Assert::AreEqual(found_pos, wtest.find_n(wch, 2, pcs::CppString::size_type(5)) - 2); - CppWString ws(wch); + 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) @@ -2728,7 +2732,7 @@ namespace cppstringstests } catch (const string_type::NotFoundException e) { /* ok case! */ } - CppString s(ch); + 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'; @@ -2818,14 +2822,14 @@ namespace cppstringstests TEST_METHOD(isalpha) { - Assert::IsFalse(CppString().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(CppWString().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); @@ -2835,14 +2839,14 @@ namespace cppstringstests TEST_METHOD(isascii) { - Assert::IsTrue(CppString().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(CppWString().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); @@ -2852,14 +2856,14 @@ namespace cppstringstests TEST_METHOD(isdecimal) { - Assert::IsFalse(CppString().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(CppWString().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); @@ -2869,14 +2873,14 @@ namespace cppstringstests TEST_METHOD(isdigit) { - Assert::IsFalse(CppString().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(CppWString().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); @@ -2911,14 +2915,14 @@ namespace cppstringstests TEST_METHOD(islower) { - Assert::IsFalse(CppString().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(CppWString().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); @@ -2928,14 +2932,14 @@ namespace cppstringstests TEST_METHOD(isnumeric) { - Assert::IsFalse(CppString().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(CppWString().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); @@ -2945,14 +2949,14 @@ namespace cppstringstests TEST_METHOD(isprintable) { - Assert::IsTrue(CppString().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(CppWString().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); @@ -2962,33 +2966,33 @@ namespace cppstringstests TEST_METHOD(ispunctuation) { - Assert::IsFalse(CppString().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), CppString(ch).ispunctuation()); + Assert::AreEqual(pcs::is_punctuation(ch), pcs::CppString(ch).ispunctuation()); } - Assert::IsFalse(CppWString().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), CppWString(wch).ispunctuation()); + Assert::AreEqual(pcs::is_punctuation(wch), pcs::CppWString(wch).ispunctuation()); } } TEST_METHOD(isspace) { - Assert::IsFalse(CppString().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(CppWString().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); @@ -3009,14 +3013,14 @@ namespace cppstringstests TEST_METHOD(isupper) { - Assert::IsFalse(CppString().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(CppWString().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); @@ -3026,14 +3030,14 @@ namespace cppstringstests TEST_METHOD(is_words_sep) { - Assert::IsFalse(CppString().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(CppWString().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); @@ -3044,40 +3048,41 @@ namespace cppstringstests TEST_METHOD(join) { pcs::CppString s("##"); - std::array arr{ "abcd", "efg" }; + 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()); + 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" }; + 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()); + 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" }; + 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" }; + 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::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()); + 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) @@ -3129,10 +3134,10 @@ namespace cppstringstests Assert::AreEqual(wchar_t(std::tolower(wch)), pcs::CppWString::lower(wch)); } - CppString s(255, '\0'); + pcs::CppString s(255, '\0'); for (int i : std::views::iota(0, 256)) - s[i] = CppString::value_type(i); - CppString res{ s.lower() }; + 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)); @@ -3142,10 +3147,10 @@ namespace cppstringstests Assert::AreEqual(cs, cr); } - CppWString ws(0xffff, '\0'); + pcs::CppWString ws(0xffff, '\0'); for (int i : std::views::iota(0, 0x1'0000)) - ws[i] = CppWString::value_type(i); - CppWString wres{ ws.lower() }; + 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)); @@ -3159,29 +3164,30 @@ namespace cppstringstests 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()); + 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()); + 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) @@ -3189,73 +3195,73 @@ namespace cppstringstests pcs::CppString text("AbcdefGhijklm"); int text_size{ int(text.size()) }; - Assert::AreEqual(text(0, text_size).c_str(), text(Slice()).c_str()); + 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(StartSlice(0)).c_str()); - Assert::AreEqual(text.c_str(), text(StopSlice(123)).c_str()); - Assert::AreEqual(text.c_str(), text(StepSlice(1)).c_str()); - Assert::AreEqual(text.c_str(), text(StartStopSlice(0, 111)).c_str()); - Assert::AreEqual(text.c_str(), text(StartStepSlice(0, 1)).c_str()); - Assert::AreEqual(text.c_str(), text(StopStepSlice(text_size, 1)).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(Slice(0, text_size + 2, 2)).c_str()); - Assert::AreEqual("behk", text(Slice(1, text_size, 3)).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(Slice(5, 4, 1)).c_str()); - Assert::AreEqual("", text(Slice(text_size, text_size + 1, 1)).c_str()); - Assert::AreEqual("", text(Slice(text_size + 2, text_size + 5, 1)).c_str()); - Assert::AreEqual("", text(Slice(5, 3, 2)).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(StartStepSlice(text_size, -1)).c_str()); - Assert::AreEqual(reversed_text.c_str(), text(StopStepSlice(0, -1)).c_str()); - Assert::AreEqual(reversed_text.c_str(), text(StepSlice(-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(Slice(text_size, 0, -2)).c_str()); - Assert::AreEqual("mjGd", text(Slice(text_size-1, 1, -3)).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(Slice(4, 5, -1)).c_str()); - Assert::AreEqual("", text(Slice(text_size + 1, text_size, -1)).c_str()); - Assert::AreEqual("", text(Slice(text_size + 5, text_size + 2, -1)).c_str()); - Assert::AreEqual("", text(Slice(3, 5, -2)).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(Slice()).c_str()); + 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(StartSlice(0)).c_str()); - Assert::AreEqual(wtext.c_str(), wtext(StopSlice(123)).c_str()); - Assert::AreEqual(wtext.c_str(), wtext(StepSlice(1)).c_str()); - Assert::AreEqual(wtext.c_str(), wtext(StartStopSlice(0, 111)).c_str()); - Assert::AreEqual(wtext.c_str(), wtext(StartStepSlice(0, 1)).c_str()); - Assert::AreEqual(wtext.c_str(), wtext(StopStepSlice(text_size, 1)).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(Slice(0, text_size + 2, 2)).c_str()); - Assert::AreEqual(L"behk", wtext(Slice(1, text_size, 3)).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(Slice(5, 4, 1)).c_str()); - Assert::AreEqual(L"", wtext(Slice(text_size, text_size + 1, 1)).c_str()); - Assert::AreEqual(L"", wtext(Slice(text_size + 2, text_size + 5, 1)).c_str()); - Assert::AreEqual(L"", wtext(Slice(5, 3, 2)).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(StartStepSlice(text_size, -1)).c_str()); - Assert::AreEqual(wreversed_text.c_str(), wtext(StopStepSlice(0, -1)).c_str()); - Assert::AreEqual(wreversed_text.c_str(), wtext(StepSlice(-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(Slice(text_size, 0, -2)).c_str()); - Assert::AreEqual(L"mjGd", wtext(Slice(text_size - 1, 1, -3)).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(Slice(4, 5, -1)).c_str()); - Assert::AreEqual(L"", wtext(Slice(text_size + 1, text_size, -1)).c_str()); - Assert::AreEqual(L"", wtext(Slice(text_size + 5, text_size + 2, -1)).c_str()); - Assert::AreEqual(L"", wtext(Slice(3, 5, -2)).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) @@ -3278,7 +3284,7 @@ namespace cppstringstests TEST_METHOD(partition) { pcs::CppString s("abcd#123efg"); - std::vector res{ s.partition("#123") }; + 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()); @@ -3294,13 +3300,14 @@ namespace cppstringstests Assert::AreEqual("", res[1].c_str()); Assert::AreEqual("", res[2].c_str()); - res = ""cs.partition("A"); + 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") }; + 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()); @@ -3316,7 +3323,7 @@ namespace cppstringstests Assert::AreEqual(L"", wres[1].c_str()); Assert::AreEqual(L"", wres[2].c_str()); - wres = L""cs.partition(L"A"); + 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()); @@ -3324,36 +3331,38 @@ namespace cppstringstests 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()); + 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()); + 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()); + 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()); + 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) @@ -3414,7 +3423,7 @@ namespace cppstringstests else Assert::AreEqual(found_pos, test_str.rfind(ch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); - CppString s(ch); + 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) @@ -3466,7 +3475,7 @@ namespace cppstringstests else Assert::AreEqual(found_pos, wtest.rfind(wch, 2, pcs::CppString::size_type(5 + 2 - 1)) - 2); - CppWString ws(wch); + pcs::CppWString ws(wch); Assert::AreEqual(wtest.MyBaseClass::rfind(ws), wtest.rfind(ws)); found_pos = wtest.substr(2).MyBaseClass::rfind(ws); @@ -3525,7 +3534,7 @@ namespace cppstringstests else Assert::AreEqual(found_pos, test_str.rfind_n(ch, 2, pcs::CppString::size_type(5)) - 2); - CppString s(ch); + 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) @@ -3580,7 +3589,7 @@ namespace cppstringstests else Assert::AreEqual(found_pos, wtest.rfind_n(wch, 2, pcs::CppString::size_type(5)) - 2); - CppWString ws(wch); + 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) @@ -3787,7 +3796,7 @@ namespace cppstringstests } catch (const string_type::NotFoundException e) { /* ok case! */ } - CppString s(ch); + 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'; @@ -3897,7 +3906,7 @@ namespace cppstringstests TEST_METHOD(rpartition) { pcs::CppString s("abcd#123efg#123hij"); - std::vector res{ s.rpartition("#123") }; + 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()); @@ -3913,13 +3922,14 @@ namespace cppstringstests Assert::AreEqual("", res[1].c_str()); Assert::AreEqual("", res[2].c_str()); - res = ""cs.rpartition("A"); + 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") }; + 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()); @@ -3935,7 +3945,7 @@ namespace cppstringstests Assert::AreEqual(L"", wres[1].c_str()); Assert::AreEqual(L"", wres[2].c_str()); - wres = L""cs.rpartition(L"A"); + 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()); @@ -3944,7 +3954,7 @@ namespace cppstringstests TEST_METHOD(rsplit) { pcs::CppString s(" abcd efg hij klmn "); - std::vector res{ s.rsplit() }; + 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()); @@ -4051,7 +4061,7 @@ namespace cppstringstests Assert::AreEqual("", res[7].c_str()); Assert::AreEqual("", res[8].c_str()); - s = pcs::CppString(5, ' '); //" "cs; + s = pcs::CppString(5, ' '); //" "_cs; res = s.rsplit(); Assert::AreEqual(pcs::CppString::size_type(6), res.size()); Assert::AreEqual("", res[0].c_str()); @@ -4062,7 +4072,8 @@ namespace cppstringstests Assert::AreEqual("", res[5].c_str()); - s = " abcd#123efg#123hij #123#123klmn "cs; + 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()); @@ -4071,7 +4082,7 @@ namespace cppstringstests Assert::AreEqual("", res[3].c_str()); Assert::AreEqual("klmn ", res[4].c_str()); - s = "#123#123abcd#123123efg#123hij #123#123klmn #123#123"cs; + 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()); @@ -4178,7 +4189,7 @@ namespace cppstringstests pcs::CppWString ws(L" abcd efg hij klmn "); - std::vector wres{ ws.rsplit() }; + 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()); @@ -4285,7 +4296,7 @@ namespace cppstringstests Assert::AreEqual(L"", wres[7].c_str()); Assert::AreEqual(L"", wres[8].c_str()); - ws = pcs::CppWString(5, ' '); //L" "cs; + 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()); @@ -4295,7 +4306,7 @@ namespace cppstringstests Assert::AreEqual(L"", wres[4].c_str()); Assert::AreEqual(L"", wres[5].c_str()); - ws = L" abcd#123efg#123hij #123#123klmn "cs; + 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()); @@ -4304,7 +4315,7 @@ namespace cppstringstests 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; + 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()); @@ -4416,23 +4427,24 @@ namespace cppstringstests pcs::CppString sres{ s.rstrip() }; Assert::AreEqual(" abcd efg", sres.c_str()); - s = " abcd efg hij"cs; + using namespace pcs; + s = " abcd efg hij"_cs; sres = s.rstrip(); Assert::AreEqual(" abcd efg hij", sres.c_str()); - s = ""cs; + s = ""_cs; sres = s.rstrip(); Assert::AreEqual("", sres.c_str()); - s = " "cs; + s = " "_cs; sres = s.rstrip(); Assert::AreEqual("", sres.c_str()); - s = "#124abcd#124efg#1241#24#142"cs; + s = "#124abcd#124efg#1241#24#142"_cs; sres = s.rstrip("#124"); Assert::AreEqual("#124abcd#124efg", sres.c_str()); - s = "#124abcd#124efg#124#124hij"cs; + s = "#124abcd#124efg#124#124hij"_cs; sres = s.rstrip("#124"); Assert::AreEqual("#124abcd#124efg#124#124hij", sres.c_str()); @@ -4444,23 +4456,23 @@ namespace cppstringstests pcs::CppWString wsres{ ws.rstrip() }; Assert::AreEqual(L" abcd efg", wsres.c_str()); - ws = L" abcd efg hij"cs; + ws = L" abcd efg hij"_cs; wsres = ws.rstrip(); Assert::AreEqual(L" abcd efg hij", wsres.c_str()); - ws = L""cs; + ws = L""_cs; wsres = ws.rstrip(); Assert::AreEqual(L"", wsres.c_str()); - ws = L" "cs; + ws = L" "_cs; wsres = ws.rstrip(); Assert::AreEqual(L"", wsres.c_str()); - ws = L"#124abcd#124efg#124#124#124"cs; + 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; + ws = L"#124abcd#124efg#124#124hij"_cs; wsres = ws.rstrip(L"#124"); Assert::AreEqual(L"#124abcd#124efg#124#124hij", wsres.c_str()); @@ -4472,7 +4484,7 @@ namespace cppstringstests TEST_METHOD(split) { pcs::CppString s(" abcd efg hij klmn "); - std::vector res{ s.rsplit() }; + 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()); @@ -4590,7 +4602,8 @@ namespace cppstringstests Assert::AreEqual("", res[5].c_str()); - s = " abcd#124efg#124hij #124#124klmn "cs; + 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()); @@ -4598,7 +4611,7 @@ namespace cppstringstests Assert::AreEqual("", res[3].c_str()); Assert::AreEqual("klmn ", res[4].c_str()); - s = "#124#124abcd#124124efg#124hij #124#124klmn #124#124"cs; + 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()); @@ -4705,7 +4718,7 @@ namespace cppstringstests pcs::CppWString ws(L" abcd efg hij klmn "); - std::vector wres{ ws.split() }; + 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()); @@ -4813,7 +4826,7 @@ namespace cppstringstests Assert::AreEqual(L"", wres[7].c_str()); Assert::AreEqual(L"", wres[8].c_str()); - ws = pcs::CppWString(5, ' '); //L" "cs; + 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()); @@ -4823,7 +4836,7 @@ namespace cppstringstests Assert::AreEqual(L"", wres[4].c_str()); Assert::AreEqual(L"", wres[5].c_str()); - ws = L" abcd#124efg#124hij #124#124klmn "cs; + 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()); @@ -4831,7 +4844,7 @@ namespace cppstringstests 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; + 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()); @@ -4941,9 +4954,9 @@ namespace cppstringstests #pragma warning(push) #pragma warning(disable: 4566) // to get no warning when current page code is not compatible with next unicode points { - 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", "." }; + 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) { @@ -4954,9 +4967,9 @@ namespace cppstringstests } { - 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", "." }; + 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) { @@ -4967,9 +4980,9 @@ namespace cppstringstests } { - 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", ".", "" }; + 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) { @@ -4980,9 +4993,9 @@ namespace cppstringstests } { - 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{ + 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" }; @@ -4996,9 +5009,9 @@ namespace cppstringstests } { - 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{ + 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" }; @@ -5012,9 +5025,9 @@ namespace cppstringstests } { - 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{ + 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" }; @@ -5029,9 +5042,9 @@ namespace cppstringstests { - 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"."}; + 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) { @@ -5042,9 +5055,9 @@ namespace cppstringstests } { - 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"."}; + 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) { @@ -5055,9 +5068,9 @@ namespace cppstringstests } { - 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""}; + 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) { @@ -5068,9 +5081,9 @@ namespace cppstringstests } { - 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{ + 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" }; @@ -5084,9 +5097,9 @@ namespace cppstringstests } { - 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{ + 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" }; @@ -5100,9 +5113,9 @@ namespace cppstringstests } { - 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{ + 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" }; @@ -5121,7 +5134,7 @@ namespace cppstringstests TEST_METHOD(startswith) { - CppString text("Abcdef"); + pcs::CppString text("Abcdef"); const size_t len{ text.size() }; Assert::IsTrue(text.startswith("A")); @@ -5181,7 +5194,7 @@ namespace cppstringstests Assert::IsFalse(text.startswith({ "def", "ghi", "Abcd" }, 0, len - 4)); - CppWString wtext(L"Abcdef"); + pcs::CppWString wtext(L"Abcdef"); Assert::IsTrue(wtext.startswith(L"A")); Assert::IsTrue(wtext.startswith(L"Ab")); @@ -5242,7 +5255,7 @@ namespace cppstringstests TEST_METHOD(startswith_n) { - CppString text("Abcdef"); + pcs::CppString text("Abcdef"); const size_t len{ text.size() }; Assert::IsTrue(text.startswith_n("A", 2)); @@ -5302,7 +5315,7 @@ namespace cppstringstests Assert::IsFalse(text.startswith_n({ "def", "ghi", "Abcd" }, 0, len - 4)); - CppWString wtext(L"Abcdef"); + pcs::CppWString wtext(L"Abcdef"); const size_t wlen{ wtext.size() }; Assert::IsTrue(wtext.startswith_n(L"A", 2)); @@ -5364,7 +5377,7 @@ namespace cppstringstests TEST_METHOD(strip) { - CppString text("abcdefedcbaea"); + pcs::CppString text("abcdefedcbaea"); Assert::AreEqual("bcdefedcbae", text.strip("a").c_str()); Assert::AreEqual("cdefedcbae", text.strip("ba").c_str()); @@ -5376,7 +5389,7 @@ namespace cppstringstests Assert::AreEqual("abcdefedcbaea", text.strip("ghijZ").c_str()); Assert::AreEqual("abcdefedcbaea", text.strip("ABc").c_str()); - CppWString wtext(L"abcdefedcbaea"); + 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()); @@ -5391,7 +5404,7 @@ namespace cppstringstests TEST_METHOD(substr) { - CppString text("AbcDefGhi"); + pcs::CppString text("AbcDefGhi"); Assert::AreEqual("AbcDefGhi", text.substr(0, 9).c_str()); Assert::AreEqual("bcDefGhi", text.substr(1, 8).c_str()); @@ -5429,7 +5442,7 @@ namespace cppstringstests Assert::AreEqual("", text.substr(10, 15).c_str()); Assert::AreEqual("", text.substr(21).c_str()); - CppWString wtext(L"AbcDefGhi"); + 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()); @@ -5470,10 +5483,10 @@ namespace cppstringstests TEST_METHOD(swapcase) { - CppString s(255, '\0'); + pcs::CppString s(255, '\0'); for (int i : std::views::iota(0, 256)) - s[i] = CppString::value_type(i); - CppString res{ s.swapcase() }; + 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)); @@ -5483,10 +5496,10 @@ namespace cppstringstests Assert::AreEqual(s, r); } - CppWString ws(0xffff, '\0'); + pcs::CppWString ws(0xffff, '\0'); for (int i : std::views::iota(0, 0x1'0000)) - ws[i] = CppWString::value_type(i); - CppWString wres{ ws.swapcase() }; + 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)); @@ -5499,28 +5512,28 @@ namespace cppstringstests TEST_METHOD(title) { - CppString text("to bE TiTlEd - cheCKing,errors, in Case oF aNy fOUNd"); - CppString expected("To Be Titled - Checking,errors, In Case Of Any Found"); - CppString res{ text.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()); - CppWString wtext(L"to bE TiTlEd - cheCKing,errors, in Case oF aNy fOUNd\u2026\x86"); - CppWString wexpected(L"To Be Titled - Checking,errors, In Case Of Any Found\u2026\x86"); - CppWString wres{ wtext.title() }; + 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) { - CppString::TransTable trans_table("oizeaslbgOIZEASLG", "012345789012345789"); - CppString text("This is a big 'Oiseau' that can be seen in 'Le Zoo'"); - CppString expected("Th15 15 4 819 '01534u' th4t c4n 83 533n 1n '73 200'"); + 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()); - CppWString::TransTable wtrans_table(L"oizeaslbgOIZEASLG", L"012345789012345789"); - CppWString wtext(L"This is a big 'Oiseau' that can be seen in 'Le Zoo'"); - CppWString wexpected(L"Th15 15 4 819 '01534u' th4t c4n 83 533n 1n '73 200'"); + 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()); } @@ -5546,10 +5559,10 @@ namespace cppstringstests Assert::AreEqual(wchar_t(std::toupper(wch)), pcs::CppWString::upper(wch)); } - CppString s(255, '\0'); + pcs::CppString s(255, '\0'); for (int i : std::views::iota(0, 256)) - s[i] = CppString::value_type(i); - CppString res{ s.upper() }; + 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)); @@ -5559,10 +5572,10 @@ namespace cppstringstests Assert::AreEqual(cs, cr); } - CppWString ws(0xffff, '\0'); + pcs::CppWString ws(0xffff, '\0'); for (int i : std::views::iota(0, 0x1'0000)) - ws[i] = CppWString::value_type(i); - CppWString wres{ ws.upper() }; + 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)); @@ -5576,7 +5589,7 @@ namespace cppstringstests TEST_METHOD(zfill) { - CppString s("1.23"); + 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()); @@ -5616,7 +5629,7 @@ namespace cppstringstests Assert::AreEqual("00*1.23", s.zfill(7).c_str()); - CppWString ws(L"1.23"); + 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()); diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index 3c330f7..a25554c 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -29,8 +29,8 @@ using namespace pcs; */ int main() { - CppString s = "-5.1"cs; - CppWString ws{ L"-5.2"cs }; + CppString s = "-5.1"_cs; + CppWString ws{ L"-5.2"_cs }; std::cout << ws.isupper() << std::endl; std::cout << s.zfill(10).c_str() << std::endl; diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 678c9c4..729994f 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -36,13 +36,9 @@ #include + namespace pcs // i.e. "pythonic c++ strings" { -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4455) // to avoid boring warnings with litteral operators definitions -#endif - //============================================================= // Forward declarations @@ -58,6 +54,16 @@ namespace pcs // i.e. "pythonic c++ strings" 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 @@ -88,11 +94,6 @@ namespace pcs // i.e. "pythonic c++ strings" struct StopStepSlice; //!< struct of slices with default start values - // 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. - - // 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. @@ -1825,6 +1826,20 @@ namespace pcs // i.e. "pythonic c++ strings" }; + //===== 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. */ @@ -2037,20 +2052,6 @@ namespace pcs // i.e. "pythonic c++ strings" }; - //===== 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)); - } - - //===== templated chars classes =========================== //--- is_alpha() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ @@ -2345,9 +2346,8 @@ namespace pcs // i.e. "pythonic c++ strings" 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) \ No newline at end of file +} // end of namespace pcs // (pythonic c++ strings) From b9ae59c5fa52bf20f51a3b1327a4deae3c11e9d2 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 00:03:50 +0200 Subject: [PATCH 134/137] #206-fix missing \briefs in doxygen strings Completed. Validated. --- cpp-strings/cppstrings.h | 70 ++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 729994f..f860cbf 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -501,7 +501,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- contains_n() ------------------------------------ - /** Returns true if the passed string is found within the slice str[start:start+count-1], or false otherwise. + /** \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. */ @@ -553,25 +553,25 @@ namespace pcs // i.e. "pythonic c++ strings" //--- endswith() -------------------------------------- - /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops at end position. */ + /** \brief Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops at end position. */ 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); } - /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start of string and stops at end position. */ + /** \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. */ inline const bool endswith(const CppStringT& suffix, const size_type end) const noexcept { return this->substr(0, end).MyBaseClass::ends_with(suffix); } - /** Returns true if the string ends with the specified suffix, otherwise returns false. Test runs on the whole string. */ + /** \brief Returns true if the string ends with the specified suffix, otherwise returns false. Test runs on the whole string. */ inline const bool endswith(const CppStringT& suffix) const noexcept { return static_cast(MyBaseClass::ends_with(suffix)); } - /** 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. */ + /** \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. */ const bool endswith(const std::initializer_list& suffixes, const size_type start, const size_type end) const noexcept { if (start > end) @@ -587,19 +587,19 @@ namespace pcs // i.e. "pythonic c++ strings" //--- endswith_n() ------------------------------------ - /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions. */ + /** \brief Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions. */ 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); } - /** Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions. */ + /** \brief Returns true if the string ends with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions. */ inline const bool endswith_n(const CppStringT& suffix, const size_type count) const noexcept { return endswith(suffix, 0, count - 1); } - /** 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. */ + /** \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. */ 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); @@ -607,7 +607,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- expand_tabs() ----------------------------------- - /** 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. */ + /** \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. */ CppStringT expand_tabs(const size_type tabsize = 8) const noexcept { const size_type tabsize_{ tabsize == 0 ? 1 : tabsize }; @@ -636,7 +636,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- find() ------------------------------------------ - /** 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. + /** \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(). @@ -659,7 +659,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- find_n() ---------------------------------------- - /** 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. + /** \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(). @@ -686,7 +686,7 @@ namespace pcs // i.e. "pythonic c++ strings" } } - /** 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. + /** \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(). @@ -705,7 +705,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- format() ---------------------------------------- - /** Formats this string according to c++20 std::format() specification. Returns this string. */ + /** \brief Formats this string according to c++20 std::format() specification. Returns this string. */ template inline CppStringT& format( const std::basic_format_string...> frmt, @@ -735,7 +735,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- index() ----------------------------------------- - /** Like find(const CppStringT&), but raises NotFoundException when the substring sub is not found. + /** \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(). @@ -751,7 +751,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- index_n() --------------------------------------- - /** Like find_n(sub, start, count), but raises NotFoundException when the substring is not found. + /** \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(). @@ -761,7 +761,7 @@ namespace pcs // i.e. "pythonic c++ strings" return index(sub, start, start + count - 1); } - /** Like find_n(sub, count), but raises NotFoundException when the substring is not found. + /** \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(). @@ -1139,7 +1139,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- partition() ------------------------------------- - /** 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. + /** \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. @@ -1209,7 +1209,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- rfind() ----------------------------------------- - /** 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. + /** \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. * @@ -1236,7 +1236,7 @@ namespace pcs // i.e. "pythonic c++ strings" } - /** 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. + /** \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. * @@ -1256,7 +1256,7 @@ namespace pcs // i.e. "pythonic c++ strings" } - /** 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. + /** \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. * @@ -1277,7 +1277,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- rfind_n() --------------------------------------- - /** 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. + /** \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(). @@ -1290,7 +1290,7 @@ namespace pcs // i.e. "pythonic c++ strings" return rfind(sub, start, start + count - 1); } - /** 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. + /** \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(). @@ -1308,7 +1308,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- rindex() ---------------------------------------- - /** Like rfind(sub, start, end), but raises NotFoundException when the substring is not found. + /** \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(). @@ -1322,7 +1322,7 @@ namespace pcs // i.e. "pythonic c++ strings" return ret_value; } - /** Like rfind(sub, start), but raises NotFoundException when the substring is not found. + /** \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(). @@ -1332,7 +1332,7 @@ namespace pcs // i.e. "pythonic c++ strings" return rindex(sub, start, this->size() - 1); } - /** Like rfind(sub), but raises NotFoundException when the substring is not found. + /** \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(). @@ -1344,7 +1344,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- rindex_n() -------------------------------------- - /** Like rfind_n(sub, start, count), but raises NotFoundException when the substring is not found. + /** \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(). @@ -1354,7 +1354,7 @@ namespace pcs // i.e. "pythonic c++ strings" return rindex(sub, start, start + count - 1); } - /** Like rfind_n(sub, count), but raises NotFoundException when the substring is not found. + /** \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(). @@ -1381,7 +1381,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- rpartition() ------------------------------------- - /** 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. + /** \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. @@ -1650,25 +1650,25 @@ namespace pcs // i.e. "pythonic c++ strings" //--- startswith() ------------------------------------ - /** Returns true if the string starts with the specified prefix, otherwise returns false. Test begins at start position and stops at end position. */ + /** \brief Returns true if the string starts with the specified prefix, otherwise returns false. Test begins at start position and stops at end position. */ 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); } - /** Returns true if the string starts with the specified prefix, otherwise returns false. Test begins at start position and stops at end of string. */ + /** \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. */ inline const bool startswith(const CppStringT& prefix, const size_type start) const noexcept { return startswith(prefix, start, this->size() - 1); } - /** Returns true if the string starts with the specified prefix, otherwise returns false. Test runs on the whole string. */ + /** \brief Returns true if the string starts with the specified prefix, otherwise returns false. Test runs on the whole string. */ inline const bool startswith(const CppStringT& prefix) const noexcept { return this->starts_with(prefix); } - /** 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. */ + /** \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. */ inline const bool startswith(const std::initializer_list& prefixes, const size_type start, const size_type end) const noexcept { if (start > end) @@ -1684,19 +1684,19 @@ namespace pcs // i.e. "pythonic c++ strings" //--- startswith_n() ---------------------------------- - /** Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions. */ + /** \brief Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at start position and stops after count positions. */ 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); } - /** Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions. */ + /** \brief Returns true if the string starts with the specified suffix, otherwise returns false. Test begins at position 0 and stops after count positions. */ inline const bool startswith_n(const CppStringT& prefix, const size_type count) const noexcept { return this->substr(0, count).MyBaseClass::starts_with(prefix); } - /** 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. */ + /** \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. */ 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); From 2ee75463513f229bbc5ad83cd672508064ccf039 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 00:26:55 +0200 Subject: [PATCH 135/137] #212-add attribute [[nodiscard]] at any useful place Completed. Validated. --- cpp-strings/cppstrings.h | 133 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index f860cbf..5bf55a2 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -3,7 +3,7 @@ Library cppstrings "What if c++ strings where as easy to use as Python strings?" - Copyright (C) 2023 Philippe Schmouker + 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 @@ -361,6 +361,7 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \brief Indexing operator. */ + [[nodiscard]] inline value_type operator[] (const key_type ch) noexcept { auto it = m_table.find(ch); @@ -457,6 +458,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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() }; @@ -473,6 +475,7 @@ namespace pcs // i.e. "pythonic c++ strings" * * This is a c++ implementation of Python keyword 'in' applied to strings. */ + [[nodiscard]] constexpr bool contains(const CppStringT& substr) const noexcept { if (substr.empty()) @@ -505,6 +508,7 @@ namespace pcs // i.e. "pythonic c++ strings" * * 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 { @@ -518,6 +522,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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; @@ -540,12 +545,14 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -554,24 +561,28 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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) @@ -588,18 +599,21 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -608,6 +622,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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 }; @@ -647,6 +662,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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 }; @@ -671,6 +687,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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 }; @@ -698,6 +715,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -712,7 +730,7 @@ namespace pcs // i.e. "pythonic c++ strings" ArgsT&&... args ) { - return CppStringT(); + return *this; } template @@ -740,6 +758,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -756,6 +775,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -766,6 +786,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -774,6 +795,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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()) @@ -785,6 +807,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -796,6 +819,7 @@ namespace pcs // i.e. "pythonic c++ strings" #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); @@ -809,6 +833,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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); @@ -829,6 +854,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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(); @@ -855,6 +881,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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)); @@ -863,6 +890,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -879,6 +907,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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(); @@ -892,6 +921,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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); @@ -900,6 +930,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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]); @@ -908,6 +939,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -924,6 +956,7 @@ namespace pcs // i.e. "pythonic c++ strings" * characters following whitespaces and lowercase characters * anywhere else. */ + [[nodiscard]] inline const bool istitle() const noexcept { return !this->empty() && this->title() == *this; @@ -932,6 +965,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -940,6 +974,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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(), @@ -953,6 +988,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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()) @@ -969,6 +1005,7 @@ namespace pcs // i.e. "pythonic c++ strings" * * 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()) @@ -986,6 +1023,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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) { @@ -993,12 +1031,14 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \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; @@ -1011,6 +1051,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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) @@ -1040,6 +1081,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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)); @@ -1054,6 +1096,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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) @@ -1063,6 +1106,7 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \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) @@ -1086,6 +1130,7 @@ namespace pcs // i.e. "pythonic c++ strings" */ template requires std::is_signed_v + [[nodiscard]] CppStringT operator() (Slice slice) const noexcept { // optimization on 1 by 1 step @@ -1117,6 +1162,7 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \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); @@ -1126,6 +1172,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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) @@ -1144,6 +1191,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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); @@ -1161,6 +1209,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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)) { @@ -1174,6 +1223,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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)) { @@ -1187,6 +1237,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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()) @@ -1223,6 +1274,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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) @@ -1250,6 +1302,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -1270,6 +1323,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -1285,6 +1339,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -1298,6 +1353,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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) @@ -1313,6 +1369,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -1327,6 +1384,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -1337,6 +1395,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -1349,6 +1408,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -1359,6 +1419,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \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); @@ -1371,6 +1432,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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) @@ -1386,6 +1448,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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); @@ -1407,24 +1470,28 @@ namespace pcs // i.e. "pythonic c++ 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{}; @@ -1471,6 +1538,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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) @@ -1480,6 +1548,7 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \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) @@ -1495,6 +1564,7 @@ namespace pcs // i.e. "pythonic c++ 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; @@ -1513,6 +1583,7 @@ namespace pcs // i.e. "pythonic c++ strings" * "3"]). Splitting an empty string with a specified separator * returns {""}. */ + [[nodiscard]] inline std::vector split(const CppStringT& sep) noexcept { std::vector res; @@ -1522,12 +1593,14 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \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{}; @@ -1584,6 +1657,7 @@ namespace pcs // i.e. "pythonic c++ strings" * \u2028 Line Separator * \u2029 Paragraph Separator */ + [[nodiscard]] std::vector splitlines(const bool keep_end = false) const noexcept { std::vector res{}; @@ -1651,24 +1725,28 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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) @@ -1685,18 +1763,21 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -1710,12 +1791,14 @@ namespace pcs // i.e. "pythonic c++ strings" * 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(); @@ -1724,6 +1807,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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()) @@ -1738,6 +1822,7 @@ namespace pcs // i.e. "pythonic c++ strings" * * Note that it is not necessarily true that s.swapcase().swapcase() == s. */ + [[nodiscard]] inline CppStringT swapcase() const noexcept { CppStringT res; @@ -1748,6 +1833,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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(' ')); @@ -1769,6 +1855,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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{}; @@ -1798,6 +1885,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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)); @@ -1811,6 +1899,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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) @@ -1872,6 +1961,7 @@ namespace pcs // i.e. "pythonic c++ strings" 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; @@ -1889,6 +1979,7 @@ namespace pcs // i.e. "pythonic c++ strings" return *this; } + [[nodiscard]] inline const IntT operator*() noexcept //!< dereferences the slice. { return _index; @@ -1907,6 +1998,7 @@ namespace pcs // i.e. "pythonic c++ strings" IntT _index{ 0 }; + [[nodiscard]] const IntT _prepare_iterating(const IntT str_size) noexcept { if (_start == DEFAULT) { @@ -2056,6 +2148,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- is_alpha() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template + [[nodiscard]] inline const bool is_alpha(const CharT ch) noexcept { return false; @@ -2063,6 +2156,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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))); @@ -2070,6 +2164,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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)); @@ -2079,6 +2174,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -2088,6 +2184,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- is_decimal() ---------------------------------------- /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template + [[nodiscard]] inline const bool is_decimal(const CharT ch) noexcept { return false; @@ -2095,6 +2192,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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))); @@ -2102,6 +2200,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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); @@ -2111,6 +2210,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -2118,6 +2218,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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); @@ -2125,6 +2226,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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); @@ -2134,6 +2236,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -2143,6 +2246,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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('_'); @@ -2152,6 +2256,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- is_lower() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template + [[nodiscard]] inline const bool is_lower(const CharT ch) noexcept { return false; @@ -2159,6 +2264,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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)); @@ -2166,6 +2272,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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); @@ -2175,6 +2282,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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); @@ -2182,6 +2290,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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); @@ -2189,6 +2298,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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); @@ -2198,6 +2308,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- is_printable() -------------------------------------- /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template + [[nodiscard]] inline const bool is_printable(const CharT ch) noexcept { return false; @@ -2205,6 +2316,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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))); @@ -2212,6 +2324,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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)); @@ -2221,6 +2334,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- is_punctuation() ------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template + [[nodiscard]] inline const bool is_punctuation(const CharT ch) noexcept { return false; @@ -2228,6 +2342,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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))); @@ -2235,6 +2350,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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)); @@ -2244,6 +2360,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- is_space() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template + [[nodiscard]] inline const bool is_space(const CharT ch) noexcept { return false; @@ -2251,6 +2368,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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))); @@ -2258,6 +2376,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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)); @@ -2267,6 +2386,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- is_upper() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template + [[nodiscard]] inline const bool is_upper(const CharT ch) noexcept { return false; @@ -2274,6 +2394,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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))); @@ -2281,6 +2402,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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)); @@ -2290,6 +2412,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- 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)) @@ -2304,6 +2427,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- to_lower() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template + [[nodiscard]] inline const CharT to_lower(const CharT ch) noexcept { return ch; @@ -2311,6 +2435,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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)); @@ -2318,6 +2443,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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); @@ -2327,6 +2453,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- to_upper() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template + [[nodiscard]] inline const CharT to_upper(const CharT ch) noexcept { return ch; @@ -2334,6 +2461,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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)); @@ -2341,6 +2469,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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); From 2348d3c0ef28418813a3d65899a8ceffa5516e88 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 00:28:53 +0200 Subject: [PATCH 136/137] #219-modify copyright dates Done. --- cpp-strings-tests/cpp-strings-tests.cpp | 22 ++++++++++++++++++++++ cpp-strings/cppstrings.cpp | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cpp-strings-tests/cpp-strings-tests.cpp b/cpp-strings-tests/cpp-strings-tests.cpp index bb994c2..e0f3236 100644 --- a/cpp-strings-tests/cpp-strings-tests.cpp +++ b/cpp-strings-tests/cpp-strings-tests.cpp @@ -1,3 +1,25 @@ +/** + 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; diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index a25554c..253031d 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -2,7 +2,7 @@ Library cppstrings "What if c++ strings where as easy to use as Python strings?" - Copyright (C) 2023 Philippe Schmouker + 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 From 19d3913198712ea870932291929e8e55c39419a0 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 07:49:09 +0200 Subject: [PATCH 137/137] #213-add attribute [[likely]] and [[unlikely]] Completed. Validated. --- cpp-strings/cppstrings.h | 167 +++++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 78 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 5bf55a2..e368f9f 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -365,10 +365,10 @@ namespace pcs // i.e. "pythonic c++ strings" inline value_type operator[] (const key_type ch) noexcept { auto it = m_table.find(ch); - if (it != m_table.end()) { + if (it != m_table.end()) [[likely]] { return it->second; } - else { + else [[unlikely]] { return ch; } } @@ -443,7 +443,7 @@ namespace pcs // i.e. "pythonic c++ strings" inline CppStringT capitalize() noexcept { CppStringT res(*this); - if (!res.empty()) { + if (!res.empty()) [[likely]] { res.lower(); res[0] = pcs::to_upper(res[0]); } @@ -462,7 +462,7 @@ namespace pcs // i.e. "pythonic c++ strings" CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept { const size_type len{ this->size() }; - if (width <= len) + if (width <= len) [[unlikely]] return CppStringT(*this); const size_type half{ (width - len) / 2 }; @@ -478,7 +478,7 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] constexpr bool contains(const CppStringT& substr) const noexcept { - if (substr.empty()) + if (substr.empty()) [[unlikely]] // the empty string is always contained in any string return true; @@ -490,10 +490,10 @@ namespace pcs // i.e. "pythonic c++ strings" const size_type substr_width{ substr.size() }; const size_type width{ this->size() }; - if (substr_width > width) + if (substr_width > width) [[unlikely]] return false; - for (size_type index = 0; index <= width - substr_width; ++index) { + for (size_type index = 0; index <= width - substr_width; ++index) [[likely]] { if (substr == this->substr(index, substr_width)) return true; } @@ -585,12 +585,12 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] const bool endswith(const std::initializer_list& suffixes, const size_type start, const size_type end) const noexcept { - if (start > end) + if (start > end) [[unlikely]] return false; CppStringT tmp(this->substr(start, end - start + 1)); for (auto& suffix : suffixes) { - if (tmp.ends_with(suffix)) + if (tmp.ends_with(suffix)) [[unlikely]] return true; } return false; @@ -630,17 +630,17 @@ namespace pcs // i.e. "pythonic c++ strings" std::size_t current_pos{ 0 }; for (const value_type ch : *this) { - if (ch == value_type('\t')) { + 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')) { + else if (ch == value_type('\n') || ch == value_type('\r')) [[unlikely]] { ret += ch; current_pos = 0; } - else { + else [[likely]] { ret += ch; current_pos++; } @@ -667,9 +667,9 @@ namespace pcs // i.e. "pythonic c++ strings" { const size_type end_{ (end == -1) ? this->size() : end }; - if (start > end_) + if (start > end_) [[unlikely]] return CppStringT::npos; - else + else [[likely]] return find_n(sub, start, end_ - start + 1); } @@ -798,10 +798,14 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] inline const bool isalnum() const noexcept { - if (this->empty()) + if (this->empty()) [[unlikely]] return false; - 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); }); + 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); } + ); } @@ -977,8 +981,12 @@ namespace pcs // i.e. "pythonic c++ strings" [[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); }); + return !this->empty() && + std::all_of( + this->cbegin(), + this->cend(), + [](const value_type ch) { return pcs::is_space(ch) || pcs::is_punctuation(ch); } + ); } @@ -991,12 +999,12 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] CppStringT join(const std::array& strs) const noexcept { - if (strs.empty()) + if (strs.empty()) [[unlikely]] return CppStringT(); auto str_it = strs.cbegin(); CppStringT res{ *str_it++ }; - while (str_it != strs.cend()) + while (str_it != strs.cend()) [[likely]] res += *this + *str_it++; return res; } @@ -1008,12 +1016,12 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] CppStringT join(const std::vector& strs) const noexcept { - if (strs.empty()) + if (strs.empty()) [[unlikely]] return CppStringT(); auto str_it = strs.cbegin(); CppStringT res{ *str_it++ }; - while (str_it != strs.cend()) + while (str_it != strs.cend()) [[likely]] res += *this + *str_it++; return res; } @@ -1054,9 +1062,9 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] inline CppStringT ljust(const size_type width, const value_type fillch = value_type(' ')) const noexcept { - if (this->size() >= width) + if (this->size() >= width) [[unlikely]] return *this; - else + else [[likely]] return CppStringT(width - this->size(), fillch) + *this; } @@ -1069,7 +1077,9 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline CppStringT& lower() noexcept { - std::transform(this->begin(), this->end(), + std::transform( + this->begin(), + this->end(), this->begin(), [&](value_type ch) { return this->lower(ch); } ); @@ -1099,8 +1109,8 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] inline CppStringT lstrip(const CppStringT& removedchars) const noexcept { - for (auto it = this->cbegin(); it != this->cend(); ++it) - if (std::none_of(removedchars.cbegin(), removedchars.cend(), [it](const value_type ch) { return *it == ch; })) + 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(); } @@ -1109,8 +1119,8 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] inline CppStringT lstrip() const noexcept { - for (auto it = this->cbegin(); it != this->cend(); ++it) - if (*it != value_type(' ')) + for (auto it = this->cbegin(); it != this->cend(); ++it) [[likely]] + if (*it != value_type(' ')) [[unlikely]] return CppStringT(it, this->cend()); return CppStringT(); } @@ -1134,11 +1144,11 @@ namespace pcs // i.e. "pythonic c++ strings" CppStringT operator() (Slice slice) const noexcept { // optimization on 1 by 1 step - if (slice.step() == 1) { + if (slice.step() == 1) [[likely]] { slice.begin(*this); - if (slice.start() < slice.stop()) + if (slice.start() < slice.stop()) [[likely]] return this->substr(size_type(slice.start()), size_type(slice.stop() - slice.start() + 1)); - else + else [[unlikely]] return CppStringT(); } @@ -1147,7 +1157,7 @@ namespace pcs // i.e. "pythonic c++ strings" // optimization on reversed 1 by 1 step if (slice.step() == -1) { slice.begin(*this); - if (slice.stop() < slice.start()) { + 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 } @@ -1175,11 +1185,11 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] CppStringT operator* (std::int64_t count) const noexcept { - if (count <= 0) + if (count <= 0) [[unlikely]] return CppStringT(); CppStringT res(*this); - while (--count) + while (--count) [[likely]] res += *this; return res; } @@ -1240,7 +1250,7 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] CppStringT replace(const CppStringT& old, const CppStringT& new_, size_type count = -1) const noexcept { - if (old == new_ || old.empty()) + if (old == new_ || old.empty()) [[unlikely]] return *this; CppStringT res{}; @@ -1252,7 +1262,7 @@ namespace pcs // i.e. "pythonic c++ strings" --count; } - if (prev_index < this->size()) + if (prev_index < this->size()) [[likely]] res += this->substr(prev_index, this->size() - prev_index); return res; @@ -1277,11 +1287,11 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] inline constexpr size_type rfind(const CppStringT& sub, const size_type start, const size_type end) const noexcept { - if (start > end) + if (start > end) [[unlikely]] return CppStringT::npos; - else if (sub.empty()) + else if (sub.empty()) [[unlikely]] return 0; - else { + 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; } @@ -1356,9 +1366,9 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] inline constexpr size_type rfind_n(const CppStringT& sub, const size_type count) const noexcept { - if (count == 0) + if (count == 0) [[unlikely]] return CppStringT::npos; - else + else [[likely]] return rfind(sub, 0, count - 1); } @@ -1435,9 +1445,9 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] inline CppStringT rjust(const size_type width, const value_type fillch = value_type(' ')) const noexcept { - if (this->size() >= width) + if (this->size() >= width) [[unlikely]] return *this; - else + else [[likely]] return *this + CppStringT(width - this->size(), fillch); } @@ -1496,10 +1506,10 @@ namespace pcs // i.e. "pythonic c++ strings" { std::vector res{}; - if (maxsplit == 0) { + if (maxsplit == 0) [[unlikely]] { res.push_back({ *this }); } - else { + else [[likely]] { const size_type sep_size{ sep.size() }; std::vector indexes{}; CppStringT tmp{ *this }; @@ -1605,10 +1615,10 @@ namespace pcs // i.e. "pythonic c++ strings" { std::vector res{}; - if (maxsplit == 0) { + if (maxsplit == 0) [[unlikely]] { res.push_back(*this); } - else { + else [[likely]] { const size_type sep_size{ sep.size() }; std::vector indexes{}; size_type count{ maxsplit }; @@ -1666,37 +1676,37 @@ namespace pcs // i.e. "pythonic c++ strings" for (const value_type ch : *this) { switch (ch) { - case 0x0b: // Line Tabulation, \v as well as \x0b and \013 - case 0x0c: // Form Feed, \f as well as \x0c and \014 - case 0x1c: // File Separator, or \034 - case 0x1d: // Group Separator, or \035 - case 0x1e: // Record Separator, or \036 - //case L'\u0085': // Next Line (C1 Control Code), or \0205 - //case L'\u2028': // Line Separator - //case L'\u2029': // Paragraph Separator - if (prev_cr) { + 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) + if (keep_end) [[unlikely]] current += ch; res.push_back(current); current.clear(); prev_cr = false; break; - case value_type('\r'): // Line Feed - if (prev_cr) { + case value_type('\r'): [[unlikely]] // Line Feed + if (prev_cr) [[unlikely]] { res.push_back(current); current.clear(); } - if (keep_end) + if (keep_end) [[unlikely]] current += ch; prev_cr = true; break; - case value_type('\n'): // Carriage return - if (keep_end) + case value_type('\n'): [[unlikely]] // Carriage return + if (keep_end) [[unlikely]] current += ch; res.push_back(current); current.clear(); @@ -1704,8 +1714,8 @@ namespace pcs // i.e. "pythonic c++ strings" break; - default: - if (prev_cr) { + default: [[likely]] + if (prev_cr) [[unlikely]] { res.push_back(current); current.clear(); prev_cr = false; @@ -1715,7 +1725,7 @@ namespace pcs // i.e. "pythonic c++ strings" } } - if (prev_cr) { + if (prev_cr) [[unlikely]] { res.push_back(current); } @@ -1810,8 +1820,9 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] inline CppStringT substr(const size_type start, const size_type count = -1) const noexcept { - if (start > this->size()) + if (start > this->size()) [[unlikely]] return CppStringT(); + const size_type width{ std::min(count, this->size() - start + 1) }; return CppStringT(MyBaseClass::substr(start, width)); } @@ -1902,13 +1913,13 @@ namespace pcs // i.e. "pythonic c++ strings" [[nodiscard]] inline CppStringT zfill(const size_type width) const noexcept { - if (this->size() >= width) + if (this->size() >= width) [[unlikely]] return *this; const size_type padding_width = width - this->size(); - if ((*this)[0] == '+' || (*this)[0] == '-') + if ((*this)[0] == '-' || (*this)[0] == '+') [[unlikely]] return (*this)[0] + this->substr(1, this->size() - 1).ljust(width - 1, value_type('0')); - else + else [[likely]] return this->ljust(width, value_type('0')); } @@ -2002,14 +2013,14 @@ namespace pcs // i.e. "pythonic c++ strings" const IntT _prepare_iterating(const IntT str_size) noexcept { if (_start == DEFAULT) { - if (_step < 0 && _step != DEFAULT) + if (_step < 0 && _step != DEFAULT) [[unlikely]] _start = str_size - 1; - else + else [[likely]] _start = 0; } else if (_start < 0) { _start += str_size; - if (_start < 0) + if (_start < 0) [[unlikely]] _start = 0; } else if (_start >= str_size) { @@ -2018,7 +2029,7 @@ namespace pcs // i.e. "pythonic c++ strings" } if (_stop == DEFAULT) { - if (_step < 0 && _step != DEFAULT) + if (_step < 0 && _step != DEFAULT) [[unlikely]] _stop = 0; else _stop = str_size; @@ -2031,13 +2042,13 @@ namespace pcs // i.e. "pythonic c++ strings" else if (_stop > str_size) _stop = str_size; - if (_step == DEFAULT) + if (_step == DEFAULT) [[likely]] _step = 1; - if (_step < 0) { + if (_step < 0) [[unlikely]] { if (_start <= _stop) _step = 0; // will force end() to true } - else { + else [[unlikely]] { if (_start >= _stop) _step = 0; // will force end() to true }