1 /* 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 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 #include "utils/Portability.h" 18 19 #include <algorithm> 20 #include <cstddef> 21 #include <cstring> 22 #include <stdexcept> 23 #include <string> 24 #include <type_traits> 25 26 namespace pzstd { 27 28 namespace detail { 29 /* 30 *Use IsCharPointer<T>::type to enable const char* or char*. 31 *Use IsCharPointer<T>::const_type to enable only const char*. 32 */ 33 template <class T> 34 struct IsCharPointer {}; 35 36 template <> 37 struct IsCharPointer<char*> { 38 typedef int type; 39 }; 40 41 template <> 42 struct IsCharPointer<const char*> { 43 typedef int const_type; 44 typedef int type; 45 }; 46 47 } // namespace detail 48 49 template <typename Iter> 50 class Range { 51 Iter b_; 52 Iter e_; 53 54 public: 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; 61 62 constexpr Range() : b_(), e_() {} 63 constexpr Range(Iter begin, Iter end) : b_(begin), e_(end) {} 64 65 constexpr Range(Iter begin, size_type size) : b_(begin), e_(begin + size) {} 66 67 template <class T = Iter, typename detail::IsCharPointer<T>::type = 0> 68 /* implicit */ Range(Iter str) : b_(str), e_(str + std::strlen(str)) {} 69 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()) {} 73 74 // Allow implicit conversion from Range<From> to Range<To> if From is 75 // implicitly convertible to To. 76 template < 77 class OtherIter, 78 typename std::enable_if< 79 (!std::is_same<Iter, OtherIter>::value && 80 std::is_convertible<OtherIter, Iter>::value), 81 int>::type = 0> 82 constexpr /* implicit */ Range(const Range<OtherIter>& other) 83 : b_(other.begin()), e_(other.end()) {} 84 85 Range(const Range&) = default; 86 Range(Range&&) = default; 87 88 Range& operator=(const Range&) = default; 89 Range& operator=(Range&&) = default; 90 91 constexpr size_type size() const { 92 return e_ - b_; 93 } 94 bool empty() const { 95 return b_ == e_; 96 } 97 Iter data() const { 98 return b_; 99 } 100 Iter begin() const { 101 return b_; 102 } 103 Iter end() const { 104 return e_; 105 } 106 107 void advance(size_type n) { 108 if (UNLIKELY(n > size())) { 109 throw std::out_of_range("index out of range"); 110 } 111 b_ += n; 112 } 113 114 void subtract(size_type n) { 115 if (UNLIKELY(n > size())) { 116 throw std::out_of_range("index out of range"); 117 } 118 e_ -= n; 119 } 120 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"); 124 } 125 126 return Range(b_ + first, std::min(length, size() - first)); 127 } 128 }; 129 130 using ByteRange = Range<const unsigned char*>; 131 using MutableByteRange = Range<unsigned char*>; 132 using StringPiece = Range<const char*>; 133 } 134