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 */ 26template<class T> 27class array_view { 28public: 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 36 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 81 constexpr array_view() noexcept : begin_(nullptr), size_(0), end_(nullptr) {} 82 constexpr array_view(pointer aBegin, pointer aEnd) noexcept : begin_(aBegin), size_(aEnd - aBegin), end_(aEnd) 83 { 84 assert(end_ >= begin_); 85 } 86 constexpr array_view(pointer aBegin, size_type aSize) noexcept : begin_(aBegin), size_(aSize), end_(aBegin + aSize) 87 {} 88 template<size_t 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>> 92 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>> 96 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>> 99 constexpr array_view(const U& container) noexcept : array_view(container.data(), container.size()) 100 {} 101 ~array_view() = default; 102 constexpr size_type size() const noexcept 103 { 104 return size_; 105 } 106 constexpr size_type size_bytes() const noexcept 107 { 108 return size_ * sizeof(T); 109 } 110 constexpr bool empty() const noexcept 111 { 112 return size_ == 0; 113 } 114 constexpr const_pointer data() const noexcept 115 { 116 return begin_; 117 } 118 constexpr pointer data() noexcept 119 { 120 return begin_; 121 } 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 } 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 } 146 constexpr iterator begin() noexcept 147 { 148 return iterator(begin_); 149 } 150 constexpr iterator end() noexcept 151 { 152 return iterator(begin_ + size_); 153 } 154 constexpr const_iterator begin() const noexcept 155 { 156 return const_iterator(begin_); 157 } 158 constexpr const_iterator end() const noexcept 159 { 160 return const_iterator(begin_ + size_); 161 } 162 constexpr const_iterator cbegin() const noexcept 163 { 164 return begin(); 165 } 166 constexpr const_iterator cend() const noexcept 167 { 168 return end(); 169 } 170 171private: 172 template<class U> 173 friend class array_view; 174 175 pointer begin_; 176 size_type size_; 177 pointer end_; 178}; 179 180template<typename T, size_t N> 181constexpr size_t countof(T (&)[N]) noexcept 182{ 183 return N; 184} 185template<typename T, size_t N> 186constexpr 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. 191template<typename T> 192constexpr 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