1 /*
2 * Copyright (c) 2024 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 <cstddef>
21 #include <cstdint>
22
23 #include <base/containers/iterator.h>
24 #include <base/containers/type_traits.h>
25 #include <base/namespace.h>
26 #include <base/util/hash.h>
27 #include <base/util/log.h>
28
BASE_BEGIN_NAMESPACE()29 BASE_BEGIN_NAMESPACE()
30 /** @ingroup group_containers_arrayview */
31 /** Array view */
32 template<class T>
33 class array_view {
34 public:
35 using value_type = T;
36 using difference_type = ptrdiff_t;
37 using pointer = value_type*;
38 using reference = value_type&;
39
40 using size_type = size_t;
41 using const_reference = const value_type&;
42 using const_pointer = const value_type*;
43
44 using iterator = BASE_NS::iterator<array_view<T>>;
45 using const_iterator = BASE_NS::const_iterator<array_view<T>>;
46
47 constexpr array_view() noexcept : begin_(nullptr), size_(0) {}
48 constexpr array_view(pointer begin, pointer end) noexcept
49 : begin_(begin), size_(static_cast<size_type>(end - begin))
50 {
51 BASE_ASSERT(end >= begin);
52 }
53 constexpr array_view(pointer begin, size_type aSize) noexcept : begin_(begin), size_(aSize) {}
54 template<size_t N>
55 constexpr array_view(value_type (&arr)[N]) noexcept : begin_(arr), size_(N)
56 {}
57 template<class U, class = enable_if_t<is_same<remove_const_t<T>, U>::value>>
58 constexpr array_view(const array_view<U>& other) noexcept : begin_(other.begin_), size_(other.size_)
59 {}
60 template<class U, class = enable_if_t<is_same<remove_const_t<T>, typename U::value_type>::value>>
61 constexpr array_view(U& container) noexcept : array_view(container.data(), container.size())
62 {}
63 template<class U, class = enable_if_t<is_same<remove_const_t<T>, typename U::value_type>::value>>
64 constexpr array_view(const U& container) noexcept : array_view(container.data(), container.size())
65 {}
66 ~array_view() = default;
67 constexpr size_type size() const noexcept
68 {
69 return size_;
70 }
71 constexpr size_type size_bytes() const noexcept
72 {
73 return size_ * sizeof(T);
74 }
75 constexpr bool empty() const noexcept
76 {
77 return size_ == 0;
78 }
79 constexpr const_pointer data() const noexcept
80 {
81 return begin_;
82 }
83 constexpr pointer data() noexcept
84 {
85 return begin_;
86 }
87 constexpr reference at(size_type aIndex) noexcept
88 {
89 // If index out-of-range, undefined behaviour on release builds, assert on debug builds.
90 BASE_ASSERT(aIndex < size());
91 return begin_[aIndex];
92 }
93 constexpr const_reference at(size_type aIndex) const noexcept
94 {
95 // If index out-of-range, undefined behaviour on release builds, assert on debug builds.
96 BASE_ASSERT(aIndex < size());
97 return begin_[aIndex];
98 }
99 constexpr reference operator[](size_type aIndex)
100 {
101 // If index out-of-range, undefined behaviour on release builds, assert on debug builds.
102 BASE_ASSERT(aIndex < size());
103 return begin_[aIndex];
104 }
105 constexpr const_reference operator[](size_type aIndex) const
106 {
107 // If index out-of-range, undefined behaviour on release builds, assert on debug builds.
108 BASE_ASSERT(aIndex < size());
109 return begin_[aIndex];
110 }
111 constexpr iterator begin() noexcept
112 {
113 return iterator(begin_);
114 }
115 constexpr iterator end() noexcept
116 {
117 return iterator(begin_ + size_);
118 }
119 constexpr const_iterator begin() const noexcept
120 {
121 return const_iterator(begin_);
122 }
123 constexpr const_iterator end() const noexcept
124 {
125 return const_iterator(begin_ + size_);
126 }
127 constexpr const_iterator cbegin() const noexcept
128 {
129 return begin();
130 }
131 constexpr const_iterator cend() const noexcept
132 {
133 return end();
134 }
135
136 private:
137 template<class U>
138 friend class array_view;
139
140 pointer begin_;
141 size_type size_;
142 };
143
144 template<typename T, size_t N>
arrayview(T (& arr)[N])145 constexpr array_view<T> arrayview(T (&arr)[N]) noexcept
146 {
147 return array_view<T>(arr, N);
148 }
149 // Returns a const uint8_t array_view of any object.
150 template<typename T>
arrayviewU8(const T & arr)151 constexpr array_view<const uint8_t> arrayviewU8(const T& arr) noexcept
152 {
153 return array_view(reinterpret_cast<const uint8_t*>(&arr), sizeof(arr));
154 }
155
156 template<typename T>
hash(const array_view<T> & view)157 inline uint64_t hash(const array_view<T>& view)
158 {
159 return FNV1aHash(view.data(), view.size());
160 }
161 BASE_END_NAMESPACE()
162
163 #endif // API_BASE_CONTAINERS_ARRAYVIEW_H
164