• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_LIBPANDABASE_UTILS_SPAN_H_
17 #define PANDA_LIBPANDABASE_UTILS_SPAN_H_
18 
19 #include "macros.h"
20 
21 #include <cstddef>
22 #include <iterator>
23 
24 namespace panda {
25 
26 /**
27  * Similar to std::span that will come in C++20.
28  */
29 template <class T>
30 class Span {
31 public:
32     using ElementType = T;
33     using value_type = std::remove_cv_t<T>;
34     using ValueType = value_type;
35     using Reference = T &;
36     using ConstReference = const T &;
37     using Iterator = T *;
38     using ConstIterator = const T *;
39     using ReverseIterator = std::reverse_iterator<Iterator>;
40     using ConstReverseIterator = std::reverse_iterator<ConstIterator>;
41 
42     Span() = default;
Span(Iterator data,size_t size)43     Span(Iterator data, size_t size) : data_(data), size_(size) {}
44     constexpr Span(const Span &other) noexcept = default;
45     Span(Span &&other) noexcept = default;
46     ~Span() = default;
47 
48     // The following constructor is non-explicit to be aligned with std::span
49     template <class U, size_t N>
50     // NOLINTNEXTLINE(google-explicit-constructor,modernize-avoid-c-arrays)
Span(U (& array)[N])51     constexpr Span(U (&array)[N]) : Span(array, N)
52     {
53     }
54 
Span(Iterator begin,Iterator end)55     Span(Iterator begin, Iterator end) : Span(begin, end - begin) {}
56 
57     template <class Vector>
Span(Vector & v)58     explicit Span(Vector &v) : Span(v.data(), v.size())
59     {
60     }
61 
62     template <class Vector>
Span(const Vector & v)63     explicit Span(const Vector &v) : Span(v.data(), v.size())
64     {
65     }
66 
67     constexpr Span &operator=(const Span &other) noexcept = default;
68     Span &operator=(Span &&other) noexcept = default;
69 
70     // NOLINTNEXTLINE(readability-identifier-naming)
begin()71     Iterator begin()
72     {
73         return data_;
74     }
75 
76     // NOLINTNEXTLINE(readability-identifier-naming)
begin()77     ConstIterator begin() const
78     {
79         return data_;
80     }
81 
82     // NOLINTNEXTLINE(readability-identifier-naming)
cbegin()83     ConstIterator cbegin() const
84     {
85         return data_;
86     }
87 
88     // NOLINTNEXTLINE(readability-identifier-naming)
end()89     Iterator end()
90     {
91         return data_ + size_;  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
92     }
93 
94     // NOLINTNEXTLINE(readability-identifier-naming)
end()95     ConstIterator end() const
96     {
97         return data_ + size_;  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
98     }
99 
100     // NOLINTNEXTLINE(readability-identifier-naming)
cend()101     ConstIterator cend() const
102     {
103         return data_ + size_;  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
104     }
105 
106     // NOLINTNEXTLINE(readability-identifier-naming)
rbegin()107     ReverseIterator rbegin()
108     {
109         return ReverseIterator(end());
110     }
111 
112     // NOLINTNEXTLINE(readability-identifier-naming)
rbegin()113     ConstReverseIterator rbegin() const
114     {
115         return ConstReverseIterator(end());
116     }
117 
118     // NOLINTNEXTLINE(readability-identifier-naming)
crbegin()119     ConstReverseIterator crbegin() const
120     {
121         return ConstReverseIterator(cend());
122     }
123 
124     // NOLINTNEXTLINE(readability-identifier-naming)
rend()125     ReverseIterator rend()
126     {
127         return ReverseIterator(begin());
128     }
129 
130     // NOLINTNEXTLINE(readability-identifier-naming)
rend()131     ConstReverseIterator rend() const
132     {
133         return ConstReverseIterator(begin());
134     }
135 
136     // NOLINTNEXTLINE(readability-identifier-naming)
crend()137     ConstReverseIterator crend() const
138     {
139         return ConstReverseIterator(cbegin());
140     }
141 
142     // NOLINT(readability-identifier-naming)
143     Reference operator[](size_t index)
144     {
145         ASSERT(index < size_);
146         return data_[index];  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
147     }
148 
149     // NOLINT(readability-identifier-naming)
150     ConstReference operator[](size_t index) const
151     {
152         ASSERT(index < size_);
153         return data_[index];  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
154     }
155 
Size()156     constexpr size_t Size() const
157     {
158         return size_;
159     }
160 
SizeBytes()161     constexpr size_t SizeBytes() const
162     {
163         return size_ * sizeof(ElementType);
164     }
165 
Empty()166     constexpr bool Empty() const
167     {
168         return size_ == 0U;
169     }
170 
Data()171     Iterator Data()
172     {
173         return data_;
174     }
175 
Data()176     ConstIterator Data() const
177     {
178         return data_;
179     }
180 
First(size_t length)181     Span First(size_t length) const
182     {
183         ASSERT(length <= size_);
184         return SubSpan(0, length);
185     }
186 
Last(size_t length)187     Span Last(size_t length) const
188     {
189         ASSERT(length <= size_);
190         return SubSpan(size_ - length, length);
191     }
192 
SubSpan(size_t position,size_t length)193     Span SubSpan(size_t position, size_t length) const
194     {
195         ASSERT((position + length) <= size_);
196         return Span(data_ + position, length);  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
197     }
198 
SubSpan(size_t position)199     Span SubSpan(size_t position) const
200     {
201         ASSERT(position <= size_);
202         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
203         return Span(data_ + position, size_ - position);
204     }
205 
206     template <typename SubT>
SubSpan(size_t position,size_t length)207     Span<SubT> SubSpan(size_t position, size_t length) const
208     {
209         ASSERT((position * sizeof(T) + length * sizeof(SubT)) <= (size_ * sizeof(T)));
210         ASSERT(((reinterpret_cast<uintptr_t>(data_ + position)) % alignof(SubT)) == 0);
211         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
212         return Span<SubT>(reinterpret_cast<SubT *>(data_ + position), length);
213     }
214 
ToConst()215     auto ToConst() const
216     {
217         return Span<const std::remove_const_t<T>>(data_, size_);
218     }
219 
220     // Methods for compatibility with std containers
221     // NOLINTNEXTLINE(readability-identifier-naming)
size()222     size_t size() const
223     {
224         return size_;
225     }
226 
227     // NOLINTNEXTLINE(readability-identifier-naming)
empty()228     size_t empty() const
229     {
230         return size() == 0;
231     }
232 
233     // NOLINTNEXTLINE(readability-identifier-naming)
data()234     Iterator data()
235     {
236         return data_;
237     }
238 
239     // NOLINTNEXTLINE(readability-identifier-naming)
data()240     ConstIterator data() const
241     {
242         return data_;
243     }
244 
245 private:
246     Iterator data_ {nullptr};
247     size_t size_ {0};
248 };
249 
250 // Deduction guides
251 template <class U, size_t N>
252 Span(U (&)[N])->Span<U>;  // NOLINT(modernize-avoid-c-arrays)
253 
254 template <class Vector>
255 Span(Vector &)->Span<typename Vector::value_type>;
256 
257 template <class Vector>
258 Span(const Vector &)->Span<const typename Vector::value_type>;
259 
260 // Non-member functions
261 template <class T>
AsBytes(Span<T> s)262 Span<const std::byte> AsBytes(Span<T> s) noexcept
263 {
264     return {reinterpret_cast<const std::byte *>(s.Data()), s.SizeBytes()};
265 }
266 
267 template <class T, typename = std::enable_if_t<!std::is_const_v<T>>>
AsWritableBytes(Span<T> s)268 Span<std::byte> AsWritableBytes(Span<T> s) noexcept
269 {
270     return {reinterpret_cast<std::byte *>(s.Data()), s.SizeBytes()};
271 }
272 
273 }  // namespace panda
274 
275 #endif  // PANDA_LIBPANDABASE_UTILS_SPAN_H_
276