Bug 1562789 - SmallPointerArray should support moves, and have an IsEmpty() helper. r=froydnj
This also implicitly deletes its copy-assignment operator and copy-constructor, which is great since it's a huge footgun. Differential Revision: https://phabricator.services.mozilla.com/D36549
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#define mozilla_SmallPointerArray_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
@@ -19,7 +20,7 @@
|
||||
namespace mozilla {
|
||||
|
||||
// Array class for situations where a small number of NON-NULL elements (<= 2)
|
||||
// is expected, a large number of elements must be accomodated if necessary,
|
||||
// is expected, a large number of elements must be accommodated if necessary,
|
||||
// and the size of the class must be minimal. Typical vector implementations
|
||||
// will fulfill the first two requirements by simply adding inline storage
|
||||
// alongside the rest of their member variables. While this strategy works,
|
||||
@@ -49,6 +50,17 @@ class SmallPointerArray {
|
||||
}
|
||||
}
|
||||
|
||||
SmallPointerArray(SmallPointerArray&& aOther) {
|
||||
PodCopy(mArray, aOther.mArray, 2);
|
||||
aOther.mArray[0].mValue = nullptr;
|
||||
aOther.mArray[1].mVector = nullptr;
|
||||
}
|
||||
|
||||
SmallPointerArray& operator=(SmallPointerArray&& aOther) {
|
||||
std::swap(mArray, aOther.mArray);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
if (first()) {
|
||||
first() = nullptr;
|
||||
@@ -160,6 +172,8 @@ class SmallPointerArray {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IsEmpty() const { return Length() == 0; }
|
||||
|
||||
T* ElementAt(size_t aIndex) const {
|
||||
MOZ_ASSERT(aIndex < Length());
|
||||
if (first()) {
|
||||
|
||||
@@ -192,8 +192,46 @@ void TestRangeBasedLoops() {
|
||||
MOZ_RELEASE_ASSERT(entries == 0);
|
||||
}
|
||||
|
||||
void TestMove() {
|
||||
using namespace mozilla;
|
||||
|
||||
SmallPointerArray<void> testArray;
|
||||
testArray.AppendElement(PTR1);
|
||||
testArray.AppendElement(PTR2);
|
||||
|
||||
SmallPointerArray<void> moved = std::move(testArray);
|
||||
|
||||
MOZ_RELEASE_ASSERT(testArray.IsEmpty());
|
||||
MOZ_RELEASE_ASSERT(moved.Length() == 2);
|
||||
MOZ_RELEASE_ASSERT(moved[0] == PTR1);
|
||||
MOZ_RELEASE_ASSERT(moved[1] == PTR2);
|
||||
|
||||
// Heap case.
|
||||
moved.AppendElement(PTR3);
|
||||
|
||||
SmallPointerArray<void> another = std::move(moved);
|
||||
|
||||
MOZ_RELEASE_ASSERT(testArray.IsEmpty());
|
||||
MOZ_RELEASE_ASSERT(moved.IsEmpty());
|
||||
MOZ_RELEASE_ASSERT(another.Length() == 3);
|
||||
MOZ_RELEASE_ASSERT(another[0] == PTR1);
|
||||
MOZ_RELEASE_ASSERT(another[1] == PTR2);
|
||||
MOZ_RELEASE_ASSERT(another[2] == PTR3);
|
||||
|
||||
// Move assignment.
|
||||
testArray = std::move(another);
|
||||
|
||||
MOZ_RELEASE_ASSERT(moved.IsEmpty());
|
||||
MOZ_RELEASE_ASSERT(another.IsEmpty());
|
||||
MOZ_RELEASE_ASSERT(testArray.Length() == 3);
|
||||
MOZ_RELEASE_ASSERT(testArray[0] == PTR1);
|
||||
MOZ_RELEASE_ASSERT(testArray[1] == PTR2);
|
||||
MOZ_RELEASE_ASSERT(testArray[2] == PTR3);
|
||||
}
|
||||
|
||||
int main() {
|
||||
TestArrayManipulation();
|
||||
TestRangeBasedLoops();
|
||||
TestMove();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user