Bug 1322700 - Enable range-for with nsDeque - r?froydnj draft
authorGerald Squelart <gsquelart@mozilla.com>
Thu, 02 Feb 2017 12:28:35 +1100
changeset 469318 5603093ee9d80f06b3df767270f43e77f0ffd34a
parent 469305 8196774c6b8a858e5145524f4d250df8431ebc78
child 544159 37386b7888c11cb3f12771502d9a4a66ce092357
push id43684
push usergsquelart@mozilla.com
push dateThu, 02 Feb 2017 01:30:32 +0000
reviewersfroydnj
bugs1322700
milestone54.0a1
Bug 1322700 - Enable range-for with nsDeque - r?froydnj It's now possible to write: for (void* item : deque) { ... } MozReview-Commit-ID: FLoczCZd77y
xpcom/ds/nsDeque.h
xpcom/tests/gtest/TestNsDeque.cpp
--- 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();
+}