TLS and other features will need an array implementation. We can take the one from PHC rename it and move it to a new header file. Differential Revision: https://phabricator.services.mozilla.com/D279246
104 lines
2.6 KiB
C++
104 lines
2.6 KiB
C++
/* 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 */
|