From a42832268203ebaf2e025da4812a8542c1f94072 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 7 Mar 2023 14:29:12 +0100 Subject: [PATCH 001/220] #3 - Create Visual Studio 2022 project Completed. --- cpp-strings/cpp-strings.vcxproj | 144 ++++++++++++++++++++++++ cpp-strings/cpp-strings.vcxproj.filters | 27 +++++ cpp-strings/cpp-strings.vcxproj.user | 6 + 3 files changed, 177 insertions(+) create mode 100644 cpp-strings/cpp-strings.vcxproj create mode 100644 cpp-strings/cpp-strings.vcxproj.filters create mode 100644 cpp-strings/cpp-strings.vcxproj.user diff --git a/cpp-strings/cpp-strings.vcxproj b/cpp-strings/cpp-strings.vcxproj new file mode 100644 index 0000000..7fe9606 --- /dev/null +++ b/cpp-strings/cpp-strings.vcxproj @@ -0,0 +1,144 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {520980fd-2242-443e-89db-b8e41d9606b5} + cppstrings + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpplatest + stdc17 + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpplatest + stdc17 + true + + + Console + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/cpp-strings/cpp-strings.vcxproj.filters b/cpp-strings/cpp-strings.vcxproj.filters new file mode 100644 index 0000000..2461996 --- /dev/null +++ b/cpp-strings/cpp-strings.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {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 + + + + + Header Files + + + \ No newline at end of file diff --git a/cpp-strings/cpp-strings.vcxproj.user b/cpp-strings/cpp-strings.vcxproj.user new file mode 100644 index 0000000..966b4ff --- /dev/null +++ b/cpp-strings/cpp-strings.vcxproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file From b3d0cbc6541551be35e526c1dc392f6be6c841d9 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 7 Mar 2023 14:29:42 +0100 Subject: [PATCH 002/220] #2 - Create empty module cppstrings.h. Completed. --- cpp-strings/cppstrings.cpp | 30 ++++++++++++++++++++++++++++++ cpp-strings/cppstrings.h | 23 +++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 cpp-strings/cppstrings.cpp create mode 100644 cpp-strings/cppstrings.h diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp new file mode 100644 index 0000000..3a38c7c --- /dev/null +++ b/cpp-strings/cppstrings.cpp @@ -0,0 +1,30 @@ +/** + Library cppstrings + "What if c++ strings where as easy to use as Python strings?" + + Copyright (C) 2023 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 "cppstrings.h" + +/** +* Notice: this module is for tests and validation purposes only. +*/ +int main() +{ + return 0; +} diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h new file mode 100644 index 0000000..853b526 --- /dev/null +++ b/cpp-strings/cppstrings.h @@ -0,0 +1,23 @@ +#pragma once +/** + Library cppstrings + "What if c++ strings where as easy to use as Python strings?" + + Copyright (C) 2023 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 . +*/ + + From 0b4227dab3c5358bf8d007b632cde013fac75dbc Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 7 Mar 2023 14:30:31 +0100 Subject: [PATCH 003/220] #3 - Create Visual Studio 2022 project Completed. --- cpp-strings/cpp-strings.sln | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 cpp-strings/cpp-strings.sln diff --git a/cpp-strings/cpp-strings.sln b/cpp-strings/cpp-strings.sln new file mode 100644 index 0000000..c5029ce --- /dev/null +++ b/cpp-strings/cpp-strings.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33414.496 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpp-strings", "cpp-strings.vcxproj", "{520980FD-2242-443E-89DB-B8E41D9606B5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {520980FD-2242-443E-89DB-B8E41D9606B5}.Debug|x64.ActiveCfg = Debug|x64 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Debug|x64.Build.0 = Debug|x64 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Debug|x86.ActiveCfg = Debug|Win32 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Debug|x86.Build.0 = Debug|Win32 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Release|x64.ActiveCfg = Release|x64 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Release|x64.Build.0 = Release|x64 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Release|x86.ActiveCfg = Release|Win32 + {520980FD-2242-443E-89DB-B8E41D9606B5}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {ECEA0DAB-2736-4B43-9AEC-7B84A49AFF74} + EndGlobalSection +EndGlobal From 41767dafaeab288f1c97125558455d38eb41cac9 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 7 Mar 2023 14:30:55 +0100 Subject: [PATCH 004/220] #4 - Modify .gitignore Completed. --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 259148f..0455c1a 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ *.exe *.out *.app + +# Visual Studio specifics +.vs +x64 From 5fc27242ec482c79a1ee75bce6a99a2e97b21b4d Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 8 Mar 2023 01:00:26 +0100 Subject: [PATCH 005/220] #6 - Implement specialized class CppString Completed. --- cpp-strings/cppstrings.h | 73 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 853b526..bb17805 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -20,4 +20,77 @@ along with this program. If not, see . */ +//============================================================= +#include +//#include + +//============================================================= +// Forward declarations +template< + class CharT, + class TraitsT = std::char_traits, + class AllocatorT = std::allocator +> class CppStringT; //!< The templated base class. Use its specializations instead! + +using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' +using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' + + +//===== CppStringT<> ====================================== +/** +* \brief This is the templated base class for all CppString +* classes. +* +* Users should instantiate any specialization of this base class +* rather than this base class itself: +* - \see CppString for CppStringT. +* - \see CppWString for CppStringT. +* +* This base class inherits from std::basic_string. As such, +* it gets direct access to all public methods of its base class. +* \see https://en.cppreference.com/w/cpp/string/basic_string for +* a full list of such methods, for instance. +* +* You may specialize it by your own with any of the next char +* types: +* - char8_t (C++20) +* - char16_t (C++11) +* - char32_t (C++11) +*/ +template +class CppStringT : public std::basic_string +{ +public: + //--- Wrappers ---------------------------------------- + using MyBaseClass = std::basic_string; + using size_type = MyBaseClass::size_type; + + //--- Constructors ------------------------------------ + 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) {} + + template + inline CppStringT(InputIt first, InputIt last) : MyBaseClass(first, last) {} + + template + explicit CppStringT(const StringViewLike& svl) : MyBaseClass(svl) {} + + template + CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} + +protected: + + +private: + +}; From f7dd584961497ebd9a32ed32e8d6c245fd89f927 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 8 Mar 2023 01:01:13 +0100 Subject: [PATCH 006/220] #7 - Implement specialized class CppWString Completed. --- cpp-strings/cppstrings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index 3a38c7c..3871000 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -26,5 +26,6 @@ */ int main() { + CppString s; return 0; } From afa16872e3124732370119238434183581a79df3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 8 Mar 2023 01:03:26 +0100 Subject: [PATCH 007/220] #5 - Create templated base class CppStringT<> Created. Dev still in progress. --- cpp-strings/cppstrings.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index bb17805..74f5d79 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -64,7 +64,21 @@ class CppStringT : public std::basic_string public: //--- Wrappers ---------------------------------------- using MyBaseClass = std::basic_string; - using size_type = MyBaseClass::size_type; + + using traits_type = MyBaseClass::traits_type; + using value_type = MyBaseClass::value_type; + using allocator_type = MyBaseClass::allocator_type; + using size_type = MyBaseClass::size_type; + using difference_type = MyBaseClass::difference_type; + using reference = MyBaseClass::reference; + using const_reference = MyBaseClass::const_reference; + using pointer = MyBaseClass::pointer; + using const_pointer = MyBaseClass::const_pointer; + using iterator = MyBaseClass::iterator; + using const_iterator = MyBaseClass::const_iterator; + using reverse_iterator = MyBaseClass::reverse_iterator; + using const_reverse_iterator = MyBaseClass::const_reverse_iterator; + //--- Constructors ------------------------------------ inline CppStringT() : MyBaseClass() {} @@ -88,6 +102,10 @@ class CppStringT : public std::basic_string template CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} + + //--- Methods ----------------------------------------- + + protected: From 266fe347992ac4cc3369ca73eb4c7d80194fe859 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 9 Mar 2023 11:19:42 +0100 Subject: [PATCH 008/220] #60 - Implement method is_punctuation Completed. --- cpp-strings/cppstrings.cpp | 4 +++- cpp-strings/cppstrings.h | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index 3871000..c4cb537 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -26,6 +26,8 @@ */ int main() { - CppString s; + CppString s; + CppWString ws; + return 0; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 74f5d79..0a036ec 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -22,6 +22,7 @@ //============================================================= #include +#include //#include @@ -31,7 +32,7 @@ template< class CharT, class TraitsT = std::char_traits, class AllocatorT = std::allocator -> class CppStringT; //!< The templated base class. Use its specializations instead! +> class CppStringT; //!< The templated base class. Use its belowing specializations instead! using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' @@ -62,7 +63,7 @@ template class CppStringT : public std::basic_string { public: - //--- Wrappers ---------------------------------------- + //=== Wrappers ======================================== using MyBaseClass = std::basic_string; using traits_type = MyBaseClass::traits_type; @@ -80,7 +81,7 @@ class CppStringT : public std::basic_string using const_reverse_iterator = MyBaseClass::const_reverse_iterator; - //--- Constructors ------------------------------------ + //=== Constructors ==================================== inline CppStringT() : MyBaseClass() {} inline CppStringT(const CppStringT& other) : MyBaseClass(other) {} inline CppStringT(const CppStringT& other, const AllocatorT& alloc) : MyBaseClass(other, alloc){} @@ -103,12 +104,21 @@ class CppStringT : public std::basic_string CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} - //--- Methods ----------------------------------------- + //=== Methods ========================================= + + //--- is_punctuation ---------------------------------- + /** \brief Returns true if a character belongs to ASCII punctuation set. */ + inline const bool is_punctuation(const value_type ch) noexcept + { + return _ASCII_PUNCT_DATA.contains(ch); + } protected: private: + //=== DATA ============================================ + static inline constexpr std::vector _ASCII_PUNCT_DATA{ '!', ',', '.', ':', ';', '?' }; }; From 3fd297355608c9742ea1550c0980efb0e1e42ae5 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 9 Mar 2023 14:28:38 +0100 Subject: [PATCH 009/220] #30 - Implement method CppStringT::isspace() Completed. --- cpp-strings/cppstrings.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 0a036ec..34445c5 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -21,6 +21,7 @@ */ //============================================================= +#include #include #include //#include @@ -113,6 +114,23 @@ class CppStringT : public std::basic_string return _ASCII_PUNCT_DATA.contains(ch); } + //--- is_space ---------------------------------------- + /** \brief Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise. + * + * Notice for version 2.0 of this library: a character is whitespace if + * in the Unicode character database, either its general category is Zs + * (“Separator, space”), or its bidirectional class is one of WS, B, or S. + */ + inline const bool is_space(const MyBaseClass& str) noexcept + { + if (str.size() == 0) + return false; + for (auto& c : str) + if (std::find(str.cbegin(), str.cend(), c) == str.cend()) + return false; + return true; + } + protected: @@ -120,5 +138,6 @@ class CppStringT : public std::basic_string private: //=== DATA ============================================ static inline constexpr std::vector _ASCII_PUNCT_DATA{ '!', ',', '.', ':', ';', '?' }; + static inline constexpr std::vector _ASCII_SEP{ ' ', '\t', '\n', 'r', '\f' }; }; From b606e4d7f87a28dfc4643fdc25c66b202dfc9e28 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 9 Mar 2023 14:32:27 +0100 Subject: [PATCH 010/220] #60 - Implement method is_punctuation Fixed error on `is_punctuation()` signature in class `CppStringT`. --- cpp-strings/cppstrings.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 34445c5..db53760 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -108,10 +108,10 @@ class CppStringT : public std::basic_string //=== Methods ========================================= //--- is_punctuation ---------------------------------- - /** \brief Returns true if a character belongs to ASCII punctuation set. */ - inline const bool is_punctuation(const value_type ch) noexcept + /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ + inline const bool is_punctuation(const MyBaseClass& str) noexcept { - return _ASCII_PUNCT_DATA.contains(ch); + return str.size == 1 && _ASCII_PUNCT_DATA.contains(str[0]); } //--- is_space ---------------------------------------- @@ -126,7 +126,7 @@ class CppStringT : public std::basic_string if (str.size() == 0) return false; for (auto& c : str) - if (std::find(str.cbegin(), str.cend(), c) == str.cend()) + if (std::find(_ASCII_SEP.cbegin(), _ASCII_SEP.cend(), c) == _ASCII_SEP.cend()) return false; return true; } From f28a337303b14988c09607412233afed9e704760 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 9 Mar 2023 14:44:21 +0100 Subject: [PATCH 011/220] #30 - Implement method CppStringT::isspace() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Completed. Fixed ìs_punctuation()`. --- cpp-strings/cppstrings.h | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index db53760..7c01b1b 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -109,11 +109,18 @@ class CppStringT : public std::basic_string //--- is_punctuation ---------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ - inline const bool is_punctuation(const MyBaseClass& str) noexcept + inline const bool is_punctuation() noexcept { - return str.size == 1 && _ASCII_PUNCT_DATA.contains(str[0]); + return this->length() == 1 && is_punctuation((*this)[0]); } + /** \brief Returns true if character belongs to the ASCII punctuation set. */ + static inline const bool is_punctuation(const value_type& ch) noexcept + { + return _ASCII_PUNCT_DATA.contains(ch); + } + + //--- is_space ---------------------------------------- /** \brief Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise. * @@ -121,16 +128,23 @@ class CppStringT : public std::basic_string * in the Unicode character database, either its general category is Zs * (“Separator, space”), or its bidirectional class is one of WS, B, or S. */ - inline const bool is_space(const MyBaseClass& str) noexcept + inline const bool is_space() noexcept { - if (str.size() == 0) + if (this->length() == 0) return false; - for (auto& c : str) - if (std::find(_ASCII_SEP.cbegin(), _ASCII_SEP.cend(), c) == _ASCII_SEP.cend()) + for (auto& c : *this) + if (!is_space(c)) return false; return true; } + /** \brief Returns true if character belongs to the ASCII spaces set. */ + static inline const bool is_space(const value_type& ch) noexcept + { + return _ASCII_SPACES.contains(ch); + } + + protected: @@ -138,6 +152,6 @@ class CppStringT : public std::basic_string private: //=== DATA ============================================ static inline constexpr std::vector _ASCII_PUNCT_DATA{ '!', ',', '.', ':', ';', '?' }; - static inline constexpr std::vector _ASCII_SEP{ ' ', '\t', '\n', 'r', '\f' }; + static inline constexpr std::vector _ASCII_SPACES{ ' ', '\t', '\n', 'r', '\f' }; }; From c12ba5f7c09a2384e186a369baf5f7ec919c774e Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 9 Mar 2023 14:52:48 +0100 Subject: [PATCH 012/220] #61- Implement method is_words_sep Completed. Fixed signature on a fex other methods. --- cpp-strings/cppstrings.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 7c01b1b..768c947 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -109,7 +109,7 @@ class CppStringT : public std::basic_string //--- is_punctuation ---------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ - inline const bool is_punctuation() noexcept + inline const bool is_punctuation() const noexcept { return this->length() == 1 && is_punctuation((*this)[0]); } @@ -128,7 +128,7 @@ class CppStringT : public std::basic_string * in the Unicode character database, either its general category is Zs * (“Separator, space”), or its bidirectional class is one of WS, B, or S. */ - inline const bool is_space() noexcept + inline const bool is_space() const noexcept { if (this->length() == 0) return false; @@ -145,6 +145,19 @@ class CppStringT : public std::basic_string } + //--- 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. */ + inline const bool is_words_sep() const noexcept + { + return is_space() || is_punctuation(); + } + + /** \brief Returns true if character belongs to ASCII spaces or punctuation sets. */ + static inline const bool is_words_sep(const value_type& ch) noexcept + { + return is_space(ch) || is_punctuation(ch); + } + protected: From a45bc567f09e9d1d1f70ded46b14ebf8a5988526 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 9 Mar 2023 15:09:43 +0100 Subject: [PATCH 013/220] #35 - Implement method CppStringT::lower() Completed. --- 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 768c947..2025240 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -22,6 +22,7 @@ //============================================================= #include +#include #include #include //#include @@ -107,7 +108,7 @@ class CppStringT : public std::basic_string //=== Methods ========================================= - //--- is_punctuation ---------------------------------- + //--- is_punctuation() -------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept { @@ -121,7 +122,7 @@ class CppStringT : public std::basic_string } - //--- is_space ---------------------------------------- + //--- is_space() -------------------------------------- /** \brief Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise. * * Notice for version 2.0 of this library: a character is whitespace if @@ -145,7 +146,7 @@ class CppStringT : public std::basic_string } - //--- is_words_sep ------------------------------------ + //--- 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. */ inline const bool is_words_sep() const noexcept { @@ -159,6 +160,31 @@ class CppStringT : public std::basic_string } + //--- lower () ----------------------------------------- + /** \brief In-place replaces all characters of the string with their lowercase conversion. Returns a reference to string. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + inline CppStringT& lower() noexcept + { + std::transform(this->begin(), this->end(), + this->begin(), + [](value_type ch) { return this->lower(ch); }); + return *this; + } + + /** \brief Returns lowercase conversion of the character. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + static inline const value_type lower(const value_type ch) noexcept + { + return value_type(std::tolower(ch)); + } + + protected: From 9fb272f4f562f936fe2278ac9e4f10ae5b4cad5e Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 9 Mar 2023 15:11:24 +0100 Subject: [PATCH 014/220] #55 - Implement method CppStringT::upper() Completed. --- cpp-strings/cppstrings.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 2025240..cf1baed 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -185,6 +185,32 @@ class CppStringT : public std::basic_string } + //--- upper () ----------------------------------------- + /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + inline CppStringT& upper() noexcept + { + std::transform(this->begin(), this->end(), + this->begin(), + [](value_type ch) { return this->upper(ch); }); + return *this; + } + + /** \brief Returns uppercase conversion of the character. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + static inline const value_type upper(const value_type ch) noexcept + { + return value_type(std::toupper(ch)); + } + + + protected: From 60782bb5b99e5cd335118419af0367bab73a771c Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 9 Mar 2023 15:15:08 +0100 Subject: [PATCH 015/220] #8 - Implement method CppStringT::capitalize() Completed. --- cpp-strings/cppstrings.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index cf1baed..3ec6c7f 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -108,6 +108,16 @@ class CppStringT : public std::basic_string //=== 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 + { + this->lower(); + (*this)[0] = upper((*this)[0]); + return *this; + } + + //--- is_punctuation() -------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept From a3c86ef59057d6e2e10a0991a66bf19d96aa5595 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 9 Mar 2023 19:26:45 +0100 Subject: [PATCH 016/220] #10 - Implement method CppStringT::center() Comlpeted. --- cpp-strings/cppstrings.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 3ec6c7f..844c3b0 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -109,7 +109,7 @@ class CppStringT : public std::basic_string //=== Methods ========================================= //--- capitalize() ------------------------------------ - // /** \brief In-place modifies the string with its first character capitalized and the rest lowercased. Returns a reference to the string*/ + /** \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 { this->lower(); @@ -118,6 +118,23 @@ class CppStringT : public std::basic_string } + //--- center() ---------------------------------------- + /** Returns the string centered in a string of length width. + * * + * Padding is done using the specified fillchar (default is an ASCII space). + * A copy of the original string is returned if width is less than or equal + * to the length of the string. The original string remains unchanged. + */ + inline CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept + { + const size_type l = this->length(); + if (l <= width) + return CppStringT(*this); + const size_type half = (width - l) / 2; + return CppStringT(fillch, half) + *this + CppStringT(fillch, width - half - l); + } + + //--- is_punctuation() -------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept From 1dee9cf55485a5b5c950edb387269ee5776c8ca3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 10 Mar 2023 01:26:25 +0100 Subject: [PATCH 017/220] #16 - Implement method CppStringT::find() Completed. --- cpp-strings/cppstrings.h | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 844c3b0..cf7c31e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -119,8 +119,8 @@ class CppStringT : public std::basic_string //--- center() ---------------------------------------- - /** Returns the string centered in a string of length width. - * * + /** \brief Returns the string centered in a string of length width. + * * Padding is done using the specified fillchar (default is an ASCII space). * A copy of the original string is returned if width is less than or equal * to the length of the string. The original string remains unchanged. @@ -135,6 +135,22 @@ class CppStringT : public std::basic_string } + //--- find() ------------------------------------------ + /** Returns the lowest index in the string where substring sub is found within the slice string[start:end], or -1 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(). + */ + inline constexpr size_type find(const CppStringT& sub, const size_type start, const size_type end) const noexcept + { + const size_type l = this->length(); + if (start >= l || end >= l || start > end) + return -1; + else + return MyBaseClass(this->cbegin() + start, this->cbegin() + end()).find(sub); + } + + //--- is_punctuation() -------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept From 9fe08ff58b9a13eea376f96acc433a53b5009590 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 10 Mar 2023 12:19:24 +0100 Subject: [PATCH 018/220] #11 - Implement method CppStringT::count() Completed. --- cpp-strings/cppstrings.h | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index cf7c31e..4c4816e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -127,27 +127,42 @@ class CppStringT : public std::basic_string */ inline CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept { - const size_type l = this->length(); + const size_type l{ this->length() }; if (l <= width) return CppStringT(*this); - const size_type half = (width - l) / 2; + const size_type half{ (width - l) / 2 }; return CppStringT(fillch, half) + *this + CppStringT(fillch, width - half - l); } + //--- 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 + { + const size_type length{ this->length() }; + const size_type end_{ (end == 0) ? length : end }; + + size_type n = 0; + size_type start_ = start; + while ((start_ = find(sub, start_, end_)) != CppStringT::npos) + n++; + + return n; + } + //--- find() ------------------------------------------ - /** Returns the lowest index in the string where substring sub is found within the slice string[start:end], or -1 if sub is not found. + /** 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(). */ inline constexpr size_type find(const CppStringT& sub, const size_type start, const size_type end) const noexcept { - const size_type l = this->length(); - if (start >= l || end >= l || start > end) - return -1; + const size_type length{ this->length() }; + if (start >= length || start > end) + return CppStringT::npos; else - return MyBaseClass(this->cbegin() + start, this->cbegin() + end()).find(sub); + return MyBaseClass(this->cbegin() + start, this->cbegin() + std::min(end, length - 1)).find(sub); } @@ -237,8 +252,8 @@ class CppStringT : public std::basic_string inline CppStringT& upper() noexcept { std::transform(this->begin(), this->end(), - this->begin(), - [](value_type ch) { return this->upper(ch); }); + this->begin(), + [](value_type ch) { return this->upper(ch); }); return *this; } @@ -259,7 +274,7 @@ class CppStringT : public std::basic_string private: //=== DATA ============================================ - static inline constexpr std::vector _ASCII_PUNCT_DATA{ '!', ',', '.', ':', ';', '?' }; - static inline constexpr std::vector _ASCII_SPACES{ ' ', '\t', '\n', 'r', '\f' }; + static inline constexpr std::vector _ASCII_PUNCT_DATA { '!', ',', '.', ':', ';', '?' }; + static inline constexpr std::vector _ASCII_SPACES { ' ', '\t', '\n', 'r', '\f' }; }; From f3cfc00806dc45be22aed1c2992d62556f740712 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 10 Mar 2023 12:23:17 +0100 Subject: [PATCH 019/220] #12 - Implement method CppStringT::count_n() Completed. --- cpp-strings/cppstrings.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 4c4816e..36cbf18 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -150,6 +150,21 @@ class CppStringT : public std::basic_string return n; } + + //--- count_n() --------------------------------------- + /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, start+length-1]. */ + 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]. */ + inline constexpr size_type count_n(const CppStringT& sub, const size_type length) const noexcept + { + return count(sub, 0, length - 1); + } + + //--- 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. * From 224de07477d066621f8c2599d9900b6d714b7c8f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 10 Mar 2023 12:26:00 +0100 Subject: [PATCH 020/220] #17 - Implement method CppStringT::find_n() Completed. --- cpp-strings/cppstrings.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 36cbf18..5abc945 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -181,6 +181,28 @@ class CppStringT : public std::basic_string } + //--- find_n() ---------------------------------------- + /** Returns the lowest index in the string where substring sub is found within the slice str[start:start+length-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(). + */ + inline constexpr size_type find_n(const CppStringT& sub, const size_type start, const size_type length) const noexcept + { + return find(sub, start, start + length - 1); + } + + /** Returns the lowest index in the string where substring sub is found within the slice str[0:length-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(). + */ + inline constexpr size_type find_n(const CppStringT& sub, const size_type length) const noexcept + { + return find(sub, 0, length - 1); + } + + //--- is_punctuation() -------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept From f82fc5d9b6fd63bc7f8fdec3f30fd02fde224e66 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 10 Mar 2023 12:43:10 +0100 Subject: [PATCH 021/220] #62 - Implement exception CppStringT::NotFoundException Completed. --- cpp-strings/cppstrings.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 5abc945..6d42620 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -23,6 +23,7 @@ //============================================================= #include #include +#include #include #include //#include @@ -106,6 +107,16 @@ class CppStringT : public std::basic_string CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} + //=== Exceptions ====================================== + class NotFoundException : public std::logic_error + { + public: + using MyBaseClass = std::logic_error; + + inline NotFoundException(const std::string& what_arg) : MyBaseClass(what_arg) {} + inline NotFoundException(const char* what_arg) : MyBaseClass(what_arg) {} + }; + //=== Methods ========================================= //--- capitalize() ------------------------------------ From fc98a0771ec06d7c4fe6c24035df0126bf295bec Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 10 Mar 2023 12:50:57 +0100 Subject: [PATCH 022/220] #19 - Implement method CppStringT::index() Completed. --- cpp-strings/cppstrings.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 6d42620..9f2b55e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -23,10 +23,10 @@ //============================================================= #include #include +#include #include #include #include -//#include //============================================================= @@ -214,6 +214,18 @@ class CppStringT : public std::basic_string } + //--- index() ----------------------------------------- + /** Like find(), but raises NotFoundException when the substring is not found. */ + inline constexpr size_type index(const CppStringT& sub, const size_type start, const size_type end) 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())); + else + return ret_value; + } + + //--- is_punctuation() -------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept From b428966ebbdb1ff7c26bd0c310f241e245f05eb3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 10 Mar 2023 12:54:54 +0100 Subject: [PATCH 023/220] #20 - Implement method CppStringT::index_n() Completed. --- cpp-strings/cppstrings.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 9f2b55e..17eb4f1 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -226,6 +226,21 @@ class CppStringT : public std::basic_string } + //--- index_n() --------------------------------------- + /** Like find_n(sub, start, length), but raises NotFoundException when the substring is not found. */ + inline constexpr size_type index_n(const CppStringT& sub, const size_type start, const size_type length) const + { + return index_n(sub, start, start + length - 1); + } + + /** Like find_n(sub, length), but raises NotFoundException when the substring is not found. */ + inline constexpr size_type index_n(const CppStringT& sub, const size_type length) const + { + return index_n(sub, 0, length - 1); + } + + + //--- is_punctuation() -------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept From c368826a303cecf8d0354078a9941e23f63b5286 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 10 Mar 2023 22:48:53 +0100 Subject: [PATCH 024/220] #42 - Implement method CppStringT::rfind() Completed. --- cpp-strings/cppstrings.h | 77 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 17eb4f1..0081aff 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -181,6 +181,9 @@ class CppStringT : public std::basic_string * * 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 CppStringT& sub, const size_type start, const size_type end) const noexcept { @@ -197,6 +200,9 @@ class CppStringT : public std::basic_string * * 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 CppStringT& sub, const size_type start, const size_type length) const noexcept { @@ -207,6 +213,9 @@ class CppStringT : public std::basic_string * * 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 CppStringT& sub, const size_type length) const noexcept { @@ -215,7 +224,11 @@ class CppStringT : public std::basic_string //--- index() ----------------------------------------- - /** Like find(), but raises NotFoundException when the substring is not found. */ + /** Like find(), but raises NotFoundException when the substring 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 { const size_type ret_value = find(sub, start, end); @@ -227,13 +240,21 @@ class CppStringT : public std::basic_string //--- index_n() --------------------------------------- - /** Like find_n(sub, start, length), but raises NotFoundException when the substring is not found. */ + /** Like find_n(sub, start, length), but raises NotFoundException when the 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 CppStringT& sub, const size_type start, const size_type length) const { return index_n(sub, start, start + length - 1); } - /** Like find_n(sub, length), but raises NotFoundException when the substring is not found. */ + /** Like find_n(sub, length), but raises NotFoundException when the 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 CppStringT& sub, const size_type length) const { return index_n(sub, 0, length - 1); @@ -318,6 +339,56 @@ class CppStringT : public std::basic_string } + //--- 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. + * + * 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(), 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 size_type end) const noexcept + { + const size_type length{ this->length() }; + if (start >= length || start > end) + return CppStringT::npos; + else + return this->find_end(this->cbegin()+start, this->cbegin()+end, sub.cbegin(), sub.cend()); + } + + /** 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: 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(), 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 + { + const size_type length{ this->length() }; + if (start >= length) + return CppStringT::npos; + else + return this->find_end(this->cbegin() + start, this->cend(), sub.cbegin(), sub.cend()); + } + + /** 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. + * + * 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(), find_n() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type rfind(const CppStringT& sub) const noexcept + { + return this->find_end(this->cbegin(), this->cend(), sub.cbegin(), sub.cend()); + } + + + //--- upper () ----------------------------------------- /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. * From 5d49ab1267e7dee3c8e488730606ec42438203df Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 10 Mar 2023 23:06:29 +0100 Subject: [PATCH 025/220] #43 - Implement method CppStringT::rindex() Completed. --- cpp-strings/cppstrings.h | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 0081aff..271bf76 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -388,6 +388,49 @@ class CppStringT : public std::basic_string } + //--- rindex() ---------------------------------------- + /** 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(). + */ + 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) + throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); + else + return ret_value; + } + + /** 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(). + */ + inline constexpr size_type rindex(const CppStringT& sub, const size_type start) const + { + const size_type ret_value = rfind(sub, start); + if (size_type == CppStringT::npos) + throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); + else + return ret_value; + } + + /** 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(). + */ + inline constexpr size_type rindex(const CppStringT& sub) const + { + const size_type ret_value = rfind(sub); + if (size_type == CppStringT::npos) + throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); + else + return ret_value; + } + //--- upper () ----------------------------------------- /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. From 895404bb229c476b9f44739dc5ebb905ff51006f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 00:09:48 +0100 Subject: [PATCH 026/220] #66 - Fix methods find() and find_n() Completed. --- cpp-strings/cppstrings.h | 53 +++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 271bf76..46c1b4e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -179,47 +179,51 @@ class CppStringT : public std::basic_string //--- 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. * - * 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(). - * + * 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_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 { - const size_type length{ this->length() }; - if (start >= length || start > end) + if (start > end) return CppStringT::npos; else - return MyBaseClass(this->cbegin() + start, this->cbegin() + std::min(end, length - 1)).find(sub); + return find_n(sub, start, end - start + 1); } //--- find_n() ---------------------------------------- - /** Returns the lowest index in the string where substring sub is found within the slice str[start:start+length-1], or -1 (i.e. 'npos') if sub is not found. + /** 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(). + * 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 CppStringT& sub, const size_type start, const size_type length) const noexcept + inline constexpr size_type find_n(const CppStringT& sub, const size_type start, const size_type count) const noexcept { - return find(sub, start, start + length - 1); + try { + return this->substr(start, count).find(sub); + } + catch (...) { + return CppStringT::npos; + } } - /** Returns the lowest index in the string where substring sub is found within the slice str[0:length-1], or -1 (i.e. 'npos') if sub is not found. + /** 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(). + * 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 CppStringT& sub, const size_type length) const noexcept + inline constexpr size_type find_n(const CppStringT& sub, const size_type count) const noexcept { - return find(sub, 0, length - 1); + return find_n(sub, 0, count); } @@ -250,7 +254,7 @@ class CppStringT : public std::basic_string return index_n(sub, start, start + length - 1); } - /** Like find_n(sub, length), but raises NotFoundException when the substring is not found. + /** Like find_n(sub, start), but raises NotFoundException when the substring is not found. * * \see index_n(), rindex() and rindex_n(). * \see find(), find_n(), rfind() and rfind_n(). @@ -388,6 +392,21 @@ class CppStringT : public std::basic_string } + //--- rfind_n() --------------------------------------- + /** Returns the highest index in the string where substring sub is found within the slice str[start:start+length-1], or -1 (i.e. 'npos') if sub is not found. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains_n(). + * + * \see find(), find_n() and rfind(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type rfind_n(const CppStringT& sub, const size_type start, const size_type length) const noexcept + { + return rfind(sub, start, start + length - 1); + } + + //--- rindex() ---------------------------------------- /** Like rfind(sub, start, end), but raises NotFoundException when the substring is not found. * From 8a666e5dafa19914792c4ec43179cee371c60953 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 00:19:12 +0100 Subject: [PATCH 027/220] #67 - Fix methods index() and index_n() Completed. --- cpp-strings/cppstrings.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 46c1b4e..77f244d 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -249,9 +249,9 @@ class CppStringT : public std::basic_string * \see index_n(), rindex() and rindex_n(). * \see find(), find_n(), rfind() and rfind_n(). */ - inline constexpr size_type index_n(const CppStringT& sub, const size_type start, const size_type length) const + inline constexpr size_type index_n(const CppStringT& sub, const size_type start, const size_type count) const { - return index_n(sub, start, start + length - 1); + return index(sub, start, start + count - 1); } /** Like find_n(sub, start), but raises NotFoundException when the substring is not found. @@ -259,13 +259,12 @@ class CppStringT : public std::basic_string * \see index_n(), rindex() and rindex_n(). * \see find(), find_n(), rfind() and rfind_n(). */ - inline constexpr size_type index_n(const CppStringT& sub, const size_type length) const + inline constexpr size_type index_n(const CppStringT& sub, const size_type count) const { - return index_n(sub, 0, length - 1); + return index(sub, 0, count - 1); } - //--- is_punctuation() -------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept From 7eb0631a602f36c575851b7a65709392abd11a27 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 00:29:57 +0100 Subject: [PATCH 028/220] #68 - Fix method rfind() Completed. --- cpp-strings/cppstrings.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 77f244d..0e5eb0c 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -345,6 +345,8 @@ class CppStringT : public std::basic_string //--- 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. * + * Note that this is an offset from the start of the string, not the end. + * * Note: this method should be used only if you need to know the position * of sub. To check if sub is a substring or not, use the method contains(). * @@ -353,15 +355,16 @@ class CppStringT : public std::basic_string */ inline constexpr size_type rfind(const CppStringT& sub, const size_type start, const size_type end) const noexcept { - const size_type length{ this->length() }; - if (start >= length || start > end) + if (start > end) return CppStringT::npos; else - return this->find_end(this->cbegin()+start, this->cbegin()+end, sub.cbegin(), sub.cend()); + return this->substr(start, end - start + 1).rfind(sub); } /** Returns the highest index in the string where substring sub is found starting at start position in string, or -1 (i.e. 'npos') if sub is not found. * + * Note that this is an offset from the start of the string, not the end. + * * Note: this method should be used only if you need to know the position * of sub. To check if sub is a substring or not, use the method contains(). * @@ -370,15 +373,13 @@ class CppStringT : public std::basic_string */ inline constexpr size_type rfind(const CppStringT& sub, const size_type start) const noexcept { - const size_type length{ this->length() }; - if (start >= length) - return CppStringT::npos; - else - return this->find_end(this->cbegin() + start, this->cend(), sub.cbegin(), sub.cend()); + return rfind(sub, start, this->size() - start + 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. * + * Note that this is an offset from the start of the string, not the end. + * * Note: this method should be used only if you need to know the position * of sub. To check if sub is a substring or not, use the method contains(). * @@ -387,7 +388,7 @@ class CppStringT : public std::basic_string */ inline constexpr size_type rfind(const CppStringT& sub) const noexcept { - return this->find_end(this->cbegin(), this->cend(), sub.cbegin(), sub.cend()); + return MyBaseClass::rfind(sub); } From 14ecbfee2262ea7ba9f48c126c45a8ad04b18df8 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 00:33:44 +0100 Subject: [PATCH 029/220] #64 - Implement method rfind_n() Completed. --- cpp-strings/cppstrings.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 0e5eb0c..d64aca0 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -138,7 +138,7 @@ class CppStringT : public std::basic_string */ inline CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept { - const size_type l{ this->length() }; + const size_type l{ this->size() }; if (l <= width) return CppStringT(*this); const size_type half{ (width - l) / 2 }; @@ -150,7 +150,7 @@ class CppStringT : public std::basic_string /** \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 { - const size_type length{ this->length() }; + const size_type length{ this->size() }; const size_type end_{ (end == 0) ? length : end }; size_type n = 0; @@ -269,7 +269,7 @@ class CppStringT : public std::basic_string /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept { - return this->length() == 1 && is_punctuation((*this)[0]); + return this->size() == 1 && is_punctuation((*this)[0]); } /** \brief Returns true if character belongs to the ASCII punctuation set. */ @@ -288,7 +288,7 @@ class CppStringT : public std::basic_string */ inline const bool is_space() const noexcept { - if (this->length() == 0) + if (this->size() == 0) return false; for (auto& c : *this) if (!is_space(c)) From 2c76cd624381bb31a22cf90570b8acda0ed9967a Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 00:52:50 +0100 Subject: [PATCH 030/220] #69 - Fix method rindex() Completed. --- cpp-strings/cppstrings.h | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index d64aca0..e79c783 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -429,11 +429,7 @@ class CppStringT : public std::basic_string */ inline constexpr size_type rindex(const CppStringT& sub, const size_type start) const { - const size_type ret_value = rfind(sub, start); - if (size_type == CppStringT::npos) - throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); - else - return ret_value; + return rindex(sub, start, this->size() - 1); } /** Like rfind(sub), but raises NotFoundException when the substring is not found. @@ -443,11 +439,7 @@ class CppStringT : public std::basic_string */ inline constexpr size_type rindex(const CppStringT& sub) const { - const size_type ret_value = rfind(sub); - if (size_type == CppStringT::npos) - throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); - else - return ret_value; + return rindex(sub, 0, this->size() - 1); } From eab2dabf1f7ac5a9d57f4435a2c364f2e1605293 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 01:00:46 +0100 Subject: [PATCH 031/220] #65 - Implement method rindex_n() Completed. Fixed a few doc comments; added a missing method signature. --- cpp-strings/cppstrings.h | 47 +++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index e79c783..11e36d1 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -244,7 +244,7 @@ class CppStringT : public std::basic_string //--- index_n() --------------------------------------- - /** Like find_n(sub, start, length), but raises NotFoundException when the substring is not found. + /** 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(). @@ -254,14 +254,14 @@ class CppStringT : public std::basic_string return index(sub, start, start + count - 1); } - /** Like find_n(sub, start), but raises NotFoundException when the substring is not found. + /** 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(). */ inline constexpr size_type index_n(const CppStringT& sub, const size_type count) const { - return index(sub, 0, count - 1); + return index(sub, 0, count); } @@ -393,7 +393,7 @@ class CppStringT : public std::basic_string //--- rfind_n() --------------------------------------- - /** Returns the highest index in the string where substring sub is found within the slice str[start:start+length-1], or -1 (i.e. 'npos') if sub is not found. + /** 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(). @@ -401,9 +401,22 @@ class CppStringT : public std::basic_string * \see find(), find_n() and rfind(). * \see index(), index_n(), rindex() and rindex_n(). */ - inline constexpr size_type rfind_n(const CppStringT& sub, const size_type start, const size_type length) const noexcept + inline constexpr size_type rfind_n(const CppStringT& sub, const size_type start, const size_type count) const noexcept { - return rfind(sub, start, start + length - 1); + 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. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains_n(). + * + * \see find(), find_n() and rfind(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type rfind_n(const CppStringT& sub, const size_type count) const noexcept + { + return rfind(sub, 0, count); } @@ -443,6 +456,28 @@ class CppStringT : public std::basic_string } + //--- rindex_n() -------------------------------------- + /** 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(). + */ + 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); + } + + /** 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(). + */ + inline constexpr size_type rindex_n(const CppStringT& sub, const size_type count) const + { + return rindex(sub, 0, count); + } + + //--- upper () ----------------------------------------- /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. * From e3d8f118bb7b0854f3508c32acd01625f8685fd3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 17:03:28 +0100 Subject: [PATCH 032/220] #13 - Implement method CppStringT::endswith() Completed. --- cpp-strings/cppstrings.h | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 11e36d1..d196095 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -24,8 +24,9 @@ #include #include #include +#include #include -#include +#include #include @@ -194,6 +195,40 @@ class CppStringT : public std::basic_string } + //--- endswith() -------------------------------------- + /** Returns true if the string ends with the specified suffix, otherwise return 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); + } + + /** Returns true if the string ends with the specified suffix, otherwise return 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 + { + return endswith(std::span{ suffix }, start, this->size()-1); + } + + /** Returns true if the string ends with the specified suffix, otherwise return false. Test runs on the whole string. */ + inline const bool endswith(const CppStringT& suffix) const noexcept + { + return this->ends_with(suffix); + } + + /** Returns true if the string ends with any of the specified suffixes, otherwise return 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 + { + if (start > end) + return false; + + for (auto& suffix : suffixes) { + if (this->substr(start, end).ends_with(suffix)) + return true; + } + + return false; + } + + //--- 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 11cae6494718a1091f524167b9e257058e48210a Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 17:09:37 +0100 Subject: [PATCH 033/220] #14 - Implement method CppStringT::endswith_n() Completed. --- cpp-strings/cppstrings.h | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index d196095..999ef9f 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -196,25 +196,25 @@ class CppStringT : public std::basic_string //--- endswith() -------------------------------------- - /** Returns true if the string ends with the specified suffix, otherwise return false. Test begins at start position and stops at end position. */ + /** 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); } - /** Returns true if the string ends with the specified suffix, otherwise return false. Test begins at start position and stops at end of string. */ + /** 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 { return endswith(std::span{ suffix }, start, this->size()-1); } - /** Returns true if the string ends with the specified suffix, otherwise return false. Test runs on the whole string. */ + /** 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); } - /** Returns true if the string ends with any of the specified suffixes, otherwise return false. Test begins at start position and stops at end of string. */ + /** 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 { if (start > end) @@ -229,6 +229,26 @@ class CppStringT : public std::basic_string } + //--- 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. */ + 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); + } + + /** 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); + } + + /** 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 + { + return endswith(suffixes, start, start + count - 1); + } + + //--- 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 14054fb4a1bcfbc00a613c0beed16ace35d0a01b Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 17:40:19 +0100 Subject: [PATCH 034/220] #15 - Implement method CppStringT::expand_tabs() Completed. --- cpp-strings/cppstrings.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 999ef9f..70385b7 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -249,6 +249,35 @@ class CppStringT : public std::basic_string } + //--- 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. */ + CppStringT expand_tabs(const size_type tabsize = 8) const noexcept + { + const size_type tabsize_{ tabsize == 0 ? 1 : tabsize }; + CppStringT ret{}; + + std::size_t current_pos{ 0 }; + for (const value_type ch : *this) { + if (ch == value_type('\t')) { + do { + ret += value_type(' '); + current_pos++; + } while (current_pos % tabsize_ != 0); + } + else if (ch == value_type('\n') || ch == value_type('\r')) { + ret += ch; + current_pos = 0; + } + else { + ret += ch; + current_pos++; + } + } + + return ret; + } + + //--- 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 4b0c7067709be01bbc98857f67450cd81483c804 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 20:56:03 +0100 Subject: [PATCH 035/220] #21 - Implement method CppStringT::isalnum() Completed. --- cpp-strings/cppstrings.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 70385b7..0644504 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -23,6 +23,7 @@ //============================================================= #include #include +#include #include #include #include @@ -349,6 +350,42 @@ class CppStringT : public std::basic_string } + //--- isalnum() --------------------------------------- + /** \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(); + } + + + //--- isalpha() -------------------------------------- + inline const bool isalpha() const noexcept + { + return false; + } + + + //--- isdecimal() ------------------------------------- + inline const bool isdecimal() const noexcept + { + return false; + } + + + //--- isdigit() --------------------------------------- + inline const bool isdigit() const noexcept + { + return false; + } + + + //--- isnumeric() ------------------------------------- + inline const bool isnumeric() const noexcept + { + return false; + } + + //--- is_punctuation() -------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept From 6ca96ba9fa98fdf49ce14545bb8e7a8d466cbfeb Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 22:22:39 +0100 Subject: [PATCH 036/220] #22 - Implement method CppStringT::isalpha() Completed. Added namespace `pcs`. Modified forward declarations. Added chars classification templated functions and their specializations for alpha chars. --- cpp-strings/cppstrings.cpp | 1 + cpp-strings/cppstrings.h | 1058 +++++++++++++++++++----------------- 2 files changed, 546 insertions(+), 513 deletions(-) diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index c4cb537..ec199f7 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -20,6 +20,7 @@ */ #include "cppstrings.h" +using namespace pcs; /** * Notice: this module is for tests and validation purposes only. diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 0644504..786a59f 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -31,606 +31,638 @@ #include -//============================================================= -// Forward declarations -template< - class CharT, - class TraitsT = std::char_traits, - class AllocatorT = std::allocator -> class CppStringT; //!< The templated base class. Use its belowing specializations instead! - -using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' -using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' - - -//===== CppStringT<> ====================================== -/** -* \brief This is the templated base class for all CppString -* classes. -* -* Users should instantiate any specialization of this base class -* rather than this base class itself: -* - \see CppString for CppStringT. -* - \see CppWString for CppStringT. -* -* This base class inherits from std::basic_string. As such, -* it gets direct access to all public methods of its base class. -* \see https://en.cppreference.com/w/cpp/string/basic_string for -* a full list of such methods, for instance. -* -* You may specialize it by your own with any of the next char -* types: -* - char8_t (C++20) -* - char16_t (C++11) -* - char32_t (C++11) -*/ -template -class CppStringT : public std::basic_string +namespace pcs // i.e. "pythonic c++ strings" { -public: - //=== Wrappers ======================================== - using MyBaseClass = std::basic_string; - - using traits_type = MyBaseClass::traits_type; - using value_type = MyBaseClass::value_type; - using allocator_type = MyBaseClass::allocator_type; - using size_type = MyBaseClass::size_type; - using difference_type = MyBaseClass::difference_type; - using reference = MyBaseClass::reference; - using const_reference = MyBaseClass::const_reference; - using pointer = MyBaseClass::pointer; - using const_pointer = MyBaseClass::const_pointer; - using iterator = MyBaseClass::iterator; - using const_iterator = MyBaseClass::const_iterator; - using reverse_iterator = MyBaseClass::reverse_iterator; - using const_reverse_iterator = MyBaseClass::const_reverse_iterator; - - - //=== Constructors ==================================== - 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) {} - - template - inline CppStringT(InputIt first, InputIt last) : MyBaseClass(first, last) {} - - template - explicit CppStringT(const StringViewLike& svl) : MyBaseClass(svl) {} - - template - CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} - - - //=== Exceptions ====================================== - class NotFoundException : public std::logic_error - { - public: - using MyBaseClass = std::logic_error; + //============================================================= + // Forward declarations - inline NotFoundException(const std::string& what_arg) : MyBaseClass(what_arg) {} - inline NotFoundException(const char* what_arg) : MyBaseClass(what_arg) {} - }; + // base class -- not to be directly instantiated, see belowing specializations instead + template< + class CharT, + class TraitsT = std::char_traits, + class AllocatorT = std::allocator + > class CppStringT; //!< The templated base class. Use its belowing specializations instead! - //=== Methods ========================================= + // specializations of the base class -- these are the ones that should be instantiated by user. + using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' + using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' + + // 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); - //--- 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 - { - this->lower(); - (*this)[0] = upper((*this)[0]); - return *this; - } - //--- center() ---------------------------------------- - /** \brief Returns the string centered in a string of length width. + //===== CppStringT<> ====================================== + /** + * \brief This is the templated base class for all CppString + * classes. * - * Padding is done using the specified fillchar (default is an ASCII space). - * A copy of the original string is returned if width is less than or equal - * to the length of the string. The original string remains unchanged. + * Users should instantiate any specialization of this base class + * rather than this base class itself: + * - \see CppString for CppStringT. + * - \see CppWString for CppStringT. + * + * This base class inherits from std::basic_string. As such, + * it gets direct access to all public methods of its base class. + * \see https://en.cppreference.com/w/cpp/string/basic_string for + * a full list of such methods, for instance. + * + * You may specialize it by your own with any of the next char + * types: + * - char8_t (C++20) + * - char16_t (C++11) + * - char32_t (C++11) */ - inline CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept + template + class CppStringT : public std::basic_string { - const size_type l{ this->size() }; - if (l <= width) - return CppStringT(*this); - const size_type half{ (width - l) / 2 }; - return CppStringT(fillch, half) + *this + CppStringT(fillch, width - half - l); - } + public: + //=== Wrappers ======================================== + using MyBaseClass = std::basic_string; + + using traits_type = MyBaseClass::traits_type; + using value_type = MyBaseClass::value_type; + using allocator_type = MyBaseClass::allocator_type; + using size_type = MyBaseClass::size_type; + using difference_type = MyBaseClass::difference_type; + using reference = MyBaseClass::reference; + using const_reference = MyBaseClass::const_reference; + using pointer = MyBaseClass::pointer; + using const_pointer = MyBaseClass::const_pointer; + using iterator = MyBaseClass::iterator; + using const_iterator = MyBaseClass::const_iterator; + using reverse_iterator = MyBaseClass::reverse_iterator; + using const_reverse_iterator = MyBaseClass::const_reverse_iterator; + + + //=== 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) {} + + template + inline CppStringT(InputIt first, InputIt last) : MyBaseClass(first, last) {} + + template + explicit CppStringT(const StringViewLike& svl) : MyBaseClass(svl) {} + template + CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} + + inline ~CppStringT() = default; + + + //=== Exceptions ====================================== + class NotFoundException : public std::logic_error + { + public: + using MyBaseClass = std::logic_error; + + inline NotFoundException(const std::string& what_arg) : MyBaseClass(what_arg) {} + inline NotFoundException(const char* what_arg) : MyBaseClass(what_arg) {} + }; + + //=== Methods ========================================= + + //--- capitalize() ------------------------------------ + /** \brief In-place modifies the string with its first character capitalized and the rest lowercased. Returns a reference to the string*/ + inline CppStringT& capitalize() noexcept + { + this->lower(); + (*this)[0] = upper((*this)[0]); + return *this; + } - //--- 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 - { - const size_type length{ this->size() }; - const size_type end_{ (end == 0) ? length : end }; + //--- center() ---------------------------------------- + /** \brief Returns the string centered in a string of length width. + * + * Padding is done using the specified fillchar (default is an ASCII space). + * A copy of the original string is returned if width is less than or equal + * to the length of the string. The original string remains unchanged. + */ + inline CppStringT center(const size_type width, const value_type fillch = value_type(' ')) const noexcept + { + const size_type l{ this->size() }; + if (l <= width) + return CppStringT(*this); + const size_type half{ (width - l) / 2 }; + return CppStringT(fillch, half) + *this + CppStringT(fillch, width - half - l); + } - size_type n = 0; - size_type start_ = start; - while ((start_ = find(sub, start_, end_)) != CppStringT::npos) - n++; - return n; - } + //--- 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 + { + 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) + n++; - //--- count_n() --------------------------------------- - /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, start+length-1]. */ - 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); - } + return n; + } - /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [0, length-1]. */ - inline constexpr size_type count_n(const CppStringT& sub, const size_type length) const noexcept - { - return count(sub, 0, length - 1); - } + //--- count_n() --------------------------------------- + /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [start, start+length-1]. */ + 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); + } - //--- 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. - * - * 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_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 - { - if (start > end) - return CppStringT::npos; - else - return find_n(sub, start, end - start + 1); - } + /** \brief Returns the number of non-overlapping occurrences of substring sub in the range [0, length-1]. */ + inline constexpr size_type count_n(const CppStringT& sub, const size_type length) const noexcept + { + return count(sub, 0, length - 1); + } - //--- endswith() -------------------------------------- - /** 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); - } + //--- 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. + * + * 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_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 + { + if (start > end) + return CppStringT::npos; + else + return find_n(sub, start, end - start + 1); + } - /** 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 - { - return endswith(std::span{ suffix }, start, this->size()-1); - } - /** 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); - } + //--- endswith() -------------------------------------- + /** 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); + } - /** 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 - { - if (start > end) - return false; + /** 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 + { + return endswith(std::span{ suffix }, start, this->size() - 1); + } - for (auto& suffix : suffixes) { - if (this->substr(start, end).ends_with(suffix)) - return true; + /** 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 false; - } + /** 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 + { + if (start > end) + return false; + for (auto& suffix : suffixes) { + if (this->substr(start, end).ends_with(suffix)) + return true; + } - //--- 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. */ - 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 false; + } - /** 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); - } - /** 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 - { - return endswith(suffixes, start, start + count - 1); - } + //--- 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. */ + 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); + } + /** 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); + } - //--- 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. */ - CppStringT expand_tabs(const size_type tabsize = 8) const noexcept - { - const size_type tabsize_{ tabsize == 0 ? 1 : tabsize }; - CppStringT ret{}; - - std::size_t current_pos{ 0 }; - for (const value_type ch : *this) { - if (ch == value_type('\t')) { - do { - ret += value_type(' '); + /** 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 + { + return endswith(suffixes, start, start + count - 1); + } + + + //--- 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. */ + CppStringT expand_tabs(const size_type tabsize = 8) const noexcept + { + const size_type tabsize_{ tabsize == 0 ? 1 : tabsize }; + CppStringT ret{}; + + std::size_t current_pos{ 0 }; + for (const value_type ch : *this) { + if (ch == value_type('\t')) { + do { + ret += value_type(' '); + current_pos++; + } while (current_pos % tabsize_ != 0); + } + else if (ch == value_type('\n') || ch == value_type('\r')) { + ret += ch; + current_pos = 0; + } + else { + ret += ch; current_pos++; - } while (current_pos % tabsize_ != 0); + } } - else if (ch == value_type('\n') || ch == value_type('\r')) { - ret += ch; - current_pos = 0; + + return ret; + } + + + //--- 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. + * + * 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 CppStringT& sub, const size_type start, const size_type count) const noexcept + { + try { + return this->substr(start, count).find(sub); } - else { - ret += ch; - current_pos++; + catch (...) { + return CppStringT::npos; } } - return ret; - } + /** 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(). + * + * \see find(), rfind() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type find_n(const CppStringT& sub, const size_type count) const noexcept + { + return find_n(sub, 0, count); + } - //--- 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. - * - * 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 CppStringT& sub, const size_type start, const size_type count) const noexcept - { - try { - return this->substr(start, count).find(sub); + //--- index() ----------------------------------------- + /** Like find(), but raises NotFoundException when the substring 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 + { + 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())); + else + return ret_value; } - catch (...) { - return CppStringT::npos; + + + //--- index_n() --------------------------------------- + /** 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(). + */ + 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); } - } - /** 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(). - * - * \see find(), rfind() and rfind_n(). - * \see index(), index_n(), rindex() and rindex_n(). - */ - inline constexpr size_type find_n(const CppStringT& sub, const size_type count) const noexcept - { - return find_n(sub, 0, count); - } + /** 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(). + */ + inline constexpr size_type index_n(const CppStringT& sub, const size_type count) const + { + return index(sub, 0, count); + } - //--- index() ----------------------------------------- - /** Like find(), but raises NotFoundException when the substring 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 - { - 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())); - else - return ret_value; - } + //--- isalnum() --------------------------------------- + /** \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(); + } - //--- index_n() --------------------------------------- - /** 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(). - */ - 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); - } + //--- isalpha() -------------------------------------- + /** \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 + { + if (this->size() == 0) + return false; + else + return std::all_of(this->cbegin(), this->cend(), [](const value_type ch) { return pcs::is_alpha(ch); }); + } - /** 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(). - */ - inline constexpr size_type index_n(const CppStringT& sub, const size_type count) const - { - return index(sub, 0, count); - } + //--- isdecimal() ------------------------------------- + inline const bool isdecimal() const noexcept + { + return false; + } - //--- isalnum() --------------------------------------- - /** \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(); - } + //--- isdigit() --------------------------------------- + inline const bool isdigit() const noexcept + { + return false; + } - //--- isalpha() -------------------------------------- - inline const bool isalpha() const noexcept - { - return false; - } + //--- isnumeric() ------------------------------------- + inline const bool isnumeric() const noexcept + { + return false; + } - //--- isdecimal() ------------------------------------- - inline const bool isdecimal() const noexcept - { - return false; - } + //--- is_punctuation() -------------------------------- + /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ + inline const bool is_punctuation() const noexcept + { + return this->size() == 1 && is_punctuation((*this)[0]); + } - //--- isdigit() --------------------------------------- - inline const bool isdigit() const noexcept - { - return false; - } + /** \brief Returns true if character belongs to the ASCII punctuation set. */ + static inline const bool is_punctuation(const value_type& ch) noexcept + { + return _ASCII_PUNCT_DATA.contains(ch); + } - //--- isnumeric() ------------------------------------- - inline const bool isnumeric() const noexcept - { - return false; - } + //--- is_space() -------------------------------------- + /** \brief Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise. + * + * Notice for version 2.0 of this library: a character is whitespace if + * in the Unicode character database, either its general category is Zs + * (“Separator, space”), or its bidirectional class is one of WS, B, or S. + */ + inline const bool is_space() const noexcept + { + if (this->size() == 0) + return false; + for (auto& c : *this) + if (!is_space(c)) + return false; + return true; + } + /** \brief Returns true if character belongs to the ASCII spaces set. */ + static inline const bool is_space(const value_type& ch) noexcept + { + return _ASCII_SPACES.contains(ch); + } - //--- is_punctuation() -------------------------------- - /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ - inline const bool is_punctuation() const noexcept - { - return this->size() == 1 && is_punctuation((*this)[0]); - } - /** \brief Returns true if character belongs to the ASCII punctuation set. */ - static inline const bool is_punctuation(const value_type& ch) noexcept - { - return _ASCII_PUNCT_DATA.contains(ch); - } + //--- 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. */ + inline const bool is_words_sep() const noexcept + { + return is_space() || is_punctuation(); + } + /** \brief Returns true if character belongs to ASCII spaces or punctuation sets. */ + static inline const bool is_words_sep(const value_type& ch) noexcept + { + return is_space(ch) || is_punctuation(ch); + } - //--- is_space() -------------------------------------- - /** \brief Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise. - * - * Notice for version 2.0 of this library: a character is whitespace if - * in the Unicode character database, either its general category is Zs - * (“Separator, space”), or its bidirectional class is one of WS, B, or S. - */ - inline const bool is_space() const noexcept - { - if (this->size() == 0) - return false; - for (auto& c : *this) - if (!is_space(c)) - return false; - return true; - } - /** \brief Returns true if character belongs to the ASCII spaces set. */ - static inline const bool is_space(const value_type& ch) noexcept - { - return _ASCII_SPACES.contains(ch); - } + //--- lower () ----------------------------------------- + /** \brief In-place replaces all characters of the string with their lowercase conversion. Returns a reference to string. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + inline CppStringT& lower() noexcept + { + std::transform(this->begin(), this->end(), + this->begin(), + [](value_type ch) { return this->lower(ch); }); + return *this; + } + /** \brief Returns lowercase conversion of the character. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + static inline const value_type lower(const value_type ch) noexcept + { + return value_type(std::tolower(ch)); + } - //--- 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. */ - inline const bool is_words_sep() const noexcept - { - return is_space() || is_punctuation(); - } - /** \brief Returns true if character belongs to ASCII spaces or punctuation sets. */ - static inline const bool is_words_sep(const value_type& ch) noexcept - { - return is_space(ch) || is_punctuation(ch); - } + //--- 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. + * + * Note that this is an offset from the start of the string, not the end. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains(). + * + * \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 size_type end) const noexcept + { + if (start > end) + return CppStringT::npos; + else + return this->substr(start, end - start + 1).rfind(sub); + } + /** Returns the highest index in the string where substring sub is found starting at start position in string, or -1 (i.e. 'npos') if sub is not found. + * + * Note that this is an offset from the start of the string, not the end. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains(). + * + * \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); + } - //--- lower () ----------------------------------------- - /** \brief In-place replaces all characters of the string with their lowercase conversion. Returns a reference to string. - * - * Notice: uses the currently set std::locale, which is the "C" one - * by default or any other one as previously set by the user. - */ - inline CppStringT& lower() noexcept - { - std::transform(this->begin(), this->end(), - this->begin(), - [](value_type ch) { return this->lower(ch); }); - return *this; - } + /** 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. + * + * Note that this is an offset from the start of the string, not the end. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains(). + * + * \see find(), find_n() and rfind_n(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type rfind(const CppStringT& sub) const noexcept + { + return MyBaseClass::rfind(sub); + } - /** \brief Returns lowercase conversion of the character. - * - * Notice: uses the currently set std::locale, which is the "C" one - * by default or any other one as previously set by the user. - */ - static inline const value_type lower(const value_type ch) noexcept - { - return value_type(std::tolower(ch)); - } + //--- 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. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains_n(). + * + * \see find(), find_n() and rfind(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + 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); + } - //--- 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. - * - * Note that this is an offset from the start of the string, not the end. - * - * Note: this method should be used only if you need to know the position - * of sub. To check if sub is a substring or not, use the method contains(). - * - * \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 size_type end) const noexcept - { - if (start > end) - return CppStringT::npos; - else - return this->substr(start, end - start + 1).rfind(sub); - } + /** Returns the highest index in the string where substring sub is found within the slice str[0:count-1], or -1 (i.e. 'npos') if sub is not found. + * + * Note: this method should be used only if you need to know the position + * of sub. To check if sub is a substring or not, use the method contains_n(). + * + * \see find(), find_n() and rfind(). + * \see index(), index_n(), rindex() and rindex_n(). + */ + inline constexpr size_type rfind_n(const CppStringT& sub, const size_type count) const noexcept + { + return rfind(sub, 0, count); + } - /** Returns the highest index in the string where substring sub is found starting at start position in string, or -1 (i.e. 'npos') if sub is not found. - * - * Note that this is an offset from the start of the string, not the end. - * - * Note: this method should be used only if you need to know the position - * of sub. To check if sub is a substring or not, use the method contains(). - * - * \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); - } - /** 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. - * - * Note that this is an offset from the start of the string, not the end. - * - * Note: this method should be used only if you need to know the position - * of sub. To check if sub is a substring or not, use the method contains(). - * - * \see find(), find_n() and rfind_n(). - * \see index(), index_n(), rindex() and rindex_n(). - */ - inline constexpr size_type rfind(const CppStringT& sub) const noexcept - { - return MyBaseClass::rfind(sub); - } + //--- rindex() ---------------------------------------- + /** 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(). + */ + 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) + throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); + else + return ret_value; + } + /** 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(). + */ + inline constexpr size_type rindex(const CppStringT& sub, const size_type start) const + { + return rindex(sub, start, this->size() - 1); + } - //--- 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. - * - * Note: this method should be used only if you need to know the position - * of sub. To check if sub is a substring or not, use the method contains_n(). - * - * \see find(), find_n() and rfind(). - * \see index(), index_n(), rindex() and rindex_n(). - */ - 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); - } - - /** Returns the highest index in the string where substring sub is found within the slice str[0:count-1], or -1 (i.e. 'npos') if sub is not found. - * - * Note: this method should be used only if you need to know the position - * of sub. To check if sub is a substring or not, use the method contains_n(). - * - * \see find(), find_n() and rfind(). - * \see index(), index_n(), rindex() and rindex_n(). - */ - inline constexpr size_type rfind_n(const CppStringT& sub, const size_type count) const noexcept - { - return rfind(sub, 0, count); - } + /** 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(). + */ + inline constexpr size_type rindex(const CppStringT& sub) const + { + return rindex(sub, 0, this->size() - 1); + } - //--- rindex() ---------------------------------------- - /** 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(). - */ - 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) - throw NotFoundException(std::format("substring \"{}\" not found in string \"{}\"", sub, this->c_str())); - else - return ret_value; - } - - /** 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(). - */ - inline constexpr size_type rindex(const CppStringT& sub, const size_type start) const - { - return rindex(sub, start, this->size() - 1); - } - - /** 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(). - */ - inline constexpr size_type rindex(const CppStringT& sub) const - { - return rindex(sub, 0, this->size() - 1); - } + //--- rindex_n() -------------------------------------- + /** 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(). + */ + 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); + } + /** 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(). + */ + inline constexpr size_type rindex_n(const CppStringT& sub, const size_type count) const + { + return rindex(sub, 0, count); + } - //--- rindex_n() -------------------------------------- - /** 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(). - */ - 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); - } - /** 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(). - */ - inline constexpr size_type rindex_n(const CppStringT& sub, const size_type count) const - { - return rindex(sub, 0, count); - } + //--- upper () ----------------------------------------- + /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + inline CppStringT& upper() noexcept + { + std::transform(this->begin(), this->end(), + this->begin(), + [](value_type ch) { return this->upper(ch); }); + return *this; + } + + /** \brief Returns uppercase conversion of the character. + * + * Notice: uses the currently set std::locale, which is the "C" one + * by default or any other one as previously set by the user. + */ + static inline const value_type upper(const value_type ch) noexcept + { + return value_type(std::toupper(ch)); + } - //--- upper () ----------------------------------------- - /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. - * - * Notice: uses the currently set std::locale, which is the "C" one - * by default or any other one as previously set by the user. - */ - inline CppStringT& upper() noexcept - { - std::transform(this->begin(), this->end(), - this->begin(), - [](value_type ch) { return this->upper(ch); }); - return *this; - } + protected: - /** \brief Returns uppercase conversion of the character. - * - * Notice: uses the currently set std::locale, which is the "C" one - * by default or any other one as previously set by the user. - */ - static inline const value_type upper(const value_type ch) noexcept - { - return value_type(std::toupper(ch)); - } + + private: + //=== DATA ============================================ + static inline constexpr std::vector _ASCII_PUNCT_DATA{ '!', ',', '.', ':', ';', '?' }; + static inline constexpr std::vector _ASCII_SPACES{ ' ', '\t', '\n', 'r', '\f' }; + + }; -protected: + //===== templated chars classes =========================== + //--- is_alpha() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + inline const bool is_alpha(const CharT ch) { 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) { return std::isalpha(static_cast(ch)); } -private: - //=== DATA ============================================ - static inline constexpr std::vector _ASCII_PUNCT_DATA { '!', ',', '.', ':', ';', '?' }; - static inline constexpr std::vector _ASCII_SPACES { ' ', '\t', '\n', 'r', '\f' }; + /** \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) { return std::iswalpha(ch); } -}; +} // end of namespace pcs // (pythonic c++ strings) \ No newline at end of file From 0f1e18f27989fbf1c88bf4cf07613b2a1b48e76f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 22:49:34 +0100 Subject: [PATCH 037/220] #71 - Modify method is_punctuation() Completed. --- cpp-strings/cppstrings.h | 60 ++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 786a59f..d539b70 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -41,22 +41,26 @@ namespace pcs // i.e. "pythonic c++ strings" class CharT, class TraitsT = std::char_traits, class AllocatorT = std::allocator - > class CppStringT; //!< The templated base class. Use its belowing specializations instead! + > class CppStringT; // specializations of the base class -- these are the ones that should be instantiated by user. - using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' - using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' + using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' + using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' // 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); + inline const bool is_alpha(const CharT ch); //!< Returns true if character ch is alphabetic, or false otherwise. */ + + template + inline const bool is_punctuation(const CharT ch); //!< Returns true if character ch is punctuation, or false otherwise. */ + + template + inline const bool is_space(const CharT ch); //!< Returns true if character ch is white space, or false otherwise. */ //===== CppStringT<> ====================================== - /** - * \brief This is the templated base class for all CppString - * classes. + /** \brief This is the templated base class for all CppString classes. * * Users should instantiate any specialization of this base class * rather than this base class itself: @@ -405,13 +409,7 @@ namespace pcs // i.e. "pythonic c++ strings" /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool is_punctuation() const noexcept { - return this->size() == 1 && is_punctuation((*this)[0]); - } - - /** \brief Returns true if character belongs to the ASCII punctuation set. */ - static inline const bool is_punctuation(const value_type& ch) noexcept - { - return _ASCII_PUNCT_DATA.contains(ch); + return this->size() == 1 && pcs::is_punctuation((*this)[0]); } @@ -665,4 +663,38 @@ namespace pcs // i.e. "pythonic c++ strings" template<> inline const bool is_alpha(const wchar_t ch) { return std::iswalpha(ch); } + + //--- is_punctuation ---------------------------------- + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + inline const bool is_punctuation(const CharT ch) + { + static const std::vector punct_chars{ '!', ',', '.', ':', ';', '?' }; + return std::find(punct_chars.cbegin(), punct_chars.cend(), (ch)) != punct_chars.cend(); + } + + /** \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) + { + static const std::vector punct_chars { '!', ',', '.', ':', ';', '?' }; + return std::find(punct_chars.cbegin(), punct_chars.cend(), (ch)) != punct_chars.cend(); + } + */ + + /** \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) + { + static const std::vector punct_chars{ '!', ',', '.', ':', ';', '?' }; + return std::find(punct_chars.cbegin(), punct_chars.cend(), (ch)) != punct_chars.cend(); + } + */ + + //--- is_space() -------------------------------------- + template + inline const bool is_space(const CharT ch); //!< Returns true if character ch is white space, or false otherwise. */ + } // end of namespace pcs // (pythonic c++ strings) \ No newline at end of file From f4c308c99b4b1cf1eff90fa5c27fc0851e892613 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 11 Mar 2023 22:57:12 +0100 Subject: [PATCH 038/220] #70 - Modify method is_space() Completed. --- cpp-strings/cppstrings.cpp | 4 +++ cpp-strings/cppstrings.h | 68 ++++++++++---------------------------- 2 files changed, 22 insertions(+), 50 deletions(-) diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index ec199f7..c6307ab 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -19,6 +19,8 @@ along with this program. If not, see . */ +#include + #include "cppstrings.h" using namespace pcs; @@ -30,5 +32,7 @@ int main() CppString s; CppWString ws; + //std::cout << ws.isspace() << std::endl; + return 0; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index d539b70..7a3b92c 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -405,35 +405,21 @@ namespace pcs // i.e. "pythonic c++ strings" } - //--- is_punctuation() -------------------------------- + //--- ispunctuation() --------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ - inline const bool is_punctuation() const noexcept + inline const bool ispunctuation() const noexcept { return this->size() == 1 && pcs::is_punctuation((*this)[0]); } - //--- is_space() -------------------------------------- - /** \brief Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise. - * - * Notice for version 2.0 of this library: a character is whitespace if - * in the Unicode character database, either its general category is Zs - * (“Separator, space”), or its bidirectional class is one of WS, B, or S. - */ - inline const bool is_space() const noexcept + //--- is_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 { if (this->size() == 0) return false; - for (auto& c : *this) - if (!is_space(c)) - return false; - return true; - } - - /** \brief Returns true if character belongs to the ASCII spaces set. */ - static inline const bool is_space(const value_type& ch) noexcept - { - return _ASCII_SPACES.contains(ch); + else + return std::all_of(this->cbegin(), this->cend(), pcs::is_space); } @@ -441,13 +427,7 @@ 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 is_space() || is_punctuation(); - } - - /** \brief Returns true if character belongs to ASCII spaces or punctuation sets. */ - static inline const bool is_words_sep(const value_type& ch) noexcept - { - return is_space(ch) || is_punctuation(ch); + return isspace() || ispunctuation(); } @@ -641,9 +621,6 @@ namespace pcs // i.e. "pythonic c++ strings" private: - //=== DATA ============================================ - static inline constexpr std::vector _ASCII_PUNCT_DATA{ '!', ',', '.', ':', ';', '?' }; - static inline constexpr std::vector _ASCII_SPACES{ ' ', '\t', '\n', 'r', '\f' }; }; @@ -665,7 +642,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- is_punctuation ---------------------------------- - /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ template inline const bool is_punctuation(const CharT ch) { @@ -673,28 +650,19 @@ namespace pcs // i.e. "pythonic c++ strings" return std::find(punct_chars.cbegin(), punct_chars.cend(), (ch)) != punct_chars.cend(); } - /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ - /* + + //--- is_space() -------------------------------------- + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + inline const bool is_space(const CharT ch) { return false; } + + /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> - inline const bool is_punctuation(const char ch) - { - static const std::vector punct_chars { '!', ',', '.', ':', ';', '?' }; - return std::find(punct_chars.cbegin(), punct_chars.cend(), (ch)) != punct_chars.cend(); - } - */ + inline const bool is_space(const char ch) { return std::isspace(static_cast(ch)); } - /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ - /* + /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> - inline const bool is_punctuation(const wchar_t ch) - { - static const std::vector punct_chars{ '!', ',', '.', ':', ';', '?' }; - return std::find(punct_chars.cbegin(), punct_chars.cend(), (ch)) != punct_chars.cend(); - } - */ + inline const bool is_space(const wchar_t ch) { return std::iswspace(ch); } - //--- is_space() -------------------------------------- - template - inline const bool is_space(const CharT ch); //!< Returns true if character ch is white space, or false otherwise. */ } // end of namespace pcs // (pythonic c++ strings) \ No newline at end of file From 4903ec2af732ff20092d40e8f1c9c292e931eac8 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 01:22:44 +0100 Subject: [PATCH 039/220] #23 - Implement method CppStringT::isascii() Completed. --- cpp-strings/cppstrings.h | 58 +++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 7a3b92c..806c4f9 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -44,18 +44,21 @@ namespace pcs // i.e. "pythonic c++ strings" > class CppStringT; // specializations of the base class -- these are the ones that should be instantiated by user. - using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' - using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' + using CppString = CppStringT; //!< Specialization of basic class with template argument 'char' + using CppWString = CppStringT; //!< Specialization of basic class with template argument 'wchar_t' // 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); //!< Returns true if character ch is alphabetic, or false otherwise. */ + inline const bool is_alpha(const CharT ch) noexcept; //!< Returns true if character ch is alphabetic, or false otherwise. template - inline const bool is_punctuation(const CharT ch); //!< Returns true if character ch is punctuation, or false otherwise. */ + 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_space(const CharT ch); //!< Returns true if character ch is white space, or false otherwise. */ + inline const bool is_punctuation(const CharT ch) noexcept; //!< Returns true if character ch is punctuation, or false otherwise. + + template + inline const bool is_space(const CharT ch) noexcept; //!< Returns true if character ch is white space, or false otherwise. @@ -384,6 +387,17 @@ 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 + inline const bool isascii() const noexcept + { + return this->size() == 0 || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii); + } + + //--- isdecimal() ------------------------------------- inline const bool isdecimal() const noexcept { @@ -413,7 +427,8 @@ namespace pcs // i.e. "pythonic c++ strings" } - //--- is_Returns true if there are only whitespace characters in the string and there is at least one character, or false otherwise. */- + //--- isspace() --------------------------------------- + /** \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 { if (this->size() == 0) @@ -630,39 +645,52 @@ namespace pcs // i.e. "pythonic c++ strings" //--- is_alpha() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template - inline const bool is_alpha(const CharT ch) { return false; } + inline const bool is_alpha(const CharT ch) noexcept + { return false; } /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> - inline const bool is_alpha(const char ch) { return std::isalpha(static_cast(ch)); } + inline const bool is_alpha(const char ch) noexcept + { return 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) { return std::iswalpha(ch); } + inline const bool is_alpha(const wchar_t ch) noexcept + { return 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); } - //--- is_punctuation ---------------------------------- + //--- is_punctuation() ------------------------------------ /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ template - inline const bool is_punctuation(const CharT ch) + inline const bool is_punctuation(const CharT ch) noexcept { static const std::vector punct_chars{ '!', ',', '.', ':', ';', '?' }; return std::find(punct_chars.cbegin(), punct_chars.cend(), (ch)) != punct_chars.cend(); } - //--- is_space() -------------------------------------- + //--- is_space() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template - inline const bool is_space(const CharT ch) { return false; } + inline const bool is_space(const CharT ch) noexcept + { return false; } /** \brief Returns true if character ch is alphabetic, or false otherwise. Conforms to the current locale settings. */ template<> - inline const bool is_space(const char ch) { return std::isspace(static_cast(ch)); } + inline const bool is_space(const char ch) noexcept + { return 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) { return std::iswspace(ch); } + inline const bool is_space(const wchar_t ch) noexcept + { return std::iswspace(ch); } } // end of namespace pcs // (pythonic c++ strings) \ No newline at end of file From 66d1acd71cd6b4fd8fbec463c3c48fdd35b50c7e Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 01:40:58 +0100 Subject: [PATCH 040/220] #24 - Implement method CppStringT::isdecimal() Completed. --- cpp-strings/cppstrings.h | 60 ++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 806c4f9..87f92db 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -54,6 +54,9 @@ namespace pcs // i.e. "pythonic c++ strings" template inline const bool is_ascii(const CharT ch) noexcept; //!< Returns true if character ch gets ASCII code, or false otherwise. + template + inline const bool is_decimal(const CharT ch) noexcept; //!< Returns true if character is a decimal digit, or false otherwise. + template inline const bool is_punctuation(const CharT ch) noexcept; //!< Returns true if character ch is punctuation, or false otherwise. @@ -380,28 +383,31 @@ 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 { - if (this->size() == 0) - return false; - else - return std::all_of(this->cbegin(), this->cend(), [](const value_type ch) { return pcs::is_alpha(ch); }); + return this->size() > 0 && std::all_of(this->cbegin(), this->cend(), [](const value_type ch) { return pcs::is_alpha(ch); }); } //--- 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 + #if defined(isascii) // may be already defined in header file #undef isascii #endif inline const bool isascii() const noexcept { - return this->size() == 0 || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii); + return this->size() == 0 || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii); } //--- isdecimal() ------------------------------------- + /** \brief Returns true if all characters in the string are decimal characters and there is at least one character, or false otherwise. + * + * Decimal characters are those that can be used to form numbers in + * base 10, e.g. U+0660, ARABIC-INDIC DIGIT ZERO. Formally a decimal + * character is a character in the Unicode General Category “Nd”. + */ inline const bool isdecimal() const noexcept { - return false; + return this->size() > 0 && std::all_of(this->cbegin(), this->cend(), pcs::is_decimal); } @@ -666,15 +672,45 @@ namespace pcs // i.e. "pythonic c++ strings" { return CharT(0x00) <= ch && ch <= CharT(0x7f); } - //--- is_punctuation() ------------------------------------ - /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ + //--- is_decimal() ---------------------------------------- + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template - inline const bool is_punctuation(const CharT ch) noexcept + inline const bool is_decimal(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character is a decimal digit, or false otherwise. */ + template<> + inline const bool is_decimal(const char ch) noexcept { - static const std::vector punct_chars{ '!', ',', '.', ':', ';', '?' }; - return std::find(punct_chars.cbegin(), punct_chars.cend(), (ch)) != punct_chars.cend(); + return 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::isdigit(ch); + } + + + //--- is_punctuation() ------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + inline const bool is_punctuation(const CharT ch) noexcept + { return false; } + + /** \brief Returns true if character ch is punctuation, or false otherwise. Conforms to the current locale settings. */ + template<> + inline const bool is_punctuation(const char ch) noexcept + { return 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); } + //--- is_space() ------------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ From 0bd3d0a81ce9d524d60daa16503a7380542088da Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 01:46:10 +0100 Subject: [PATCH 041/220] #25 - Implement method CppStringT::isdigit() Completed. --- cpp-strings/cppstrings.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 87f92db..d315d0c 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -412,9 +412,21 @@ namespace pcs // i.e. "pythonic c++ strings" //--- isdigit() --------------------------------------- + /** \brief Returns true if all characters in the string are digits and there is at least one character, or false otherwise. + * + * Digits include decimal characters and digits that need special + * handling, such as the compatibility superscript digits. This + * covers digits which cannot be used to form numbers in base 10, + * like the Kharosthi numbers. Formally, a digit is a character + * that has the property value Numeric_Type=Digit or Numeric_Type=Decimal. + * + * CAUTION: current implementation of library cpp-strings does + * not implement above algorithm. It just returns the same result + * as 'isdecimal()' which is NOT what Python str library does. + */ inline const bool isdigit() const noexcept { - return false; + return isdecimal(); } From 27edefcab298da0291a331e5839bca7414416eba Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 13:18:19 +0100 Subject: [PATCH 042/220] #26 - Implement method CppStringT::isidentifier() Completed. A few fixes on strings emptyness evaluation plus one code simplification. --- cpp-strings/cppstrings.h | 72 ++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index d315d0c..0343f9f 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -54,9 +54,15 @@ namespace pcs // i.e. "pythonic c++ strings" template inline const bool is_ascii(const CharT ch) noexcept; //!< Returns true if character ch gets ASCII code, or false otherwise. + template + inline const bool is_id_continue(const CharT ch) noexcept; //!< Returns true if character is a continuing char for identifiers, or false otherwise. + template inline const bool is_decimal(const CharT ch) noexcept; //!< Returns true if character is a decimal digit, or false otherwise. + template + inline const bool is_id_start(const CharT ch) noexcept; //!< Returns true if character is a starting char for identifiers, or false otherwise. + template inline const bool is_punctuation(const CharT ch) noexcept; //!< Returns true if character ch is punctuation, or false otherwise. @@ -383,7 +389,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->size() > 0 && 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(), [](const value_type ch) { return pcs::is_alpha(ch); }); } @@ -394,7 +400,7 @@ namespace pcs // i.e. "pythonic c++ strings" #endif inline const bool isascii() const noexcept { - return this->size() == 0 || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii); + return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_ascii); } @@ -407,7 +413,7 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline const bool isdecimal() const noexcept { - return this->size() > 0 && std::all_of(this->cbegin(), this->cend(), pcs::is_decimal); + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_decimal); } @@ -418,7 +424,8 @@ namespace pcs // i.e. "pythonic c++ strings" * 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. + * 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 @@ -430,6 +437,32 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- isidentifier() ---------------------------------- + /** \brief Returns true if the string is not empty and is a valid identifier according to the language definition, or false otherwise. + * + * CAUTION: the current implementation of this method does not deal with the proper c++ + * defintiion of identifiers (see https://en.cppreference.com/w/cpp/language/identifiers + * and https://www.unicode.org/reports/tr31/#Table_Lexical_Classes_for_Identifiers). + * + * While the specification of identifiers in c++ is this one: + * + * identifier ::= XID_Start XID_Continue* + * XID_Start ::= ID_Start XID_Continue* + * ID_Start ::= + * XID_Continue ::= + * ID_Continue ::= ID_Start | + * + * the currently implemented rule is this simpler one: + * + * identifier ::= ID_Start id_continue* + * id_continue ::= ID_Start | + */ + 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)); + } + + //--- isnumeric() ------------------------------------- inline const bool isnumeric() const noexcept { @@ -449,10 +482,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 { - if (this->size() == 0) - return false; - else - return std::all_of(this->cbegin(), this->cend(), pcs::is_space); + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_space); } @@ -688,23 +718,31 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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 std::isdigit(static_cast(ch)); - } + { return 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::isdigit(ch); - } + { return std::iswdigit(ch); } + + + //--- is_id_continue() ------------------------------------ + /** \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); } + + + //--- 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('_'); } //--- is_punctuation() ------------------------------------ From b41823bb09eb0e18b9b17d2f1be77f1120a63652 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 14:42:40 +0100 Subject: [PATCH 043/220] #27 - Implement method CppStringT::islower() Completed. --- cpp-strings/cppstrings.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 0343f9f..29ad3c5 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -63,6 +63,9 @@ namespace pcs // i.e. "pythonic c++ strings" template inline const bool is_id_start(const CharT ch) noexcept; //!< Returns true if character is a starting char for identifiers, or false otherwise. + template + inline const bool is_lower(const CharT ch) noexcept; //!< Returns true if character is lowercase, or false otherwise. + template inline const bool is_punctuation(const CharT ch) noexcept; //!< Returns true if character ch is punctuation, or false otherwise. @@ -463,6 +466,14 @@ 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. */ + inline const bool islower() const noexcept + { + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_lower); + } + + //--- isnumeric() ------------------------------------- inline const bool isnumeric() const noexcept { @@ -745,6 +756,29 @@ namespace pcs // i.e. "pythonic c++ strings" { return pcs::is_alpha(ch) || ch == CharT('_'); } + //--- is_lower() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + inline const bool is_lower(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale settings. */ + template<> + inline const bool is_lower(const char ch) noexcept + { + return std::islower(static_cast(ch)); + } + + /** \brief Returns true if character ch is lowercase, or false otherwise. Conforms to the current locale settings. */ + template<> + inline const bool is_lower(const wchar_t ch) noexcept + { + return std::iswlower(ch); + } + + //--- is_punctuation() ------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template From f8f6970a54b6070650c63108333c9809a1a1d3c3 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 18:02:44 +0100 Subject: [PATCH 044/220] #28 - Implement method CppStringT::isnumeric() Completed. --- cpp-strings/cppstrings.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 29ad3c5..b37eab2 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -475,9 +475,18 @@ namespace pcs // i.e. "pythonic c++ strings" //--- isnumeric() ------------------------------------- + /** \brief Returns true if all characters in the string are numeric characters, and there is at least one character, or false otherwise. + * + * CAUTION: current implementation just returns isdecimal() result, + * while the description of isnumeric() should be this one: + * Numeric characters include digit characters, and all characters + * that have the Unicode numeric value property. Formally, numeric + * characters are those with the property value Numeric_Type=Digit, + * Numeric_Type=Decimal or Numeric_Type=Numeric. + */ inline const bool isnumeric() const noexcept { - return false; + return isdecimal(); } From 46387e1a8d9d42aa00806d8c1085ca1ad694aad1 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 18:09:54 +0100 Subject: [PATCH 045/220] #29 - Implement method CppStringT::isprintable() Completed. --- cpp-strings/cppstrings.h | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index b37eab2..130c755 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -64,7 +64,10 @@ namespace pcs // i.e. "pythonic c++ strings" inline const bool is_id_start(const CharT ch) noexcept; //!< Returns true if character is a starting char for identifiers, or false otherwise. template - inline const bool is_lower(const CharT ch) noexcept; //!< Returns true if character is lowercase, or false otherwise. + inline const bool is_lower(const CharT ch) noexcept; //!< Returns true if character is lowercase, or false otherwise. + + template + inline const bool is_printable(const CharT ch) noexcept; //!< Returns true if character ch is printable, or false otherwise. template inline const bool is_punctuation(const CharT ch) noexcept; //!< Returns true if character ch is punctuation, or false otherwise. @@ -490,6 +493,19 @@ 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 + * space (0x20) which is considered printable. + */ + inline const bool isprintable() const noexcept + { + return this->empty() || std::all_of(this->cbegin(), this->cend(), pcs::is_printable); + } + + //--- ispunctuation() --------------------------------- /** \brief Returns true if the string contains only one character and if this character belongs to the ASCII punctuation set. */ inline const bool ispunctuation() const noexcept @@ -788,6 +804,27 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- is_printable() -------------------------------------- + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + inline const bool is_printable(const CharT ch) noexcept + { return false; } + + /** \brief Returns true if character ch is printable, or false otherwise. */ + template<> + inline const bool is_printable(const char ch) noexcept + { + return 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); + } + + //--- is_punctuation() ------------------------------------ /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ template From bee370ff02c4e52b102814737be31137c0b5f213 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 18:18:19 +0100 Subject: [PATCH 046/220] #31 - Implement method CppStringT::istitle() Completed. --- cpp-strings/cppstrings.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 130c755..69569d2 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -522,6 +522,18 @@ 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 + * characters and lowercase characters only cased ones. + */ + inline const bool istitle() const noexcept + { + return !this->empty && this->title() == *this; + } + + //--- 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. */ inline const bool is_words_sep() const noexcept @@ -691,6 +703,14 @@ 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. */ + inline CppStringT title() const noexcept + { + return *this; + } + + //--- upper () ----------------------------------------- /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. * From 4ee68e3f7af174adf481c614cebc19f1161609fc Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 18:21:35 +0100 Subject: [PATCH 047/220] #32 - Implement method CppStringT::isupper() Completed. --- cpp-strings/cppstrings.cpp | 2 +- cpp-strings/cppstrings.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index c6307ab..3c9c506 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -32,7 +32,7 @@ int main() CppString s; CppWString ws; - //std::cout << ws.isspace() << std::endl; + std::cout << ws.isupper() << std::endl; return 0; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 69569d2..9665aa9 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -75,6 +75,9 @@ namespace pcs // i.e. "pythonic c++ strings" template inline const bool is_space(const CharT ch) noexcept; //!< Returns true if character ch is white space, or false otherwise. + template + inline const bool is_upper(const CharT ch) noexcept; //!< Returns true if character is uppercase, or false otherwise. + //===== CppStringT<> ====================================== @@ -534,6 +537,14 @@ 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. */ + inline const bool isupper() const noexcept + { + return !this->empty() && std::all_of(this->cbegin(), this->cend(), pcs::is_upper); + } + + //--- is_words_sep() ---------------------------------- /** \brief Returns true if there are only whitespace and punctuation characters in the string and there is at least one character, or false otherwise. */ inline const bool is_words_sep() const noexcept @@ -879,4 +890,26 @@ namespace pcs // i.e. "pythonic c++ strings" { return std::iswspace(ch); } + //--- is_upper() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + inline const bool is_upper(const CharT ch) noexcept + { + return false; + } + + /** \brief Returns true if character ch is uppercase, or false otherwise. Conforms to the current locale settings. */ + template<> + inline const bool is_upper(const char ch) noexcept + { + return 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); + } + } // end of namespace pcs // (pythonic c++ strings) \ No newline at end of file From e0f0489705734423fdc2fb7c1bcddd986e033f7c Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 21:18:58 +0100 Subject: [PATCH 048/220] #33 - Implement method CppStringT::join() Completed. --- cpp-strings/cppstrings.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 9665aa9..b10ab38 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -553,6 +554,31 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- join() ------------------------------------------ + /** \brief Returns a string which is the concatenation of the strings in the parameters list. + * + * The separator between elements is the string to which this method is applied. + */ + template + inline CppStringT join(const CppStringT& first, const NextCppStringsT... others) const noexcept + requires (sizeof...(others) > 0) + { + return first + *this + this->join(others...); + } + + /** \brief A single parameter signature. Returns a copy of this parameter. */ + inline const CppStringT join(const CppStringT& s) const noexcept + { + return s; + } + + /** \brief Empty parameters list signature. Returns a copy of current string. */ + inline const CppStringT join() const noexcept + { + return *this; + } + + //--- lower () ----------------------------------------- /** \brief In-place replaces all characters of the string with their lowercase conversion. Returns a reference to string. * From fad66410d9d98fc0f5dc6dd78a0b51506257b5d1 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 21:24:45 +0100 Subject: [PATCH 049/220] #34 - Implement method CppStringT::ljust() Completed. --- cpp-strings/cppstrings.h | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index b10ab38..c7d37ac 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -566,7 +566,7 @@ namespace pcs // i.e. "pythonic c++ strings" return first + *this + this->join(others...); } - /** \brief A single parameter signature. Returns a copy of this parameter. */ + /** \brief Single parameter signature. Returns a copy of this parameter. */ inline const CppStringT join(const CppStringT& s) const noexcept { return s; @@ -579,6 +579,21 @@ 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). + * 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 + { + if (this->size() >= width) + return *this; + else + return CppStringT(width - this->size(), fillch) + *this; + } + + //--- lower () ----------------------------------------- /** \brief In-place replaces all characters of the string with their lowercase conversion. Returns a reference to string. * From b6b54d6c5129a8ce3fc59f488b8051b87fc2ba2b Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 21:41:26 +0100 Subject: [PATCH 050/220] #36 - Implement method CppStringT::lstrip() Completed. --- cpp-strings/cppstrings.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index c7d37ac..dcc0e35 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -603,8 +603,8 @@ 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; } @@ -619,6 +619,23 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- lstrip() ---------------------------------------- + /** \brief Return a copy of the string with leading characters removed. + * + * The passed string specifies the set of characters to be removed. + * If omitted, the chars argument defaults to removing whitespace. + * The chars argument is not a prefix; rather, all combinations of + * its values are stripped. + */ + 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; })) + return CppStringT(it, this->cend()); + return CppStringT(); + } + + //--- 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. * @@ -772,8 +789,8 @@ 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); }); + this->begin(), + [](value_type ch) { return this->upper(ch); }); return *this; } From 76a222eddb37fdcc07b1f83d5d9f48f0f4eb4632 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 23:51:07 +0100 Subject: [PATCH 051/220] #38 - Implement method CppStringT::partition() 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 dcc0e35..fdecd76 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -620,10 +621,9 @@ namespace pcs // i.e. "pythonic c++ strings" //--- lstrip() ---------------------------------------- - /** \brief Return a copy of the string with leading characters removed. + /** \brief Returns a copy of the string with leading characters removed. * * The passed string specifies the set of characters to be removed. - * If omitted, the chars argument defaults to removing whitespace. * The chars argument is not a prefix; rather, all combinations of * its values are stripped. */ @@ -635,6 +635,35 @@ namespace pcs // i.e. "pythonic c++ strings" return CppStringT(); } + /** \brief Returns a copy of the string with leading whitespaces removed. */ + inline CppStringT lstrip() const noexcept + { + for (auto it = this->cbegin(); it != this->cend(); ++it) + if (*it != value_type(' ')) + return CppStringT(it, this->cend()); + return CppStringT(); + } + + + //--- 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. + * + * If the separator is not found, returns a 3-items vector + * containing the string itself, followed by two empty strings. + */ + std::vector partition(const CppStringT& sep) const noexcept + { + const size_type sep_index = find(sep); + if (sep_index == CppStringT::npos) { + return std::vector({ *this, CppStringT(), CppStringT() }); + } + else { + const size_type third_index = sep_index + sep.size(); + const size_type third_size = this->size() - third_index + 1; + return std::vector({ substr(0, sep_index), sep, substr(third_index, third_size) }); + } + } + //--- 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. From a9733c0cc202d786fe0cae651c651cdf7972e8b0 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sun, 12 Mar 2023 23:57:56 +0100 Subject: [PATCH 052/220] #39 - Implement method CppStringT::removeprefix() Completed. --- cpp-strings/cppstrings.h | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index fdecd76..c2edc66 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -626,6 +626,7 @@ namespace pcs // i.e. "pythonic c++ strings" * 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()'. */ inline CppStringT lstrip(const CppStringT& prefix) const noexcept { @@ -655,16 +656,30 @@ namespace pcs // i.e. "pythonic c++ strings" { const size_type sep_index = find(sep); if (sep_index == CppStringT::npos) { - return std::vector({ *this, CppStringT(), CppStringT() }); + const CppStringT empty{}; + return std::vector({ *this, empty, empty }); } else { const size_type third_index = sep_index + sep.size(); const size_type third_size = this->size() - third_index + 1; - return std::vector({ substr(0, sep_index), sep, substr(third_index, third_size) }); + return std::vector({ this->substr(0, sep_index), sep, this->substr(third_index, third_size) }); } } + //--- removeprefix() ---------------------------------- + /** \brief If the string starts with the prefix string, returns a new string with the prefix removed. Otherwise, returns a copy of the original string. */ + inline CppStringT removeprefix(const CppStringT& prefix) const noexcept + { + if (this->startswith(prefix)) { + const size_type prefix_length = prefix.size(); + return this->substr(prefix_length, this->size - prefix_length + 1); + } + else + return *this; + } + + //--- 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. * @@ -809,6 +824,13 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- startswith -------------------------------------- + inline const bool startswith(const CppStringT& prefix) const noexcept + { + return false; + } + + //--- upper () ----------------------------------------- /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. * From de3e8e040acff87d656455c508dc0571f9dbd7fb Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 13 Mar 2023 00:03:13 +0100 Subject: [PATCH 053/220] #40 - Implement method CppStringT::removesuffix() Completed. Fixed wrong ordering on methods definitions. --- cpp-strings/cppstrings.h | 53 +++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index c2edc66..0c32b31 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -216,24 +216,6 @@ 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. - * - * 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_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 - { - if (start > end) - return CppStringT::npos; - else - return find_n(sub, start, end - start + 1); - } - - //--- endswith() -------------------------------------- /** 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 @@ -269,7 +251,7 @@ 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. */ + /** 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); @@ -317,6 +299,24 @@ 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. + * + * 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_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 + { + if (start > end) + return CppStringT::npos; + else + return find_n(sub, start, end - start + 1); + } + + //--- 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. * @@ -673,7 +673,20 @@ namespace pcs // i.e. "pythonic c++ strings" { if (this->startswith(prefix)) { const size_type prefix_length = prefix.size(); - return this->substr(prefix_length, this->size - prefix_length + 1); + return this->substr(prefix_length, this->size() - prefix_length + 1); + } + else + return *this; + } + + + //--- removesuffix() ---------------------------------- + /** \brief If the string ends with the suffix string, returns a new string with the suffix removed. Otherwise, returns a copy of the original string. */ + inline CppStringT removesuffix(const CppStringT& suffix) const noexcept + { + if (this->endswith(suffix)) { + const size_type suffix_length = suffix.size(); + return this->substr(0, this->size() - suffix_length + 1); } else return *this; From f7883808afafc831c635067d6858187782e34d11 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 13 Mar 2023 00:14:08 +0100 Subject: [PATCH 054/220] #41 - Implement method CppStringT::replace() Completed. --- cpp-strings/cppstrings.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 0c32b31..82dbe79 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -693,6 +693,27 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- replace() --------------------------------------- + /** \brief Returns a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced. */ + inline 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; + } + + //--- 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. * From faaa9422a296698c56b56d23c7b5e0a1ae99d5f5 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 13 Mar 2023 00:16:51 +0100 Subject: [PATCH 055/220] #44 - Implement method CppStringT::rjust() Completed. --- cpp-strings/cppstrings.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 82dbe79..46bb2fb 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -591,7 +591,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); } @@ -850,6 +850,22 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- rjust() ----------------------------------------- + /** \brief Returns the string right justified in a string of length width. + * + * Padding is done using the specified fillchar (default is an ASCII space). + * The original string is returned if width is less than or equal to len(s). + */ + inline CppStringT rjust(const size_type width, const value_type fillch = value_type(' ')) const noexcept + { + if (this->size() >= width) + return *this; + else + return CppStringT(width - this->size(), fillch) + *this; + } + + + //--- title() ----------------------------------------- /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ inline CppStringT title() const noexcept From 8126e7a1e00b978f4f5fbec5166db199b0ae4969 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 13 Mar 2023 00:20:47 +0100 Subject: [PATCH 056/220] #41 - Implement method CppStringT::replace() Added missing signature. --- cpp-strings/cppstrings.h | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 46bb2fb..6497a1e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -694,7 +694,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- replace() --------------------------------------- - /** \brief Returns a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced. */ + /** \brief Returns a copy of the string with all occurrences of substring old replaced by new. */ inline CppStringT replace(const CppStringT& old, const CppStringT& new_) const noexcept { if (!this->contains(old)) @@ -707,12 +707,34 @@ namespace pcs // i.e. "pythonic c++ strings" 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. */ + inline CppStringT replace(const CppStringT& old, const CppStringT& new_, size_type count) const noexcept + { + if (!this->contains(old) || count == 0) + return *this; + + CppStringT res{}; + size_type last_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; + --count; + } + + if (last_index != this->size()) + res += this->substr(last_index, this->size - last_index); + + return res; + } + //--- 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. From 6d3729eacf5bdf1ced334d92b520da909b98728d Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 13 Mar 2023 00:23:03 +0100 Subject: [PATCH 057/220] #45 - Implement method CppStringT::rpartition() Completed. --- cpp-strings/cppstrings.h | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 6497a1e..a643413 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -695,7 +695,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- replace() --------------------------------------- /** \brief Returns a copy of the string with all occurrences of substring old replaced by new. */ - inline CppStringT replace(const CppStringT& old, const CppStringT& new_) const noexcept + CppStringT replace(const CppStringT& old, const CppStringT& new_) const noexcept { if (!this->contains(old)) return *this; @@ -715,7 +715,7 @@ namespace pcs // i.e. "pythonic c++ strings" } /** \brief Returns a copy of the string with first count occurrences of substring old replaced by new. */ - inline CppStringT replace(const CppStringT& old, const CppStringT& new_, size_type count) const noexcept + CppStringT replace(const CppStringT& old, const CppStringT& new_, size_type count) const noexcept { if (!this->contains(old) || count == 0) return *this; @@ -736,6 +736,27 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- rpartition() ------------------------------------- + /** Split 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. + */ + std::vector rpartition(const CppStringT& sep) const noexcept + { + const size_type sep_index = rfind(sep); + if (sep_index == CppStringT::npos) { + const CppStringT empty{}; + return std::vector({ *this, empty, empty }); + } + else { + const size_type third_index = sep_index + sep.size(); + const size_type third_size = this->size() - third_index + 1; + return std::vector({ this->substr(0, sep_index), sep, this->substr(third_index, third_size) }); + } + } + + //--- 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. * From b235aef1b13e1102e868dbdf403882f3f406e89f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Mon, 13 Mar 2023 07:18:37 +0100 Subject: [PATCH 058/220] #46 - Implement method CppStringT::rsplit() Completed. --- cpp-strings/cppstrings.h | 120 ++++++++++++++++++++++++++++++++------- 1 file changed, 99 insertions(+), 21 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index a643413..399c9f2 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -736,27 +736,6 @@ namespace pcs // i.e. "pythonic c++ strings" } - //--- rpartition() ------------------------------------- - /** Split 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. - */ - std::vector rpartition(const CppStringT& sep) const noexcept - { - const size_type sep_index = rfind(sep); - if (sep_index == CppStringT::npos) { - const CppStringT empty{}; - return std::vector({ *this, empty, empty }); - } - else { - const size_type third_index = sep_index + sep.size(); - const size_type third_size = this->size() - third_index + 1; - return std::vector({ this->substr(0, sep_index), sep, this->substr(third_index, third_size) }); - } - } - - //--- 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. * @@ -908,6 +887,105 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- rpartition() ------------------------------------- + /** Split 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. + */ + std::vector rpartition(const CppStringT& sep) const noexcept + { + const size_type sep_index = rfind(sep); + if (sep_index == CppStringT::npos) { + const CppStringT empty{}; + return std::vector({ *this, empty, empty }); + } + else { + const size_type third_index = sep_index + sep.size(); + const size_type third_size = this->size() - third_index + 1; + return std::vector({ this->substr(0, sep_index), sep, this->substr(third_index, third_size) }); + } + } + + + //--- rsplit() ---------------------------------------- + /** \brief Returns a vector of the words in the string, as seperated with whitespace strings. */ + inline std::vector rsplit() const noexcept + { + return split(); + } + + /** \brief Returns a vector of the words in the string, using sep as the delimiter string. */ + inline std::vector rsplit(const CppStringT& sep) const 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 + { + if (maxsplit == 0) + return *this; + + constexpr CppStringT spc2(" "); + constexpr CppStringT spc(value_type(' ')); + CppStringT tmp = *this; + while (tmp.contains(spc2)) + tmp = tmp.replace(spc2, spc); + + return this->rsplit(spc, 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. Except + * for splitting from the right, rsplit() behaves like split()]. + */ + std::vector rsplit(const CppStringT& sep, const size_type maxsplit) const noexcept + { + std::vector res{}; + + std::vector indexes{}; + CppStringT tmp = *this; + size_type count = maxsplit; + size_type index; + while ((index = tmp.rfind(sep)) != CppStringT::npos && count > 0) { + indexes.insert(indexes.begin(), index); + if (index == 0) + break; + tmp = tmp.substr(0, index-1); + 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 + 1; + } + res.push_back(this->substr(index, this->size() - index)); + } + return res; + } + + + //--- split() ----------------------------------------- + inline std::vector split() const noexcept + { + return std::vector(); + } + + /** \brief Returns a vector of the words in the string, using sep as the delimiter string. */ + inline std::vector split(const CppStringT& sep) const noexcept + { + return std::vector(); + } + //--- title() ----------------------------------------- /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ From 861e82c5e104b6bd82fa73567dd8f54b446b16cf Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 14 Mar 2023 22:36:11 +0100 Subject: [PATCH 059/220] #73 - Refactor method CppStringT::rsplit() Completed. --- cpp-strings/cppstrings.h | 125 ++++++++++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 35 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 399c9f2..cd8a9c5 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -106,7 +107,8 @@ namespace pcs // i.e. "pythonic c++ strings" { public: //=== Wrappers ======================================== - using MyBaseClass = std::basic_string; + using MyBaseClass = std::basic_string; + using MyStringView = std::basic_string_view; using traits_type = MyBaseClass::traits_type; using value_type = MyBaseClass::value_type; @@ -141,6 +143,7 @@ namespace pcs // i.e. "pythonic c++ strings" template explicit CppStringT(const StringViewLike& svl) : MyBaseClass(svl) {} + template CppStringT(const StringViewLike& svl, size_type pos, size_type n) : MyBaseClass(svl, pos, n) {} @@ -888,7 +891,7 @@ namespace pcs // i.e. "pythonic c++ strings" //--- rpartition() ------------------------------------- - /** Split 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. + /** 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. @@ -909,67 +912,119 @@ namespace pcs // i.e. "pythonic c++ strings" //--- rsplit() ---------------------------------------- - /** \brief Returns a vector of the words in the string, as seperated with whitespace strings. */ + /** \brief Returns a vector of the words in the whole string, as seperated with whitespace strings. */ inline std::vector rsplit() const noexcept { return split(); } - /** \brief Returns a vector of the words in the string, using sep as the delimiter string. */ + /** \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 { 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. - */ + /** \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 { - if (maxsplit == 0) - return *this; + std::vector res{}; - constexpr CppStringT spc2(" "); - constexpr CppStringT spc(value_type(' ')); - CppStringT tmp = *this; - while (tmp.contains(spc2)) - tmp = tmp.replace(spc2, spc); + 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 this->rsplit(spc, maxsplit); + return res; } /** \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. Except - * for splitting from the right, rsplit() behaves like split()]. + * At most maxsplit splits are done, the rightmost ones. */ std::vector rsplit(const CppStringT& sep, const size_type maxsplit) const noexcept { std::vector res{}; - std::vector indexes{}; - CppStringT tmp = *this; - size_type count = maxsplit; - size_type index; - while ((index = tmp.rfind(sep)) != CppStringT::npos && count > 0) { - indexes.insert(indexes.begin(), index); - if (index == 0) - break; - tmp = tmp.substr(0, index-1); - count--; + if (maxsplit == 0) { + res.push_back({ *this }); } - - 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 + 1; + 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{}; + CppStringT tmp = *this; + size_type count = maxsplit; + size_type index; + while ((index = tmp.rfind(sep)) != CppStringT::npos && count > 0) { + indexes.insert(indexes.begin(), index); + if (index == 0) + break; + tmp = tmp.substr(0, index-1); + 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 + 1; } res.push_back(this->substr(index, this->size() - index)); + */ } + return res; } From a66f7b51d9cb9a1a0b7b77708cd82047942a1c04 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Tue, 14 Mar 2023 22:44:16 +0100 Subject: [PATCH 060/220] #47 - Implement method CppStringT::rstrip() Completed. --- cpp-strings/cppstrings.h | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index cd8a9c5..4a466cd 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -621,7 +621,7 @@ 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. @@ -1029,6 +1029,32 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- rstrip() ---------------------------------------- + /** \brief Returns a copy of the string with trailing characters removed. + * + * The passed string specifies the set of characters to be removed. + * The chars argument is not a prefix; rather, all combinations of + * its values are stripped. + * To remove a suffix, rather call method 'removesuffix()'. + */ + inline CppStringT rstrip(const CppStringT& prefix) 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; })) + return CppStringT(this->cbegin(), it); + return CppStringT(); + } + + /** \brief Returns a copy of the string with trailing whitespaces removed. */ + inline CppStringT rstrip() const noexcept + { + for (auto it = this->crbegin(); it != this->crend(); ++it) + if (*it != value_type(' ')) + return CppStringT(this->cbegin(), it); + return CppStringT(); + } + + //--- split() ----------------------------------------- inline std::vector split() const noexcept { From 2424122c74e5f357113caf96c1c32fa80fd463c1 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 15 Mar 2023 00:05:35 +0100 Subject: [PATCH 061/220] #48 - Implement method CppStringT::split() Completed. --- cpp-strings/cppstrings.h | 111 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 8 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 4a466cd..3faeb47 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -912,7 +912,15 @@ namespace pcs // i.e. "pythonic c++ strings" //--- rsplit() ---------------------------------------- - /** \brief Returns a vector of the words in the whole string, as seperated with whitespace strings. */ + /** \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. + */ inline std::vector rsplit() const noexcept { return split(); @@ -969,10 +977,7 @@ namespace pcs // i.e. "pythonic c++ strings" return res; } - /** \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. - */ + /** \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 res{}; @@ -1056,17 +1061,107 @@ 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. + */ inline std::vector split() const noexcept { - return std::vector(); + std::vector res; + constexpr CppStringT whitespace(value_type(' ')); + for (const auto& word : *this | std::views::split(whitespace)) + if (!word.empty()) + res.push_back(CppStringT(word.begin(), word.end())); + return res; } - /** \brief Returns a vector of the words in the string, using sep as the delimiter string. */ + /** \brief Returns a vector of the words in the whole string, using sep as the delimiter string. + * + * Notice: consecutive delimiters are not grouped together and are + * deemed to delimit empty strings (for example, "1,,2".split(",") + * returns {"1", "", "2"}). The sep argument may consist of multiple + * characters (for example, "1<>2<>3".split("<>") returns {"1", "2", + * "3"]). Splitting an empty string with a specified separator + * returns {""}. + */ inline std::vector split(const CppStringT& sep) const noexcept { - return std::vector(); + std::vector res; + for (const auto& word : *this | std::views::split(sep)) + res.push_back(CppStringT(word.begin(), word.end())); + return res; } + /** \brief Returns a vector of the words in the string, as seperated with whitespace strings. At most maxsplit splits are done, the leftmost ones. */ + std::vector split(const size_type maxsplit) const 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; + } + + /** \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. */ + inline std::vector split(const CppStringT& sep, const size_type maxsplit) const 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()) { + 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; + } + + //--- title() ----------------------------------------- /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ From 90310d79c5b708c35ef743aac4ac3957eecea744 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 15 Mar 2023 00:30:06 +0100 Subject: [PATCH 062/220] #49 - Implement method CppStringT::splitlines() Completed. --- cpp-strings/cppstrings.h | 86 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 3faeb47..5193375 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1131,7 +1131,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. */ - inline std::vector split(const CppStringT& sep, const size_type maxsplit) const noexcept + std::vector split(const CppStringT& sep, const size_type maxsplit) const noexcept { std::vector res{}; @@ -1140,7 +1140,7 @@ namespace pcs // i.e. "pythonic c++ strings" } else { const CppStringT whitespace(value_type(' ')); - std::vector all_words{ this->split(whitespace) }; + std::vector all_words{ this->split(sep) }; size_type count = maxsplit; auto word_it = all_words.cbegin(); @@ -1162,6 +1162,88 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- splitlines() ------------------------------------ + /** \brief Return a list of the lines in the string, breaking at line boundaries. + * + * Line breaks are not included in the resulting list unless keepends is given and true. + * + * This method splits on the following line boundaries. In particular, the boundaries are a superset of universal newlines: + * \n Line Feed + * \r Carriage Return + * \r\n Carriage Return + Line Feed + * \v or \x0b Line Tabulation + * \f or \x0c Form Feed + * \x1c File Separator + * \x1d Group Separator + * \x1e Record Separator + * \x85 Next Line (C1 Control Code) + * \u2028 Line Separator + * \u2029 Paragraph Separator + */ + std::vector splitlines(const bool keep_end = false) const noexcept + { + std::vector res{}; + CppStringT current{}; + bool prev_cr = false; + + for (const value_type& ch : *this) { + switch (ch) { + case 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) + case value_type('\u2028'): // Line Separator + case value_type('\u2029'): // Paragraph Separator +#pragma warning(pop) + if (prev_cr) { + res.push_back(current); + current.clear(); + } + if (keep_end) + current += ch; + res.push_back(current); + current.clear(); + prev_cr = false; + break; + + case value_type('\r'): // Line Feed + if (prev_cr) { + res.push_back(current); + current.clear(); + } + if (keep_end) + current += ch; + prev_cr = true; + break; + + case value_type('\n'): // Line Feed + if (keep_end) + current += ch; + res.push_back(current); + current.clear(); + prev_cr = false; + break; + + + default: + if (prev_cr) { + res.push_back(current); + current.clear(); + } + current += ch; + break; + } + } + + return res; + } + //--- title() ----------------------------------------- /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ From 0b9b7e71adc17d36bc0bd2c204a8ad24ea0bda95 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 15 Mar 2023 18:34:36 +0100 Subject: [PATCH 063/220] #50 - Implement method CppStringT::startswith() Completed. Optimization done also on formerly implemented method `endswith()`. --- cpp-strings/cppstrings.h | 49 +++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 5193375..a990b88 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -243,13 +243,16 @@ 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); + /* for (auto& suffix : suffixes) { if (this->substr(start, end).ends_with(suffix)) return true; } return false; + */ } @@ -1197,7 +1200,7 @@ namespace pcs // i.e. "pythonic c++ strings" case value_type('\x1e'): // Record Separator case value_type('\x85'): // Next Line (C1 Control Code) #pragma warning(push) -#pragma warning(disable: 4566) +#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) @@ -1245,18 +1248,48 @@ 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. */ - inline CppStringT title() const noexcept + //--- 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 { - return *this; + return startswith(std::span{ suffix }, start, end); } + /** 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 + { + return startswith(std::span{ suffix }, 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 + { + return this->starts_with(suffix); + } - //--- startswith -------------------------------------- - inline const bool startswith(const CppStringT& prefix) const noexcept + /** 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 { + 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)) + return true; + } + return false; + */ + } + + + //--- title() ----------------------------------------- + /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ + inline CppStringT title() const noexcept + { + return *this; } From 9845babd19db5edcab4963537a89193f80242a4a Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 15 Mar 2023 18:38:24 +0100 Subject: [PATCH 064/220] #74 - Implement method CppStringT::startswith_n() Completed. --- cpp-strings/cppstrings.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index a990b88..c60aa0b 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1285,6 +1285,26 @@ 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 + { + return startswith(std::span{ 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. */ + inline const bool startswith_n(const CppStringT& suffix, const size_type count) const noexcept + { + return startswith(std::span{ suffix }, 0, count - 1); + } + + /** 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 + { + return startswith(suffixes, start, start + count - 1); + } + + //--- title() ----------------------------------------- /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ inline CppStringT title() const noexcept From 7351b16641171da79fe539c479e72ec85ce4fb56 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 15 Mar 2023 23:07:57 +0100 Subject: [PATCH 065/220] #51 - Implement method CppStringT::strip() Completed. --- cpp-strings/cppstrings.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index c60aa0b..b2e2cc9 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1305,6 +1305,26 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- strip() ----------------------------------------- + /** \brief Returns a copy of the string with the leading and trailing characters removed. + * + * The passed string specifies the set of characters to be removed. + * The chars argument is not a prefix; rather, all combinations of + * its values are stripped. + */ + inline CppStringT strip(const CppStringT& prefix) const noexcept + { + return this->rstrip(prefix).lstrip(prefix); + } + + /** \brief Returns a copy of the string with the leading and trailing whitespaces removed. */ + inline CppStringT strip() const noexcept + { + return this->rstrip().lstrip(); + } + + + //--- title() ----------------------------------------- /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ inline CppStringT title() const noexcept From 00815f48e4f701abac0741d8c9cf7e0a3a9a7578 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 15 Mar 2023 23:36:55 +0100 Subject: [PATCH 066/220] #52 - Implement method CppStringT::swapcase() Completed. --- cpp-strings/cppstrings.h | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index b2e2cc9..2706461 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -81,6 +81,14 @@ namespace pcs // i.e. "pythonic c++ strings" template inline const bool is_upper(const CharT ch) noexcept; //!< Returns true if character is uppercase, or false otherwise. + template + inline const CharT swap_case(const CharT ch) noexcept; //!< Returns the swapped case form of character ch if it exists, or ch itself otherwise. + + template + inline const CharT to_lower(const CharT ch) noexcept; //!< Returns the lowercase form of character ch if it exists, or ch itself otherwise. + + template + inline const CharT to_upper(const CharT ch) noexcept; //!< Returns the uppercase form of character ch if it exists, or ch itself otherwise. //===== CppStringT<> ====================================== @@ -1324,6 +1332,18 @@ namespace pcs // i.e. "pythonic c++ strings" } + //--- swapcase() -------------------------------------- + /** \brief Returns a copy of the string with uppercase characters converted to lowercase and vice versa. + * + * Note that it is not necessarily true that s.swapcase().swapcase() == s. + */ + inline CppStringT swapcase() const noexcept + { + CppStringT res( *this ); + std::transform(this->cbegin(), this->cend(), res.begin(), pcs::swap_case); + return res; + } + //--- title() ----------------------------------------- /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ @@ -1523,4 +1543,65 @@ namespace pcs // i.e. "pythonic c++ strings" return std::iswupper(ch); } + + //--- swap_case() ----------------------------------------- + /** \brief Returns the swapped case form of character ch if it exists, or ch itself otherwise. */ + template + inline const CharT swap_case(const CharT ch) noexcept + { + if (pcs::is_lower(ch)) + return pcs::to_upper(ch); + else if (pcs::is_upper(ch)) + return pcs::to_lower(ch); + else + return ch; + } + + + //--- to_lower() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + inline const CharT to_lower(const CharT ch) noexcept + { + return ch; + } + + /** \brief Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings. */ + template<> + inline const char to_lower(const char ch) noexcept + { + return std::tolower(static_cast(ch)); + } + + /** \brief Returns the lowercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings. */ + template<> + inline const wchar_t to_lower(const wchar_t ch) noexcept + { + return std::towlower(ch); + } + + + //--- to_upper() ------------------------------------------ + /** \brief SHOULD NEVER BE USED. Use next specializations instead. */ + template + inline const CharT to_upper(const CharT ch) noexcept + { + return ch; + } + + /** \brief Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings. */ + template<> + inline const char to_upper(const char ch) noexcept + { + return std::toupper(static_cast(ch)); + } + + /** \brief Returns the uppercase form of character ch if it exists, or ch itself otherwise. Conforms to the current locale settings. */ + template<> + inline const wchar_t to_upper(const wchar_t ch) noexcept + { + return std::towupper(ch); + } + + } // end of namespace pcs // (pythonic c++ strings) \ No newline at end of file From 6996af38aa4117d269ea6e6b6cc90e9aee4cf96b Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 16 Mar 2023 00:30:15 +0100 Subject: [PATCH 067/220] #53 - Implement method CppStringT::title() Completed. Fixed a bug in method `capitalize()`. --- cpp-strings/cppstrings.h | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 2706461..6db8600 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -174,8 +174,10 @@ namespace pcs // i.e. "pythonic c++ strings" /** \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 { - this->lower(); - (*this)[0] = upper((*this)[0]); + if (!this->empty()) { + this->lower(); + (*this)[0] = pcs::to_upper((*this)[0]); + } return *this; } @@ -1339,17 +1341,30 @@ namespace pcs // i.e. "pythonic c++ strings" */ inline CppStringT swapcase() const noexcept { - CppStringT res( *this ); + /* + 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)); + return res; } //--- title() ----------------------------------------- /** \brief Returns a titlecased copy of the string where words start with an uppercase character and the remaining characters are lowercase. */ - inline CppStringT title() const noexcept + CppStringT title() const noexcept { - return *this; + constexpr CppStringT whitespace(value_type(' ')); + + CppStringT res(*this); + std::vector words = res.split(whitespace); + + for (CppStringT& word : words) + word.capitalize(); + + return whitespace.join(words); } From 65b40a77e762db6886863be3913eb0e622739a25 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 16 Mar 2023 09:59:41 +0100 Subject: [PATCH 068/220] #56 - Implement method CppStringT::zfill() Completed. --- cpp-strings/cppstrings.h | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 6db8600..949db7e 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1393,10 +1393,24 @@ namespace pcs // i.e. "pythonic c++ strings" } - protected: - + //--- zfill() ----------------------------------------- + /** \brief Returns a copy of the string left filled with ASCII '0' digits to make a string of length width. + * + * A leading sign prefix ('+'/'-') is handled by inserting the padding + * after the sign character rather than before. The original string is + * returned if width is less than or equal to len(s). + */ + inline CppStringT zfill(const size_type width) const noexcept + { + if (this->size() >= width) + return *this; - private: + 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')); + else + return this->ljust(padding_width, value_type('0')); + } }; From 42928ad8fdf589e503ee809b99c309f01e43264b Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 16 Mar 2023 21:55:15 +0100 Subject: [PATCH 069/220] #75 - Implement method CppStringT::substr() Completed. --- cpp-strings/cppstrings.cpp | 5 +++-- cpp-strings/cppstrings.h | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index 3c9c506..bd5a72a 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -29,10 +29,11 @@ using namespace pcs; */ int main() { - CppString s; - CppWString ws; + CppString s("-5.1"); + CppWString ws(L"-5.1"); std::cout << ws.isupper() << std::endl; + std::cout << s.zfill(10).c_str() << std::endl; return 0; } diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 949db7e..6147daa 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -146,6 +146,11 @@ namespace pcs // i.e. "pythonic c++ strings" 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) {} + template inline CppStringT(InputIt first, InputIt last) : MyBaseClass(first, last) {} @@ -1334,6 +1339,17 @@ 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 + { + if (start > this->size()) + return *this; + const size_type width = std::min(count, this->size() - start); + return CppStringT(MyBaseClass::substr(start, width)); + } + + //--- swapcase() -------------------------------------- /** \brief Returns a copy of the string with uppercase characters converted to lowercase and vice versa. * From 122dfd1238c73e7ebeebce14747c419ca0e13b60 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 16 Mar 2023 22:13:39 +0100 Subject: [PATCH 070/220] #57 - Implement operator ""cs Completed. --- cpp-strings/cppstrings.cpp | 4 ++-- cpp-strings/cppstrings.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/cpp-strings/cppstrings.cpp b/cpp-strings/cppstrings.cpp index bd5a72a..3ec760f 100644 --- a/cpp-strings/cppstrings.cpp +++ b/cpp-strings/cppstrings.cpp @@ -29,8 +29,8 @@ using namespace pcs; */ int main() { - CppString s("-5.1"); - CppWString ws(L"-5.1"); + CppString s = "-5.1"; + 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 6147daa..2f9ab16 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -50,6 +50,13 @@ 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' + // 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. */ + // 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. @@ -1431,6 +1438,31 @@ 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) + { + return CppString(CppString::MyBaseClass(str, len)); + } + + /** \brief Forms a CppString view literal. */ + inline const CppString operator""csv(const char* str, std::size_t len) + { + return CppString(CppString::MyStringView(str, len)); + } + + /* + inline const CppWString operator""cs(const wchar_t* str, std::size_t len) + { + return CppWString(CppWString::MyBaseClass(str, len)); + } + + inline const CppWString operator""csv(const wchar_t* str, std::size_t len) + { + return CppWString(CppWString::MyStringView(str, len)); + } + */ + //===== templated chars classes =========================== //--- is_alpha() ------------------------------------------ From a7aab2b6db3ccce4d0b9d7b6678e08bf678b552d Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Thu, 16 Mar 2023 22:15:26 +0100 Subject: [PATCH 071/220] #58 - Implement operator ""csv Completed. --- cpp-strings/cppstrings.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 2f9ab16..a605997 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -54,8 +54,8 @@ namespace pcs // i.e. "pythonic c++ strings" #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 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. // chars classifications -- not to be directly called, see respective specializations at the very end of this module. template @@ -1451,17 +1451,17 @@ namespace pcs // i.e. "pythonic c++ strings" return CppString(CppString::MyStringView(str, len)); } - /* + /** \brief Forms a CppWString literal. */ inline const 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) { return CppWString(CppWString::MyStringView(str, len)); } - */ //===== templated chars classes =========================== From 9e8fa92333e81f903dadee9a85656ed3fe2c1d53 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 17 Mar 2023 19:35:14 +0100 Subject: [PATCH 072/220] #37 - Implement method CppStringT::maketrans() Finally implement as an internal class named `TransTable`. --- cpp-strings/cppstrings.h | 88 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index a605997..df0d00a 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -22,6 +22,7 @@ //============================================================= #include +#include #include #include #include @@ -180,6 +181,7 @@ namespace pcs // i.e. "pythonic c++ strings" inline NotFoundException(const char* what_arg) : MyBaseClass(what_arg) {} }; + //=== Methods ========================================= //--- capitalize() ------------------------------------ @@ -1435,6 +1437,92 @@ namespace pcs // i.e. "pythonic c++ strings" return this->ljust(padding_width, value_type('0')); } + + //=== Translation Table =============================== + /** \brief The internal class of translation tables, as used with methods CppStringT::maketrans and CppStringT::translate. */ + class TransTable + { + public: + //--- wrappers ------------------------------------ + using key_type = CharT; + using value_type = CppStringT; + + //--- Constructors / destructor ------------------- + inline TransTable(const std::map trans_table) + : table{ trans_table } + {} + + TransTable(const CppStringT& keys, const CppStringT& values) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + table[k] = value_type(*val_it++); + } + + inline TransTable(const std::initializer_list keys, + const std::initializer_list values) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + table[(*k)[0]] = *val_it++; + } + + inline TransTable(const CharT* keys, const CharT* values) + { + while (*keys && *values) + table[*keys++] = value_type(*values++); + } + + template + inline TransTable(InputIt first_key, InputIt last_key, InputIt first_value, InputIt last_value) + { + InputIt key_it{ first_key }; + InputIt val_it{ first_value }; + while (key_it != last_key && val_it != last_value) + table[*key_it++] = value_type(*val_it++); + } + + template + explicit TransTable(const StringViewLike& keys, const StringViewLike& values) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + table[(*k)[0]] = value_type(*val_it++); + } + + inline TransTable() noexcept = default; + inline TransTable(const TransTable&) noexcept = default; + inline TransTable(TransTable&&) noexcept = default; + + inline ~TransTable() noexcept = default; + + //--- operators ----------------------------------- + inline TransTable& operator= (const TransTable&) noexcept = default; + inline TransTable& operator= (TransTable&&) noexcept = default; + + inline TransTable& operator= (const std::map& trans_table) noexcept + { + table = trans_table; + return *this; + } + + inline CppStringT operator[] (const CharT ch) const noexcept + { + try { + return table[ch]; + } + catch (...) { + return CppStringT(); + } + } + + //--- data ---------------------------------------- + std::map table{}; + }; + }; From 1e776b1098917a3831fc1091c1a6e0d6ade86f23 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 17 Mar 2023 22:53:51 +0100 Subject: [PATCH 073/220] #76 - Enhance class CppStringT::TransTable Completed. --- cpp-strings/cppstrings.h | 172 ++++++++++++++++++++++++++++++++++----- 1 file changed, 150 insertions(+), 22 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index df0d00a..73f419a 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -1439,7 +1439,7 @@ namespace pcs // i.e. "pythonic c++ strings" //=== Translation Table =============================== - /** \brief The internal class of translation tables, as used with methods CppStringT::maketrans and CppStringT::translate. */ + /** \brief The internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate. */ class TransTable { public: @@ -1448,79 +1448,207 @@ namespace pcs // i.e. "pythonic c++ strings" using value_type = CppStringT; //--- Constructors / destructor ------------------- + /** \brief Creates a TransTable from a standard map. */ inline TransTable(const std::map trans_table) - : table{ trans_table } + : m_table{ trans_table } {} + /** \brief Creates a TransTable from two 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. + */ TransTable(const CppStringT& keys, const CppStringT& values) { assert(keys.size() == values.size()); auto val_it = values.cbegin(); for (const auto k : keys) - table[k] = value_type(*val_it++); + m_table[k] = value_type(*val_it++); + } + + /** \brief Creates a TransTable from three 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. + */ + TransTable(const CppStringT& keys, const CppStringT& values, const CppStringT& not_translated) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[k] = value_type(*val_it++); + for (const auto k : not_translated) + m_table[k] = CppStringT(); } + /** \brief Creates a TransTable from two initalization lists. + * + * 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) { assert(keys.size() == values.size()); auto val_it = values.cbegin(); for (const auto k : keys) - table[(*k)[0]] = *val_it++; + m_table[(*k)[0]] = *val_it++; } + /** \brief Creates a TransTable from three initalization lists. + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i -th character in values. Finally, the characters + * contained in string not_translated are associated in the + * translation table with the empty string. + */ + inline TransTable(const std::initializer_list keys, + const std::initializer_list values, + const CppStringT& not_translated) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[(*k)[0]] = *val_it++; + for (const auto k : not_translated) + m_table[k] = CppStringT(); + } + + /** \brief Creates a TransTable from two pointers to null-terminated lists of characters. + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i-th character in values. + */ inline TransTable(const CharT* keys, const CharT* values) { while (*keys && *values) - table[*keys++] = value_type(*values++); + m_table[*keys++] = value_type(*values++); + } + + /** \brief Creates a TransTable from three pointers to null-terminated lists of characters. + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i -th character in values. Finally, the characters + * contained in string not_translated are associated in the + * translation table with the empty string. + */ + inline TransTable(const CharT* keys, const CharT* values, const CharT* not_translated) + { + while (*keys && *values) + m_table[*keys++] = value_type(*values++); + while (*not_translated) + m_table[*not_translated++] = CppStringT(); + } + + /** \brief Creates a TransTable from two containers iterators. + * + * 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. + */ + template + inline TransTable(KeyIt first_key, KeyIt last_key, ValueIt first_value, ValueIt last_value) + { + KeyIt key_it{ first_key }; + ValueIt val_it{ first_value }; + while (key_it != last_key && val_it != last_value) + m_table[*key_it++] = value_type(*val_it++); } - template - inline TransTable(InputIt first_key, InputIt last_key, InputIt first_value, InputIt last_value) + /** \brief Creates a TransTable from three containers iterators. + * + * Both containers should have the same size. The i-th + * character in key is associated in the translation table with + * the i -th character in values. Finally, the characters + * contained in string not_translated are associated in the + * translation table with the empty string. + */ + template + inline TransTable(KeyIt first_key, KeyIt last_key, + ValueIt first_value, ValueIt last_value, + KeyIt first_not_translated, KeyIt last_not_translated) { - InputIt key_it{ first_key }; - InputIt val_it{ first_value }; + KeyIt key_it{ first_key }; + ValueIt val_it{ first_value }; while (key_it != last_key && val_it != last_value) - table[*key_it++] = value_type(*val_it++); + m_table[*key_it++] = value_type(*val_it++); + key_it = first_not_translated; + while (key_it != last_not_translated) + m_table[*key_it++] = CppStringT(); } + /** \brief Creates a TransTable from two string views. + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i-th character in values. + */ template explicit TransTable(const StringViewLike& keys, const StringViewLike& values) { assert(keys.size() == values.size()); auto val_it = values.cbegin(); for (const auto k : keys) - table[(*k)[0]] = value_type(*val_it++); + m_table[(*k)[0]] = value_type(*val_it++); + } + + /** \brief Creates a TransTable from three string views. + * + * 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; - inline TransTable(const TransTable&) noexcept = default; - inline TransTable(TransTable&&) noexcept = default; + 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; + inline ~TransTable() noexcept = default; //!< Default descrtuctor //--- operators ----------------------------------- - inline TransTable& operator= (const TransTable&) noexcept = default; - inline TransTable& operator= (TransTable&&) noexcept = default; + inline TransTable& operator= (const TransTable&) noexcept = default; //!< Default copy assignment + inline TransTable& operator= (TransTable&&) noexcept = default; //!< Default move assignment + /** \brief Assignment operator with a standard map. */ inline TransTable& operator= (const std::map& trans_table) noexcept { - table = trans_table; + m_table = trans_table; return *this; } - inline CppStringT operator[] (const CharT ch) const noexcept + /** \biref Indexing operator. */ + inline CppStringT operator[] (const key_type ch) const noexcept { try { - return table[ch]; + return m_table[ch]; } catch (...) { return CppStringT(); } } - //--- data ---------------------------------------- - std::map table{}; + private: + std::map m_table{}; // the itnernal storage of the translation table. Access it via the indexing operator. }; }; From cfdb44812de7f700a19758d46f3829b78974f55f Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Fri, 17 Mar 2023 23:15:28 +0100 Subject: [PATCH 074/220] #54 - Implement method CppStringT::translate() Completed. --- cpp-strings/cppstrings.h | 451 +++++++++++++++++++++------------------ 1 file changed, 240 insertions(+), 211 deletions(-) diff --git a/cpp-strings/cppstrings.h b/cpp-strings/cppstrings.h index 73f419a..051abbd 100644 --- a/cpp-strings/cppstrings.h +++ b/cpp-strings/cppstrings.h @@ -141,6 +141,217 @@ namespace pcs // i.e. "pythonic c++ strings" using const_reverse_iterator = MyBaseClass::const_reverse_iterator; + //=== Translation Table =============================== + /** \brief The internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate. */ + class TransTable + { + public: + //--- wrappers ------------------------------------ + using key_type = CharT; + using value_type = CppStringT; + + //--- Constructors / destructor ------------------- + /** \brief Creates a TransTable from a standard map. */ + inline TransTable(const std::map trans_table) + : m_table{ trans_table } + {} + + /** \brief Creates a TransTable from two 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. + */ + TransTable(const CppStringT& keys, const CppStringT& values) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[k] = value_type(*val_it++); + } + + /** \brief Creates a TransTable from three 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. + */ + TransTable(const CppStringT& keys, const CppStringT& values, const CppStringT& not_translated) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[k] = value_type(*val_it++); + for (const auto k : not_translated) + m_table[k] = CppStringT(); + } + + /** \brief Creates a TransTable from two initalization lists. + * + * 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) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[(*k)[0]] = *val_it++; + } + + /** \brief Creates a TransTable from three initalization lists. + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i -th character in values. Finally, the characters + * contained in string not_translated are associated in the + * translation table with the empty string. + */ + inline TransTable(const std::initializer_list keys, + const std::initializer_list values, + const CppStringT& not_translated) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[(*k)[0]] = *val_it++; + for (const auto k : not_translated) + m_table[k] = CppStringT(); + } + + /** \brief Creates a TransTable from two pointers to null-terminated lists of characters. + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i-th character in values. + */ + inline TransTable(const CharT* keys, const CharT* values) + { + while (*keys && *values) + m_table[*keys++] = value_type(*values++); + } + + /** \brief Creates a TransTable from three pointers to null-terminated lists of characters. + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i -th character in values. Finally, the characters + * contained in string not_translated are associated in the + * translation table with the empty string. + */ + inline TransTable(const CharT* keys, const CharT* values, const CharT* not_translated) + { + while (*keys && *values) + m_table[*keys++] = value_type(*values++); + while (*not_translated) + m_table[*not_translated++] = CppStringT(); + } + + /** \brief Creates a TransTable from two containers iterators. + * + * 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. + */ + template + inline TransTable(KeyIt first_key, KeyIt last_key, ValueIt first_value, ValueIt last_value) + { + KeyIt key_it{ first_key }; + ValueIt val_it{ first_value }; + while (key_it != last_key && val_it != last_value) + m_table[*key_it++] = value_type(*val_it++); + } + + /** \brief Creates a TransTable from three containers iterators. + * + * Both containers should have the same size. The i-th + * character in key is associated in the translation table with + * the i -th character in values. Finally, the characters + * contained in string not_translated are associated in the + * translation table with the empty string. + */ + template + inline TransTable(KeyIt first_key, KeyIt last_key, + ValueIt first_value, ValueIt last_value, + KeyIt first_not_translated, KeyIt last_not_translated) + { + KeyIt key_it{ first_key }; + ValueIt val_it{ first_value }; + while (key_it != last_key && val_it != last_value) + m_table[*key_it++] = value_type(*val_it++); + key_it = first_not_translated; + while (key_it != last_not_translated) + m_table[*key_it++] = CppStringT(); + } + + /** \brief Creates a TransTable from two string views. + * + * Parameters keys and values must have the same size. The i-th + * character in key is associated in the translation table with + * the i-th character in values. + */ + template + explicit TransTable(const StringViewLike& keys, const StringViewLike& values) + { + assert(keys.size() == values.size()); + auto val_it = values.cbegin(); + for (const auto k : keys) + m_table[(*k)[0]] = value_type(*val_it++); + } + + /** \brief Creates a TransTable from three string views. + * + * 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 descrtuctor + + //--- operators ----------------------------------- + inline TransTable& operator= (const TransTable&) noexcept = default; //!< Default copy assignment + inline TransTable& operator= (TransTable&&) noexcept = default; //!< Default move assignment + + /** \brief Assignment operator with a standard map. */ + inline TransTable& operator= (const std::map& trans_table) noexcept + { + m_table = trans_table; + return *this; + } + + /** \biref Indexing operator. */ + inline CppStringT operator[] (const key_type ch) const noexcept + { + try { + return m_table[ch]; + } + catch (...) { + return CppStringT(); + } + } + }; + + //=== Constructors / Destructor =================== inline CppStringT() : MyBaseClass() {} inline CppStringT(const CppStringT& other) : MyBaseClass(other) {} @@ -1393,6 +1604,34 @@ 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 + * 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 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; + } + + //--- upper () ----------------------------------------- /** \brief In-place replaces all characters of the string with their uppercase conversion. Returns a reference to string. * @@ -1438,218 +1677,8 @@ namespace pcs // i.e. "pythonic c++ strings" } - //=== Translation Table =============================== - /** \brief The internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate. */ - class TransTable - { - public: - //--- wrappers ------------------------------------ - using key_type = CharT; - using value_type = CppStringT; - - //--- Constructors / destructor ------------------- - /** \brief Creates a TransTable from a standard map. */ - inline TransTable(const std::map trans_table) - : m_table{ trans_table } - {} - - /** \brief Creates a TransTable from two 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. - */ - TransTable(const CppStringT& keys, const CppStringT& values) - { - assert(keys.size() == values.size()); - auto val_it = values.cbegin(); - for (const auto k : keys) - m_table[k] = value_type(*val_it++); - } - - /** \brief Creates a TransTable from three 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. - */ - TransTable(const CppStringT& keys, const CppStringT& values, const CppStringT& not_translated) - { - assert(keys.size() == values.size()); - auto val_it = values.cbegin(); - for (const auto k : keys) - m_table[k] = value_type(*val_it++); - for (const auto k : not_translated) - m_table[k] = CppStringT(); - } - - /** \brief Creates a TransTable from two initalization lists. - * - * 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) - { - assert(keys.size() == values.size()); - auto val_it = values.cbegin(); - for (const auto k : keys) - m_table[(*k)[0]] = *val_it++; - } - - /** \brief Creates a TransTable from three initalization lists. - * - * Parameters keys and values must have the same size. The i-th - * character in key is associated in the translation table with - * the i -th character in values. Finally, the characters - * contained in string not_translated are associated in the - * translation table with the empty string. - */ - inline TransTable(const std::initializer_list keys, - const std::initializer_list values, - const CppStringT& not_translated) - { - assert(keys.size() == values.size()); - auto val_it = values.cbegin(); - for (const auto k : keys) - m_table[(*k)[0]] = *val_it++; - for (const auto k : not_translated) - m_table[k] = CppStringT(); - } - - /** \brief Creates a TransTable from two pointers to null-terminated lists of characters. - * - * Parameters keys and values must have the same size. The i-th - * character in key is associated in the translation table with - * the i-th character in values. - */ - inline TransTable(const CharT* keys, const CharT* values) - { - while (*keys && *values) - m_table[*keys++] = value_type(*values++); - } - - /** \brief Creates a TransTable from three pointers to null-terminated lists of characters. - * - * Parameters keys and values must have the same size. The i-th - * character in key is associated in the translation table with - * the i -th character in values. Finally, the characters - * contained in string not_translated are associated in the - * translation table with the empty string. - */ - inline TransTable(const CharT* keys, const CharT* values, const CharT* not_translated) - { - while (*keys && *values) - m_table[*keys++] = value_type(*values++); - while (*not_translated) - m_table[*not_translated++] = CppStringT(); - } - - /** \brief Creates a TransTable from two containers iterators. - * - * 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. - */ - template - inline TransTable(KeyIt first_key, KeyIt last_key, ValueIt first_value, ValueIt last_value) - { - KeyIt key_it{ first_key }; - ValueIt val_it{ first_value }; - while (key_it != last_key && val_it != last_value) - m_table[*key_it++] = value_type(*val_it++); - } - - /** \brief Creates a TransTable from three containers iterators. - * - * Both containers should have the same size. The i-th - * character in key is associated in the translation table with - * the i -th character in values. Finally, the characters - * contained in string not_translated are associated in the - * translation table with the empty string. - */ - template - inline TransTable(KeyIt first_key, KeyIt last_key, - ValueIt first_value, ValueIt last_value, - KeyIt first_not_translated, KeyIt last_not_translated) - { - KeyIt key_it{ first_key }; - ValueIt val_it{ first_value }; - while (key_it != last_key && val_it != last_value) - m_table[*key_it++] = value_type(*val_it++); - key_it = first_not_translated; - while (key_it != last_not_translated) - m_table[*key_it++] = CppStringT(); - } - - /** \brief Creates a TransTable from two string views. - * - * Parameters keys and values must have the same size. The i-th - * character in key is associated in the translation table with - * the i-th character in values. - */ - template - explicit TransTable(const StringViewLike& keys, const StringViewLike& values) - { - assert(keys.size() == values.size()); - auto val_it = values.cbegin(); - for (const auto k : keys) - m_table[(*k)[0]] = value_type(*val_it++); - } - - /** \brief Creates a TransTable from three string views. - * - * 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 descrtuctor - - //--- operators ----------------------------------- - inline TransTable& operator= (const TransTable&) noexcept = default; //!< Default copy assignment - inline TransTable& operator= (TransTable&&) noexcept = default; //!< Default move assignment - - /** \brief Assignment operator with a standard map. */ - inline TransTable& operator= (const std::map& trans_table) noexcept - { - m_table = trans_table; - return *this; - } - - /** \biref Indexing operator. */ - inline CppStringT operator[] (const key_type ch) const noexcept - { - try { - return m_table[ch]; - } - catch (...) { - return CppStringT(); - } - } - private: - std::map m_table{}; // the itnernal storage of the translation table. Access it via the indexing operator. - }; + std::map m_table{}; // the itnernal storage of the translation table. Access it via the indexing operator. }; From 090b04c3b3fc7cca8b8cb5927f08657c0805a5cb Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Sat, 18 Mar 2023 00:08:15 +0100 Subject: [PATCH 075/220] #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 076/220] #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 077/220] #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 078/220] #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 079/220] #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 080/220] #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 081/220] #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 082/220] #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 083/220] 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 084/220] #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 085/220] #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 086/220] #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 087/220] #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 088/220] #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 089/220] #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 090/220] #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 091/220] #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 092/220] #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 093/220] #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 094/220] #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 095/220] #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 096/220] #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 097/220] #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 098/220] #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 099/220] #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 100/220] #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 101/220] #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 102/220] #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 103/220] #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 104/220] #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 105/220] #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 106/220] #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 107/220] #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 108/220] #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 109/220] #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 110/220] #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 111/220] #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 112/220] #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 113/220] #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 114/220] #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 115/220] #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 116/220] #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 117/220] #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 118/220] #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 119/220] #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 120/220] #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 121/220] #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 122/220] #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 123/220] #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 124/220] #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 125/220] #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 126/220] #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 127/220] #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 128/220] #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 129/220] #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 130/220] #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 131/220] #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 132/220] #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 133/220] #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 134/220] #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 135/220] #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 136/220] #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 137/220] #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 138/220] #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 139/220] #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 140/220] #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 141/220] #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 142/220] #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 143/220] #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 144/220] #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 145/220] #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 146/220] #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 147/220] #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 148/220] #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 149/220] #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 150/220] #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 151/220] #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 152/220] #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 153/220] #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 154/220] #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 155/220] #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 156/220] #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 157/220] #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 158/220] #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 159/220] #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 160/220] #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 161/220] #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 162/220] #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 163/220] #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 164/220] #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 165/220] #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 166/220] #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 167/220] #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 168/220] #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 169/220] #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 170/220] #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 171/220] #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 172/220] #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 173/220] #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 174/220] #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 175/220] #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 176/220] #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 177/220] #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 178/220] #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 179/220] #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 180/220] #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 181/220] #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 182/220] #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 183/220] #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 184/220] #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 185/220] #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 186/220] #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 187/220] #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 188/220] #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 189/220] #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 190/220] #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 191/220] #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 192/220] #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 193/220] #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 194/220] #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 195/220] #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 196/220] #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 197/220] #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 198/220] #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 199/220] #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 200/220] #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 201/220] #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 202/220] #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 203/220] #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 204/220] #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 205/220] #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 206/220] #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 207/220] #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 208/220] #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 209/220] #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 210/220] #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 211/220] #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 } From 685553f8623134cc33c5ac7f739ce4102f337044 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 09:29:29 +0200 Subject: [PATCH 212/220] #204-create PCS documentation intermediate commit. --- README.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index edd5347..968ee72 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,33 @@ -# cpp-strings +# Library cpp-strings [![license](http://img.shields.io/github/license/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=lightblue)](https://github.com/schmouk/cpprandlib/license) [![Latest release](http://img.shields.io/github/release/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=success)](https://github.com/schmouk/cpprandlib/releases) [![code_coverage](https://img.shields.io/badge/code_coverage-100%25-success?style=plastic&labelColor=blueviolet)]() [![tests](https://img.shields.io/badge/tests-passing-success?style=plastic&labelColor=blueviolet)] + What if c++ strings where as easy to use as Python strings? + +Copyright © 2023-2025 Philippe Schmouker +contact - ph (dot) schmouker (at) gmail (dot) com + + +--- +## License + + Library cpp-strings + "What if c++ strings where as easy to use as Python strings?" + + Copyright (C) 2023-2025 Philippe Schmouker + contact - ph (dot) schmouker (at) gmail (dot) com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + +--- +## Intro \ No newline at end of file From 7a771e27bf9519856ef1fd4c08befed8392d9206 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 10:23:50 +0200 Subject: [PATCH 213/220] #204-create PCS documentation intermediate commit. --- README.md | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 968ee72..ae5e3ac 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,28 @@ What if c++ strings where as easy to use as Python strings? -Copyright © 2023-2025 Philippe Schmouker -contact - ph (dot) schmouker (at) gmail (dot) com +Let's just use c++ strings as are Python ones, with same API or as similar API as possible. +Library **cpp-strings** is fully templated. Just download header file `cppstrings.h` and put it anywhere in your project. Notice: all of its stuff is declared and defined in namespace `pcs` - which stands for **P**ythonic **C**++ **S**trings. + +* The templated class `pcs::CppStringT<>` defines all constructors and methods that implement the equivalent of Python strings API. +* Class `pcs::CppString` specializes the templated class with `char` characters. +* Class `pcs::CppWString` specializes the templated class with `wchar_t` characters. + +**cpp-strings** is implemented with the currently most recent c++ standard available with gcc, clang and msvc c++ compilers, i.e. standard **c++20**. + +* directory `cpp-strings` contains the header file `cppstring.h`. +This is the header file to include in your projects. +* directory `cpp-strings-tests` contains the unit test file `cpp-strings-tests.cpp` +This file tests all the library stuff. It is a valuable code container with so many examples of use of the library, the classes, the methods and the functions it defines. + +The code has been developed using VS2022 IDE. As such, unitary tests have been coded using Microsoft Visual Studio Cpp Unit Test Framework. The related VS project is provided with this library. + +Notice: no clang, gcc or msvc specific declarations or goodies have been use to code library **cpp-strings**. It should then be compilable with any of these compilers. To be able to use it with your project, just ensure that the c++ standard used with you favorite compiler is **c++20**: options `-std=c++20` or +* options `-std=c++20` or `-std=c++latest` for clang and gcc (v. 10 and above), +or option `-std=c++2a` for clang and gcc (v. 9 and earlier); +* options `/std=c++20` or `/std=c++latest` for Visual Studio 2019 and above + +If you want to run the unitary tests, well, use Visual Studio 2022. The Community free version will truly be fine. The vcproject associated with the unit tests is already configured to use the option flag `/std:c++latest` since the implemented code uses a very few but very useful c++23 goodies. --- @@ -30,4 +50,6 @@ contact - ph (dot) schmouker (at) gmail (dot) com --- -## Intro \ No newline at end of file +## Intro + +... document creation still in progress ... From 96c75d67eb008ed2330c7c88291ae57cc8788b60 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 14:25:39 +0200 Subject: [PATCH 214/220] #204-create PCS documentation intermediate commit. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae5e3ac..efdc8ac 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Library cpp-strings [![license](http://img.shields.io/github/license/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=lightblue)](https://github.com/schmouk/cpprandlib/license) [![Latest release](http://img.shields.io/github/release/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=success)](https://github.com/schmouk/cpprandlib/releases) [![code_coverage](https://img.shields.io/badge/code_coverage-100%25-success?style=plastic&labelColor=blueviolet)]() [![tests](https://img.shields.io/badge/tests-passing-success?style=plastic&labelColor=blueviolet)] +# Library cpp-strings [![license](http://img.shields.io/github/license/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=lightblue)](https://github.com/schmouk/cpprandlib/license) [![Latest release](http://img.shields.io/github/release/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=success)](https://github.com/schmouk/cpprandlib/releases) [![code_coverage](https://img.shields.io/badge/code_coverage-100%25-success?style=plastic&labelColor=blueviolet)]() [![tests](https://img.shields.io/badge/tests-passing-success?style=plastic&labelColor=blueviolet)]() What if c++ strings where as easy to use as Python strings? From 4fda9ec478f95695c11533f0a58ea2ca4ab67e3c Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 14:26:42 +0200 Subject: [PATCH 215/220] Update README.md intermediate commit. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index efdc8ac..1fdad34 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# Library cpp-strings [![license](http://img.shields.io/github/license/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=lightblue)](https://github.com/schmouk/cpprandlib/license) [![Latest release](http://img.shields.io/github/release/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=success)](https://github.com/schmouk/cpprandlib/releases) [![code_coverage](https://img.shields.io/badge/code_coverage-100%25-success?style=plastic&labelColor=blueviolet)]() [![tests](https://img.shields.io/badge/tests-passing-success?style=plastic&labelColor=blueviolet)]() +# Library cpp-string + [![license](http://img.shields.io/github/license/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=lightblue)](https://github.com/schmouk/cpprandlib/license) [![Latest release](http://img.shields.io/github/release/schmouk/cpp-strings.svg?style=plastic&labelColor=blueviolet&color=success)](https://github.com/schmouk/cpprandlib/releases) [![code_coverage](https://img.shields.io/badge/code_coverage-100%25-success?style=plastic&labelColor=blueviolet)]() [![tests](https://img.shields.io/badge/tests-passing-success?style=plastic&labelColor=blueviolet)]() What if c++ strings where as easy to use as Python strings? From 2e1ad62a454df9cd16009fffe704edce08c30977 Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 14:37:13 +0200 Subject: [PATCH 216/220] #204 intermediate commit. --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1fdad34..23ad29f 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,13 @@ This file tests all the library stuff. It is a valuable code container with so m The code has been developed using VS2022 IDE. As such, unitary tests have been coded using Microsoft Visual Studio Cpp Unit Test Framework. The related VS project is provided with this library. -Notice: no clang, gcc or msvc specific declarations or goodies have been use to code library **cpp-strings**. It should then be compilable with any of these compilers. To be able to use it with your project, just ensure that the c++ standard used with you favorite compiler is **c++20**: options `-std=c++20` or +Notice: no clang, gcc or msvc specific declarations or goodies have been use to code library **cpp-strings**. It should then be compilable with any of these compilers. To be able to use it with your project, just ensure that the c++ standard used with you favorite compiler is **c++20**: * options `-std=c++20` or `-std=c++latest` for clang and gcc (v. 10 and above), or option `-std=c++2a` for clang and gcc (v. 9 and earlier); -* options `/std=c++20` or `/std=c++latest` for Visual Studio 2019 and above +* options `/std=c++20` or `/std=c++latest` for Visual Studio 2019 and later. -If you want to run the unitary tests, well, use Visual Studio 2022. The Community free version will truly be fine. The vcproject associated with the unit tests is already configured to use the option flag `/std:c++latest` since the implemented code uses a very few but very useful c++23 goodies. +If you want to run the unitary tests, well, use the last version of Visual Studio (i.e. VS 2022, by July 2025). The Community free version will truly be fine. +The vcproject associated with the unit tests in **cpp-strings** is already configured to use the option flag `/std:c++latest` since the implemented code uses a very few but very useful c++23 goodies. --- From cac9c07b1de1dbc67c635efc5617e47605aaefaa Mon Sep 17 00:00:00 2001 From: Philippe Schmouker Date: Wed, 16 Jul 2025 19:51:40 +0200 Subject: [PATCH 217/220] #224-generate doxygen documentation Completed. Reviewed. --- cpp-strings/cpp-strings.cfg | 96 + cpp-strings/html/annotated.html | 117 + cpp-strings/html/annotated_dup.js | 13 + cpp-strings/html/classes.html | 117 + .../classpcs_1_1_cpp_string_t-members.html | 235 ++ .../html/classpcs_1_1_cpp_string_t.html | 3645 +++++++++++++++++ cpp-strings/html/classpcs_1_1_cpp_string_t.js | 99 + .../html/classpcs_1_1_cpp_string_t.png | Bin 0 -> 1118 bytes ...ing_t_1_1_not_found_exception-members.html | 108 + ..._cpp_string_t_1_1_not_found_exception.html | 132 + ...1_cpp_string_t_1_1_not_found_exception.png | Bin 0 -> 1461 bytes ..._cpp_string_t_1_1_trans_table-members.html | 126 + ...spcs_1_1_cpp_string_t_1_1_trans_table.html | 836 ++++ ...asspcs_1_1_cpp_string_t_1_1_trans_table.js | 22 + .../html/classpcs_1_1_slice-members.html | 116 + cpp-strings/html/classpcs_1_1_slice.html | 485 +++ cpp-strings/html/classpcs_1_1_slice.js | 13 + cpp-strings/html/classpcs_1_1_slice.png | Bin 0 -> 1565 bytes cpp-strings/html/clipboard.js | 61 + cpp-strings/html/cookie.js | 58 + cpp-strings/html/cppstrings_8h_source.html | 2231 ++++++++++ cpp-strings/html/doxygen.css | 2468 +++++++++++ cpp-strings/html/doxygen.svg | 28 + cpp-strings/html/doxygen_crawl.html | 227 + cpp-strings/html/dynsections.js | 191 + cpp-strings/html/files.html | 107 + cpp-strings/html/files_dup.js | 4 + cpp-strings/html/functions.html | 245 ++ cpp-strings/html/functions_func.html | 245 ++ cpp-strings/html/hierarchy.html | 121 + cpp-strings/html/hierarchy.js | 22 + cpp-strings/html/index.html | 169 + cpp-strings/html/index.js | 6 + cpp-strings/html/jquery.js | 204 + cpp-strings/html/menu.js | 131 + cpp-strings/html/menudata.js | 82 + cpp-strings/html/namespacemembers.html | 159 + cpp-strings/html/namespacemembers_func.html | 153 + cpp-strings/html/namespacemembers_type.html | 103 + cpp-strings/html/namespacepcs.html | 1493 +++++++ cpp-strings/html/namespacepcs.js | 52 + cpp-strings/html/namespaces.html | 107 + cpp-strings/html/namespaces_dup.js | 4 + cpp-strings/html/navtree.css | 327 ++ cpp-strings/html/navtree.js | 899 ++++ cpp-strings/html/navtreedata.js | 60 + cpp-strings/html/navtreeindex0.js | 253 ++ cpp-strings/html/navtreeindex1.js | 102 + cpp-strings/html/search/all_0.js | 7 + cpp-strings/html/search/all_1.js | 5 + cpp-strings/html/search/all_10.js | 12 + cpp-strings/html/search/all_11.js | 4 + cpp-strings/html/search/all_12.js | 4 + cpp-strings/html/search/all_13.js | 11 + cpp-strings/html/search/all_2.js | 5 + cpp-strings/html/search/all_3.js | 4 + cpp-strings/html/search/all_4.js | 15 + cpp-strings/html/search/all_5.js | 7 + cpp-strings/html/search/all_6.js | 6 + cpp-strings/html/search/all_7.js | 4 + cpp-strings/html/search/all_8.js | 50 + cpp-strings/html/search/all_9.js | 4 + cpp-strings/html/search/all_a.js | 9 + cpp-strings/html/search/all_b.js | 4 + cpp-strings/html/search/all_c.js | 9 + cpp-strings/html/search/all_d.js | 5 + cpp-strings/html/search/all_e.js | 16 + cpp-strings/html/search/all_f.js | 22 + cpp-strings/html/search/classes_0.js | 6 + cpp-strings/html/search/classes_1.js | 4 + cpp-strings/html/search/classes_2.js | 10 + cpp-strings/html/search/classes_3.js | 4 + cpp-strings/html/search/functions_0.js | 4 + cpp-strings/html/search/functions_1.js | 9 + cpp-strings/html/search/functions_2.js | 7 + cpp-strings/html/search/functions_3.js | 6 + cpp-strings/html/search/functions_4.js | 4 + cpp-strings/html/search/functions_5.js | 49 + cpp-strings/html/search/functions_6.js | 4 + cpp-strings/html/search/functions_7.js | 6 + cpp-strings/html/search/functions_8.js | 9 + cpp-strings/html/search/functions_9.js | 4 + cpp-strings/html/search/functions_a.js | 14 + cpp-strings/html/search/functions_b.js | 21 + cpp-strings/html/search/functions_c.js | 12 + cpp-strings/html/search/functions_d.js | 4 + cpp-strings/html/search/functions_e.js | 4 + cpp-strings/html/search/functions_f.js | 11 + cpp-strings/html/search/namespaces_0.js | 4 + cpp-strings/html/search/pages_0.js | 7 + cpp-strings/html/search/pages_1.js | 5 + cpp-strings/html/search/pages_2.js | 5 + cpp-strings/html/search/pages_3.js | 4 + cpp-strings/html/search/pages_4.js | 4 + cpp-strings/html/search/pages_5.js | 6 + cpp-strings/html/search/pages_6.js | 5 + cpp-strings/html/search/pages_7.js | 4 + cpp-strings/html/search/search.css | 378 ++ cpp-strings/html/search/search.js | 708 ++++ cpp-strings/html/search/searchdata.js | 30 + cpp-strings/html/search/typedefs_0.js | 5 + .../structpcs_1_1_start_slice-members.html | 119 + .../html/structpcs_1_1_start_slice.html | 235 ++ cpp-strings/html/structpcs_1_1_start_slice.js | 5 + .../html/structpcs_1_1_start_slice.png | Bin 0 -> 620 bytes ...tructpcs_1_1_start_step_slice-members.html | 119 + .../html/structpcs_1_1_start_step_slice.html | 239 ++ .../html/structpcs_1_1_start_step_slice.js | 5 + .../html/structpcs_1_1_start_step_slice.png | Bin 0 -> 678 bytes ...tructpcs_1_1_start_stop_slice-members.html | 119 + .../html/structpcs_1_1_start_stop_slice.html | 239 ++ .../html/structpcs_1_1_start_stop_slice.js | 5 + .../html/structpcs_1_1_start_stop_slice.png | Bin 0 -> 677 bytes .../structpcs_1_1_step_slice-members.html | 119 + .../html/structpcs_1_1_step_slice.html | 235 ++ cpp-strings/html/structpcs_1_1_step_slice.js | 5 + cpp-strings/html/structpcs_1_1_step_slice.png | Bin 0 -> 621 bytes .../structpcs_1_1_stop_slice-members.html | 119 + .../html/structpcs_1_1_stop_slice.html | 235 ++ cpp-strings/html/structpcs_1_1_stop_slice.js | 5 + cpp-strings/html/structpcs_1_1_stop_slice.png | Bin 0 -> 618 bytes ...structpcs_1_1_stop_step_slice-members.html | 119 + .../html/structpcs_1_1_stop_step_slice.html | 239 ++ .../html/structpcs_1_1_stop_step_slice.js | 5 + .../html/structpcs_1_1_stop_step_slice.png | Bin 0 -> 661 bytes cpp-strings/html/tabs.css | 1 + 126 files changed, 20199 insertions(+) create mode 100644 cpp-strings/cpp-strings.cfg create mode 100644 cpp-strings/html/annotated.html create mode 100644 cpp-strings/html/annotated_dup.js create mode 100644 cpp-strings/html/classes.html create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t-members.html create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t.html create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t.js create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t.png create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception-members.html create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.html create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.png create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table-members.html create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table.html create mode 100644 cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table.js create mode 100644 cpp-strings/html/classpcs_1_1_slice-members.html create mode 100644 cpp-strings/html/classpcs_1_1_slice.html create mode 100644 cpp-strings/html/classpcs_1_1_slice.js create mode 100644 cpp-strings/html/classpcs_1_1_slice.png create mode 100644 cpp-strings/html/clipboard.js create mode 100644 cpp-strings/html/cookie.js create mode 100644 cpp-strings/html/cppstrings_8h_source.html create mode 100644 cpp-strings/html/doxygen.css create mode 100644 cpp-strings/html/doxygen.svg create mode 100644 cpp-strings/html/doxygen_crawl.html create mode 100644 cpp-strings/html/dynsections.js create mode 100644 cpp-strings/html/files.html create mode 100644 cpp-strings/html/files_dup.js create mode 100644 cpp-strings/html/functions.html create mode 100644 cpp-strings/html/functions_func.html create mode 100644 cpp-strings/html/hierarchy.html create mode 100644 cpp-strings/html/hierarchy.js create mode 100644 cpp-strings/html/index.html create mode 100644 cpp-strings/html/index.js create mode 100644 cpp-strings/html/jquery.js create mode 100644 cpp-strings/html/menu.js create mode 100644 cpp-strings/html/menudata.js create mode 100644 cpp-strings/html/namespacemembers.html create mode 100644 cpp-strings/html/namespacemembers_func.html create mode 100644 cpp-strings/html/namespacemembers_type.html create mode 100644 cpp-strings/html/namespacepcs.html create mode 100644 cpp-strings/html/namespacepcs.js create mode 100644 cpp-strings/html/namespaces.html create mode 100644 cpp-strings/html/namespaces_dup.js create mode 100644 cpp-strings/html/navtree.css create mode 100644 cpp-strings/html/navtree.js create mode 100644 cpp-strings/html/navtreedata.js create mode 100644 cpp-strings/html/navtreeindex0.js create mode 100644 cpp-strings/html/navtreeindex1.js create mode 100644 cpp-strings/html/search/all_0.js create mode 100644 cpp-strings/html/search/all_1.js create mode 100644 cpp-strings/html/search/all_10.js create mode 100644 cpp-strings/html/search/all_11.js create mode 100644 cpp-strings/html/search/all_12.js create mode 100644 cpp-strings/html/search/all_13.js create mode 100644 cpp-strings/html/search/all_2.js create mode 100644 cpp-strings/html/search/all_3.js create mode 100644 cpp-strings/html/search/all_4.js create mode 100644 cpp-strings/html/search/all_5.js create mode 100644 cpp-strings/html/search/all_6.js create mode 100644 cpp-strings/html/search/all_7.js create mode 100644 cpp-strings/html/search/all_8.js create mode 100644 cpp-strings/html/search/all_9.js create mode 100644 cpp-strings/html/search/all_a.js create mode 100644 cpp-strings/html/search/all_b.js create mode 100644 cpp-strings/html/search/all_c.js create mode 100644 cpp-strings/html/search/all_d.js create mode 100644 cpp-strings/html/search/all_e.js create mode 100644 cpp-strings/html/search/all_f.js create mode 100644 cpp-strings/html/search/classes_0.js create mode 100644 cpp-strings/html/search/classes_1.js create mode 100644 cpp-strings/html/search/classes_2.js create mode 100644 cpp-strings/html/search/classes_3.js create mode 100644 cpp-strings/html/search/functions_0.js create mode 100644 cpp-strings/html/search/functions_1.js create mode 100644 cpp-strings/html/search/functions_2.js create mode 100644 cpp-strings/html/search/functions_3.js create mode 100644 cpp-strings/html/search/functions_4.js create mode 100644 cpp-strings/html/search/functions_5.js create mode 100644 cpp-strings/html/search/functions_6.js create mode 100644 cpp-strings/html/search/functions_7.js create mode 100644 cpp-strings/html/search/functions_8.js create mode 100644 cpp-strings/html/search/functions_9.js create mode 100644 cpp-strings/html/search/functions_a.js create mode 100644 cpp-strings/html/search/functions_b.js create mode 100644 cpp-strings/html/search/functions_c.js create mode 100644 cpp-strings/html/search/functions_d.js create mode 100644 cpp-strings/html/search/functions_e.js create mode 100644 cpp-strings/html/search/functions_f.js create mode 100644 cpp-strings/html/search/namespaces_0.js create mode 100644 cpp-strings/html/search/pages_0.js create mode 100644 cpp-strings/html/search/pages_1.js create mode 100644 cpp-strings/html/search/pages_2.js create mode 100644 cpp-strings/html/search/pages_3.js create mode 100644 cpp-strings/html/search/pages_4.js create mode 100644 cpp-strings/html/search/pages_5.js create mode 100644 cpp-strings/html/search/pages_6.js create mode 100644 cpp-strings/html/search/pages_7.js create mode 100644 cpp-strings/html/search/search.css create mode 100644 cpp-strings/html/search/search.js create mode 100644 cpp-strings/html/search/searchdata.js create mode 100644 cpp-strings/html/search/typedefs_0.js create mode 100644 cpp-strings/html/structpcs_1_1_start_slice-members.html create mode 100644 cpp-strings/html/structpcs_1_1_start_slice.html create mode 100644 cpp-strings/html/structpcs_1_1_start_slice.js create mode 100644 cpp-strings/html/structpcs_1_1_start_slice.png create mode 100644 cpp-strings/html/structpcs_1_1_start_step_slice-members.html create mode 100644 cpp-strings/html/structpcs_1_1_start_step_slice.html create mode 100644 cpp-strings/html/structpcs_1_1_start_step_slice.js create mode 100644 cpp-strings/html/structpcs_1_1_start_step_slice.png create mode 100644 cpp-strings/html/structpcs_1_1_start_stop_slice-members.html create mode 100644 cpp-strings/html/structpcs_1_1_start_stop_slice.html create mode 100644 cpp-strings/html/structpcs_1_1_start_stop_slice.js create mode 100644 cpp-strings/html/structpcs_1_1_start_stop_slice.png create mode 100644 cpp-strings/html/structpcs_1_1_step_slice-members.html create mode 100644 cpp-strings/html/structpcs_1_1_step_slice.html create mode 100644 cpp-strings/html/structpcs_1_1_step_slice.js create mode 100644 cpp-strings/html/structpcs_1_1_step_slice.png create mode 100644 cpp-strings/html/structpcs_1_1_stop_slice-members.html create mode 100644 cpp-strings/html/structpcs_1_1_stop_slice.html create mode 100644 cpp-strings/html/structpcs_1_1_stop_slice.js create mode 100644 cpp-strings/html/structpcs_1_1_stop_slice.png create mode 100644 cpp-strings/html/structpcs_1_1_stop_step_slice-members.html create mode 100644 cpp-strings/html/structpcs_1_1_stop_step_slice.html create mode 100644 cpp-strings/html/structpcs_1_1_stop_step_slice.js create mode 100644 cpp-strings/html/structpcs_1_1_stop_step_slice.png create mode 100644 cpp-strings/html/tabs.css diff --git a/cpp-strings/cpp-strings.cfg b/cpp-strings/cpp-strings.cfg new file mode 100644 index 0000000..847ae88 --- /dev/null +++ b/cpp-strings/cpp-strings.cfg @@ -0,0 +1,96 @@ +# Doxyfile 1.14.0 + +# This file describes the settings to be used by the documentation system +# Doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use Doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use Doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "cpp-strings" +PROJECT_NUMBER = "1.0.0" +PROJECT_BRIEF = "Pythonic c++ strings" +OUTPUT_DIRECTORY = + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +ALWAYS_DETAILED_SEC = YES +FULL_PATH_NAMES = NO +BUILTIN_STL_SUPPORT = YES +TIMESTAMP = DATE ##YES ##NO ##DATETIME ## + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +HIDE_UNDOC_NAMESPACES = NO +SORT_BRIEF_DOCS = YES +WARN_NO_PARAMDOC = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ./ ../ +INPUT_ENCODING = UTF-8 +USE_MDFILE_AS_MAINPAGE = ../README.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_DYNAMIC_MENUS = YES +HTML_DYNAMIC_SECTIONS = NO +HTML_CODE_FOLDING = NO ##YES +HTML_COPY_CLIPBOARD = YES +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_TREEVIEW = YES +FULL_SIDEBAR = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO diff --git a/cpp-strings/html/annotated.html b/cpp-strings/html/annotated.html new file mode 100644 index 0000000..cccc0e4 --- /dev/null +++ b/cpp-strings/html/annotated.html @@ -0,0 +1,117 @@ + + + + + + + +cpp-strings: Class List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+
[detail level 123]
+ + + + + + + + + + + +
 Npcs
 CCppStringTThis is the templated base class for all CppString classes
 CNotFoundException
 CTransTableThe internal class of translation tables, used with methods CppStringT::maketrans and CppStringT::translate
 CSliceBase class for slices, with start, stop and step specified values
 CStartSliceBase class for slices, with start, stop and step specified values
 CStartStepSliceStruct of slices with default step values
 CStartStopSliceStruct of slices with default start and stop values
 CStepSliceStruct of slices with default start and step values
 CStopSliceStruct of slices with default stop and step values
 CStopStepSliceStruct of slices with default stop values
+
+
+
+
+ + + + diff --git a/cpp-strings/html/annotated_dup.js b/cpp-strings/html/annotated_dup.js new file mode 100644 index 0000000..328bcbb --- /dev/null +++ b/cpp-strings/html/annotated_dup.js @@ -0,0 +1,13 @@ +var annotated_dup = +[ + [ "pcs", "namespacepcs.html", [ + [ "CppStringT", "classpcs_1_1_cpp_string_t.html", "classpcs_1_1_cpp_string_t" ], + [ "Slice", "classpcs_1_1_slice.html", "classpcs_1_1_slice" ], + [ "StartSlice", "structpcs_1_1_start_slice.html", "structpcs_1_1_start_slice" ], + [ "StartStepSlice", "structpcs_1_1_start_step_slice.html", "structpcs_1_1_start_step_slice" ], + [ "StartStopSlice", "structpcs_1_1_start_stop_slice.html", "structpcs_1_1_start_stop_slice" ], + [ "StepSlice", "structpcs_1_1_step_slice.html", "structpcs_1_1_step_slice" ], + [ "StopSlice", "structpcs_1_1_stop_slice.html", "structpcs_1_1_stop_slice" ], + [ "StopStepSlice", "structpcs_1_1_stop_step_slice.html", "structpcs_1_1_stop_step_slice" ] + ] ] +]; \ No newline at end of file diff --git a/cpp-strings/html/classes.html b/cpp-strings/html/classes.html new file mode 100644 index 0000000..cac03fe --- /dev/null +++ b/cpp-strings/html/classes.html @@ -0,0 +1,117 @@ + + + + + + + +cpp-strings: Class Index + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class Index
+
+ +
+
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t-members.html b/cpp-strings/html/classpcs_1_1_cpp_string_t-members.html new file mode 100644 index 0000000..184420d --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t-members.html @@ -0,0 +1,235 @@ + + + + + + + +cpp-strings: Member List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT > Member List
+
+
+ +

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

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

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

