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