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