LCOV - code coverage report
Current view: directory - objdir/dist/include - nsTObserverArray.h (source / functions) Found Hit Coverage
Test: app.info Lines: 86 80 93.0 %
Date: 2012-06-02 Functions: 207 134 64.7 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2006
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Jonas Sicking <jonas@sicking.cc> (Original Author)
      23                 :  *   Daniel Witte <dwitte@stanford.edu>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #ifndef nsTObserverArray_h___
      40                 : #define nsTObserverArray_h___
      41                 : 
      42                 : #include "nsTArray.h"
      43                 : 
      44                 : /**
      45                 :  * An array of observers. Like a normal array, but supports iterators that are
      46                 :  * stable even if the array is modified during iteration.
      47                 :  * The template parameter T is the observer type the array will hold;
      48                 :  * N is the number of built-in storage slots that come with the array.
      49                 :  * NOTE: You probably want to use nsTObserverArray, unless you specifically
      50                 :  * want built-in storage. See below.
      51                 :  * @see nsTObserverArray, nsTArray
      52                 :  */
      53                 : 
      54                 : class NS_COM_GLUE nsTObserverArray_base {
      55                 :   public:
      56                 :     typedef PRUint32 index_type;
      57                 :     typedef PRUint32 size_type;
      58                 :     typedef PRInt32  diff_type;
      59                 : 
      60                 :   protected:
      61                 :     class Iterator_base {
      62                 :       protected:
      63                 :         friend class nsTObserverArray_base;
      64                 : 
      65          385871 :         Iterator_base(index_type aPosition, Iterator_base* aNext)
      66                 :           : mPosition(aPosition),
      67          385871 :             mNext(aNext) {
      68          385871 :         }
      69                 : 
      70                 :         // The current position of the iterator. Its exact meaning differs
      71                 :         // depending on iterator. See nsTObserverArray<T>::ForwardIterator.
      72                 :         index_type mPosition;
      73                 : 
      74                 :         // The next iterator currently iterating the same array
      75                 :         Iterator_base* mNext;
      76                 :     };
      77                 : 
      78           17871 :     nsTObserverArray_base()
      79           17871 :       : mIterators(nsnull) {
      80           17871 :     }
      81                 : 
      82           17852 :     ~nsTObserverArray_base() {
      83           17852 :       NS_ASSERTION(mIterators == nsnull, "iterators outlasting array");
      84           17852 :     }
      85                 : 
      86                 :     /**
      87                 :      * Adjusts iterators after an element has been inserted or removed
      88                 :      * from the array.
      89                 :      * @param modPos     Position where elements were added or removed.
      90                 :      * @param adjustment -1 if an element was removed, 1 if an element was
      91                 :      *                   added.
      92                 :      */
      93                 :     void AdjustIterators(index_type aModPos, diff_type aAdjustment);
      94                 : 
      95                 :     /**
      96                 :      * Clears iterators when the array is destroyed.
      97                 :      */
      98                 :     void ClearIterators();
      99                 : 
     100                 :     mutable Iterator_base* mIterators;
     101                 : };
     102                 : 
     103                 : template<class T, PRUint32 N>
     104           17852 : class nsAutoTObserverArray : protected nsTObserverArray_base {
     105                 :   public:
     106                 :     typedef T           elem_type;
     107                 :     typedef nsTArray<T> array_type;
     108                 : 
     109           17871 :     nsAutoTObserverArray() {
     110           17871 :     }
     111                 : 
     112                 :     //
     113                 :     // Accessor methods
     114                 :     //
     115                 : 
     116                 :     // @return The number of elements in the array.
     117         1120645 :     size_type Length() const {
     118         1120645 :       return mArray.Length();
     119                 :     }
     120                 : 
     121                 :     // @return True if the array is empty or false otherwise.
     122          639331 :     bool IsEmpty() const {
     123          639331 :       return mArray.IsEmpty();
     124                 :     }
     125                 : 
     126                 :     // This method provides direct access to the i'th element of the array.
     127                 :     // The given index must be within the array bounds.
     128                 :     // @param i  The index of an element in the array.
     129                 :     // @return   A reference to the i'th element of the array.
     130          387681 :     elem_type& ElementAt(index_type i) {
     131          387681 :       return mArray.ElementAt(i);
     132                 :     }
     133                 : 
     134                 :     // Same as above, but readonly.
     135               0 :     const elem_type& ElementAt(index_type i) const {
     136               0 :       return mArray.ElementAt(i);
     137                 :     }
     138                 : 
     139                 :     // This method provides direct access to the i'th element of the array in
     140                 :     // a bounds safe manner. If the requested index is out of bounds the
     141                 :     // provided default value is returned.
     142                 :     // @param i  The index of an element in the array.
     143                 :     // @param def The value to return if the index is out of bounds.
     144                 :     elem_type& SafeElementAt(index_type i, elem_type& def) {
     145                 :       return mArray.SafeElementAt(i, def);
     146                 :     }
     147                 : 
     148                 :     // Same as above, but readonly.
     149               0 :     const elem_type& SafeElementAt(index_type i, const elem_type& def) const {
     150               0 :       return mArray.SafeElementAt(i, def);
     151                 :     }
     152                 : 
     153                 :     //
     154                 :     // Search methods
     155                 :     //
     156                 : 
     157                 :     // This method searches, starting from the beginning of the array,
     158                 :     // for the first element in this array that is equal to the given element.
     159                 :     // 'operator==' must be defined for elem_type.
     160                 :     // @param item   The item to search for.
     161                 :     // @return       true if the element was found.
     162                 :     template<class Item>
     163            3186 :     bool Contains(const Item& item) const {
     164            3186 :       return IndexOf(item) != array_type::NoIndex;
     165                 :     }
     166                 : 
     167                 :     // This method searches for the offset of the first element in this
     168                 :     // array that is equal to the given element.
     169                 :     // 'operator==' must be defined for elem_type.
     170                 :     // @param item   The item to search for.
     171                 :     // @param start  The index to start from.
     172                 :     // @return       The index of the found element or NoIndex if not found.
     173                 :     template<class Item>
     174            9571 :     index_type IndexOf(const Item& item, index_type start = 0) const {
     175            9571 :       return mArray.IndexOf(item, start);
     176                 :     }
     177                 : 
     178                 :     //
     179                 :     // Mutation methods
     180                 :     //
     181                 : 
     182                 :     // Prepend an element to the array unless it already exists in the array.
     183                 :     // 'operator==' must be defined for elem_type.
     184                 :     // @param item   The item to prepend.
     185                 :     // @return       true if the element was found, or inserted successfully.
     186                 :     template<class Item>
     187            1275 :     bool PrependElementUnlessExists(const Item& item) {
     188            1275 :       return Contains(item) || mArray.InsertElementAt(0, item) != nsnull;
     189                 :     }
     190                 : 
     191                 :     // Append an element to the array.
     192                 :     // @param item   The item to append.
     193                 :     // @return A pointer to the newly appended element, or null on OOM.
     194                 :     template<class Item>
     195            8303 :     elem_type* AppendElement(const Item& item) {
     196            8303 :       return mArray.AppendElement(item);
     197                 :     }
     198                 : 
     199                 :     // Same as above, but without copy-constructing. This is useful to avoid
     200                 :     // temporaries.
     201            4584 :     elem_type* AppendElement() {
     202            4584 :       return mArray.AppendElement();
     203                 :     }
     204                 : 
     205                 :     // Append an element to the array unless it already exists in the array.
     206                 :     // 'operator==' must be defined for elem_type.
     207                 :     // @param item   The item to append.
     208                 :     // @return       true if the element was found, or inserted successfully.
     209                 :     template<class Item>
     210              29 :     bool AppendElementUnlessExists(const Item& item) {
     211              29 :       return Contains(item) || AppendElement(item) != nsnull;
     212                 :     }
     213                 : 
     214                 :     // Remove an element from the array.
     215                 :     // @param index  The index of the item to remove.
     216              34 :     void RemoveElementAt(index_type index) {
     217              34 :       NS_ASSERTION(index < mArray.Length(), "invalid index");
     218              34 :       mArray.RemoveElementAt(index);
     219              34 :       AdjustIterators(index, -1);
     220              34 :     }
     221                 : 
     222                 :     // This helper function combines IndexOf with RemoveElementAt to "search
     223                 :     // and destroy" the first element that is equal to the given element.
     224                 :     // 'operator==' must be defined for elem_type.
     225                 :     // @param item  The item to search for.
     226                 :     // @return true if the element was found and removed.
     227                 :     template<class Item>
     228            9064 :     bool RemoveElement(const Item& item) {
     229            9064 :       index_type index = mArray.IndexOf(item, 0);
     230            9064 :       if (index == array_type::NoIndex)
     231            2200 :         return false;
     232                 : 
     233            6864 :       mArray.RemoveElementAt(index);
     234            6864 :       AdjustIterators(index, -1);
     235            6864 :       return true;
     236                 :     }
     237                 : 
     238                 :     // Removes all observers and collapses all iterators to the beginning of
     239                 :     // the array. The result is that forward iterators will see all elements
     240                 :     // in the array.
     241           15132 :     void Clear() {
     242           15132 :       mArray.Clear();
     243           15132 :       ClearIterators();
     244           15132 :     }
     245                 : 
     246                 :     // Returns the number of bytes on the heap taken up by this object, not
     247                 :     // including sizeof(*this).
     248               0 :     size_t SizeOfExcludingThis(nsMallocSizeOfFun mallocSizeOf) const {
     249               0 :       return mArray.SizeOfExcludingThis(mallocSizeOf);
     250                 :     }
     251                 : 
     252                 :     //
     253                 :     // Iterators
     254                 :     //
     255                 : 
     256                 :     // Base class for iterators. Do not use this directly.
     257                 :     class Iterator : public Iterator_base {
     258                 :       protected:
     259                 :         friend class nsAutoTObserverArray;
     260                 :         typedef nsAutoTObserverArray<T, N> array_type;
     261                 : 
     262          385871 :         Iterator(index_type aPosition, const array_type& aArray)
     263                 :           : Iterator_base(aPosition, aArray.mIterators),
     264          385871 :             mArray(const_cast<array_type&>(aArray)) {
     265          385871 :           aArray.mIterators = this;
     266          385871 :         }
     267                 : 
     268          385871 :         ~Iterator() {
     269          385871 :           NS_ASSERTION(mArray.mIterators == this,
     270                 :                        "Iterators must currently be destroyed in opposite order "
     271                 :                        "from the construction order. It is suggested that you "
     272                 :                        "simply put them on the stack");
     273          385871 :           mArray.mIterators = mNext;
     274          385871 :         }
     275                 : 
     276                 :         // The array we're iterating
     277                 :         array_type& mArray;
     278                 :     };
     279                 : 
     280                 :     // Iterates the array forward from beginning to end. mPosition points
     281                 :     // to the element that will be returned on next call to GetNext.
     282                 :     // Elements:
     283                 :     // - prepended to the array during iteration *will not* be traversed
     284                 :     // - appended during iteration *will* be traversed
     285                 :     // - removed during iteration *will not* be traversed.
     286                 :     // @see EndLimitedIterator
     287          385871 :     class ForwardIterator : protected Iterator {
     288                 :       public:
     289                 :         typedef nsAutoTObserverArray<T, N> array_type;
     290                 :         typedef Iterator                   base_type;
     291                 : 
     292          377637 :         ForwardIterator(const array_type& aArray)
     293          377637 :           : Iterator(0, aArray) {
     294          377637 :         }
     295                 : 
     296            8234 :         ForwardIterator(const array_type& aArray, index_type aPos)
     297            8234 :           : Iterator(aPos, aArray) {
     298            8234 :         }
     299                 : 
     300           36392 :         bool operator <(const ForwardIterator& aOther) const {
     301           36392 :           NS_ASSERTION(&this->mArray == &aOther.mArray,
     302                 :                        "not iterating the same array");
     303           36392 :           return base_type::mPosition < aOther.mPosition;
     304                 :         }
     305                 : 
     306                 :         // Returns true if there are more elements to iterate.
     307                 :         // This must precede a call to GetNext(). If false is
     308                 :         // returned, GetNext() must not be called.
     309         1105663 :         bool HasMore() const {
     310         1105663 :           return base_type::mPosition < base_type::mArray.Length();
     311                 :         }
     312                 : 
     313                 :         // Returns the next element and steps one step. This must
     314                 :         // be preceded by a call to HasMore().
     315                 :         // @return The next observer.
     316          368125 :         elem_type& GetNext() {
     317          368125 :           NS_ASSERTION(HasMore(), "iterating beyond end of array");
     318          368125 :           return base_type::mArray.ElementAt(base_type::mPosition++);
     319                 :         }
     320                 :     };
     321                 : 
     322                 :     // EndLimitedIterator works like ForwardIterator, but will not iterate new
     323                 :     // observers appended to the array after the iterator was created.
     324            8234 :     class EndLimitedIterator : protected ForwardIterator {
     325                 :       public:
     326                 :         typedef nsAutoTObserverArray<T, N> array_type;
     327                 :         typedef Iterator                   base_type;
     328                 : 
     329            8234 :         EndLimitedIterator(const array_type& aArray)
     330                 :           : ForwardIterator(aArray),
     331            8234 :             mEnd(aArray, aArray.Length()) {
     332            8234 :         }
     333                 : 
     334                 :         // Returns true if there are more elements to iterate.
     335                 :         // This must precede a call to GetNext(). If false is
     336                 :         // returned, GetNext() must not be called.
     337           36392 :         bool HasMore() const {
     338           36392 :           return *this < mEnd;
     339                 :         }
     340                 : 
     341                 :         // Returns the next element and steps one step. This must
     342                 :         // be preceded by a call to HasMore().
     343                 :         // @return The next observer.
     344           14078 :         elem_type& GetNext() {
     345           14078 :           NS_ASSERTION(HasMore(), "iterating beyond end of array");
     346           14078 :           return base_type::mArray.ElementAt(base_type::mPosition++);
     347                 :         }
     348                 : 
     349                 :       private:
     350                 :         ForwardIterator mEnd;
     351                 :     };
     352                 : 
     353                 :   protected:
     354                 :     nsAutoTArray<T, N> mArray;
     355                 : };
     356                 : 
     357                 : template<class T>
     358            7170 : class nsTObserverArray : public nsAutoTObserverArray<T, 0> {
     359                 :   public:
     360                 :     typedef nsAutoTObserverArray<T, 0>       base_type;
     361                 :     typedef nsTObserverArray_base::size_type size_type;
     362                 : 
     363                 :     //
     364                 :     // Initialization methods
     365                 :     //
     366                 : 
     367            7176 :     nsTObserverArray() {}
     368                 : 
     369                 :     // Initialize this array and pre-allocate some number of elements.
     370                 :     explicit nsTObserverArray(size_type capacity) {
     371                 :       base_type::mArray.SetCapacity(capacity);
     372                 :     }
     373                 : };
     374                 : 
     375                 : // XXXbz I wish I didn't have to pass in the observer type, but I
     376                 : // don't see a way to get it out of array_.
     377                 : // Note that this macro only works if the array holds pointers to XPCOM objects.
     378                 : #define NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(array_, obstype_, func_, params_) \
     379                 :   PR_BEGIN_MACRO                                                             \
     380                 :     nsTObserverArray<obstype_ *>::ForwardIterator iter_(array_);             \
     381                 :     nsCOMPtr<obstype_> obs_;                                                 \
     382                 :     while (iter_.HasMore()) {                                                 \
     383                 :       obs_ = iter_.GetNext();                                                \
     384                 :       obs_ -> func_ params_ ;                                                \
     385                 :     }                                                                        \
     386                 :   PR_END_MACRO
     387                 : 
     388                 : // Note that this macro only works if the array holds pointers to XPCOM objects.
     389                 : #define NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(array_, obstype_, func_, params_) \
     390                 :   PR_BEGIN_MACRO                                                             \
     391                 :     nsTObserverArray<obstype_ *>::ForwardIterator iter_(array_);             \
     392                 :     obstype_* obs_;                                                          \
     393                 :     while (iter_.HasMore()) {                                                \
     394                 :       obs_ = iter_.GetNext();                                                \
     395                 :       obs_ -> func_ params_ ;                                                \
     396                 :     }                                                                        \
     397                 :   PR_END_MACRO
     398                 : #endif // nsTObserverArray_h___

Generated by: LCOV version 1.7