Bug 1322700 - Enable range-for with nsDeque - r?froydnj
It's now possible to write:
for (void* item : deque) { ... }
MozReview-Commit-ID: FLoczCZd77y
--- a/xpcom/ds/nsDeque.h
+++ b/xpcom/ds/nsDeque.h
@@ -54,18 +54,16 @@ public:
* whose behavior mimics a line in your favorite checkout stand.
* Classic CS describes the common behavior of a queue as FIFO.
* A deque allows insertion and removal at both ends of
* the container.
*
* The deque stores pointers to items.
*/
-class nsDequeIterator;
-
class nsDeque
{
typedef mozilla::fallible_t fallible_t;
public:
explicit nsDeque(nsDequeFunctor* aDeallocator = nullptr);
~nsDeque();
/**
@@ -151,16 +149,31 @@ public:
* Call this method when you want to iterate all the
* members of the container, passing a functor along
* to call your code.
*
* @param aFunctor object to call for each member
*/
void ForEach(nsDequeFunctor& aFunctor) const;
+ class ConstIterator
+ {
+ public:
+ ConstIterator(const nsDeque& aDeque, size_t aIndex) : mDeque(aDeque), mIndex(aIndex) { }
+ ConstIterator& operator++() { ++mIndex; return *this; }
+ bool operator==(const ConstIterator& aOther) const { return mIndex == aOther.mIndex; }
+ bool operator!=(const ConstIterator& aOther) const { return mIndex != aOther.mIndex; }
+ void* operator*() const { return mDeque.ObjectAt(mIndex); }
+ private:
+ const nsDeque& mDeque;
+ size_t mIndex;
+ };
+ ConstIterator begin() const { return ConstIterator(*this, 0); }
+ ConstIterator end() const { return ConstIterator(*this, mSize); }
+
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
protected:
size_t mSize;
size_t mCapacity;
size_t mOrigin;
nsDequeFunctor* mDeallocator;
--- a/xpcom/tests/gtest/TestNsDeque.cpp
+++ b/xpcom/tests/gtest/TestNsDeque.cpp
@@ -8,79 +8,79 @@
#include "nsDeque.h"
#include "nsCRT.h"
#include <stdio.h>
/**************************************************************
Now define the token deallocator class...
**************************************************************/
namespace TestNsDeque {
-
- class _Dealloc: public nsDequeFunctor
+
+ class _Dealloc: public nsDequeFunctor
{
virtual void* operator()(void* aObject) {
return 0;
}
};
- static bool VerifyContents(const nsDeque& aDeque, const int* aContents, size_t aLength)
+ static bool VerifyContents(const nsDeque& aDeque, const int* aContents, size_t aLength)
{
for (size_t i=0; i<aLength; ++i) {
if (*(int*)aDeque.ObjectAt(i) != aContents[i]) {
return false;
}
}
return true;
}
class Deallocator: public nsDequeFunctor
{
- virtual void* operator()(void* aObject)
+ virtual void* operator()(void* aObject)
{
- if (aObject)
+ if (aObject)
{
// Set value to -1, to use in test function.
*((int*)aObject) = -1;
}
return nullptr;
}
};
class ForEachAdder: public nsDequeFunctor
{
- virtual void* operator()(void* aObject)
+ virtual void* operator()(void* aObject)
{
- if (aObject)
+ if (aObject)
{
sum += *(int*)aObject;
}
return aObject;
}
private:
int sum = 0;
-
+
public:
int GetSum() { return sum; }
-
+
};
}
using namespace TestNsDeque;
TEST(NsDeque, OriginalTest)
{
const size_t size = 200;
int ints[size];
size_t i=0;
int temp;
nsDeque theDeque(new _Dealloc); //construct a simple one...
-
+
// ints = [0...199]
for (i=0;i<size;i++) { //initialize'em
ints[i]=static_cast<int>(i);
}
// queue = [0...69]
for (i=0;i<70;i++) {
theDeque.Push(&ints[i]);
temp=*(int*)theDeque.Peek();
@@ -307,17 +307,17 @@ TEST(NsDeque,TestEraseShouldCallDealloca
*(testArray[i]) = i;
d.Push((void*)testArray[i]);
}
d.Erase();
// Now check it again.
CheckIfQueueEmpty(d);
-
+
for (size_t i=0; i < NumTestValues; i++)
{
EXPECT_EQ(-1, *(testArray[i])) << "Erase should call deallocator: " << *(testArray[i]);
}
}
TEST(NsDeque, TestForEach)
{
@@ -335,8 +335,32 @@ TEST(NsDeque, TestForEach)
}
ForEachAdder adder;
d.ForEach(adder);
EXPECT_EQ(sum, adder.GetSum()) << "For each should iterate over values";
d.Erase();
}
+
+TEST(NsDeque, TestRangeFor)
+{
+ nsDeque d(new Deallocator());
+ const size_t NumTestValues = 8;
+ int sum = 0;
+
+ int* testArray[NumTestValues];
+ for (size_t i=0; i < NumTestValues; i++)
+ {
+ testArray[i] = new int();
+ *(testArray[i]) = i;
+ sum += i;
+ d.Push((void*)testArray[i]);
+ }
+
+ int added = 0;
+ for (void* ob : d) {
+ added += *(int*)ob;
+ }
+ EXPECT_EQ(sum, added) << "Range-for should iterate over values";
+
+ d.Erase();
+}