blob: 0a1fc08a0c549a8f00c991c006d3b7a59c3f2d20 [file] [log] [blame]
// 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_