From 8bb9ef822b69fdab6a504a721576fbc495c80b26 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Tue, 10 Dec 2013 13:28:31 +0100 Subject: [PATCH] Bug 493701 - part 1: add nsTObserverArray::BackwardIterator; r=bzbarsky --HG-- extra : rebase_source : cf37f9cf8ee8a4198741eea69d0fcedef64053fc --- xpcom/glue/nsTObserverArray.h | 44 ++++++++++++++++++++++++++++++ xpcom/tests/TestObserverArray.cpp | 45 ++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/xpcom/glue/nsTObserverArray.h b/xpcom/glue/nsTObserverArray.h index 92dc9d0e13f..9ed0ceaf7df 100644 --- a/xpcom/glue/nsTObserverArray.h +++ b/xpcom/glue/nsTObserverArray.h @@ -242,6 +242,11 @@ class nsAutoTObserverArray : protected nsTObserverArray_base { 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 { @@ -349,6 +354,45 @@ class nsAutoTObserverArray : protected nsTObserverArray_base { 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 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 mArray; }; diff --git a/xpcom/tests/TestObserverArray.cpp b/xpcom/tests/TestObserverArray.cpp index 8cd28745337..853e79deef5 100644 --- a/xpcom/tests/TestObserverArray.cpp +++ b/xpcom/tests/TestObserverArray.cpp @@ -131,8 +131,7 @@ int main(int argc, char **argv) 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); } @@ -140,7 +139,45 @@ int main(int argc, char **argv) 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; }