From e56696ad857dd2b57b6a56da223838594cbc2f80 Mon Sep 17 00:00:00 2001 From: bergmann Date: Fri, 6 Dec 2019 00:23:29 +0100 Subject: [PATCH] * Implemented invariant string comparison --- include/cppcore/conversion/enum.h | 2 +- include/cppcore/misc/compare.h | 24 +++++++++++++++++++--- include/cppcore/misc/compare.inl | 32 ++++++++++++++++++++++++----- test/cppcore/misc/compare_tests.cpp | 21 +++++++++++++++++++ 4 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 test/cppcore/misc/compare_tests.cpp diff --git a/include/cppcore/conversion/enum.h b/include/cppcore/conversion/enum.h index 99c3163..e6c2fca 100644 --- a/include/cppcore/conversion/enum.h +++ b/include/cppcore/conversion/enum.h @@ -62,7 +62,7 @@ namespace cppcore using enum_type = T_enum; using traits_type = T_traits; using enum_to_string_map_type = std::map; - using string_to_enum_map_type = std::map; + using string_to_enum_map_type = std::map; /** * @brief Returns a map with enum to string values. diff --git a/include/cppcore/misc/compare.h b/include/cppcore/misc/compare.h index b5dfbd4..45e18ba 100644 --- a/include/cppcore/misc/compare.h +++ b/include/cppcore/misc/compare.h @@ -6,12 +6,12 @@ namespace cppcore { /** - * @brief Predicate class to caompare to string ignoring the case and variant. + * @brief Predicate class to compare two strings ignoring the case and variant. */ - struct op_less_invariant_string + struct op_invariant_string_less { /** - * @brief Compare to string. + * @brief Compare two strings. * * @param[in] lhs Left hand value. * @param[in] rhs Right hand value. @@ -22,6 +22,24 @@ namespace cppcore inline bool operator()(const std::string& lhs, const std::string& rhs) const; }; + /** + * @brief Predicate class to compare two strings ignoring the case and variant. + */ + struct op_invariant_string_compare + { + /** + * @brief Compare two strings. + * + * @param[in] lhs Left hand value. + * @param[in] rhs Right hand value. + * + * @retval -1 If lhs is less than rhs. + * @retval 0 If lhs is equal rhs. + * @retval 1 If lhs is greater than rhs. + */ + inline int operator()(const std::string& lhs, const std::string& rhs) const; + }; + } #include "compare.inl" diff --git a/include/cppcore/misc/compare.inl b/include/cppcore/misc/compare.inl index 68a4d6c..d673712 100644 --- a/include/cppcore/misc/compare.inl +++ b/include/cppcore/misc/compare.inl @@ -5,15 +5,21 @@ namespace cppcore { - /* op_less_invariant_string */ + /* op_invariant_string_less */ - bool op_less_invariant_string + bool op_invariant_string_less ::operator()(const std::string& lhs, const std::string& rhs) const + { return op_invariant_string_compare { } (lhs, rhs) < 0; } + + /* op_invariant_string_compare */ + + int op_invariant_string_compare::operator()(const std::string& lhs, const std::string& rhs) const { auto c1 = lhs.c_str(); auto c2 = rhs.c_str(); auto l1 = lhs.size(); auto l2 = rhs.size(); + while (l1 > 0 && l2 > 0 && std::tolower(*c1) == std::tolower(*c2)) { ++c1; @@ -21,9 +27,25 @@ namespace cppcore --l1; --l2; } - return l1 > 0 && l2 > 0 - ? std::tolower(*c1) < std::tolower(*c2) - : l1 < l2; + + if (l1 > 0 && l2 > 0) + { + auto x1 = std::tolower(*c1); + auto x2 = std::tolower(*c2); + + return + x1 < x2 ? -1 : + x1 > x2 ? 1 : + 0; + } + else + { + return + l1 < l2 ? -1 : + l1 > l2 ? 1 : + 0; + } } + } diff --git a/test/cppcore/misc/compare_tests.cpp b/test/cppcore/misc/compare_tests.cpp new file mode 100644 index 0000000..758d057 --- /dev/null +++ b/test/cppcore/misc/compare_tests.cpp @@ -0,0 +1,21 @@ +#include + +#include + +using namespace ::cppcore; +using namespace ::testing; + +TEST(compare_tests, invariant_string_compare) +{ + op_invariant_string_compare cmp; + + // Length check + EXPECT_EQ( 0, cmp("abcdef", "AbCdef")); + EXPECT_EQ(-1, cmp("abcde", "AbCdef")); + EXPECT_EQ( 1, cmp("abcdeF", "AbCde")); + + // Value checks + EXPECT_EQ( 0, cmp("abcdef", "AbCdef")); + EXPECT_EQ(-1, cmp("aBbDef", "AbCdef")); + EXPECT_EQ( 1, cmp("abcdeF", "AbCdeD")); +}