38 #include <type_traits> 40 #if FOLLY_HAS_STRING_VIEW 41 #include <string_view> 76 class Comp = std::equal_to<typename Range<Iter>::value_type>>
104 template <
class Iter>
117 template <
class Iter>
118 typename std::enable_if<
120 typename std::iterator_traits<Iter>::iterator_category,
121 std::random_access_iterator_tag>
::value,
122 typename std::iterator_traits<Iter>::reference>
::type 130 template <
class Iter>
131 typename std::enable_if<
133 typename std::iterator_traits<Iter>::iterator_category,
134 std::random_access_iterator_tag>
::value,
135 typename std::iterator_traits<Iter>::reference>
::type 171 template <
class Iter>
177 typedef typename std::remove_reference<
180 typedef typename std::iterator_traits<Iter>::reference
reference;
188 typedef typename std::conditional<
212 #if !__clang__ || __CLANG_PREREQ(3, 7) // Clang 3.6 crashes on this line 213 Range(std::nullptr_t) =
delete;
220 "This constructor is only available for character ranges");
223 template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
225 : b_(str.
data()), e_(b_ + str.
size()) {}
227 template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
229 if (
UNLIKELY(startFrom > str.size())) {
230 throw_exception<std::out_of_range>(
"index out of range");
232 b_ = str.data() + startFrom;
233 e_ = str.data() + str.size();
236 template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
239 std::string::size_type startFrom,
240 std::string::size_type
size) {
241 if (
UNLIKELY(startFrom > str.size())) {
242 throw_exception<std::out_of_range>(
"index out of range");
244 b_ = str.data() + startFrom;
245 if (str.size() - startFrom <
size) {
246 e_ = str.data() + str.size();
253 :
Range(other.subpiece(first, length)) {}
257 class =
typename std::enable_if<
260 Iter(std::declval<Container const&>().
data()),
262 std::declval<Container const&>().
data() +
263 std::declval<Container const&>().
size()))>
264 constexpr
Range(Container
const& container)
265 : b_(container.
data()), e_(b_ + container.
size()) {}
269 class =
typename std::enable_if<
272 Iter(std::declval<Container const&>().
data()),
274 std::declval<Container const&>().
data() +
275 std::declval<Container const&>().
size()))>
276 Range(Container
const& container,
typename Container::size_type startFrom) {
277 auto const cdata = container.data();
278 auto const csize = container.size();
280 throw_exception<std::out_of_range>(
"index out of range");
282 b_ = cdata + startFrom;
288 class =
typename std::enable_if<
291 Iter(std::declval<Container const&>().
data()),
293 std::declval<Container const&>().
data() +
294 std::declval<Container const&>().
size()))>
296 Container
const& container,
297 typename Container::size_type startFrom,
298 typename Container::size_type
size) {
299 auto const cdata = container.data();
300 auto const csize = container.size();
302 throw_exception<std::out_of_range>(
"index out of range");
304 b_ = cdata + startFrom;
305 if (csize - startFrom < size) {
318 typename std::enable_if<
324 : b_(reinterpret_cast<
const unsigned char*>(other.
begin())),
325 e_(reinterpret_cast<
const unsigned char*>(other.
end())) {}
329 typename std::enable_if<
334 : b_(reinterpret_cast<unsigned char*>(other.
begin())),
335 e_(reinterpret_cast<unsigned char*>(other.
end())) {}
339 typename std::enable_if<
345 : b_(reinterpret_cast<
const char*>(other.
begin())),
346 e_(reinterpret_cast<
const char*>(other.
end())) {}
350 typename std::enable_if<
355 : b_(reinterpret_cast<char*>(other.
begin())),
356 e_(reinterpret_cast<char*>(other.
end())) {}
362 typename std::enable_if<
367 : b_(other.
begin()), e_(other.
end()) {}
373 typename std::enable_if<
379 : b_(other.
begin()), e_(other.
end()) {}
391 typename =
typename std::enable_if<
393 constexpr
explicit Range(
const std::array<T, N>& array)
394 : b_{array.empty() ?
nullptr : &array.at(0)},
395 e_{array.empty() ?
nullptr : &array.at(0) + N} {}
401 constexpr
explicit Range(std::array<T, N>& array)
402 : b_{array.empty() ?
nullptr : &array.at(0)},
403 e_{array.empty() ?
nullptr : &array.at(0) + N} {}
408 template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
428 reset(str.data(), str.size());
431 constexpr size_type
size()
const {
438 return size_type(e_ - b_);
441 return size_type(std::distance(b_, e_));
476 const value_type&
back()
const {
498 #if FOLLY_HAS_STRING_VIEW 499 using StringViewType =
500 std::basic_string_view<std::remove_const_t<value_type>>;
502 template <
typename Target>
504 std::is_constructible<StringViewType, Iter const&, size_type>,
505 std::is_constructible<Target, StringViewType>>;
507 template <
typename Target>
526 std::is_nothrow_constructible<Tgt,
Iter const&, size_type>::
value) {
527 return Tgt(b_, walk_size());
541 #if FOLLY_HAS_STRING_VIEW 547 std::is_same<Tgt, StringViewType>,
548 std::is_constructible<StringViewType, Iter const&, size_type>>
:: 551 constexpr
operator Tgt()
const noexcept(
553 return Tgt(b_, walk_size());
570 template <
typename Tgt,
typename...
Args>
571 constexpr std::enable_if_t<
575 std::is_nothrow_constructible<Tgt,
Iter const&, size_type,
Args&&...>::
577 return Tgt(b_, walk_size(), static_cast<Args&&>(args)...);
579 template <
typename Tgt,
typename...
Args>
580 constexpr std::enable_if_t<
581 !std::is_constructible<Tgt, Iter const&, size_type>::value &&
587 return Tgt(b_, e_, static_cast<Args&&>(args)...);
592 return to<std::string>();
595 return to<std::string>();
599 return const_range_type(*
this);
602 int compare(
const const_range_type& o)
const {
603 const size_type tsize = this->
size();
604 const size_type osize = o.size();
605 const size_type msize =
std::min(tsize, osize);
606 int r = traits_type::compare(
data(), o.data(), msize);
607 if (r == 0 && tsize != osize) {
611 r = (
static_cast<int>((osize - tsize) >> (CHAR_BIT *
sizeof(
size_t) - 1))
628 value_type&
at(
size_t i) {
630 throw_exception<std::out_of_range>(
"index out of range");
635 const value_type&
at(
size_t i)
const {
637 throw_exception<std::out_of_range>(
"index out of range");
661 "Replace with folly::Hash if the hash is not serialized")]]
uint32_t 666 for (
size_t ix = 0; ix <
size(); ix++) {
667 hash = ((hash << 5) + hash) + b_[ix];
674 throw_exception<std::out_of_range>(
"index out of range");
681 throw_exception<std::out_of_range>(
"index out of range");
688 throw_exception<std::out_of_range>(
"index out of range");
706 assert(first <=
size());
721 size_type
find(const_range_type str)
const {
722 return qfind(castToConst(), str);
725 size_type
find(const_range_type str,
size_t pos)
const {
727 return std::string::npos;
729 size_t ret =
qfind(castToConst().subpiece(pos), str);
730 return ret == npos ? ret : ret + pos;
735 return std::string::npos;
737 auto forFinding = castToConst();
739 pos ? forFinding.subpiece(pos) : forFinding, const_range_type(s, n));
740 return ret == npos ? ret : ret + pos;
745 return qfind(castToConst(), const_range_type(s));
751 return std::string::npos;
753 size_type ret =
qfind(castToConst().subpiece(pos), const_range_type(s));
754 return ret == npos ? ret : ret + pos;
757 size_type
find(value_type
c)
const {
758 return qfind(castToConst(), c);
765 size_type
find(value_type
c,
size_t pos)
const {
767 return std::string::npos;
769 size_type ret =
qfind(castToConst().subpiece(pos), c);
770 return ret == npos ? ret : ret + pos;
779 return std::string::npos;
781 size_type ret =
qfind_first_of(castToConst().subpiece(pos), needles);
782 return ret == npos ? ret : ret + pos;
787 return find_first_of(const_range_type(needles));
792 return find_first_of(const_range_type(needles), pos);
796 return find_first_of(const_range_type(needles, n), pos);
812 bool contains(
const const_range_type& other)
const {
813 return find(other) != std::string::npos;
817 return find(other) != std::string::npos;
829 return size() >= other.size() &&
830 castToConst().subpiece(0, other.size()) == other;
833 return !
empty() && front() ==
c;
836 template <
class Comp>
837 bool startsWith(
const const_range_type& other, Comp&& eq)
const {
838 if (
size() < other.size()) {
841 auto const trunc = subpiece(0, other.size());
843 trunc.begin(), trunc.end(), other.begin(), std::forward<Comp>(
eq));
849 bool endsWith(
const const_range_type& other)
const {
850 return size() >= other.size() &&
851 castToConst().subpiece(
size() - other.size()) == other;
854 return !
empty() && back() ==
c;
857 template <
class Comp>
858 bool endsWith(
const const_range_type& other, Comp&& eq)
const {
859 if (
size() < other.size()) {
862 auto const trunc = subpiece(
size() - other.size());
864 trunc.begin(), trunc.end(), other.begin(), std::forward<Comp>(
eq));
867 template <
class Comp>
868 bool equals(
const const_range_type& other, Comp&& eq)
const {
869 return size() == other.size() &&
870 std::equal(
begin(),
end(), other.begin(), std::forward<Comp>(
eq));
882 }
else if (e == e_) {
885 throw_exception<std::out_of_range>(
"index out of range");
894 return startsWith(prefix) && (b_ += prefix.size(),
true);
897 return startsWith(prefix) && (++b_,
true);
905 return endsWith(suffix) && (e_ -= suffix.size(),
true);
908 return endsWith(suffix) && (--e_,
true);
925 bool replaceAt(
size_t pos, const_range_type replacement) {
926 if (
size() < pos + replacement.size()) {
950 if (source.size() != dest.size()) {
951 throw_exception<std::invalid_argument>(
952 "replacement must have the same size as source");
960 size_t num_replaced = 0;
961 size_type found = std::string::npos;
962 while ((found = find(source, pos)) != std::string::npos) {
963 replaceAt(found, dest);
964 pos += source.size();
1002 auto i = std::find(b_, e_, delimiter);
1011 auto i = find(delimiter);
1012 Range result(b_,
i == std::string::npos ?
size() :
i);
1014 b_ = result.
end() == e_
1018 typename std::iterator_traits<Iter>::difference_type(
1086 template <
typename TProcess,
typename...
Args>
1088 -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...)) {
1089 return process(split_step(delimiter), std::forward<Args>(args)...);
1092 template <
typename TProcess,
typename...
Args>
1094 -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...)) {
1095 return process(split_step(delimiter), std::forward<Args>(args)...);
1102 template <
class Iter>
1105 template <
class Iter>
1113 template <
class Iter>
1122 template <
class Collection>
1124 return Range<decltype(
v.data())>(
v.data(),
v.data() +
v.size());
1126 template <
class Collection>
1128 return Range<decltype(
v.data())>(
v.data(),
v.data() +
v.size());
1130 template <
class Collection>
1132 return Range<decltype(
v.data())>(
v.data(),
v.data() +
v.size());
1135 template <
class T,
size_t n>
1139 template <
class T,
size_t n>
1143 template <
class T,
size_t n>
1148 template <
class T,
size_t n>
1152 template <
class T,
size_t n>
1156 template <
class T,
size_t n>
1168 std::basic_ostream<C>& os,
1170 using StreamSize = decltype(os.width());
1171 os.write(piece.
start(),
static_cast<StreamSize
>(piece.
size()));
1176 std::basic_ostream<C>& operator<<(std::basic_ostream<C>& os,
Range<C*> piece) {
1177 using StreamSize = decltype(os.width());
1178 os.write(piece.start(),
static_cast<StreamSize
>(piece.size()));
1186 template <
class Iter>
1191 template <
class Iter>
1196 template <
class Iter>
1198 return lhs.compare(rhs) < 0;
1201 template <
class Iter>
1203 return lhs.compare(rhs) <= 0;
1206 template <
class Iter>
1211 template <
class Iter>
1222 template <
class A,
class B>
1237 template <
class T,
class U>
1246 template <
class T,
class U>
1255 template <
class T,
class U>
1264 template <
class T,
class U>
1273 template <
class T,
class U>
1282 template <
class T,
class U>
1291 template <
class Iter,
class Comp>
1295 auto const nsize = needle.
size();
1296 if (haystack.
size() < nsize) {
1297 return std::string::npos;
1302 auto const nsize_1 = nsize - 1;
1303 auto const lastNeedle = needle[nsize_1];
1308 std::string::size_type
skip = 0;
1310 auto i = haystack.
begin();
1311 auto iEnd = haystack.
end() - nsize_1;
1315 while (!eq(
i[nsize_1], lastNeedle)) {
1318 return std::string::npos;
1323 for (
size_t j = 0;;) {
1325 if (!eq(
i[j], needle[j])) {
1330 while (skip <= nsize_1 && !eq(needle[nsize_1 - skip], lastNeedle)) {
1340 return size_t(
i - haystack.
begin());
1344 return std::string::npos;
1350 const StringPiece haystack,
1351 const StringPiece needles) {
1355 return qfind_first_byte_of_fn(haystack, needles);
1360 template <
class Iter,
class Comp>
1365 auto ret = std::find_first_of(
1367 return ret == haystack.
end() ? std::string::npos : ret - haystack.
begin();
1391 return (k >=
'a' && k <=
'z');
1395 template <
class Iter>
1400 return pos == haystack.
end() ? std::string::npos : pos - haystack.
data();
1403 template <
class Iter>
1407 for (
auto i = haystack.
size();
i-- > 0;) {
1408 if (haystack[
i] == needle) {
1412 return std::string::npos;
1419 if (haystack.
empty()) {
1420 return std::string::npos;
1422 auto pos =
static_cast<const char*
>(
1424 return pos ==
nullptr ? std::string::npos : pos - haystack.
data();
1430 if (haystack.
empty()) {
1431 return std::string::npos;
1433 auto pos =
static_cast<const char*
>(
1435 return pos ==
nullptr ? std::string::npos : pos - haystack.
data();
1442 const unsigned char& needle) {
1444 if (haystack.
empty()) {
1445 return std::string::npos;
1447 auto pos =
static_cast<const unsigned char*
>(
1449 return pos ==
nullptr ? std::string::npos : pos - haystack.
data();
1455 const unsigned char& needle) {
1457 if (haystack.
empty()) {
1458 return std::string::npos;
1460 auto pos =
static_cast<const unsigned char*
>(
1462 return pos ==
nullptr ? std::string::npos : pos - haystack.
data();
1465 template <
class Iter>
1487 template <
class Key,
class Enable>
1493 std::enable_if_t<std::is_integral<T>::value, void>> {
1503 return hash::SpookyHashV2::Hash64(r.
begin(), r.
size() *
sizeof(
T), 0);
1513 inline namespace literals {
1514 inline namespace string_piece_literals {
1522 char16_t
const* str,
1528 char32_t
const* str,
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator>(const T &lhs, const U &rhs)
const value_type & back() const
size_t qfind_first_byte_of_sse42(const StringPieceLite haystack, const StringPieceLite needles)
bool operator==(const char *c, CStringRange::Sentinel)
#define FOLLY_GNU_DISABLE_WARNING(warningName)
#define FOLLY_POP_WARNING
Range(Container const &container, typename Container::size_type startFrom)
std::char_traits< typename std::remove_const< value_type >::type > traits_type
size_type find_first_of(value_type c) const
bool contains(const value_type &other) const
#define FOLLY_PUSH_WARNING
std::enable_if< !std::is_same< typename std::iterator_traits< Iter >::iterator_category, std::random_access_iterator_tag >::value, typename std::iterator_traits< Iter >::reference >::type value_before(Iter i)
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator<(const T &lhs, const U &rhs)
bool replaceAt(size_t pos, const_range_type replacement)
void * memrchr(const void *s, int c, size_t n)
constexpr Range< T const * > crange(std::array< T, n > const &array)
void uncheckedSubtract(size_type n)
bool operator()(char lhs, char rhs) const
auto split_step(Range delimiter, TProcess &&process, Args &&...args) -> decltype(process(std::declval< Range >(), std::forward< Args >(args)...))
size_type find_first_of(const_range_type needles) const
size_type find(const_range_type str) const
void advance(size_type n)
bool removePrefix(value_type prefix)
constexpr size_type size() const
auto begin(TestAdlIterable &instance)
bool operator()(char lhs, char rhs) const
const value_type & operator[](size_t i) const
size_type find_first_of(Iter needles, size_t pos) const
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator<=(const T &lhs, const U &rhs)
Range< char * > MutableStringPiece
Range split_step(value_type delimiter)
typename std::iterator_traits< unsigned char * >::difference_type difference_type
Range(const Range< OtherIter > &other)
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
size_type find(value_type c) const
std::basic_ostream< C > & operator<<(std::basic_ostream< C > &os, Range< C * > piece)
—— Concurrent Priority Queue Implementation ——
size_type find(const_range_type str, size_t pos) const
detail::Skip skip(size_t count)
requires E e noexcept(noexcept(s.error(std::move(e))))
Range< unsigned char * > MutableByteRange
bool prefix(Cursor &c, uint32_t expected)
size_t operator()(folly::Range< T * > r) const
auto split_step(value_type delimiter, TProcess &&process, Args &&...args) -> decltype(process(std::declval< Range >(), std::forward< Args >(args)...))
bool startsWith(const const_range_type &other, Comp &&eq) const
bool equals(const const_range_type &other, Comp &&eq) const
size_type find_first_of(Iter needles) const
constexpr Iter start() const
size_t qfind(const Range< const unsigned char * > &haystack, const unsigned char &needle)
size_type find(value_type c, size_t pos) const
bool_constant< true > true_type
value_type & operator[](size_t i)
FOLLY_PUSH_WARNING RHS rhs
Range(const Range &other, size_type first, size_type length=npos)
bool removeSuffix(const const_range_type &suffix)
std::iterator_traits< Iter >::reference reference
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
constexpr Iter cend() const
std::conditional< std::is_same< Iter, char * >::value||std::is_same< Iter, unsigned char * >::value, Range< const value_type * >, Range< Iter > >::type const_range_type
constexpr auto size(C const &c) -> decltype(c.size())
constexpr bool empty() const
Range(const std::string &str, std::string::size_type startFrom)
std::false_type IsConstructibleViaStringView
constexpr auto empty(C const &c) -> decltype(c.empty())
def Iter(n, format, sep='')
size_type find(const Iter s, size_t pos) const
size_type rfind(value_type c) const
size_t qfind_first_byte_of(const StringPiece haystack, const StringPiece needles)
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(...)
Range split_step(Range delimiter)
auto end(TestAdlIterable &instance)
size_t qfind_first_byte_of_nosse(const StringPieceLite haystack, const StringPieceLite needles)
constexpr Iter cbegin() const
size_type find(Iter s, size_t pos, size_t n) const
constexpr Iter data() const
void assign(Iter start, Iter end)
size_t rfind(const Range< Iter > &haystack, const typename Range< Iter >::value_type &needle)
size_type find(const Iter s) const
constexpr size_type walk_size() const
Range subpiece(size_type first, size_type length=npos) const
size_t rfind(const Range< const unsigned char * > &haystack, const unsigned char &needle)
size_t qfind_first_of(const Range< const unsigned char * > &haystack, const Range< const unsigned char * > &needles)
constexpr Range(Iter str)
int compare(const const_range_type &o) const
FOLLY_ALWAYS_INLINE bool sse42() const
bool startsWith(value_type c) const
void swap(Range< Iter > &lhs, Range< Iter > &rhs)
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator!=(const T &lhs, const U &rhs)
const_range_type castToConst() const
static const char *const value
bool removePrefix(const const_range_type &prefix)
constexpr std::enable_if_t< std::is_constructible< Tgt, Iter const &, size_type >::value, Tgt > to(Args &&...args) const noexcept(std::is_nothrow_constructible< Tgt, Iter const &, size_type, Args &&... >::value)
Range(Container const &container, typename Container::size_type startFrom, typename Container::size_type size)
constexpr Iter end() const
size_type find_first_of(const_range_type needles, size_t pos) const
bool contains(const const_range_type &other) const
constexpr Range(Iter start, Iter end)
std::remove_reference< typename std::iterator_traits< Iter >::reference >::type value_type
Range(const std::string &str, std::string::size_type startFrom, std::string::size_type size)
constexpr Iter begin() const
Range uncheckedSubpiece(size_type first, size_type length=npos) const
bool startsWith(const const_range_type &other) const
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator>=(const T &lhs, const U &rhs)
std::string toString() const
constexpr size_t constexpr_strlen(const Char *s)
static const size_type npos
constexpr std::enable_if_t< !std::is_constructible< Tgt, Iter const &, size_type >::value &&std::is_constructible< Tgt, Iter const &, Iter const & >::value, Tgt > to(Args &&...args) const noexcept(std::is_nothrow_constructible< Tgt, Iter const &, Iter const &, Args &&... >::value)
void uncheckedAdvance(size_type n)
bool endsWith(value_type c) const
Range< const unsigned char * > ByteRange
bool endsWith(const const_range_type &other, Comp &&eq) const
void subtract(size_type n)
bool_constant< false > false_type
size_type find_first_of(Iter needles, size_t pos, size_t n) const
constexpr Range(Iter start, size_t size)
value_type & at(size_t i)
size_t replaceAll(const_range_type source, const_range_type dest)
void reset(const std::string &str)
bool removeSuffix(value_type suffix)
constexpr Range(Container const &container)
bool endsWith(const const_range_type &other) const
Range< const char * > StringPiece
Range(const std::string &str)
void erase(Iter b, Iter e)
static constexpr uint64_t data[1]
std::true_type folly_is_avalanching
constexpr Range< T const * > range(std::array< T, n > const &array)
constexpr Range(std::array< T, N > &array)
constexpr Range(const std::array< T, N > &array)
void reset(Iter start, size_type size)
constexpr detail::First first
const value_type & at(size_t i) const
constexpr Range(const Range< OtherIter > &other)
size_type find_first_of(value_type c, size_t pos) const
const value_type & front() const