1 /* 2 * Copyright (c) 2016-present, Facebook, Inc. 3 * All rights reserved. 4 * 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). 8 */ 9 10 /** 11 * A subset of `folly/Range.h`. 12 * All code copied verbatim modulo formatting 13 */ 14 #pragma once 15 16 #include "utils/Likely.h" 17 18 #include <cstddef> 19 #include <cstring> 20 #include <stdexcept> 21 #include <string> 22 #include <type_traits> 23 24 namespace pzstd { 25 26 namespace detail { 27 /* 28 *Use IsCharPointer<T>::type to enable const char* or char*. 29 *Use IsCharPointer<T>::const_type to enable only const char*. 30 */ 31 template <class T> 32 struct IsCharPointer {}; 33 34 template <> 35 struct IsCharPointer<char*> { 36 typedef int type; 37 }; 38 39 template <> 40 struct IsCharPointer<const char*> { 41 typedef int const_type; 42 typedef int type; 43 }; 44 45 } // namespace detail 46 47 template <typename Iter> 48 class Range { 49 Iter b_; 50 Iter e_; 51 52 public: 53 using size_type = std::size_t; 54 using iterator = Iter; 55 using const_iterator = Iter; 56 using value_type = typename std::remove_reference< 57 typename std::iterator_traits<Iter>::reference>::type; 58 using reference = typename std::iterator_traits<Iter>::reference; 59 60 constexpr Range() : b_(), e_() {} 61 constexpr Range(Iter begin, Iter end) : b_(begin), e_(end) {} 62 63 constexpr Range(Iter begin, size_type size) : b_(begin), e_(begin + size) {} 64 65 template <class T = Iter, typename detail::IsCharPointer<T>::type = 0> 66 /* implicit */ Range(Iter str) : b_(str), e_(str + std::strlen(str)) {} 67 68 template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> 69 /* implicit */ Range(const std::string& str) 70 : b_(str.data()), e_(b_ + str.size()) {} 71 72 // Allow implicit conversion from Range<From> to Range<To> if From is 73 // implicitly convertible to To. 74 template < 75 class OtherIter, 76 typename std::enable_if< 77 (!std::is_same<Iter, OtherIter>::value && 78 std::is_convertible<OtherIter, Iter>::value), 79 int>::type = 0> 80 constexpr /* implicit */ Range(const Range<OtherIter>& other) 81 : b_(other.begin()), e_(other.end()) {} 82 83 Range(const Range&) = default; 84 Range(Range&&) = default; 85 86 Range& operator=(const Range&) & = default; 87 Range& operator=(Range&&) & = default; 88 89 constexpr size_type size() const { 90 return e_ - b_; 91 } 92 bool empty() const { 93 return b_ == e_; 94 } 95 Iter data() const { 96 return b_; 97 } 98 Iter begin() const { 99 return b_; 100 } 101 Iter end() const { 102 return e_; 103 } 104 105 void advance(size_type n) { 106 if (UNLIKELY(n > size())) { 107 throw std::out_of_range("index out of range"); 108 } 109 b_ += n; 110 } 111 112 void subtract(size_type n) { 113 if (UNLIKELY(n > size())) { 114 throw std::out_of_range("index out of range"); 115 } 116 e_ -= n; 117 } 118 119 Range subpiece(size_type first, size_type length = std::string::npos) const { 120 if (UNLIKELY(first > size())) { 121 throw std::out_of_range("index out of range"); 122 } 123 124 return Range(b_ + first, std::min(length, size() - first)); 125 } 126 }; 127 128 using ByteRange = Range<const unsigned char*>; 129 using MutableByteRange = Range<unsigned char*>; 130 using StringPiece = Range<const char*>; 131 } 132