Bug 493701 - part 1: add nsTObserverArray::BackwardIterator; r=bzbarsky
authorArpad Borsos <arpad.borsos@googlemail.com>
Tue, 10 Dec 2013 13:28:31 +0100
changeset 180765 154fb9a9e0bca82352b76893d86f3ad419067816
parent 180764 dc3c5febcdaf772160d20975dc15335cab834fcd
child 180766 f615a0532971b0671eea443dcd95558b3bdd3fd0
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersbzbarsky
bugs493701
milestone31.0a1
Bug 493701 - part 1: add nsTObserverArray::BackwardIterator; r=bzbarsky
xpcom/glue/nsTObserverArray.h
xpcom/tests/TestObserverArray.cpp
--- a/xpcom/glue/nsTObserverArray.h
+++ b/xpcom/glue/nsTObserverArray.h
@@ -237,16 +237,21 @@ class nsAutoTObserverArray : protected n
     // Removes all observers and collapses all iterators to the beginning of
     // the array. The result is that forward iterators will see all elements
     // in the array.
     void Clear() {
       mArray.Clear();
       ClearIterators();
     }
 
+    // Compact the array to minimize the memory it uses
+    void Compact() {
+      mArray.Compact();
+    }
+
     // Returns the number of bytes on the heap taken up by this object, not
     // including sizeof(*this).
     size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
       return mArray.SizeOfExcludingThis(mallocSizeOf);
     }
 
     //
     // Iterators
@@ -344,16 +349,55 @@ class nsAutoTObserverArray : protected n
           NS_ASSERTION(HasMore(), "iterating beyond end of array");
           return base_type::mArray.ElementAt(base_type::mPosition++);
         }
 
       private:
         ForwardIterator mEnd;
     };
 
+    // Iterates the array backward from end to start. mPosition points
+    // to the element that was returned last.
+    // Elements:
+    // - prepended to the array during iteration *will* be traversed,
+    //   unless the iteration already arrived at the first element
+    // - appended during iteration *will not* be traversed
+    // - removed during iteration *will not* be traversed.
+    class BackwardIterator : protected Iterator {
+      public:
+        typedef nsAutoTObserverArray<T, N> array_type;
+        typedef Iterator                   base_type;
+
+        BackwardIterator(const array_type& aArray)
+          : Iterator(aArray.Length(), aArray) {
+        }
+
+        // Returns true if there are more elements to iterate.
+        // This must precede a call to GetNext(). If false is
+        // returned, GetNext() must not be called.
+        bool HasMore() const {
+          return base_type::mPosition > 0;
+        }
+
+        // Returns the next element and steps one step. This must
+        // be preceded by a call to HasMore().
+        // @return The next observer.
+        elem_type& GetNext() {
+          NS_ASSERTION(HasMore(), "iterating beyond start of array");
+          return base_type::mArray.ElementAt(--base_type::mPosition);
+        }
+
+        // Removes the element at the current iterator position.
+        // (the last element returned from |GetNext()|)
+        // This will not affect the next call to |GetNext()|
+        void Remove() {
+          return base_type::mArray.RemoveElementAt(base_type::mPosition);
+        }
+    };
+
   protected:
     nsAutoTArray<T, N> mArray;
 };
 
 template<class T>
 class nsTObserverArray : public nsAutoTObserverArray<T, 0> {
   public:
     typedef nsAutoTObserverArray<T, 0>       base_type;
--- a/xpcom/tests/TestObserverArray.cpp
+++ b/xpcom/tests/TestObserverArray.cpp
@@ -126,21 +126,58 @@ int main(int argc, char **argv)
   // Prepends
   arr.PrependElementUnlessExists(3);
   static int test19Expected[] = { 3, 4, 7, 2, 8 };
   DO_TEST(ForwardIterator, test19Expected, { /* nothing */ });
 
   arr.PrependElementUnlessExists(7);
   DO_TEST(ForwardIterator, test19Expected, { /* nothing */ });
 
-  // Commented out because it fails; bug 474369 will fix
-  /*  DO_TEST(ForwardIterator, test19Expected,
+  DO_TEST(ForwardIterator, test19Expected,
           if (count == 1) {
             arr.PrependElementUnlessExists(9);
           }
           );
 
   static int test22Expected[] = { 9, 3, 4, 7, 2, 8 };
   DO_TEST(ForwardIterator, test22Expected, { });
-  */
-  
+
+  // BackwardIterator
+  static int test23Expected[] = { 8, 2, 7, 4, 3, 9 };
+  DO_TEST(BackwardIterator, test23Expected, );
+
+  // Removals
+  static int test24Expected[] = { 8, 2, 7, 4, 9 };
+  DO_TEST(BackwardIterator, test24Expected,
+          if (count == 1) arr.RemoveElementAt(1);
+          );
+
+  // Appends
+  DO_TEST(BackwardIterator, test24Expected,
+          if (count == 1) arr.AppendElement(1);
+          );
+
+  static int test26Expected[] = { 1, 8, 2, 7, 4, 9 };
+  DO_TEST(BackwardIterator, test26Expected, );
+
+  // Prepends
+  static int test27Expected[] = { 1, 8, 2, 7, 4, 9, 3 };
+  DO_TEST(BackwardIterator, test27Expected,
+          if (count == 1) arr.PrependElementUnlessExists(3);
+          );
+
+  // Removal using Iterator
+  DO_TEST(BackwardIterator, test27Expected,
+          if (count == 1) iter.Remove();
+          );
+
+  static int test28Expected[] = { 1, 8, 2, 7, 4, 3 };
+  DO_TEST(BackwardIterator, test28Expected, );
+
+  /**
+   * Note: _code is executed before the call to GetNext(), it can therefore not
+   * test the case of prepending when the BackwardIterator already returned the
+   * first element.
+   * In that case BackwardIterator does not traverse the newly prepended Element
+   */
+
   return rv;
 }