+ +

#include <cppstrings.h>

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

+Classes

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

+Public Types

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

+Public Member Functions

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

+Static Public Member Functions

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

Detailed Description

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

This is the templated base class for all CppString classes.

+

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

+

Member Function Documentation

+ +

◆ capitalize()

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

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

+ +
+
+ +

◆ center()

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

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

+

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

+ +
+
+ +

◆ contains()

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

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

+

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

+ +

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

+ +
+
+ +

◆ contains_n()

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

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

+

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

+ +
+
+ +

◆ count()

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

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

+ +

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

+ +
+
+ +

◆ count_n() [1/2]

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

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

+ +
+
+ +

◆ count_n() [2/2]

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

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

+ +
+
+ +

◆ endswith() [1/4]

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

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

+ +
+
+ +

◆ endswith() [2/4]

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

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

+ +
+
+ +

◆ endswith() [3/4]

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

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

+ +

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

+ +
+
+ +

◆ endswith() [4/4]

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

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

+ +
+
+ +

◆ endswith_n() [1/3]

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

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

+ +
+
+ +

◆ endswith_n() [2/3]

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

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

+ +
+
+ +

◆ endswith_n() [3/3]

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

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

+ +
+
+ +

◆ expand_tabs()

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

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

+ +
+
+ +

