xpcom/glue/nsDeque.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsDeque.h"
michael@0 7 #include "nsISupportsImpl.h"
michael@0 8 #include <string.h>
michael@0 9 #ifdef DEBUG_rickg
michael@0 10 #include <stdio.h>
michael@0 11 #endif
michael@0 12
michael@0 13 /**
michael@0 14 * 07/02/2001 09:17p 509,104 clangref.pdf from openwatcom's site
michael@0 15 * Watcom C Language Reference Edition 11.0c
michael@0 16 * page 118 of 297
michael@0 17 *
michael@0 18 * The % symbol yields the remainder from the division of the first operand
michael@0 19 * by the second operand. The operands of % must have integral type.
michael@0 20 *
michael@0 21 * When both operands of % are positive, the result is a positive value
michael@0 22 * smaller than the second operand. When one or both operands is negative,
michael@0 23 * whether the result is positive or negative is implementation-defined.
michael@0 24 *
michael@0 25 */
michael@0 26 /* Ok, so first of all, C is underspecified. joy.
michael@0 27 * The following functions do not provide a correct implementation of modulus
michael@0 28 * They provide functionality for x>-y.
michael@0 29 * There are risks of 2*y being greater than max int, which is part of the
michael@0 30 * reason no multiplication is used and other operations are avoided.
michael@0 31 *
michael@0 32 * modasgn
michael@0 33 * @param x variable
michael@0 34 * @param y expression
michael@0 35 * approximately equivalent to x %= y
michael@0 36 *
michael@0 37 * modulus
michael@0 38 * @param x expression
michael@0 39 * @param y expression
michael@0 40 * approximately equivalent to x % y
michael@0 41 */
michael@0 42 #define modasgn(x,y) if (x<0) x+=y; x%=y
michael@0 43 #define modulus(x,y) ((x<0)?(x+y)%(y):(x)%(y))
michael@0 44
michael@0 45 /**
michael@0 46 * Standard constructor
michael@0 47 * @param deallocator, called by Erase and ~nsDeque
michael@0 48 */
michael@0 49 nsDeque::nsDeque(nsDequeFunctor* aDeallocator) {
michael@0 50 MOZ_COUNT_CTOR(nsDeque);
michael@0 51 mDeallocator=aDeallocator;
michael@0 52 mOrigin=mSize=0;
michael@0 53 mData=mBuffer; // don't allocate space until you must
michael@0 54 mCapacity=sizeof(mBuffer)/sizeof(mBuffer[0]);
michael@0 55 memset(mData, 0, mCapacity*sizeof(mBuffer[0]));
michael@0 56 }
michael@0 57
michael@0 58 /**
michael@0 59 * Destructor
michael@0 60 */
michael@0 61 nsDeque::~nsDeque() {
michael@0 62 MOZ_COUNT_DTOR(nsDeque);
michael@0 63
michael@0 64 #ifdef DEBUG_rickg
michael@0 65 char buffer[30];
michael@0 66 printf("Capacity: %i\n", mCapacity);
michael@0 67
michael@0 68 static int mCaps[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
michael@0 69 switch(mCapacity) {
michael@0 70 case 4: mCaps[0]++; break;
michael@0 71 case 8: mCaps[1]++; break;
michael@0 72 case 16: mCaps[2]++; break;
michael@0 73 case 32: mCaps[3]++; break;
michael@0 74 case 64: mCaps[4]++; break;
michael@0 75 case 128: mCaps[5]++; break;
michael@0 76 case 256: mCaps[6]++; break;
michael@0 77 case 512: mCaps[7]++; break;
michael@0 78 case 1024: mCaps[8]++; break;
michael@0 79 case 2048: mCaps[9]++; break;
michael@0 80 case 4096: mCaps[10]++; break;
michael@0 81 default:
michael@0 82 break;
michael@0 83 }
michael@0 84 #endif
michael@0 85
michael@0 86 Erase();
michael@0 87 if (mData && (mData!=mBuffer)) {
michael@0 88 free(mData);
michael@0 89 }
michael@0 90 mData=0;
michael@0 91 SetDeallocator(0);
michael@0 92 }
michael@0 93
michael@0 94 size_t nsDeque::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
michael@0 95 size_t size = 0;
michael@0 96 if (mData != mBuffer) {
michael@0 97 size += aMallocSizeOf(mData);
michael@0 98 }
michael@0 99
michael@0 100 if (mDeallocator) {
michael@0 101 size += aMallocSizeOf(mDeallocator);
michael@0 102 }
michael@0 103
michael@0 104 return size;
michael@0 105 }
michael@0 106
michael@0 107 size_t nsDeque::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
michael@0 108 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
michael@0 109 }
michael@0 110
michael@0 111 /**
michael@0 112 * Set the functor to be called by Erase()
michael@0 113 * The deque owns the functor.
michael@0 114 *
michael@0 115 * @param aDeallocator functor object for use by Erase()
michael@0 116 */
michael@0 117 void nsDeque::SetDeallocator(nsDequeFunctor* aDeallocator){
michael@0 118 delete mDeallocator;
michael@0 119 mDeallocator=aDeallocator;
michael@0 120 }
michael@0 121
michael@0 122 /**
michael@0 123 * Remove all items from container without destroying them.
michael@0 124 */
michael@0 125 void nsDeque::Empty() {
michael@0 126 if (mSize && mData) {
michael@0 127 memset(mData, 0, mCapacity*sizeof(mData));
michael@0 128 }
michael@0 129 mSize=0;
michael@0 130 mOrigin=0;
michael@0 131 }
michael@0 132
michael@0 133 /**
michael@0 134 * Remove and delete all items from container
michael@0 135 */
michael@0 136 void nsDeque::Erase() {
michael@0 137 if (mDeallocator && mSize) {
michael@0 138 ForEach(*mDeallocator);
michael@0 139 }
michael@0 140 Empty();
michael@0 141 }
michael@0 142
michael@0 143 /**
michael@0 144 * This method quadruples the size of the deque
michael@0 145 * Elements in the deque are resequenced so that elements
michael@0 146 * in the deque are stored sequentially
michael@0 147 *
michael@0 148 * @return whether growing succeeded
michael@0 149 */
michael@0 150 bool nsDeque::GrowCapacity() {
michael@0 151 int32_t theNewSize=mCapacity<<2;
michael@0 152 NS_ASSERTION(theNewSize>mCapacity, "Overflow");
michael@0 153 if (theNewSize<=mCapacity)
michael@0 154 return false;
michael@0 155 void** temp=(void**)malloc(theNewSize * sizeof(void*));
michael@0 156 if (!temp)
michael@0 157 return false;
michael@0 158
michael@0 159 //Here's the interesting part: You can't just move the elements
michael@0 160 //directly (in situ) from the old buffer to the new one.
michael@0 161 //Since capacity has changed, the old origin doesn't make
michael@0 162 //sense anymore. It's better to resequence the elements now.
michael@0 163
michael@0 164 memcpy(temp, mData + mOrigin, sizeof(void*) * (mCapacity - mOrigin));
michael@0 165 memcpy(temp + (mCapacity - mOrigin), mData, sizeof(void*) * mOrigin);
michael@0 166
michael@0 167 if (mData != mBuffer) {
michael@0 168 free(mData);
michael@0 169 }
michael@0 170
michael@0 171 mCapacity=theNewSize;
michael@0 172 mOrigin=0; //now realign the origin...
michael@0 173 mData=temp;
michael@0 174
michael@0 175 return true;
michael@0 176 }
michael@0 177
michael@0 178 /**
michael@0 179 * This method adds an item to the end of the deque.
michael@0 180 * This operation has the potential to cause the
michael@0 181 * underlying buffer to resize.
michael@0 182 *
michael@0 183 * @param aItem: new item to be added to deque
michael@0 184 */
michael@0 185 bool nsDeque::Push(void* aItem, const fallible_t&) {
michael@0 186 if (mSize==mCapacity && !GrowCapacity()) {
michael@0 187 return false;
michael@0 188 }
michael@0 189 mData[modulus(mOrigin + mSize, mCapacity)]=aItem;
michael@0 190 mSize++;
michael@0 191 return true;
michael@0 192 }
michael@0 193
michael@0 194 /**
michael@0 195 * This method adds an item to the front of the deque.
michael@0 196 * This operation has the potential to cause the
michael@0 197 * underlying buffer to resize.
michael@0 198 *
michael@0 199 * --Commments for GrowCapacity() case
michael@0 200 * We've grown and shifted which means that the old
michael@0 201 * final element in the deque is now the first element
michael@0 202 * in the deque. This is temporary.
michael@0 203 * We haven't inserted the new element at the front.
michael@0 204 *
michael@0 205 * To continue with the idea of having the front at zero
michael@0 206 * after a grow, we move the old final item (which through
michael@0 207 * the voodoo of mOrigin-- is now the first) to its final
michael@0 208 * position which is conveniently the old length.
michael@0 209 *
michael@0 210 * Note that this case only happens when the deque is full.
michael@0 211 * [And that pieces of this magic only work if the deque is full.]
michael@0 212 * picture:
michael@0 213 * [ABCDEFGH] @[mOrigin:3]:D.
michael@0 214 * Task: PushFront("Z")
michael@0 215 * shift mOrigin so, @[mOrigin:2]:C
michael@0 216 * stretch and rearrange: (mOrigin:0)
michael@0 217 * [CDEFGHAB ________ ________ ________]
michael@0 218 * copy: (The second C is currently out of bounds)
michael@0 219 * [CDEFGHAB C_______ ________ ________]
michael@0 220 * later we will insert Z:
michael@0 221 * [ZDEFGHAB C_______ ________ ________]
michael@0 222 * and increment size: 9. (C is no longer out of bounds)
michael@0 223 * --
michael@0 224 * @param aItem: new item to be added to deque
michael@0 225 */
michael@0 226 bool nsDeque::PushFront(void* aItem, const fallible_t&) {
michael@0 227 mOrigin--;
michael@0 228 modasgn(mOrigin,mCapacity);
michael@0 229 if (mSize==mCapacity) {
michael@0 230 if (!GrowCapacity()) {
michael@0 231 return false;
michael@0 232 }
michael@0 233 /* Comments explaining this are above*/
michael@0 234 mData[mSize]=mData[mOrigin];
michael@0 235 }
michael@0 236 mData[mOrigin]=aItem;
michael@0 237 mSize++;
michael@0 238 return true;
michael@0 239 }
michael@0 240
michael@0 241 /**
michael@0 242 * Remove and return the last item in the container.
michael@0 243 *
michael@0 244 * @return ptr to last item in container
michael@0 245 */
michael@0 246 void* nsDeque::Pop() {
michael@0 247 void* result=0;
michael@0 248 if (mSize>0) {
michael@0 249 --mSize;
michael@0 250 int32_t offset=modulus(mSize + mOrigin, mCapacity);
michael@0 251 result=mData[offset];
michael@0 252 mData[offset]=0;
michael@0 253 if (!mSize) {
michael@0 254 mOrigin=0;
michael@0 255 }
michael@0 256 }
michael@0 257 return result;
michael@0 258 }
michael@0 259
michael@0 260 /**
michael@0 261 * This method gets called you want to remove and return
michael@0 262 * the first member in the container.
michael@0 263 *
michael@0 264 * @return last item in container
michael@0 265 */
michael@0 266 void* nsDeque::PopFront() {
michael@0 267 void* result=0;
michael@0 268 if (mSize>0) {
michael@0 269 NS_ASSERTION(mOrigin < mCapacity, "Error: Bad origin");
michael@0 270 result=mData[mOrigin];
michael@0 271 mData[mOrigin++]=0; //zero it out for debugging purposes.
michael@0 272 mSize--;
michael@0 273 // Cycle around if we pop off the end
michael@0 274 // and reset origin if when we pop the last element
michael@0 275 if (mCapacity==mOrigin || !mSize) {
michael@0 276 mOrigin=0;
michael@0 277 }
michael@0 278 }
michael@0 279 return result;
michael@0 280 }
michael@0 281
michael@0 282 /**
michael@0 283 * This method gets called you want to peek at the bottom
michael@0 284 * member without removing it.
michael@0 285 *
michael@0 286 * @return last item in container
michael@0 287 */
michael@0 288 void* nsDeque::Peek() {
michael@0 289 void* result=0;
michael@0 290 if (mSize>0) {
michael@0 291 result = mData[modulus(mSize - 1 + mOrigin, mCapacity)];
michael@0 292 }
michael@0 293 return result;
michael@0 294 }
michael@0 295
michael@0 296 /**
michael@0 297 * This method gets called you want to peek at the topmost
michael@0 298 * member without removing it.
michael@0 299 *
michael@0 300 * @return last item in container
michael@0 301 */
michael@0 302 void* nsDeque::PeekFront() {
michael@0 303 void* result=0;
michael@0 304 if (mSize>0) {
michael@0 305 result=mData[mOrigin];
michael@0 306 }
michael@0 307 return result;
michael@0 308 }
michael@0 309
michael@0 310 /**
michael@0 311 * Call this to retrieve the ith element from this container.
michael@0 312 * Keep in mind that accessing the underlying elements is
michael@0 313 * done in a relative fashion. Object 0 is not necessarily
michael@0 314 * the first element (the first element is at mOrigin).
michael@0 315 *
michael@0 316 * @param aIndex : 0 relative offset of item you want
michael@0 317 * @return void* or null
michael@0 318 */
michael@0 319 void* nsDeque::ObjectAt(int32_t aIndex) const {
michael@0 320 void* result=0;
michael@0 321 if ((aIndex>=0) && (aIndex<mSize)) {
michael@0 322 result=mData[modulus(mOrigin + aIndex, mCapacity)];
michael@0 323 }
michael@0 324 return result;
michael@0 325 }
michael@0 326
michael@0 327 void* nsDeque::RemoveObjectAt(int32_t aIndex) {
michael@0 328 if ((aIndex<0) || (aIndex>=mSize)) {
michael@0 329 return 0;
michael@0 330 }
michael@0 331 void* result=mData[modulus(mOrigin + aIndex, mCapacity)];
michael@0 332
michael@0 333 // "Shuffle down" all elements in the array by 1, overwritting the element
michael@0 334 // being removed.
michael@0 335 for (int32_t i=aIndex; i<mSize; i++) {
michael@0 336 mData[modulus(mOrigin + i, mCapacity)] = mData[modulus(mOrigin + i + 1, mCapacity)];
michael@0 337 }
michael@0 338 mSize--;
michael@0 339
michael@0 340 return result;
michael@0 341 }
michael@0 342
michael@0 343 /**
michael@0 344 * Create and return an iterator pointing to
michael@0 345 * the beginning of the queue. Note that this
michael@0 346 * takes the circular buffer semantics into account.
michael@0 347 *
michael@0 348 * @return new deque iterator, init'ed to 1st item
michael@0 349 */
michael@0 350 nsDequeIterator nsDeque::Begin() const{
michael@0 351 return nsDequeIterator(*this, 0);
michael@0 352 }
michael@0 353
michael@0 354 /**
michael@0 355 * Create and return an iterator pointing to
michael@0 356 * the last item in the deque.
michael@0 357 * Note that this takes the circular buffer semantics
michael@0 358 * into account.
michael@0 359 *
michael@0 360 * @return new deque iterator, init'ed to the last item
michael@0 361 */
michael@0 362 nsDequeIterator nsDeque::End() const{
michael@0 363 return nsDequeIterator(*this, mSize - 1);
michael@0 364 }
michael@0 365
michael@0 366 void* nsDeque::Last() const {
michael@0 367 return End().GetCurrent();
michael@0 368 }
michael@0 369
michael@0 370 /**
michael@0 371 * Call this method when you want to iterate all the
michael@0 372 * members of the container, passing a functor along
michael@0 373 * to call your code.
michael@0 374 *
michael@0 375 * @param aFunctor object to call for each member
michael@0 376 * @return *this
michael@0 377 */
michael@0 378 void nsDeque::ForEach(nsDequeFunctor& aFunctor) const{
michael@0 379 for (int32_t i=0; i<mSize; i++) {
michael@0 380 aFunctor(ObjectAt(i));
michael@0 381 }
michael@0 382 }
michael@0 383
michael@0 384 /**
michael@0 385 * Call this method when you want to iterate all the
michael@0 386 * members of the container, calling the functor you
michael@0 387 * passed with each member. This process will interrupt
michael@0 388 * if your function returns non 0 to this method.
michael@0 389 *
michael@0 390 * @param aFunctor object to call for each member
michael@0 391 * @return first nonzero result of aFunctor or 0.
michael@0 392 */
michael@0 393 const void* nsDeque::FirstThat(nsDequeFunctor& aFunctor) const{
michael@0 394 for (int32_t i=0; i<mSize; i++) {
michael@0 395 void* obj=aFunctor(ObjectAt(i));
michael@0 396 if (obj) {
michael@0 397 return obj;
michael@0 398 }
michael@0 399 }
michael@0 400 return 0;
michael@0 401 }
michael@0 402
michael@0 403 /******************************************************
michael@0 404 * Here comes the nsDequeIterator class...
michael@0 405 ******************************************************/
michael@0 406
michael@0 407 /**
michael@0 408 * DequeIterator is an object that knows how to iterate (forward and backward)
michael@0 409 * through a Deque. Normally, you don't need to do this, but there are some special
michael@0 410 * cases where it is pretty handy, so here you go.
michael@0 411 *
michael@0 412 * This is a standard dequeiterator constructor
michael@0 413 *
michael@0 414 * @param aQueue is the deque object to be iterated
michael@0 415 * @param aIndex is the starting position for your iteration
michael@0 416 */
michael@0 417 nsDequeIterator::nsDequeIterator(const nsDeque& aQueue, int aIndex)
michael@0 418 : mIndex(aIndex),
michael@0 419 mDeque(aQueue)
michael@0 420 {
michael@0 421 }
michael@0 422
michael@0 423 /**
michael@0 424 * Create a copy of a DequeIterator
michael@0 425 *
michael@0 426 * @param aCopy is another iterator to copy from
michael@0 427 */
michael@0 428 nsDequeIterator::nsDequeIterator(const nsDequeIterator& aCopy)
michael@0 429 : mIndex(aCopy.mIndex),
michael@0 430 mDeque(aCopy.mDeque)
michael@0 431 {
michael@0 432 }
michael@0 433
michael@0 434 /**
michael@0 435 * Moves iterator to first element in deque
michael@0 436 * @return *this
michael@0 437 */
michael@0 438 nsDequeIterator& nsDequeIterator::First(){
michael@0 439 mIndex=0;
michael@0 440 return *this;
michael@0 441 }
michael@0 442
michael@0 443 /**
michael@0 444 * Standard assignment operator for dequeiterator
michael@0 445 *
michael@0 446 * @param aCopy is an iterator to be copied from
michael@0 447 * @return *this
michael@0 448 */
michael@0 449 nsDequeIterator& nsDequeIterator::operator=(const nsDequeIterator& aCopy) {
michael@0 450 NS_ASSERTION(&mDeque==&aCopy.mDeque,"you can't change the deque that an interator is iterating over, sorry.");
michael@0 451 mIndex=aCopy.mIndex;
michael@0 452 return *this;
michael@0 453 }
michael@0 454
michael@0 455 /**
michael@0 456 * preform ! operation against to iterators to test for equivalence
michael@0 457 * (or lack thereof)!
michael@0 458 *
michael@0 459 * @param aIter is the object to be compared to
michael@0 460 * @return TRUE if NOT equal.
michael@0 461 */
michael@0 462 bool nsDequeIterator::operator!=(nsDequeIterator& aIter) {
michael@0 463 return bool(!this->operator==(aIter));
michael@0 464 }
michael@0 465
michael@0 466 /**
michael@0 467 * Compare two iterators for increasing order.
michael@0 468 *
michael@0 469 * @param aIter is the other iterator to be compared to
michael@0 470 * @return TRUE if this object points to an element before
michael@0 471 * the element pointed to by aIter.
michael@0 472 * FALSE if this and aIter are not iterating over the same deque.
michael@0 473 */
michael@0 474 bool nsDequeIterator::operator<(nsDequeIterator& aIter) {
michael@0 475 return bool(((mIndex<aIter.mIndex) && (&mDeque==&aIter.mDeque)));
michael@0 476 }
michael@0 477
michael@0 478 /**
michael@0 479 * Compare two iterators for equivalence.
michael@0 480 *
michael@0 481 * @param aIter is the other iterator to be compared to
michael@0 482 * @return TRUE if EQUAL
michael@0 483 */
michael@0 484 bool nsDequeIterator::operator==(nsDequeIterator& aIter) {
michael@0 485 return bool(((mIndex==aIter.mIndex) && (&mDeque==&aIter.mDeque)));
michael@0 486 }
michael@0 487
michael@0 488 /**
michael@0 489 * Compare two iterators for non strict decreasing order.
michael@0 490 *
michael@0 491 * @param aIter is the other iterator to be compared to
michael@0 492 * @return TRUE if this object points to the same element, or
michael@0 493 * an element after the element pointed to by aIter.
michael@0 494 * FALSE if this and aIter are not iterating over the same deque.
michael@0 495 */
michael@0 496 bool nsDequeIterator::operator>=(nsDequeIterator& aIter) {
michael@0 497 return bool(((mIndex>=aIter.mIndex) && (&mDeque==&aIter.mDeque)));
michael@0 498 }
michael@0 499
michael@0 500 /**
michael@0 501 * Pre-increment operator
michael@0 502 *
michael@0 503 * @return object at post-incremented index
michael@0 504 */
michael@0 505 void* nsDequeIterator::operator++() {
michael@0 506 NS_ASSERTION(mIndex<mDeque.mSize,
michael@0 507 "You have reached the end of the Internet."\
michael@0 508 "You have seen everything there is to see. Please go back. Now."
michael@0 509 );
michael@0 510 #ifndef TIMELESS_LIGHTWEIGHT
michael@0 511 if (mIndex>=mDeque.mSize) return 0;
michael@0 512 #endif
michael@0 513 return mDeque.ObjectAt(++mIndex);
michael@0 514 }
michael@0 515
michael@0 516 /**
michael@0 517 * Post-increment operator
michael@0 518 *
michael@0 519 * @param param is ignored
michael@0 520 * @return object at pre-incremented index
michael@0 521 */
michael@0 522 void* nsDequeIterator::operator++(int) {
michael@0 523 NS_ASSERTION(mIndex<=mDeque.mSize,
michael@0 524 "You have already reached the end of the Internet."\
michael@0 525 "You have seen everything there is to see. Please go back. Now."
michael@0 526 );
michael@0 527 #ifndef TIMELESS_LIGHTWEIGHT
michael@0 528 if (mIndex>mDeque.mSize) return 0;
michael@0 529 #endif
michael@0 530 return mDeque.ObjectAt(mIndex++);
michael@0 531 }
michael@0 532
michael@0 533 /**
michael@0 534 * Pre-decrement operator
michael@0 535 *
michael@0 536 * @return object at pre-decremented index
michael@0 537 */
michael@0 538 void* nsDequeIterator::operator--() {
michael@0 539 NS_ASSERTION(mIndex>=0,
michael@0 540 "You have reached the beginning of the Internet."\
michael@0 541 "You have seen everything there is to see. Please go forward. Now."
michael@0 542 );
michael@0 543 #ifndef TIMELESS_LIGHTWEIGHT
michael@0 544 if (mIndex<0) return 0;
michael@0 545 #endif
michael@0 546 return mDeque.ObjectAt(--mIndex);
michael@0 547 }
michael@0 548
michael@0 549 /**
michael@0 550 * Post-decrement operator
michael@0 551 *
michael@0 552 * @param param is ignored
michael@0 553 * @return object at post-decremented index
michael@0 554 */
michael@0 555 void* nsDequeIterator::operator--(int) {
michael@0 556 NS_ASSERTION(mIndex>=0,
michael@0 557 "You have already reached the beginning of the Internet."\
michael@0 558 "You have seen everything there is to see. Please go forward. Now."
michael@0 559 );
michael@0 560 #ifndef TIMELESS_LIGHTWEIGHT
michael@0 561 if (mIndex<0) return 0;
michael@0 562 #endif
michael@0 563 return mDeque.ObjectAt(mIndex--);
michael@0 564 }
michael@0 565
michael@0 566 /**
michael@0 567 * Dereference operator
michael@0 568 * Note that the iterator floats, so you don't need to do:
michael@0 569 * <code>++iter; aDeque.PopFront();</code>
michael@0 570 * Unless you actually want your iterator to jump 2 spaces.
michael@0 571 *
michael@0 572 * Picture: [1 2I 3 4]
michael@0 573 * PopFront()
michael@0 574 * Picture: [2 3I 4]
michael@0 575 * Note that I still happily points to object at the second index
michael@0 576 *
michael@0 577 * @return object at ith index
michael@0 578 */
michael@0 579 void* nsDequeIterator::GetCurrent() {
michael@0 580 NS_ASSERTION(mIndex<mDeque.mSize&&mIndex>=0,"Current is out of bounds");
michael@0 581 #ifndef TIMELESS_LIGHTWEIGHT
michael@0 582 if (mIndex>=mDeque.mSize||mIndex<0) return 0;
michael@0 583 #endif
michael@0 584 return mDeque.ObjectAt(mIndex);
michael@0 585 }
michael@0 586
michael@0 587 /**
michael@0 588 * Call this method when you want to iterate all the
michael@0 589 * members of the container, passing a functor along
michael@0 590 * to call your code.
michael@0 591 *
michael@0 592 * @param aFunctor object to call for each member
michael@0 593 * @return *this
michael@0 594 */
michael@0 595 void nsDequeIterator::ForEach(nsDequeFunctor& aFunctor) const{
michael@0 596 mDeque.ForEach(aFunctor);
michael@0 597 }
michael@0 598
michael@0 599 /**
michael@0 600 * Call this method when you want to iterate all the
michael@0 601 * members of the container, calling the functor you
michael@0 602 * passed with each member. This process will interrupt
michael@0 603 * if your function returns non 0 to this method.
michael@0 604 *
michael@0 605 * @param aFunctor object to call for each member
michael@0 606 * @return first nonzero result of aFunctor or 0.
michael@0 607 */
michael@0 608 const void* nsDequeIterator::FirstThat(nsDequeFunctor& aFunctor) const{
michael@0 609 return mDeque.FirstThat(aFunctor);
michael@0 610 }

mercurial