proxygen
Range.h
Go to the documentation of this file.
1 /*
2  * Copyright 2011-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // @author Mark Rabkin (mrabkin@fb.com)
18 // @author Andrei Alexandrescu (andrei.alexandrescu@fb.com)
19 
20 #pragma once
21 
22 #include <folly/Portability.h>
24 #include <folly/lang/Exception.h>
27 
28 #include <algorithm>
29 #include <array>
30 #include <cassert>
31 #include <climits>
32 #include <cstddef>
33 #include <cstring>
34 #include <iosfwd>
35 #include <iterator>
36 #include <stdexcept>
37 #include <string>
38 #include <type_traits>
39 
40 #if FOLLY_HAS_STRING_VIEW
41 #include <string_view> // @manual
42 #endif
43 
44 #include <folly/CpuId.h>
45 #include <folly/Likely.h>
46 #include <folly/Traits.h>
49 
50 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
52 FOLLY_GNU_DISABLE_WARNING("-Wshadow")
53 
54 namespace folly {
55 
59 template <class T>
60 struct IsSomeString : std::false_type {};
61 
62 template <>
64 
65 template <class Iter>
66 class Range;
67 
74 template <
75  class Iter,
76  class Comp = std::equal_to<typename Range<Iter>::value_type>>
77 inline size_t
78 qfind(const Range<Iter>& haystack, const Range<Iter>& needle, Comp eq = Comp());
79 
85 template <class Iter>
86 size_t qfind(
87  const Range<Iter>& haystack,
88  const typename Range<Iter>::value_type& needle);
89 
95 template <class Iter>
96 size_t rfind(
97  const Range<Iter>& haystack,
98  const typename Range<Iter>::value_type& needle);
99 
104 template <class Iter>
105 inline size_t qfind_first_of(
106  const Range<Iter>& haystack,
107  const Range<Iter>& needle);
108 
112 namespace detail {
113 
117 template <class Iter>
118 typename std::enable_if<
119  std::is_same<
120  typename std::iterator_traits<Iter>::iterator_category,
121  std::random_access_iterator_tag>::value,
122  typename std::iterator_traits<Iter>::reference>::type
124  return i[-1];
125 }
126 
130 template <class Iter>
131 typename std::enable_if<
132  !std::is_same<
133  typename std::iterator_traits<Iter>::iterator_category,
134  std::random_access_iterator_tag>::value,
135  typename std::iterator_traits<Iter>::reference>::type
137  return *--i;
138 }
139 
140 /*
141  * Use IsCharPointer<T>::type to enable const char* or char*.
142  * Use IsCharPointer<T>::const_type to enable only const char*.
143  */
144 template <class T>
145 struct IsCharPointer {};
146 
147 template <>
148 struct IsCharPointer<char*> {
149  typedef int type;
150 };
151 
152 template <>
153 struct IsCharPointer<const char*> {
154  typedef int const_type;
155  typedef int type;
156 };
157 
158 } // namespace detail
159 
171 template <class Iter>
172 class Range {
173  public:
174  typedef std::size_t size_type;
175  typedef Iter iterator;
177  typedef typename std::remove_reference<
178  typename std::iterator_traits<Iter>::reference>::type value_type;
179  using difference_type = typename std::iterator_traits<Iter>::difference_type;
180  typedef typename std::iterator_traits<Iter>::reference reference;
181 
188  typedef typename std::conditional<
193 
196 
197  static const size_type npos;
198 
199  // Works for all iterators
200  constexpr Range() : b_(), e_() {}
201 
202  constexpr Range(const Range&) = default;
203  constexpr Range(Range&&) = default;
204 
205  public:
206  // Works for all iterators
207  constexpr Range(Iter start, Iter end) : b_(start), e_(end) {}
208 
209  // Works only for random-access iterators
210  constexpr Range(Iter start, size_t size) : b_(start), e_(start + size) {}
211 
212 #if !__clang__ || __CLANG_PREREQ(3, 7) // Clang 3.6 crashes on this line
213  /* implicit */ Range(std::nullptr_t) = delete;
214 #endif
215 
216  constexpr /* implicit */ Range(Iter str)
217  : b_(str), e_(str + constexpr_strlen(str)) {
218  static_assert(
219  std::is_same<int, typename detail::IsCharPointer<Iter>::type>::value,
220  "This constructor is only available for character ranges");
221  }
222 
223  template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
224  /* implicit */ Range(const std::string& str)
225  : b_(str.data()), e_(b_ + str.size()) {}
226 
227  template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
228  Range(const std::string& str, std::string::size_type startFrom) {
229  if (UNLIKELY(startFrom > str.size())) {
230  throw_exception<std::out_of_range>("index out of range");
231  }
232  b_ = str.data() + startFrom;
233  e_ = str.data() + str.size();
234  }
235 
236  template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
238  const std::string& str,
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");
243  }
244  b_ = str.data() + startFrom;
245  if (str.size() - startFrom < size) {
246  e_ = str.data() + str.size();
247  } else {
248  e_ = b_ + size;
249  }
250  }
251 
252  Range(const Range& other, size_type first, size_type length = npos)
253  : Range(other.subpiece(first, length)) {}
254 
255  template <
256  class Container,
257  class = typename std::enable_if<
259  class = decltype(
260  Iter(std::declval<Container const&>().data()),
261  Iter(
262  std::declval<Container const&>().data() +
263  std::declval<Container const&>().size()))>
264  /* implicit */ constexpr Range(Container const& container)
265  : b_(container.data()), e_(b_ + container.size()) {}
266 
267  template <
268  class Container,
269  class = typename std::enable_if<
271  class = decltype(
272  Iter(std::declval<Container const&>().data()),
273  Iter(
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();
279  if (UNLIKELY(startFrom > csize)) {
280  throw_exception<std::out_of_range>("index out of range");
281  }
282  b_ = cdata + startFrom;
283  e_ = cdata + csize;
284  }
285 
286  template <
287  class Container,
288  class = typename std::enable_if<
290  class = decltype(
291  Iter(std::declval<Container const&>().data()),
292  Iter(
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();
301  if (UNLIKELY(startFrom > csize)) {
302  throw_exception<std::out_of_range>("index out of range");
303  }
304  b_ = cdata + startFrom;
305  if (csize - startFrom < size) {
306  e_ = cdata + csize;
307  } else {
308  e_ = b_ + size;
309  }
310  }
311 
312  // Allow implicit conversion from Range<const char*> (aka StringPiece) to
313  // Range<const unsigned char*> (aka ByteRange), as they're both frequently
314  // used to represent ranges of bytes. Allow explicit conversion in the other
315  // direction.
316  template <
317  class OtherIter,
318  typename std::enable_if<
322  int>::type = 0>
323  /* implicit */ Range(const Range<OtherIter>& other)
324  : b_(reinterpret_cast<const unsigned char*>(other.begin())),
325  e_(reinterpret_cast<const unsigned char*>(other.end())) {}
326 
327  template <
328  class OtherIter,
329  typename std::enable_if<
332  int>::type = 0>
333  /* implicit */ Range(const Range<OtherIter>& other)
334  : b_(reinterpret_cast<unsigned char*>(other.begin())),
335  e_(reinterpret_cast<unsigned char*>(other.end())) {}
336 
337  template <
338  class OtherIter,
339  typename std::enable_if<
343  int>::type = 0>
344  explicit Range(const Range<OtherIter>& other)
345  : b_(reinterpret_cast<const char*>(other.begin())),
346  e_(reinterpret_cast<const char*>(other.end())) {}
347 
348  template <
349  class OtherIter,
350  typename std::enable_if<
353  int>::type = 0>
354  explicit Range(const Range<OtherIter>& other)
355  : b_(reinterpret_cast<char*>(other.begin())),
356  e_(reinterpret_cast<char*>(other.end())) {}
357 
358  // Allow implicit conversion from Range<From> to Range<To> if From is
359  // implicitly convertible to To.
360  template <
361  class OtherIter,
362  typename std::enable_if<
365  int>::type = 0>
366  constexpr /* implicit */ Range(const Range<OtherIter>& other)
367  : b_(other.begin()), e_(other.end()) {}
368 
369  // Allow explicit conversion from Range<From> to Range<To> if From is
370  // explicitly convertible to To.
371  template <
372  class OtherIter,
373  typename std::enable_if<
377  int>::type = 0>
378  constexpr explicit Range(const Range<OtherIter>& other)
379  : b_(other.begin()), e_(other.end()) {}
380 
388  template <
389  class T,
390  size_t N,
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} {}
396  template <
397  class T,
398  size_t N,
399  typename =
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} {}
404 
405  Range& operator=(const Range& rhs) & = default;
406  Range& operator=(Range&& rhs) & = default;
407 
408  template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
409  Range& operator=(std::string&& rhs) = delete;
410 
411  void clear() {
412  b_ = Iter();
413  e_ = Iter();
414  }
415 
417  b_ = start;
418  e_ = end;
419  }
420 
421  void reset(Iter start, size_type size) {
422  b_ = start;
423  e_ = start + size;
424  }
425 
426  // Works only for Range<const char*>
427  void reset(const std::string& str) {
428  reset(str.data(), str.size());
429  }
430 
431  constexpr size_type size() const {
432  // It would be nice to assert(b_ <= e_) here. This can be achieved even
433  // in a C++11 compatible constexpr function:
434  // http://ericniebler.com/2014/09/27/assert-and-constexpr-in-cxx11/
435  // Unfortunately current gcc versions have a bug causing it to reject
436  // this check in a constexpr function:
437  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71448
438  return size_type(e_ - b_);
439  }
440  constexpr size_type walk_size() const {
441  return size_type(std::distance(b_, e_));
442  }
443  constexpr bool empty() const {
444  return b_ == e_;
445  }
446  constexpr Iter data() const {
447  return b_;
448  }
449  constexpr Iter start() const {
450  return b_;
451  }
452  constexpr Iter begin() const {
453  return b_;
454  }
455  constexpr Iter end() const {
456  return e_;
457  }
458  constexpr Iter cbegin() const {
459  return b_;
460  }
461  constexpr Iter cend() const {
462  return e_;
463  }
464  value_type& front() {
465  assert(b_ < e_);
466  return *b_;
467  }
468  value_type& back() {
469  assert(b_ < e_);
470  return detail::value_before(e_);
471  }
472  const value_type& front() const {
473  assert(b_ < e_);
474  return *b_;
475  }
476  const value_type& back() const {
477  assert(b_ < e_);
478  return detail::value_before(e_);
479  }
480 
481  private:
482  // It would be nice to be able to implicit convert to any target type
483  // T for which either an (Iter, Iter) or (Iter, size_type) noexcept
484  // constructor was available, and explicitly convert to any target
485  // type for which those signatures were available but not noexcept.
486  // The problem is that this creates ambiguity when there is also a
487  // T constructor that takes a type U that is implicitly convertible
488  // from Range.
489  //
490  // To avoid ambiguity, we need to avoid having explicit operator T
491  // and implicit operator U coexist when T is constructible from U.
492  // U cannot be deduced when searching for operator T (and C++ won't
493  // perform an existential search for it), so we must limit the implicit
494  // target types to a finite set that we can enumerate.
495  //
496  // At the moment the set of implicit target types consists of just
497  // std::string_view (when it is available).
498 #if FOLLY_HAS_STRING_VIEW
499  using StringViewType =
500  std::basic_string_view<std::remove_const_t<value_type>>;
501 
502  template <typename Target>
504  std::is_constructible<StringViewType, Iter const&, size_type>,
505  std::is_constructible<Target, StringViewType>>;
506 #else
507  template <typename Target>
509 #endif
510 
511  public:
519  template <
520  typename Tgt,
521  std::enable_if_t<
524  int> = 0>
525  constexpr explicit operator Tgt() const noexcept(
526  std::is_nothrow_constructible<Tgt, Iter const&, size_type>::value) {
527  return Tgt(b_, walk_size());
528  }
529  template <
530  typename Tgt,
531  std::enable_if_t<
535  int> = 0>
536  constexpr explicit operator Tgt() const noexcept(
537  std::is_nothrow_constructible<Tgt, Iter const&, Iter const&>::value) {
538  return Tgt(b_, e_);
539  }
540 
541 #if FOLLY_HAS_STRING_VIEW
542  template <
544  typename Tgt,
545  std::enable_if_t<
547  std::is_same<Tgt, StringViewType>,
548  std::is_constructible<StringViewType, Iter const&, size_type>>::
549  value,
550  int> = 0>
551  constexpr operator Tgt() const noexcept(
553  return Tgt(b_, walk_size());
554  }
555 #endif
556 
570  template <typename Tgt, typename... Args>
571  constexpr std::enable_if_t<
573  Tgt>
574  to(Args&&... args) const noexcept(
575  std::is_nothrow_constructible<Tgt, Iter const&, size_type, Args&&...>::
576  value) {
577  return Tgt(b_, walk_size(), static_cast<Args&&>(args)...);
578  }
579  template <typename Tgt, typename... Args>
580  constexpr std::enable_if_t<
581  !std::is_constructible<Tgt, Iter const&, size_type>::value &&
583  Tgt>
584  to(Args&&... args) const noexcept(
585  std::is_nothrow_constructible<Tgt, Iter const&, Iter const&, Args&&...>::
586  value) {
587  return Tgt(b_, e_, static_cast<Args&&>(args)...);
588  }
589 
590  // Works only for Range<const char*> and Range<char*>
591  std::string str() const {
592  return to<std::string>();
593  }
595  return to<std::string>();
596  }
597 
598  const_range_type castToConst() const {
599  return const_range_type(*this);
600  }
601 
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) {
608  // We check the signed bit of the subtraction and bit shift it
609  // to produce either 0 or 2. The subtraction yields the
610  // comparison values of either -1 or 1.
611  r = (static_cast<int>((osize - tsize) >> (CHAR_BIT * sizeof(size_t) - 1))
612  << 1) -
613  1;
614  }
615  return r;
616  }
617 
618  value_type& operator[](size_t i) {
619  assert(i < size());
620  return b_[i];
621  }
622 
623  const value_type& operator[](size_t i) const {
624  assert(i < size());
625  return b_[i];
626  }
627 
628  value_type& at(size_t i) {
629  if (i >= size()) {
630  throw_exception<std::out_of_range>("index out of range");
631  }
632  return b_[i];
633  }
634 
635  const value_type& at(size_t i) const {
636  if (i >= size()) {
637  throw_exception<std::out_of_range>("index out of range");
638  }
639  return b_[i];
640  }
641 
642  // Do NOT use this function, which was left behind for backwards
643  // compatibility. Use SpookyHashV2 instead -- it is faster, and produces
644  // a 64-bit hash, which means dramatically fewer collisions in large maps.
645  // (The above advice does not apply if you are targeting a 32-bit system.)
646  //
647  // Works only for Range<const char*> and Range<char*>
648  //
649  //
650  // ** WANT TO GET RID OF THIS LINT? **
651  //
652  // A) Use a better hash function (*cough*folly::Hash*cough*), but
653  // only if you don't serialize data in a format that depends on
654  // this formula (ie the writer and reader assume this exact hash
655  // function is used).
656  //
657  // B) If you have to use this exact function then make your own hasher
658  // object and copy the body over (see thrift example: D3972362).
659  // https://github.com/facebook/fbthrift/commit/f8ed502e24ab4a32a9d5f266580
660  [[deprecated(
661  "Replace with folly::Hash if the hash is not serialized")]] uint32_t
662  hash() const {
663  // Taken from fbi/nstring.h:
664  // Quick and dirty bernstein hash...fine for short ascii strings
665  uint32_t hash = 5381;
666  for (size_t ix = 0; ix < size(); ix++) {
667  hash = ((hash << 5) + hash) + b_[ix];
668  }
669  return hash;
670  }
671 
672  void advance(size_type n) {
673  if (UNLIKELY(n > size())) {
674  throw_exception<std::out_of_range>("index out of range");
675  }
676  b_ += n;
677  }
678 
679  void subtract(size_type n) {
680  if (UNLIKELY(n > size())) {
681  throw_exception<std::out_of_range>("index out of range");
682  }
683  e_ -= n;
684  }
685 
686  Range subpiece(size_type first, size_type length = npos) const {
687  if (UNLIKELY(first > size())) {
688  throw_exception<std::out_of_range>("index out of range");
689  }
690 
691  return Range(b_ + first, std::min(length, size() - first));
692  }
693 
694  // unchecked versions
695  void uncheckedAdvance(size_type n) {
696  assert(n <= size());
697  b_ += n;
698  }
699 
700  void uncheckedSubtract(size_type n) {
701  assert(n <= size());
702  e_ -= n;
703  }
704 
705  Range uncheckedSubpiece(size_type first, size_type length = npos) const {
706  assert(first <= size());
707  return Range(b_ + first, std::min(length, size() - first));
708  }
709 
710  void pop_front() {
711  assert(b_ < e_);
712  ++b_;
713  }
714 
715  void pop_back() {
716  assert(b_ < e_);
717  --e_;
718  }
719 
720  // string work-alike functions
721  size_type find(const_range_type str) const {
722  return qfind(castToConst(), str);
723  }
724 
725  size_type find(const_range_type str, size_t pos) const {
726  if (pos > size()) {
727  return std::string::npos;
728  }
729  size_t ret = qfind(castToConst().subpiece(pos), str);
730  return ret == npos ? ret : ret + pos;
731  }
732 
733  size_type find(Iter s, size_t pos, size_t n) const {
734  if (pos > size()) {
735  return std::string::npos;
736  }
737  auto forFinding = castToConst();
738  size_t ret = qfind(
739  pos ? forFinding.subpiece(pos) : forFinding, const_range_type(s, n));
740  return ret == npos ? ret : ret + pos;
741  }
742 
743  // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
744  size_type find(const Iter s) const {
745  return qfind(castToConst(), const_range_type(s));
746  }
747 
748  // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
749  size_type find(const Iter s, size_t pos) const {
750  if (pos > size()) {
751  return std::string::npos;
752  }
753  size_type ret = qfind(castToConst().subpiece(pos), const_range_type(s));
754  return ret == npos ? ret : ret + pos;
755  }
756 
757  size_type find(value_type c) const {
758  return qfind(castToConst(), c);
759  }
760 
761  size_type rfind(value_type c) const {
762  return folly::rfind(castToConst(), c);
763  }
764 
765  size_type find(value_type c, size_t pos) const {
766  if (pos > size()) {
767  return std::string::npos;
768  }
769  size_type ret = qfind(castToConst().subpiece(pos), c);
770  return ret == npos ? ret : ret + pos;
771  }
772 
773  size_type find_first_of(const_range_type needles) const {
774  return qfind_first_of(castToConst(), needles);
775  }
776 
777  size_type find_first_of(const_range_type needles, size_t pos) const {
778  if (pos > size()) {
779  return std::string::npos;
780  }
781  size_type ret = qfind_first_of(castToConst().subpiece(pos), needles);
782  return ret == npos ? ret : ret + pos;
783  }
784 
785  // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
786  size_type find_first_of(Iter needles) const {
787  return find_first_of(const_range_type(needles));
788  }
789 
790  // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
791  size_type find_first_of(Iter needles, size_t pos) const {
792  return find_first_of(const_range_type(needles), pos);
793  }
794 
795  size_type find_first_of(Iter needles, size_t pos, size_t n) const {
796  return find_first_of(const_range_type(needles, n), pos);
797  }
798 
799  size_type find_first_of(value_type c) const {
800  return find(c);
801  }
802 
803  size_type find_first_of(value_type c, size_t pos) const {
804  return find(c, pos);
805  }
806 
812  bool contains(const const_range_type& other) const {
813  return find(other) != std::string::npos;
814  }
815 
816  bool contains(const value_type& other) const {
817  return find(other) != std::string::npos;
818  }
819 
820  void swap(Range& rhs) {
821  std::swap(b_, rhs.b_);
822  std::swap(e_, rhs.e_);
823  }
824 
828  bool startsWith(const const_range_type& other) const {
829  return size() >= other.size() &&
830  castToConst().subpiece(0, other.size()) == other;
831  }
832  bool startsWith(value_type c) const {
833  return !empty() && front() == c;
834  }
835 
836  template <class Comp>
837  bool startsWith(const const_range_type& other, Comp&& eq) const {
838  if (size() < other.size()) {
839  return false;
840  }
841  auto const trunc = subpiece(0, other.size());
842  return std::equal(
843  trunc.begin(), trunc.end(), other.begin(), std::forward<Comp>(eq));
844  }
845 
849  bool endsWith(const const_range_type& other) const {
850  return size() >= other.size() &&
851  castToConst().subpiece(size() - other.size()) == other;
852  }
853  bool endsWith(value_type c) const {
854  return !empty() && back() == c;
855  }
856 
857  template <class Comp>
858  bool endsWith(const const_range_type& other, Comp&& eq) const {
859  if (size() < other.size()) {
860  return false;
861  }
862  auto const trunc = subpiece(size() - other.size());
863  return std::equal(
864  trunc.begin(), trunc.end(), other.begin(), std::forward<Comp>(eq));
865  }
866 
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));
871  }
872 
879  void erase(Iter b, Iter e) {
880  if (b == b_) {
881  b_ = e;
882  } else if (e == e_) {
883  e_ = b;
884  } else {
885  throw_exception<std::out_of_range>("index out of range");
886  }
887  }
888 
893  bool removePrefix(const const_range_type& prefix) {
894  return startsWith(prefix) && (b_ += prefix.size(), true);
895  }
896  bool removePrefix(value_type prefix) {
897  return startsWith(prefix) && (++b_, true);
898  }
899 
904  bool removeSuffix(const const_range_type& suffix) {
905  return endsWith(suffix) && (e_ -= suffix.size(), true);
906  }
907  bool removeSuffix(value_type suffix) {
908  return endsWith(suffix) && (--e_, true);
909  }
910 
925  bool replaceAt(size_t pos, const_range_type replacement) {
926  if (size() < pos + replacement.size()) {
927  return false;
928  }
929 
930  std::copy(replacement.begin(), replacement.end(), begin() + pos);
931 
932  return true;
933  }
934 
949  size_t replaceAll(const_range_type source, const_range_type dest) {
950  if (source.size() != dest.size()) {
951  throw_exception<std::invalid_argument>(
952  "replacement must have the same size as source");
953  }
954 
955  if (dest.empty()) {
956  return 0;
957  }
958 
959  size_t pos = 0;
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();
965  ++num_replaced;
966  }
967 
968  return num_replaced;
969  }
970 
1001  Range split_step(value_type delimiter) {
1002  auto i = std::find(b_, e_, delimiter);
1003  Range result(b_, i);
1004 
1005  b_ = i == e_ ? e_ : std::next(i);
1006 
1007  return result;
1008  }
1009 
1010  Range split_step(Range delimiter) {
1011  auto i = find(delimiter);
1012  Range result(b_, i == std::string::npos ? size() : i);
1013 
1014  b_ = result.end() == e_
1015  ? e_
1016  : std::next(
1017  result.end(),
1018  typename std::iterator_traits<Iter>::difference_type(
1019  delimiter.size()));
1020 
1021  return result;
1022  }
1023 
1086  template <typename TProcess, typename... Args>
1087  auto split_step(value_type delimiter, TProcess&& process, Args&&... args)
1088  -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...)) {
1089  return process(split_step(delimiter), std::forward<Args>(args)...);
1090  }
1091 
1092  template <typename TProcess, typename... Args>
1093  auto split_step(Range delimiter, TProcess&& process, Args&&... args)
1094  -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...)) {
1095  return process(split_step(delimiter), std::forward<Args>(args)...);
1096  }
1097 
1098  private:
1099  Iter b_, e_;
1100 };
1101 
1102 template <class Iter>
1103 const typename Range<Iter>::size_type Range<Iter>::npos = std::string::npos;
1104 
1105 template <class Iter>
1106 void swap(Range<Iter>& lhs, Range<Iter>& rhs) {
1107  lhs.swap(rhs);
1108 }
1109 
1113 template <class Iter>
1114 constexpr Range<Iter> range(Iter first, Iter last) {
1115  return Range<Iter>(first, last);
1116 }
1117 
1118 /*
1119  * Creates a range to reference the contents of a contiguous-storage container.
1120  */
1121 // Use pointers for types with '.data()' member
1122 template <class Collection>
1123 constexpr auto range(Collection& v) -> Range<decltype(v.data())> {
1124  return Range<decltype(v.data())>(v.data(), v.data() + v.size());
1125 }
1126 template <class Collection>
1127 constexpr auto range(Collection const& v) -> Range<decltype(v.data())> {
1128  return Range<decltype(v.data())>(v.data(), v.data() + v.size());
1129 }
1130 template <class Collection>
1131 constexpr auto crange(Collection const& v) -> Range<decltype(v.data())> {
1132  return Range<decltype(v.data())>(v.data(), v.data() + v.size());
1133 }
1134 
1135 template <class T, size_t n>
1136 constexpr Range<T*> range(T (&array)[n]) {
1137  return Range<T*>(array, array + n);
1138 }
1139 template <class T, size_t n>
1140 constexpr Range<T const*> range(T const (&array)[n]) {
1141  return Range<T const*>(array, array + n);
1142 }
1143 template <class T, size_t n>
1144 constexpr Range<T const*> crange(T const (&array)[n]) {
1145  return Range<T const*>(array, array + n);
1146 }
1147 
1148 template <class T, size_t n>
1149 constexpr Range<T*> range(std::array<T, n>& array) {
1150  return Range<T*>{array};
1151 }
1152 template <class T, size_t n>
1153 constexpr Range<T const*> range(std::array<T, n> const& array) {
1154  return Range<T const*>{array};
1155 }
1156 template <class T, size_t n>
1157 constexpr Range<T const*> crange(std::array<T, n> const& array) {
1158  return Range<T const*>{array};
1159 }
1160 
1165 
1166 template <class C>
1167 std::basic_ostream<C>& operator<<(
1168  std::basic_ostream<C>& os,
1169  Range<C const*> piece) {
1170  using StreamSize = decltype(os.width());
1171  os.write(piece.start(), static_cast<StreamSize>(piece.size()));
1172  return os;
1173 }
1174 
1175 template <class C>
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()));
1179  return os;
1180 }
1181 
1186 template <class Iter>
1187 inline bool operator==(const Range<Iter>& lhs, const Range<Iter>& rhs) {
1188  return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
1189 }
1190 
1191 template <class Iter>
1192 inline bool operator!=(const Range<Iter>& lhs, const Range<Iter>& rhs) {
1193  return !(operator==(lhs, rhs));
1194 }
1195 
1196 template <class Iter>
1197 inline bool operator<(const Range<Iter>& lhs, const Range<Iter>& rhs) {
1198  return lhs.compare(rhs) < 0;
1199 }
1200 
1201 template <class Iter>
1202 inline bool operator<=(const Range<Iter>& lhs, const Range<Iter>& rhs) {
1203  return lhs.compare(rhs) <= 0;
1204 }
1205 
1206 template <class Iter>
1207 inline bool operator>(const Range<Iter>& lhs, const Range<Iter>& rhs) {
1208  return lhs.compare(rhs) > 0;
1209 }
1210 
1211 template <class Iter>
1212 inline bool operator>=(const Range<Iter>& lhs, const Range<Iter>& rhs) {
1213  return lhs.compare(rhs) >= 0;
1214 }
1215 
1220 namespace detail {
1221 
1222 template <class A, class B>
1224  enum {
1229  };
1230 };
1231 
1232 } // namespace detail
1233 
1237 template <class T, class U>
1239 operator==(const T& lhs, const U& rhs) {
1240  return StringPiece(lhs) == StringPiece(rhs);
1241 }
1242 
1246 template <class T, class U>
1248 operator!=(const T& lhs, const U& rhs) {
1249  return StringPiece(lhs) != StringPiece(rhs);
1250 }
1251 
1255 template <class T, class U>
1257 operator<(const T& lhs, const U& rhs) {
1258  return StringPiece(lhs) < StringPiece(rhs);
1259 }
1260 
1264 template <class T, class U>
1266 operator>(const T& lhs, const U& rhs) {
1267  return StringPiece(lhs) > StringPiece(rhs);
1268 }
1269 
1273 template <class T, class U>
1275 operator<=(const T& lhs, const U& rhs) {
1276  return StringPiece(lhs) <= StringPiece(rhs);
1277 }
1278 
1282 template <class T, class U>
1284 operator>=(const T& lhs, const U& rhs) {
1285  return StringPiece(lhs) >= StringPiece(rhs);
1286 }
1287 
1291 template <class Iter, class Comp>
1292 size_t qfind(const Range<Iter>& haystack, const Range<Iter>& needle, Comp eq) {
1293  // Don't use std::search, use a Boyer-Moore-like trick by comparing
1294  // the last characters first
1295  auto const nsize = needle.size();
1296  if (haystack.size() < nsize) {
1297  return std::string::npos;
1298  }
1299  if (!nsize) {
1300  return 0;
1301  }
1302  auto const nsize_1 = nsize - 1;
1303  auto const lastNeedle = needle[nsize_1];
1304 
1305  // Boyer-Moore skip value for the last char in the needle. Zero is
1306  // not a valid value; skip will be computed the first time it's
1307  // needed.
1308  std::string::size_type skip = 0;
1309 
1310  auto i = haystack.begin();
1311  auto iEnd = haystack.end() - nsize_1;
1312 
1313  while (i < iEnd) {
1314  // Boyer-Moore: match the last element in the needle
1315  while (!eq(i[nsize_1], lastNeedle)) {
1316  if (++i == iEnd) {
1317  // not found
1318  return std::string::npos;
1319  }
1320  }
1321  // Here we know that the last char matches
1322  // Continue in pedestrian mode
1323  for (size_t j = 0;;) {
1324  assert(j < nsize);
1325  if (!eq(i[j], needle[j])) {
1326  // Not found, we can skip
1327  // Compute the skip value lazily
1328  if (skip == 0) {
1329  skip = 1;
1330  while (skip <= nsize_1 && !eq(needle[nsize_1 - skip], lastNeedle)) {
1331  ++skip;
1332  }
1333  }
1334  i += skip;
1335  break;
1336  }
1337  // Check if done searching
1338  if (++j == nsize) {
1339  // Yay
1340  return size_t(i - haystack.begin());
1341  }
1342  }
1343  }
1344  return std::string::npos;
1345 }
1346 
1347 namespace detail {
1348 
1349 inline size_t qfind_first_byte_of(
1350  const StringPiece haystack,
1351  const StringPiece needles) {
1352  static auto const qfind_first_byte_of_fn = folly::CpuId().sse42()
1355  return qfind_first_byte_of_fn(haystack, needles);
1356 }
1357 
1358 } // namespace detail
1359 
1360 template <class Iter, class Comp>
1362  const Range<Iter>& haystack,
1363  const Range<Iter>& needles,
1364  Comp eq) {
1365  auto ret = std::find_first_of(
1366  haystack.begin(), haystack.end(), needles.begin(), needles.end(), eq);
1367  return ret == haystack.end() ? std::string::npos : ret - haystack.begin();
1368 }
1369 
1371  bool operator()(char lhs, char rhs) const {
1372  return lhs == rhs;
1373  }
1374 };
1375 
1382  bool operator()(char lhs, char rhs) const {
1383  char k = lhs ^ rhs;
1384  if (k == 0) {
1385  return true;
1386  }
1387  if (k != 32) {
1388  return false;
1389  }
1390  k = lhs | rhs;
1391  return (k >= 'a' && k <= 'z');
1392  }
1393 };
1394 
1395 template <class Iter>
1396 size_t qfind(
1397  const Range<Iter>& haystack,
1398  const typename Range<Iter>::value_type& needle) {
1399  auto pos = std::find(haystack.begin(), haystack.end(), needle);
1400  return pos == haystack.end() ? std::string::npos : pos - haystack.data();
1401 }
1402 
1403 template <class Iter>
1404 size_t rfind(
1405  const Range<Iter>& haystack,
1406  const typename Range<Iter>::value_type& needle) {
1407  for (auto i = haystack.size(); i-- > 0;) {
1408  if (haystack[i] == needle) {
1409  return i;
1410  }
1411  }
1412  return std::string::npos;
1413 }
1414 
1415 // specialization for StringPiece
1416 template <>
1417 inline size_t qfind(const Range<const char*>& haystack, const char& needle) {
1418  // memchr expects a not-null pointer, early return if the range is empty.
1419  if (haystack.empty()) {
1420  return std::string::npos;
1421  }
1422  auto pos = static_cast<const char*>(
1423  ::memchr(haystack.data(), needle, haystack.size()));
1424  return pos == nullptr ? std::string::npos : pos - haystack.data();
1425 }
1426 
1427 template <>
1428 inline size_t rfind(const Range<const char*>& haystack, const char& needle) {
1429  // memchr expects a not-null pointer, early return if the range is empty.
1430  if (haystack.empty()) {
1431  return std::string::npos;
1432  }
1433  auto pos = static_cast<const char*>(
1434  ::memrchr(haystack.data(), needle, haystack.size()));
1435  return pos == nullptr ? std::string::npos : pos - haystack.data();
1436 }
1437 
1438 // specialization for ByteRange
1439 template <>
1440 inline size_t qfind(
1441  const Range<const unsigned char*>& haystack,
1442  const unsigned char& needle) {
1443  // memchr expects a not-null pointer, early return if the range is empty.
1444  if (haystack.empty()) {
1445  return std::string::npos;
1446  }
1447  auto pos = static_cast<const unsigned char*>(
1448  ::memchr(haystack.data(), needle, haystack.size()));
1449  return pos == nullptr ? std::string::npos : pos - haystack.data();
1450 }
1451 
1452 template <>
1453 inline size_t rfind(
1454  const Range<const unsigned char*>& haystack,
1455  const unsigned char& needle) {
1456  // memchr expects a not-null pointer, early return if the range is empty.
1457  if (haystack.empty()) {
1458  return std::string::npos;
1459  }
1460  auto pos = static_cast<const unsigned char*>(
1461  ::memrchr(haystack.data(), needle, haystack.size()));
1462  return pos == nullptr ? std::string::npos : pos - haystack.data();
1463 }
1464 
1465 template <class Iter>
1466 size_t qfind_first_of(const Range<Iter>& haystack, const Range<Iter>& needles) {
1467  return qfind_first_of(haystack, needles, AsciiCaseSensitive());
1468 }
1469 
1470 // specialization for StringPiece
1471 template <>
1472 inline size_t qfind_first_of(
1473  const Range<const char*>& haystack,
1474  const Range<const char*>& needles) {
1475  return detail::qfind_first_byte_of(haystack, needles);
1476 }
1477 
1478 // specialization for ByteRange
1479 template <>
1480 inline size_t qfind_first_of(
1481  const Range<const unsigned char*>& haystack,
1482  const Range<const unsigned char*>& needles) {
1484  StringPiece(haystack), StringPiece(needles));
1485 }
1486 
1487 template <class Key, class Enable>
1488 struct hasher;
1489 
1490 template <class T>
1491 struct hasher<
1492  folly::Range<T*>,
1493  std::enable_if_t<std::is_integral<T>::value, void>> {
1495 
1496  size_t operator()(folly::Range<T*> r) const {
1497  // std::is_integral<T> is too restrictive, but is sufficient to
1498  // guarantee we can just hash all of the underlying bytes to get a
1499  // suitable hash of T. Something like absl::is_uniquely_represented<T>
1500  // would be better. std::is_pod is not enough, because POD types
1501  // can contain pointers and padding. Also, floating point numbers
1502  // may be == without being bit-identical.
1503  return hash::SpookyHashV2::Hash64(r.begin(), r.size() * sizeof(T), 0);
1504  }
1505 };
1506 
1513 inline namespace literals {
1514 inline namespace string_piece_literals {
1515 constexpr Range<char const*> operator"" _sp(
1516  char const* str,
1517  size_t len) noexcept {
1518  return Range<char const*>(str, len);
1519 }
1520 
1521 constexpr Range<char16_t const*> operator"" _sp(
1522  char16_t const* str,
1523  size_t len) noexcept {
1524  return Range<char16_t const*>(str, len);
1525 }
1526 
1527 constexpr Range<char32_t const*> operator"" _sp(
1528  char32_t const* str,
1529  size_t len) noexcept {
1530  return Range<char32_t const*>(str, len);
1531 }
1532 
1533 constexpr Range<wchar_t const*> operator"" _sp(
1534  wchar_t const* str,
1535  size_t len) noexcept {
1536  return Range<wchar_t const*>(str, len);
1537 }
1538 } // namespace string_piece_literals
1539 } // namespace literals
1540 
1541 } // namespace folly
1542 
1544 
const string needle
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator>(const T &lhs, const U &rhs)
Definition: Range.h:1266
const value_type & back() const
Definition: Range.h:476
size_t qfind_first_byte_of_sse42(const StringPieceLite haystack, const StringPieceLite needles)
Definition: RangeSse42.cpp:31
bool operator==(const char *c, CStringRange::Sentinel)
#define T(v)
Definition: http_parser.c:233
#define FOLLY_GNU_DISABLE_WARNING(warningName)
Definition: Portability.h:180
#define FOLLY_POP_WARNING
Definition: Portability.h:179
void pop_front()
Definition: Range.h:710
std::string str() const
Definition: Range.h:591
Range(Container const &container, typename Container::size_type startFrom)
Definition: Range.h:276
std::char_traits< typename std::remove_const< value_type >::type > traits_type
Definition: Range.h:195
size_type find_first_of(value_type c) const
Definition: Range.h:799
bool contains(const value_type &other) const
Definition: Range.h:816
#define FOLLY_PUSH_WARNING
Definition: Portability.h:178
char b
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)
Definition: Range.h:136
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator<(const T &lhs, const U &rhs)
Definition: Range.h:1257
Iter e_
Definition: Range.h:1099
bool replaceAt(size_t pos, const_range_type replacement)
Definition: Range.h:925
void * memrchr(const void *s, int c, size_t n)
Definition: String.cpp:20
constexpr Range< T const * > crange(std::array< T, n > const &array)
Definition: Range.h:1157
void uncheckedSubtract(size_type n)
Definition: Range.h:700
PskType type
bool operator()(char lhs, char rhs) const
Definition: Range.h:1371
auto split_step(Range delimiter, TProcess &&process, Args &&...args) -> decltype(process(std::declval< Range >(), std::forward< Args >(args)...))
Definition: Range.h:1093
size_type find_first_of(const_range_type needles) const
Definition: Range.h:773
size_type find(const_range_type str) const
Definition: Range.h:721
void advance(size_type n)
Definition: Range.h:672
dest
Definition: upload.py:394
STL namespace.
bool removePrefix(value_type prefix)
Definition: Range.h:896
constexpr size_type size() const
Definition: Range.h:431
auto begin(TestAdlIterable &instance)
Definition: ForeachTest.cpp:56
bool operator()(char lhs, char rhs) const
Definition: Range.h:1382
void swap(Range &rhs)
Definition: Range.h:820
const value_type & operator[](size_t i) const
Definition: Range.h:623
size_type find_first_of(Iter needles, size_t pos) const
Definition: Range.h:791
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator<=(const T &lhs, const U &rhs)
Definition: Range.h:1275
Range< char * > MutableStringPiece
Definition: Range.h:1162
void pop_back()
Definition: Range.h:715
Range split_step(value_type delimiter)
Definition: Range.h:1001
typename std::iterator_traits< unsigned char * >::difference_type difference_type
Definition: Range.h:179
Range(const Range< OtherIter > &other)
Definition: Range.h:323
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
size_type find(value_type c) const
Definition: Range.h:757
std::basic_ostream< C > & operator<<(std::basic_ostream< C > &os, Range< C * > piece)
Definition: Range.h:1176
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
size_type find(const_range_type str, size_t pos) const
Definition: Range.h:725
detail::Skip skip(size_t count)
Definition: Base-inl.h:2598
requires E e noexcept(noexcept(s.error(std::move(e))))
Range< unsigned char * > MutableByteRange
Definition: Range.h:1164
bool prefix(Cursor &c, uint32_t expected)
auto split_step(value_type delimiter, TProcess &&process, Args &&...args) -> decltype(process(std::declval< Range >(), std::forward< Args >(args)...))
Definition: Range.h:1087
bool startsWith(const const_range_type &other, Comp &&eq) const
Definition: Range.h:837
bool equals(const const_range_type &other, Comp &&eq) const
Definition: Range.h:868
size_type find_first_of(Iter needles) const
Definition: Range.h:786
constexpr Iter start() const
Definition: Range.h:449
size_t qfind(const Range< const unsigned char * > &haystack, const unsigned char &needle)
Definition: Range.h:1440
size_type find(value_type c, size_t pos) const
Definition: Range.h:765
bool_constant< true > true_type
Definition: gtest-port.h:2210
value_type & operator[](size_t i)
Definition: Range.h:618
FOLLY_PUSH_WARNING RHS rhs
Definition: Traits.h:649
Range(const Range &other, size_type first, size_type length=npos)
Definition: Range.h:252
bool removeSuffix(const const_range_type &suffix)
Definition: Range.h:904
void clear()
Definition: Range.h:411
std::iterator_traits< Iter >::reference reference
Definition: Range.h:180
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
Definition: Utility.h:72
constexpr Iter cend() const
Definition: Range.h:461
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
Definition: Range.h:192
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
constexpr bool empty() const
Definition: Range.h:443
Range(const std::string &str, std::string::size_type startFrom)
Definition: Range.h:228
std::false_type IsConstructibleViaStringView
Definition: Range.h:508
constexpr auto empty(C const &c) -> decltype(c.empty())
Definition: Access.h:55
def Iter(n, format, sep='')
LogLevel min
Definition: LogLevel.cpp:30
size_type find(const Iter s, size_t pos) const
Definition: Range.h:749
size_type rfind(value_type c) const
Definition: Range.h:761
size_t qfind_first_byte_of(const StringPiece haystack, const StringPiece needles)
Definition: Range.h:1349
const char * suffix
Definition: String.cpp:272
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(...)
Definition: Traits.h:543
typename T::type _t
Definition: Traits.h:171
Range split_step(Range delimiter)
Definition: Range.h:1010
auto end(TestAdlIterable &instance)
Definition: ForeachTest.cpp:62
size_t qfind_first_byte_of_nosse(const StringPieceLite haystack, const StringPieceLite needles)
Definition: RangeCommon.h:92
constexpr Iter cbegin() const
Definition: Range.h:458
size_type find(Iter s, size_t pos, size_t n) const
Definition: Range.h:733
constexpr Iter data() const
Definition: Range.h:446
void assign(Iter start, Iter end)
Definition: Range.h:416
size_t rfind(const Range< Iter > &haystack, const typename Range< Iter >::value_type &needle)
Definition: Range.h:1404
size_type find(const Iter s) const
Definition: Range.h:744
constexpr size_type walk_size() const
Definition: Range.h:440
Range subpiece(size_type first, size_type length=npos) const
Definition: Range.h:686
Iter iterator
Definition: Range.h:175
size_t rfind(const Range< const unsigned char * > &haystack, const unsigned char &needle)
Definition: Range.h:1453
size_t qfind_first_of(const Range< const unsigned char * > &haystack, const Range< const unsigned char * > &needles)
Definition: Range.h:1480
constexpr Range(Iter str)
Definition: Range.h:216
int compare(const const_range_type &o) const
Definition: Range.h:602
FOLLY_ALWAYS_INLINE bool sse42() const
Definition: CpuId.h:133
bool startsWith(value_type c) const
Definition: Range.h:832
void swap(Range< Iter > &lhs, Range< Iter > &rhs)
Definition: Range.h:1106
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator!=(const T &lhs, const U &rhs)
Definition: Range.h:1248
const_range_type castToConst() const
Definition: Range.h:598
static const char *const value
Definition: Conv.cpp:50
bool removePrefix(const const_range_type &prefix)
Definition: Range.h:893
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)
Definition: Range.h:574
auto start
Range(Container const &container, typename Container::size_type startFrom, typename Container::size_type size)
Definition: Range.h:295
constexpr Iter end() const
Definition: Range.h:455
size_type find_first_of(const_range_type needles, size_t pos) const
Definition: Range.h:777
bool contains(const const_range_type &other) const
Definition: Range.h:812
constexpr Range(Iter start, Iter end)
Definition: Range.h:207
std::remove_reference< typename std::iterator_traits< Iter >::reference >::type value_type
Definition: Range.h:178
Range(const std::string &str, std::string::size_type startFrom, std::string::size_type size)
Definition: Range.h:237
Iter const_iterator
Definition: Range.h:176
constexpr Iter begin() const
Definition: Range.h:452
Range uncheckedSubpiece(size_type first, size_type length=npos) const
Definition: Range.h:705
uint32_t hash() const
Definition: Range.h:662
bool startsWith(const const_range_type &other) const
Definition: Range.h:828
_t< std::enable_if< detail::ComparableAsStringPiece< T, U >::value, bool > > operator>=(const T &lhs, const U &rhs)
Definition: Range.h:1284
std::string toString() const
Definition: Range.h:594
constexpr size_t constexpr_strlen(const Char *s)
Definition: Constexpr.h:57
static const size_type npos
Definition: Range.h:197
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)
Definition: Range.h:584
const char * string
Definition: Conv.cpp:212
std::size_t size_type
Definition: Range.h:174
void uncheckedAdvance(size_type n)
Definition: Range.h:695
bool endsWith(value_type c) const
Definition: Range.h:853
value_type & front()
Definition: Range.h:464
Range< const unsigned char * > ByteRange
Definition: Range.h:1163
bool endsWith(const const_range_type &other, Comp &&eq) const
Definition: Range.h:858
static set< string > s
const
Definition: upload.py:398
constexpr Range()
Definition: Range.h:200
void subtract(size_type n)
Definition: Range.h:679
bool_constant< false > false_type
Definition: gtest-port.h:2209
size_type find_first_of(Iter needles, size_t pos, size_t n) const
Definition: Range.h:795
constexpr Range(Iter start, size_t size)
Definition: Range.h:210
value_type & at(size_t i)
Definition: Range.h:628
size_t replaceAll(const_range_type source, const_range_type dest)
Definition: Range.h:949
void reset(const std::string &str)
Definition: Range.h:427
bool removeSuffix(value_type suffix)
Definition: Range.h:907
constexpr Range(Container const &container)
Definition: Range.h:264
bool endsWith(const const_range_type &other) const
Definition: Range.h:849
Range< const char * > StringPiece
#define UNLIKELY(x)
Definition: Likely.h:48
Range(const std::string &str)
Definition: Range.h:224
char c
KeyT k
void erase(Iter b, Iter e)
Definition: Range.h:879
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
constexpr Range< T const * > range(std::array< T, n > const &array)
Definition: Range.h:1153
constexpr Range(std::array< T, N > &array)
Definition: Range.h:401
Iter b_
Definition: Range.h:1099
constexpr Range(const std::array< T, N > &array)
Definition: Range.h:393
void reset(Iter start, size_type size)
Definition: Range.h:421
value_type & back()
Definition: Range.h:468
constexpr detail::First first
Definition: Base-inl.h:2553
const value_type & at(size_t i) const
Definition: Range.h:635
def next(obj)
Definition: ast.py:58
constexpr Range(const Range< OtherIter > &other)
Definition: Range.h:366
size_type find_first_of(value_type c, size_t pos) const
Definition: Range.h:803
const value_type & front() const
Definition: Range.h:472