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