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
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /**
39 : * MODULE NOTES:
40 : *
41 : * The Deque is a very small, very efficient container object
42 : * than can hold elements of type void*, offering the following features:
43 : * Its interface supports pushing and popping of elements.
44 : * It can iterate (via an interator class) its elements.
45 : * When full, it can efficiently resize dynamically.
46 : *
47 : *
48 : * NOTE: The only bit of trickery here is that this deque is
49 : * built upon a ring-buffer. Like all ring buffers, the first
50 : * element may not be at index[0]. The mOrigin member determines
51 : * where the first child is. This point is quietly hidden from
52 : * customers of this class.
53 : *
54 : */
55 :
56 : #ifndef _NSDEQUE
57 : #define _NSDEQUE
58 :
59 : #include "nscore.h"
60 :
61 : /**
62 : * The nsDequeFunctor class is used when you want to create
63 : * callbacks between the deque and your generic code.
64 : * Use these objects in a call to ForEach();
65 : *
66 : */
67 :
68 4 : class nsDequeFunctor{
69 : public:
70 : virtual void* operator()(void* anObject)=0;
71 : };
72 :
73 : /******************************************************
74 : * Here comes the nsDeque class itself...
75 : ******************************************************/
76 :
77 : /**
78 : * The deque (double-ended queue) class is a common container type,
79 : * whose behavior mimics a line in your favorite checkout stand.
80 : * Classic CS describes the common behavior of a queue as FIFO.
81 : * A deque allows insertion and removal at both ends of
82 : * the container.
83 : *
84 : * The deque stores pointers to items.
85 : */
86 :
87 : class nsDequeIterator;
88 :
89 : class NS_COM_GLUE nsDeque {
90 : friend class nsDequeIterator;
91 : public:
92 : nsDeque(nsDequeFunctor* aDeallocator = nsnull);
93 : ~nsDeque();
94 :
95 : /**
96 : * Returns the number of elements currently stored in
97 : * this deque.
98 : *
99 : * @return number of elements currently in the deque
100 : */
101 1918118 : inline PRInt32 GetSize() const {return mSize;}
102 :
103 : /**
104 : * Appends new member at the end of the deque.
105 : *
106 : * @param item to store in deque
107 : * @return *this
108 : */
109 : nsDeque& Push(void* aItem);
110 :
111 : /**
112 : * Inserts new member at the front of the deque.
113 : *
114 : * @param item to store in deque
115 : * @return *this
116 : */
117 : nsDeque& PushFront(void* aItem);
118 :
119 : /**
120 : * Remove and return the last item in the container.
121 : *
122 : * @return the item that was the last item in container
123 : */
124 : void* Pop();
125 :
126 : /**
127 : * Remove and return the first item in the container.
128 : *
129 : * @return the item that was first item in container
130 : */
131 : void* PopFront();
132 :
133 : /**
134 : * Retrieve the bottom item without removing it.
135 : *
136 : * @return the first item in container
137 : */
138 :
139 : void* Peek();
140 : /**
141 : * Return topmost item without removing it.
142 : *
143 : * @return the first item in container
144 : */
145 : void* PeekFront();
146 :
147 : /**
148 : * Retrieve the i'th member from the deque without removing it.
149 : *
150 : * @param index of desired item
151 : * @return i'th element in list
152 : */
153 : void* ObjectAt(int aIndex) const;
154 :
155 : /**
156 : * Removes and returns the i'th member from the deque.
157 : *
158 : * @param index of desired item
159 : * @return the element which was removed
160 : */
161 : void* RemoveObjectAt(int aIndex);
162 :
163 : /**
164 : * Remove all items from container without destroying them.
165 : *
166 : * @return *this
167 : */
168 : nsDeque& Empty();
169 :
170 : /**
171 : * Remove and delete all items from container.
172 : * Deletes are handled by the deallocator nsDequeFunctor
173 : * which is specified at deque construction.
174 : *
175 : * @return *this
176 : */
177 : nsDeque& Erase();
178 :
179 : /**
180 : * Creates a new iterator, pointing to the first
181 : * item in the deque.
182 : *
183 : * @return new dequeIterator
184 : */
185 : nsDequeIterator Begin() const;
186 :
187 : /**
188 : * Creates a new iterator, pointing to the last
189 : * item in the deque.
190 : *
191 : * @return new dequeIterator
192 : */
193 : nsDequeIterator End() const;
194 :
195 : void* Last() const;
196 : /**
197 : * Call this method when you want to iterate all the
198 : * members of the container, passing a functor along
199 : * to call your code.
200 : *
201 : * @param aFunctor object to call for each member
202 : * @return *this
203 : */
204 : void ForEach(nsDequeFunctor& aFunctor) const;
205 :
206 : /**
207 : * Call this method when you want to iterate all the
208 : * members of the container, calling the functor you
209 : * passed with each member. This process will interrupt
210 : * if your function returns non 0 to this method.
211 : *
212 : * @param aFunctor object to call for each member
213 : * @return first nonzero result of aFunctor or 0.
214 : */
215 : const void* FirstThat(nsDequeFunctor& aFunctor) const;
216 :
217 : void SetDeallocator(nsDequeFunctor* aDeallocator);
218 :
219 : protected:
220 : PRInt32 mSize;
221 : PRInt32 mCapacity;
222 : PRInt32 mOrigin;
223 : nsDequeFunctor* mDeallocator;
224 : void* mBuffer[8];
225 : void** mData;
226 :
227 : private:
228 :
229 : /**
230 : * Copy constructor (PRIVATE)
231 : *
232 : * @param another deque
233 : */
234 : nsDeque(const nsDeque& other);
235 :
236 : /**
237 : * Deque assignment operator (PRIVATE)
238 : *
239 : * @param another deque
240 : * @return *this
241 : */
242 : nsDeque& operator=(const nsDeque& anOther);
243 :
244 : bool GrowCapacity();
245 : };
246 :
247 : /******************************************************
248 : * Here comes the nsDequeIterator class...
249 : ******************************************************/
250 :
251 : class NS_COM_GLUE nsDequeIterator {
252 : public:
253 : /**
254 : * DequeIterator is an object that knows how to iterate
255 : * (forward and backward) through a Deque. Normally,
256 : * you don't need to do this, but there are some special
257 : * cases where it is pretty handy.
258 : *
259 : * One warning: the iterator is not bound to an item,
260 : * it is bound to an index, so if you insert or remove
261 : * from the beginning while using an iterator
262 : * (which is not recommended) then the iterator will
263 : * point to a different item. @see GetCurrent()
264 : *
265 : * Here you go.
266 : *
267 : * @param aQueue is the deque object to be iterated
268 : * @param aIndex is the starting position for your iteration
269 : */
270 : nsDequeIterator(const nsDeque& aQueue, int aIndex=0);
271 :
272 : /**
273 : * Create a copy of a DequeIterator
274 : *
275 : * @param aCopy is another iterator to copy from
276 : */
277 : nsDequeIterator(const nsDequeIterator& aCopy);
278 :
279 : /**
280 : * Moves iterator to first element in the deque
281 : * @return *this
282 : */
283 : nsDequeIterator& First();
284 :
285 : /**
286 : * Standard assignment operator for dequeiterator
287 : * @param aCopy is another iterator to copy from
288 : * @return *this
289 : */
290 : nsDequeIterator& operator=(const nsDequeIterator& aCopy);
291 :
292 : /**
293 : * preform ! operation against two iterators to test for equivalence
294 : * (or lack thereof)!
295 : *
296 : * @param aIter is the object to be compared to
297 : * @return TRUE if NOT equal.
298 : */
299 : bool operator!=(nsDequeIterator& aIter);
300 :
301 : /**
302 : * Compare two iterators for increasing order.
303 : *
304 : * @param aIter is the other iterator to be compared to
305 : * @return TRUE if this object points to an element before
306 : * the element pointed to by aIter.
307 : * FALSE if this and aIter are not iterating over
308 : * the same deque.
309 : */
310 : bool operator<(nsDequeIterator& aIter);
311 :
312 : /**
313 : * Compare two iterators for equivalence.
314 : *
315 : * @param aIter is the other iterator to be compared to
316 : * @return TRUE if EQUAL
317 : */
318 : bool operator==(nsDequeIterator& aIter);
319 :
320 : /**
321 : * Compare two iterators for non strict decreasing order.
322 : *
323 : * @param aIter is the other iterator to be compared to
324 : * @return TRUE if this object points to the same element, or
325 : * an element after the element pointed to by aIter.
326 : * FALSE if this and aIter are not iterating over
327 : * the same deque.
328 : */
329 : bool operator>=(nsDequeIterator& aIter);
330 :
331 : /**
332 : * Pre-increment operator
333 : * Iterator will advance one index towards the end.
334 : *
335 : * @return object_at(++index)
336 : */
337 : void* operator++();
338 :
339 : /**
340 : * Post-increment operator
341 : * Iterator will advance one index towards the end.
342 : *
343 : * @param param is ignored
344 : * @return object_at(mIndex++)
345 : */
346 : void* operator++(int);
347 :
348 : /**
349 : * Pre-decrement operator
350 : * Iterator will advance one index towards the beginning.
351 : *
352 : * @return object_at(--index)
353 : */
354 : void* operator--();
355 :
356 : /**
357 : * Post-decrement operator
358 : * Iterator will advance one index towards the beginning.
359 : *
360 : * @param param is ignored
361 : * @return object_at(index--)
362 : */
363 : void* operator--(int);
364 :
365 : /**
366 : * Retrieve the the iterator's notion of current node.
367 : *
368 : * Note that the iterator floats, so you don't need to do:
369 : * <code>++iter; aDeque.PopFront();</code>
370 : * Unless you actually want your iterator to jump 2 positions
371 : * relative to its origin.
372 : *
373 : * Picture: [1 2i 3 4]
374 : * PopFront()
375 : * Picture: [2 3i 4]
376 : * Note that I still happily points to object at the second index.
377 : *
378 : * @return object at i'th index
379 : */
380 : void* GetCurrent();
381 :
382 : /**
383 : * Call this method when you want to iterate all the
384 : * members of the container, passing a functor along
385 : * to call your code.
386 : *
387 : * @param aFunctor object to call for each member
388 : * @return *this
389 : */
390 : void ForEach(nsDequeFunctor& aFunctor) const;
391 :
392 : /**
393 : * Call this method when you want to iterate all the
394 : * members of the container, calling the functor you
395 : * passed with each member. This process will interrupt
396 : * if your function returns non 0 to this method.
397 : *
398 : * @param aFunctor object to call for each member
399 : * @return first nonzero result of aFunctor or 0.
400 : */
401 : const void* FirstThat(nsDequeFunctor& aFunctor) const;
402 :
403 : protected:
404 :
405 : PRInt32 mIndex;
406 : const nsDeque& mDeque;
407 : };
408 : #endif
|