Make Range.h and FBString.h mutually independent
[folly.git] / folly / Range.h
1 /*
2  * Copyright 2017 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>
23 #include <folly/hash/SpookyHashV2.h>
24 #include <folly/portability/BitsFunctexcept.h>
25 #include <folly/portability/Constexpr.h>
26 #include <folly/portability/String.h>
27
28 #include <boost/operators.hpp>
29 #include <glog/logging.h>
30 #include <algorithm>
31 #include <array>
32 #include <cassert>
33 #include <climits>
34 #include <cstddef>
35 #include <cstring>
36 #include <iosfwd>
37 #include <stdexcept>
38 #include <string>
39 #include <type_traits>
40
41 #include <folly/CpuId.h>
42 #include <folly/Likely.h>
43 #include <folly/Traits.h>
44 #include <folly/detail/RangeCommon.h>
45 #include <folly/detail/RangeSse42.h>
46
47 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
48 FOLLY_PUSH_WARNING
49 FOLLY_GCC_DISABLE_WARNING("-Wshadow")
50
51 namespace folly {
52
53 /**
54  * Ubiquitous helper template for knowing what's a string.
55  */
56 template <class T>
57 struct IsSomeString : std::false_type {};
58
59 template <>
60 struct IsSomeString<std::string> : std::true_type {};
61
62 template <class Iter>
63 class Range;
64
65 /**
66  * Finds the first occurrence of needle in haystack. The algorithm is on
67  * average faster than O(haystack.size() * needle.size()) but not as fast
68  * as Boyer-Moore. On the upside, it does not do any upfront
69  * preprocessing and does not allocate memory.
70  */
71 template <
72     class Iter,
73     class Comp = std::equal_to<typename Range<Iter>::value_type>>
74 inline size_t
75 qfind(const Range<Iter>& haystack, const Range<Iter>& needle, Comp eq = Comp());
76
77 /**
78  * Finds the first occurrence of needle in haystack. The result is the
79  * offset reported to the beginning of haystack, or string::npos if
80  * needle wasn't found.
81  */
82 template <class Iter>
83 size_t qfind(
84     const Range<Iter>& haystack,
85     const typename Range<Iter>::value_type& needle);
86
87 /**
88  * Finds the last occurrence of needle in haystack. The result is the
89  * offset reported to the beginning of haystack, or string::npos if
90  * needle wasn't found.
91  */
92 template <class Iter>
93 size_t rfind(
94     const Range<Iter>& haystack,
95     const typename Range<Iter>::value_type& needle);
96
97 /**
98  * Finds the first occurrence of any element of needle in
99  * haystack. The algorithm is O(haystack.size() * needle.size()).
100  */
101 template <class Iter>
102 inline size_t qfind_first_of(
103     const Range<Iter>& haystack,
104     const Range<Iter>& needle);
105
106 /**
107  * Small internal helper - returns the value just before an iterator.
108  */
109 namespace detail {
110
111 /**
112  * For random-access iterators, the value before is simply i[-1].
113  */
114 template <class Iter>
115 typename std::enable_if<
116     std::is_same<
117         typename std::iterator_traits<Iter>::iterator_category,
118         std::random_access_iterator_tag>::value,
119     typename std::iterator_traits<Iter>::reference>::type
120 value_before(Iter i) {
121   return i[-1];
122 }
123
124 /**
125  * For all other iterators, we need to use the decrement operator.
126  */
127 template <class Iter>
128 typename std::enable_if<
129     !std::is_same<
130         typename std::iterator_traits<Iter>::iterator_category,
131         std::random_access_iterator_tag>::value,
132     typename std::iterator_traits<Iter>::reference>::type
133 value_before(Iter i) {
134   return *--i;
135 }
136
137 /*
138  * Use IsCharPointer<T>::type to enable const char* or char*.
139  * Use IsCharPointer<T>::const_type to enable only const char*.
140  */
141 template <class T>
142 struct IsCharPointer {};
143
144 template <>
145 struct IsCharPointer<char*> {
146   typedef int type;
147 };
148
149 template <>
150 struct IsCharPointer<const char*> {
151   typedef int const_type;
152   typedef int type;
153 };
154
155 } // namespace detail
156
157 /**
158  * Range abstraction keeping a pair of iterators. We couldn't use
159  * boost's similar range abstraction because we need an API identical
160  * with the former StringPiece class, which is used by a lot of other
161  * code. This abstraction does fulfill the needs of boost's
162  * range-oriented algorithms though.
163  *
164  * (Keep memory lifetime in mind when using this class, since it
165  * doesn't manage the data it refers to - just like an iterator
166  * wouldn't.)
167  */
168 template <class Iter>
169 class Range : private boost::totally_ordered<Range<Iter>> {
170  public:
171   typedef std::size_t size_type;
172   typedef Iter iterator;
173   typedef Iter const_iterator;
174   typedef typename std::remove_reference<
175       typename std::iterator_traits<Iter>::reference>::type value_type;
176   using difference_type = typename std::iterator_traits<Iter>::difference_type;
177   typedef typename std::iterator_traits<Iter>::reference reference;
178
179   /**
180    * For MutableStringPiece and MutableByteRange we define StringPiece
181    * and ByteRange as const_range_type (for everything else its just
182    * identity). We do that to enable operations such as find with
183    * args which are const.
184    */
185   typedef typename std::conditional<
186       std::is_same<Iter, char*>::value ||
187           std::is_same<Iter, unsigned char*>::value,
188       Range<const value_type*>,
189       Range<Iter>>::type const_range_type;
190
191   typedef std::char_traits<typename std::remove_const<value_type>::type>
192       traits_type;
193
194   static const size_type npos;
195
196   // Works for all iterators
197   constexpr Range() : b_(), e_() {}
198
199   constexpr Range(const Range&) = default;
200   constexpr Range(Range&&) = default;
201
202  public:
203   // Works for all iterators
204   constexpr Range(Iter start, Iter end) : b_(start), e_(end) {}
205
206   // Works only for random-access iterators
207   constexpr Range(Iter start, size_t size) : b_(start), e_(start + size) {}
208
209 #if !__clang__ || __CLANG_PREREQ(3, 7) // Clang 3.6 crashes on this line
210   /* implicit */ Range(std::nullptr_t) = delete;
211 #endif
212
213   constexpr /* implicit */ Range(Iter str)
214       : b_(str), e_(str + constexpr_strlen(str)) {
215     static_assert(
216         std::is_same<int, typename detail::IsCharPointer<Iter>::type>::value,
217         "This constructor is only available for character ranges");
218   }
219
220   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
221   /* implicit */ Range(const std::string& str)
222       : b_(str.data()), e_(b_ + str.size()) {}
223
224   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
225   Range(const std::string& str, std::string::size_type startFrom) {
226     if (UNLIKELY(startFrom > str.size())) {
227       std::__throw_out_of_range("index out of range");
228     }
229     b_ = str.data() + startFrom;
230     e_ = str.data() + str.size();
231   }
232
233   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
234   Range(
235       const std::string& str,
236       std::string::size_type startFrom,
237       std::string::size_type size) {
238     if (UNLIKELY(startFrom > str.size())) {
239       std::__throw_out_of_range("index out of range");
240     }
241     b_ = str.data() + startFrom;
242     if (str.size() - startFrom < size) {
243       e_ = str.data() + str.size();
244     } else {
245       e_ = b_ + size;
246     }
247   }
248
249   Range(const Range& other, size_type first, size_type length = npos)
250       : Range(other.subpiece(first, length)) {}
251
252   template <
253       class Container,
254       class = typename std::enable_if<
255           std::is_same<Iter, typename Container::const_pointer>::value>::type,
256       class = decltype(
257           Iter(std::declval<Container const&>().data()),
258           Iter(
259               std::declval<Container const&>().data() +
260               std::declval<Container const&>().size()))>
261   /* implicit */ constexpr Range(Container const& container)
262       : b_(container.data()), e_(b_ + container.size()) {}
263
264   template <
265       class Container,
266       class = typename std::enable_if<
267           std::is_same<Iter, typename Container::const_pointer>::value>::type,
268       class = decltype(
269           Iter(std::declval<Container const&>().data()),
270           Iter(
271               std::declval<Container const&>().data() +
272               std::declval<Container const&>().size()))>
273   Range(Container const& container, typename Container::size_type startFrom) {
274     auto const cdata = container.data();
275     auto const csize = container.size();
276     if (UNLIKELY(startFrom > csize)) {
277       std::__throw_out_of_range("index out of range");
278     }
279     b_ = cdata + startFrom;
280     e_ = cdata + csize;
281   }
282
283   template <
284       class Container,
285       class = typename std::enable_if<
286           std::is_same<Iter, typename Container::const_pointer>::value>::type,
287       class = decltype(
288           Iter(std::declval<Container const&>().data()),
289           Iter(
290               std::declval<Container const&>().data() +
291               std::declval<Container const&>().size()))>
292   Range(
293       Container const& container,
294       typename Container::size_type startFrom,
295       typename Container::size_type size) {
296     auto const cdata = container.data();
297     auto const csize = container.size();
298     if (UNLIKELY(startFrom > csize)) {
299       std::__throw_out_of_range("index out of range");
300     }
301     b_ = cdata + startFrom;
302     if (csize - startFrom < size) {
303       e_ = cdata + csize;
304     } else {
305       e_ = b_ + size;
306     }
307   }
308
309   // Allow implicit conversion from Range<const char*> (aka StringPiece) to
310   // Range<const unsigned char*> (aka ByteRange), as they're both frequently
311   // used to represent ranges of bytes.  Allow explicit conversion in the other
312   // direction.
313   template <
314       class OtherIter,
315       typename std::enable_if<
316           (std::is_same<Iter, const unsigned char*>::value &&
317            (std::is_same<OtherIter, const char*>::value ||
318             std::is_same<OtherIter, char*>::value)),
319           int>::type = 0>
320   /* implicit */ Range(const Range<OtherIter>& other)
321       : b_(reinterpret_cast<const unsigned char*>(other.begin())),
322         e_(reinterpret_cast<const unsigned char*>(other.end())) {}
323
324   template <
325       class OtherIter,
326       typename std::enable_if<
327           (std::is_same<Iter, unsigned char*>::value &&
328            std::is_same<OtherIter, char*>::value),
329           int>::type = 0>
330   /* implicit */ Range(const Range<OtherIter>& other)
331       : b_(reinterpret_cast<unsigned char*>(other.begin())),
332         e_(reinterpret_cast<unsigned char*>(other.end())) {}
333
334   template <
335       class OtherIter,
336       typename std::enable_if<
337           (std::is_same<Iter, const char*>::value &&
338            (std::is_same<OtherIter, const unsigned char*>::value ||
339             std::is_same<OtherIter, unsigned char*>::value)),
340           int>::type = 0>
341   explicit Range(const Range<OtherIter>& other)
342       : b_(reinterpret_cast<const char*>(other.begin())),
343         e_(reinterpret_cast<const char*>(other.end())) {}
344
345   template <
346       class OtherIter,
347       typename std::enable_if<
348           (std::is_same<Iter, char*>::value &&
349            std::is_same<OtherIter, unsigned char*>::value),
350           int>::type = 0>
351   explicit Range(const Range<OtherIter>& other)
352       : b_(reinterpret_cast<char*>(other.begin())),
353         e_(reinterpret_cast<char*>(other.end())) {}
354
355   // Allow implicit conversion from Range<From> to Range<To> if From is
356   // implicitly convertible to To.
357   template <
358       class OtherIter,
359       typename std::enable_if<
360           (!std::is_same<Iter, OtherIter>::value &&
361            std::is_convertible<OtherIter, Iter>::value),
362           int>::type = 0>
363   constexpr /* implicit */ Range(const Range<OtherIter>& other)
364       : b_(other.begin()), e_(other.end()) {}
365
366   // Allow explicit conversion from Range<From> to Range<To> if From is
367   // explicitly convertible to To.
368   template <
369       class OtherIter,
370       typename std::enable_if<
371           (!std::is_same<Iter, OtherIter>::value &&
372            !std::is_convertible<OtherIter, Iter>::value &&
373            std::is_constructible<Iter, const OtherIter&>::value),
374           int>::type = 0>
375   constexpr explicit Range(const Range<OtherIter>& other)
376       : b_(other.begin()), e_(other.end()) {}
377
378   /**
379    * Allow explicit construction of Range() from a std::array of a
380    * convertible type.
381    *
382    * For instance, this allows constructing StringPiece from a
383    * std::array<char, N> or a std::array<const char, N>
384    */
385   template <
386       class T,
387       size_t N,
388       typename = typename std::enable_if<
389           std::is_convertible<const T*, Iter>::value>::type>
390   constexpr explicit Range(const std::array<T, N>& array)
391       : b_{array.empty() ? nullptr : &array.at(0)},
392         e_{array.empty() ? nullptr : &array.at(0) + N} {}
393   template <
394       class T,
395       size_t N,
396       typename =
397           typename std::enable_if<std::is_convertible<T*, Iter>::value>::type>
398   constexpr explicit Range(std::array<T, N>& array)
399       : b_{array.empty() ? nullptr : &array.at(0)},
400         e_{array.empty() ? nullptr : &array.at(0) + N} {}
401
402   Range& operator=(const Range& rhs) & = default;
403   Range& operator=(Range&& rhs) & = default;
404
405   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
406   Range& operator=(std::string&& rhs) = delete;
407
408   void clear() {
409     b_ = Iter();
410     e_ = Iter();
411   }
412
413   void assign(Iter start, Iter end) {
414     b_ = start;
415     e_ = end;
416   }
417
418   void reset(Iter start, size_type size) {
419     b_ = start;
420     e_ = start + size;
421   }
422
423   // Works only for Range<const char*>
424   void reset(const std::string& str) {
425     reset(str.data(), str.size());
426   }
427
428   constexpr size_type size() const {
429     // It would be nice to assert(b_ <= e_) here.  This can be achieved even
430     // in a C++11 compatible constexpr function:
431     // http://ericniebler.com/2014/09/27/assert-and-constexpr-in-cxx11/
432     // Unfortunately current gcc versions have a bug causing it to reject
433     // this check in a constexpr function:
434     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71448
435     return size_type(e_ - b_);
436   }
437   constexpr size_type walk_size() const {
438     return size_type(std::distance(b_, e_));
439   }
440   constexpr bool empty() const {
441     return b_ == e_;
442   }
443   constexpr Iter data() const {
444     return b_;
445   }
446   constexpr Iter start() const {
447     return b_;
448   }
449   constexpr Iter begin() const {
450     return b_;
451   }
452   constexpr Iter end() const {
453     return e_;
454   }
455   constexpr Iter cbegin() const {
456     return b_;
457   }
458   constexpr Iter cend() const {
459     return e_;
460   }
461   value_type& front() {
462     assert(b_ < e_);
463     return *b_;
464   }
465   value_type& back() {
466     assert(b_ < e_);
467     return detail::value_before(e_);
468   }
469   const value_type& front() const {
470     assert(b_ < e_);
471     return *b_;
472   }
473   const value_type& back() const {
474     assert(b_ < e_);
475     return detail::value_before(e_);
476   }
477
478   template <typename Tgt>
479   auto to() const
480       -> decltype(Tgt(std::declval<Iter const&>(), std::declval<size_type>())) {
481     return Tgt(b_, size());
482   }
483   // Works only for Range<const char*> and Range<char*>
484   template <typename Tgt = std::string>
485   auto str() const
486       -> decltype(Tgt(std::declval<Iter const&>(), std::declval<size_type>())) {
487     return to<Tgt>();
488   }
489   template <typename Tgt = std::string>
490   auto toString() const
491       -> decltype(Tgt(std::declval<Iter const&>(), std::declval<size_type>())) {
492     return to<Tgt>();
493   }
494
495   const_range_type castToConst() const {
496     return const_range_type(*this);
497   }
498
499   // Works only for Range<const char*> and Range<char*>
500   int compare(const const_range_type& o) const {
501     const size_type tsize = this->size();
502     const size_type osize = o.size();
503     const size_type msize = std::min(tsize, osize);
504     int r = traits_type::compare(data(), o.data(), msize);
505     if (r == 0 && tsize != osize) {
506       // We check the signed bit of the subtraction and bit shift it
507       // to produce either 0 or 2. The subtraction yields the
508       // comparison values of either -1 or 1.
509       r = (static_cast<int>((osize - tsize) >> (CHAR_BIT * sizeof(size_t) - 1))
510            << 1) -
511           1;
512     }
513     return r;
514   }
515
516   value_type& operator[](size_t i) {
517     DCHECK_GT(size(), i);
518     return b_[i];
519   }
520
521   const value_type& operator[](size_t i) const {
522     DCHECK_GT(size(), i);
523     return b_[i];
524   }
525
526   value_type& at(size_t i) {
527     if (i >= size()) {
528       std::__throw_out_of_range("index out of range");
529     }
530     return b_[i];
531   }
532
533   const value_type& at(size_t i) const {
534     if (i >= size()) {
535       std::__throw_out_of_range("index out of range");
536     }
537     return b_[i];
538   }
539
540   // Do NOT use this function, which was left behind for backwards
541   // compatibility.  Use SpookyHashV2 instead -- it is faster, and produces
542   // a 64-bit hash, which means dramatically fewer collisions in large maps.
543   // (The above advice does not apply if you are targeting a 32-bit system.)
544   //
545   // Works only for Range<const char*> and Range<char*>
546   //
547   //
548   //         ** WANT TO GET RID OF THIS LINT? **
549   //
550   // A) Use a better hash function (*cough*folly::Hash*cough*), but
551   //    only if you don't serialize data in a format that depends on
552   //    this formula (ie the writer and reader assume this exact hash
553   //    function is used).
554   //
555   // B) If you have to use this exact function then make your own hasher
556   //    object and copy the body over (see thrift example: D3972362).
557   //    https://github.com/facebook/fbthrift/commit/f8ed502e24ab4a32a9d5f266580
558   FOLLY_DEPRECATED("Replace with folly::Hash if the hash is not serialized")
559   uint32_t hash() const {
560     // Taken from fbi/nstring.h:
561     //    Quick and dirty bernstein hash...fine for short ascii strings
562     uint32_t hash = 5381;
563     for (size_t ix = 0; ix < size(); ix++) {
564       hash = ((hash << 5) + hash) + b_[ix];
565     }
566     return hash;
567   }
568
569   void advance(size_type n) {
570     if (UNLIKELY(n > size())) {
571       std::__throw_out_of_range("index out of range");
572     }
573     b_ += n;
574   }
575
576   void subtract(size_type n) {
577     if (UNLIKELY(n > size())) {
578       std::__throw_out_of_range("index out of range");
579     }
580     e_ -= n;
581   }
582
583   Range subpiece(size_type first, size_type length = npos) const {
584     if (UNLIKELY(first > size())) {
585       std::__throw_out_of_range("index out of range");
586     }
587
588     return Range(b_ + first, std::min(length, size() - first));
589   }
590
591   // unchecked versions
592   void uncheckedAdvance(size_type n) {
593     DCHECK_LE(n, size());
594     b_ += n;
595   }
596
597   void uncheckedSubtract(size_type n) {
598     DCHECK_LE(n, size());
599     e_ -= n;
600   }
601
602   Range uncheckedSubpiece(size_type first, size_type length = npos) const {
603     DCHECK_LE(first, size());
604     return Range(b_ + first, std::min(length, size() - first));
605   }
606
607   void pop_front() {
608     assert(b_ < e_);
609     ++b_;
610   }
611
612   void pop_back() {
613     assert(b_ < e_);
614     --e_;
615   }
616
617   // string work-alike functions
618   size_type find(const_range_type str) const {
619     return qfind(castToConst(), str);
620   }
621
622   size_type find(const_range_type str, size_t pos) const {
623     if (pos > size()) {
624       return std::string::npos;
625     }
626     size_t ret = qfind(castToConst().subpiece(pos), str);
627     return ret == npos ? ret : ret + pos;
628   }
629
630   size_type find(Iter s, size_t pos, size_t n) const {
631     if (pos > size()) {
632       return std::string::npos;
633     }
634     auto forFinding = castToConst();
635     size_t ret = qfind(
636         pos ? forFinding.subpiece(pos) : forFinding, const_range_type(s, n));
637     return ret == npos ? ret : ret + pos;
638   }
639
640   // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
641   size_type find(const Iter s) const {
642     return qfind(castToConst(), const_range_type(s));
643   }
644
645   // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
646   size_type find(const Iter s, size_t pos) const {
647     if (pos > size()) {
648       return std::string::npos;
649     }
650     size_type ret = qfind(castToConst().subpiece(pos), const_range_type(s));
651     return ret == npos ? ret : ret + pos;
652   }
653
654   size_type find(value_type c) const {
655     return qfind(castToConst(), c);
656   }
657
658   size_type rfind(value_type c) const {
659     return folly::rfind(castToConst(), c);
660   }
661
662   size_type find(value_type c, size_t pos) const {
663     if (pos > size()) {
664       return std::string::npos;
665     }
666     size_type ret = qfind(castToConst().subpiece(pos), c);
667     return ret == npos ? ret : ret + pos;
668   }
669
670   size_type find_first_of(const_range_type needles) const {
671     return qfind_first_of(castToConst(), needles);
672   }
673
674   size_type find_first_of(const_range_type needles, size_t pos) const {
675     if (pos > size()) {
676       return std::string::npos;
677     }
678     size_type ret = qfind_first_of(castToConst().subpiece(pos), needles);
679     return ret == npos ? ret : ret + pos;
680   }
681
682   // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
683   size_type find_first_of(Iter needles) const {
684     return find_first_of(const_range_type(needles));
685   }
686
687   // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
688   size_type find_first_of(Iter needles, size_t pos) const {
689     return find_first_of(const_range_type(needles), pos);
690   }
691
692   size_type find_first_of(Iter needles, size_t pos, size_t n) const {
693     return find_first_of(const_range_type(needles, n), pos);
694   }
695
696   size_type find_first_of(value_type c) const {
697     return find(c);
698   }
699
700   size_type find_first_of(value_type c, size_t pos) const {
701     return find(c, pos);
702   }
703
704   /**
705    * Determine whether the range contains the given subrange or item.
706    *
707    * Note: Call find() directly if the index is needed.
708    */
709   bool contains(const const_range_type& other) const {
710     return find(other) != std::string::npos;
711   }
712
713   bool contains(const value_type& other) const {
714     return find(other) != std::string::npos;
715   }
716
717   void swap(Range& rhs) {
718     std::swap(b_, rhs.b_);
719     std::swap(e_, rhs.e_);
720   }
721
722   /**
723    * Does this Range start with another range?
724    */
725   bool startsWith(const const_range_type& other) const {
726     return size() >= other.size() &&
727         castToConst().subpiece(0, other.size()) == other;
728   }
729   bool startsWith(value_type c) const {
730     return !empty() && front() == c;
731   }
732
733   template <class Comp>
734   bool startsWith(const const_range_type& other, Comp&& eq) const {
735     if (size() < other.size()) {
736       return false;
737     }
738     auto const trunc = subpiece(0, other.size());
739     return std::equal(
740         trunc.begin(), trunc.end(), other.begin(), std::forward<Comp>(eq));
741   }
742
743   /**
744    * Does this Range end with another range?
745    */
746   bool endsWith(const const_range_type& other) const {
747     return size() >= other.size() &&
748         castToConst().subpiece(size() - other.size()) == other;
749   }
750   bool endsWith(value_type c) const {
751     return !empty() && back() == c;
752   }
753
754   template <class Comp>
755   bool endsWith(const const_range_type& other, Comp&& eq) const {
756     if (size() < other.size()) {
757       return false;
758     }
759     auto const trunc = subpiece(size() - other.size());
760     return std::equal(
761         trunc.begin(), trunc.end(), other.begin(), std::forward<Comp>(eq));
762   }
763
764   template <class Comp>
765   bool equals(const const_range_type& other, Comp&& eq) const {
766     return size() == other.size() &&
767         std::equal(begin(), end(), other.begin(), std::forward<Comp>(eq));
768   }
769
770   /**
771    * Remove the items in [b, e), as long as this subrange is at the beginning
772    * or end of the Range.
773    *
774    * Required for boost::algorithm::trim()
775    */
776   void erase(Iter b, Iter e) {
777     if (b == b_) {
778       b_ = e;
779     } else if (e == e_) {
780       e_ = b;
781     } else {
782       std::__throw_out_of_range("index out of range");
783     }
784   }
785
786   /**
787    * Remove the given prefix and return true if the range starts with the given
788    * prefix; return false otherwise.
789    */
790   bool removePrefix(const const_range_type& prefix) {
791     return startsWith(prefix) && (b_ += prefix.size(), true);
792   }
793   bool removePrefix(value_type prefix) {
794     return startsWith(prefix) && (++b_, true);
795   }
796
797   /**
798    * Remove the given suffix and return true if the range ends with the given
799    * suffix; return false otherwise.
800    */
801   bool removeSuffix(const const_range_type& suffix) {
802     return endsWith(suffix) && (e_ -= suffix.size(), true);
803   }
804   bool removeSuffix(value_type suffix) {
805     return endsWith(suffix) && (--e_, true);
806   }
807
808   /**
809    * Replaces the content of the range, starting at position 'pos', with
810    * contents of 'replacement'. Entire 'replacement' must fit into the
811    * range. Returns false if 'replacements' does not fit. Example use:
812    *
813    * char in[] = "buffer";
814    * auto msp = MutablesStringPiece(input);
815    * EXPECT_TRUE(msp.replaceAt(2, "tt"));
816    * EXPECT_EQ(msp, "butter");
817    *
818    * // not enough space
819    * EXPECT_FALSE(msp.replace(msp.size() - 1, "rr"));
820    * EXPECT_EQ(msp, "butter"); // unchanged
821    */
822   bool replaceAt(size_t pos, const_range_type replacement) {
823     if (size() < pos + replacement.size()) {
824       return false;
825     }
826
827     std::copy(replacement.begin(), replacement.end(), begin() + pos);
828
829     return true;
830   }
831
832   /**
833    * Replaces all occurences of 'source' with 'dest'. Returns number
834    * of replacements made. Source and dest have to have the same
835    * length. Throws if the lengths are different. If 'source' is a
836    * pattern that is overlapping with itself, we perform sequential
837    * replacement: "aaaaaaa".replaceAll("aa", "ba") --> "bababaa"
838    *
839    * Example use:
840    *
841    * char in[] = "buffer";
842    * auto msp = MutablesStringPiece(input);
843    * EXPECT_EQ(msp.replaceAll("ff","tt"), 1);
844    * EXPECT_EQ(msp, "butter");
845    */
846   size_t replaceAll(const_range_type source, const_range_type dest) {
847     if (source.size() != dest.size()) {
848       throw std::invalid_argument(
849           "replacement must have the same size as source");
850     }
851
852     if (dest.empty()) {
853       return 0;
854     }
855
856     size_t pos = 0;
857     size_t num_replaced = 0;
858     size_type found = std::string::npos;
859     while ((found = find(source, pos)) != std::string::npos) {
860       replaceAt(found, dest);
861       pos += source.size();
862       ++num_replaced;
863     }
864
865     return num_replaced;
866   }
867
868   /**
869    * Splits this `Range` `[b, e)` in the position `i` dictated by the next
870    * occurence of `delimiter`.
871    *
872    * Returns a new `Range` `[b, i)` and adjusts this range to start right after
873    * the delimiter's position. This range will be empty if the delimiter is not
874    * found. If called on an empty `Range`, both this and the returned `Range`
875    * will be empty.
876    *
877    * Example:
878    *
879    *  folly::StringPiece s("sample string for split_next");
880    *  auto p = s.split_step(' ');
881    *
882    *  // prints "string for split_next"
883    *  cout << s << endl;
884    *
885    *  // prints "sample"
886    *  cout << p << endl;
887    *
888    * Example 2:
889    *
890    *  void tokenize(StringPiece s, char delimiter) {
891    *    while (!s.empty()) {
892    *      cout << s.split_step(delimiter);
893    *    }
894    *  }
895    *
896    * @author: Marcelo Juchem <marcelo@fb.com>
897    */
898   Range split_step(value_type delimiter) {
899     auto i = std::find(b_, e_, delimiter);
900     Range result(b_, i);
901
902     b_ = i == e_ ? e_ : std::next(i);
903
904     return result;
905   }
906
907   Range split_step(Range delimiter) {
908     auto i = find(delimiter);
909     Range result(b_, i == std::string::npos ? size() : i);
910
911     b_ = result.end() == e_
912         ? e_
913         : std::next(
914               result.end(),
915               typename std::iterator_traits<Iter>::difference_type(
916                   delimiter.size()));
917
918     return result;
919   }
920
921   /**
922    * Convenience method that calls `split_step()` and passes the result to a
923    * functor, returning whatever the functor does. Any additional arguments
924    * `args` passed to this function are perfectly forwarded to the functor.
925    *
926    * Say you have a functor with this signature:
927    *
928    *  Foo fn(Range r) { }
929    *
930    * `split_step()`'s return type will be `Foo`. It works just like:
931    *
932    *  auto result = fn(myRange.split_step(' '));
933    *
934    * A functor returning `void` is also supported.
935    *
936    * Example:
937    *
938    *  void do_some_parsing(folly::StringPiece s) {
939    *    auto version = s.split_step(' ', [&](folly::StringPiece x) {
940    *      if (x.empty()) {
941    *        throw std::invalid_argument("empty string");
942    *      }
943    *      return std::strtoull(x.begin(), x.end(), 16);
944    *    });
945    *
946    *    // ...
947    *  }
948    *
949    *  struct Foo {
950    *    void parse(folly::StringPiece s) {
951    *      s.split_step(' ', parse_field, bar, 10);
952    *      s.split_step('\t', parse_field, baz, 20);
953    *
954    *      auto const kludge = [](folly::StringPiece x, int &out, int def) {
955    *        if (x == "null") {
956    *          out = 0;
957    *        } else {
958    *          parse_field(x, out, def);
959    *        }
960    *      };
961    *
962    *      s.split_step('\t', kludge, gaz);
963    *      s.split_step(' ', kludge, foo);
964    *    }
965    *
966    *  private:
967    *    int bar;
968    *    int baz;
969    *    int gaz;
970    *    int foo;
971    *
972    *    static parse_field(folly::StringPiece s, int &out, int def) {
973    *      try {
974    *        out = folly::to<int>(s);
975    *      } catch (std::exception const &) {
976    *        value = def;
977    *      }
978    *    }
979    *  };
980    *
981    * @author: Marcelo Juchem <marcelo@fb.com>
982    */
983   template <typename TProcess, typename... Args>
984   auto split_step(value_type delimiter, TProcess&& process, Args&&... args)
985       -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...)) {
986     return process(split_step(delimiter), std::forward<Args>(args)...);
987   }
988
989   template <typename TProcess, typename... Args>
990   auto split_step(Range delimiter, TProcess&& process, Args&&... args)
991       -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...)) {
992     return process(split_step(delimiter), std::forward<Args>(args)...);
993   }
994
995  private:
996   Iter b_, e_;
997 };
998
999 template <class Iter>
1000 const typename Range<Iter>::size_type Range<Iter>::npos = std::string::npos;
1001
1002 template <class Iter>
1003 void swap(Range<Iter>& lhs, Range<Iter>& rhs) {
1004   lhs.swap(rhs);
1005 }
1006
1007 /**
1008  * Create a range from two iterators, with type deduction.
1009  */
1010 template <class Iter>
1011 constexpr Range<Iter> range(Iter first, Iter last) {
1012   return Range<Iter>(first, last);
1013 }
1014
1015 /*
1016  * Creates a range to reference the contents of a contiguous-storage container.
1017  */
1018 // Use pointers for types with '.data()' member
1019 template <
1020     class Collection,
1021     class T = typename std::remove_pointer<
1022         decltype(std::declval<Collection>().data())>::type>
1023 constexpr Range<T*> range(Collection&& v) {
1024   return Range<T*>(v.data(), v.data() + v.size());
1025 }
1026
1027 template <class T, size_t n>
1028 constexpr Range<T*> range(T (&array)[n]) {
1029   return Range<T*>(array, array + n);
1030 }
1031
1032 template <class T, size_t n>
1033 constexpr Range<const T*> range(const std::array<T, n>& array) {
1034   return Range<const T*>{array};
1035 }
1036
1037 typedef Range<const char*> StringPiece;
1038 typedef Range<char*> MutableStringPiece;
1039 typedef Range<const unsigned char*> ByteRange;
1040 typedef Range<unsigned char*> MutableByteRange;
1041
1042 template <class C>
1043 std::basic_ostream<C>& operator<<(
1044     std::basic_ostream<C>& os,
1045     Range<C const*> piece) {
1046   using StreamSize = decltype(os.width());
1047   os.write(piece.start(), static_cast<StreamSize>(piece.size()));
1048   return os;
1049 }
1050
1051 template <class C>
1052 std::basic_ostream<C>& operator<<(std::basic_ostream<C>& os, Range<C*> piece) {
1053   using StreamSize = decltype(os.width());
1054   os.write(piece.start(), static_cast<StreamSize>(piece.size()));
1055   return os;
1056 }
1057
1058 /**
1059  * Templated comparison operators
1060  */
1061
1062 template <class Iter>
1063 inline bool operator==(const Range<Iter>& lhs, const Range<Iter>& rhs) {
1064   return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
1065 }
1066
1067 template <class Iter>
1068 inline bool operator<(const Range<Iter>& lhs, const Range<Iter>& rhs) {
1069   return lhs.compare(rhs) < 0;
1070 }
1071
1072 /**
1073  * Specializations of comparison operators for StringPiece
1074  */
1075
1076 namespace detail {
1077
1078 template <class A, class B>
1079 struct ComparableAsStringPiece {
1080   enum {
1081     value = (std::is_convertible<A, StringPiece>::value &&
1082              std::is_same<B, StringPiece>::value) ||
1083         (std::is_convertible<B, StringPiece>::value &&
1084          std::is_same<A, StringPiece>::value)
1085   };
1086 };
1087
1088 } // namespace detail
1089
1090 /**
1091  * operator== through conversion for Range<const char*>
1092  */
1093 template <class T, class U>
1094 _t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>>
1095 operator==(const T& lhs, const U& rhs) {
1096   return StringPiece(lhs) == StringPiece(rhs);
1097 }
1098
1099 /**
1100  * operator< through conversion for Range<const char*>
1101  */
1102 template <class T, class U>
1103 _t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>>
1104 operator<(const T& lhs, const U& rhs) {
1105   return StringPiece(lhs) < StringPiece(rhs);
1106 }
1107
1108 /**
1109  * operator> through conversion for Range<const char*>
1110  */
1111 template <class T, class U>
1112 _t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>>
1113 operator>(const T& lhs, const U& rhs) {
1114   return StringPiece(lhs) > StringPiece(rhs);
1115 }
1116
1117 /**
1118  * operator< through conversion for Range<const char*>
1119  */
1120 template <class T, class U>
1121 _t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>>
1122 operator<=(const T& lhs, const U& rhs) {
1123   return StringPiece(lhs) <= StringPiece(rhs);
1124 }
1125
1126 /**
1127  * operator> through conversion for Range<const char*>
1128  */
1129 template <class T, class U>
1130 _t<std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>>
1131 operator>=(const T& lhs, const U& rhs) {
1132   return StringPiece(lhs) >= StringPiece(rhs);
1133 }
1134
1135 /**
1136  * Finds substrings faster than brute force by borrowing from Boyer-Moore
1137  */
1138 template <class Iter, class Comp>
1139 size_t qfind(const Range<Iter>& haystack, const Range<Iter>& needle, Comp eq) {
1140   // Don't use std::search, use a Boyer-Moore-like trick by comparing
1141   // the last characters first
1142   auto const nsize = needle.size();
1143   if (haystack.size() < nsize) {
1144     return std::string::npos;
1145   }
1146   if (!nsize) {
1147     return 0;
1148   }
1149   auto const nsize_1 = nsize - 1;
1150   auto const lastNeedle = needle[nsize_1];
1151
1152   // Boyer-Moore skip value for the last char in the needle. Zero is
1153   // not a valid value; skip will be computed the first time it's
1154   // needed.
1155   std::string::size_type skip = 0;
1156
1157   auto i = haystack.begin();
1158   auto iEnd = haystack.end() - nsize_1;
1159
1160   while (i < iEnd) {
1161     // Boyer-Moore: match the last element in the needle
1162     while (!eq(i[nsize_1], lastNeedle)) {
1163       if (++i == iEnd) {
1164         // not found
1165         return std::string::npos;
1166       }
1167     }
1168     // Here we know that the last char matches
1169     // Continue in pedestrian mode
1170     for (size_t j = 0;;) {
1171       assert(j < nsize);
1172       if (!eq(i[j], needle[j])) {
1173         // Not found, we can skip
1174         // Compute the skip value lazily
1175         if (skip == 0) {
1176           skip = 1;
1177           while (skip <= nsize_1 && !eq(needle[nsize_1 - skip], lastNeedle)) {
1178             ++skip;
1179           }
1180         }
1181         i += skip;
1182         break;
1183       }
1184       // Check if done searching
1185       if (++j == nsize) {
1186         // Yay
1187         return size_t(i - haystack.begin());
1188       }
1189     }
1190   }
1191   return std::string::npos;
1192 }
1193
1194 namespace detail {
1195
1196 inline size_t qfind_first_byte_of(
1197     const StringPiece haystack,
1198     const StringPiece needles) {
1199   static auto const qfind_first_byte_of_fn = folly::CpuId().sse42()
1200       ? qfind_first_byte_of_sse42
1201       : qfind_first_byte_of_nosse;
1202   return qfind_first_byte_of_fn(haystack, needles);
1203 }
1204
1205 } // namespace detail
1206
1207 template <class Iter, class Comp>
1208 size_t qfind_first_of(
1209     const Range<Iter>& haystack,
1210     const Range<Iter>& needles,
1211     Comp eq) {
1212   auto ret = std::find_first_of(
1213       haystack.begin(), haystack.end(), needles.begin(), needles.end(), eq);
1214   return ret == haystack.end() ? std::string::npos : ret - haystack.begin();
1215 }
1216
1217 struct AsciiCaseSensitive {
1218   bool operator()(char lhs, char rhs) const {
1219     return lhs == rhs;
1220   }
1221 };
1222
1223 /**
1224  * Check if two ascii characters are case insensitive equal.
1225  * The difference between the lower/upper case characters are the 6-th bit.
1226  * We also check they are alpha chars, in case of xor = 32.
1227  */
1228 struct AsciiCaseInsensitive {
1229   bool operator()(char lhs, char rhs) const {
1230     char k = lhs ^ rhs;
1231     if (k == 0) {
1232       return true;
1233     }
1234     if (k != 32) {
1235       return false;
1236     }
1237     k = lhs | rhs;
1238     return (k >= 'a' && k <= 'z');
1239   }
1240 };
1241
1242 template <class Iter>
1243 size_t qfind(
1244     const Range<Iter>& haystack,
1245     const typename Range<Iter>::value_type& needle) {
1246   auto pos = std::find(haystack.begin(), haystack.end(), needle);
1247   return pos == haystack.end() ? std::string::npos : pos - haystack.data();
1248 }
1249
1250 template <class Iter>
1251 size_t rfind(
1252     const Range<Iter>& haystack,
1253     const typename Range<Iter>::value_type& needle) {
1254   for (auto i = haystack.size(); i-- > 0;) {
1255     if (haystack[i] == needle) {
1256       return i;
1257     }
1258   }
1259   return std::string::npos;
1260 }
1261
1262 // specialization for StringPiece
1263 template <>
1264 inline size_t qfind(const Range<const char*>& haystack, const char& needle) {
1265   // memchr expects a not-null pointer, early return if the range is empty.
1266   if (haystack.empty()) {
1267     return std::string::npos;
1268   }
1269   auto pos = static_cast<const char*>(
1270       ::memchr(haystack.data(), needle, haystack.size()));
1271   return pos == nullptr ? std::string::npos : pos - haystack.data();
1272 }
1273
1274 template <>
1275 inline size_t rfind(const Range<const char*>& haystack, const char& needle) {
1276   // memchr expects a not-null pointer, early return if the range is empty.
1277   if (haystack.empty()) {
1278     return std::string::npos;
1279   }
1280   auto pos = static_cast<const char*>(
1281       ::memrchr(haystack.data(), needle, haystack.size()));
1282   return pos == nullptr ? std::string::npos : pos - haystack.data();
1283 }
1284
1285 // specialization for ByteRange
1286 template <>
1287 inline size_t qfind(
1288     const Range<const unsigned char*>& haystack,
1289     const unsigned char& needle) {
1290   // memchr expects a not-null pointer, early return if the range is empty.
1291   if (haystack.empty()) {
1292     return std::string::npos;
1293   }
1294   auto pos = static_cast<const unsigned char*>(
1295       ::memchr(haystack.data(), needle, haystack.size()));
1296   return pos == nullptr ? std::string::npos : pos - haystack.data();
1297 }
1298
1299 template <>
1300 inline size_t rfind(
1301     const Range<const unsigned char*>& haystack,
1302     const unsigned char& needle) {
1303   // memchr expects a not-null pointer, early return if the range is empty.
1304   if (haystack.empty()) {
1305     return std::string::npos;
1306   }
1307   auto pos = static_cast<const unsigned char*>(
1308       ::memrchr(haystack.data(), needle, haystack.size()));
1309   return pos == nullptr ? std::string::npos : pos - haystack.data();
1310 }
1311
1312 template <class Iter>
1313 size_t qfind_first_of(const Range<Iter>& haystack, const Range<Iter>& needles) {
1314   return qfind_first_of(haystack, needles, AsciiCaseSensitive());
1315 }
1316
1317 // specialization for StringPiece
1318 template <>
1319 inline size_t qfind_first_of(
1320     const Range<const char*>& haystack,
1321     const Range<const char*>& needles) {
1322   return detail::qfind_first_byte_of(haystack, needles);
1323 }
1324
1325 // specialization for ByteRange
1326 template <>
1327 inline size_t qfind_first_of(
1328     const Range<const unsigned char*>& haystack,
1329     const Range<const unsigned char*>& needles) {
1330   return detail::qfind_first_byte_of(
1331       StringPiece(haystack), StringPiece(needles));
1332 }
1333
1334 template <class Key, class Enable>
1335 struct hasher;
1336
1337 template <class T>
1338 struct hasher<
1339     folly::Range<T*>,
1340     typename std::enable_if<std::is_pod<T>::value, void>::type> {
1341   size_t operator()(folly::Range<T*> r) const {
1342     return hash::SpookyHashV2::Hash64(r.begin(), r.size() * sizeof(T), 0);
1343   }
1344 };
1345
1346 /**
1347  * _sp is a user-defined literal suffix to make an appropriate Range
1348  * specialization from a literal string.
1349  *
1350  * Modeled after C++17's `sv` suffix.
1351  */
1352 inline namespace literals {
1353 inline namespace string_piece_literals {
1354 constexpr Range<char const*> operator"" _sp(
1355     char const* str,
1356     size_t len) noexcept {
1357   return Range<char const*>(str, len);
1358 }
1359
1360 constexpr Range<char16_t const*> operator"" _sp(
1361     char16_t const* str,
1362     size_t len) noexcept {
1363   return Range<char16_t const*>(str, len);
1364 }
1365
1366 constexpr Range<char32_t const*> operator"" _sp(
1367     char32_t const* str,
1368     size_t len) noexcept {
1369   return Range<char32_t const*>(str, len);
1370 }
1371
1372 constexpr Range<wchar_t const*> operator"" _sp(
1373     wchar_t const* str,
1374     size_t len) noexcept {
1375   return Range<wchar_t const*>(str, len);
1376 }
1377 } // inline namespace string_piece_literals
1378 } // inline namespace literals
1379
1380 } // namespace folly
1381
1382 FOLLY_POP_WARNING
1383
1384 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(folly::Range);