Remove unnecessary constraint from Range subpiece constructor
[folly.git] / folly / Range.h
1 /*
2  * Copyright 2014 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 #ifndef FOLLY_RANGE_H_
21 #define FOLLY_RANGE_H_
22
23 #include <folly/Portability.h>
24 #include <folly/FBString.h>
25 #include <algorithm>
26 #include <boost/operators.hpp>
27 #include <cstring>
28 #include <glog/logging.h>
29 #include <iosfwd>
30 #include <stdexcept>
31 #include <string>
32 #include <type_traits>
33
34 // libc++ doesn't provide this header, nor does msvc
35 #ifdef FOLLY_HAVE_BITS_CXXCONFIG_H
36 // This file appears in two locations: inside fbcode and in the
37 // libstdc++ source code (when embedding fbstring as std::string).
38 // To aid in this schizophrenic use, two macros are defined in
39 // c++config.h:
40 //   _LIBSTDCXX_FBSTRING - Set inside libstdc++.  This is useful to
41 //      gate use inside fbcode v. libstdc++
42 #include <bits/c++config.h>
43 #endif
44
45 #include <folly/CpuId.h>
46 #include <folly/Traits.h>
47 #include <folly/Likely.h>
48
49 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
50 #pragma GCC diagnostic push
51 #pragma GCC diagnostic ignored "-Wshadow"
52
53 namespace folly {
54
55 template <class T> class Range;
56
57 /**
58  * Finds the first occurrence of needle in haystack. The algorithm is on
59  * average faster than O(haystack.size() * needle.size()) but not as fast
60  * as Boyer-Moore. On the upside, it does not do any upfront
61  * preprocessing and does not allocate memory.
62  */
63 template <class T, class Comp = std::equal_to<typename Range<T>::value_type>>
64 inline size_t qfind(const Range<T> & haystack,
65                     const Range<T> & needle,
66                     Comp eq = Comp());
67
68 /**
69  * Finds the first occurrence of needle in haystack. The result is the
70  * offset reported to the beginning of haystack, or string::npos if
71  * needle wasn't found.
72  */
73 template <class T>
74 size_t qfind(const Range<T> & haystack,
75              const typename Range<T>::value_type& needle);
76
77 /**
78  * Finds the last 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 T>
83 size_t rfind(const Range<T> & haystack,
84              const typename Range<T>::value_type& needle);
85
86
87 /**
88  * Finds the first occurrence of any element of needle in
89  * haystack. The algorithm is O(haystack.size() * needle.size()).
90  */
91 template <class T>
92 inline size_t qfind_first_of(const Range<T> & haystack,
93                              const Range<T> & needle);
94
95 /**
96  * Small internal helper - returns the value just before an iterator.
97  */
98 namespace detail {
99
100 /**
101  * For random-access iterators, the value before is simply i[-1].
102  */
103 template <class Iter>
104 typename std::enable_if<
105   std::is_same<typename std::iterator_traits<Iter>::iterator_category,
106                std::random_access_iterator_tag>::value,
107   typename std::iterator_traits<Iter>::reference>::type
108 value_before(Iter i) {
109   return i[-1];
110 }
111
112 /**
113  * For all other iterators, we need to use the decrement operator.
114  */
115 template <class Iter>
116 typename std::enable_if<
117   !std::is_same<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;
122 }
123
124 /*
125  * Use IsCharPointer<T>::type to enable const char* or char*.
126  * Use IsCharPointer<T>::const_type to enable only const char*.
127  */
128 template <class T> struct IsCharPointer {};
129
130 template <>
131 struct IsCharPointer<char*> {
132   typedef int type;
133 };
134
135 template <>
136 struct IsCharPointer<const char*> {
137   typedef int const_type;
138   typedef int type;
139 };
140
141 } // namespace detail
142
143 /**
144  * Range abstraction keeping a pair of iterators. We couldn't use
145  * boost's similar range abstraction because we need an API identical
146  * with the former StringPiece class, which is used by a lot of other
147  * code. This abstraction does fulfill the needs of boost's
148  * range-oriented algorithms though.
149  *
150  * (Keep memory lifetime in mind when using this class, since it
151  * doesn't manage the data it refers to - just like an iterator
152  * wouldn't.)
153  */
154 template <class Iter>
155 class Range : private boost::totally_ordered<Range<Iter> > {
156 public:
157   typedef std::size_t size_type;
158   typedef Iter iterator;
159   typedef Iter const_iterator;
160   typedef typename std::remove_reference<
161     typename std::iterator_traits<Iter>::reference>::type
162   value_type;
163   typedef typename std::iterator_traits<Iter>::reference reference;
164
165   /**
166    * For MutableStringPiece and MutableByteRange we define StringPiece
167    * and ByteRange as const_range_type (for everything else its just
168    * identity). We do that to enable operations such as find with
169    * args which are const.
170    */
171   typedef typename std::conditional<
172     std::is_same<Iter, char*>::value
173       || std::is_same<Iter, unsigned char*>::value,
174     Range<const value_type*>,
175     Range<Iter>>::type const_range_type;
176
177   typedef std::char_traits<typename std::remove_const<value_type>::type>
178     traits_type;
179
180   static const size_type npos;
181
182   // Works for all iterators
183   constexpr Range() : b_(), e_() {
184   }
185
186 public:
187   // Works for all iterators
188   constexpr Range(Iter start, Iter end) : b_(start), e_(end) {
189   }
190
191   // Works only for random-access iterators
192   constexpr Range(Iter start, size_t size)
193       : b_(start), e_(start + size) { }
194
195 #if FOLLY_HAVE_CONSTEXPR_STRLEN
196   template <class T = Iter, typename detail::IsCharPointer<T>::type = 0>
197   constexpr /* implicit */ Range(Iter str)
198       : b_(str), e_(str + strlen(str)) {}
199 #else
200   template <class T = Iter, typename detail::IsCharPointer<T>::type = 0>
201   /* implicit */ Range(Iter str)
202       : b_(str), e_(str + strlen(str)) {}
203 #endif
204   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
205   /* implicit */ Range(const std::string& str)
206       : b_(str.data()), e_(b_ + str.size()) {}
207
208   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
209   Range(const std::string& str, std::string::size_type startFrom) {
210     if (UNLIKELY(startFrom > str.size())) {
211       throw std::out_of_range("index out of range");
212     }
213     b_ = str.data() + startFrom;
214     e_ = str.data() + str.size();
215   }
216
217   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
218   Range(const std::string& str,
219         std::string::size_type startFrom,
220         std::string::size_type size) {
221     if (UNLIKELY(startFrom > str.size())) {
222       throw std::out_of_range("index out of range");
223     }
224     b_ = str.data() + startFrom;
225     if (str.size() - startFrom < size) {
226       e_ = str.data() + str.size();
227     } else {
228       e_ = b_ + size;
229     }
230   }
231
232   Range(const Range& other,
233         size_type first,
234         size_type length = npos)
235       : Range(other.subpiece(first, length))
236     { }
237
238   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
239   /* implicit */ Range(const fbstring& str)
240     : b_(str.data()), e_(b_ + str.size()) { }
241
242   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
243   Range(const fbstring& str, fbstring::size_type startFrom) {
244     if (UNLIKELY(startFrom > str.size())) {
245       throw std::out_of_range("index out of range");
246     }
247     b_ = str.data() + startFrom;
248     e_ = str.data() + str.size();
249   }
250
251   template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
252   Range(const fbstring& str, fbstring::size_type startFrom,
253         fbstring::size_type size) {
254     if (UNLIKELY(startFrom > str.size())) {
255       throw std::out_of_range("index out of range");
256     }
257     b_ = str.data() + startFrom;
258     if (str.size() - startFrom < size) {
259       e_ = str.data() + str.size();
260     } else {
261       e_ = b_ + size;
262     }
263   }
264
265   // Allow implicit conversion from Range<const char*> (aka StringPiece) to
266   // Range<const unsigned char*> (aka ByteRange), as they're both frequently
267   // used to represent ranges of bytes.  Allow explicit conversion in the other
268   // direction.
269   template <class OtherIter, typename std::enable_if<
270       (std::is_same<Iter, const unsigned char*>::value &&
271        (std::is_same<OtherIter, const char*>::value ||
272         std::is_same<OtherIter, char*>::value)), int>::type = 0>
273   /* implicit */ Range(const Range<OtherIter>& other)
274     : b_(reinterpret_cast<const unsigned char*>(other.begin())),
275       e_(reinterpret_cast<const unsigned char*>(other.end())) {
276   }
277
278   template <class OtherIter, typename std::enable_if<
279       (std::is_same<Iter, unsigned char*>::value &&
280        std::is_same<OtherIter, char*>::value), int>::type = 0>
281   /* implicit */ Range(const Range<OtherIter>& other)
282     : b_(reinterpret_cast<unsigned char*>(other.begin())),
283       e_(reinterpret_cast<unsigned char*>(other.end())) {
284   }
285
286   template <class OtherIter, typename std::enable_if<
287       (std::is_same<Iter, const char*>::value &&
288        (std::is_same<OtherIter, const unsigned char*>::value ||
289         std::is_same<OtherIter, unsigned char*>::value)), int>::type = 0>
290   explicit Range(const Range<OtherIter>& other)
291     : b_(reinterpret_cast<const char*>(other.begin())),
292       e_(reinterpret_cast<const char*>(other.end())) {
293   }
294
295   template <class OtherIter, typename std::enable_if<
296       (std::is_same<Iter, char*>::value &&
297        std::is_same<OtherIter, unsigned char*>::value), int>::type = 0>
298   explicit Range(const Range<OtherIter>& other)
299     : b_(reinterpret_cast<char*>(other.begin())),
300       e_(reinterpret_cast<char*>(other.end())) {
301   }
302
303   // Allow implicit conversion from Range<From> to Range<To> if From is
304   // implicitly convertible to To.
305   template <class OtherIter, typename std::enable_if<
306      (!std::is_same<Iter, OtherIter>::value &&
307       std::is_convertible<OtherIter, Iter>::value), int>::type = 0>
308   constexpr /* implicit */ Range(const Range<OtherIter>& other)
309     : b_(other.begin()),
310       e_(other.end()) {
311   }
312
313   // Allow explicit conversion from Range<From> to Range<To> if From is
314   // explicitly convertible to To.
315   template <class OtherIter, typename std::enable_if<
316     (!std::is_same<Iter, OtherIter>::value &&
317      !std::is_convertible<OtherIter, Iter>::value &&
318      std::is_constructible<Iter, const OtherIter&>::value), int>::type = 0>
319   constexpr explicit Range(const Range<OtherIter>& other)
320     : b_(other.begin()),
321       e_(other.end()) {
322   }
323
324   void clear() {
325     b_ = Iter();
326     e_ = Iter();
327   }
328
329   void assign(Iter start, Iter end) {
330     b_ = start;
331     e_ = end;
332   }
333
334   void reset(Iter start, size_type size) {
335     b_ = start;
336     e_ = start + size;
337   }
338
339   // Works only for Range<const char*>
340   void reset(const std::string& str) {
341     reset(str.data(), str.size());
342   }
343
344   size_type size() const {
345     assert(b_ <= e_);
346     return e_ - b_;
347   }
348   size_type walk_size() const {
349     assert(b_ <= e_);
350     return std::distance(b_, e_);
351   }
352   bool empty() const { return b_ == e_; }
353   Iter data() const { return b_; }
354   Iter start() const { return b_; }
355   Iter begin() const { return b_; }
356   Iter end() const { return e_; }
357   Iter cbegin() const { return b_; }
358   Iter cend() const { return e_; }
359   value_type& front() {
360     assert(b_ < e_);
361     return *b_;
362   }
363   value_type& back() {
364     assert(b_ < e_);
365     return detail::value_before(e_);
366   }
367   const value_type& front() const {
368     assert(b_ < e_);
369     return *b_;
370   }
371   const value_type& back() const {
372     assert(b_ < e_);
373     return detail::value_before(e_);
374   }
375   // Works only for Range<const char*> and Range<char*>
376   std::string str() const { return std::string(b_, size()); }
377   std::string toString() const { return str(); }
378   // Works only for Range<const char*> and Range<char*>
379   fbstring fbstr() const { return fbstring(b_, size()); }
380   fbstring toFbstring() const { return fbstr(); }
381
382   const_range_type castToConst() const {
383     return const_range_type(*this);
384   };
385
386   // Works only for Range<const char*> and Range<char*>
387   int compare(const const_range_type& o) const {
388     const size_type tsize = this->size();
389     const size_type osize = o.size();
390     const size_type msize = std::min(tsize, osize);
391     int r = traits_type::compare(data(), o.data(), msize);
392     if (r == 0) r = tsize - osize;
393     return r;
394   }
395
396   value_type& operator[](size_t i) {
397     DCHECK_GT(size(), i);
398     return b_[i];
399   }
400
401   const value_type& operator[](size_t i) const {
402     DCHECK_GT(size(), i);
403     return b_[i];
404   }
405
406   value_type& at(size_t i) {
407     if (i >= size()) throw std::out_of_range("index out of range");
408     return b_[i];
409   }
410
411   const value_type& at(size_t i) const {
412     if (i >= size()) throw std::out_of_range("index out of range");
413     return b_[i];
414   }
415
416   // Works only for Range<const char*> and Range<char*>
417   uint32_t hash() const {
418     // Taken from fbi/nstring.h:
419     //    Quick and dirty bernstein hash...fine for short ascii strings
420     uint32_t hash = 5381;
421     for (size_t ix = 0; ix < size(); ix++) {
422       hash = ((hash << 5) + hash) + b_[ix];
423     }
424     return hash;
425   }
426
427   void advance(size_type n) {
428     if (UNLIKELY(n > size())) {
429       throw std::out_of_range("index out of range");
430     }
431     b_ += n;
432   }
433
434   void subtract(size_type n) {
435     if (UNLIKELY(n > size())) {
436       throw std::out_of_range("index out of range");
437     }
438     e_ -= n;
439   }
440
441   void pop_front() {
442     assert(b_ < e_);
443     ++b_;
444   }
445
446   void pop_back() {
447     assert(b_ < e_);
448     --e_;
449   }
450
451   Range subpiece(size_type first, size_type length = npos) const {
452     if (UNLIKELY(first > size())) {
453       throw std::out_of_range("index out of range");
454     }
455
456     return Range(b_ + first, std::min(length, size() - first));
457   }
458
459   // string work-alike functions
460   size_type find(const_range_type str) const {
461     return qfind(castToConst(), str);
462   }
463
464   size_type find(const_range_type str, size_t pos) const {
465     if (pos > size()) return std::string::npos;
466     size_t ret = qfind(castToConst().subpiece(pos), str);
467     return ret == npos ? ret : ret + pos;
468   }
469
470   size_type find(Iter s, size_t pos, size_t n) const {
471     if (pos > size()) return std::string::npos;
472     auto forFinding = castToConst();
473     size_t ret = qfind(
474         pos ? forFinding.subpiece(pos) : forFinding, const_range_type(s, n));
475     return ret == npos ? ret : ret + pos;
476   }
477
478   // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
479   size_type find(const Iter s) const {
480     return qfind(castToConst(), const_range_type(s));
481   }
482
483   // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
484   size_type find(const Iter s, size_t pos) const {
485     if (pos > size()) return std::string::npos;
486     size_type ret = qfind(castToConst().subpiece(pos), const_range_type(s));
487     return ret == npos ? ret : ret + pos;
488   }
489
490   size_type find(value_type c) const {
491     return qfind(castToConst(), c);
492   }
493
494   size_type rfind(value_type c) const {
495     return folly::rfind(castToConst(), c);
496   }
497
498   size_type find(value_type c, size_t pos) const {
499     if (pos > size()) return std::string::npos;
500     size_type ret = qfind(castToConst().subpiece(pos), c);
501     return ret == npos ? ret : ret + pos;
502   }
503
504   size_type find_first_of(const_range_type needles) const {
505     return qfind_first_of(castToConst(), needles);
506   }
507
508   size_type find_first_of(const_range_type needles, size_t pos) const {
509     if (pos > size()) return std::string::npos;
510     size_type ret = qfind_first_of(castToConst().subpiece(pos), needles);
511     return ret == npos ? ret : ret + pos;
512   }
513
514   // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
515   size_type find_first_of(Iter needles) const {
516     return find_first_of(const_range_type(needles));
517   }
518
519   // Works only for Range<(const) (unsigned) char*> which have Range(Iter) ctor
520   size_type find_first_of(Iter needles, size_t pos) const {
521     return find_first_of(const_range_type(needles), pos);
522   }
523
524   size_type find_first_of(Iter needles, size_t pos, size_t n) const {
525     return find_first_of(const_range_type(needles, n), pos);
526   }
527
528   size_type find_first_of(value_type c) const {
529     return find(c);
530   }
531
532   size_type find_first_of(value_type c, size_t pos) const {
533     return find(c, pos);
534   }
535
536   /**
537    * Determine whether the range contains the given subrange or item.
538    *
539    * Note: Call find() directly if the index is needed.
540    */
541   bool contains(const const_range_type& other) const {
542     return find(other) != std::string::npos;
543   }
544
545   bool contains(const value_type& other) const {
546     return find(other) != std::string::npos;
547   }
548
549   void swap(Range& rhs) {
550     std::swap(b_, rhs.b_);
551     std::swap(e_, rhs.e_);
552   }
553
554   /**
555    * Does this Range start with another range?
556    */
557   bool startsWith(const const_range_type& other) const {
558     return size() >= other.size()
559       && castToConst().subpiece(0, other.size()) == other;
560   }
561   bool startsWith(value_type c) const {
562     return !empty() && front() == c;
563   }
564
565   /**
566    * Does this Range end with another range?
567    */
568   bool endsWith(const const_range_type& other) const {
569     return size() >= other.size()
570       && castToConst().subpiece(size() - other.size()) == other;
571   }
572   bool endsWith(value_type c) const {
573     return !empty() && back() == c;
574   }
575
576   /**
577    * Remove the given prefix and return true if the range starts with the given
578    * prefix; return false otherwise.
579    */
580   bool removePrefix(const const_range_type& prefix) {
581     return startsWith(prefix) && (b_ += prefix.size(), true);
582   }
583   bool removePrefix(value_type prefix) {
584     return startsWith(prefix) && (++b_, true);
585   }
586
587   /**
588    * Remove the given suffix and return true if the range ends with the given
589    * suffix; return false otherwise.
590    */
591   bool removeSuffix(const const_range_type& suffix) {
592     return endsWith(suffix) && (e_ -= suffix.size(), true);
593   }
594   bool removeSuffix(value_type suffix) {
595     return endsWith(suffix) && (--e_, true);
596   }
597
598   /**
599    * Replaces the content of the range, starting at position 'pos', with
600    * contents of 'replacement'. Entire 'replacement' must fit into the
601    * range. Returns false if 'replacements' does not fit. Example use:
602    *
603    * char in[] = "buffer";
604    * auto msp = MutablesStringPiece(input);
605    * EXPECT_TRUE(msp.replaceAt(2, "tt"));
606    * EXPECT_EQ(msp, "butter");
607    *
608    * // not enough space
609    * EXPECT_FALSE(msp.replace(msp.size() - 1, "rr"));
610    * EXPECT_EQ(msp, "butter"); // unchanged
611    */
612   bool replaceAt(size_t pos, const_range_type replacement) {
613     if (size() < pos + replacement.size()) {
614       return false;
615     }
616
617     std::copy(replacement.begin(), replacement.end(), begin() + pos);
618
619     return true;
620   }
621
622   /**
623    * Replaces all occurences of 'source' with 'dest'. Returns number
624    * of replacements made. Source and dest have to have the same
625    * length. Throws if the lengths are different. If 'source' is a
626    * pattern that is overlapping with itself, we perform sequential
627    * replacement: "aaaaaaa".replaceAll("aa", "ba") --> "bababaa"
628    *
629    * Example use:
630    *
631    * char in[] = "buffer";
632    * auto msp = MutablesStringPiece(input);
633    * EXPECT_EQ(msp.replaceAll("ff","tt"), 1);
634    * EXPECT_EQ(msp, "butter");
635    */
636   size_t replaceAll(const_range_type source, const_range_type dest) {
637     if (source.size() != dest.size()) {
638       throw std::invalid_argument(
639           "replacement must have the same size as source");
640     }
641
642     if (dest.empty()) {
643       return 0;
644     }
645
646     size_t pos = 0;
647     size_t num_replaced = 0;
648     size_type found = std::string::npos;
649     while ((found = find(source, pos)) != std::string::npos) {
650       replaceAt(found, dest);
651       pos += source.size();
652       ++num_replaced;
653     }
654
655     return num_replaced;
656   }
657
658   /**
659    * Splits this `Range` `[b, e)` in the position `i` dictated by the next
660    * occurence of `delimiter`.
661    *
662    * Returns a new `Range` `[b, i)` and adjusts this range to start right after
663    * the delimiter's position. This range will be empty if the delimiter is not
664    * found. If called on an empty `Range`, both this and the returned `Range`
665    * will be empty.
666    *
667    * Example:
668    *
669    *  folly::StringPiece s("sample string for split_next");
670    *  auto p = s.split_step(' ');
671    *
672    *  // prints "string for split_next"
673    *  cout << s << endl;
674    *
675    *  // prints "sample"
676    *  cout << p << endl;
677    *
678    * Example 2:
679    *
680    *  void tokenize(StringPiece s, char delimiter) {
681    *    while (!s.empty()) {
682    *      cout << s.split_step(delimiter);
683    *    }
684    *  }
685    *
686    * @author: Marcelo Juchem <marcelo@fb.com>
687    */
688   Range split_step(value_type delimiter) {
689     auto i = std::find(b_, e_, delimiter);
690     Range result(b_, i);
691
692     b_ = i == e_ ? e_ : std::next(i);
693
694     return result;
695   }
696
697   Range split_step(Range delimiter) {
698     auto i = find(delimiter);
699     Range result(b_, i == std::string::npos ? size() : i);
700
701     b_ = result.end() == e_ ? e_ : std::next(result.end(), delimiter.size());
702
703     return result;
704   }
705
706   /**
707    * Convenience method that calls `split_step()` and passes the result to a
708    * functor, returning whatever the functor does. Any additional arguments
709    * `args` passed to this function are perfectly forwarded to the functor.
710    *
711    * Say you have a functor with this signature:
712    *
713    *  Foo fn(Range r) { }
714    *
715    * `split_step()`'s return type will be `Foo`. It works just like:
716    *
717    *  auto result = fn(myRange.split_step(' '));
718    *
719    * A functor returning `void` is also supported.
720    *
721    * Example:
722    *
723    *  void do_some_parsing(folly::StringPiece s) {
724    *    auto version = s.split_step(' ', [&](folly::StringPiece x) {
725    *      if (x.empty()) {
726    *        throw std::invalid_argument("empty string");
727    *      }
728    *      return std::strtoull(x.begin(), x.end(), 16);
729    *    });
730    *
731    *    // ...
732    *  }
733    *
734    *  struct Foo {
735    *    void parse(folly::StringPiece s) {
736    *      s.split_step(' ', parse_field, bar, 10);
737    *      s.split_step('\t', parse_field, baz, 20);
738    *
739    *      auto const kludge = [](folly::StringPiece x, int &out, int def) {
740    *        if (x == "null") {
741    *          out = 0;
742    *        } else {
743    *          parse_field(x, out, def);
744    *        }
745    *      };
746    *
747    *      s.split_step('\t', kludge, gaz);
748    *      s.split_step(' ', kludge, foo);
749    *    }
750    *
751    *  private:
752    *    int bar;
753    *    int baz;
754    *    int gaz;
755    *    int foo;
756    *
757    *    static parse_field(folly::StringPiece s, int &out, int def) {
758    *      try {
759    *        out = folly::to<int>(s);
760    *      } catch (std::exception const &) {
761    *        value = def;
762    *      }
763    *    }
764    *  };
765    *
766    * @author: Marcelo Juchem <marcelo@fb.com>
767    */
768   template <typename TProcess, typename... Args>
769   auto split_step(value_type delimiter, TProcess &&process, Args &&...args)
770     -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...))
771   { return process(split_step(delimiter), std::forward<Args>(args)...); }
772
773   template <typename TProcess, typename... Args>
774   auto split_step(Range delimiter, TProcess &&process, Args &&...args)
775     -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...))
776   { return process(split_step(delimiter), std::forward<Args>(args)...); }
777
778 private:
779   Iter b_, e_;
780 };
781
782 template <class Iter>
783 const typename Range<Iter>::size_type Range<Iter>::npos = std::string::npos;
784
785 template <class T>
786 void swap(Range<T>& lhs, Range<T>& rhs) {
787   lhs.swap(rhs);
788 }
789
790 /**
791  * Create a range from two iterators, with type deduction.
792  */
793 template <class Iter>
794 Range<Iter> range(Iter first, Iter last) {
795   return Range<Iter>(first, last);
796 }
797
798 /*
799  * Creates a range to reference the contents of a contiguous-storage container.
800  */
801 // Use pointers for types with '.data()' member
802 template <class Collection,
803           class T = typename std::remove_pointer<
804               decltype(std::declval<Collection>().data())>::type>
805 Range<T*> range(Collection&& v) {
806   return Range<T*>(v.data(), v.data() + v.size());
807 }
808
809 template <class T, size_t n>
810 Range<T*> range(T (&array)[n]) {
811   return Range<T*>(array, array + n);
812 }
813
814 typedef Range<const char*> StringPiece;
815 typedef Range<char*> MutableStringPiece;
816 typedef Range<const unsigned char*> ByteRange;
817 typedef Range<unsigned char*> MutableByteRange;
818
819 std::ostream& operator<<(std::ostream& os, const StringPiece piece);
820 std::ostream& operator<<(std::ostream& os, const MutableStringPiece piece);
821
822 /**
823  * Templated comparison operators
824  */
825
826 template <class T>
827 inline bool operator==(const Range<T>& lhs, const Range<T>& rhs) {
828   return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
829 }
830
831 template <class T>
832 inline bool operator<(const Range<T>& lhs, const Range<T>& rhs) {
833   return lhs.compare(rhs) < 0;
834 }
835
836 /**
837  * Specializations of comparison operators for StringPiece
838  */
839
840 namespace detail {
841
842 template <class A, class B>
843 struct ComparableAsStringPiece {
844   enum {
845     value =
846     (std::is_convertible<A, StringPiece>::value
847      && std::is_same<B, StringPiece>::value)
848     ||
849     (std::is_convertible<B, StringPiece>::value
850      && std::is_same<A, StringPiece>::value)
851   };
852 };
853
854 } // namespace detail
855
856 /**
857  * operator== through conversion for Range<const char*>
858  */
859 template <class T, class U>
860 typename
861 std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>::type
862 operator==(const T& lhs, const U& rhs) {
863   return StringPiece(lhs) == StringPiece(rhs);
864 }
865
866 /**
867  * operator< through conversion for Range<const char*>
868  */
869 template <class T, class U>
870 typename
871 std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>::type
872 operator<(const T& lhs, const U& rhs) {
873   return StringPiece(lhs) < StringPiece(rhs);
874 }
875
876 /**
877  * operator> through conversion for Range<const char*>
878  */
879 template <class T, class U>
880 typename
881 std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>::type
882 operator>(const T& lhs, const U& rhs) {
883   return StringPiece(lhs) > StringPiece(rhs);
884 }
885
886 /**
887  * operator< through conversion for Range<const char*>
888  */
889 template <class T, class U>
890 typename
891 std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>::type
892 operator<=(const T& lhs, const U& rhs) {
893   return StringPiece(lhs) <= StringPiece(rhs);
894 }
895
896 /**
897  * operator> through conversion for Range<const char*>
898  */
899 template <class T, class U>
900 typename
901 std::enable_if<detail::ComparableAsStringPiece<T, U>::value, bool>::type
902 operator>=(const T& lhs, const U& rhs) {
903   return StringPiece(lhs) >= StringPiece(rhs);
904 }
905
906 struct StringPieceHash {
907   std::size_t operator()(const StringPiece str) const {
908     return static_cast<std::size_t>(str.hash());
909   }
910 };
911
912 /**
913  * Finds substrings faster than brute force by borrowing from Boyer-Moore
914  */
915 template <class T, class Comp>
916 size_t qfind(const Range<T>& haystack,
917              const Range<T>& needle,
918              Comp eq) {
919   // Don't use std::search, use a Boyer-Moore-like trick by comparing
920   // the last characters first
921   auto const nsize = needle.size();
922   if (haystack.size() < nsize) {
923     return std::string::npos;
924   }
925   if (!nsize) return 0;
926   auto const nsize_1 = nsize - 1;
927   auto const lastNeedle = needle[nsize_1];
928
929   // Boyer-Moore skip value for the last char in the needle. Zero is
930   // not a valid value; skip will be computed the first time it's
931   // needed.
932   std::string::size_type skip = 0;
933
934   auto i = haystack.begin();
935   auto iEnd = haystack.end() - nsize_1;
936
937   while (i < iEnd) {
938     // Boyer-Moore: match the last element in the needle
939     while (!eq(i[nsize_1], lastNeedle)) {
940       if (++i == iEnd) {
941         // not found
942         return std::string::npos;
943       }
944     }
945     // Here we know that the last char matches
946     // Continue in pedestrian mode
947     for (size_t j = 0; ; ) {
948       assert(j < nsize);
949       if (!eq(i[j], needle[j])) {
950         // Not found, we can skip
951         // Compute the skip value lazily
952         if (skip == 0) {
953           skip = 1;
954           while (skip <= nsize_1 && !eq(needle[nsize_1 - skip], lastNeedle)) {
955             ++skip;
956           }
957         }
958         i += skip;
959         break;
960       }
961       // Check if done searching
962       if (++j == nsize) {
963         // Yay
964         return i - haystack.begin();
965       }
966     }
967   }
968   return std::string::npos;
969 }
970
971 namespace detail {
972
973 size_t qfind_first_byte_of_nosse(const StringPiece haystack,
974                                  const StringPiece needles);
975
976 #if FOLLY_HAVE_EMMINTRIN_H && __GNUC_PREREQ(4, 6)
977 size_t qfind_first_byte_of_sse42(const StringPiece haystack,
978                                  const StringPiece needles);
979
980 inline size_t qfind_first_byte_of(const StringPiece haystack,
981                                   const StringPiece needles) {
982   static auto const qfind_first_byte_of_fn =
983     folly::CpuId().sse42() ? qfind_first_byte_of_sse42
984                            : qfind_first_byte_of_nosse;
985   return qfind_first_byte_of_fn(haystack, needles);
986 }
987
988 #else
989 inline size_t qfind_first_byte_of(const StringPiece haystack,
990                                   const StringPiece needles) {
991   return qfind_first_byte_of_nosse(haystack, needles);
992 }
993 #endif // FOLLY_HAVE_EMMINTRIN_H
994
995 } // namespace detail
996
997 template <class T, class Comp>
998 size_t qfind_first_of(const Range<T> & haystack,
999                       const Range<T> & needles,
1000                       Comp eq) {
1001   auto ret = std::find_first_of(haystack.begin(), haystack.end(),
1002                                 needles.begin(), needles.end(),
1003                                 eq);
1004   return ret == haystack.end() ? std::string::npos : ret - haystack.begin();
1005 }
1006
1007 struct AsciiCaseSensitive {
1008   bool operator()(char lhs, char rhs) const {
1009     return lhs == rhs;
1010   }
1011 };
1012
1013 /**
1014  * Check if two ascii characters are case insensitive equal.
1015  * The difference between the lower/upper case characters are the 6-th bit.
1016  * We also check they are alpha chars, in case of xor = 32.
1017  */
1018 struct AsciiCaseInsensitive {
1019   bool operator()(char lhs, char rhs) const {
1020     char k = lhs ^ rhs;
1021     if (k == 0) return true;
1022     if (k != 32) return false;
1023     k = lhs | rhs;
1024     return (k >= 'a' && k <= 'z');
1025   }
1026 };
1027
1028 extern const AsciiCaseSensitive asciiCaseSensitive;
1029 extern const AsciiCaseInsensitive asciiCaseInsensitive;
1030
1031 template <class T>
1032 size_t qfind(const Range<T>& haystack,
1033              const typename Range<T>::value_type& needle) {
1034   auto pos = std::find(haystack.begin(), haystack.end(), needle);
1035   return pos == haystack.end() ? std::string::npos : pos - haystack.data();
1036 }
1037
1038 template <class T>
1039 size_t rfind(const Range<T>& haystack,
1040              const typename Range<T>::value_type& needle) {
1041   for (auto i = haystack.size(); i-- > 0; ) {
1042     if (haystack[i] == needle) {
1043       return i;
1044     }
1045   }
1046   return std::string::npos;
1047 }
1048
1049 // specialization for StringPiece
1050 template <>
1051 inline size_t qfind(const Range<const char*>& haystack, const char& needle) {
1052   auto pos = static_cast<const char*>(
1053     ::memchr(haystack.data(), needle, haystack.size()));
1054   return pos == nullptr ? std::string::npos : pos - haystack.data();
1055 }
1056
1057 #if FOLLY_HAVE_MEMRCHR
1058 template <>
1059 inline size_t rfind(const Range<const char*>& haystack, const char& needle) {
1060   auto pos = static_cast<const char*>(
1061     ::memrchr(haystack.data(), needle, haystack.size()));
1062   return pos == nullptr ? std::string::npos : pos - haystack.data();
1063 }
1064 #endif
1065
1066 // specialization for ByteRange
1067 template <>
1068 inline size_t qfind(const Range<const unsigned char*>& haystack,
1069                     const unsigned char& needle) {
1070   auto pos = static_cast<const unsigned char*>(
1071     ::memchr(haystack.data(), needle, haystack.size()));
1072   return pos == nullptr ? std::string::npos : pos - haystack.data();
1073 }
1074
1075 #if FOLLY_HAVE_MEMRCHR
1076 template <>
1077 inline size_t rfind(const Range<const unsigned char*>& haystack,
1078                     const unsigned char& needle) {
1079   auto pos = static_cast<const unsigned char*>(
1080     ::memrchr(haystack.data(), needle, haystack.size()));
1081   return pos == nullptr ? std::string::npos : pos - haystack.data();
1082 }
1083 #endif
1084
1085 template <class T>
1086 size_t qfind_first_of(const Range<T>& haystack,
1087                       const Range<T>& needles) {
1088   return qfind_first_of(haystack, needles, asciiCaseSensitive);
1089 }
1090
1091 // specialization for StringPiece
1092 template <>
1093 inline size_t qfind_first_of(const Range<const char*>& haystack,
1094                              const Range<const char*>& needles) {
1095   return detail::qfind_first_byte_of(haystack, needles);
1096 }
1097
1098 // specialization for ByteRange
1099 template <>
1100 inline size_t qfind_first_of(const Range<const unsigned char*>& haystack,
1101                              const Range<const unsigned char*>& needles) {
1102   return detail::qfind_first_byte_of(StringPiece(haystack),
1103                                      StringPiece(needles));
1104 }
1105 }  // !namespace folly
1106
1107 #pragma GCC diagnostic pop
1108
1109 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(folly::Range);
1110
1111 #endif // FOLLY_RANGE_H_