2 * Copyright (c) Meta Platforms, Inc. and affiliates.
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
11 * A subset of `folly/Range.h`.
12 * All code copied verbatim modulo formatting
16 #include "utils/Likely.h"
17 #include "utils/Portability.h"
24 #include <type_traits>
30 *Use IsCharPointer<T>::type to enable const char* or char*.
31 *Use IsCharPointer<T>::const_type to enable only const char*.
34 struct IsCharPointer {};
37 struct IsCharPointer<char*> {
42 struct IsCharPointer<const char*> {
43 typedef int const_type;
49 template <typename Iter>
55 using size_type = std::size_t;
56 using iterator = Iter;
57 using const_iterator = Iter;
58 using value_type = typename std::remove_reference<
59 typename std::iterator_traits<Iter>::reference>::type;
60 using reference = typename std::iterator_traits<Iter>::reference;
62 constexpr Range() : b_(), e_() {}
63 constexpr Range(Iter begin, Iter end) : b_(begin), e_(end) {}
65 constexpr Range(Iter begin, size_type size) : b_(begin), e_(begin + size) {}
67 template <class T = Iter, typename detail::IsCharPointer<T>::type = 0>
68 /* implicit */ Range(Iter str) : b_(str), e_(str + std::strlen(str)) {}
70 template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
71 /* implicit */ Range(const std::string& str)
72 : b_(str.data()), e_(b_ + str.size()) {}
74 // Allow implicit conversion from Range<From> to Range<To> if From is
75 // implicitly convertible to To.
78 typename std::enable_if<
79 (!std::is_same<Iter, OtherIter>::value &&
80 std::is_convertible<OtherIter, Iter>::value),
82 constexpr /* implicit */ Range(const Range<OtherIter>& other)
83 : b_(other.begin()), e_(other.end()) {}
85 Range(const Range&) = default;
86 Range(Range&&) = default;
88 Range& operator=(const Range&) = default;
89 Range& operator=(Range&&) = default;
91 constexpr size_type size() const {
107 void advance(size_type n) {
108 if (UNLIKELY(n > size())) {
109 throw std::out_of_range("index out of range");
114 void subtract(size_type n) {
115 if (UNLIKELY(n > size())) {
116 throw std::out_of_range("index out of range");
121 Range subpiece(size_type first, size_type length = std::string::npos) const {
122 if (UNLIKELY(first > size())) {
123 throw std::out_of_range("index out of range");
126 return Range(b_ + first, std::min(length, size() - first));
130 using ByteRange = Range<const unsigned char*>;
131 using MutableByteRange = Range<unsigned char*>;
132 using StringPiece = Range<const char*>;