1 /*
2 * Copyright (C) 2023 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 API_BASE_CONTAINERS_ARRAYVIEW_H
17 #define API_BASE_CONTAINERS_ARRAYVIEW_H
18
19 #include <cassert>
20 #include <cstdint>
21 #include <iterator>
22 #include <type_traits>
23
24 /** @ingroup group_containers_arrayview */
25 /** Array view */
26 template<class T>
27 class array_view {
28 public:
29 struct Iterator {
30 using iterator_category = std::forward_iterator_tag;
31 using difference_type = std::ptrdiff_t;
32 using value_type = T;
33 using pointer = T*;
34 using reference = T&;
35
IteratorIterator36 Iterator(pointer ptr) : m_ptr(ptr) {}
37
38 reference operator*() const
39 {
40 return *m_ptr;
41 }
42 pointer operator->()
43 {
44 return m_ptr;
45 }
46 Iterator& operator++()
47 {
48 m_ptr++;
49 return *this;
50 }
51 Iterator operator++(int)
52 {
53 Iterator tmp = *this;
54 ++(*this);
55 return tmp;
56 }
57 friend bool operator==(const Iterator& a, const Iterator& b)
58 {
59 return a.m_ptr == b.m_ptr;
60 };
61 friend bool operator!=(const Iterator& a, const Iterator& b)
62 {
63 return a.m_ptr != b.m_ptr;
64 };
65
66 private:
67 pointer m_ptr;
68 };
69 using value_type = T;
70 using difference_type = size_t;
71 using pointer = value_type*;
72 using reference = value_type&;
73
74 using size_type = size_t;
75 using const_reference = const value_type&;
76 using const_pointer = const value_type*;
77
78 using iterator = Iterator;
79 using const_iterator = Iterator;
80
array_view()81 constexpr array_view() noexcept : begin_(nullptr), size_(0), end_(nullptr) {}
array_view(pointer aBegin,pointer aEnd)82 constexpr array_view(pointer aBegin, pointer aEnd) noexcept : begin_(aBegin), size_(aEnd - aBegin), end_(aEnd)
83 {
84 assert(end_ >= begin_);
85 }
array_view(pointer aBegin,size_type aSize)86 constexpr array_view(pointer aBegin, size_type aSize) noexcept : begin_(aBegin), size_(aSize), end_(aBegin + aSize)
87 {}
88 template<size_t N>
array_view(value_type (& arr)[N])89 constexpr array_view(value_type (&arr)[N]) noexcept : begin_(arr), size_(N), end_(arr + N)
90 {}
91 template<class U, class = std::enable_if_t<std::is_same<std::remove_const_t<T>, U>::value>>
array_view(const array_view<U> & other)92 explicit constexpr array_view(const array_view<U>& other) noexcept
93 : begin_(other.begin_), size_(other.size_), end_(other.end_)
94 {}
95 template<class U, class = std::enable_if_t<std::is_same<std::remove_const_t<T>, typename U::value_type>::value>>
array_view(U & container)96 explicit constexpr array_view(U& container) noexcept : array_view(container.data(), container.size())
97 {}
98 template<class U, class = std::enable_if_t<std::is_same<std::remove_const_t<T>, typename U::value_type>::value>>
array_view(const U & container)99 explicit constexpr array_view(const U& container) noexcept : array_view(container.data(), container.size())
100 {}
101 ~array_view() = default;
size()102 constexpr size_type size() const noexcept
103 {
104 return size_;
105 }
size_bytes()106 constexpr size_type size_bytes() const noexcept
107 {
108 return size_ * sizeof(T);
109 }
empty()110 constexpr bool empty() const noexcept
111 {
112 return size_ == 0;
113 }
data()114 constexpr const_pointer data() const noexcept
115 {
116 return begin_;
117 }
data()118 constexpr pointer data() noexcept
119 {
120 return begin_;
121 }
at(size_type aIndex)122 constexpr reference at(size_type aIndex) noexcept
123 {
124 // If index out-of-range, undefined behaviour on release builds, assert on debug builds.
125 assert(aIndex < size());
126 return begin_[aIndex];
127 }
at(size_type aIndex)128 constexpr const_reference at(size_type aIndex) const noexcept
129 {
130 // If index out-of-range, undefined behaviour on release builds, assert on debug builds.
131 assert(aIndex < size());
132 return begin_[aIndex];
133 }
134 constexpr reference operator[](size_type aIndex)
135 {
136 // If index out-of-range, undefined behaviour on release builds, assert on debug builds.
137 assert(aIndex < size());
138 return begin_[aIndex];
139 }
140 constexpr const_reference operator[](size_type aIndex) const
141 {
142 // If index out-of-range, undefined behaviour on release builds, assert on debug builds.
143 assert(aIndex < size());
144 return begin_[aIndex];
145 }
begin()146 constexpr iterator begin() noexcept
147 {
148 return iterator(begin_);
149 }
end()150 constexpr iterator end() noexcept
151 {
152 return iterator(begin_ + size_);
153 }
begin()154 constexpr const_iterator begin() const noexcept
155 {
156 return const_iterator(begin_);
157 }
end()158 constexpr const_iterator end() const noexcept
159 {
160 return const_iterator(begin_ + size_);
161 }
cbegin()162 constexpr const_iterator cbegin() const noexcept
163 {
164 return begin();
165 }
cend()166 constexpr const_iterator cend() const noexcept
167 {
168 return end();
169 }
170
171 private:
172 template<class U>
173 friend class array_view;
174
175 pointer begin_;
176 size_type size_;
177 pointer end_;
178 };
179
180 template<typename T, size_t N>
countof(T (&)[N])181 constexpr size_t countof(T (&)[N]) noexcept
182 {
183 return N;
184 }
185 template<typename T, size_t N>
arrayview(T (& arr)[N])186 constexpr array_view<T> arrayview(T (&arr)[N]) noexcept
187 {
188 return array_view<T>(arr, N);
189 }
190 // Returns a const uint8_t array_view of any object.
191 template<typename T>
arrayviewU8(const T & arr)192 constexpr array_view<const uint8_t> arrayviewU8(const T& arr) noexcept
193 {
194 return array_view(reinterpret_cast<const uint8_t*>(&arr), sizeof(arr));
195 }
196
197 #endif // API_BASE_CONTAINERS_ARRAYVIEW_H
198