PageRenderTime 38ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/gecko_api/include/nsVoidArray.h

http://firefox-mac-pdf.googlecode.com/
C Header | 441 lines | 255 code | 89 blank | 97 comment | 8 complexity | 2b24cbaa872b8c8699f84699b6d5210f MD5 | raw file
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; c-file-offsets: ((substatement-open . 0)) -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * The Original Code is mozilla.org code.
  16. *
  17. * The Initial Developer of the Original Code is
  18. * Netscape Communications Corporation.
  19. * Portions created by the Initial Developer are Copyright (C) 1998
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either of the GNU General Public License Version 2 or later (the "GPL"),
  26. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. #ifndef nsVoidArray_h___
  38. #define nsVoidArray_h___
  39. //#define DEBUG_VOIDARRAY 1
  40. #include "nscore.h"
  41. #include "nsStringGlue.h"
  42. #include "nsDebug.h"
  43. // Comparator callback function for sorting array values.
  44. typedef int (* PR_CALLBACK nsVoidArrayComparatorFunc)
  45. (const void* aElement1, const void* aElement2, void* aData);
  46. // Enumerator callback function. Return PR_FALSE to stop
  47. typedef PRBool (* PR_CALLBACK nsVoidArrayEnumFunc)(void* aElement, void *aData);
  48. /// A basic zero-based array of void*'s that manages its own memory
  49. class NS_COM_GLUE nsVoidArray {
  50. public:
  51. nsVoidArray();
  52. nsVoidArray(PRInt32 aCount); // initial count of aCount elements set to nsnull
  53. ~nsVoidArray();
  54. nsVoidArray& operator=(const nsVoidArray& other);
  55. inline PRInt32 Count() const {
  56. return mImpl ? mImpl->mCount : 0;
  57. }
  58. // returns the max number that can be held without allocating
  59. inline PRInt32 GetArraySize() const {
  60. return mImpl ? (PRInt32(mImpl->mBits) & kArraySizeMask) : 0;
  61. }
  62. void* FastElementAt(PRInt32 aIndex) const
  63. {
  64. NS_ASSERTION(0 <= aIndex && aIndex < Count(), "nsVoidArray::FastElementAt: index out of range");
  65. return mImpl->mArray[aIndex];
  66. }
  67. // This both asserts and bounds-checks, because (1) we don't want
  68. // people to write bad code, but (2) we don't want to change it to
  69. // crashing for backwards compatibility. See bug 96108.
  70. void* ElementAt(PRInt32 aIndex) const
  71. {
  72. NS_ASSERTION(0 <= aIndex && aIndex < Count(), "nsVoidArray::ElementAt: index out of range");
  73. return SafeElementAt(aIndex);
  74. }
  75. // bounds-checked version
  76. void* SafeElementAt(PRInt32 aIndex) const
  77. {
  78. if (PRUint32(aIndex) >= PRUint32(Count())) // handles aIndex < 0 too
  79. {
  80. return nsnull;
  81. }
  82. // The bounds check ensures mImpl is non-null.
  83. return mImpl->mArray[aIndex];
  84. }
  85. void* operator[](PRInt32 aIndex) const { return ElementAt(aIndex); }
  86. PRInt32 IndexOf(void* aPossibleElement) const;
  87. PRBool InsertElementAt(void* aElement, PRInt32 aIndex);
  88. PRBool InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex);
  89. PRBool ReplaceElementAt(void* aElement, PRInt32 aIndex);
  90. // useful for doing LRU arrays, sorting, etc
  91. PRBool MoveElement(PRInt32 aFrom, PRInt32 aTo);
  92. PRBool AppendElement(void* aElement) {
  93. return InsertElementAt(aElement, Count());
  94. }
  95. PRBool AppendElements(nsVoidArray& aElements) {
  96. return InsertElementsAt(aElements, Count());
  97. }
  98. PRBool RemoveElement(void* aElement);
  99. PRBool RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount);
  100. PRBool RemoveElementAt(PRInt32 aIndex) { return RemoveElementsAt(aIndex,1); }
  101. void Clear();
  102. PRBool SizeTo(PRInt32 aMin);
  103. // Subtly different - Compact() tries to be smart about whether we
  104. // should reallocate the array; SizeTo() always reallocates.
  105. void Compact();
  106. void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
  107. PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
  108. PRBool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
  109. protected:
  110. PRBool GrowArrayBy(PRInt32 aGrowBy);
  111. struct Impl {
  112. /**
  113. * Packed bits. The low 30 bits are the array's size.
  114. * The two highest bits indicate whether or not we "own" mImpl and
  115. * must free() it when destroyed, and whether we have a preallocated
  116. * nsAutoVoidArray buffer.
  117. */
  118. PRUint32 mBits;
  119. /**
  120. * The number of elements in the array
  121. */
  122. PRInt32 mCount;
  123. /**
  124. * Array data, padded out to the actual size of the array.
  125. */
  126. void* mArray[1];
  127. };
  128. Impl* mImpl;
  129. #if DEBUG_VOIDARRAY
  130. PRInt32 mMaxCount;
  131. PRInt32 mMaxSize;
  132. PRBool mIsAuto;
  133. #endif
  134. enum {
  135. kArrayOwnerMask = 1 << 31,
  136. kArrayHasAutoBufferMask = 1 << 30,
  137. kArraySizeMask = ~(kArrayOwnerMask | kArrayHasAutoBufferMask)
  138. };
  139. enum { kAutoBufSize = 8 };
  140. // bit twiddlers
  141. void SetArray(Impl *newImpl, PRInt32 aSize, PRInt32 aCount, PRBool aOwner,
  142. PRBool aHasAuto);
  143. inline PRBool IsArrayOwner() const {
  144. return mImpl && (mImpl->mBits & kArrayOwnerMask);
  145. }
  146. inline PRBool HasAutoBuffer() const {
  147. return mImpl && (mImpl->mBits & kArrayHasAutoBufferMask);
  148. }
  149. private:
  150. /// Copy constructors are not allowed
  151. nsVoidArray(const nsVoidArray& other);
  152. };
  153. // A zero-based array with a bit of automatic internal storage
  154. class NS_COM_GLUE nsAutoVoidArray : public nsVoidArray {
  155. public:
  156. nsAutoVoidArray();
  157. void ResetToAutoBuffer()
  158. {
  159. SetArray(reinterpret_cast<Impl*>(mAutoBuf), kAutoBufSize, 0, PR_FALSE,
  160. PR_TRUE);
  161. }
  162. protected:
  163. // The internal storage
  164. char mAutoBuf[sizeof(Impl) + (kAutoBufSize - 1) * sizeof(void*)];
  165. };
  166. class nsString;
  167. typedef int (* PR_CALLBACK nsStringArrayComparatorFunc)
  168. (const nsString* aElement1, const nsString* aElement2, void* aData);
  169. typedef PRBool (*nsStringArrayEnumFunc)(nsString& aElement, void *aData);
  170. class NS_COM_GLUE nsStringArray: private nsVoidArray
  171. {
  172. public:
  173. nsStringArray(void);
  174. nsStringArray(PRInt32 aCount); // Storage for aCount elements will be pre-allocated
  175. ~nsStringArray(void);
  176. nsStringArray& operator=(const nsStringArray& other);
  177. PRInt32 Count(void) const {
  178. return nsVoidArray::Count();
  179. }
  180. void StringAt(PRInt32 aIndex, nsAString& aString) const;
  181. nsString* StringAt(PRInt32 aIndex) const;
  182. nsString* operator[](PRInt32 aIndex) const { return StringAt(aIndex); }
  183. PRInt32 IndexOf(const nsAString& aPossibleString) const;
  184. PRBool InsertStringAt(const nsAString& aString, PRInt32 aIndex);
  185. PRBool ReplaceStringAt(const nsAString& aString, PRInt32 aIndex);
  186. PRBool AppendString(const nsAString& aString) {
  187. return InsertStringAt(aString, Count());
  188. }
  189. PRBool RemoveString(const nsAString& aString);
  190. PRBool RemoveStringAt(PRInt32 aIndex);
  191. void Clear(void);
  192. void Compact(void) {
  193. nsVoidArray::Compact();
  194. }
  195. void Sort(void);
  196. void Sort(nsStringArrayComparatorFunc aFunc, void* aData);
  197. PRBool EnumerateForwards(nsStringArrayEnumFunc aFunc, void* aData);
  198. PRBool EnumerateBackwards(nsStringArrayEnumFunc aFunc, void* aData);
  199. private:
  200. /// Copy constructors are not allowed
  201. nsStringArray(const nsStringArray& other);
  202. };
  203. class nsCString;
  204. typedef int (* PR_CALLBACK nsCStringArrayComparatorFunc)
  205. (const nsCString* aElement1, const nsCString* aElement2, void* aData);
  206. typedef PRBool (*nsCStringArrayEnumFunc)(nsCString& aElement, void *aData);
  207. class NS_COM_GLUE nsCStringArray: private nsVoidArray
  208. {
  209. public:
  210. nsCStringArray(void);
  211. nsCStringArray(PRInt32 aCount); // Storage for aCount elements will be pre-allocated
  212. ~nsCStringArray(void);
  213. nsCStringArray& operator=(const nsCStringArray& other);
  214. // Parses a given string using the delimiter passed in. If the array
  215. // already has some elements, items parsed from string will be appended
  216. // to array. For example, array.ParseString("a,b,c", ","); will add strings
  217. // "a", "b" and "c" to the array. Parsing process has the same tokenizing
  218. // behavior as strtok().
  219. PRBool ParseString(const char* string, const char* delimiter);
  220. PRInt32 Count(void) const {
  221. return nsVoidArray::Count();
  222. }
  223. void CStringAt(PRInt32 aIndex, nsACString& aCString) const;
  224. nsCString* CStringAt(PRInt32 aIndex) const;
  225. nsCString* operator[](PRInt32 aIndex) const { return CStringAt(aIndex); }
  226. PRInt32 IndexOf(const nsACString& aPossibleString) const;
  227. #ifdef MOZILLA_INTERNAL_API
  228. PRInt32 IndexOfIgnoreCase(const nsACString& aPossibleString) const;
  229. #endif
  230. PRBool InsertCStringAt(const nsACString& aCString, PRInt32 aIndex);
  231. PRBool ReplaceCStringAt(const nsACString& aCString, PRInt32 aIndex);
  232. PRBool AppendCString(const nsACString& aCString) {
  233. return InsertCStringAt(aCString, Count());
  234. }
  235. PRBool RemoveCString(const nsACString& aCString);
  236. #ifdef MOZILLA_INTERNAL_API
  237. PRBool RemoveCStringIgnoreCase(const nsACString& aCString);
  238. #endif
  239. PRBool RemoveCStringAt(PRInt32 aIndex);
  240. void Clear(void);
  241. void Compact(void) {
  242. nsVoidArray::Compact();
  243. }
  244. void Sort(void);
  245. #ifdef MOZILLA_INTERNAL_API
  246. void SortIgnoreCase(void);
  247. #endif
  248. void Sort(nsCStringArrayComparatorFunc aFunc, void* aData);
  249. PRBool EnumerateForwards(nsCStringArrayEnumFunc aFunc, void* aData);
  250. PRBool EnumerateBackwards(nsCStringArrayEnumFunc aFunc, void* aData);
  251. private:
  252. /// Copy constructors are not allowed
  253. nsCStringArray(const nsCStringArray& other);
  254. };
  255. //===================================================================
  256. // nsSmallVoidArray is not a general-purpose replacement for
  257. // ns(Auto)VoidArray because there is (some) extra CPU overhead for arrays
  258. // larger than 1 element, though not a lot. It is appropriate for
  259. // space-sensitive uses where sizes of 0 or 1 are moderately common or
  260. // more, and where we're NOT storing arbitrary integers or arbitrary
  261. // pointers.
  262. // NOTE: nsSmallVoidArray can ONLY be used for holding items that always
  263. // have the low bit as a 0 - i.e. element & 1 == 0. This happens to be
  264. // true for allocated and object pointers for all the architectures we run
  265. // on, but conceivably there might be some architectures/compilers for
  266. // which it is NOT true. We know this works for all existing architectures
  267. // because if it didn't then nsCheapVoidArray would have failed. Also note
  268. // that we will ASSERT if this assumption is violated in DEBUG builds.
  269. // XXX we're really re-implementing the whole nsVoidArray interface here -
  270. // some form of abstract class would be useful
  271. // I disagree on the abstraction here. If the point of this class is to be
  272. // as small as possible, and no one will ever derive from it, as I found
  273. // today, there should not be any virtualness to it to avoid the vtable
  274. // ptr overhead.
  275. class NS_COM_GLUE nsSmallVoidArray : private nsVoidArray
  276. {
  277. public:
  278. ~nsSmallVoidArray();
  279. nsSmallVoidArray& operator=(nsSmallVoidArray& other);
  280. void* operator[](PRInt32 aIndex) const { return ElementAt(aIndex); }
  281. PRInt32 GetArraySize() const;
  282. PRInt32 Count() const;
  283. void* FastElementAt(PRInt32 aIndex) const;
  284. // This both asserts and bounds-checks, because (1) we don't want
  285. // people to write bad code, but (2) we don't want to change it to
  286. // crashing for backwards compatibility. See bug 96108.
  287. void* ElementAt(PRInt32 aIndex) const
  288. {
  289. NS_ASSERTION(0 <= aIndex && aIndex < Count(), "nsSmallVoidArray::ElementAt: index out of range");
  290. return SafeElementAt(aIndex);
  291. }
  292. void* SafeElementAt(PRInt32 aIndex) const {
  293. // let compiler inline; it may be able to remove these checks
  294. if (PRUint32(aIndex) >= PRUint32(Count())) // handles aIndex < 0 too
  295. {
  296. return nsnull;
  297. }
  298. return FastElementAt(aIndex);
  299. }
  300. PRInt32 IndexOf(void* aPossibleElement) const;
  301. PRBool InsertElementAt(void* aElement, PRInt32 aIndex);
  302. PRBool InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex);
  303. PRBool ReplaceElementAt(void* aElement, PRInt32 aIndex);
  304. PRBool MoveElement(PRInt32 aFrom, PRInt32 aTo);
  305. PRBool AppendElement(void* aElement);
  306. PRBool AppendElements(nsVoidArray& aElements) {
  307. return InsertElementsAt(aElements, Count());
  308. }
  309. PRBool RemoveElement(void* aElement);
  310. PRBool RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount);
  311. PRBool RemoveElementAt(PRInt32 aIndex);
  312. void Clear();
  313. PRBool SizeTo(PRInt32 aMin);
  314. void Compact();
  315. void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
  316. PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
  317. PRBool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
  318. private:
  319. PRBool HasSingle() const
  320. {
  321. return !!(reinterpret_cast<PRWord>(mImpl) & 0x1);
  322. }
  323. void* GetSingle() const
  324. {
  325. NS_ASSERTION(HasSingle(), "wrong type");
  326. return reinterpret_cast<void*>
  327. (reinterpret_cast<PRWord>(mImpl) & ~0x1);
  328. }
  329. void SetSingle(void *aChild)
  330. {
  331. NS_ASSERTION(HasSingle() || !mImpl, "overwriting array");
  332. mImpl = reinterpret_cast<Impl*>
  333. (reinterpret_cast<PRWord>(aChild) | 0x1);
  334. }
  335. PRBool IsEmpty() const
  336. {
  337. // Note that this isn't the same as Count()==0
  338. return !mImpl;
  339. }
  340. const nsVoidArray* AsArray() const
  341. {
  342. NS_ASSERTION(!HasSingle(), "This is a single");
  343. return this;
  344. }
  345. nsVoidArray* AsArray()
  346. {
  347. NS_ASSERTION(!HasSingle(), "This is a single");
  348. return this;
  349. }
  350. PRBool EnsureArray();
  351. };
  352. #endif /* nsVoidArray_h___ */