VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.cpp@ 102324

Last change on this file since 102324 was 102324, checked in by vboxsync, 13 months ago

libs/xpcom: Replace NS_QuickSort with IPRT RTSortShell and get rid of it, bugref:10545

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.8 KB
Line 
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#include <iprt/cdefs.h>
38#include <iprt/sort.h>
39
40#include "nsVoidArray.h"
41#include "prmem.h"
42#include "nsCRT.h"
43#include "nsString.h"
44#include "prbit.h"
45
46/**
47 * Grow the array by at least this many elements at a time.
48 */
49static const PRInt32 kMinGrowArrayBy = 8;
50static const PRInt32 kMaxGrowArrayBy = 1024;
51
52/**
53 * This is the threshold (in bytes) of the mImpl struct, past which
54 * we'll force the array to grow geometrically
55 */
56static const PRInt32 kLinearThreshold = 24 * sizeof(void *);
57
58/**
59 * Compute the number of bytes requires for the mImpl struct that will
60 * hold |n| elements.
61 */
62#define SIZEOF_IMPL(n_) (sizeof(Impl) + sizeof(void *) * ((n_) - 1))
63
64
65/**
66 * Compute the number of elements that an mImpl struct of |n| bytes
67 * will hold.
68 */
69#define CAPACITYOF_IMPL(n_) ((((n_) - sizeof(Impl)) / sizeof(void *)) + 1)
70
71#if DEBUG_VOIDARRAY
72#define MAXVOID 10
73
74class VoidStats {
75public:
76 VoidStats();
77 ~VoidStats();
78
79};
80
81static int sizesUsed; // number of the elements of the arrays used
82static int sizesAlloced[MAXVOID]; // sizes of the allocations. sorted
83static int NumberOfSize[MAXVOID]; // number of this allocation size (1 per array)
84static int AllocedOfSize[MAXVOID]; // number of this allocation size (each size for array used)
85static int MaxAuto[MAXVOID]; // AutoArrays that maxed out at this size
86static int GrowInPlace[MAXVOID]; // arrays this size that grew in-place via realloc
87
88// these are per-allocation
89static int MaxElements[2000]; // # of arrays that maxed out at each size.
90
91// statistics macros
92#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
93 { \
94 if (sizesAlloced[i] == (int)(size)) \
95 { ((x)[i])++; break; } \
96 } \
97 if (i >= sizesUsed && sizesUsed < MAXVOID) \
98 { sizesAlloced[sizesUsed] = (size); \
99 ((x)[sizesUsed++])++; break; \
100 } \
101 } while (0)
102
103#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
104 { \
105 if (sizesAlloced[i] == (int)(size)) \
106 { ((x)[i])--; break; } \
107 } \
108 } while (0)
109
110
111VoidStats::VoidStats()
112{
113 sizesUsed = 1;
114 sizesAlloced[0] = 0;
115}
116
117VoidStats::~VoidStats()
118{
119 int i;
120 for (i = 0; i < sizesUsed; i++)
121 {
122 printf("Size %d:\n",sizesAlloced[i]);
123 printf("\tNumber of VoidArrays this size (max): %d\n",NumberOfSize[i]-MaxAuto[i]);
124 printf("\tNumber of AutoVoidArrays this size (max): %d\n",MaxAuto[i]);
125 printf("\tNumber of allocations this size (total): %d\n",AllocedOfSize[i]);
126 printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]);
127 }
128 printf("Max Size of VoidArray:\n");
129 for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++)
130 {
131 if (MaxElements[i])
132 printf("\t%d: %d\n",i,MaxElements[i]);
133 }
134}
135
136// Just so constructor/destructor's get called
137VoidStats gVoidStats;
138#endif
139
140inline void
141nsVoidArray::SetArray(Impl *newImpl, PRInt32 aSize, PRInt32 aCount, PRBool owner)
142{
143 // old mImpl has been realloced and so we don't free/delete it
144 NS_PRECONDITION(newImpl, "can't set size");
145 mImpl = newImpl;
146 mImpl->mCount = aCount;
147 mImpl->mBits = PRUint32(aSize & kArraySizeMask) |
148 (owner ? kArrayOwnerMask : 0);
149}
150
151// This does all allocation/reallocation of the array.
152// It also will compact down to N - good for things that might grow a lot
153// at times, but usually are smaller, like JS deferred GC releases.
154PRBool nsVoidArray::SizeTo(PRInt32 aSize)
155{
156 PRUint32 oldsize = GetArraySize();
157
158 if (aSize == (PRInt32) oldsize)
159 return PR_TRUE; // no change
160
161 if (aSize <= 0)
162 {
163 // free the array if allocated
164 if (mImpl)
165 {
166 if (IsArrayOwner())
167 {
168 PR_Free(NS_REINTERPRET_CAST(char *, mImpl));
169 mImpl = nsnull;
170 }
171 else
172 {
173 mImpl->mCount = 0; // nsAutoVoidArray
174 }
175 }
176 return PR_TRUE;
177 }
178
179 if (mImpl && IsArrayOwner())
180 {
181 // We currently own an array impl. Resize it appropriately.
182 if (aSize < mImpl->mCount)
183 {
184 // XXX Note: we could also just resize to mCount
185 return PR_TRUE; // can't make it that small, ignore request
186 }
187
188 char* bytes = (char *) PR_Realloc(mImpl,SIZEOF_IMPL(aSize));
189 Impl* newImpl = NS_REINTERPRET_CAST(Impl*, bytes);
190 if (!newImpl)
191 return PR_FALSE;
192
193#if DEBUG_VOIDARRAY
194 if (mImpl == newImpl)
195 ADD_TO_STATS(GrowInPlace,oldsize);
196 ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize));
197 if (aSize > mMaxSize)
198 {
199 ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize));
200 if (oldsize)
201 SUB_FROM_STATS(NumberOfSize,oldsize);
202 mMaxSize = aSize;
203 if (mIsAuto)
204 {
205 ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize));
206 SUB_FROM_STATS(MaxAuto,oldsize);
207 }
208 }
209#endif
210 SetArray(newImpl,aSize,newImpl->mCount,PR_TRUE);
211 return PR_TRUE;
212 }
213
214 // just allocate an array
215 // allocate the exact size requested
216 char* bytes = (char *) PR_Malloc(SIZEOF_IMPL(aSize));
217 Impl* newImpl = NS_REINTERPRET_CAST(Impl*, bytes);
218 if (!newImpl)
219 return PR_FALSE;
220
221#if DEBUG_VOIDARRAY
222 ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize));
223 if (aSize > mMaxSize)
224 {
225 ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize));
226 if (oldsize && !mImpl)
227 SUB_FROM_STATS(NumberOfSize,oldsize);
228 mMaxSize = aSize;
229 }
230#endif
231 if (mImpl)
232 {
233#if DEBUG_VOIDARRAY
234 ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize));
235 SUB_FROM_STATS(MaxAuto,0);
236 SUB_FROM_STATS(NumberOfSize,0);
237 mIsAuto = PR_TRUE;
238#endif
239 // We must be growing an nsAutoVoidArray - copy since we didn't
240 // realloc.
241 memcpy(newImpl->mArray, mImpl->mArray,
242 mImpl->mCount * sizeof(mImpl->mArray[0]));
243 }
244
245 SetArray(newImpl,aSize,mImpl ? mImpl->mCount : 0,PR_TRUE);
246 // no memset; handled later in ReplaceElementAt if needed
247 return PR_TRUE;
248}
249
250PRBool nsVoidArray::GrowArrayBy(PRInt32 aGrowBy)
251{
252 // We have to grow the array. Grow by kMinGrowArrayBy slots if we're
253 // smaller than kLinearThreshold bytes, or a power of two if we're
254 // larger. This is much more efficient with most memory allocators,
255 // especially if it's very large, or of the allocator is binned.
256 if (aGrowBy < kMinGrowArrayBy)
257 aGrowBy = kMinGrowArrayBy;
258
259 PRUint32 newCapacity = GetArraySize() + aGrowBy; // Minimum increase
260 PRUint32 newSize = SIZEOF_IMPL(newCapacity);
261
262 if (newSize >= (PRUint32) kLinearThreshold)
263 {
264 // newCount includes enough space for at least kMinGrowArrayBy new
265 // slots. Select the next power-of-two size in bytes above or
266 // equal to that.
267 // Also, limit the increase in size to about a VM page or two.
268 if (GetArraySize() >= kMaxGrowArrayBy)
269 {
270 newCapacity = GetArraySize() + PR_MAX(kMaxGrowArrayBy,aGrowBy);
271 newSize = SIZEOF_IMPL(newCapacity);
272 }
273 else
274 {
275 newSize = PR_BIT(PR_CeilingLog2(newSize));
276 newCapacity = CAPACITYOF_IMPL(newSize);
277 }
278 }
279 // frees old mImpl IF this succeeds
280 if (!SizeTo(newCapacity))
281 return PR_FALSE;
282
283 return PR_TRUE;
284}
285
286nsVoidArray::nsVoidArray()
287 : mImpl(nsnull)
288{
289 MOZ_COUNT_CTOR(nsVoidArray);
290#if DEBUG_VOIDARRAY
291 mMaxCount = 0;
292 mMaxSize = 0;
293 mIsAuto = PR_FALSE;
294 ADD_TO_STATS(NumberOfSize,0);
295 MaxElements[0]++;
296#endif
297}
298
299nsVoidArray::nsVoidArray(PRInt32 aCount)
300 : mImpl(nsnull)
301{
302 MOZ_COUNT_CTOR(nsVoidArray);
303#if DEBUG_VOIDARRAY
304 mMaxCount = 0;
305 mMaxSize = 0;
306 mIsAuto = PR_FALSE;
307 MaxElements[0]++;
308#endif
309 SizeTo(aCount);
310}
311
312nsVoidArray& nsVoidArray::operator=(const nsVoidArray& other)
313{
314 PRInt32 otherCount = other.Count();
315 PRInt32 maxCount = GetArraySize();
316 if (otherCount)
317 {
318 if (otherCount > maxCount)
319 {
320 // frees old mImpl IF this succeeds
321 if (!GrowArrayBy(otherCount-maxCount))
322 return *this; // XXX The allocation failed - don't do anything
323
324 memcpy(mImpl->mArray, other.mImpl->mArray, otherCount * sizeof(mImpl->mArray[0]));
325 mImpl->mCount = otherCount;
326 }
327 else
328 {
329 // the old array can hold the new array
330 memcpy(mImpl->mArray, other.mImpl->mArray, otherCount * sizeof(mImpl->mArray[0]));
331 mImpl->mCount = otherCount;
332 // if it shrank a lot, compact it anyways
333 if ((otherCount*2) < maxCount && maxCount > 100)
334 {
335 Compact(); // shrank by at least 50 entries
336 }
337 }
338#if DEBUG_VOIDARRAY
339 if (mImpl->mCount > mMaxCount &&
340 mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
341 {
342 MaxElements[mImpl->mCount]++;
343 MaxElements[mMaxCount]--;
344 mMaxCount = mImpl->mCount;
345 }
346#endif
347 }
348 else
349 {
350 if (mImpl && IsArrayOwner())
351 PR_Free(NS_REINTERPRET_CAST(char*, mImpl));
352
353 mImpl = nsnull;
354 }
355
356 return *this;
357}
358
359nsVoidArray::~nsVoidArray()
360{
361 MOZ_COUNT_DTOR(nsVoidArray);
362 if (mImpl && IsArrayOwner())
363 PR_Free(NS_REINTERPRET_CAST(char*, mImpl));
364}
365
366PRInt32 nsVoidArray::IndexOf(void* aPossibleElement) const
367{
368 if (mImpl)
369 {
370 void** ap = mImpl->mArray;
371 void** end = ap + mImpl->mCount;
372 while (ap < end)
373 {
374 if (*ap == aPossibleElement)
375 {
376 return ap - mImpl->mArray;
377 }
378 ap++;
379 }
380 }
381 return -1;
382}
383
384PRBool nsVoidArray::InsertElementAt(void* aElement, PRInt32 aIndex)
385{
386 PRInt32 oldCount = Count();
387 NS_ASSERTION(aIndex >= 0,"InsertElementAt(negative index)");
388 if (PRUint32(aIndex) > PRUint32(oldCount))
389 {
390 // An invalid index causes the insertion to fail
391 // Invalid indexes are ones that add more than one entry to the
392 // array (i.e., they can append).
393 return PR_FALSE;
394 }
395
396 if (oldCount >= GetArraySize())
397 {
398 if (!GrowArrayBy(1))
399 return PR_FALSE;
400 }
401 // else the array is already large enough
402
403 PRInt32 slide = oldCount - aIndex;
404 if (0 != slide)
405 {
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]));
409 }
410
411 mImpl->mArray[aIndex] = aElement;
412 mImpl->mCount++;
413
414#if DEBUG_VOIDARRAY
415 if (mImpl->mCount > mMaxCount &&
416 mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
417 {
418 MaxElements[mImpl->mCount]++;
419 MaxElements[mMaxCount]--;
420 mMaxCount = mImpl->mCount;
421 }
422#endif
423
424 return PR_TRUE;
425}
426
427PRBool nsVoidArray::InsertElementsAt(const nsVoidArray& other, PRInt32 aIndex)
428{
429 PRInt32 oldCount = Count();
430 PRInt32 otherCount = other.Count();
431
432 NS_ASSERTION(aIndex >= 0,"InsertElementsAt(negative index)");
433 if (PRUint32(aIndex) > PRUint32(oldCount))
434 {
435 // An invalid index causes the insertion to fail
436 // Invalid indexes are ones that are more than one entry past the end of
437 // the array (i.e., they can append).
438 return PR_FALSE;
439 }
440
441 if (oldCount + otherCount > GetArraySize())
442 {
443 if (!GrowArrayBy(otherCount))
444 return PR_FALSE;;
445 }
446 // else the array is already large enough
447
448 PRInt32 slide = oldCount - aIndex;
449 if (0 != slide)
450 {
451 // Slide data over to make room for the insertion
452 memmove(mImpl->mArray + aIndex + otherCount, mImpl->mArray + aIndex,
453 slide * sizeof(mImpl->mArray[0]));
454 }
455
456 for (PRInt32 i = 0; i < otherCount; i++)
457 {
458 // copy all the elements (destroys aIndex)
459 mImpl->mArray[aIndex++] = other.mImpl->mArray[i];
460 mImpl->mCount++;
461 }
462
463#if DEBUG_VOIDARRAY
464 if (mImpl->mCount > mMaxCount &&
465 mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
466 {
467 MaxElements[mImpl->mCount]++;
468 MaxElements[mMaxCount]--;
469 mMaxCount = mImpl->mCount;
470 }
471#endif
472
473 return PR_TRUE;
474}
475
476PRBool nsVoidArray::ReplaceElementAt(void* aElement, PRInt32 aIndex)
477{
478 NS_ASSERTION(aIndex >= 0,"ReplaceElementAt(negative index)");
479 if (aIndex < 0)
480 return PR_FALSE;
481
482 // Unlike InsertElementAt, ReplaceElementAt can implicitly add more
483 // than just the one element to the array.
484 if (PRUint32(aIndex) >= PRUint32(GetArraySize()))
485 {
486 PRInt32 oldCount = Count();
487 PRInt32 requestedCount = aIndex + 1;
488 PRInt32 growDelta = requestedCount - oldCount;
489
490 // frees old mImpl IF this succeeds
491 if (!GrowArrayBy(growDelta))
492 return PR_FALSE;
493 }
494
495 mImpl->mArray[aIndex] = aElement;
496 if (aIndex >= mImpl->mCount)
497 {
498 // Make sure that any entries implicitly added to the array by this
499 // ReplaceElementAt are cleared to 0. Some users of this assume that.
500 // This code means we don't have to memset when we allocate an array.
501 if (aIndex > mImpl->mCount) // note: not >=
502 {
503 // For example, if mCount is 2, and we do a ReplaceElementAt for
504 // element[5], then we need to set three entries ([2], [3], and [4])
505 // to 0.
506 memset(&mImpl->mArray[mImpl->mCount], 0,
507 (aIndex - mImpl->mCount) * sizeof(mImpl->mArray[0]));
508 }
509
510 mImpl->mCount = aIndex + 1;
511
512#if DEBUG_VOIDARRAY
513 if (mImpl->mCount > mMaxCount &&
514 mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
515 {
516 MaxElements[mImpl->mCount]++;
517 MaxElements[mMaxCount]--;
518 mMaxCount = mImpl->mCount;
519 }
520#endif
521 }
522
523 return PR_TRUE;
524}
525
526// useful for doing LRU arrays
527PRBool nsVoidArray::MoveElement(PRInt32 aFrom, PRInt32 aTo)
528{
529 void *tempElement;
530
531 if (aTo == aFrom)
532 return PR_TRUE;
533
534 NS_ASSERTION(aTo >= 0 && aFrom >= 0,"MoveElement(negative index)");
535 if (aTo >= Count() || aFrom >= Count())
536 {
537 // can't extend the array when moving an element. Also catches mImpl = null
538 return PR_FALSE;
539 }
540 tempElement = mImpl->mArray[aFrom];
541
542 if (aTo < aFrom)
543 {
544 // Moving one element closer to the head; the elements inbetween move down
545 memmove(mImpl->mArray + aTo + 1, mImpl->mArray + aTo,
546 (aFrom-aTo) * sizeof(mImpl->mArray[0]));
547 mImpl->mArray[aTo] = tempElement;
548 }
549 else // already handled aFrom == aTo
550 {
551 // Moving one element closer to the tail; the elements inbetween move up
552 memmove(mImpl->mArray + aFrom, mImpl->mArray + aFrom + 1,
553 (aTo-aFrom) * sizeof(mImpl->mArray[0]));
554 mImpl->mArray[aTo] = tempElement;
555 }
556
557 return PR_TRUE;
558}
559
560PRBool nsVoidArray::RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount)
561{
562 PRInt32 oldCount = Count();
563 NS_ASSERTION(aIndex >= 0,"RemoveElementsAt(negative index)");
564 if (PRUint32(aIndex) >= PRUint32(oldCount))
565 {
566 // An invalid index causes the replace to fail
567 return PR_FALSE;
568 }
569 // Limit to available entries starting at aIndex
570 if (aCount + aIndex > oldCount)
571 aCount = oldCount - aIndex;
572
573 // We don't need to move any elements if we're removing the
574 // last element in the array
575 if (aIndex < (oldCount - aCount))
576 {
577 memmove(mImpl->mArray + aIndex, mImpl->mArray + aIndex + aCount,
578 (oldCount - (aIndex + aCount)) * sizeof(mImpl->mArray[0]));
579 }
580
581 mImpl->mCount -= aCount;
582 return PR_TRUE;
583}
584
585PRBool nsVoidArray::RemoveElement(void* aElement)
586{
587 PRInt32 theIndex = IndexOf(aElement);
588 if (theIndex != -1)
589 return RemoveElementAt(theIndex);
590
591 return PR_FALSE;
592}
593
594void nsVoidArray::Clear()
595{
596 if (mImpl)
597 {
598 mImpl->mCount = 0;
599 }
600}
601
602void nsVoidArray::Compact()
603{
604 if (mImpl)
605 {
606 // XXX NOTE: this is quite inefficient in many cases if we're only
607 // compacting by a little, but some callers care more about memory use.
608 if (GetArraySize() > Count())
609 {
610 SizeTo(Count());
611 }
612 }
613}
614
615// Needed because we want to pass the pointer to the item in the array
616// to the comparator function, not a pointer to the pointer in the array.
617struct VoidArrayComparatorContext {
618 nsVoidArrayComparatorFunc mComparatorFunc;
619 void* mData;
620};
621
622static DECLCALLBACK(int) VoidArrayComparator(const void* aElement1, const void* aElement2, void* aData)
623{
624 VoidArrayComparatorContext* ctx = NS_STATIC_CAST(VoidArrayComparatorContext*, aData);
625 return (*ctx->mComparatorFunc)(*NS_STATIC_CAST(void* const*, aElement1),
626 *NS_STATIC_CAST(void* const*, aElement2),
627 ctx->mData);
628}
629
630void nsVoidArray::Sort(nsVoidArrayComparatorFunc aFunc, void* aData)
631{
632 if (mImpl && mImpl->mCount > 1)
633 {
634 VoidArrayComparatorContext ctx = {aFunc, aData};
635 RTSortShell(mImpl->mArray, mImpl->mCount, sizeof(mImpl->mArray[0]),
636 VoidArrayComparator, &ctx);
637 }
638}
639
640PRBool nsVoidArray::EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData)
641{
642 PRInt32 index = -1;
643 PRBool running = PR_TRUE;
644
645 if (mImpl)
646 {
647 while (running && (++index < mImpl->mCount))
648 {
649 running = (*aFunc)(mImpl->mArray[index], aData);
650 }
651 }
652 return running;
653}
654
655PRBool nsVoidArray::EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData)
656{
657 PRBool running = PR_TRUE;
658
659 if (mImpl)
660 {
661 PRInt32 index = Count();
662 while (running && (0 <= --index))
663 {
664 running = (*aFunc)(mImpl->mArray[index], aData);
665 }
666 }
667 return running;
668}
669
670//----------------------------------------------------------------
671// nsAutoVoidArray
672
673nsAutoVoidArray::nsAutoVoidArray()
674 : nsVoidArray()
675{
676 // Don't need to clear it. Some users just call ReplaceElementAt(),
677 // but we'll clear it at that time if needed to save CPU cycles.
678#if DEBUG_VOIDARRAY
679 mIsAuto = PR_TRUE;
680 ADD_TO_STATS(MaxAuto,0);
681#endif
682 SetArray(NS_REINTERPRET_CAST(Impl*, mAutoBuf),kAutoBufSize,0,PR_FALSE);
683}
684
685void nsAutoVoidArray::Clear()
686{
687 // We don't have to free on Clear, but since we have a built-in buffer,
688 // it's worth considering.
689 nsVoidArray::Clear();
690 if (IsArrayOwner() && GetArraySize() > 4*kAutoBufSize)
691 SizeTo(0); // we override CompactTo - delete and repoint at auto array
692}
693
694PRBool nsAutoVoidArray::SizeTo(PRInt32 aSize)
695{
696 if (!nsVoidArray::SizeTo(aSize))
697 return PR_FALSE;
698
699 if (!mImpl)
700 {
701 // reset the array to point to our autobuf
702 SetArray(NS_REINTERPRET_CAST(Impl*, mAutoBuf),kAutoBufSize,0,PR_FALSE);
703 }
704 return PR_TRUE;
705}
706
707void nsAutoVoidArray::Compact()
708{
709 nsVoidArray::Compact();
710 if (!mImpl)
711 {
712 // reset the array to point to our autobuf
713 SetArray(NS_REINTERPRET_CAST(Impl*, mAutoBuf),kAutoBufSize,0,PR_FALSE);
714 }
715}
716
717//----------------------------------------------------------------
718// nsStringArray
719
720nsStringArray::nsStringArray(void)
721 : nsVoidArray()
722{
723}
724
725nsStringArray::nsStringArray(PRInt32 aCount)
726 : nsVoidArray(aCount)
727{
728}
729
730nsStringArray::~nsStringArray(void)
731{
732 Clear();
733}
734
735nsStringArray&
736nsStringArray::operator=(const nsStringArray& other)
737{
738 // Copy the pointers
739 nsVoidArray::operator=(other);
740
741 // Now copy the strings
742 for (PRInt32 i = Count() - 1; i >= 0; --i)
743 {
744 nsString* oldString = NS_STATIC_CAST(nsString*, other.ElementAt(i));
745 mImpl->mArray[i] = new nsString(*oldString);
746 }
747
748 return *this;
749}
750
751void
752nsStringArray::StringAt(PRInt32 aIndex, nsAString& aString) const
753{
754 nsString* string = NS_STATIC_CAST(nsString*, nsVoidArray::ElementAt(aIndex));
755 if (nsnull != string)
756 {
757 aString.Assign(*string);
758 }
759 else
760 {
761 aString.Truncate();
762 }
763}
764
765nsString*
766nsStringArray::StringAt(PRInt32 aIndex) const
767{
768 return NS_STATIC_CAST(nsString*, nsVoidArray::ElementAt(aIndex));
769}
770
771PRInt32
772nsStringArray::IndexOf(const nsAString& aPossibleString) const
773{
774 if (mImpl)
775 {
776 void** ap = mImpl->mArray;
777 void** end = ap + mImpl->mCount;
778 while (ap < end)
779 {
780 nsString* string = NS_STATIC_CAST(nsString*, *ap);
781 if (string->Equals(aPossibleString))
782 {
783 return ap - mImpl->mArray;
784 }
785 ap++;
786 }
787 }
788 return -1;
789}
790
791PRBool
792nsStringArray::InsertStringAt(const nsAString& aString, PRInt32 aIndex)
793{
794 nsString* string = new nsString(aString);
795 if (nsVoidArray::InsertElementAt(string, aIndex))
796 {
797 return PR_TRUE;
798 }
799 delete string;
800 return PR_FALSE;
801}
802
803PRBool
804nsStringArray::ReplaceStringAt(const nsAString& aString,
805 PRInt32 aIndex)
806{
807 nsString* string = NS_STATIC_CAST(nsString*, nsVoidArray::ElementAt(aIndex));
808 if (nsnull != string)
809 {
810 *string = aString;
811 return PR_TRUE;
812 }
813 return PR_FALSE;
814}
815
816PRBool
817nsStringArray::RemoveString(const nsAString& aString)
818{
819 PRInt32 index = IndexOf(aString);
820 if (-1 < index)
821 {
822 return RemoveStringAt(index);
823 }
824 return PR_FALSE;
825}
826
827PRBool nsStringArray::RemoveStringAt(PRInt32 aIndex)
828{
829 nsString* string = StringAt(aIndex);
830 if (nsnull != string)
831 {
832 nsVoidArray::RemoveElementAt(aIndex);
833 delete string;
834 return PR_TRUE;
835 }
836 return PR_FALSE;
837}
838
839void
840nsStringArray::Clear(void)
841{
842 PRInt32 index = Count();
843 while (0 <= --index)
844 {
845 nsString* string = NS_STATIC_CAST(nsString*, mImpl->mArray[index]);
846 delete string;
847 }
848 nsVoidArray::Clear();
849}
850
851PR_STATIC_CALLBACK(int)
852CompareString(const nsString* aString1, const nsString* aString2, void*)
853{
854 return Compare(*aString1, *aString2);
855}
856
857void nsStringArray::Sort(void)
858{
859 Sort(CompareString, nsnull);
860}
861
862void nsStringArray::Sort(nsStringArrayComparatorFunc aFunc, void* aData)
863{
864 nsVoidArray::Sort(NS_REINTERPRET_CAST(nsVoidArrayComparatorFunc, aFunc), aData);
865}
866
867PRBool
868nsStringArray::EnumerateForwards(nsStringArrayEnumFunc aFunc, void* aData)
869{
870 PRInt32 index = -1;
871 PRBool running = PR_TRUE;
872
873 if (mImpl)
874 {
875 while (running && (++index < mImpl->mCount))
876 {
877 running = (*aFunc)(*NS_STATIC_CAST(nsString*, mImpl->mArray[index]), aData);
878 }
879 }
880 return running;
881}
882
883PRBool
884nsStringArray::EnumerateBackwards(nsStringArrayEnumFunc aFunc, void* aData)
885{
886 PRInt32 index = Count();
887 PRBool running = PR_TRUE;
888
889 if (mImpl)
890 {
891 while (running && (0 <= --index))
892 {
893 running = (*aFunc)(*NS_STATIC_CAST(nsString*, mImpl->mArray[index]), aData);
894 }
895 }
896 return running;
897}
898
899
900
901//----------------------------------------------------------------
902// nsCStringArray
903
904nsCStringArray::nsCStringArray(void)
905 : nsVoidArray()
906{
907}
908
909// Parses a given string using the delimiter passed in and appends items
910// parsed to the array.
911void
912nsCStringArray::ParseString(const char* string, const char* delimiter)
913{
914 if (string && *string && delimiter && *delimiter) {
915 char *newStr;
916 char *rest = nsCRT::strdup(string);
917 char *token = nsCRT::strtok(rest, delimiter, &newStr);
918
919 while (token) {
920 if (*token) {
921 /* calling AppendElement(void*) to avoid extra nsCString copy */
922 AppendElement(new nsCString(token));
923 }
924 token = nsCRT::strtok(newStr, delimiter, &newStr);
925 }
926 PR_FREEIF(rest);
927 }
928}
929
930nsCStringArray::nsCStringArray(PRInt32 aCount)
931 : nsVoidArray(aCount)
932{
933}
934
935nsCStringArray::~nsCStringArray(void)
936{
937 Clear();
938}
939
940nsCStringArray&
941nsCStringArray::operator=(const nsCStringArray& other)
942{
943 // Copy the pointers
944 nsVoidArray::operator=(other);
945
946 // Now copy the strings
947 for (PRInt32 i = Count() - 1; i >= 0; --i)
948 {
949 nsCString* oldString = NS_STATIC_CAST(nsCString*, other.ElementAt(i));
950 mImpl->mArray[i] = new nsCString(*oldString);
951 }
952
953 return *this;
954}
955
956void
957nsCStringArray::CStringAt(PRInt32 aIndex, nsACString& aCString) const
958{
959 nsCString* string = NS_STATIC_CAST(nsCString*, nsVoidArray::ElementAt(aIndex));
960 if (nsnull != string)
961 {
962 aCString = *string;
963 }
964 else
965 {
966 aCString.Truncate();
967 }
968}
969
970nsCString*
971nsCStringArray::CStringAt(PRInt32 aIndex) const
972{
973 return NS_STATIC_CAST(nsCString*, nsVoidArray::ElementAt(aIndex));
974}
975
976PRInt32
977nsCStringArray::IndexOf(const nsACString& aPossibleString) const
978{
979 if (mImpl)
980 {
981 void** ap = mImpl->mArray;
982 void** end = ap + mImpl->mCount;
983 while (ap < end)
984 {
985 nsCString* string = NS_STATIC_CAST(nsCString*, *ap);
986 if (string->Equals(aPossibleString))
987 {
988 return ap - mImpl->mArray;
989 }
990 ap++;
991 }
992 }
993 return -1;
994}
995
996PRInt32
997nsCStringArray::IndexOfIgnoreCase(const nsACString& aPossibleString) const
998{
999 if (mImpl)
1000 {
1001 void** ap = mImpl->mArray;
1002 void** end = ap + mImpl->mCount;
1003 while (ap < end)
1004 {
1005 nsCString* string = NS_STATIC_CAST(nsCString*, *ap);
1006 if (string->Equals(aPossibleString, nsCaseInsensitiveCStringComparator()))
1007 {
1008 return ap - mImpl->mArray;
1009 }
1010 ap++;
1011 }
1012 }
1013 return -1;
1014}
1015
1016PRBool
1017nsCStringArray::InsertCStringAt(const nsACString& aCString, PRInt32 aIndex)
1018{
1019 nsCString* string = new nsCString(aCString);
1020 if (nsVoidArray::InsertElementAt(string, aIndex))
1021 {
1022 return PR_TRUE;
1023 }
1024 delete string;
1025 return PR_FALSE;
1026}
1027
1028PRBool
1029nsCStringArray::ReplaceCStringAt(const nsACString& aCString, PRInt32 aIndex)
1030{
1031 nsCString* string = NS_STATIC_CAST(nsCString*, nsVoidArray::ElementAt(aIndex));
1032 if (nsnull != string)
1033 {
1034 *string = aCString;
1035 return PR_TRUE;
1036 }
1037 return PR_FALSE;
1038}
1039
1040PRBool
1041nsCStringArray::RemoveCString(const nsACString& aCString)
1042{
1043 PRInt32 index = IndexOf(aCString);
1044 if (-1 < index)
1045 {
1046 return RemoveCStringAt(index);
1047 }
1048 return PR_FALSE;
1049}
1050
1051PRBool
1052nsCStringArray::RemoveCStringIgnoreCase(const nsACString& aCString)
1053{
1054 PRInt32 index = IndexOfIgnoreCase(aCString);
1055 if (-1 < index)
1056 {
1057 return RemoveCStringAt(index);
1058 }
1059 return PR_FALSE;
1060}
1061
1062PRBool nsCStringArray::RemoveCStringAt(PRInt32 aIndex)
1063{
1064 nsCString* string = CStringAt(aIndex);
1065 if (nsnull != string)
1066 {
1067 nsVoidArray::RemoveElementAt(aIndex);
1068 delete string;
1069 return PR_TRUE;
1070 }
1071 return PR_FALSE;
1072}
1073
1074void
1075nsCStringArray::Clear(void)
1076{
1077 PRInt32 index = Count();
1078 while (0 <= --index)
1079 {
1080 nsCString* string = NS_STATIC_CAST(nsCString*, mImpl->mArray[index]);
1081 delete string;
1082 }
1083 nsVoidArray::Clear();
1084}
1085
1086PR_STATIC_CALLBACK(int)
1087CompareCString(const nsCString* aCString1, const nsCString* aCString2, void*)
1088{
1089 return Compare(*aCString1, *aCString2);
1090}
1091
1092PR_STATIC_CALLBACK(int)
1093CompareCStringIgnoreCase(const nsCString* aCString1, const nsCString* aCString2, void*)
1094{
1095 return Compare(*aCString1, *aCString2, nsCaseInsensitiveCStringComparator());
1096}
1097
1098void nsCStringArray::Sort(void)
1099{
1100 Sort(CompareCString, nsnull);
1101}
1102
1103void nsCStringArray::SortIgnoreCase(void)
1104{
1105 Sort(CompareCStringIgnoreCase, nsnull);
1106}
1107
1108void nsCStringArray::Sort(nsCStringArrayComparatorFunc aFunc, void* aData)
1109{
1110 nsVoidArray::Sort(NS_REINTERPRET_CAST(nsVoidArrayComparatorFunc, aFunc), aData);
1111}
1112
1113PRBool
1114nsCStringArray::EnumerateForwards(nsCStringArrayEnumFunc aFunc, void* aData)
1115{
1116 PRBool running = PR_TRUE;
1117
1118 if (mImpl)
1119 {
1120 PRInt32 index = -1;
1121 while (running && (++index < mImpl->mCount))
1122 {
1123 running = (*aFunc)(*NS_STATIC_CAST(nsCString*, mImpl->mArray[index]), aData);
1124 }
1125 }
1126 return running;
1127}
1128
1129PRBool
1130nsCStringArray::EnumerateBackwards(nsCStringArrayEnumFunc aFunc, void* aData)
1131{
1132 PRBool running = PR_TRUE;
1133
1134 if (mImpl)
1135 {
1136 PRInt32 index = Count();
1137 while (running && (0 <= --index))
1138 {
1139 running = (*aFunc)(*NS_STATIC_CAST(nsCString*, mImpl->mArray[index]), aData);
1140 }
1141 }
1142 return running;
1143}
1144
1145
1146//----------------------------------------------------------------------
1147// NOTE: nsSmallVoidArray elements MUST all have the low bit as 0.
1148// This means that normally it's only used for pointers, and in particular
1149// structures or objects.
1150nsSmallVoidArray::nsSmallVoidArray()
1151{
1152 mChildren = nsnull;
1153}
1154
1155nsSmallVoidArray::~nsSmallVoidArray()
1156{
1157 if (HasVector())
1158 {
1159 nsVoidArray* vector = GetChildVector();
1160 delete vector;
1161 }
1162}
1163
1164nsSmallVoidArray&
1165nsSmallVoidArray::operator=(nsSmallVoidArray& other)
1166{
1167 nsVoidArray* ourArray = GetChildVector();
1168 nsVoidArray* otherArray = other.GetChildVector();
1169
1170 if (HasVector())
1171 {
1172 if (other.HasVector())
1173 {
1174 // if both are real arrays, just use array= */
1175 *ourArray = *otherArray;
1176 }
1177 else
1178 {
1179 // we have an array, but the other doesn't.
1180 otherArray = other.SwitchToVector();
1181 if (otherArray)
1182 *ourArray = *otherArray;
1183 }
1184 }
1185 else
1186 {
1187 if (other.HasVector())
1188 {
1189 // we have no array, but other does
1190 ourArray = SwitchToVector();
1191 if (ourArray)
1192 *ourArray = *otherArray;
1193 }
1194 else
1195 {
1196 // neither has an array (either may have 0 or 1 items)
1197 SetSingleChild(other.GetSingleChild());
1198 }
1199 }
1200 return *this;
1201}
1202
1203PRInt32
1204nsSmallVoidArray::GetArraySize() const
1205{
1206 nsVoidArray* vector = GetChildVector();
1207 if (vector)
1208 return vector->GetArraySize();
1209
1210 return 1;
1211}
1212
1213PRInt32
1214nsSmallVoidArray::Count() const
1215{
1216 if (HasSingleChild())
1217 {
1218 return 1;
1219 }
1220 else {
1221 nsVoidArray* vector = GetChildVector();
1222 if (vector)
1223 return vector->Count();
1224 }
1225
1226 return 0;
1227}
1228
1229void*
1230nsSmallVoidArray::ElementAt(PRInt32 aIndex) const
1231{
1232 if (HasSingleChild())
1233 {
1234 if (0 == aIndex)
1235 return (void*)GetSingleChild();
1236 }
1237 else
1238 {
1239 nsVoidArray* vector = GetChildVector();
1240 if (vector)
1241 return vector->ElementAt(aIndex);
1242 }
1243
1244 return nsnull;
1245}
1246
1247PRInt32
1248nsSmallVoidArray::IndexOf(void* aPossibleElement) const
1249{
1250 if (HasSingleChild())
1251 {
1252 if (aPossibleElement == (void*)GetSingleChild())
1253 return 0;
1254 }
1255 else
1256 {
1257 nsVoidArray* vector = GetChildVector();
1258 if (vector)
1259 return vector->IndexOf(aPossibleElement);
1260 }
1261
1262 return -1;
1263}
1264
1265PRBool
1266nsSmallVoidArray::InsertElementAt(void* aElement, PRInt32 aIndex)
1267{
1268 nsVoidArray* vector;
1269 NS_ASSERTION(!(PtrBits(aElement) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
1270 NS_ASSERTION(aElement != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
1271
1272 if (HasSingleChild())
1273 {
1274 vector = SwitchToVector();
1275 }
1276 else
1277 {
1278 vector = GetChildVector();
1279 if (!vector)
1280 {
1281 if (0 == aIndex)
1282 {
1283 SetSingleChild(aElement);
1284 return PR_TRUE;
1285 }
1286 return PR_FALSE;
1287 }
1288 }
1289
1290 return vector->InsertElementAt(aElement, aIndex);
1291}
1292
1293PRBool nsSmallVoidArray::InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex)
1294{
1295 nsVoidArray* vector;
1296 PRInt32 count = other.Count();
1297 if (count == 0)
1298 return PR_TRUE;
1299
1300#ifdef DEBUG
1301 for (int i = 0; i < count; i++)
1302 {
1303 NS_ASSERTION(!(PtrBits(other.ElementAt(i)) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
1304 NS_ASSERTION(other.ElementAt(i) != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
1305 }
1306#endif
1307
1308 if (!HasVector())
1309 {
1310 if (HasSingleChild() || count > 1 || aIndex > 0)
1311 {
1312 vector = SwitchToVector();
1313 }
1314 else
1315 {
1316 // count == 1, aIndex == 0, no elements already
1317 SetSingleChild(other[0]);
1318 return PR_TRUE;
1319 }
1320 }
1321 else
1322 {
1323 vector = GetChildVector();
1324 }
1325
1326 if (vector)
1327 {
1328 return vector->InsertElementsAt(other,aIndex);
1329 }
1330 return PR_TRUE;
1331}
1332
1333PRBool
1334nsSmallVoidArray::ReplaceElementAt(void* aElement, PRInt32 aIndex)
1335{
1336 NS_ASSERTION(!(PtrBits(aElement) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
1337 NS_ASSERTION(aElement != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
1338
1339 if (HasSingleChild())
1340 {
1341 if (aIndex == 0)
1342 {
1343 SetSingleChild(aElement);
1344 return PR_TRUE;
1345 }
1346 return PR_FALSE;
1347 }
1348 else
1349 {
1350 nsVoidArray* vector = GetChildVector();
1351 if (vector)
1352 return vector->ReplaceElementAt(aElement, aIndex);
1353
1354 return PR_FALSE;
1355 }
1356}
1357
1358PRBool
1359nsSmallVoidArray::AppendElement(void* aElement)
1360{
1361 NS_ASSERTION(!(PtrBits(aElement) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
1362 NS_ASSERTION(aElement != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
1363
1364 nsVoidArray* vector;
1365 if (HasSingleChild())
1366 {
1367 vector = SwitchToVector();
1368 }
1369 else
1370 {
1371 vector = GetChildVector();
1372 if (!vector)
1373 {
1374 SetSingleChild(aElement);
1375 return PR_TRUE;
1376 }
1377 }
1378
1379 return vector->AppendElement(aElement);
1380}
1381
1382PRBool
1383nsSmallVoidArray::RemoveElement(void* aElement)
1384{
1385 if (HasSingleChild())
1386 {
1387 if (aElement == GetSingleChild())
1388 {
1389 SetSingleChild(nsnull);
1390 return PR_TRUE;
1391 }
1392 }
1393 else
1394 {
1395 nsVoidArray* vector = GetChildVector();
1396 if (vector)
1397 return vector->RemoveElement(aElement);
1398 }
1399
1400 return PR_FALSE;
1401}
1402
1403PRBool
1404nsSmallVoidArray::RemoveElementAt(PRInt32 aIndex)
1405{
1406 if (HasSingleChild())
1407 {
1408 if (0 == aIndex)
1409 {
1410 SetSingleChild(nsnull);
1411 return PR_TRUE;
1412 }
1413 }
1414 else
1415 {
1416 nsVoidArray* vector = GetChildVector();
1417 if (vector)
1418 {
1419 return vector->RemoveElementAt(aIndex);
1420 }
1421 }
1422
1423 return PR_FALSE;
1424}
1425
1426PRBool
1427nsSmallVoidArray::RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount)
1428{
1429 nsVoidArray* vector = GetChildVector();
1430
1431 if (aCount == 0)
1432 return PR_TRUE;
1433
1434 if (HasSingleChild())
1435 {
1436 if (aIndex == 0)
1437 SetSingleChild(nsnull);
1438 return PR_TRUE;
1439 }
1440
1441 if (!vector)
1442 return PR_TRUE;
1443
1444 // complex case; remove entries from an array
1445 return vector->RemoveElementsAt(aIndex,aCount);
1446}
1447
1448void
1449nsSmallVoidArray::Clear()
1450{
1451 if (HasVector())
1452 {
1453 nsVoidArray* vector = GetChildVector();
1454 vector->Clear();
1455 }
1456 else
1457 {
1458 SetSingleChild(nsnull);
1459 }
1460}
1461
1462PRBool
1463nsSmallVoidArray::SizeTo(PRInt32 aMin)
1464{
1465 nsVoidArray* vector;
1466 if (!HasVector())
1467 {
1468 if (aMin <= 1)
1469 return PR_TRUE;
1470 vector = SwitchToVector();
1471 }
1472 else
1473 {
1474 vector = GetChildVector();
1475 if (aMin <= 1)
1476 {
1477 void *prev = nsnull;
1478 if (vector->Count() == 1)
1479 {
1480 prev = vector->ElementAt(0);
1481 }
1482 delete vector;
1483 SetSingleChild(prev);
1484 return PR_TRUE;
1485 }
1486 }
1487 return vector->SizeTo(aMin);
1488}
1489
1490void
1491nsSmallVoidArray::Compact()
1492{
1493 if (!HasSingleChild())
1494 {
1495 nsVoidArray* vector = GetChildVector();
1496 if (vector)
1497 vector->Compact();
1498 }
1499}
1500
1501void
1502nsSmallVoidArray::Sort(nsVoidArrayComparatorFunc aFunc, void* aData)
1503{
1504 if (HasVector())
1505 {
1506 nsVoidArray* vector = GetChildVector();
1507 vector->Sort(aFunc,aData);
1508 }
1509}
1510
1511PRBool
1512nsSmallVoidArray::EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData)
1513{
1514 if (HasVector())
1515 {
1516 nsVoidArray* vector = GetChildVector();
1517 return vector->EnumerateForwards(aFunc,aData);
1518 }
1519 if (HasSingleChild())
1520 {
1521 return (*aFunc)(GetSingleChild(), aData);
1522 }
1523 return PR_TRUE;
1524}
1525
1526PRBool
1527nsSmallVoidArray::EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData)
1528{
1529 if (HasVector())
1530 {
1531 nsVoidArray* vector = GetChildVector();
1532 return vector->EnumerateBackwards(aFunc,aData);
1533 }
1534 if (HasSingleChild())
1535 {
1536 return (*aFunc)(GetSingleChild(), aData);
1537 }
1538 return PR_TRUE;
1539}
1540
1541void
1542nsSmallVoidArray::SetSingleChild(void* aChild)
1543{
1544 if (aChild)
1545 mChildren = (void*)(PtrBits(aChild) | 0x1);
1546 else
1547 mChildren = nsnull;
1548}
1549
1550nsVoidArray*
1551nsSmallVoidArray::SwitchToVector()
1552{
1553 void* child = GetSingleChild();
1554
1555 mChildren = (void*)new nsAutoVoidArray();
1556 nsVoidArray* vector = GetChildVector();
1557 if (vector && child)
1558 vector->AppendElement(child);
1559
1560 return vector;
1561}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette