/* * Copyright (C) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef API_BASE_CONTAINERS_ARRAYVIEW_H #define API_BASE_CONTAINERS_ARRAYVIEW_H #include <cassert> #include <cstdint> #include <iterator> #include <type_traits> /** @ingroup group_containers_arrayview */ /** Array view */ template<class T> class array_view { public: struct Iterator { using iterator_category = std::forward_iterator_tag; using difference_type = std::ptrdiff_t; using value_type = T; using pointer = T*; using reference = T&; Iterator(pointer ptr) : m_ptr(ptr) {} reference operator*() const { return *m_ptr; } pointer operator->() { return m_ptr; } Iterator& operator++() { m_ptr++; return *this; } Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; } friend bool operator==(const Iterator& a, const Iterator& b) { return a.m_ptr == b.m_ptr; }; friend bool operator!=(const Iterator& a, const Iterator& b) { return a.m_ptr != b.m_ptr; }; private: pointer m_ptr; }; using value_type = T; using difference_type = size_t; using pointer = value_type*; using reference = value_type&; using size_type = size_t; using const_reference = const value_type&; using const_pointer = const value_type*; using iterator = Iterator; using const_iterator = Iterator; constexpr array_view() noexcept : begin_(nullptr), size_(0), end_(nullptr) {} constexpr array_view(pointer aBegin, pointer aEnd) noexcept : begin_(aBegin), size_(aEnd - aBegin), end_(aEnd) { assert(end_ >= begin_); } constexpr array_view(pointer aBegin, size_type aSize) noexcept : begin_(aBegin), size_(aSize), end_(aBegin + aSize) {} template<size_t N> constexpr array_view(value_type (&arr)[N]) noexcept : begin_(arr), size_(N), end_(arr + N) {} template<class U, class = std::enable_if_t<std::is_same<std::remove_const_t<T>, U>::value>> explicit constexpr array_view(const array_view<U>& other) noexcept : begin_(other.begin_), size_(other.size_), end_(other.end_) {} template<class U, class = std::enable_if_t<std::is_same<std::remove_const_t<T>, typename U::value_type>::value>> explicit constexpr array_view(U& container) noexcept : array_view(container.data(), container.size()) {} template<class U, class = std::enable_if_t<std::is_same<std::remove_const_t<T>, typename U::value_type>::value>> explicit constexpr array_view(const U& container) noexcept : array_view(container.data(), container.size()) {} ~array_view() = default; constexpr size_type size() const noexcept { return size_; } constexpr size_type size_bytes() const noexcept { return size_ * sizeof(T); } constexpr bool empty() const noexcept { return size_ == 0; } constexpr const_pointer data() const noexcept { return begin_; } constexpr pointer data() noexcept { return begin_; } constexpr reference at(size_type aIndex) noexcept { // If index out-of-range, undefined behaviour on release builds, assert on debug builds. assert(aIndex < size()); return begin_[aIndex]; } constexpr const_reference at(size_type aIndex) const noexcept { // If index out-of-range, undefined behaviour on release builds, assert on debug builds. assert(aIndex < size()); return begin_[aIndex]; } constexpr reference operator[](size_type aIndex) { // If index out-of-range, undefined behaviour on release builds, assert on debug builds. assert(aIndex < size()); return begin_[aIndex]; } constexpr const_reference operator[](size_type aIndex) const { // If index out-of-range, undefined behaviour on release builds, assert on debug builds. assert(aIndex < size()); return begin_[aIndex]; } constexpr iterator begin() noexcept { return iterator(begin_); } constexpr iterator end() noexcept { return iterator(begin_ + size_); } constexpr const_iterator begin() const noexcept { return const_iterator(begin_); } constexpr const_iterator end() const noexcept { return const_iterator(begin_ + size_); } constexpr const_iterator cbegin() const noexcept { return begin(); } constexpr const_iterator cend() const noexcept { return end(); } private: template<class U> friend class array_view; pointer begin_; size_type size_; pointer end_; }; template<typename T, size_t N> constexpr size_t countof(T (&)[N]) noexcept { return N; } template<typename T, size_t N> constexpr array_view<T> arrayview(T (&arr)[N]) noexcept { return array_view<T>(arr, N); } // Returns a const uint8_t array_view of any object. template<typename T> constexpr array_view<const uint8_t> arrayviewU8(const T& arr) noexcept { return array_view(reinterpret_cast<const uint8_t*>(&arr), sizeof(arr)); } #endif // API_BASE_CONTAINERS_ARRAYVIEW_H