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