| // Copyright 2016 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 FBL_ARRAY_H_ |
| #define FBL_ARRAY_H_ |
| |
| #include <zircon/assert.h> |
| |
| #include <type_traits> |
| |
| #include <fbl/macros.h> |
| |
| namespace fbl { |
| |
| class AllocChecker; |
| |
| // |Array| is lightweight movable container that takes ownership of an array. |
| // At destruction or when reset() is invoked, it uses delete[] to release the owned array. |
| template <typename T> |
| class __OWNER(T) Array { |
| public: |
| constexpr Array() : ptr_(nullptr), count_(0U) {} |
| constexpr Array(decltype(nullptr)) : Array() {} |
| |
| Array(T* array, size_t count) : ptr_(array), count_(count) {} |
| |
| Array(Array&& other) : ptr_(nullptr), count_(other.count_) { ptr_ = other.release(); } |
| |
| // Move constructor allowing us to move from Array<T> to Array<const T> |
| template <typename OtherType> |
| Array(Array<OtherType>&& other) : ptr_(nullptr), count_(other.size()) { |
| static_assert(!std::is_const<OtherType>::value && std::is_same<const OtherType, T>::value); |
| |
| ptr_ = other.release(); |
| } |
| |
| size_t size() const { return count_; } |
| |
| bool empty() const { return size() == 0; } |
| |
| ~Array() { reset(); } |
| |
| Array& operator=(Array&& o) { |
| auto count = o.count_; |
| reset(o.release(), count); |
| return *this; |
| } |
| |
| // Move operator allowing us to move from Array<T> to Array<const T> |
| template <typename OtherType> |
| Array& operator=(Array<OtherType>&& o) { |
| static_assert(!std::is_const<OtherType>::value && std::is_same<const OtherType, T>::value); |
| |
| auto count = o.size(); |
| reset(o.release(), count); |
| return *this; |
| } |
| |
| // move semantics only |
| DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Array); |
| |
| T* release() { |
| T* t = ptr_; |
| ptr_ = nullptr; |
| count_ = 0; |
| return t; |
| } |
| |
| void reset() { reset(nullptr, 0U); } |
| |
| void reset(T* t, size_t count) { |
| T* ptr = ptr_; |
| ptr_ = t; |
| count_ = count; |
| delete[] ptr; |
| } |
| |
| void swap(Array& other) { |
| T* t = ptr_; |
| ptr_ = other.ptr_; |
| other.ptr_ = t; |
| size_t c = count_; |
| count_ = other.count_; |
| other.count_ = c; |
| } |
| |
| T* get() const { return ptr_; } |
| |
| T* data() const { return ptr_; } |
| |
| explicit operator bool() const { return static_cast<bool>(ptr_); } |
| |
| T& operator[](size_t i) const { |
| ZX_DEBUG_ASSERT(i < count_); |
| return ptr_[i]; |
| } |
| |
| T* begin() const { return ptr_; } |
| |
| T* end() const { return &ptr_[count_]; } |
| |
| private: |
| T* ptr_; |
| size_t count_; |
| }; |
| |
| // Allocate memory for an array of size `n`, default-constructing each element in the array. |
| // |
| // If the allocation fails, an array of size 0 is returned. |
| template <typename T> |
| Array<T> MakeArray(fbl::AllocChecker* ac, size_t n) { |
| auto* alloc = new (ac) T[n](); |
| if (unlikely(alloc == nullptr)) { |
| return Array<T>(); |
| } |
| return Array<T>(alloc, n); |
| } |
| |
| #ifndef _KERNEL |
| // Allocate memory for an array of size `n`. |
| template <typename T> |
| Array<T> MakeArray(size_t n) { |
| return Array<T>(new T[n](), n); |
| } |
| #endif |
| |
| } // namespace fbl |
| |
| #endif // FBL_ARRAY_H_ |