1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/MathAlgorithms.h"
8 #include "mozilla/MemoryReporting.h"
11 #include "nsVoidArray.h"
12 #include "nsQuickSort.h"
13 #include "nsISupportsImpl.h" // for nsTraceRefcnt
14 #include "nsAlgorithm.h"
17 * Grow the array by at least this many elements at a time.
19 static const int32_t kMinGrowArrayBy
= 8;
20 static const int32_t kMaxGrowArrayBy
= 1024;
23 * This is the threshold (in bytes) of the mImpl struct, past which
24 * we'll force the array to grow geometrically
26 static const int32_t kLinearThreshold
= 24 * sizeof(void*);
29 * Compute the number of bytes requires for the mImpl struct that will
32 #define SIZEOF_IMPL(n_) (sizeof(Impl) + sizeof(void *) * ((n_) - 1))
35 * Compute the number of elements that an mImpl struct of |n| bytes
38 #define CAPACITYOF_IMPL(n_) ((((n_) - sizeof(Impl)) / sizeof(void *)) + 1)
50 static int sizesUsed
; // number of the elements of the arrays used
51 static int sizesAlloced
[MAXVOID
]; // sizes of the allocations. sorted
52 static int NumberOfSize
[MAXVOID
]; // number of this allocation size (1 per array)
53 static int AllocedOfSize
[MAXVOID
]; // number of this allocation size (each size for array used)
54 static int MaxAuto
[MAXVOID
]; // AutoArrays that maxed out at this size
55 static int GrowInPlace
[MAXVOID
]; // arrays this size that grew in-place via realloc
57 // these are per-allocation
58 static int MaxElements
[2000]; // # of arrays that maxed out at each size.
61 #define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
63 if (sizesAlloced[i] == (int)(size)) \
64 { ((x)[i])++; break; } \
66 if (i >= sizesUsed && sizesUsed < MAXVOID) \
67 { sizesAlloced[sizesUsed] = (size); \
68 ((x)[sizesUsed++])++; break; \
72 #define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
74 if (sizesAlloced[i] == (int)(size)) \
75 { ((x)[i])--; break; } \
80 VoidStats::VoidStats()
86 VoidStats::~VoidStats()
89 for (i
= 0; i
< sizesUsed
; ++i
) {
90 printf("Size %d:\n",sizesAlloced
[i
]);
91 printf("\tNumber of VoidArrays this size (max): %d\n",NumberOfSize
[i
]-MaxAuto
[i
]);
92 printf("\tNumber of AutoVoidArrays this size (max): %d\n",MaxAuto
[i
]);
93 printf("\tNumber of allocations this size (total): %d\n",AllocedOfSize
[i
]);
94 printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace
[i
]);
96 printf("Max Size of VoidArray:\n");
97 for (i
= 0; i
< (int)(sizeof(MaxElements
) / sizeof(MaxElements
[0])); ++i
) {
99 printf("\t%d: %d\n", i
, MaxElements
[i
]);
104 // Just so constructor/destructor's get called
105 VoidStats gVoidStats
;
109 nsVoidArray::SetArray(Impl
* aNewImpl
, int32_t aSize
, int32_t aCount
)
111 // old mImpl has been realloced and so we don't free/delete it
112 NS_PRECONDITION(aNewImpl
, "can't set size");
114 mImpl
->mCount
= aCount
;
115 mImpl
->mSize
= aSize
;
118 // This does all allocation/reallocation of the array.
119 // It also will compact down to N - good for things that might grow a lot
120 // at times, but usually are smaller, like JS deferred GC releases.
122 nsVoidArray::SizeTo(int32_t aSize
)
124 uint32_t oldsize
= GetArraySize();
126 if (aSize
== (int32_t)oldsize
) {
127 return true; // no change
131 // free the array if allocated
133 free(reinterpret_cast<char*>(mImpl
));
140 // We currently own an array impl. Resize it appropriately.
141 if (aSize
< mImpl
->mCount
) {
142 // XXX Note: we could also just resize to mCount
143 return true; // can't make it that small, ignore request
146 char* bytes
= (char*)realloc(mImpl
, SIZEOF_IMPL(aSize
));
147 Impl
* newImpl
= reinterpret_cast<Impl
*>(bytes
);
153 if (mImpl
== newImpl
) {
154 ADD_TO_STATS(GrowInPlace
, oldsize
);
156 ADD_TO_STATS(AllocedOfSize
, SIZEOF_IMPL(aSize
));
157 if (aSize
> mMaxSize
) {
158 ADD_TO_STATS(NumberOfSize
, SIZEOF_IMPL(aSize
));
160 SUB_FROM_STATS(NumberOfSize
, oldsize
);
164 ADD_TO_STATS(MaxAuto
, SIZEOF_IMPL(aSize
));
165 SUB_FROM_STATS(MaxAuto
, oldsize
);
169 SetArray(newImpl
, aSize
, newImpl
->mCount
);
173 if ((uint32_t)aSize
< oldsize
) {
174 // No point in allocating if it won't free the current Impl anyway.
178 // just allocate an array
179 // allocate the exact size requested
180 char* bytes
= (char*)malloc(SIZEOF_IMPL(aSize
));
181 Impl
* newImpl
= reinterpret_cast<Impl
*>(bytes
);
187 ADD_TO_STATS(AllocedOfSize
, SIZEOF_IMPL(aSize
));
188 if (aSize
> mMaxSize
) {
189 ADD_TO_STATS(NumberOfSize
, SIZEOF_IMPL(aSize
));
190 if (oldsize
&& !mImpl
) {
191 SUB_FROM_STATS(NumberOfSize
, oldsize
);
198 ADD_TO_STATS(MaxAuto
, SIZEOF_IMPL(aSize
));
199 SUB_FROM_STATS(MaxAuto
, 0);
200 SUB_FROM_STATS(NumberOfSize
, 0);
203 // We must be growing an nsAutoVoidArray - copy since we didn't
205 memcpy(newImpl
->mArray
, mImpl
->mArray
,
206 mImpl
->mCount
* sizeof(mImpl
->mArray
[0]));
209 SetArray(newImpl
, aSize
, mImpl
? mImpl
->mCount
: 0);
210 // no memset; handled later in ReplaceElementAt if needed
215 nsVoidArray::GrowArrayBy(int32_t aGrowBy
)
217 // We have to grow the array. Grow by kMinGrowArrayBy slots if we're
218 // smaller than kLinearThreshold bytes, or a power of two if we're
219 // larger. This is much more efficient with most memory allocators,
220 // especially if it's very large, or of the allocator is binned.
221 if (aGrowBy
< kMinGrowArrayBy
) {
222 aGrowBy
= kMinGrowArrayBy
;
225 uint32_t newCapacity
= GetArraySize() + aGrowBy
; // Minimum increase
226 uint32_t newSize
= SIZEOF_IMPL(newCapacity
);
228 if (newSize
>= (uint32_t)kLinearThreshold
) {
229 // newCount includes enough space for at least kMinGrowArrayBy new
230 // slots. Select the next power-of-two size in bytes above or
232 // Also, limit the increase in size to about a VM page or two.
233 if (GetArraySize() >= kMaxGrowArrayBy
) {
234 newCapacity
= GetArraySize() + XPCOM_MAX(kMaxGrowArrayBy
, aGrowBy
);
235 newSize
= SIZEOF_IMPL(newCapacity
);
237 newSize
= mozilla::CeilingLog2(newSize
);
238 newCapacity
= CAPACITYOF_IMPL(1u << newSize
);
241 // frees old mImpl IF this succeeds
242 if (!SizeTo(newCapacity
)) {
249 nsVoidArray::nsVoidArray()
252 MOZ_COUNT_CTOR(nsVoidArray
);
257 ADD_TO_STATS(NumberOfSize
, 0);
262 nsVoidArray::nsVoidArray(int32_t aCount
)
265 MOZ_COUNT_CTOR(nsVoidArray
);
276 nsVoidArray::operator=(const nsVoidArray
& aOther
)
278 int32_t otherCount
= aOther
.Count();
279 int32_t maxCount
= GetArraySize();
281 if (otherCount
> maxCount
) {
282 // frees old mImpl IF this succeeds
283 if (!GrowArrayBy(otherCount
- maxCount
)) {
284 return *this; // XXX The allocation failed - don't do anything
287 memcpy(mImpl
->mArray
, aOther
.mImpl
->mArray
,
288 otherCount
* sizeof(mImpl
->mArray
[0]));
289 mImpl
->mCount
= otherCount
;
291 // the old array can hold the new array
292 memcpy(mImpl
->mArray
, aOther
.mImpl
->mArray
,
293 otherCount
* sizeof(mImpl
->mArray
[0]));
294 mImpl
->mCount
= otherCount
;
295 // if it shrank a lot, compact it anyways
296 if ((otherCount
* 2) < maxCount
&& maxCount
> 100) {
297 Compact(); // shrank by at least 50 entries
301 if (mImpl
->mCount
> mMaxCount
&&
302 mImpl
->mCount
< (int32_t)(sizeof(MaxElements
) / sizeof(MaxElements
[0]))) {
303 MaxElements
[mImpl
->mCount
]++;
304 MaxElements
[mMaxCount
]--;
305 mMaxCount
= mImpl
->mCount
;
309 // Why do we drop the buffer here when we don't in Clear()?
316 nsVoidArray::~nsVoidArray()
318 MOZ_COUNT_DTOR(nsVoidArray
);
320 free(reinterpret_cast<char*>(mImpl
));
325 nsVoidArray::SetCount(int32_t aNewCount
)
327 NS_ASSERTION(aNewCount
>= 0, "SetCount(negative index)");
332 if (aNewCount
== 0) {
337 if (uint32_t(aNewCount
) > uint32_t(GetArraySize())) {
338 int32_t oldCount
= Count();
339 int32_t growDelta
= aNewCount
- oldCount
;
341 // frees old mImpl IF this succeeds
342 if (!GrowArrayBy(growDelta
)) {
347 if (aNewCount
> mImpl
->mCount
) {
348 // Make sure that new entries added to the array by this
349 // SetCount are cleared to 0. Some users of this assume that.
350 // This code means we don't have to memset when we allocate an array.
351 memset(&mImpl
->mArray
[mImpl
->mCount
], 0,
352 (aNewCount
- mImpl
->mCount
) * sizeof(mImpl
->mArray
[0]));
355 mImpl
->mCount
= aNewCount
;
358 if (mImpl
->mCount
> mMaxCount
&&
359 mImpl
->mCount
< (int32_t)(sizeof(MaxElements
) / sizeof(MaxElements
[0]))) {
360 MaxElements
[mImpl
->mCount
]++;
361 MaxElements
[mMaxCount
]--;
362 mMaxCount
= mImpl
->mCount
;
370 nsVoidArray::IndexOf(void* aPossibleElement
) const
373 void** ap
= mImpl
->mArray
;
374 void** end
= ap
+ mImpl
->mCount
;
376 if (*ap
== aPossibleElement
) {
377 return ap
- mImpl
->mArray
;
386 nsVoidArray::InsertElementAt(void* aElement
, int32_t aIndex
)
388 int32_t oldCount
= Count();
389 NS_ASSERTION(aIndex
>= 0, "InsertElementAt(negative index)");
390 if (uint32_t(aIndex
) > uint32_t(oldCount
)) {
391 // An invalid index causes the insertion to fail
392 // Invalid indexes are ones that add more than one entry to the
393 // array (i.e., they can append).
397 if (oldCount
>= GetArraySize()) {
398 if (!GrowArrayBy(1)) {
402 // else the array is already large enough
404 int32_t slide
= oldCount
- aIndex
;
406 // Slide data over to make room for the insertion
407 memmove(mImpl
->mArray
+ aIndex
+ 1, mImpl
->mArray
+ aIndex
,
408 slide
* sizeof(mImpl
->mArray
[0]));
411 mImpl
->mArray
[aIndex
] = aElement
;
415 if (mImpl
->mCount
> mMaxCount
&&
416 mImpl
->mCount
< (int32_t)(sizeof(MaxElements
) / sizeof(MaxElements
[0]))) {
417 MaxElements
[mImpl
->mCount
]++;
418 MaxElements
[mMaxCount
]--;
419 mMaxCount
= mImpl
->mCount
;
427 nsVoidArray::InsertElementsAt(const nsVoidArray
& aOther
, int32_t aIndex
)
429 int32_t oldCount
= Count();
430 int32_t otherCount
= aOther
.Count();
432 NS_ASSERTION(aIndex
>= 0, "InsertElementsAt(negative index)");
433 if (uint32_t(aIndex
) > uint32_t(oldCount
)) {
434 // An invalid index causes the insertion to fail
435 // Invalid indexes are ones that are more than one entry past the end of
436 // the array (i.e., they can append).
440 if (oldCount
+ otherCount
> GetArraySize()) {
441 if (!GrowArrayBy(otherCount
)) {
445 // else the array is already large enough
447 int32_t slide
= oldCount
- aIndex
;
449 // Slide data over to make room for the insertion
450 memmove(mImpl
->mArray
+ aIndex
+ otherCount
, mImpl
->mArray
+ aIndex
,
451 slide
* sizeof(mImpl
->mArray
[0]));
454 for (int32_t i
= 0; i
< otherCount
; ++i
) {
455 // copy all the elements (destroys aIndex)
456 mImpl
->mArray
[aIndex
++] = aOther
.mImpl
->mArray
[i
];
461 if (mImpl
->mCount
> mMaxCount
&&
462 mImpl
->mCount
< (int32_t)(sizeof(MaxElements
) / sizeof(MaxElements
[0]))) {
463 MaxElements
[mImpl
->mCount
]++;
464 MaxElements
[mMaxCount
]--;
465 mMaxCount
= mImpl
->mCount
;
473 nsVoidArray::ReplaceElementAt(void* aElement
, int32_t aIndex
)
475 NS_ASSERTION(aIndex
>= 0, "ReplaceElementAt(negative index)");
480 // Unlike InsertElementAt, ReplaceElementAt can implicitly add more
481 // than just the one element to the array.
482 if (uint32_t(aIndex
) >= uint32_t(GetArraySize())) {
483 int32_t oldCount
= Count();
484 int32_t requestedCount
= aIndex
+ 1;
485 int32_t growDelta
= requestedCount
- oldCount
;
487 // frees old mImpl IF this succeeds
488 if (!GrowArrayBy(growDelta
)) {
493 mImpl
->mArray
[aIndex
] = aElement
;
494 if (aIndex
>= mImpl
->mCount
) {
495 // Make sure that any entries implicitly added to the array by this
496 // ReplaceElementAt are cleared to 0. Some users of this assume that.
497 // This code means we don't have to memset when we allocate an array.
498 if (aIndex
> mImpl
->mCount
) { // note: not >=
499 // For example, if mCount is 2, and we do a ReplaceElementAt for
500 // element[5], then we need to set three entries ([2], [3], and [4])
502 memset(&mImpl
->mArray
[mImpl
->mCount
], 0,
503 (aIndex
- mImpl
->mCount
) * sizeof(mImpl
->mArray
[0]));
506 mImpl
->mCount
= aIndex
+ 1;
509 if (mImpl
->mCount
> mMaxCount
&&
510 mImpl
->mCount
< (int32_t)(sizeof(MaxElements
) / sizeof(MaxElements
[0]))) {
511 MaxElements
[mImpl
->mCount
]++;
512 MaxElements
[mMaxCount
]--;
513 mMaxCount
= mImpl
->mCount
;
521 // useful for doing LRU arrays
523 nsVoidArray::MoveElement(int32_t aFrom
, int32_t aTo
)
531 NS_ASSERTION(aTo
>= 0 && aFrom
>= 0, "MoveElement(negative index)");
532 if (aTo
>= Count() || aFrom
>= Count()) {
533 // can't extend the array when moving an element. Also catches mImpl = null
536 tempElement
= mImpl
->mArray
[aFrom
];
539 // Moving one element closer to the head; the elements inbetween move down
540 memmove(mImpl
->mArray
+ aTo
+ 1, mImpl
->mArray
+ aTo
,
541 (aFrom
- aTo
) * sizeof(mImpl
->mArray
[0]));
542 mImpl
->mArray
[aTo
] = tempElement
;
543 } else { // already handled aFrom == aTo
544 // Moving one element closer to the tail; the elements inbetween move up
545 memmove(mImpl
->mArray
+ aFrom
, mImpl
->mArray
+ aFrom
+ 1,
546 (aTo
- aFrom
) * sizeof(mImpl
->mArray
[0]));
547 mImpl
->mArray
[aTo
] = tempElement
;
554 nsVoidArray::RemoveElementsAt(int32_t aIndex
, int32_t aCount
)
556 int32_t oldCount
= Count();
557 NS_ASSERTION(aIndex
>= 0, "RemoveElementsAt(negative index)");
558 if (uint32_t(aIndex
) >= uint32_t(oldCount
)) {
561 // Limit to available entries starting at aIndex
562 if (aCount
+ aIndex
> oldCount
) {
563 aCount
= oldCount
- aIndex
;
566 // We don't need to move any elements if we're removing the
567 // last element in the array
568 if (aIndex
< (oldCount
- aCount
)) {
569 memmove(mImpl
->mArray
+ aIndex
, mImpl
->mArray
+ aIndex
+ aCount
,
570 (oldCount
- (aIndex
+ aCount
)) * sizeof(mImpl
->mArray
[0]));
573 mImpl
->mCount
-= aCount
;
578 nsVoidArray::RemoveElement(void* aElement
)
580 int32_t theIndex
= IndexOf(aElement
);
581 if (theIndex
!= -1) {
582 RemoveElementAt(theIndex
);
598 nsVoidArray::Compact()
601 // XXX NOTE: this is quite inefficient in many cases if we're only
602 // compacting by a little, but some callers care more about memory use.
603 int32_t count
= Count();
604 if (GetArraySize() > count
) {
610 // Needed because we want to pass the pointer to the item in the array
611 // to the comparator function, not a pointer to the pointer in the array.
612 struct VoidArrayComparatorContext
614 nsVoidArrayComparatorFunc mComparatorFunc
;
619 VoidArrayComparator(const void* aElement1
, const void* aElement2
, void* aData
)
621 VoidArrayComparatorContext
* ctx
= static_cast<VoidArrayComparatorContext
*>(aData
);
622 return (*ctx
->mComparatorFunc
)(*static_cast<void* const*>(aElement1
),
623 *static_cast<void* const*>(aElement2
),
628 nsVoidArray::Sort(nsVoidArrayComparatorFunc aFunc
, void* aData
)
630 if (mImpl
&& mImpl
->mCount
> 1) {
631 VoidArrayComparatorContext ctx
= {aFunc
, aData
};
632 NS_QuickSort(mImpl
->mArray
, mImpl
->mCount
, sizeof(mImpl
->mArray
[0]),
633 VoidArrayComparator
, &ctx
);
638 nsVoidArray::EnumerateForwards(nsVoidArrayEnumFunc aFunc
, void* aData
)
644 while (running
&& (++index
< mImpl
->mCount
)) {
645 running
= (*aFunc
)(mImpl
->mArray
[index
], aData
);
652 nsVoidArray::EnumerateForwards(nsVoidArrayEnumFuncConst aFunc
,
659 while (running
&& (++index
< mImpl
->mCount
)) {
660 running
= (*aFunc
)(mImpl
->mArray
[index
], aData
);
667 nsVoidArray::EnumerateBackwards(nsVoidArrayEnumFunc aFunc
, void* aData
)
672 int32_t index
= Count();
673 while (running
&& (--index
>= 0)) {
674 running
= (*aFunc
)(mImpl
->mArray
[index
], aData
);
680 struct SizeOfElementIncludingThisData
683 nsVoidArraySizeOfElementIncludingThisFunc mSizeOfElementIncludingThis
;
684 mozilla::MallocSizeOf mMallocSizeOf
;
685 void* mData
; // the arg passed by the user
689 SizeOfElementIncludingThisEnumerator(const void* aElement
, void* aData
)
691 SizeOfElementIncludingThisData
* d
= (SizeOfElementIncludingThisData
*)aData
;
692 d
->mSize
+= d
->mSizeOfElementIncludingThis(aElement
, d
->mMallocSizeOf
, d
->mData
);
697 nsVoidArray::SizeOfExcludingThis(
698 nsVoidArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis
,
699 mozilla::MallocSizeOf aMallocSizeOf
, void* aData
) const
702 // Measure the element storage.
704 n
+= aMallocSizeOf(mImpl
);
706 // Measure things pointed to by the elements.
707 if (aSizeOfElementIncludingThis
) {
708 SizeOfElementIncludingThisData data2
=
709 { 0, aSizeOfElementIncludingThis
, aMallocSizeOf
, aData
};
710 EnumerateForwards(SizeOfElementIncludingThisEnumerator
, &data2
);
716 //----------------------------------------------------------------------
717 // NOTE: nsSmallVoidArray elements MUST all have the low bit as 0.
718 // This means that normally it's only used for pointers, and in particular
719 // structures or objects.
720 nsSmallVoidArray::~nsSmallVoidArray()
723 // Have to null out mImpl before the nsVoidArray dtor runs.
729 nsSmallVoidArray::operator=(nsSmallVoidArray
& aOther
)
731 int32_t count
= aOther
.Count();
738 AppendElement(aOther
.ElementAt(0));
741 if (GetArraySize() >= count
|| SizeTo(count
)) {
742 *AsArray() = *aOther
.AsArray();
750 nsSmallVoidArray::GetArraySize() const
756 return AsArray()->GetArraySize();
760 nsSmallVoidArray::Count() const
766 return AsArray()->Count();
770 nsSmallVoidArray::FastElementAt(int32_t aIndex
) const
772 NS_ASSERTION(aIndex
>= 0 && aIndex
< Count(),
773 "nsSmallVoidArray::FastElementAt: index out of range");
779 return AsArray()->FastElementAt(aIndex
);
783 nsSmallVoidArray::IndexOf(void* aPossibleElement
) const
786 return aPossibleElement
== GetSingle() ? 0 : -1;
789 return AsArray()->IndexOf(aPossibleElement
);
793 nsSmallVoidArray::InsertElementAt(void* aElement
, int32_t aIndex
)
795 NS_ASSERTION(!(NS_PTR_TO_INT32(aElement
) & 0x1),
796 "Attempt to add element with 0x1 bit set to nsSmallVoidArray");
798 if (aIndex
== 0 && IsEmpty()) {
804 if (!EnsureArray()) {
808 return AsArray()->InsertElementAt(aElement
, aIndex
);
812 nsSmallVoidArray::InsertElementsAt(const nsVoidArray
& aOther
, int32_t aIndex
)
815 for (int i
= 0; i
< aOther
.Count(); ++i
) {
816 NS_ASSERTION(!(NS_PTR_TO_INT32(aOther
.ElementAt(i
)) & 0x1),
817 "Attempt to add element with 0x1 bit set to nsSmallVoidArray");
821 if (aIndex
== 0 && IsEmpty() && aOther
.Count() == 1) {
822 SetSingle(aOther
.FastElementAt(0));
827 if (!EnsureArray()) {
831 return AsArray()->InsertElementsAt(aOther
, aIndex
);
835 nsSmallVoidArray::ReplaceElementAt(void* aElement
, int32_t aIndex
)
837 NS_ASSERTION(!(NS_PTR_TO_INT32(aElement
) & 0x1),
838 "Attempt to add element with 0x1 bit set to nsSmallVoidArray");
840 if (aIndex
== 0 && (IsEmpty() || HasSingle())) {
846 if (!EnsureArray()) {
850 return AsArray()->ReplaceElementAt(aElement
, aIndex
);
854 nsSmallVoidArray::AppendElement(void* aElement
)
856 NS_ASSERTION(!(NS_PTR_TO_INT32(aElement
) & 0x1),
857 "Attempt to add element with 0x1 bit set to nsSmallVoidArray");
865 if (!EnsureArray()) {
869 return AsArray()->AppendElement(aElement
);
873 nsSmallVoidArray::RemoveElement(void* aElement
)
876 if (aElement
== GetSingle()) {
884 return AsArray()->RemoveElement(aElement
);
888 nsSmallVoidArray::RemoveElementAt(int32_t aIndex
)
898 AsArray()->RemoveElementAt(aIndex
);
902 nsSmallVoidArray::RemoveElementsAt(int32_t aIndex
, int32_t aCount
)
914 AsArray()->RemoveElementsAt(aIndex
, aCount
);
918 nsSmallVoidArray::Clear()
928 nsSmallVoidArray::SizeTo(int32_t aMin
)
931 return AsArray()->SizeTo(aMin
);
944 void* single
= GetSingle();
946 if (!AsArray()->SizeTo(aMin
)) {
952 AsArray()->AppendElement(single
);
958 nsSmallVoidArray::Compact()
961 AsArray()->Compact();
966 nsSmallVoidArray::Sort(nsVoidArrayComparatorFunc aFunc
, void* aData
)
969 AsArray()->Sort(aFunc
, aData
);
974 nsSmallVoidArray::EnumerateForwards(nsVoidArrayEnumFunc aFunc
, void* aData
)
977 return (*aFunc
)(GetSingle(), aData
);
979 return AsArray()->EnumerateForwards(aFunc
, aData
);
983 nsSmallVoidArray::EnumerateBackwards(nsVoidArrayEnumFunc aFunc
, void* aData
)
986 return (*aFunc
)(GetSingle(), aData
);
988 return AsArray()->EnumerateBackwards(aFunc
, aData
);
992 nsSmallVoidArray::EnsureArray()
998 void* single
= GetSingle();
1000 if (!AsArray()->AppendElement(single
)) {