/* 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 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(sizeof(T)) * aCapacity; MOZ_ASSERT(size_bytes.isValid()); if (!size_bytes.isValid()) { return false; } mArray = reinterpret_cast(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(sizeof(T)) * aNewCapacity; MOZ_ASSERT(size_bytes.isValid()); if (!size_bytes.isValid()) { return false; } T* new_array = reinterpret_cast(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 */