PageRenderTime 1260ms CodeModel.GetById 122ms app.highlight 995ms RepoModel.GetById 103ms app.codeStats 0ms

/gecko_api/include/nsTArray.h

http://firefox-mac-pdf.googlecode.com/
C++ Header | 796 lines | 382 code | 96 blank | 318 comment | 40 complexity | 85c29b6209d7e3a531da96045eb46cf2 MD5 | raw file
  1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2/* vim:set ts=2 sw=2 sts=2 et cindent: */
  3/* ***** BEGIN LICENSE BLOCK *****
  4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5 *
  6 * The contents of this file are subject to the Mozilla Public License Version
  7 * 1.1 (the "License"); you may not use this file except in compliance with
  8 * the License. You may obtain a copy of the License at
  9 * http://www.mozilla.org/MPL/
 10 *
 11 * Software distributed under the License is distributed on an "AS IS" basis,
 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 13 * for the specific language governing rights and limitations under the
 14 * License.
 15 *
 16 * The Original Code is C++ array template.
 17 *
 18 * The Initial Developer of the Original Code is Google Inc.
 19 * Portions created by the Initial Developer are Copyright (C) 2005
 20 * the Initial Developer. All Rights Reserved.
 21 *
 22 * Contributor(s):
 23 *  Darin Fisher <darin@meer.net>
 24 *
 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.
 36 *
 37 * ***** END LICENSE BLOCK ***** */
 38
 39#ifndef nsTArray_h__
 40#define nsTArray_h__
 41
 42#include "prtypes.h"
 43#include "nsQuickSort.h"
 44#include "nsDebug.h"
 45#include "nsTraceRefcnt.h"
 46#include NEW_H
 47
 48//
 49// This class serves as a base class for nsTArray.  It shouldn't be used
 50// directly.  It holds common implementation code that does not depend on the
 51// element type of the nsTArray.
 52//
 53class NS_COM_GLUE nsTArray_base {
 54  public:
 55    typedef PRUint32 size_type;
 56    typedef PRUint32 index_type;
 57
 58    // A special value that is used to indicate an invalid or unknown index
 59    // into the array.
 60    enum {
 61      NoIndex = index_type(-1)
 62    };
 63
 64    // @return The number of elements in the array.
 65    size_type Length() const {
 66      return mHdr->mLength;
 67    }
 68
 69    // @return True if the array is empty or false otherwise.
 70    PRBool IsEmpty() const {
 71      return Length() == 0;
 72    }
 73
 74    // @return The number of elements that can fit in the array without forcing
 75    // the array to be re-allocated.  The length of an array is always less
 76    // than or equal to its capacity.
 77    size_type Capacity() const {
 78      return mHdr->mCapacity;
 79    }
 80
 81#ifdef DEBUG
 82    void* DebugGetHeader() {
 83      return mHdr;
 84    }
 85#endif
 86
 87  protected:
 88    nsTArray_base();
 89    ~nsTArray_base();  
 90
 91    // Resize the storage if necessary to achieve the requested capacity.
 92    // @param capacity     The requested number of array elements.
 93    // @param elementSize  The size of an array element.
 94    // @return False if insufficient memory is available; true otherwise.
 95    PRBool EnsureCapacity(size_type capacity, size_type elementSize);
 96
 97    // Resize the storage to the minimum required amount.
 98    // @param elementSize  The size of an array element.
 99    void ShrinkCapacity(size_type elementSize);
100    
101    // This method may be called to resize a "gap" in the array by shifting
102    // elements around.  It updates mLength appropriately.  If the resulting
103    // array has zero elements, then the array's memory is free'd.
104    // @param start        The starting index of the gap.
105    // @param oldLen       The current length of the gap.
106    // @param newLen       The desired length of the gap.
107    // @param elementSize  The size of an array element.
108    void ShiftData(index_type start, size_type oldLen, size_type newLen,
109                   size_type elementSize);
110
111    // This method increments the length member of the array's header.
112    // Note that mHdr may actually be sEmptyHdr in the case where a
113    // zero-length array is inserted into our array. But then n should
114    // always be 0.
115    void IncrementLength(PRUint32 n) {
116      NS_ASSERTION(mHdr != &sEmptyHdr || n == 0, "bad data pointer");
117      mHdr->mLength += n;
118    }
119
120    // This method inserts blank slots into the array.
121    // @param index the place to insert the new elements. This must be no
122    //              greater than the current length of the array.
123    // @param count the number of slots to insert
124    // @param elementSize the size of an array element.
125    PRBool InsertSlotsAt(index_type index, size_type count,
126                         size_type elementSize);
127
128  protected:
129
130    // NOTE: This method isn't heavily optimized if either array is an
131    // nsAutoTArray.
132    PRBool SwapArrayElements(nsTArray_base& other, size_type elementSize);
133
134    // Helper function for SwapArrayElements. Ensures that if the array
135    // is an nsAutoTArray that it doesn't use the built-in buffer.
136    PRBool EnsureNotUsingAutoArrayBuffer(size_type elemSize);
137
138    // We prefix mData with a structure of this type.  This is done to minimize
139    // the size of the nsTArray object when it is empty.
140    struct Header {
141      PRUint32 mLength;
142      PRUint32 mCapacity : 31;
143      PRUint32 mIsAutoArray : 1;
144    };
145
146    // Returns true if this nsTArray is an nsAutoTArray with a built-in buffer.
147    PRBool IsAutoArray() {
148      return mHdr->mIsAutoArray;
149    }
150
151    // Returns a Header for the built-in buffer of this nsAutoTArray.
152    Header* GetAutoArrayBuffer() {
153      NS_ASSERTION(IsAutoArray(), "Should be an auto array to call this");
154
155      return reinterpret_cast<Header*>(&mHdr + 1);
156    }
157
158    // Returns true if this is an nsAutoTArray and it currently uses the
159    // built-in buffer to store its elements.
160    PRBool UsesAutoArrayBuffer() {
161      return mHdr->mIsAutoArray && mHdr == GetAutoArrayBuffer();
162    }
163
164    // This is not const since we may actually write to it. However we will
165    // always write to it the same data that it already contains. See
166    // IncrementLength
167    static Header sEmptyHdr;
168
169    // The array's elements (prefixed with a Header).  This pointer is never
170    // null.  If the array is empty, then this will point to sEmptyHdr.
171    Header *mHdr;
172};
173
174//
175// This class defines convenience functions for element specific operations.
176// Specialize this template if necessary.
177//
178template<class E>
179class nsTArrayElementTraits {
180  public:
181    // Invoke the default constructor in place.
182    static inline void Construct(E *e) {
183      // Do NOT call "E()"! That triggers C++ "default initialization"
184      // which zeroes out POD ("plain old data") types such as regular ints.
185      // We don't want that because it can be a performance issue and people
186      // don't expect it; nsTArray should work like a regular C/C++ array in
187      // this respect.
188      new (static_cast<void *>(e)) E;
189    }
190    // Invoke the copy-constructor in place.
191    template<class A>
192    static inline void Construct(E *e, const A &arg) {
193      new (static_cast<void *>(e)) E(arg);
194    }
195    // Invoke the destructor in place.
196    static inline void Destruct(E *e) {
197      e->~E();
198    }
199};
200
201// This class exists because VC6 cannot handle static template functions.
202// Otherwise, the Compare method would be defined directly on nsTArray.
203template <class E, class Comparator>
204class nsQuickSortComparator {
205  public:
206    typedef E elem_type;
207    // This function is meant to be used with the NS_QuickSort function.  It
208    // maps the callback API expected by NS_QuickSort to the Comparator API
209    // used by nsTArray.  See nsTArray::Sort.
210    static int Compare(const void* e1, const void* e2, void *data) {
211      const Comparator* c = reinterpret_cast<const Comparator*>(data);
212      const elem_type* a = static_cast<const elem_type*>(e1);
213      const elem_type* b = static_cast<const elem_type*>(e2);
214      return c->LessThan(*a, *b) ? -1 : (c->Equals(*a, *b) ? 0 : 1);
215    }
216};
217
218// The default comparator used by nsTArray
219template<class A, class B>
220class nsDefaultComparator {
221  public:
222    PRBool Equals(const A& a, const B& b) const {
223      return a == b;
224    }
225    PRBool LessThan(const A& a, const B& b) const {
226      return a < b;
227    }
228};
229
230//
231// The templatized array class that dynamically resizes its storage as elements
232// are added.  This class is designed to behave a bit like std::vector.
233//
234// The template parameter specifies the type of the elements (elem_type), and
235// has the following requirements:
236//
237//   elem_type MUST define a copy-constructor.
238//   elem_type MAY define operator< for sorting.
239//   elem_type MAY define operator== for searching.
240//
241// For methods taking a Comparator instance, the Comparator must be a class
242// defining the following methods:
243//
244//   class Comparator {
245//     public:
246//       /** @return True if the elements are equals; false otherwise. */
247//       PRBool Equals(const elem_type& a, const elem_type& b) const;
248//
249//       /** @return True if (a < b); false otherwise. */
250//       PRBool LessThan(const elem_type& a, const elem_type& b) const;
251//   };
252//
253// The Equals method is used for searching, and the LessThan method is used
254// for sorting.
255//
256template<class E>
257class nsTArray : public nsTArray_base {
258  public:
259    typedef E                        elem_type;
260    typedef nsTArray<E>              self_type;
261    typedef nsTArrayElementTraits<E> elem_traits;
262
263    //
264    // Finalization method
265    //
266
267    ~nsTArray() { Clear(); }
268
269    //
270    // Initialization methods
271    //
272
273    nsTArray() {}
274
275    // Initialize this array and pre-allocate some number of elements.
276    explicit nsTArray(size_type capacity) {
277      SetCapacity(capacity);
278    }
279    
280    // The array's copy-constructor performs a 'deep' copy of the given array.
281    // @param other  The array object to copy.
282    nsTArray(const self_type& other) {
283      AppendElements(other);
284    }
285
286    // The array's assignment operator performs a 'deep' copy of the given
287    // array.  It is optimized to reuse existing storage if possible.
288    // @param other  The array object to copy.
289    nsTArray& operator=(const self_type& other) {
290      ReplaceElementsAt(0, Length(), other.Elements(), other.Length());
291      return *this;
292    }
293
294    //
295    // Accessor methods
296    //
297
298    // This method provides direct access to the array elements.
299    // @return A pointer to the first element of the array.  If the array is
300    // empty, then this pointer must not be dereferenced.
301    elem_type* Elements() {
302      return reinterpret_cast<elem_type *>(mHdr + 1);
303    }
304
305    // This method provides direct, readonly access to the array elements.
306    // @return A pointer to the first element of the array.  If the array is
307    // empty, then this pointer must not be dereferenced.
308    const elem_type* Elements() const {
309      return reinterpret_cast<const elem_type *>(mHdr + 1);
310    }
311    
312    // This method provides direct access to the i'th element of the array.
313    // The given index must be within the array bounds.
314    // @param i  The index of an element in the array.
315    // @return   A reference to the i'th element of the array.
316    elem_type& ElementAt(index_type i) {
317      NS_ASSERTION(i < Length(), "invalid array index");
318      return Elements()[i];
319    }
320
321    // This method provides direct, readonly access to the i'th element of the
322    // array.  The given index must be within the array bounds.
323    // @param i  The index of an element in the array.
324    // @return   A const reference to the i'th element of the array.
325    const elem_type& ElementAt(index_type i) const {
326      NS_ASSERTION(i < Length(), "invalid array index");
327      return Elements()[i];
328    }
329
330    // This method provides direct access to the i'th element of the array in
331    // a bounds safe manner. If the requested index is out of bounds the
332    // provided default value is returned.
333    // @param i  The index of an element in the array.
334    // @param def The value to return if the index is out of bounds.
335    elem_type& SafeElementAt(index_type i, elem_type& def) {
336      return i < Length() ? Elements()[i] : def;
337    }
338
339    // This method provides direct access to the i'th element of the array in
340    // a bounds safe manner. If the requested index is out of bounds the
341    // provided default value is returned.
342    // @param i  The index of an element in the array.
343    // @param def The value to return if the index is out of bounds.
344    const elem_type& SafeElementAt(index_type i, const elem_type& def) const {
345      return i < Length() ? Elements()[i] : def;
346    }
347
348    // Shorthand for ElementAt(i)
349    elem_type& operator[](index_type i) {
350      return ElementAt(i);
351    }
352
353    // Shorthand for ElementAt(i)
354    const elem_type& operator[](index_type i) const {
355      return ElementAt(i);
356    }
357
358    //
359    // Search methods
360    //
361
362    // This method searches for the first element in this array that is equal
363    // to the given element.
364    // @param item   The item to search for.
365    // @param comp   The Comparator used to determine element equality.
366    // @return       PR_TRUE if the element was found.
367    template<class Item, class Comparator>
368    PRBool Contains(const Item& item, const Comparator& comp) const {
369      return IndexOf(item, 0, comp) != NoIndex;
370    }
371
372    // This method searches for the first element in this array that is equal
373    // to the given element.  This method assumes that 'operator==' is defined
374    // for elem_type.
375    // @param item   The item to search for.
376    // @return       PR_TRUE if the element was found.
377    template<class Item>
378    PRBool Contains(const Item& item) const {
379      return IndexOf(item) != NoIndex;
380    }
381
382    // This method searches for the offset of the first element in this
383    // array that is equal to the given element.
384    // @param item   The item to search for.
385    // @param start  The index to start from.
386    // @param comp   The Comparator used to determine element equality.
387    // @return       The index of the found element or NoIndex if not found.
388    template<class Item, class Comparator>
389    index_type IndexOf(const Item& item, index_type start,
390                       const Comparator& comp) const {
391      const elem_type* iter = Elements() + start, *end = iter + Length();
392      for (; iter != end; ++iter) {
393        if (comp.Equals(*iter, item))
394          return iter - Elements();
395      }
396      return NoIndex;
397    }
398
399    // This method searches for the offset of the first element in this
400    // array that is equal to the given element.  This method assumes
401    // that 'operator==' is defined for elem_type.
402    // @param item   The item to search for.
403    // @param start  The index to start from.
404    // @return       The index of the found element or NoIndex if not found.
405    template<class Item>
406    index_type IndexOf(const Item& item, index_type start = 0) const {
407      return IndexOf(item, start, nsDefaultComparator<elem_type, Item>());
408    }
409
410    // This method searches for the offset of the last element in this
411    // array that is equal to the given element.
412    // @param item   The item to search for.
413    // @param start  The index to start from.  If greater than or equal to the
414    //               length of the array, then the entire array is searched.
415    // @param comp   The Comparator used to determine element equality.
416    // @return       The index of the found element or NoIndex if not found.
417    template<class Item, class Comparator>
418    index_type LastIndexOf(const Item& item, index_type start,
419                           const Comparator& comp) const {
420      if (start >= Length())
421        start = Length() - 1;
422      const elem_type* end = Elements() - 1, *iter = end + start + 1;
423      for (; iter != end; --iter) {
424        if (comp.Equals(*iter, item))
425          return iter - Elements();
426      }
427      return NoIndex;
428    }
429
430    // This method searches for the offset of the last element in this
431    // array that is equal to the given element.  This method assumes
432    // that 'operator==' is defined for elem_type.
433    // @param item   The item to search for.
434    // @param start  The index to start from.  If greater than or equal to the
435    //               length of the array, then the entire array is searched.
436    // @return       The index of the found element or NoIndex if not found.
437    template<class Item>
438    index_type LastIndexOf(const Item& item,
439                           index_type start = NoIndex) const {
440      return LastIndexOf(item, start, nsDefaultComparator<elem_type, Item>());
441    }
442
443    // This method searches for the offset for the element in this array
444    // that is equal to the given element. The array is assumed to be sorted.
445    // @param item   The item to search for.
446    // @param comp   The Comparator used.
447    // @return       The index of the found element or NoIndex if not found.
448    template<class Item, class Comparator>
449    index_type BinaryIndexOf(const Item& item, const Comparator& comp) const {
450      index_type low = 0, high = Length();
451      while (high > low) {
452        index_type mid = (high + low) >> 1;
453        if (comp.Equals(ElementAt(mid), item))
454          return mid;
455        if (comp.LessThan(ElementAt(mid), item))
456          low = mid + 1;
457        else
458          high = mid;
459      }
460      return NoIndex;
461    }
462
463    // This method searches for the offset for the element in this array
464    // that is equal to the given element. The array is assumed to be sorted.
465    // This method assumes that 'operator==' and 'operator<' are defined.
466    // @param item   The item to search for.
467    // @return       The index of the found element or NoIndex if not found.
468    template<class Item>
469    index_type BinaryIndexOf(const Item& item) const {
470      return BinaryIndexOf(item, nsDefaultComparator<elem_type, Item>());
471    }
472
473    //
474    // Mutation methods
475    //
476
477    // This method replaces a range of elements in this array.
478    // @param start     The starting index of the elements to replace.
479    // @param count     The number of elements to replace.  This may be zero to
480    //                  insert elements without removing any existing elements.
481    // @param array     The values to copy into this array.  Must be non-null,
482    //                  and these elements must not already exist in the array
483    //                  being modified.
484    // @param arrayLen  The number of values to copy into this array.
485    // @return          A pointer to the new elements in the array, or null if
486    //                  the operation failed due to insufficient memory.
487    template<class Item>
488    elem_type *ReplaceElementsAt(index_type start, size_type count,
489                                 const Item* array, size_type arrayLen) {
490      // Adjust memory allocation up-front to catch errors.
491      if (!EnsureCapacity(Length() + arrayLen - count, sizeof(elem_type)))
492        return nsnull;
493      DestructRange(start, count);
494      ShiftData(start, count, arrayLen, sizeof(elem_type));
495      AssignRange(start, arrayLen, array);
496      return Elements() + start;
497    }
498
499    // A variation on the ReplaceElementsAt method defined above.
500    template<class Item>
501    elem_type *ReplaceElementsAt(index_type start, size_type count,
502                                 const nsTArray<Item>& array) {
503      return ReplaceElementsAt(start, count, array.Elements(), array.Length());
504    }
505
506    // A variation on the ReplaceElementsAt method defined above.
507    template<class Item>
508    elem_type *ReplaceElementsAt(index_type start, size_type count,
509                                 const Item& item) {
510      return ReplaceElementsAt(start, count, &item, 1);
511    }
512    
513    // A variation on the ReplaceElementsAt method defined above.
514    template<class Item>
515    elem_type *InsertElementsAt(index_type index, const Item* array,
516                                size_type arrayLen) {
517      return ReplaceElementsAt(index, 0, array, arrayLen);
518    }
519
520    // A variation on the ReplaceElementsAt method defined above.
521    template<class Item>
522    elem_type *InsertElementsAt(index_type index, const nsTArray<Item>& array) {
523      return ReplaceElementsAt(index, 0, array.Elements(), array.Length());
524    }
525
526    // A variation on the ReplaceElementsAt method defined above.
527    template<class Item>
528    elem_type *InsertElementAt(index_type index, const Item& item) {
529      return ReplaceElementsAt(index, 0, &item, 1);
530    }
531
532    // Insert a new element without copy-constructing. This is useful to avoid
533    // temporaries.
534    // @return A pointer to the newly inserted element, or null on OOM.
535    elem_type* InsertElementAt(index_type index) {
536      if (!EnsureCapacity(Length() + 1, sizeof(elem_type)))
537         return nsnull;
538      ShiftData(index, 0, 1, sizeof(elem_type));
539      elem_type *elem = Elements() + index;
540      elem_traits::Construct(elem);
541      return elem;
542    }
543
544    // This method appends elements to the end of this array.
545    // @param array     The elements to append to this array.
546    // @param arrayLen  The number of elements to append to this array.
547    // @return          A pointer to the new elements in the array, or null if
548    //                  the operation failed due to insufficient memory.
549    template<class Item>
550    elem_type *AppendElements(const Item* array, size_type arrayLen) {
551      if (!EnsureCapacity(Length() + arrayLen, sizeof(elem_type)))
552        return nsnull;
553      index_type len = Length();
554      AssignRange(len, arrayLen, array);
555      IncrementLength(arrayLen);
556      return Elements() + len;
557    }
558
559    // A variation on the AppendElements method defined above.
560    template<class Item>
561    elem_type *AppendElements(const nsTArray<Item>& array) {
562      return AppendElements(array.Elements(), array.Length());
563    }
564
565    // A variation on the AppendElements method defined above.
566    template<class Item>
567    elem_type *AppendElement(const Item& item) {
568      return AppendElements(&item, 1);
569    }
570
571    // Append new elements without copy-constructing. This is useful to avoid
572    // temporaries.
573    // @return A pointer to the newly appended elements, or null on OOM.
574    elem_type *AppendElements(size_type count) {
575      if (!EnsureCapacity(Length() + count, sizeof(elem_type)))
576         return nsnull;
577      elem_type *elems = Elements() + Length();
578      size_type i;
579      for (i = 0; i < count; ++i) {
580        elem_traits::Construct(elems + i);
581      }
582      IncrementLength(count);
583      return elems;
584    }
585
586    // Append a new element without copy-constructing. This is useful to avoid
587    // temporaries.
588    // @return A pointer to the newly appended element, or null on OOM.
589    elem_type *AppendElement() {
590      return AppendElements(1);
591    }
592
593    // This method removes a range of elements from this array.
594    // @param start  The starting index of the elements to remove.
595    // @param count  The number of elements to remove.
596    void RemoveElementsAt(index_type start, size_type count) {
597      NS_ASSERTION(count == 0 || start < Length(), "Invalid start index");
598      NS_ASSERTION(start + count <= Length(), "Invalid length");
599      DestructRange(start, count);
600      ShiftData(start, count, 0, sizeof(elem_type));
601    }
602
603    // A variation on the RemoveElementsAt method defined above.
604    void RemoveElementAt(index_type index) {
605      RemoveElementsAt(index, 1);
606    }
607
608    // A variation on the RemoveElementsAt method defined above.
609    void Clear() {
610      RemoveElementsAt(0, Length());
611    }
612
613    // This helper function combines IndexOf with RemoveElementAt to "search
614    // and destroy" the first element that is equal to the given element.
615    // @param item  The item to search for.
616    // @param comp  The Comparator used to determine element equality.
617    // @return PR_TRUE if the element was found
618    template<class Item, class Comparator>
619    PRBool RemoveElement(const Item& item, const Comparator& comp) {
620      index_type i = IndexOf(item, 0, comp);
621      if (i == NoIndex)
622        return PR_FALSE;
623
624      RemoveElementAt(i);
625      return PR_TRUE;
626    }
627
628    // A variation on the RemoveElement method defined above that assumes
629    // that 'operator==' is defined for elem_type.
630    template<class Item>
631    PRBool RemoveElement(const Item& item) {
632      return RemoveElement(item, nsDefaultComparator<elem_type, Item>());
633    }
634
635    // This method causes the elements contained in this array and the given
636    // array to be swapped.
637    // NOTE: This method isn't heavily optimized if either array is an
638    // nsAutoTArray.
639    PRBool SwapElements(self_type& other) {
640      return SwapArrayElements(other, sizeof(elem_type));
641    }
642
643    //
644    // Allocation
645    //
646
647    // This method may increase the capacity of this array object by the
648    // specified amount.  This method may be called in advance of several
649    // AppendElement operations to minimize heap re-allocations.  This method
650    // will not reduce the number of elements in this array.
651    // @param capacity  The desired capacity of this array.
652    // @return True if the operation succeeded; false if we ran out of memory
653    PRBool SetCapacity(size_type capacity) {
654      return EnsureCapacity(capacity, sizeof(elem_type));
655    }
656
657    // This method modifies the length of the array.  If the new length is
658    // larger than the existing length of the array, then new elements will be
659    // constructed using elem_type's default constructor.  Otherwise, this call
660    // removes elements from the array (see also RemoveElementsAt).
661    // @param newLen  The desired length of this array.
662    // @return        True if the operation succeeded; false otherwise.
663    PRBool SetLength(size_type newLen) {
664      size_type oldLen = Length();
665      if (newLen > oldLen) {
666        return InsertElementsAt(oldLen, newLen - oldLen) != nsnull;
667      }
668      
669      RemoveElementsAt(newLen, oldLen - newLen);
670      return PR_TRUE;
671    }
672
673    // This method inserts elements into the array, constructing
674    // them using elem_type's default constructor.
675    // @param index the place to insert the new elements. This must be no
676    //              greater than the current length of the array.
677    // @param count the number of elements to insert
678    elem_type *InsertElementsAt(index_type index, size_type count) {
679      if (!nsTArray_base::InsertSlotsAt(index, count, sizeof(elem_type))) {
680        return nsnull;
681      }
682
683      // Initialize the extra array elements
684      elem_type *iter = Elements() + index, *end = iter + count;
685      for (; iter != end; ++iter) {
686        elem_traits::Construct(iter);
687      }
688
689      return Elements() + index;
690    }
691
692    // This method inserts elements into the array, constructing them
693    // elem_type's copy constructor (or whatever one-arg constructor
694    // happens to match the Item type).
695    // @param index the place to insert the new elements. This must be no
696    //              greater than the current length of the array.
697    // @param count the number of elements to insert.
698    // @param item the value to use when constructing the new elements.
699    template<class Item>
700    elem_type *InsertElementsAt(index_type index, size_type count,
701                                const Item& item) {
702      if (!nsTArray_base::InsertSlotsAt(index, count, sizeof(elem_type))) {
703        return nsnull;
704      }
705
706      // Initialize the extra array elements
707      elem_type *iter = Elements() + index, *end = iter + count;
708      for (; iter != end; ++iter) {
709        elem_traits::Construct(iter, item);
710      }
711
712      return Elements() + index;
713    }
714
715    // This method may be called to minimize the memory used by this array.
716    void Compact() {
717      ShrinkCapacity(sizeof(elem_type));
718    }
719
720    //
721    // Sorting
722    //
723
724    // This method sorts the elements of the array.  It uses the LessThan
725    // method defined on the given Comparator object to collate elements.
726    // @param c  The Comparator to used to collate elements.
727    template<class Comparator>
728    void Sort(const Comparator& comp) {
729      NS_QuickSort(Elements(), Length(), sizeof(elem_type),
730                   nsQuickSortComparator<elem_type, Comparator>::Compare,
731                   const_cast<Comparator*>(&comp));
732    }
733
734    // A variation on the Sort method defined above that assumes that
735    // 'operator<' is defined for elem_type.
736    void Sort() {
737      Sort(nsDefaultComparator<elem_type, elem_type>());
738    }
739
740  protected:
741
742    // This method invokes elem_type's destructor on a range of elements.
743    // @param start  The index of the first element to destroy.
744    // @param count  The number of elements to destroy.
745    void DestructRange(index_type start, size_type count) {
746      elem_type *iter = Elements() + start, *end = iter + count;
747      for (; iter != end; ++iter) {
748        elem_traits::Destruct(iter);
749      }
750    }
751
752    // This method invokes elem_type's copy-constructor on a range of elements.
753    // @param start   The index of the first element to construct.
754    // @param count   The number of elements to construct. 
755    // @param values  The array of elements to copy. 
756    template<class Item>
757    void AssignRange(index_type start, size_type count,
758                     const Item *values) {
759      elem_type *iter = Elements() + start, *end = iter + count;
760      for (; iter != end; ++iter, ++values) {
761        elem_traits::Construct(iter, *values);
762      }
763    }
764};
765
766template<class E, PRUint32 N>
767class nsAutoTArray : public nsTArray<E> {
768  public:
769    typedef nsTArray<E> base_type;
770    typedef typename base_type::Header Header;
771    typedef typename base_type::elem_type elem_type;
772
773    nsAutoTArray() {
774      base_type::mHdr = reinterpret_cast<Header*>(&mAutoBuf);
775      base_type::mHdr->mLength = 0;
776      base_type::mHdr->mCapacity = N;
777      base_type::mHdr->mIsAutoArray = 1;
778
779      NS_ASSERTION(base_type::GetAutoArrayBuffer() ==
780                   reinterpret_cast<Header*>(&mAutoBuf),
781                   "GetAutoArrayBuffer needs to be fixed");
782    }
783
784  protected:
785    char mAutoBuf[sizeof(Header) + N * sizeof(elem_type)];
786};
787
788// specialization for N = 0. this makes the inheritance model easier for
789// templated users of nsAutoTArray.
790template<class E>
791class nsAutoTArray<E, 0> : public nsTArray<E> {
792  public:
793    nsAutoTArray() {}
794};
795
796#endif  // nsTArray_h__