| /* |
| * 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 <algorithm> |
| #include <cstddef> |
| #include <cstring> |
| #include <stdexcept> |
| #include <string> |
| #include <type_traits> |
| |
| namespace pzstd { |
| |
| namespace detail { |
| /* |
| *Use IsCharPointer<T>::type to enable const char* or char*. |
| *Use IsCharPointer<T>::const_type to enable only const char*. |
| */ |
| template <class T> |
| struct IsCharPointer {}; |
| |
| template <> |
| struct IsCharPointer<char*> { |
| typedef int type; |
| }; |
| |
| template <> |
| struct IsCharPointer<const char*> { |
| typedef int const_type; |
| typedef int type; |
| }; |
| |
| } // namespace detail |
| |
| template <typename Iter> |
| 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<Iter>::reference>::type; |
| using reference = typename std::iterator_traits<Iter>::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 <class T = Iter, typename detail::IsCharPointer<T>::type = 0> |
| /* implicit */ Range(Iter str) : b_(str), e_(str + std::strlen(str)) {} |
| |
| template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> |
| /* implicit */ Range(const std::string& str) |
| : b_(str.data()), e_(b_ + str.size()) {} |
| |
| // Allow implicit conversion from Range<From> to Range<To> if From is |
| // implicitly convertible to To. |
| template < |
| class OtherIter, |
| typename std::enable_if< |
| (!std::is_same<Iter, OtherIter>::value && |
| std::is_convertible<OtherIter, Iter>::value), |
| int>::type = 0> |
| constexpr /* implicit */ Range(const Range<OtherIter>& 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<const unsigned char*>; |
| using MutableByteRange = Range<unsigned char*>; |
| using StringPiece = Range<const char*>; |
| } |