From 64a3b61468a35ec6b9be4957225b607f8fc6c2f4 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 17 Oct 2024 20:06:46 -0700 Subject: [PATCH] [FixedString] Add .find_[first|last]_[|not]of() --- include/fixed_containers/fixed_string.hpp | 124 +++++++++++++ test/fixed_string_test.cpp | 212 ++++++++++++++++++++++ 2 files changed, 336 insertions(+) diff --git a/include/fixed_containers/fixed_string.hpp b/include/fixed_containers/fixed_string.hpp index bb5f45e2..ab8cad48 100644 --- a/include/fixed_containers/fixed_string.hpp +++ b/include/fixed_containers/fixed_string.hpp @@ -407,6 +407,130 @@ class FixedString return as_view().rfind(str, pos); } + template + [[nodiscard]] constexpr size_type find_first_of( + const FixedString& str, const size_type pos = 0) const + { + return as_view().find_first_of(str, pos); + } + [[nodiscard]] constexpr size_type find_first_of(const CharT* char_ptr, + size_type pos, + size_type count) const + { + return as_view().find_first_of(char_ptr, pos, count); + } + [[nodiscard]] constexpr size_type find_first_of(const CharT* const str, + const size_type pos = 0) const + { + return as_view().find_first_of(str, pos); + } + [[nodiscard]] constexpr size_type find_first_of(const CharT character, + const size_type pos = 0) const + { + return as_view().find_first_of(character, pos); + } + template + requires(std::is_convertible_v and + not std::is_convertible_v) + [[nodiscard]] constexpr size_type find_first_of(const StringViewLike& str, + const size_type pos = 0) const + { + return as_view().find_first_of(str, pos); + } + + template + [[nodiscard]] constexpr size_type find_first_not_of( + const FixedString& str, const size_type pos = 0) const + { + return as_view().find_first_not_of(str, pos); + } + [[nodiscard]] constexpr size_type find_first_not_of(const CharT* char_ptr, + size_type pos, + size_type count) const + { + return as_view().find_first_not_of(char_ptr, pos, count); + } + [[nodiscard]] constexpr size_type find_first_not_of(const CharT* const str, + const size_type pos = 0) const + { + return as_view().find_first_not_of(str, pos); + } + [[nodiscard]] constexpr size_type find_first_not_of(const CharT character, + const size_type pos = 0) const + { + return as_view().find_first_not_of(character, pos); + } + template + requires(std::is_convertible_v and + not std::is_convertible_v) + [[nodiscard]] constexpr size_type find_first_not_of(const StringViewLike& str, + const size_type pos = 0) const + { + return as_view().find_first_not_of(str, pos); + } + + template + [[nodiscard]] constexpr size_type find_last_of( + const FixedString& str, const size_type pos = npos) const + { + return as_view().find_last_of(str, pos); + } + [[nodiscard]] constexpr size_type find_last_of(const CharT* char_ptr, + size_type pos, + size_type count) const + { + return as_view().find_last_of(char_ptr, pos, count); + } + [[nodiscard]] constexpr size_type find_last_of(const CharT* const str, + const size_type pos = npos) const + { + return as_view().find_last_of(str, pos); + } + [[nodiscard]] constexpr size_type find_last_of(const CharT character, + const size_type pos = npos) const + { + return as_view().find_last_of(character, pos); + } + template + requires(std::is_convertible_v and + not std::is_convertible_v) + [[nodiscard]] constexpr size_type find_last_of(const StringViewLike& str, + const size_type pos = npos) const + { + return as_view().find_last_of(str, pos); + } + + template + [[nodiscard]] constexpr size_type find_last_not_of( + const FixedString& str, const size_type pos = npos) const + { + return as_view().find_last_not_of(str, pos); + } + [[nodiscard]] constexpr size_type find_last_not_of(const CharT* char_ptr, + size_type pos, + size_type count) const + { + return as_view().find_last_not_of(char_ptr, pos, count); + } + [[nodiscard]] constexpr size_type find_last_not_of(const CharT* const str, + const size_type pos = npos) const + { + return as_view().find_last_not_of(str, pos); + } + [[nodiscard]] constexpr size_type find_last_not_of(const CharT character, + const size_type pos = npos) const + { + return as_view().find_last_not_of(character, pos); + } + template + requires(std::is_convertible_v and + not std::is_convertible_v) + [[nodiscard]] constexpr size_type find_last_not_of(const StringViewLike& str, + const size_type pos = npos) const + { + return as_view().find_last_not_of(str, pos); + } + [[nodiscard]] constexpr int compare(std::string_view view) const { return std::string_view(*this).compare(view); diff --git a/test/fixed_string_test.cpp b/test/fixed_string_test.cpp index 73211256..d896dab0 100644 --- a/test/fixed_string_test.cpp +++ b/test/fixed_string_test.cpp @@ -1309,6 +1309,218 @@ TEST(FixedString, Rfind) } } +TEST(FixedString, FindFirstOf) +{ + { + const FixedString<20> var1{"abcdefg_abcdefg"}; + const std::string non_present{"zzz"}; + const std::string present{"zzzedczzz"}; + + ASSERT_EQ(NPOS, var1.find_first_of(non_present)); + ASSERT_EQ(2, var1.find_first_of(present)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr FixedString<9> NON_PRESENT{"zzz"}; + constexpr FixedString<25> PRESENT{"zzzedczzz"}; + + static_assert(NPOS == VAR1.find_first_of(NON_PRESENT)); + static_assert(2 == VAR1.find_first_of(PRESENT)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char* NON_PRESENT{"zzz"}; + constexpr const char* PRESENT{"zzzedczzzBLAHBLAH"}; + + static_assert(NPOS == VAR1.find_first_of(NON_PRESENT, 0, 3)); + static_assert(2 == VAR1.find_first_of(PRESENT, 0, 6)); + static_assert(NPOS == VAR1.find_first_of(PRESENT, 0, 3)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char* NON_PRESENT{"zzz"}; + constexpr const char* PRESENT{"zzzedczzz"}; + + static_assert(NPOS == VAR1.find_first_of(NON_PRESENT)); + static_assert(2 == VAR1.find_first_of(PRESENT)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char NON_PRESENT_CHAR{'z'}; + constexpr const char PRESENT_CHAR{'c'}; + + static_assert(NPOS == VAR1.find_first_of(NON_PRESENT_CHAR)); + static_assert(2 == VAR1.find_first_of(PRESENT_CHAR)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr std::string_view NON_PRESENT{"zzz"}; + constexpr std::string_view PRESENT{"zzzedczzz"}; + + static_assert(NPOS == VAR1.find_first_of(NON_PRESENT)); + static_assert(2 == VAR1.find_first_of(PRESENT)); + } +} + +TEST(FixedString, FindFirstNotOf) +{ + { + const FixedString<20> var1{"abcdefg_abcdefg"}; + const std::string non_present{"abZdefg"}; + const std::string present{"abcdefg_"}; + + ASSERT_EQ(2, var1.find_first_not_of(non_present)); + ASSERT_EQ(NPOS, var1.find_first_not_of(present)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr FixedString<9> NON_PRESENT{"abZdefg"}; + constexpr FixedString<25> PRESENT{"abcdefg_"}; + + static_assert(2 == VAR1.find_first_not_of(NON_PRESENT)); + static_assert(NPOS == VAR1.find_first_not_of(PRESENT)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char* NON_PRESENT{"abZdefgBLAHBLAH"}; + constexpr const char* PRESENT{"abcdefg_BLAHBLAH"}; + + static_assert(2 == VAR1.find_first_not_of(NON_PRESENT, 0, 3)); + static_assert(2 == VAR1.find_first_not_of(NON_PRESENT, 0, 7)); + static_assert(NPOS == VAR1.find_first_not_of(PRESENT, 0, 8)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char* NON_PRESENT{"abZdefg"}; + constexpr const char* PRESENT{"abcdefg_"}; + + static_assert(2 == VAR1.find_first_not_of(NON_PRESENT)); + static_assert(NPOS == VAR1.find_first_not_of(PRESENT)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char NON_PRESENT_CHAR{'z'}; + constexpr const char PRESENT_CHAR{'a'}; + + static_assert(0 == VAR1.find_first_not_of(NON_PRESENT_CHAR)); + static_assert(1 == VAR1.find_first_not_of(PRESENT_CHAR)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr std::string_view NON_PRESENT{"abZdefg"}; + constexpr std::string_view PRESENT{"abcdefg_"}; + + static_assert(2 == VAR1.find_first_not_of(NON_PRESENT)); + static_assert(NPOS == VAR1.find_first_not_of(PRESENT)); + } +} + +TEST(FixedString, FindLastOf) +{ + { + const FixedString<20> var1{"abcdefg_abcdefg"}; + const std::string non_present{"zzz"}; + const std::string present{"zzzcdezzz"}; + + ASSERT_EQ(NPOS, var1.find_last_of(non_present)); + ASSERT_EQ(12, var1.find_last_of(present)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr FixedString<9> NON_PRESENT{"zzz"}; + constexpr FixedString<25> PRESENT{"zzzcdezzz"}; + + static_assert(NPOS == VAR1.find_last_of(NON_PRESENT)); + static_assert(12 == VAR1.find_last_of(PRESENT)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char* NON_PRESENT{"zzz"}; + constexpr const char* PRESENT{"zzzcdezzzBLAHBLAH"}; + + static_assert(NPOS == VAR1.find_last_of(NON_PRESENT, NPOS, 3)); + static_assert(12 == VAR1.find_last_of(PRESENT, NPOS, 6)); + static_assert(NPOS == VAR1.find_last_of(PRESENT, NPOS, 3)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char* NON_PRESENT{"zzz"}; + constexpr const char* PRESENT{"zzzcdezzz"}; + + static_assert(NPOS == VAR1.find_last_of(NON_PRESENT)); + static_assert(12 == VAR1.find_last_of(PRESENT)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char NON_PRESENT_CHAR{'z'}; + constexpr const char PRESENT_CHAR{'c'}; + + static_assert(NPOS == VAR1.find_last_of(NON_PRESENT_CHAR)); + static_assert(10 == VAR1.find_last_of(PRESENT_CHAR)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr std::string_view NON_PRESENT{"zzz"}; + constexpr std::string_view PRESENT{"zzzcdezzz"}; + + static_assert(NPOS == VAR1.find_last_of(NON_PRESENT)); + static_assert(12 == VAR1.find_last_of(PRESENT)); + } +} + +TEST(FixedString, FindLastNotOf) +{ + { + const FixedString<20> var1{"abcdefg_abcdefg"}; + const std::string non_present{"abZdefg"}; + const std::string present{"abcdefg_"}; + + ASSERT_EQ(10, var1.find_last_not_of(non_present)); + ASSERT_EQ(NPOS, var1.find_last_not_of(present)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr FixedString<9> NON_PRESENT{"abZdefg"}; + constexpr FixedString<25> PRESENT{"abcdefg_"}; + + static_assert(10 == VAR1.find_last_not_of(NON_PRESENT)); + static_assert(NPOS == VAR1.find_last_not_of(PRESENT)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char* NON_PRESENT{"abZdefgBLAHBLAH"}; + constexpr const char* PRESENT{"abcdefg_BLAHBLAH"}; + + static_assert(14 == VAR1.find_last_not_of(NON_PRESENT, NPOS, 3)); + static_assert(10 == VAR1.find_last_not_of(NON_PRESENT, NPOS, 7)); + static_assert(NPOS == VAR1.find_last_not_of(PRESENT, NPOS, 8)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char* NON_PRESENT{"abZdefg"}; + constexpr const char* PRESENT{"abcdefg_"}; + + static_assert(10 == VAR1.find_last_not_of(NON_PRESENT)); + static_assert(NPOS == VAR1.find_last_not_of(PRESENT)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr const char NON_PRESENT_CHAR{'z'}; + constexpr const char PRESENT_CHAR{'g'}; + + static_assert(14 == VAR1.find_last_not_of(NON_PRESENT_CHAR)); + static_assert(13 == VAR1.find_last_not_of(PRESENT_CHAR)); + } + { + constexpr FixedString<20> VAR1{"abcdefg_abcdefg"}; + constexpr std::string_view NON_PRESENT{"abZdefg"}; + constexpr std::string_view PRESENT{"abcdefg_"}; + + static_assert(10 == VAR1.find_last_not_of(NON_PRESENT)); + static_assert(NPOS == VAR1.find_last_not_of(PRESENT)); + } +} + TEST(FixedString, Equality) { constexpr auto VAL1 = FixedString<12>{"012"};