• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 LIBPANDABASE_UTILS_SPAN_H
17 #define 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     // NOLINTNEXTLINE(readability-identifier-naming)
begin()70     Iterator begin()
71     {
72         return data_;
73     }
74     // NOLINTNEXTLINE(readability-identifier-naming)
begin()75     ConstIterator begin() const
76     {
77         return data_;
78     }
79     // NOLINTNEXTLINE(readability-identifier-naming)
cbegin()80     ConstIterator cbegin() const
81     {
82         return data_;
83     }
84     // NOLINTNEXTLINE(readability-identifier-naming)
end()85     Iterator end()
86     {
87         return data_ + size_;  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
88     }
89     // NOLINTNEXTLINE(readability-identifier-naming)
end()90     ConstIterator end() const
91     {
92         return data_ + size_;  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
93     }
94     // NOLINTNEXTLINE(readability-identifier-naming)
cend()95     ConstIterator cend() const
96     {
97         return data_ + size_;  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
98     }
99     // NOLINTNEXTLINE(readability-identifier-naming)
rbegin()100     ReverseIterator rbegin()
101     {
102         return ReverseIterator(end());
103     }
104     // NOLINTNEXTLINE(readability-identifier-naming)
rbegin()105     ConstReverseIterator rbegin() const
106     {
107         return ConstReverseIterator(end());
108     }
109     // NOLINTNEXTLINE(readability-identifier-naming)
crbegin()110     ConstReverseIterator crbegin() const
111     {
112         return ConstReverseIterator(cend());
113     }
114     // NOLINTNEXTLINE(readability-identifier-naming)
rend()115     ReverseIterator rend()
116     {
117         return ReverseIterator(begin());
118     }
119     // NOLINTNEXTLINE(readability-identifier-naming)
rend()120     ConstReverseIterator rend() const
121     {
122         return ConstReverseIterator(begin());
123     }
124     // NOLINTNEXTLINE(readability-identifier-naming)
crend()125     ConstReverseIterator crend() const
126     {
127         return ConstReverseIterator(cbegin());
128     }
129 
130     // NOLINT(readability-identifier-naming)
131     Reference operator[](size_t index)
132     {
133         ASSERT(index < size_);
134         return data_[index];  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
135     }
136 
137     // NOLINT(readability-identifier-naming)
138     ConstReference operator[](size_t index) const
139     {
140         ASSERT(index < size_);
141         return data_[index];  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
142     }
143 
Size()144     constexpr size_t Size() const
145     {
146         return size_;
147     }
SizeBytes()148     constexpr size_t SizeBytes() const
149     {
150         return size_ * sizeof(ElementType);
151     }
Empty()152     constexpr bool Empty() const
153     {
154         return size_ == 0U;
155     }
156 
Data()157     Iterator Data()
158     {
159         return data_;
160     }
Data()161     ConstIterator Data() const
162     {
163         return data_;
164     }
165 
First(size_t length)166     Span First(size_t length) const
167     {
168         ASSERT(length <= size_);
169         return SubSpan(0, length);
170     }
171 
Last(size_t length)172     Span Last(size_t length) const
173     {
174         ASSERT(length <= size_);
175         return SubSpan(size_ - length, length);
176     }
177 
SubSpan(size_t position,size_t length)178     Span SubSpan(size_t position, size_t length) const
179     {
180         ASSERT((position + length) <= size_);
181         return Span(data_ + position, length);  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
182     }
183 
SubSpan(size_t position)184     Span SubSpan(size_t position) const
185     {
186         ASSERT(position <= size_);
187         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
188         return Span(data_ + position, size_ - position);
189     }
190 
191     template <typename SubT>
SubSpan(size_t position,size_t length)192     Span<SubT> SubSpan(size_t position, size_t length) const
193     {
194         ASSERT((position * sizeof(T) + length * sizeof(SubT)) <= (size_ * sizeof(T)));
195         ASSERT(((reinterpret_cast<uintptr_t>(data_ + position)) % alignof(SubT)) == 0);
196         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
197         return Span<SubT>(reinterpret_cast<SubT *>(data_ + position), length);
198     }
199 
ToConst()200     auto ToConst() const
201     {
202         return Span<const std::remove_const_t<T>>(data_, size_);
203     }
204 
205     // Methods for compatibility with std containers
206     // NOLINTNEXTLINE(readability-identifier-naming)
size()207     size_t size() const
208     {
209         return size_;
210     }
211     // NOLINTNEXTLINE(readability-identifier-naming)
empty()212     bool empty() const
213     {
214         return size() == 0;
215     }
216     // NOLINTNEXTLINE(readability-identifier-naming)
data()217     Iterator data()
218     {
219         return data_;
220     }
221     // NOLINTNEXTLINE(readability-identifier-naming)
data()222     ConstIterator data() const
223     {
224         return data_;
225     }
GetDataOffset()226     static constexpr uint32_t GetDataOffset()
227     {
228         return MEMBER_OFFSET(Span<T>, data_);
229     }
GetSizeOffset()230     static constexpr uint32_t GetSizeOffset()
231     {
232         return MEMBER_OFFSET(Span<T>, size_);
233     }
234 
235 private:
236     Iterator data_ {nullptr};
237     size_t size_ {0};
238 };
239 
240 // Deduction guides
241 template <class U, size_t N>
242 Span(U (&)[N])->Span<U>;  // NOLINT(modernize-avoid-c-arrays)
243 
244 template <class Vector>
245 Span(Vector &)->Span<typename Vector::value_type>;
246 
247 template <class Vector>
248 Span(const Vector &)->Span<const typename Vector::value_type>;
249 
250 // Non-member functions
251 template <class T>
AsBytes(Span<T> s)252 Span<const std::byte> AsBytes(Span<T> s) noexcept
253 {
254     return {reinterpret_cast<const std::byte *>(s.Data()), s.SizeBytes()};
255 }
256 template <class T, typename = std::enable_if_t<!std::is_const_v<T>>>
AsWritableBytes(Span<T> s)257 Span<std::byte> AsWritableBytes(Span<T> s) noexcept
258 {
259     return {reinterpret_cast<std::byte *>(s.Data()), s.SizeBytes()};
260 }
261 
262 }  // namespace panda
263 
264 #endif  // LIBPANDABASE_UTILS_SPAN_H
265