xpcom/glue/nsVoidArray.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; c-file-offsets: ((substatement-open . 0)) -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5 #ifndef nsVoidArray_h___
michael@0 6 #define nsVoidArray_h___
michael@0 7
michael@0 8 //#define DEBUG_VOIDARRAY 1
michael@0 9
michael@0 10 #include "nsDebug.h"
michael@0 11
michael@0 12 #include "mozilla/MemoryReporting.h"
michael@0 13 #include <stdint.h>
michael@0 14
michael@0 15 // Comparator callback function for sorting array values.
michael@0 16 typedef int (* nsVoidArrayComparatorFunc)
michael@0 17 (const void* aElement1, const void* aElement2, void* aData);
michael@0 18
michael@0 19 // Enumerator callback function. Return false to stop
michael@0 20 typedef bool (* nsVoidArrayEnumFunc)(void* aElement, void *aData);
michael@0 21 typedef bool (* nsVoidArrayEnumFuncConst)(const void* aElement, void *aData);
michael@0 22
michael@0 23 // SizeOfExcludingThis callback function.
michael@0 24 typedef size_t (* nsVoidArraySizeOfElementIncludingThisFunc)(const void* aElement,
michael@0 25 mozilla::MallocSizeOf aMallocSizeOf,
michael@0 26 void *aData);
michael@0 27
michael@0 28 /// A basic zero-based array of void*'s that manages its own memory
michael@0 29 class NS_COM_GLUE nsVoidArray {
michael@0 30 public:
michael@0 31 nsVoidArray();
michael@0 32 nsVoidArray(int32_t aCount); // initial count of aCount elements set to nullptr
michael@0 33 ~nsVoidArray();
michael@0 34
michael@0 35 nsVoidArray& operator=(const nsVoidArray& other);
michael@0 36
michael@0 37 inline int32_t Count() const {
michael@0 38 return mImpl ? mImpl->mCount : 0;
michael@0 39 }
michael@0 40 // If the array grows, the newly created entries will all be null
michael@0 41 bool SetCount(int32_t aNewCount);
michael@0 42 // returns the max number that can be held without allocating
michael@0 43 inline int32_t GetArraySize() const {
michael@0 44 return mImpl ? mImpl->mSize : 0;
michael@0 45 }
michael@0 46
michael@0 47 void* FastElementAt(int32_t aIndex) const
michael@0 48 {
michael@0 49 NS_ASSERTION(0 <= aIndex && aIndex < Count(), "nsVoidArray::FastElementAt: index out of range");
michael@0 50 return mImpl->mArray[aIndex];
michael@0 51 }
michael@0 52
michael@0 53 // This both asserts and bounds-checks, because (1) we don't want
michael@0 54 // people to write bad code, but (2) we don't want to change it to
michael@0 55 // crashing for backwards compatibility. See bug 96108.
michael@0 56 void* ElementAt(int32_t aIndex) const
michael@0 57 {
michael@0 58 NS_ASSERTION(0 <= aIndex && aIndex < Count(), "nsVoidArray::ElementAt: index out of range");
michael@0 59 return SafeElementAt(aIndex);
michael@0 60 }
michael@0 61
michael@0 62 // bounds-checked version
michael@0 63 void* SafeElementAt(int32_t aIndex) const
michael@0 64 {
michael@0 65 if (uint32_t(aIndex) >= uint32_t(Count())) // handles aIndex < 0 too
michael@0 66 {
michael@0 67 return nullptr;
michael@0 68 }
michael@0 69 // The bounds check ensures mImpl is non-null.
michael@0 70 return mImpl->mArray[aIndex];
michael@0 71 }
michael@0 72
michael@0 73 void* operator[](int32_t aIndex) const { return ElementAt(aIndex); }
michael@0 74
michael@0 75 int32_t IndexOf(void* aPossibleElement) const;
michael@0 76
michael@0 77 bool InsertElementAt(void* aElement, int32_t aIndex);
michael@0 78 bool InsertElementsAt(const nsVoidArray &other, int32_t aIndex);
michael@0 79
michael@0 80 bool ReplaceElementAt(void* aElement, int32_t aIndex);
michael@0 81
michael@0 82 // useful for doing LRU arrays, sorting, etc
michael@0 83 bool MoveElement(int32_t aFrom, int32_t aTo);
michael@0 84
michael@0 85 bool AppendElement(void* aElement) {
michael@0 86 return InsertElementAt(aElement, Count());
michael@0 87 }
michael@0 88
michael@0 89 bool AppendElements(nsVoidArray& aElements) {
michael@0 90 return InsertElementsAt(aElements, Count());
michael@0 91 }
michael@0 92
michael@0 93 bool RemoveElement(void* aElement);
michael@0 94 void RemoveElementsAt(int32_t aIndex, int32_t aCount);
michael@0 95 void RemoveElementAt(int32_t aIndex) { return RemoveElementsAt(aIndex,1); }
michael@0 96
michael@0 97 void Clear();
michael@0 98
michael@0 99 bool SizeTo(int32_t aMin);
michael@0 100 // Subtly different - Compact() tries to be smart about whether we
michael@0 101 // should reallocate the array; SizeTo() always reallocates.
michael@0 102 void Compact();
michael@0 103
michael@0 104 void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
michael@0 105
michael@0 106 bool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
michael@0 107 bool EnumerateForwards(nsVoidArrayEnumFuncConst aFunc, void* aData) const;
michael@0 108 bool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
michael@0 109
michael@0 110 // Measures the size of the array's element storage, and if
michael@0 111 // |aSizeOfElementIncludingThis| is non-nullptr, measures the size of things
michael@0 112 // pointed to by elements.
michael@0 113 size_t SizeOfExcludingThis(
michael@0 114 nsVoidArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
michael@0 115 mozilla::MallocSizeOf aMallocSizeOf, void* aData = nullptr) const;
michael@0 116
michael@0 117 protected:
michael@0 118 bool GrowArrayBy(int32_t aGrowBy);
michael@0 119
michael@0 120 struct Impl {
michael@0 121 /**
michael@0 122 * The actual array size.
michael@0 123 */
michael@0 124 int32_t mSize;
michael@0 125
michael@0 126 /**
michael@0 127 * The number of elements in the array
michael@0 128 */
michael@0 129 int32_t mCount;
michael@0 130
michael@0 131 /**
michael@0 132 * Array data, padded out to the actual size of the array.
michael@0 133 */
michael@0 134 void* mArray[1];
michael@0 135 };
michael@0 136
michael@0 137 Impl* mImpl;
michael@0 138 #if DEBUG_VOIDARRAY
michael@0 139 int32_t mMaxCount;
michael@0 140 int32_t mMaxSize;
michael@0 141 bool mIsAuto;
michael@0 142 #endif
michael@0 143
michael@0 144 // bit twiddlers
michael@0 145 void SetArray(Impl *newImpl, int32_t aSize, int32_t aCount);
michael@0 146
michael@0 147 private:
michael@0 148 /// Copy constructors are not allowed
michael@0 149 nsVoidArray(const nsVoidArray& other);
michael@0 150 };
michael@0 151
michael@0 152 //===================================================================
michael@0 153 // nsSmallVoidArray is not a general-purpose replacement for
michael@0 154 // ns(Auto)VoidArray because there is (some) extra CPU overhead for arrays
michael@0 155 // larger than 1 element, though not a lot. It is appropriate for
michael@0 156 // space-sensitive uses where sizes of 0 or 1 are moderately common or
michael@0 157 // more, and where we're NOT storing arbitrary integers or arbitrary
michael@0 158 // pointers.
michael@0 159
michael@0 160 // NOTE: nsSmallVoidArray can ONLY be used for holding items that always
michael@0 161 // have the low bit as a 0 - i.e. element & 1 == 0. This happens to be
michael@0 162 // true for allocated and object pointers for all the architectures we run
michael@0 163 // on, but conceivably there might be some architectures/compilers for
michael@0 164 // which it is NOT true. We know this works for all existing architectures
michael@0 165 // because if it didn't then nsCheapVoidArray would have failed. Also note
michael@0 166 // that we will ASSERT if this assumption is violated in DEBUG builds.
michael@0 167
michael@0 168 // XXX we're really re-implementing the whole nsVoidArray interface here -
michael@0 169 // some form of abstract class would be useful
michael@0 170
michael@0 171 // I disagree on the abstraction here. If the point of this class is to be
michael@0 172 // as small as possible, and no one will ever derive from it, as I found
michael@0 173 // today, there should not be any virtualness to it to avoid the vtable
michael@0 174 // ptr overhead.
michael@0 175
michael@0 176 class NS_COM_GLUE nsSmallVoidArray : private nsVoidArray
michael@0 177 {
michael@0 178 public:
michael@0 179 ~nsSmallVoidArray();
michael@0 180
michael@0 181 nsSmallVoidArray& operator=(nsSmallVoidArray& other);
michael@0 182 void* operator[](int32_t aIndex) const { return ElementAt(aIndex); }
michael@0 183
michael@0 184 int32_t GetArraySize() const;
michael@0 185
michael@0 186 int32_t Count() const;
michael@0 187 void* FastElementAt(int32_t aIndex) const;
michael@0 188 // This both asserts and bounds-checks, because (1) we don't want
michael@0 189 // people to write bad code, but (2) we don't want to change it to
michael@0 190 // crashing for backwards compatibility. See bug 96108.
michael@0 191 void* ElementAt(int32_t aIndex) const
michael@0 192 {
michael@0 193 NS_ASSERTION(0 <= aIndex && aIndex < Count(), "nsSmallVoidArray::ElementAt: index out of range");
michael@0 194 return SafeElementAt(aIndex);
michael@0 195 }
michael@0 196 void* SafeElementAt(int32_t aIndex) const {
michael@0 197 // let compiler inline; it may be able to remove these checks
michael@0 198 if (uint32_t(aIndex) >= uint32_t(Count())) // handles aIndex < 0 too
michael@0 199 {
michael@0 200 return nullptr;
michael@0 201 }
michael@0 202 return FastElementAt(aIndex);
michael@0 203 }
michael@0 204 int32_t IndexOf(void* aPossibleElement) const;
michael@0 205 bool InsertElementAt(void* aElement, int32_t aIndex);
michael@0 206 bool InsertElementsAt(const nsVoidArray &other, int32_t aIndex);
michael@0 207 bool ReplaceElementAt(void* aElement, int32_t aIndex);
michael@0 208 bool MoveElement(int32_t aFrom, int32_t aTo);
michael@0 209 bool AppendElement(void* aElement);
michael@0 210 bool AppendElements(nsVoidArray& aElements) {
michael@0 211 return InsertElementsAt(aElements, Count());
michael@0 212 }
michael@0 213 bool RemoveElement(void* aElement);
michael@0 214 void RemoveElementsAt(int32_t aIndex, int32_t aCount);
michael@0 215 void RemoveElementAt(int32_t aIndex);
michael@0 216
michael@0 217 void Clear();
michael@0 218 bool SizeTo(int32_t aMin);
michael@0 219 void Compact();
michael@0 220 void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
michael@0 221
michael@0 222 bool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
michael@0 223 bool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
michael@0 224
michael@0 225 private:
michael@0 226
michael@0 227 bool HasSingle() const
michael@0 228 {
michael@0 229 return !!(reinterpret_cast<intptr_t>(mImpl) & 0x1);
michael@0 230 }
michael@0 231 void* GetSingle() const
michael@0 232 {
michael@0 233 NS_ASSERTION(HasSingle(), "wrong type");
michael@0 234 return reinterpret_cast<void*>
michael@0 235 (reinterpret_cast<intptr_t>(mImpl) & ~0x1);
michael@0 236 }
michael@0 237 void SetSingle(void *aChild)
michael@0 238 {
michael@0 239 NS_ASSERTION(HasSingle() || !mImpl, "overwriting array");
michael@0 240 mImpl = reinterpret_cast<Impl*>
michael@0 241 (reinterpret_cast<intptr_t>(aChild) | 0x1);
michael@0 242 }
michael@0 243 bool IsEmpty() const
michael@0 244 {
michael@0 245 // Note that this isn't the same as Count()==0
michael@0 246 return !mImpl;
michael@0 247 }
michael@0 248 const nsVoidArray* AsArray() const
michael@0 249 {
michael@0 250 NS_ASSERTION(!HasSingle(), "This is a single");
michael@0 251 return this;
michael@0 252 }
michael@0 253 nsVoidArray* AsArray()
michael@0 254 {
michael@0 255 NS_ASSERTION(!HasSingle(), "This is a single");
michael@0 256 return this;
michael@0 257 }
michael@0 258 bool EnsureArray();
michael@0 259 };
michael@0 260
michael@0 261 #endif /* nsVoidArray_h___ */

mercurial