/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). */ /** * A subset of `folly/Range.h`. * All code copied verbatim modulo formatting */ #pragma once #include "utils/Likely.h" #include "utils/Portability.h" #include #include #include #include #include #include namespace pzstd { namespace detail { /* *Use IsCharPointer::type to enable const char* or char*. *Use IsCharPointer::const_type to enable only const char*. */ template struct IsCharPointer {}; template <> struct IsCharPointer { typedef int type; }; template <> struct IsCharPointer { typedef int const_type; typedef int type; }; } // namespace detail template class Range { Iter b_; Iter e_; public: using size_type = std::size_t; using iterator = Iter; using const_iterator = Iter; using value_type = typename std::remove_reference< typename std::iterator_traits::reference>::type; using reference = typename std::iterator_traits::reference; constexpr Range() : b_(), e_() {} constexpr Range(Iter begin, Iter end) : b_(begin), e_(end) {} constexpr Range(Iter begin, size_type size) : b_(begin), e_(begin + size) {} template ::type = 0> /* implicit */ Range(Iter str) : b_(str), e_(str + std::strlen(str)) {} template ::const_type = 0> /* implicit */ Range(const std::string& str) : b_(str.data()), e_(b_ + str.size()) {} // Allow implicit conversion from Range to Range if From is // implicitly convertible to To. template < class OtherIter, typename std::enable_if< (!std::is_same::value && std::is_convertible::value), int>::type = 0> constexpr /* implicit */ Range(const Range& other) : b_(other.begin()), e_(other.end()) {} Range(const Range&) = default; Range(Range&&) = default; Range& operator=(const Range&) = default; Range& operator=(Range&&) = default; constexpr size_type size() const { return e_ - b_; } bool empty() const { return b_ == e_; } Iter data() const { return b_; } Iter begin() const { return b_; } Iter end() const { return e_; } void advance(size_type n) { if (UNLIKELY(n > size())) { throw std::out_of_range("index out of range"); } b_ += n; } void subtract(size_type n) { if (UNLIKELY(n > size())) { throw std::out_of_range("index out of range"); } e_ -= n; } Range subpiece(size_type first, size_type length = std::string::npos) const { if (UNLIKELY(first > size())) { throw std::out_of_range("index out of range"); } return Range(b_ + first, std::min(length, size() - first)); } }; using ByteRange = Range; using MutableByteRange = Range; using StringPiece = Range; }