• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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