| // 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_ |