X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FFixedString.h;h=ece7691b74d09b43a7e0b413394cce2b939410eb;hp=ee0528271b2d5b5d1fd3ed01725f0b9d9c8c7c06;hb=17c08956e0c46684e3a3a9d3b5e9bc733a09c0ea;hpb=2843ff12364e1159d99f2b96bcc4a5c428dad1fa diff --git a/folly/FixedString.h b/folly/FixedString.h index ee052827..ece7691b 100644 --- a/folly/FixedString.h +++ b/folly/FixedString.h @@ -28,28 +28,13 @@ #include #include +#include +#include +#include #include #include #include -// Define FOLLY_USE_CPP14_CONSTEXPR to be true if the compiler's C++14 -// constexpr support is "good enough". -#ifndef FOLLY_USE_CPP14_CONSTEXPR -#if defined(__clang__) -#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201300L -#elif defined(__GNUC__) -#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201304L -#else -#define FOLLY_USE_CPP14_CONSTEXPR 0 // MSVC? -#endif -#endif - -#if FOLLY_USE_CPP14_CONSTEXPR -#define FOLLY_CPP14_CONSTEXPR constexpr -#else -#define FOLLY_CPP14_CONSTEXPR inline -#endif - namespace folly { template @@ -119,7 +104,7 @@ enum class Cmp : int { LT = -1, EQ = 0, GT = 1 }; // Rather annoyingly, GCC's -Warray-bounds warning issues false positives for // this code. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61971 -#if defined(__GNUC__) && !defined(__CLANG__) && __GNUC__ <= 4 +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Warray-bounds" #endif @@ -318,7 +303,7 @@ struct Helper { } }; -#if defined(__GNUC__) && !defined(__CLANG__) && __GNUC__ <= 4 +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 4 #pragma GCC diagnostic pop #endif @@ -330,18 +315,6 @@ FOLLY_CPP14_CONSTEXPR void constexpr_swap(T& a, T& b) noexcept( b = std::move(tmp); } -// FUTURE: use const_log2 to fold instantiations of BasicFixedString together. -// All BasicFixedString instantiations could share the implementation -// of BasicFixedString, where M is the next highest power of 2 after N. -// -// Also, because of alignment of the data_ and size_ members, N should never be -// smaller than `(alignof(std::size_t)/sizeof(C))-1` (-1 because of the null -// terminator). OR, create a specialization for BasicFixedString that -// does not have a size_ member, since it is unnecessary. -constexpr std::size_t const_log2(std::size_t N, std::size_t log2 = 0u) { - return N / 2u == 0u ? log2 : const_log2(N / 2u, log2 + 1u); -} - // For constexpr reverse iteration over a BasicFixedString template struct ReverseIterator { @@ -436,11 +409,7 @@ struct ReverseIterator { } // namespace fixedstring } // namespace detail -// Defined in folly/Range.h -template -class Range; - -// Defined in folly/Hash.h +// Defined in folly/hash/Hash.h std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len); /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * @@ -548,6 +517,15 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { friend class BasicFixedString; friend struct detail::fixedstring::Helper; + // FUTURE: use constexpr_log2 to fold instantiations of BasicFixedString + // together. All BasicFixedString instantiations could share the + // implementation of BasicFixedString, where M is the next highest power + // of 2 after N. + // + // Also, because of alignment of the data_ and size_ members, N should never + // be smaller than `(alignof(std::size_t)/sizeof(C))-1` (-1 because of the + // null terminator). OR, create a specialization for BasicFixedString + // that does not have a size_ member, since it is unnecessary. Char data_[N + 1u]; // +1 for the null terminator std::size_t size_; // Nbr of chars, not incl. null terminator. size_ <= N. @@ -812,29 +790,6 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { return *this; } - /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** - * Conversion to folly::Range - * \return `Range{begin(), end()}` - */ - template < - class Iter, - class = typename std::enable_if< - std::is_convertible::value>::type> - FOLLY_CPP14_CONSTEXPR /* implicit */ operator Range() noexcept { - return {begin(), end()}; - } - - /** - * \overload - */ - template < - class Iter, - class = typename std::enable_if< - std::is_convertible::value>::type> - constexpr /* implicit */ operator Range() const noexcept { - return {begin(), end()}; - } - /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * Conversion to folly::Range * \return `Range{begin(), end()}` @@ -1287,8 +1242,9 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { std::size_t count, Char ch) noexcept(false) { detail::fixedstring::checkOverflow(count, N - size_); - for (std::size_t i = 0u; i < count; ++i) + for (std::size_t i = 0u; i < count; ++i) { data_[size_ + i] = ch; + } size_ += count; data_[size_] = Char(0); return *this; @@ -1335,8 +1291,9 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { detail::fixedstring::checkOverflow(pos, that.size_); count = detail::fixedstring::checkOverflowOrNpos(count, that.size_ - pos); detail::fixedstring::checkOverflow(count, N - size_); - for (std::size_t i = 0u; i < count; ++i) + for (std::size_t i = 0u; i < count; ++i) { data_[size_ + i] = that.data_[pos + i]; + } size_ += count; data_[size_] = Char(0); return *this; @@ -1363,8 +1320,9 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { const Char* that, std::size_t count) noexcept(false) { detail::fixedstring::checkOverflow(count, N - size_); - for (std::size_t i = 0u; i < count; ++i) + for (std::size_t i = 0u; i < count; ++i) { data_[size_ + i] = that[i]; + } size_ += count; data_[size_] = Char(0); return *this; @@ -1606,6 +1564,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 +1583,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 +1623,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}` @@ -2043,8 +2030,9 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { copy(Char* dest, std::size_t count, std::size_t pos) const noexcept(false) { detail::fixedstring::checkOverflow(pos, size_); for (std::size_t i = 0u; i < count; ++i) { - if (i + pos == size_) + if (i + pos == size_) { return size_; + } dest[i] = data_[i + pos]; } return count; @@ -2660,6 +2648,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 +2681,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 +2718,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 +2755,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 +2788,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 +2821,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 */ @@ -2800,6 +2900,15 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { } }; +template +inline std::basic_ostream& operator<<( + std::basic_ostream& os, + const BasicFixedString& string) { + using StreamSize = decltype(os.width()); + os.write(string.begin(), static_cast(string.size())); + return os; +} + /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * Symmetric relational operators */ @@ -2901,7 +3010,7 @@ inline namespace { // "const std::size_t&" is so that folly::npos has the same address in every // translation unit. This is to avoid potential violations of the ODR. constexpr const std::size_t& npos = detail::fixedstring::FixedStringBase::npos; -} +} // namespace #if defined(__GNUC__) #pragma GCC diagnostic push @@ -2954,8 +3063,8 @@ FOLLY_DEFINE_FIXED_STRING_UDL(64) FOLLY_DEFINE_FIXED_STRING_UDL(128) #undef FOLLY_DEFINE_FIXED_STRING_UDL -} -} +} // namespace string_literals +} // namespace literals // TODO: // // numeric conversions: @@ -2990,4 +3099,4 @@ FOLLY_DEFINE_FIXED_STRING_UDL(128) // constexpr FixedString to_fixed_string_ll() noexcept // template // constexpr FixedString to_fixed_string_ull() noexcept; -} +} // namespace folly