On x86 compilers without fastcall, simulate it when invoking traces and un-simulate...
[wine-gecko.git] / xpcom / glue / nsTObserverArray.h
blob7d4ccb006c5201b2787575ce42a437b0eefc7843
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
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/
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.
15 * The Original Code is Mozilla.org code.
17 * The Initial Developer of the Original Code is Mozilla Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2006
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Jonas Sicking <jonas@sicking.cc> (Original Author)
23 * Daniel Witte <dwitte@stanford.edu>
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.
37 * ***** END LICENSE BLOCK ***** */
39 #ifndef nsTObserverArray_h___
40 #define nsTObserverArray_h___
42 #include "nsTArray.h"
44 class NS_COM_GLUE nsTObserverArray_base {
45 public:
46 typedef PRUint32 index_type;
47 typedef PRUint32 size_type;
48 typedef PRInt32 diff_type;
50 protected:
51 class Iterator_base {
52 protected:
53 friend class nsTObserverArray_base;
55 Iterator_base(index_type aPosition, Iterator_base* aNext)
56 : mPosition(aPosition),
57 mNext(aNext) {
60 // The current position of the iterator. Its exact meaning differs
61 // depending on iterator. See nsTObserverArray<T>::ForwardIterator.
62 index_type mPosition;
64 // The next iterator currently iterating the same array
65 Iterator_base* mNext;
68 nsTObserverArray_base()
69 : mIterators(nsnull) {
72 ~nsTObserverArray_base() {
73 NS_ASSERTION(mIterators == nsnull, "iterators outlasting array");
76 /**
77 * Adjusts iterators after an element has been inserted or removed
78 * from the array.
79 * @param modPos Position where elements were added or removed.
80 * @param adjustment -1 if an element was removed, 1 if an element was
81 * added.
83 void AdjustIterators(index_type aModPos, diff_type aAdjustment);
85 /**
86 * Clears iterators when the array is destroyed.
88 void ClearIterators();
90 mutable Iterator_base* mIterators;
93 /**
94 * An array of observers. Like a normal array, but supports iterators that are
95 * stable even if the array is modified during iteration.
96 * The template parameter T is the observer type the array will hold;
97 * N is the number of built-in storage slots that come with the array.
98 * NOTE: You probably want to use nsTObserverArray, unless you specifically
99 * want built-in storage. See below.
100 * @see nsTObserverArray, nsTArray
103 template<class T, PRUint32 N>
104 class nsAutoTObserverArray : protected nsTObserverArray_base {
105 public:
106 typedef T elem_type;
107 typedef nsTArray<T> array_type;
109 nsAutoTObserverArray() {
113 // Accessor methods
116 // @return The number of elements in the array.
117 size_type Length() const {
118 return mArray.Length();
121 // @return True if the array is empty or false otherwise.
122 PRBool IsEmpty() const {
123 return mArray.IsEmpty();
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 elem_type& ElementAt(index_type i) {
131 return mArray.ElementAt(i);
134 // Same as above, but readonly.
135 const elem_type& ElementAt(index_type i) const {
136 return mArray.ElementAt(i);
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);
148 // Same as above, but readonly.
149 const elem_type& SafeElementAt(index_type i, const elem_type& def) const {
150 return mArray.SafeElementAt(i, def);
154 // Search methods
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 PR_TRUE if the element was found.
162 template<class Item>
163 PRBool Contains(const Item& item) const {
164 return IndexOf(item) != array_type::NoIndex;
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 index_type IndexOf(const Item& item, index_type start = 0) const {
175 return mArray.IndexOf(item, start);
179 // Mutation methods
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 PR_TRUE if the element was found, or inserted successfully.
186 template<class Item>
187 PRBool PrependElementUnlessExists(const Item& item) {
188 return Contains(item) || mArray.InsertElementAt(0, item) != nsnull;
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 elem_type* AppendElement(const Item& item) {
196 return mArray.AppendElement(item);
199 // Same as above, but without copy-constructing. This is useful to avoid
200 // temporaries.
201 elem_type* AppendElement() {
202 return mArray.AppendElement();
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 PR_TRUE if the element was found, or inserted successfully.
209 template<class Item>
210 PRBool AppendElementUnlessExists(const Item& item) {
211 return Contains(item) || AppendElement(item) != nsnull;
214 // Remove an element from the array.
215 // @param index The index of the item to remove.
216 void RemoveElementAt(index_type index) {
217 NS_ASSERTION(index < mArray.Length(), "invalid index");
218 mArray.RemoveElementAt(index);
219 AdjustIterators(index, -1);
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 PR_TRUE if the element was found and removed.
227 template<class Item>
228 PRBool RemoveElement(const Item& item) {
229 index_type index = mArray.IndexOf(item, 0);
230 if (index == array_type::NoIndex)
231 return PR_FALSE;
233 mArray.RemoveElementAt(index);
234 AdjustIterators(index, -1);
235 return PR_TRUE;
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 void Clear() {
242 mArray.Clear();
243 ClearIterators();
247 // Iterators
250 // Base class for iterators. Do not use this directly.
251 class Iterator : public Iterator_base {
252 protected:
253 friend class nsAutoTObserverArray;
254 typedef nsAutoTObserverArray<T, N> array_type;
256 Iterator(index_type aPosition, const array_type& aArray)
257 : Iterator_base(aPosition, aArray.mIterators),
258 mArray(const_cast<array_type&>(aArray)) {
259 aArray.mIterators = this;
262 ~Iterator() {
263 NS_ASSERTION(mArray.mIterators == this,
264 "Iterators must currently be destroyed in opposite order "
265 "from the construction order. It is suggested that you "
266 "simply put them on the stack");
267 mArray.mIterators = mNext;
270 // The array we're iterating
271 array_type& mArray;
274 // Iterates the array forward from beginning to end. mPosition points
275 // to the element that will be returned on next call to GetNext.
276 // Elements:
277 // - prepended to the array during iteration *will not* be traversed
278 // - appended during iteration *will* be traversed
279 // - removed during iteration *will not* be traversed.
280 // @see EndLimitedIterator
281 class ForwardIterator : protected Iterator {
282 public:
283 typedef nsAutoTObserverArray<T, N> array_type;
284 typedef Iterator base_type;
286 ForwardIterator(const array_type& aArray)
287 : Iterator(0, aArray) {
290 ForwardIterator(const array_type& aArray, index_type aPos)
291 : Iterator(aPos, aArray) {
294 PRBool operator <(const ForwardIterator& aOther) const {
295 NS_ASSERTION(&this->mArray == &aOther.mArray,
296 "not iterating the same array");
297 return base_type::mPosition < aOther.mPosition;
300 // Returns PR_TRUE if there are more elements to iterate.
301 // This must precede a call to GetNext(). If PR_FALSE is
302 // returned, GetNext() must not be called.
303 PRBool HasMore() const {
304 return base_type::mPosition < base_type::mArray.Length();
307 // Returns the next element and steps one step. This must
308 // be preceded by a call to HasMore().
309 // @return The next observer.
310 elem_type& GetNext() {
311 NS_ASSERTION(HasMore(), "iterating beyond end of array");
312 return base_type::mArray.ElementAt(base_type::mPosition++);
316 // EndLimitedIterator works like ForwardIterator, but will not iterate new
317 // observers appended to the array after the iterator was created.
318 class EndLimitedIterator : protected ForwardIterator {
319 public:
320 typedef nsAutoTObserverArray<T, N> array_type;
321 typedef Iterator base_type;
323 EndLimitedIterator(const array_type& aArray)
324 : ForwardIterator(aArray),
325 mEnd(aArray, aArray.Length()) {
328 // Returns PR_TRUE if there are more elements to iterate.
329 // This must precede a call to GetNext(). If PR_FALSE is
330 // returned, GetNext() must not be called.
331 PRBool HasMore() const {
332 return *this < mEnd;
335 // Returns the next element and steps one step. This must
336 // be preceded by a call to HasMore().
337 // @return The next observer.
338 elem_type& GetNext() {
339 NS_ASSERTION(HasMore(), "iterating beyond end of array");
340 return base_type::mArray.ElementAt(base_type::mPosition++);
343 private:
344 ForwardIterator mEnd;
347 protected:
348 nsAutoTArray<T, N> mArray;
351 template<class T>
352 class nsTObserverArray : public nsAutoTObserverArray<T, 0> {
353 public:
354 typedef nsAutoTObserverArray<T, 0> base_type;
355 typedef nsTObserverArray_base::size_type size_type;
358 // Initialization methods
361 nsTObserverArray() {}
363 // Initialize this array and pre-allocate some number of elements.
364 explicit nsTObserverArray(size_type capacity) {
365 base_type::mArray.SetCapacity(capacity);
369 // XXXbz I wish I didn't have to pass in the observer type, but I
370 // don't see a way to get it out of array_.
371 // Note that this macro only works if the array holds pointers to XPCOM objects.
372 #define NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(array_, obstype_, func_, params_) \
373 PR_BEGIN_MACRO \
374 nsTObserverArray<obstype_ *>::ForwardIterator iter_(array_); \
375 nsCOMPtr<obstype_> obs_; \
376 while (iter_.HasMore()) { \
377 obs_ = iter_.GetNext(); \
378 obs_ -> func_ params_ ; \
380 PR_END_MACRO
382 #endif // nsTObserverArray_h___