xpcom/glue/nsDeque.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/glue/nsDeque.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,610 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "nsDeque.h"
    1.10 +#include "nsISupportsImpl.h"
    1.11 +#include <string.h>
    1.12 +#ifdef DEBUG_rickg
    1.13 +#include <stdio.h>
    1.14 +#endif
    1.15 +
    1.16 +/**
    1.17 + * 07/02/2001  09:17p 509,104 clangref.pdf from openwatcom's site
    1.18 + * Watcom C Language Reference Edition 11.0c
    1.19 + * page 118 of 297
    1.20 + *
    1.21 + * The % symbol yields the remainder from the division of the first operand
    1.22 + * by the second operand. The operands of % must have integral type.
    1.23 + *
    1.24 + * When both operands of % are positive, the result is a positive value
    1.25 + * smaller than the second operand. When one or both operands is negative,
    1.26 + * whether the result is positive or negative is implementation-defined.
    1.27 + *
    1.28 + */
    1.29 +/* Ok, so first of all, C is underspecified. joy.
    1.30 + * The following functions do not provide a correct implementation of modulus
    1.31 + * They provide functionality for x>-y.
    1.32 + * There are risks of 2*y being greater than max int, which is part of the
    1.33 + * reason no multiplication is used and other operations are avoided.
    1.34 + *
    1.35 + * modasgn
    1.36 + * @param x variable
    1.37 + * @param y expression
    1.38 + * approximately equivalent to x %= y
    1.39 + *
    1.40 + * modulus
    1.41 + * @param x expression
    1.42 + * @param y expression
    1.43 + * approximately equivalent to x % y
    1.44 + */
    1.45 +#define modasgn(x,y) if (x<0) x+=y; x%=y
    1.46 +#define modulus(x,y) ((x<0)?(x+y)%(y):(x)%(y))
    1.47 +
    1.48 +/**
    1.49 + * Standard constructor
    1.50 + * @param deallocator, called by Erase and ~nsDeque
    1.51 + */
    1.52 +nsDeque::nsDeque(nsDequeFunctor* aDeallocator) {
    1.53 +  MOZ_COUNT_CTOR(nsDeque);
    1.54 +  mDeallocator=aDeallocator;
    1.55 +  mOrigin=mSize=0;
    1.56 +  mData=mBuffer; // don't allocate space until you must
    1.57 +  mCapacity=sizeof(mBuffer)/sizeof(mBuffer[0]);
    1.58 +  memset(mData, 0, mCapacity*sizeof(mBuffer[0]));
    1.59 +}
    1.60 +
    1.61 +/**
    1.62 + * Destructor
    1.63 + */
    1.64 +nsDeque::~nsDeque() {
    1.65 +  MOZ_COUNT_DTOR(nsDeque);
    1.66 +
    1.67 +#ifdef DEBUG_rickg
    1.68 +  char buffer[30];
    1.69 +  printf("Capacity: %i\n", mCapacity);
    1.70 +
    1.71 +  static int mCaps[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    1.72 +  switch(mCapacity) {
    1.73 +    case 4:     mCaps[0]++; break;
    1.74 +    case 8:     mCaps[1]++; break;
    1.75 +    case 16:    mCaps[2]++; break;
    1.76 +    case 32:    mCaps[3]++; break;
    1.77 +    case 64:    mCaps[4]++; break;
    1.78 +    case 128:   mCaps[5]++; break;
    1.79 +    case 256:   mCaps[6]++; break;
    1.80 +    case 512:   mCaps[7]++; break;
    1.81 +    case 1024:  mCaps[8]++; break;
    1.82 +    case 2048:  mCaps[9]++; break;
    1.83 +    case 4096:  mCaps[10]++; break;
    1.84 +    default:
    1.85 +      break;
    1.86 +  }
    1.87 +#endif
    1.88 +
    1.89 +  Erase();
    1.90 +  if (mData && (mData!=mBuffer)) {
    1.91 +    free(mData);
    1.92 +  }
    1.93 +  mData=0;
    1.94 +  SetDeallocator(0);
    1.95 +}
    1.96 +
    1.97 +size_t nsDeque::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
    1.98 +  size_t size = 0;
    1.99 +  if (mData != mBuffer) {
   1.100 +    size += aMallocSizeOf(mData);
   1.101 +  }
   1.102 +
   1.103 +  if (mDeallocator) {
   1.104 +    size += aMallocSizeOf(mDeallocator);
   1.105 +  }
   1.106 +
   1.107 +  return size;
   1.108 +}
   1.109 +
   1.110 +size_t nsDeque::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
   1.111 +  return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   1.112 +}
   1.113 +
   1.114 +/**
   1.115 + * Set the functor to be called by Erase()
   1.116 + * The deque owns the functor.
   1.117 + *
   1.118 + * @param   aDeallocator functor object for use by Erase()
   1.119 + */
   1.120 +void nsDeque::SetDeallocator(nsDequeFunctor* aDeallocator){
   1.121 +  delete mDeallocator;
   1.122 +  mDeallocator=aDeallocator;
   1.123 +}
   1.124 +
   1.125 +/**
   1.126 + * Remove all items from container without destroying them.
   1.127 + */
   1.128 +void nsDeque::Empty() {
   1.129 +  if (mSize && mData) {
   1.130 +    memset(mData, 0, mCapacity*sizeof(mData));
   1.131 +  }
   1.132 +  mSize=0;
   1.133 +  mOrigin=0;
   1.134 +}
   1.135 +
   1.136 +/**
   1.137 + * Remove and delete all items from container
   1.138 + */
   1.139 +void nsDeque::Erase() {
   1.140 +  if (mDeallocator && mSize) {
   1.141 +    ForEach(*mDeallocator);
   1.142 +  }
   1.143 +  Empty();
   1.144 +}
   1.145 +
   1.146 +/**
   1.147 + * This method quadruples the size of the deque
   1.148 + * Elements in the deque are resequenced so that elements
   1.149 + * in the deque are stored sequentially
   1.150 + *
   1.151 + * @return  whether growing succeeded
   1.152 + */
   1.153 +bool nsDeque::GrowCapacity() {
   1.154 +  int32_t theNewSize=mCapacity<<2;
   1.155 +  NS_ASSERTION(theNewSize>mCapacity, "Overflow");
   1.156 +  if (theNewSize<=mCapacity)
   1.157 +    return false;
   1.158 +  void** temp=(void**)malloc(theNewSize * sizeof(void*));
   1.159 +  if (!temp)
   1.160 +    return false;
   1.161 +
   1.162 +  //Here's the interesting part: You can't just move the elements
   1.163 +  //directly (in situ) from the old buffer to the new one.
   1.164 +  //Since capacity has changed, the old origin doesn't make
   1.165 +  //sense anymore. It's better to resequence the elements now.
   1.166 +
   1.167 +  memcpy(temp, mData + mOrigin, sizeof(void*) * (mCapacity - mOrigin));
   1.168 +  memcpy(temp + (mCapacity - mOrigin), mData, sizeof(void*) * mOrigin);
   1.169 +
   1.170 +  if (mData != mBuffer) {
   1.171 +    free(mData);
   1.172 +  }
   1.173 +
   1.174 +  mCapacity=theNewSize;
   1.175 +  mOrigin=0; //now realign the origin...
   1.176 +  mData=temp;
   1.177 +
   1.178 +  return true;
   1.179 +}
   1.180 +
   1.181 +/**
   1.182 + * This method adds an item to the end of the deque.
   1.183 + * This operation has the potential to cause the
   1.184 + * underlying buffer to resize.
   1.185 + *
   1.186 + * @param   aItem: new item to be added to deque
   1.187 + */
   1.188 +bool nsDeque::Push(void* aItem, const fallible_t&) {
   1.189 +  if (mSize==mCapacity && !GrowCapacity()) {
   1.190 +    return false;
   1.191 +  }
   1.192 +  mData[modulus(mOrigin + mSize, mCapacity)]=aItem;
   1.193 +  mSize++;
   1.194 +  return true;
   1.195 +}
   1.196 +
   1.197 +/**
   1.198 + * This method adds an item to the front of the deque.
   1.199 + * This operation has the potential to cause the
   1.200 + * underlying buffer to resize.
   1.201 + *
   1.202 + * --Commments for GrowCapacity() case
   1.203 + * We've grown and shifted which means that the old
   1.204 + * final element in the deque is now the first element
   1.205 + * in the deque.  This is temporary.
   1.206 + * We haven't inserted the new element at the front.
   1.207 + *
   1.208 + * To continue with the idea of having the front at zero
   1.209 + * after a grow, we move the old final item (which through
   1.210 + * the voodoo of mOrigin-- is now the first) to its final
   1.211 + * position which is conveniently the old length.
   1.212 + *
   1.213 + * Note that this case only happens when the deque is full.
   1.214 + * [And that pieces of this magic only work if the deque is full.]
   1.215 + * picture:
   1.216 + *   [ABCDEFGH] @[mOrigin:3]:D.
   1.217 + * Task: PushFront("Z")
   1.218 + * shift mOrigin so, @[mOrigin:2]:C
   1.219 + * stretch and rearrange: (mOrigin:0)
   1.220 + *   [CDEFGHAB ________ ________ ________]
   1.221 + * copy: (The second C is currently out of bounds)
   1.222 + *   [CDEFGHAB C_______ ________ ________]
   1.223 + * later we will insert Z:
   1.224 + *   [ZDEFGHAB C_______ ________ ________]
   1.225 + * and increment size: 9. (C is no longer out of bounds)
   1.226 + * --
   1.227 + * @param   aItem: new item to be added to deque
   1.228 + */
   1.229 +bool nsDeque::PushFront(void* aItem, const fallible_t&) {
   1.230 +  mOrigin--;
   1.231 +  modasgn(mOrigin,mCapacity);
   1.232 +  if (mSize==mCapacity) {
   1.233 +    if (!GrowCapacity()) {
   1.234 +      return false;
   1.235 +    }
   1.236 +    /* Comments explaining this are above*/
   1.237 +    mData[mSize]=mData[mOrigin];
   1.238 +  }
   1.239 +  mData[mOrigin]=aItem;
   1.240 +  mSize++;
   1.241 +  return true;
   1.242 +}
   1.243 +
   1.244 +/**
   1.245 + * Remove and return the last item in the container.
   1.246 + *
   1.247 + * @return  ptr to last item in container
   1.248 + */
   1.249 +void* nsDeque::Pop() {
   1.250 +  void* result=0;
   1.251 +  if (mSize>0) {
   1.252 +    --mSize;
   1.253 +    int32_t offset=modulus(mSize + mOrigin, mCapacity);
   1.254 +    result=mData[offset];
   1.255 +    mData[offset]=0;
   1.256 +    if (!mSize) {
   1.257 +      mOrigin=0;
   1.258 +    }
   1.259 +  }
   1.260 +  return result;
   1.261 +}
   1.262 +
   1.263 +/**
   1.264 + * This method gets called you want to remove and return
   1.265 + * the first member in the container.
   1.266 + *
   1.267 + * @return  last item in container
   1.268 + */
   1.269 +void* nsDeque::PopFront() {
   1.270 +  void* result=0;
   1.271 +  if (mSize>0) {
   1.272 +    NS_ASSERTION(mOrigin < mCapacity, "Error: Bad origin");
   1.273 +    result=mData[mOrigin];
   1.274 +    mData[mOrigin++]=0;     //zero it out for debugging purposes.
   1.275 +    mSize--;
   1.276 +    // Cycle around if we pop off the end
   1.277 +    // and reset origin if when we pop the last element
   1.278 +    if (mCapacity==mOrigin || !mSize) {
   1.279 +      mOrigin=0;
   1.280 +    }
   1.281 +  }
   1.282 +  return result;
   1.283 +}
   1.284 +
   1.285 +/**
   1.286 + * This method gets called you want to peek at the bottom
   1.287 + * member without removing it.
   1.288 + *
   1.289 + * @return  last item in container
   1.290 + */
   1.291 +void* nsDeque::Peek() {
   1.292 +  void* result=0;
   1.293 +  if (mSize>0) {
   1.294 +    result = mData[modulus(mSize - 1 + mOrigin, mCapacity)];
   1.295 +  }
   1.296 +  return result;
   1.297 +} 
   1.298 +
   1.299 +/**
   1.300 + * This method gets called you want to peek at the topmost
   1.301 + * member without removing it.
   1.302 + *
   1.303 + * @return  last item in container
   1.304 + */
   1.305 +void* nsDeque::PeekFront() {
   1.306 +  void* result=0;
   1.307 +  if (mSize>0) {
   1.308 +    result=mData[mOrigin];
   1.309 +  }
   1.310 +  return result;
   1.311 +}
   1.312 +
   1.313 +/**
   1.314 + * Call this to retrieve the ith element from this container.
   1.315 + * Keep in mind that accessing the underlying elements is
   1.316 + * done in a relative fashion. Object 0 is not necessarily
   1.317 + * the first element (the first element is at mOrigin).
   1.318 + *
   1.319 + * @param   aIndex : 0 relative offset of item you want
   1.320 + * @return  void* or null
   1.321 + */
   1.322 +void* nsDeque::ObjectAt(int32_t aIndex) const {
   1.323 +  void* result=0;
   1.324 +  if ((aIndex>=0) && (aIndex<mSize)) {
   1.325 +    result=mData[modulus(mOrigin + aIndex, mCapacity)];
   1.326 +  }
   1.327 +  return result;
   1.328 +}
   1.329 +
   1.330 +void* nsDeque::RemoveObjectAt(int32_t aIndex) {
   1.331 +  if ((aIndex<0) || (aIndex>=mSize)) {
   1.332 +    return 0;
   1.333 +  }
   1.334 +  void* result=mData[modulus(mOrigin + aIndex, mCapacity)];
   1.335 +
   1.336 +  // "Shuffle down" all elements in the array by 1, overwritting the element
   1.337 +  // being removed.
   1.338 +  for (int32_t i=aIndex; i<mSize; i++) {
   1.339 +    mData[modulus(mOrigin + i, mCapacity)] = mData[modulus(mOrigin + i + 1, mCapacity)];
   1.340 +  }
   1.341 +  mSize--;
   1.342 +
   1.343 +  return result;
   1.344 +}
   1.345 +
   1.346 +/**
   1.347 + * Create and return an iterator pointing to
   1.348 + * the beginning of the queue. Note that this
   1.349 + * takes the circular buffer semantics into account.
   1.350 + *
   1.351 + * @return  new deque iterator, init'ed to 1st item
   1.352 + */
   1.353 +nsDequeIterator nsDeque::Begin() const{
   1.354 +  return nsDequeIterator(*this, 0);
   1.355 +}
   1.356 +
   1.357 +/**
   1.358 + * Create and return an iterator pointing to
   1.359 + * the last item in the deque.
   1.360 + * Note that this takes the circular buffer semantics
   1.361 + * into account.
   1.362 + *
   1.363 + * @return  new deque iterator, init'ed to the last item
   1.364 + */
   1.365 +nsDequeIterator nsDeque::End() const{
   1.366 +  return nsDequeIterator(*this, mSize - 1);
   1.367 +}
   1.368 +
   1.369 +void* nsDeque::Last() const {
   1.370 +  return End().GetCurrent();
   1.371 +}
   1.372 +
   1.373 +/**
   1.374 + * Call this method when you want to iterate all the
   1.375 + * members of the container, passing a functor along
   1.376 + * to call your code.
   1.377 + *
   1.378 + * @param   aFunctor object to call for each member
   1.379 + * @return  *this
   1.380 + */
   1.381 +void nsDeque::ForEach(nsDequeFunctor& aFunctor) const{
   1.382 +  for (int32_t i=0; i<mSize; i++) {
   1.383 +    aFunctor(ObjectAt(i));
   1.384 +  }
   1.385 +}
   1.386 +
   1.387 +/**
   1.388 + * Call this method when you want to iterate all the
   1.389 + * members of the container, calling the functor you 
   1.390 + * passed with each member. This process will interrupt
   1.391 + * if your function returns non 0 to this method.
   1.392 + *
   1.393 + * @param   aFunctor object to call for each member
   1.394 + * @return  first nonzero result of aFunctor or 0.
   1.395 + */
   1.396 +const void* nsDeque::FirstThat(nsDequeFunctor& aFunctor) const{
   1.397 +  for (int32_t i=0; i<mSize; i++) {
   1.398 +    void* obj=aFunctor(ObjectAt(i));
   1.399 +    if (obj) {
   1.400 +      return obj;
   1.401 +    }
   1.402 +  }
   1.403 +  return 0;
   1.404 +}
   1.405 +
   1.406 +/******************************************************
   1.407 + * Here comes the nsDequeIterator class...
   1.408 + ******************************************************/
   1.409 +
   1.410 +/**
   1.411 + * DequeIterator is an object that knows how to iterate (forward and backward)
   1.412 + * through a Deque. Normally, you don't need to do this, but there are some special
   1.413 + * cases where it is pretty handy, so here you go.
   1.414 + *
   1.415 + * This is a standard dequeiterator constructor
   1.416 + *
   1.417 + * @param   aQueue is the deque object to be iterated
   1.418 + * @param   aIndex is the starting position for your iteration
   1.419 + */
   1.420 +nsDequeIterator::nsDequeIterator(const nsDeque& aQueue, int aIndex)
   1.421 +: mIndex(aIndex),
   1.422 +  mDeque(aQueue)
   1.423 +{
   1.424 +}
   1.425 +
   1.426 +/**
   1.427 + * Create a copy of a DequeIterator
   1.428 + *
   1.429 + * @param   aCopy is another iterator to copy from
   1.430 + */
   1.431 +nsDequeIterator::nsDequeIterator(const nsDequeIterator& aCopy)
   1.432 +: mIndex(aCopy.mIndex),
   1.433 +  mDeque(aCopy.mDeque)
   1.434 +{
   1.435 +}
   1.436 +
   1.437 +/**
   1.438 + * Moves iterator to first element in deque
   1.439 + * @return  *this
   1.440 + */
   1.441 +nsDequeIterator& nsDequeIterator::First(){
   1.442 +  mIndex=0;
   1.443 +  return *this;
   1.444 +}
   1.445 +
   1.446 +/**
   1.447 + * Standard assignment operator for dequeiterator
   1.448 + *
   1.449 + * @param   aCopy is an iterator to be copied from
   1.450 + * @return  *this
   1.451 + */
   1.452 +nsDequeIterator& nsDequeIterator::operator=(const nsDequeIterator& aCopy) {
   1.453 +  NS_ASSERTION(&mDeque==&aCopy.mDeque,"you can't change the deque that an interator is iterating over, sorry.");
   1.454 +  mIndex=aCopy.mIndex;
   1.455 +  return *this;
   1.456 +}
   1.457 +
   1.458 +/**
   1.459 + * preform ! operation against to iterators to test for equivalence
   1.460 + * (or lack thereof)!
   1.461 + *
   1.462 + * @param   aIter is the object to be compared to
   1.463 + * @return  TRUE if NOT equal.
   1.464 + */
   1.465 +bool nsDequeIterator::operator!=(nsDequeIterator& aIter) {
   1.466 +  return bool(!this->operator==(aIter));
   1.467 +}
   1.468 +
   1.469 +/**
   1.470 + * Compare two iterators for increasing order.
   1.471 + *
   1.472 + * @param   aIter is the other iterator to be compared to
   1.473 + * @return  TRUE if this object points to an element before
   1.474 + *          the element pointed to by aIter.
   1.475 + *          FALSE if this and aIter are not iterating over the same deque.
   1.476 + */
   1.477 +bool nsDequeIterator::operator<(nsDequeIterator& aIter) {
   1.478 +  return bool(((mIndex<aIter.mIndex) && (&mDeque==&aIter.mDeque)));
   1.479 +}
   1.480 +
   1.481 +/**
   1.482 + * Compare two iterators for equivalence.
   1.483 + *
   1.484 + * @param   aIter is the other iterator to be compared to
   1.485 + * @return  TRUE if EQUAL
   1.486 + */
   1.487 +bool nsDequeIterator::operator==(nsDequeIterator& aIter) {
   1.488 +  return bool(((mIndex==aIter.mIndex) && (&mDeque==&aIter.mDeque)));
   1.489 +}
   1.490 +
   1.491 +/**
   1.492 + * Compare two iterators for non strict decreasing order.
   1.493 + *
   1.494 + * @param   aIter is the other iterator to be compared to
   1.495 + * @return  TRUE if this object points to the same element, or
   1.496 + *          an element after the element pointed to by aIter.
   1.497 + *          FALSE if this and aIter are not iterating over the same deque.
   1.498 + */
   1.499 +bool nsDequeIterator::operator>=(nsDequeIterator& aIter) {
   1.500 +  return bool(((mIndex>=aIter.mIndex) && (&mDeque==&aIter.mDeque)));
   1.501 +}
   1.502 +
   1.503 +/**
   1.504 + * Pre-increment operator
   1.505 + *
   1.506 + * @return  object at post-incremented index
   1.507 + */
   1.508 +void* nsDequeIterator::operator++() {
   1.509 +  NS_ASSERTION(mIndex<mDeque.mSize,
   1.510 +    "You have reached the end of the Internet."\
   1.511 +    "You have seen everything there is to see. Please go back. Now."
   1.512 +  );
   1.513 +#ifndef TIMELESS_LIGHTWEIGHT
   1.514 +  if (mIndex>=mDeque.mSize) return 0;
   1.515 +#endif
   1.516 +  return mDeque.ObjectAt(++mIndex);
   1.517 +}
   1.518 +
   1.519 +/**
   1.520 + * Post-increment operator
   1.521 + *
   1.522 + * @param   param is ignored
   1.523 + * @return  object at pre-incremented index
   1.524 + */
   1.525 +void* nsDequeIterator::operator++(int) {
   1.526 +  NS_ASSERTION(mIndex<=mDeque.mSize,
   1.527 +    "You have already reached the end of the Internet."\
   1.528 +    "You have seen everything there is to see. Please go back. Now."
   1.529 +  );
   1.530 +#ifndef TIMELESS_LIGHTWEIGHT
   1.531 +  if (mIndex>mDeque.mSize) return 0;
   1.532 +#endif
   1.533 +  return mDeque.ObjectAt(mIndex++);
   1.534 +}
   1.535 +
   1.536 +/**
   1.537 + * Pre-decrement operator
   1.538 + *
   1.539 + * @return  object at pre-decremented index
   1.540 + */
   1.541 +void* nsDequeIterator::operator--() {
   1.542 +  NS_ASSERTION(mIndex>=0,
   1.543 +    "You have reached the beginning of the Internet."\
   1.544 +    "You have seen everything there is to see. Please go forward. Now."
   1.545 +  );
   1.546 +#ifndef TIMELESS_LIGHTWEIGHT
   1.547 +  if (mIndex<0) return 0;
   1.548 +#endif
   1.549 +  return mDeque.ObjectAt(--mIndex);
   1.550 +}
   1.551 +
   1.552 +/**
   1.553 + * Post-decrement operator
   1.554 + *
   1.555 + * @param   param is ignored
   1.556 + * @return  object at post-decremented index
   1.557 + */
   1.558 +void* nsDequeIterator::operator--(int) {
   1.559 +  NS_ASSERTION(mIndex>=0,
   1.560 +    "You have already reached the beginning of the Internet."\
   1.561 +    "You have seen everything there is to see. Please go forward. Now."
   1.562 +  );
   1.563 +#ifndef TIMELESS_LIGHTWEIGHT
   1.564 +  if (mIndex<0) return 0;
   1.565 +#endif
   1.566 +  return mDeque.ObjectAt(mIndex--);
   1.567 +}
   1.568 +
   1.569 +/**
   1.570 + * Dereference operator
   1.571 + * Note that the iterator floats, so you don't need to do:
   1.572 + * <code>++iter; aDeque.PopFront();</code>
   1.573 + * Unless you actually want your iterator to jump 2 spaces.
   1.574 + *
   1.575 + * Picture: [1 2I 3 4]
   1.576 + * PopFront()
   1.577 + * Picture: [2 3I 4]
   1.578 + * Note that I still happily points to object at the second index
   1.579 + *
   1.580 + * @return  object at ith index
   1.581 + */
   1.582 +void* nsDequeIterator::GetCurrent() {
   1.583 +  NS_ASSERTION(mIndex<mDeque.mSize&&mIndex>=0,"Current is out of bounds");
   1.584 +#ifndef TIMELESS_LIGHTWEIGHT
   1.585 +  if (mIndex>=mDeque.mSize||mIndex<0) return 0;
   1.586 +#endif
   1.587 +  return mDeque.ObjectAt(mIndex);
   1.588 +}
   1.589 +
   1.590 +/**
   1.591 + * Call this method when you want to iterate all the
   1.592 + * members of the container, passing a functor along
   1.593 + * to call your code.
   1.594 + *
   1.595 + * @param   aFunctor object to call for each member
   1.596 + * @return  *this
   1.597 + */
   1.598 +void nsDequeIterator::ForEach(nsDequeFunctor& aFunctor) const{
   1.599 +  mDeque.ForEach(aFunctor);
   1.600 +}
   1.601 +
   1.602 +/**
   1.603 + * Call this method when you want to iterate all the
   1.604 + * members of the container, calling the functor you 
   1.605 + * passed with each member. This process will interrupt
   1.606 + * if your function returns non 0 to this method.
   1.607 + *
   1.608 + * @param   aFunctor object to call for each member
   1.609 + * @return  first nonzero result of aFunctor or 0.
   1.610 + */
   1.611 +const void* nsDequeIterator::FirstThat(nsDequeFunctor& aFunctor) const{
   1.612 +  return mDeque.FirstThat(aFunctor);
   1.613 +}

mercurial