◆ find()

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

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

+

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

+

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

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

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

+ +
+
+ +

◆ find_n() [1/2]

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

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

+

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

+

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

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

◆ find_n() [2/2]

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

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

+

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

+

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

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

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

+ +
+
+ +

◆ format() [1/3]

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

◆ format() [2/3]

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

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

+ +
+
+ +

◆ format() [3/3]

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

◆ index()

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

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

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

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

+ +
+
+ +

◆ index_n() [1/2]

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

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

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

◆ index_n() [2/2]

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

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

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

◆ is_words_sep()

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

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

+ +
+
+ +

◆ isalnum()

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

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

+ +
+
+ +

◆ isalpha()

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

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

+ +
+
+ +

◆ isascii()

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

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

+ +
+
+ +

◆ isdecimal()

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

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

+

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

+ +

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

+ +
+
+ +

◆ isdigit()

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

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

+

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

+

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

+ +
+
+ +

◆ isidentifier()

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

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

+

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

+

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

+

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

+

the currently implemented rule is this simpler one:

+

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

+ +
+
+ +

◆ islower()

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

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

+ +
+
+ +

◆ isnumeric()

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

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

+

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

+ +
+
+ +

◆ isprintable()

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

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

+

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

+ +
+
+ +

◆ ispunctuation()

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

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

