Commit 90230f14 authored by Eric Niebler's avatar Eric Niebler Committed by Facebook Github Bot

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
parent 0917b8bd
......@@ -28,6 +28,7 @@
#include <type_traits>
#include <utility>
#include <folly/Range.h>
#include <folly/Utility.h>
#include <folly/portability/BitsFunctexcept.h>
#include <folly/portability/Constexpr.h>
......@@ -436,10 +437,6 @@ struct ReverseIterator {
} // namespace fixedstring
} // namespace detail
// Defined in folly/Range.h
template <class Iter>
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<const Char*> 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<const Char*> 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<const Char*> 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<const Char*> 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<const Char*> 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<const Char*> a,
const BasicFixedString& b) noexcept {
return !(a == b);
}
/**
* \overload
*/
friend constexpr bool operator!=(
const BasicFixedString& a,
Range<const Char*> 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<const Char*> 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<const Char*> 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<const Char*> a,
const BasicFixedString& b) noexcept {
return b < a;
}
/**
* \overload
*/
friend constexpr bool operator>(
const BasicFixedString& a,
Range<const Char*> 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 Char*> const& a,
const BasicFixedString& b) noexcept {
return !(b < a);
}
/**
* \overload
*/
friend constexpr bool operator<=(
const BasicFixedString& a,
Range<const Char*> 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<const Char*> a,
const BasicFixedString& b) noexcept {
return !(a < b);
}
/**
* \overload
*/
friend constexpr bool operator>=(
const BasicFixedString& a,
Range<const Char*> const& b) noexcept {
return !(a < b);
}
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
* Asymmetric concatenation
*/
......
......@@ -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_<OP> 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!"};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment