From: Eric Niebler Date: Fri, 5 May 2017 21:10:47 +0000 (-0700) Subject: FixedString gets comparisons with folly::Range and hence with std::string X-Git-Tag: v2017.05.08.00~3 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=90230f140b4b4cb350d087c79af30eceb21e8d41 FixedString gets comparisons with folly::Range and hence with std::string Summary: It should be possible to perform simple comparison operations between a FixedString and a std::string. By adding asymmetric comparison operators with FixedString and Range, we make FixedString comparable with anything convertible to Range, including std::string. Reviewed By: yfeldblum Differential Revision: D5007704 fbshipit-source-id: fee89d8807ac2d5378eec0d0a51eb8684976a271 --- diff --git a/folly/FixedString.h b/folly/FixedString.h index ee052827..a18838b9 100644 --- a/folly/FixedString.h +++ b/folly/FixedString.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -436,10 +437,6 @@ struct ReverseIterator { } // namespace fixedstring } // namespace detail -// Defined in folly/Range.h -template -class Range; - // Defined in folly/Hash.h std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len); @@ -1606,6 +1603,13 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { return compare(0u, size_, that, folly::constexpr_strlen(that)); } + /** + * \overload + */ + constexpr int compare(Range that) const noexcept { + return compare(0u, size_, that.begin(), that.size()); + } + /** * Compare two strings for lexicographical ordering. * \note Equivalent to @@ -1618,6 +1622,16 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { return compare(this_pos, this_count, that, folly::constexpr_strlen(that)); } + /** + * \overload + */ + constexpr int compare( + std::size_t this_pos, + std::size_t this_count, + Range that) const noexcept(false) { + return compare(this_pos, this_count, that.begin(), that.size()); + } + /** * Compare two strings for lexicographical ordering. * @@ -1648,6 +1662,18 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { that_count)); } + constexpr int compare( + std::size_t this_pos, + std::size_t this_count, + Range that, + std::size_t that_count) const noexcept(false) { + return compare( + this_pos, + this_count, + that.begin(), + detail::fixedstring::checkOverflow(that_count, that.size())); + } + /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * Return a substring from `pos` to the end of the string. * \note Equivalent to `BasicFixedString{*this, pos}` @@ -2660,6 +2686,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { return b == a; } + /** + * \overload + */ + friend constexpr bool operator==( + Range a, + const BasicFixedString& b) noexcept { + return detail::fixedstring::equal_(a.begin(), a.size(), b.data_, b.size_); + } + + /** + * \overload + */ + friend constexpr bool operator==( + const BasicFixedString& a, + Range b) noexcept { + return b == a; + } + friend constexpr bool operator!=( const Char* a, const BasicFixedString& b) noexcept { @@ -2675,6 +2719,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { return !(b == a); } + /** + * \overload + */ + friend constexpr bool operator!=( + Range a, + const BasicFixedString& b) noexcept { + return !(a == b); + } + + /** + * \overload + */ + friend constexpr bool operator!=( + const BasicFixedString& a, + Range b) noexcept { + return !(a == b); + } + friend constexpr bool operator<( const Char* a, const BasicFixedString& b) noexcept { @@ -2694,6 +2756,28 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { a.data_, 0u, a.size_, b, 0u, folly::constexpr_strlen(b)); } + /** + * \overload + */ + friend constexpr bool operator<( + Range a, + const BasicFixedString& b) noexcept { + return detail::fixedstring::Cmp::LT == + detail::fixedstring::compare_( + a.begin(), 0u, a.size(), b.data_, 0u, b.size_); + } + + /** + * \overload + */ + friend constexpr bool operator<( + const BasicFixedString& a, + Range b) noexcept { + return detail::fixedstring::Cmp::LT == + detail::fixedstring::compare_( + a.data_, 0u, a.size_, b.begin(), 0u, b.size()); + } + friend constexpr bool operator>( const Char* a, const BasicFixedString& b) noexcept { @@ -2709,6 +2793,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { return b < a; } + /** + * \overload + */ + friend constexpr bool operator>( + Range a, + const BasicFixedString& b) noexcept { + return b < a; + } + + /** + * \overload + */ + friend constexpr bool operator>( + const BasicFixedString& a, + Range b) noexcept { + return b < a; + } + friend constexpr bool operator<=( const Char* a, const BasicFixedString& b) noexcept { @@ -2724,6 +2826,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { return !(b < a); } + /** + * \overload + */ + friend constexpr bool operator<=( + Range const& a, + const BasicFixedString& b) noexcept { + return !(b < a); + } + + /** + * \overload + */ + friend constexpr bool operator<=( + const BasicFixedString& a, + Range b) noexcept { + return !(b < a); + } + friend constexpr bool operator>=( const Char* a, const BasicFixedString& b) noexcept { @@ -2739,6 +2859,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { return !(a < b); } + /** + * \overload + */ + friend constexpr bool operator>=( + Range a, + const BasicFixedString& b) noexcept { + return !(a < b); + } + + /** + * \overload + */ + friend constexpr bool operator>=( + const BasicFixedString& a, + Range const& b) noexcept { + return !(a < b); + } + /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * Asymmetric concatenation */ diff --git a/folly/test/FixedStringTest.cpp b/folly/test/FixedStringTest.cpp index c0b019be..121e94fe 100644 --- a/folly/test/FixedStringTest.cpp +++ b/folly/test/FixedStringTest.cpp @@ -312,6 +312,26 @@ TEST(FixedStringCompareTest, Compare) { static_assert(tmp3 == "aaa", ""); } +TEST(FixedStringCompareTest, CompareStdString) { + constexpr folly::FixedString<10> tmp1{"aaaaaaaaaa"}; + std::string const tmp2{"aaaaaaaaaba"}; + EXPECT_EQ(-1, tmp1.compare(tmp2)); + // These are specifically testing the operators, and so we can't rely + // on whever the implementation details of EXPECT_ might be. + EXPECT_FALSE(tmp1 == tmp2); + EXPECT_FALSE(tmp2 == tmp1); + EXPECT_TRUE(tmp1 != tmp2); + EXPECT_TRUE(tmp2 != tmp1); + EXPECT_TRUE(tmp1 < tmp2); + EXPECT_FALSE(tmp2 < tmp1); + EXPECT_TRUE(tmp1 <= tmp2); + EXPECT_FALSE(tmp2 <= tmp1); + EXPECT_FALSE(tmp1 > tmp2); + EXPECT_TRUE(tmp2 > tmp1); + EXPECT_FALSE(tmp1 >= tmp2); + EXPECT_TRUE(tmp2 >= tmp1); +} + #if FOLLY_USE_CPP14_CONSTEXPR constexpr folly::FixedString<20> constexpr_append_string_test() { folly::FixedString<20> a{"hello"}, b{"X world!"};