+ +
+
+ +

◆ isspace()

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

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

+ +
+
+ +

◆ istitle()

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

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

+

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

+

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

+ +
+
+ +

◆ isupper()

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

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

+ +
+
+ +

◆ join() [1/5]

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

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

+ +

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

+ +
+
+ +

◆ join() [2/5]

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

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

+

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

+ +
+
+ +

◆ join() [3/5]

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

Single parameter signature. Returns a copy of this parameter.

+ +
+
+ +

◆ join() [4/5]

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

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

+

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

+ +

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

+ +
+
+ +

◆ join() [5/5]

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

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

+

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

+ +
+
+ +

◆ ljust()

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

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

+

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

+ +

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

+ +
+
+ +

◆ lower() [1/2]

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

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

+

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

+ +

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

+ +
+
+ +

◆ lower() [2/2]

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

Returns lowercase conversion of the character.

+

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

+ +
+
+ +

◆ lstrip() [1/2]

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

Returns a copy of the string with leading whitespaces removed.

+ +
+
+ +

◆ lstrip() [2/2]

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

Returns a copy of the string with leading characters removed.

+

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

+ +

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

+ +
+
+ +

◆ operator()() [1/2]

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

Generates a new string according to the specified slicing values.

+ +
+
+ +

◆ operator()() [2/2]

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

