• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 ark {
25 
26 /// Similar to std::span that will come in C++20.
27 template <class T>
28 class Span {
29 public:
30     using ElementType = T;
31     // NOLINTNEXTLINE(readability-identifier-naming)
32     using value_type = std::remove_cv_t<T>;
33     using ValueType = value_type;
34     using Reference = T &;
35     using ConstReference = const T &;
36     using Iterator = T *;
37     using ConstIterator = const T *;
38     using ReverseIterator = std::reverse_iterator<Iterator>;
39     using ConstReverseIterator = std::reverse_iterator<ConstIterator>;
40 
41     Span() = default;
Span(Iterator data,size_t size)42     Span(Iterator data, size_t size) : data_(data), size_(size) {}
43     constexpr Span(const Span &other) noexcept = default;
44     Span(Span &&other) noexcept = default;
45     ~Span() = default;
46 
47     // The following constructor is non-explicit to be aligned with std::span
48     template <class U, size_t N>
49     // NOLINTNEXTLINE(google-explicit-constructor,modernize-avoid-c-arrays)
Span(U (& array)[N])50     constexpr Span(U (&array)[N]) : Span(array, N)
51     {
52     }
53 
Span(Iterator begin,Iterator end)54     Span(Iterator begin, Iterator end) : Span(begin, end - begin) {}
55 
56     template <class Vector>
Span(Vector & v)57     explicit Span(Vector &v) : Span(v.data(), v.size())
58     {
59     }
60 
61     template <class Vector>
Span(const Vector & v)62     explicit Span(const Vector &v) : Span(v.data(), v.size())
63     {
64     }
65 
66     constexpr Span &operator=(const Span &other) noexcept = default;
67     Span &operator=(Span &&other) noexcept = default;
68     // NOLINTNEXTLINE(readability-identifier-naming)
begin()69     Iterator begin()
70     {
71         return data_;
72     }
73     // NOLINTNEXTLINE(readability-identifier-naming)
begin()74     ConstIterator begin() const
75     {
76         return data_;
77     }
78     // NOLINTNEXTLINE(readability-identifier-naming)
cbegin()79     ConstIterator cbegin() const
80     {
81         return data_;
82     }
83     // NOLINTNEXTLINE(readability-identifier-naming)
end()84     Iterator end()
85     {
86         return data_ + size_;  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
87     }
88     // NOLINTNEXTLINE(readability-identifier-naming)
end()89     ConstIterator end() const
90     {
91         return data_ + size_;  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
92     }
93     // NOLINTNEXTLINE(readability-identifier-naming)
cend()94     ConstIterator cend() const
95     {
96         return data_ + size_;  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
97     }
98     // NOLINTNEXTLINE(readability-identifier-naming)
rbegin()99     ReverseIterator rbegin()
100     {
101         return ReverseIterator(end());
102     }
103     // NOLINTNEXTLINE(readability-identifier-naming)
rbegin()104     ConstReverseIterator rbegin() const
105     {
106         return ConstReverseIterator(end());
107     }
108     // NOLINTNEXTLINE(readability-identifier-naming)
crbegin()109     ConstReverseIterator crbegin() const
110     {
111         return ConstReverseIterator(cend());
112     }
113     // NOLINTNEXTLINE(readability-identifier-naming)
rend()114     ReverseIterator rend()
115     {
116         return ReverseIterator(begin());
117     }
118     // NOLINTNEXTLINE(readability-identifier-naming)
rend()119     ConstReverseIterator rend() const
120     {
121         return ConstReverseIterator(begin());
122     }
123     // NOLINTNEXTLINE(readability-identifier-naming)
crend()124     ConstReverseIterator crend() const
125     {
126         return ConstReverseIterator(cbegin());
127     }
128 
129     // NOLINT(readability-identifier-naming)
130     Reference operator[](size_t index)
131     {
132         ASSERT(data_ != nullptr);
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 ark
263 #endif  // LIBPANDABASE_UTILS_SPAN_H_
264