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