Generates a new string according to the specified slice.

+

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

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

◆ operator*()

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

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

+ +
+
+ +

◆ operator=() [1/2]

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

Default copy assignment.

+ +
+
+ +

◆ operator=() [2/2]

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

Default move assignment.

+ +
+
+ +

◆ partition()

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

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

+

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

+ +
+
+ +

◆ removeprefix()

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

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

+ +
+
+ +

◆ removesuffix()

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

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

+ +
+
+ +

◆ replace()

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

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

+ +
+
+ +

◆ rfind() [1/3]

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

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

+

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

+

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

+

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

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

◆ rfind() [2/3]

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

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

+

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

+

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

+

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

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

◆ rfind() [3/3]

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

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

+

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

+

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

+

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

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

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

+ +
+
+ +

◆ rfind_n() [1/2]

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

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

+

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

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

◆ rfind_n() [2/2]

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

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

+

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

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

◆ rindex() [1/3]

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

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

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

◆ rindex() [2/3]

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

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

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

◆ rindex() [3/3]

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

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

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

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

+ +
+
+ +

◆ rindex_n() [1/2]

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

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

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

◆ rindex_n() [2/2]

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

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

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

◆ rjust()

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

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

+

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

+ +
+
+ +

◆ rpartition()

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

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

+

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

