| // Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef SRC_LIB_CONTAINERS_CPP_ARRAY_VIEW_H_ | |
| #define SRC_LIB_CONTAINERS_CPP_ARRAY_VIEW_H_ | |
| #include <cstddef> | |
| #include <iterator> | |
| #include <vector> | |
| #include "src/lib/containers/cpp/ownership.h" | |
| namespace containers { | |
| // This is like a std::string_view but for array data. It attempts to have the same API as | |
| // std::vector without owning the underlying buffer. | |
| // | |
| // The recommended way to pass an array_view to a function is by value. It consists of two pointer | |
| // which is normally more efficient to push on the stack directly than to push one pointer that | |
| // points to two other pointers. | |
| template <typename T> | |
| class __POINTER(T) array_view { | |
| public: | |
| using value_type = T; | |
| using size_type = std::size_t; | |
| using difference_type = std::ptrdiff_t; | |
| using reference = T&; | |
| using const_reference = const T&; | |
| using pointer = T*; | |
| using const_pointer = const T*; | |
| using iterator = const T*; | |
| using const_iterator = const T*; | |
| using reverse_iterator = std::reverse_iterator<iterator>; | |
| using const_reverse_iterator = std::reverse_iterator<const_iterator>; | |
| static constexpr size_t npos = static_cast<size_t>(-1); | |
| array_view() : begin_(nullptr), end_(nullptr) {} | |
| array_view(const T* begin, const T* end) : begin_(begin), end_(end) {} | |
| array_view(const T* begin, size_t size) : begin_(begin), end_(begin + size) {} | |
| array_view(const std::vector<T>& vect) | |
| : begin_(vect.empty() ? nullptr : &vect[0]), | |
| end_(vect.empty() ? nullptr : &vect[0] + vect.size()) {} | |
| const T& operator[](size_t i) const { return begin_[i]; } | |
| const T* data() const { return begin_; } | |
| const T& front() const { return *begin_; }; | |
| const T& back() const { return *(end_ - 1); } | |
| const T* begin() const { return begin_; } | |
| const T* end() const { return end_; } | |
| const_reverse_iterator rbegin() const { return std::reverse_iterator(end()); } | |
| const_reverse_iterator rend() const { return std::reverse_iterator(begin()); } | |
| const T* cbegin() const { return begin_; } | |
| const T* cend() const { return end_; } | |
| const_reverse_iterator crbegin() const { return std::reverse_iterator(end()); } | |
| const_reverse_iterator crend() const { return std::reverse_iterator(begin()); } | |
| bool empty() const { return begin_ == end_; } | |
| size_t size() const { return end_ - begin_; } | |
| // subview() has the same variants and behaves the same as std::string::substr(). | |
| array_view<T> subview(size_t pos = 0, size_t count = npos) const { | |
| const T* new_begin; | |
| const T* new_end; | |
| if (pos < size()) { | |
| new_begin = &begin_[pos]; | |
| if (count == npos || pos + count > size()) | |
| new_end = end_; | |
| else | |
| new_end = &begin_[pos + count]; | |
| } else { | |
| new_begin = nullptr; | |
| new_end = nullptr; | |
| } | |
| return array_view<T>(new_begin, new_end); | |
| } | |
| private: | |
| const T* begin_ = nullptr; | |
| const T* end_ = nullptr; | |
| }; | |
| } // namespace containers | |
| #endif // SRC_LIB_CONTAINERS_CPP_ARRAY_VIEW_H_ |