Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef BASEARRAY_H
#define BASEARRAY_H
#include "BaseAlloc.h"
#include "mozilla/Assertions.h"
#include "mozilla/CheckedInt.h"
//---------------------------------------------------------------------------
// Array implementation
//---------------------------------------------------------------------------
// Unlike mfbt/Array.h this array has a dynamic size, but unlike a vector its
// size is set explicitly rather than grown as needed.
// It uses the base allocator to allocate / free, shrink and grow its
// storage.
template <typename T>
class BaseArray {
private:
size_t mCapacity = 0;
T* mArray = nullptr;
public:
BaseArray() {}
~BaseArray() {
for (size_t i = 0; i < mCapacity; i++) {
mArray[i].~T();
}
sBaseAlloc.free(mArray);
}
const T& operator[](size_t aIndex) const {
MOZ_ASSERT(aIndex < mCapacity);
return mArray[aIndex];
}
T& operator[](size_t aIndex) {
MOZ_ASSERT(aIndex < mCapacity);
return mArray[aIndex];
}
T* begin() { return mArray; }
const T* begin() const { return mArray; }
const T* end() const { return &mArray[mCapacity]; }
bool Init(size_t aCapacity) {
MOZ_ASSERT(mCapacity == 0);
MOZ_ASSERT(mArray == nullptr);
auto size_bytes = mozilla::CheckedInt<size_t>(sizeof(T)) * aCapacity;
MOZ_ASSERT(size_bytes.isValid());
if (!size_bytes.isValid()) {
return false;
}
mArray = reinterpret_cast<T*>(sBaseAlloc.alloc(size_bytes.value()));
if (!mArray) {
return false;
}
for (size_t i = 0; i < aCapacity; i++) {
new (&mArray[i]) T();
}
mCapacity = aCapacity;
return true;
}
size_t Capacity() const { return mCapacity; }
bool GrowTo(size_t aNewCapacity) {
MOZ_ASSERT(aNewCapacity > mCapacity);
if (mCapacity == 0) {
return Init(aNewCapacity);
}
auto size_bytes = mozilla::CheckedInt<size_t>(sizeof(T)) * aNewCapacity;
MOZ_ASSERT(size_bytes.isValid());
if (!size_bytes.isValid()) {
return false;
}
T* new_array =
reinterpret_cast<T*>(sBaseAlloc.realloc(mArray, size_bytes.value()));
if (!new_array) {
return false;
}
mArray = new_array;
for (size_t i = mCapacity; i < aNewCapacity; i++) {
new (&mArray[i]) T();
}
mCapacity = aNewCapacity;
return true;
}
size_t SizeOfExcludingThis() { return sBaseAlloc.usable_size(mArray); }
};
#endif /* ! BASEARRAY_H */