+ +
+
+ +

◆ rsplit() [1/4]

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

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

+

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

+ +

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

+ +
+
+ +

◆ rsplit() [2/4]

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

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

+ +
+
+ +

◆ rsplit() [3/4]

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

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

+ +
+
+ +

◆ rsplit() [4/4]

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

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

+ +
+
+ +

◆ rstrip() [1/2]

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

Returns a copy of the string with trailing whitespaces removed.

+ +

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

+ +
+
+ +

◆ rstrip() [2/2]

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

Returns a copy of the string with trailing characters removed.

+

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

+ +
+
+ +

◆ split() [1/4]

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

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

+

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

+ +

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

+ +
+
+ +

◆ split() [2/4]

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

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

+

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

+ +
+
+ +

◆ split() [3/4]

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

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

+ +
+
+ +

◆ split() [4/4]

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

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

+ +
+
+ +

◆ splitlines()

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

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

+

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

+

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

+ +
+
+ +

◆ startswith() [1/4]

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

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

+ +
+
+ +

◆ startswith() [2/4]

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

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

+ +
+
+ +

◆ startswith() [3/4]

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

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

+ +

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

+ +
+
+ +

◆ startswith() [4/4]

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

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

+ +
+
+ +

◆ startswith_n() [1/3]

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

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

+ +
+
+ +

◆ startswith_n() [2/3]

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

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

+ +
+
+ +

◆ startswith_n() [3/3]

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

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

+ +
+
+ +

◆ strip() [1/2]

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

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

+ +
+
+ +

◆ strip() [2/2]

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

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

+

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

+ +
+
+ +

◆ substr()

+ + + +

◆ swapcase()

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

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

+

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

+ +
+
+ +

◆ title()

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

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

+ +

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

+ +
+
+ +

◆ translate()

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

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

+

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

+ +
+
+ +

◆ upper() [1/2]

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

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

+

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

+ +

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

+ +
+
+ +

◆ upper() [2/2]

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

Returns uppercase conversion of the character.

+

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

+ +
+
+ +

◆ zfill()

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

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

+

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

