xpcom/glue/nsDeque.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/glue/nsDeque.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,391 @@
     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 +/**
    1.10 + * MODULE NOTES:
    1.11 + *
    1.12 + * The Deque is a very small, very efficient container object
    1.13 + * than can hold elements of type void*, offering the following features:
    1.14 + *    Its interface supports pushing and popping of elements.
    1.15 + *    It can iterate (via an interator class) its elements.
    1.16 + *    When full, it can efficiently resize dynamically.
    1.17 + *
    1.18 + *
    1.19 + * NOTE: The only bit of trickery here is that this deque is
    1.20 + * built upon a ring-buffer. Like all ring buffers, the first
    1.21 + * element may not be at index[0]. The mOrigin member determines
    1.22 + * where the first child is. This point is quietly hidden from
    1.23 + * customers of this class.
    1.24 + *
    1.25 + */
    1.26 +
    1.27 +#ifndef _NSDEQUE
    1.28 +#define _NSDEQUE
    1.29 +
    1.30 +#include "nscore.h"
    1.31 +#include "nsDebug.h"
    1.32 +#include "mozilla/Attributes.h"
    1.33 +#include "mozilla/fallible.h"
    1.34 +#include "mozilla/MemoryReporting.h"
    1.35 +
    1.36 +/**
    1.37 + * The nsDequeFunctor class is used when you want to create
    1.38 + * callbacks between the deque and your generic code.
    1.39 + * Use these objects in a call to ForEach();
    1.40 + *
    1.41 + */
    1.42 +
    1.43 +class nsDequeFunctor{
    1.44 +public:
    1.45 +  virtual void* operator()(void* anObject)=0;
    1.46 +  virtual ~nsDequeFunctor() {}
    1.47 +};
    1.48 +
    1.49 +/******************************************************
    1.50 + * Here comes the nsDeque class itself...
    1.51 + ******************************************************/
    1.52 +
    1.53 +/**
    1.54 + * The deque (double-ended queue) class is a common container type,
    1.55 + * whose behavior mimics a line in your favorite checkout stand.
    1.56 + * Classic CS describes the common behavior of a queue as FIFO.
    1.57 + * A deque allows insertion and removal at both ends of
    1.58 + * the container.
    1.59 + *
    1.60 + * The deque stores pointers to items.
    1.61 + */
    1.62 +
    1.63 +class nsDequeIterator;
    1.64 +
    1.65 +class NS_COM_GLUE nsDeque {
    1.66 +  friend class nsDequeIterator;
    1.67 +  typedef mozilla::fallible_t fallible_t;
    1.68 +  public:
    1.69 +   nsDeque(nsDequeFunctor* aDeallocator = nullptr);
    1.70 +  ~nsDeque();
    1.71 +
    1.72 +  /**
    1.73 +   * Returns the number of elements currently stored in
    1.74 +   * this deque.
    1.75 +   *
    1.76 +   * @return  number of elements currently in the deque
    1.77 +   */
    1.78 +  inline int32_t GetSize() const {return mSize;}
    1.79 +
    1.80 +  /**
    1.81 +   * Appends new member at the end of the deque.
    1.82 +   *
    1.83 +   * @param   item to store in deque
    1.84 +   */
    1.85 +  void Push(void* aItem) {
    1.86 +    if (!Push(aItem, fallible_t())) {
    1.87 +      NS_ABORT_OOM(mSize);
    1.88 +    }
    1.89 +  }
    1.90 +
    1.91 +  bool Push(void* aItem, const fallible_t&) NS_WARN_UNUSED_RESULT;
    1.92 +
    1.93 +  /**
    1.94 +   * Inserts new member at the front of the deque.
    1.95 +   *
    1.96 +   * @param   item to store in deque
    1.97 +   */
    1.98 +  void PushFront(void* aItem) {
    1.99 +    if (!PushFront(aItem, fallible_t())) {
   1.100 +      NS_ABORT_OOM(mSize);
   1.101 +    }
   1.102 +  }
   1.103 +
   1.104 +  bool PushFront(void* aItem, const fallible_t&) NS_WARN_UNUSED_RESULT;
   1.105 +
   1.106 +  /**
   1.107 +   * Remove and return the last item in the container.
   1.108 +   *
   1.109 +   * @return  the item that was the last item in container
   1.110 +   */
   1.111 +  void* Pop();
   1.112 +
   1.113 +  /**
   1.114 +   * Remove and return the first item in the container.
   1.115 +   *
   1.116 +   * @return  the item that was first item in container
   1.117 +   */
   1.118 +  void* PopFront();
   1.119 +
   1.120 +  /**
   1.121 +   * Retrieve the bottom item without removing it.
   1.122 +   *
   1.123 +   * @return  the first item in container
   1.124 +   */
   1.125 +
   1.126 +  void* Peek();
   1.127 +  /**
   1.128 +   * Return topmost item without removing it.
   1.129 +   *
   1.130 +   * @return  the first item in container
   1.131 +   */
   1.132 +  void* PeekFront();
   1.133 +
   1.134 +  /**
   1.135 +   * Retrieve the i'th member from the deque without removing it.
   1.136 +   *
   1.137 +   * @param   index of desired item
   1.138 +   * @return  i'th element in list
   1.139 +   */
   1.140 +  void* ObjectAt(int aIndex) const;
   1.141 +
   1.142 +  /**
   1.143 +   * Removes and returns the i'th member from the deque.
   1.144 +   *
   1.145 +   * @param   index of desired item
   1.146 +   * @return  the element which was removed
   1.147 +   */
   1.148 +  void* RemoveObjectAt(int aIndex);
   1.149 +
   1.150 +  /**
   1.151 +   * Remove all items from container without destroying them.
   1.152 +   */
   1.153 +  void Empty();
   1.154 +
   1.155 +  /**
   1.156 +   * Remove and delete all items from container.
   1.157 +   * Deletes are handled by the deallocator nsDequeFunctor
   1.158 +   * which is specified at deque construction.
   1.159 +   */
   1.160 +  void Erase();
   1.161 +
   1.162 +  /**
   1.163 +   * Creates a new iterator, pointing to the first
   1.164 +   * item in the deque.
   1.165 +   *
   1.166 +   * @return  new dequeIterator
   1.167 +   */
   1.168 +  nsDequeIterator Begin() const;
   1.169 +
   1.170 +  /**
   1.171 +   * Creates a new iterator, pointing to the last
   1.172 +   * item in the deque.
   1.173 +   *
   1.174 +   * @return  new dequeIterator
   1.175 +   */
   1.176 +  nsDequeIterator End() const;
   1.177 +
   1.178 +  void* Last() const;
   1.179 +
   1.180 +  /**
   1.181 +   * Call this method when you want to iterate all the
   1.182 +   * members of the container, passing a functor along
   1.183 +   * to call your code.
   1.184 +   *
   1.185 +   * @param   aFunctor object to call for each member
   1.186 +   */
   1.187 +  void ForEach(nsDequeFunctor& aFunctor) const;
   1.188 +
   1.189 +  /**
   1.190 +   * Call this method when you want to iterate all the
   1.191 +   * members of the container, calling the functor you 
   1.192 +   * passed with each member. This process will interrupt
   1.193 +   * if your function returns non 0 to this method.
   1.194 +   *
   1.195 +   * @param   aFunctor object to call for each member
   1.196 +   * @return  first nonzero result of aFunctor or 0.
   1.197 +   */
   1.198 +  const void* FirstThat(nsDequeFunctor& aFunctor) const;
   1.199 +
   1.200 +  void SetDeallocator(nsDequeFunctor* aDeallocator);
   1.201 +
   1.202 +  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   1.203 +  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   1.204 +
   1.205 +protected:
   1.206 +  int32_t         mSize;
   1.207 +  int32_t         mCapacity;
   1.208 +  int32_t         mOrigin;
   1.209 +  nsDequeFunctor* mDeallocator;
   1.210 +  void*           mBuffer[8];
   1.211 +  void**          mData;
   1.212 +
   1.213 +private:
   1.214 +
   1.215 +  /**
   1.216 +   * Copy constructor (PRIVATE)
   1.217 +   *
   1.218 +   * @param another deque
   1.219 +   */
   1.220 +  nsDeque(const nsDeque& other);
   1.221 +
   1.222 +  /**
   1.223 +   * Deque assignment operator (PRIVATE)
   1.224 +   *
   1.225 +   * @param   another deque
   1.226 +   * @return  *this
   1.227 +   */
   1.228 +  nsDeque& operator=(const nsDeque& anOther);
   1.229 +
   1.230 +  bool GrowCapacity();
   1.231 +};
   1.232 +
   1.233 +/******************************************************
   1.234 + * Here comes the nsDequeIterator class...
   1.235 + ******************************************************/
   1.236 +
   1.237 +class NS_COM_GLUE nsDequeIterator {
   1.238 +public:
   1.239 +  /**
   1.240 +   * DequeIterator is an object that knows how to iterate
   1.241 +   * (forward and backward) through a Deque. Normally,
   1.242 +   * you don't need to do this, but there are some special
   1.243 +   * cases where it is pretty handy.
   1.244 +   *
   1.245 +   * One warning: the iterator is not bound to an item,
   1.246 +   * it is bound to an index, so if you insert or remove
   1.247 +   * from the beginning while using an iterator
   1.248 +   * (which is not recommended) then the iterator will
   1.249 +   * point to a different item.  @see GetCurrent()
   1.250 +   *
   1.251 +   * Here you go.
   1.252 +   *
   1.253 +   * @param   aQueue is the deque object to be iterated
   1.254 +   * @param   aIndex is the starting position for your iteration
   1.255 +   */
   1.256 +  nsDequeIterator(const nsDeque& aQueue, int aIndex=0);
   1.257 +
   1.258 +  /**
   1.259 +   * Create a copy of a DequeIterator
   1.260 +   *
   1.261 +   * @param   aCopy is another iterator to copy from
   1.262 +   */
   1.263 +  nsDequeIterator(const nsDequeIterator& aCopy);
   1.264 +
   1.265 +  /**
   1.266 +   * Moves iterator to first element in the deque
   1.267 +   * @return  *this
   1.268 +   */
   1.269 +  nsDequeIterator& First();
   1.270 +
   1.271 +  /**
   1.272 +   * Standard assignment operator for dequeiterator
   1.273 +   * @param   aCopy is another iterator to copy from
   1.274 +   * @return  *this
   1.275 +   */
   1.276 +  nsDequeIterator& operator=(const nsDequeIterator& aCopy);
   1.277 +
   1.278 +  /**
   1.279 +   * preform ! operation against two iterators to test for equivalence
   1.280 +   * (or lack thereof)!
   1.281 +   *
   1.282 +   * @param   aIter is the object to be compared to
   1.283 +   * @return  TRUE if NOT equal.
   1.284 +   */
   1.285 +  bool operator!=(nsDequeIterator& aIter);
   1.286 +
   1.287 +  /**
   1.288 +   * Compare two iterators for increasing order.
   1.289 +   *
   1.290 +   * @param   aIter is the other iterator to be compared to
   1.291 +   * @return  TRUE if this object points to an element before
   1.292 +   *          the element pointed to by aIter.
   1.293 +   *          FALSE if this and aIter are not iterating over
   1.294 +   *          the same deque.
   1.295 +   */
   1.296 +  bool operator<(nsDequeIterator& aIter);
   1.297 +
   1.298 +  /**
   1.299 +   * Compare two iterators for equivalence.
   1.300 +   *
   1.301 +   * @param   aIter is the other iterator to be compared to
   1.302 +   * @return  TRUE if EQUAL
   1.303 +   */
   1.304 +  bool operator==(nsDequeIterator& aIter);
   1.305 +
   1.306 +  /**
   1.307 +   * Compare two iterators for non strict decreasing order.
   1.308 +   *
   1.309 +   * @param   aIter is the other iterator to be compared to
   1.310 +   * @return  TRUE if this object points to the same element, or
   1.311 +   *          an element after the element pointed to by aIter.
   1.312 +   *          FALSE if this and aIter are not iterating over
   1.313 +   *          the same deque.
   1.314 +   */
   1.315 +  bool operator>=(nsDequeIterator& aIter);
   1.316 +
   1.317 +  /**
   1.318 +   * Pre-increment operator
   1.319 +   * Iterator will advance one index towards the end.
   1.320 +   *
   1.321 +   * @return  object_at(++index)
   1.322 +   */
   1.323 +  void* operator++();
   1.324 +
   1.325 +  /**
   1.326 +   * Post-increment operator
   1.327 +   * Iterator will advance one index towards the end.
   1.328 +   *
   1.329 +   * @param   param is ignored
   1.330 +   * @return  object_at(mIndex++)
   1.331 +   */
   1.332 +  void* operator++(int);
   1.333 +
   1.334 +  /**
   1.335 +   * Pre-decrement operator
   1.336 +   * Iterator will advance one index towards the beginning.
   1.337 +   *
   1.338 +   * @return  object_at(--index)
   1.339 +   */
   1.340 +  void* operator--();
   1.341 +
   1.342 +  /**
   1.343 +   * Post-decrement operator
   1.344 +   * Iterator will advance one index towards the beginning.
   1.345 +   *
   1.346 +   * @param   param is ignored
   1.347 +   * @return  object_at(index--)
   1.348 +   */
   1.349 +  void* operator--(int);
   1.350 +
   1.351 +  /**
   1.352 +   * Retrieve the the iterator's notion of current node.
   1.353 +   *
   1.354 +   * Note that the iterator floats, so you don't need to do:
   1.355 +   * <code>++iter; aDeque.PopFront();</code>
   1.356 +   * Unless you actually want your iterator to jump 2 positions
   1.357 +   * relative to its origin.
   1.358 +   *
   1.359 +   * Picture: [1 2i 3 4]
   1.360 +   * PopFront()
   1.361 +   * Picture: [2 3i 4]
   1.362 +   * Note that I still happily points to object at the second index.
   1.363 +   *
   1.364 +   * @return  object at i'th index
   1.365 +   */
   1.366 +  void* GetCurrent();
   1.367 +
   1.368 +  /**
   1.369 +   * Call this method when you want to iterate all the
   1.370 +   * members of the container, passing a functor along
   1.371 +   * to call your code.
   1.372 +   *
   1.373 +   * @param   aFunctor object to call for each member
   1.374 +   * @return  *this
   1.375 +   */
   1.376 +  void ForEach(nsDequeFunctor& aFunctor) const;
   1.377 +
   1.378 +  /**
   1.379 +   * Call this method when you want to iterate all the
   1.380 +   * members of the container, calling the functor you 
   1.381 +   * passed with each member. This process will interrupt
   1.382 +   * if your function returns non 0 to this method.
   1.383 +   *
   1.384 +   * @param   aFunctor object to call for each member
   1.385 +   * @return  first nonzero result of aFunctor or 0.
   1.386 +   */
   1.387 +  const void* FirstThat(nsDequeFunctor& aFunctor) const;
   1.388 +
   1.389 +  protected:
   1.390 +
   1.391 +  int32_t         mIndex;
   1.392 +  const nsDeque&  mDeque;
   1.393 +};
   1.394 +#endif

mercurial