X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FFixedString.h;h=ece7691b74d09b43a7e0b413394cce2b939410eb;hb=8af0eef96d6b2a2d3ea4e5bd6cf6ccd841fca14b;hp=c99484d45c32cc88bb858ec93432d29a3691f7ee;hpb=6ed9b4c667bdba5ce0da3da165d4da5c42e0626f;p=folly.git diff --git a/folly/FixedString.h b/folly/FixedString.h index c99484d4..ece7691b 100644 --- a/folly/FixedString.h +++ b/folly/FixedString.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,27 +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 @@ -118,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 @@ -286,7 +272,7 @@ struct Helper { std::size_t left_count, const Right& right, std::size_t right_count, - std::index_sequence is) noexcept { + folly::index_sequence is) noexcept { return {left, left_count, right, right_count, is}; } @@ -299,7 +285,7 @@ struct Helper { const Right& right, std::size_t right_pos, std::size_t right_count, - std::index_sequence is) noexcept { + folly::index_sequence is) noexcept { return {left, left_size, left_pos, @@ -317,7 +303,7 @@ struct Helper { } }; -#if defined(__GNUC__) && !defined(__CLANG__) && __GNUC__ <= 4 +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 4 #pragma GCC diagnostic pop #endif @@ -329,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 { @@ -435,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); /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * @@ -502,7 +472,7 @@ std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len); * of types `FixedString<4>`, `FixedString<8>`, etc. For example: * \par * \code - * using namespace folly::StringLiterals; + * using namespace folly::string_literals; * constexpr auto hello = "hello"_fs8; // A FixedString<8> containing "hello" * \endcode * \par @@ -514,7 +484,7 @@ std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len); * the right size. For example: * \par * \code - * using namespace folly::StringLiterals; + * using namespace folly::string_literals; * // NOTE: Only works on compilers with GNU extensions enabled. Clang and * // gcc support this (-Wgnu-string-literal-operator-template): * constexpr auto hello = "hello"_fs; // A FixedString<5> containing "hello" @@ -547,16 +517,25 @@ 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. - using Indices = std::make_index_sequence; + using Indices = folly::make_index_sequence; template constexpr BasicFixedString( const That& that, std::size_t size, - std::index_sequence, + folly::index_sequence, std::size_t pos = 0, std::size_t count = npos) noexcept : data_{(Is < (size - pos) && Is < count ? that[Is + pos] : Char(0))..., @@ -567,7 +546,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { constexpr BasicFixedString( std::size_t count, Char ch, - std::index_sequence) noexcept + folly::index_sequence) noexcept : data_{((Is < count) ? ch : Char(0))..., Char(0)}, size_{count} {} // Concatenation constructor @@ -577,7 +556,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { std::size_t left_size, const Right& right, std::size_t right_size, - std::index_sequence) noexcept + folly::index_sequence) noexcept : data_{detail::fixedstring::char_at_( left, left_size, @@ -597,7 +576,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { const Right& right, std::size_t right_pos, std::size_t right_count, - std::index_sequence) noexcept + folly::index_sequence) noexcept : data_{detail::fixedstring::char_at_( left, left_size, @@ -686,7 +665,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { : BasicFixedString{ that.data_, that.size_, - std::make_index_sequence<(M < N ? M : N)>{}, + folly::make_index_sequence<(M < N ? M : N)>{}, pos, detail::fixedstring::checkOverflow( detail::fixedstring::checkOverflowOrNpos( @@ -707,7 +686,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { constexpr /* implicit */ BasicFixedString(const Char (&that)[M]) noexcept : BasicFixedString{detail::fixedstring::checkNullTerminated(that), M - 1u, - std::make_index_sequence{}} {} + folly::make_index_sequence{}} {} /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * Construct from a `const Char*` and count @@ -811,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()}` @@ -1286,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; @@ -1334,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; @@ -1362,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; @@ -1605,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 @@ -1617,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. * @@ -1647,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}` @@ -1884,7 +1872,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { detail::fixedstring::checkOverflow(that_pos, that.size_), detail::fixedstring::checkOverflowOrNpos( that_count, that.size_ - that_pos), - std::make_index_sequence{}); + folly::make_index_sequence{}); } /** @@ -1984,7 +1972,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { detail::fixedstring::checkNullTerminated(that), detail::fixedstring::checkOverflow(that_pos, M - 1u), detail::fixedstring::checkOverflowOrNpos(that_count, M - 1u - that_pos), - std::make_index_sequence{}); + folly::make_index_sequence{}); } /** @@ -2042,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; @@ -2659,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 { @@ -2674,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 { @@ -2693,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 { @@ -2708,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 { @@ -2723,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 { @@ -2738,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 */ @@ -2750,7 +2851,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { M - 1u, b.data_, b.size_, - std::make_index_sequence{}); + folly::make_index_sequence{}); } /** @@ -2765,7 +2866,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { a.size_, detail::fixedstring::checkNullTerminated(b), M - 1u, - std::make_index_sequence{}); + folly::make_index_sequence{}); } /** @@ -2780,7 +2881,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { 1u, b.data_, b.size_, - std::make_index_sequence{}); + folly::make_index_sequence{}); } /** @@ -2795,10 +2896,19 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { a.size_, A{b, Char(0)}, 1u, - std::make_index_sequence{}); + folly::make_index_sequence{}); } }; +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 */ @@ -2867,7 +2977,7 @@ constexpr BasicFixedString operator+( a.size(), detail::fixedstring::Helper::data_(b), b.size(), - std::make_index_sequence{}); + folly::make_index_sequence{}); } /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** @@ -2894,13 +3004,13 @@ FOLLY_CPP14_CONSTEXPR void swap( a.swap(b); } -inline namespace Literals { -inline namespace StringLiterals { +inline namespace literals { +inline namespace string_literals { 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 @@ -2914,7 +3024,7 @@ constexpr const std::size_t& npos = detail::fixedstring::FixedStringBase::npos; * \par Example: * \par * \code - * using namespace folly::StringLiterals; + * using namespace folly::string_literals; * constexpr auto hello = "hello world!"_fs; * \endcode * @@ -2953,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: @@ -2989,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