+ +
+
+
The documentation for this class was generated from the following file: +
+
+ +
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t.js b/cpp-strings/html/classpcs_1_1_cpp_string_t.js new file mode 100644 index 0000000..7ed5049 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t.js @@ -0,0 +1,99 @@ +var classpcs_1_1_cpp_string_t = +[ + [ "NotFoundException", "classpcs_1_1_cpp_string_t_1_1_not_found_exception.html", null ], + [ "TransTable", "classpcs_1_1_cpp_string_t_1_1_trans_table.html", "classpcs_1_1_cpp_string_t_1_1_trans_table" ], + [ "capitalize", "classpcs_1_1_cpp_string_t.html#a48a00cca031b9c29d1912508e120a5f6", null ], + [ "center", "classpcs_1_1_cpp_string_t.html#af18311d8608e71627bc85f96581e4dd3", null ], + [ "contains", "classpcs_1_1_cpp_string_t.html#a0674e29327353aabf83d0e207fed31ed", null ], + [ "contains_n", "classpcs_1_1_cpp_string_t.html#a031b05f290f589b2df52bb84252c27c7", null ], + [ "count", "classpcs_1_1_cpp_string_t.html#a7beda74b4d5092845a970d51d01fe4bf", null ], + [ "count_n", "classpcs_1_1_cpp_string_t.html#a59839e3b5a186c2554224dbf4528c1b4", null ], + [ "count_n", "classpcs_1_1_cpp_string_t.html#a76f97d56e1713182d5e85d58cd445d10", null ], + [ "endswith", "classpcs_1_1_cpp_string_t.html#a3e9da0bfa54e84420e81668f6ce7f52c", null ], + [ "endswith", "classpcs_1_1_cpp_string_t.html#a6b23210d7d5eb07c9f942d62cc76b05e", null ], + [ "endswith", "classpcs_1_1_cpp_string_t.html#a42f1e87d7f1903536ee79aa058d5c867", null ], + [ "endswith", "classpcs_1_1_cpp_string_t.html#a87b25fce2a05421efd718c599a784a09", null ], + [ "endswith_n", "classpcs_1_1_cpp_string_t.html#a619935926ef961883e9bbd92b2fc23bd", null ], + [ "endswith_n", "classpcs_1_1_cpp_string_t.html#a7eca5636b598c6fc107452ddd04a2f17", null ], + [ "endswith_n", "classpcs_1_1_cpp_string_t.html#a4fd91047ab0126c823aa391a699e03bf", null ], + [ "expand_tabs", "classpcs_1_1_cpp_string_t.html#a2cc04d5062162ff5f7b6111d6f1e78e8", null ], + [ "find", "classpcs_1_1_cpp_string_t.html#a24c4b7a0f713373cb3287d92289562ad", null ], + [ "find_n", "classpcs_1_1_cpp_string_t.html#a6b0bc87b284120d0d3bfc685984997c0", null ], + [ "find_n", "classpcs_1_1_cpp_string_t.html#ac4c9351bb52eb9a62fa7fb2e2d5f054d", null ], + [ "format", "classpcs_1_1_cpp_string_t.html#a1a89389b38fd6af3ea8db3489dd82f70", null ], + [ "format", "classpcs_1_1_cpp_string_t.html#a5caecc371bf390272283ceb7a15c6c1d", null ], + [ "format", "classpcs_1_1_cpp_string_t.html#a944e066f3a863c354a5613a6eda17374", null ], + [ "index", "classpcs_1_1_cpp_string_t.html#a277a2b8a3b93951ccb94b6bf39daa582", null ], + [ "index_n", "classpcs_1_1_cpp_string_t.html#a19a51054b824add817f30c5ff03effe7", null ], + [ "index_n", "classpcs_1_1_cpp_string_t.html#aee94d4b52483021051b168e776b18569", null ], + [ "is_words_sep", "classpcs_1_1_cpp_string_t.html#a7565e4f2958e485ee2b0815be1faa0fa", null ], + [ "isalnum", "classpcs_1_1_cpp_string_t.html#a8fdf96ffee524d5b795c4aad26ece6ae", null ], + [ "isalpha", "classpcs_1_1_cpp_string_t.html#a447b7c58b4be1cdcba3aedf189acbce7", null ], + [ "isascii", "classpcs_1_1_cpp_string_t.html#a710631f31d4c63c2117e8f4804fad3f2", null ], + [ "isdecimal", "classpcs_1_1_cpp_string_t.html#a0b9d8a55419274e7cfd9badb4df704e3", null ], + [ "isdigit", "classpcs_1_1_cpp_string_t.html#a21316d00180377a3f48910a6c4c43b9c", null ], + [ "isidentifier", "classpcs_1_1_cpp_string_t.html#a91f72d425dbb4c53a066338d30683246", null ], + [ "islower", "classpcs_1_1_cpp_string_t.html#ae4ff448bb92e6499c0a76f7d8e11126c", null ], + [ "isnumeric", "classpcs_1_1_cpp_string_t.html#a578176ed20fd8da965afbcae1d99dd59", null ], + [ "isprintable", "classpcs_1_1_cpp_string_t.html#a6257a1832da550d4be32e9f272e51265", null ], + [ "ispunctuation", "classpcs_1_1_cpp_string_t.html#a2842f3a067fdc674709bed048d64e12d", null ], + [ "isspace", "classpcs_1_1_cpp_string_t.html#a959a8f56bb536f2474ffc649a7ad3290", null ], + [ "istitle", "classpcs_1_1_cpp_string_t.html#ad72611f339c2b9027a72fa26f25748c3", null ], + [ "isupper", "classpcs_1_1_cpp_string_t.html#af2784cbe9655bb8e23fe90375d79e69c", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#aa3523b858357399995e4fb9ec796c96c", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#a545d669bb9296b5695b01ac8680bf3f4", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#a30860a043574996d85c80e49ef618594", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#ac1b427d4cc4c2aed8252b3526b63f1b1", null ], + [ "join", "classpcs_1_1_cpp_string_t.html#a9eed3f6c5e09f98f3d5916cc5b3a4311", null ], + [ "ljust", "classpcs_1_1_cpp_string_t.html#aed96c44c384cab45342122cd7e2f02eb", null ], + [ "lower", "classpcs_1_1_cpp_string_t.html#ad5c765eaa85cb4a3e7a914d55a6a5175", null ], + [ "lstrip", "classpcs_1_1_cpp_string_t.html#ac1ad3018d38f291e6debad8d2de92be1", null ], + [ "lstrip", "classpcs_1_1_cpp_string_t.html#aee6e48d5b478d5bab239f54523d23c15", null ], + [ "operator()", "classpcs_1_1_cpp_string_t.html#a0daec57ccab4601f46e9d1c258407765", null ], + [ "operator()", "classpcs_1_1_cpp_string_t.html#a1fa8862a5f306553d6f0dae7e76fce83", null ], + [ "operator*", "classpcs_1_1_cpp_string_t.html#a0995f5b5a01af3f4a749949e23d0d780", null ], + [ "operator=", "classpcs_1_1_cpp_string_t.html#a30e26a3082ad50d01c7d0d98cb9e9c37", null ], + [ "operator=", "classpcs_1_1_cpp_string_t.html#a810a3a27ee7396f9c472648978327a76", null ], + [ "partition", "classpcs_1_1_cpp_string_t.html#ac5f88b0fc1f33cda23c30cb1f3bc560f", null ], + [ "removeprefix", "classpcs_1_1_cpp_string_t.html#a058704b7f4538ec9e1798c5348d37c7a", null ], + [ "removesuffix", "classpcs_1_1_cpp_string_t.html#ad6a8dc124ab8b7cab1cb328240763ed0", null ], + [ "replace", "classpcs_1_1_cpp_string_t.html#ad4f39683db649aa8a65907268c499f02", null ], + [ "rfind", "classpcs_1_1_cpp_string_t.html#ac00bb6f7d74bfdde0d4cc247e78ab20e", null ], + [ "rfind", "classpcs_1_1_cpp_string_t.html#a9f43f20029596abc1362d1242e68e5db", null ], + [ "rfind", "classpcs_1_1_cpp_string_t.html#af363308ba741b267641e1aa35669d603", null ], + [ "rfind_n", "classpcs_1_1_cpp_string_t.html#a790f663f51dfe6e9e15d4f5f025bf107", null ], + [ "rfind_n", "classpcs_1_1_cpp_string_t.html#a519a292eb3f0790d54a59a201f2d6410", null ], + [ "rindex", "classpcs_1_1_cpp_string_t.html#a546105cc9a8a9d493979c30607092cf1", null ], + [ "rindex", "classpcs_1_1_cpp_string_t.html#a2baca0ddff848de56a7b867f68d3efab", null ], + [ "rindex", "classpcs_1_1_cpp_string_t.html#a6693ec49258c6ac80a7875b3ebf3c916", null ], + [ "rindex_n", "classpcs_1_1_cpp_string_t.html#ac3079cbecbdf4151e66f602f39ece836", null ], + [ "rindex_n", "classpcs_1_1_cpp_string_t.html#afc08a4e91b93710838c8f0d6234e057e", null ], + [ "rjust", "classpcs_1_1_cpp_string_t.html#a61fd4215938ec9f0fce1f885d6bb4a2b", null ], + [ "rpartition", "classpcs_1_1_cpp_string_t.html#a61674ee4e97038d82ea7ecc30b1761f6", null ], + [ "rsplit", "classpcs_1_1_cpp_string_t.html#a8111cd357773d304fbb496571d7ee6be", null ], + [ "rsplit", "classpcs_1_1_cpp_string_t.html#a0419f46de6fa532372f3b97b4927ebab", null ], + [ "rsplit", "classpcs_1_1_cpp_string_t.html#ab0ace502f0b3026fefd2942a1e8a0456", null ], + [ "rsplit", "classpcs_1_1_cpp_string_t.html#a3aa66706e268bd570a0084d70dff5cde", null ], + [ "rstrip", "classpcs_1_1_cpp_string_t.html#a86f8c78b2eeb3541fb6b56b4f4ac237b", null ], + [ "rstrip", "classpcs_1_1_cpp_string_t.html#a89e850d45d6dec167e763cf748a06971", null ], + [ "split", "classpcs_1_1_cpp_string_t.html#a7ca47096b03baa0091c3b0349d210931", null ], + [ "split", "classpcs_1_1_cpp_string_t.html#acf4d923cfed55cfd90cf12651ce0ac3d", null ], + [ "split", "classpcs_1_1_cpp_string_t.html#a55a3fa32de834f644ac28d7c2495fa77", null ], + [ "split", "classpcs_1_1_cpp_string_t.html#a8fa2afe84d7fc26f96bbd55f4266df2a", null ], + [ "splitlines", "classpcs_1_1_cpp_string_t.html#a0bd53df14569c307b5ca50a2e1e62960", null ], + [ "startswith", "classpcs_1_1_cpp_string_t.html#ae2f755ae7903586a2086b7b7f943d96e", null ], + [ "startswith", "classpcs_1_1_cpp_string_t.html#ad2cfcc7bd22736ebd9f91f04e6a42f8c", null ], + [ "startswith", "classpcs_1_1_cpp_string_t.html#a5a131c385a01ccc5410d4cffa55cf700", null ], + [ "startswith", "classpcs_1_1_cpp_string_t.html#a326eb96e19c3559a84af86ff1bf54aa4", null ], + [ "startswith_n", "classpcs_1_1_cpp_string_t.html#ae0865e2c7f8a4871804bf71c1c982dc6", null ], + [ "startswith_n", "classpcs_1_1_cpp_string_t.html#a3b7955f9c7f9452a6a025caaaf0e6d73", null ], + [ "startswith_n", "classpcs_1_1_cpp_string_t.html#ab2b293c5f1b55af52ceb75b8f7e4d42e", null ], + [ "strip", "classpcs_1_1_cpp_string_t.html#a12bc043347f555b4701e0c70d972058d", null ], + [ "strip", "classpcs_1_1_cpp_string_t.html#a02919129cdf158e75eae1e9815a071bf", null ], + [ "substr", "classpcs_1_1_cpp_string_t.html#a9debc70420a3fbc7722e3111aeccd819", null ], + [ "swapcase", "classpcs_1_1_cpp_string_t.html#a6ab02b4d1c8093a5dfc089a45427f63c", null ], + [ "title", "classpcs_1_1_cpp_string_t.html#a179634aafb049e8604ca78f813684a28", null ], + [ "translate", "classpcs_1_1_cpp_string_t.html#a2a8c1e78b93da9a0abe471c7a8d85090", null ], + [ "upper", "classpcs_1_1_cpp_string_t.html#a689d2de98f28d131bb0c8b3c87f2f120", null ], + [ "zfill", "classpcs_1_1_cpp_string_t.html#ad3d2b94f37325096205e399b95e9fc5d", null ] +]; \ No newline at end of file diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t.png b/cpp-strings/html/classpcs_1_1_cpp_string_t.png new file mode 100644 index 0000000000000000000000000000000000000000..ce95fd5e428d02a189c0b34a983445fa0511c0a8 GIT binary patch literal 1118 zcmeAS@N?(olHy`uVBq!ia0y~yU=#+j12~vLB4-l+04eDJpAgso|NjG-FW!7D?LV~K z!a%b?V)~gE4<0-KikqGdTLP5hED7=pW&rZRz?^CJ6$S?8m!2+;Ar*{o=f)O2HsEPq zIGyRc{l{e+zcP0g-FZ`XYi^?33h8#GmHtX!yMnwtrw09UP&|3%gQuFxOD`lmYsQ@T zTe~@KuqD<0ZTgrV&%gHEy#0Uce&r=Tnt!)rN$*LUf{$v#lXyzbf63f>x~lGHl6%-^ z@AnfATl5}#B79@=EobJ*&5t`b=WcxbHn@M!uQir0u6=ws^@+u+ec|8FN4mGIpSfkq z@5TRbx|XQ5zES?s-)hEIet36AUFu7pJAr2>KQZ|AM5D1|`_0z=*drUW*wxJLKJIZZ zvYcIe{g8`J%$te=LF;+tx<>bnBDd@H+%P|vm413j*)h{e(?bp%S)KFzhv?+Pc@}+) zliy{hKKg7fxcdIW<7}lH3qH-ArQf1IfAVUc$IKQ*N;i*BnQzRQ_57HnW{UjmP4##E zr@fl{tF!!|`OG7KQ_icrQx86}V*VV~3-9JyRo!0a-Sd9#O3`b~o93;E)44kF{l3F; zSl4RqxlyPWp3yijT*osYv*1LXel{%8$$p`<>+(CNN!aH)3SCeB9lMF+q7I zL&M8Pm4yrvK(U5MPZoxllQhQrJ3KX)F7eW=UEmRv^+QG2vq%*Q-%a{-vs?9K>Ato5 z&xob-PdDkyymZfI*1sRu79F+UJyAt^a^;K%zH0v6N7wAzJ41fWpR7xV{3ogLz7P8x zu6Z)B;TCGB;D^#Clj~J zUD%oWZpM#4zDH)g>N`25{=kv0?`MmPrat^}?Yh*pa}_Uje41|UEcI)uGl~~0zJ9~_ z=9kHpm!f?h)on@_`aW6n(X#n#zWa6GyS*=(?{8^V!pFVIM}zX&@Be+eWZRl^+!?E6 z-|Hnep8bAqV)^d!yt_vym8|?d&AeA7^P+hAK6#HxPPOcl|DM(N)c^9?W8d>RbDjrJ z`sZ${Hff5N+9VN;nI4n0q4@Q|B~yZe9zW-Qu*}P4^>o1>z> + + + + + + +cpp-strings: Member List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException Member List
+
+ +
+
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.html b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.html new file mode 100644 index 0000000..a96dad0 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.html @@ -0,0 +1,132 @@ + + + + + + + +cpp-strings: pcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException Class Reference + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException Class Reference
+
+
+
+Inheritance diagram for pcs::CppStringT< CharT, TraitsT, AllocatorT >::NotFoundException:
+
+
+ +
+ + + +

+Public Types

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

+Public Member Functions

NotFoundException (const char *what_arg)
NotFoundException (const std::string &what_arg)
+
The documentation for this class was generated from the following file: +
+
+ +
+ + + + diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.png b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_not_found_exception.png new file mode 100644 index 0000000000000000000000000000000000000000..55751e8d868a3cfc2f306153ef645f7a930d4947 GIT binary patch literal 1461 zcmb_cYfzGD6#lF%HNJJ78rwc^i&~khWg?K4YYLW_A*q$4Zmm{isZieXlEkdDsI8Y4 zTTM-jRVxZb^9H6?l2QiZqG1KBIgaABEYwOw_N$$K?f&fjao+Qscji3LdFITULn7`2 zO&}8h06>BtJ_rB|7;v6#v=WX3c5Un6%YqaT;;Yx|;dFd@KB=Jd=1!NbXTK{JkH32L z3a+CihpXT>qHLpeW(SRtguTqky43_n5oFJ?jJaGD&-G^Z2(lRU1w-SLc5}q3 zsZ6w=>?eL3Bc*m~_!z1M_oQ*U!nA+J3~k=dDs?5aIvyGPRu7H!7KiRE{TN5~CZVY=mSkj{gXBq(^! zLhul>pTLTupk)BQ(xYIJtCi<#N4 zfU5?D<19<`)yP_3@R_j5zi}ZYpg*lj4-0^or zbq0SnHF+L4u?1pXgt;!}l%v$`Dwm-eZzc`r_q2&Oyc-Mi>q<9?7(P$ucPDqh&v+Q` zm~@Z*!{w@}b2B&slPE}1d*OtO*HWv;DB*rGPrio2pSreRcB#z9pE+mzMSlL5d3OIh zr4R7BcLUwv)*}eG{c-W`8hRA$Xla&VI&iBC0=CgN0auQLz$om$yBr|pqrWQD7(=$U z0eJi-Jo&~GF;@t=qMp_>#Nv1^64hWC^H}Vpb_S&(tdbX~A|h38CLL6y-SHO=+vP{83uweKRyfVGjU8z% ziVt75YI>e=dbvk4B-5nMmKjJFnoIz&9=bpnndNeUGI%6 zZoojTxfy>(W-BPdq;5}H-=J4?y`oXGBcas-(?Uz#rdnh(o?Wp@90oz^MqMFeK5^R8 zU&p@NAh_RRL91lnsUOTlfx853tH^|od9|jNk*Tb!owEbAg5gjhjS||#S2dQQ+gQC4 zx^}&8FXg!kjEkyxe<;B|0D0ga5chdc9{kUqu#vW%c>MZzHiiv7*5p+fBK*Mu1YaV) J*5~J6{sFmqy$%2X literal 0 HcmV?d00001 diff --git a/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table-members.html b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table-members.html new file mode 100644 index 0000000..19c9850 --- /dev/null +++ b/cpp-strings/html/classpcs_1_1_cpp_string_t_1_1_trans_table-members.html @@ -0,0 +1,126 @@ + + + + + + + +cpp-strings: Member List + + + + + + + + + + + + + + +
+
+ + + + + + +
+
cpp-strings 1.0.0 +
+
Pythonic c++ strings
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
pcs::CppStringT< CharT, TraitsT, AllocatorT >::TransTable Member List
+
+
+ +

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

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

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

+ +

#include <cppstrings.h>

+ + + + +

+Public Types

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

+Public Member Functions

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

Detailed Description

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

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

+

Constructor & Destructor Documentation

+ +

◆ TransTable() [1/13]

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

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

+ +

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

+ +
+
+ +

◆ TransTable() [2/13]

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

Creates a TransTable from two strings (#2).

+

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

+ +
+
+ +

◆ TransTable() [3/13]

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

Creates a TransTable from three strings (#3).

+

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

+ +
+
+ +

◆ TransTable() [4/13]

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

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

+

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

+ +
+
+ +

◆ TransTable() [5/13]

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

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

+

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

+ +
+
+ +

◆ TransTable() [6/13]

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

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

+

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

+ +
+
+ +

◆ TransTable() [7/13]

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

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

+

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

+ +
+
+ +

◆ TransTable() [8/13]

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

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

+

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

+ +
+
+ +

◆ TransTable() [9/13]

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

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

+

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

+ +
+
+ +

◆ TransTable() [10/13]

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

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

+

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

+ +
+
+ +

◆ TransTable() [11/13]

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

Default empty constructor.

+ +
+
+ +

◆ TransTable() [12/13]

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

Default copy constructor.

+ +

References TransTable().

+ +
+
+ +

◆ TransTable() [13/13]

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

Default move constructor.

+ +

References TransTable().

+ +
+
+ +

◆ ~TransTable()

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

Default descrtuctor.

+ +

References TransTable().

+ +
+
+

Member Function Documentation

+ +

◆ get_table()

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

< for tests purposes

+ +
+
+ +

◆ operator=() [1/3]

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

Assignment operator with a standard map.

+ +

References TransTable().

+ +
+
+ +

◆ operator=() [2/3]

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

Default copy assignment.

+ +

References TransTable().

+ +
+
+ +

◆ operator=() [3/3]

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

Default move assignment.

+ +

References TransTable().

+ +
+
+ +

◆ operator[]()

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

Indexing operator.

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

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

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

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

+ +

#include <cppstrings.h>

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

+Public Member Functions

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

+Static Public Attributes

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

Detailed Description

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

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

+

Constructor & Destructor Documentation

+ +

◆ Slice()

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

< Valued constructor

+ +

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

+ +

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

+ +
+
+ +

◆ ~Slice()

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

Default destructor.

+ +
+
+

Member Function Documentation

+ +

◆ begin()

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

< starts iterating on specified CppString.

+ +
+
+ +

◆ end()

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

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

+ +
+
+ +

◆ operator*()

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

< dereferences the slice.

+ +
+
+ +

◆ operator++() [1/2]

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

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

+ +

References Slice().

+ +
+
+ +

◆ operator++() [2/2]

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

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

+ +

References Slice().

+ +
+
+ +

◆ start()

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

◆ step()

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

◆ stop()

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

- b -

+ + +

- c -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- i -

+ + +

- j -

+ + +

- l -

+ + +

- o -

+ + +

- p -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+ + +

- u -

+ + +

- z -

+ + +

- ~ -

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

- b -

+ + +

- c -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- i -

+ + +

- j -

+ + +

- l -

+ + +

- o -

+ + +

- p -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+ + +

- u -

+ + +

- z -

+ + +

- ~ -

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

+

license Latest release code_coverage tests

+

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

+

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

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

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

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

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

+

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

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

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

+
+

+License

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

+

+Intro

+

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

+

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

+

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

+

Header file cpp-strings/cppstrings.h defines:

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

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

+
+

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

+

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

+

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

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

    - c -

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

    - i -

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

    - o -

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

    - s -

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

    - t -

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

    - i -

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

    - o -

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

    - s -

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

    - t -

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

    +Classes

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

    +Typedefs

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

    +Functions

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

    Detailed Description

    +

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

    +

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

    +

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

    +

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

    +

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

    +

    Typedef Documentation

    + +

    ◆ CppString

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

    Specialization of basic class with template argument 'char'.

    + +
    +
    + +

    ◆ CppWString

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

    Specialization of basic class with template argument 'wchar_t'.

    + +
    +
    +

    Function Documentation

    + +

    ◆ is_alpha()

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

    struct of slices with default start values

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    +

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

    + +

    References is_alpha().

    + +

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

    + +
    +
    + +

    ◆ is_alpha< char >()

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

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

    + +
    +
    + +

    ◆ is_alpha< wchar_t >()

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

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

    + +
    +
    + +

    ◆ is_ascii()

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

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

    +

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

    + +

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

    + +
    +
    + +

    ◆ is_decimal()

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

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

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

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

    + +
    +
    + +

    ◆ is_decimal< char >()

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

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

    + +
    +
    + +

    ◆ is_decimal< wchar_t >()

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

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

    + +
    +
    + +

    ◆ is_digit()

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

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

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    References is_decimal().

    + +

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

    + +
    +
    + +

    ◆ is_digit< char >()

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

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

    + +

    References is_decimal().

    + +
    +
    + +

    ◆ is_digit< wchar_t >()

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

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

    + +

    References is_decimal().

    + +
    +
    + +

    ◆ is_id_continue()

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

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

    + +

    References is_decimal(), and is_id_start().

    + +

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

    + +
    +
    + +

    ◆ is_id_start()

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

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

    + +

    References is_alpha().

    + +

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

    + +
    +
    + +

    ◆ is_lower()

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

    Returns true if character is lowercase, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

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

    + +
    +
    + +

    ◆ is_lower< char >()

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

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

    + +
    +
    + +

    ◆ is_lower< wchar_t >()

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

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

    + +
    +
    + +

    ◆ is_numeric()

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

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

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    References is_decimal().

    + +

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

    + +
    +
    + +

    ◆ is_numeric< char >()

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

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

    + +

    References is_decimal().

    + +
    +
    + +

    ◆ is_numeric< wchar_t >()

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

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

    + +

    References is_decimal().

    + +
    +
    + +

    ◆ is_printable()

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

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

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

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

    + +
    +
    + +

    ◆ is_printable< char >()

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

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

    + +
    +
    + +

    ◆ is_printable< wchar_t >()

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

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

    + +
    +
    + +

    ◆ is_punctuation()

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

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

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

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

    + +
    +
    + +

    ◆ is_punctuation< char >()

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

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

    + +
    +
    + +

    ◆ is_punctuation< wchar_t >()

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

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

    + +
    +
    + +

    ◆ is_space()

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

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

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

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

    + +
    +
    + +

    ◆ is_space< char >()

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

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

    + +
    +
    + +

    ◆ is_space< wchar_t >()

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

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

    + +
    +
    + +

    ◆ is_upper()

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

    Returns true if character is uppercase, or false otherwise.

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

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

    + +
    +
    + +

    ◆ is_upper< char >()

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

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

    + +
    +
    + +

    ◆ is_upper< wchar_t >()

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

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

    + +
    +
    + +

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

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

    Forms a CppString literal.

    + +
    +
    + +

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

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

    Forms a CppWString literal.

    + +
    +
    + +

    ◆ swap_case()

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

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

    + +

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

    + +

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

    + +
    +
    + +

    ◆ to_lower()

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

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

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

    Referenced by swap_case().

    + +
    +
    + +

    ◆ to_lower< char >()

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

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

    + +
    +
    + +

    ◆ to_lower< wchar_t >()

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

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

    + +
    +
    + +

    ◆ to_upper()

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

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

    +

    SHOULD NEVER BE USED. Use next specializations instead.

    + +

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

    + +
    +
    + +

    ◆ to_upper< char >()

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

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

    + +
    +
    + +

    ◆ to_upper< wchar_t >()

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

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

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