2 ******************************************************************************
3 * Copyright (C) 1999-2010, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 ******************************************************************************
6 * Date Name Description
7 * 10/22/99 alan Creation.
8 **********************************************************************
17 #define DEFAULT_CAPACITY 8
20 * Constants for hinting whether a key is an integer
21 * or a pointer. If a hint bit is zero, then the associated
22 * token is assumed to be an integer. This is needed for iSeries
24 #define HINT_KEY_POINTER (1)
25 #define HINT_KEY_INTEGER (0)
27 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector
)
29 UVector::UVector(UErrorCode
&status
) :
36 _init(DEFAULT_CAPACITY
, status
);
39 UVector::UVector(int32_t initialCapacity
, UErrorCode
&status
) :
46 _init(initialCapacity
, status
);
49 UVector::UVector(UObjectDeleter
*d
, UKeyComparator
*c
, UErrorCode
&status
) :
56 _init(DEFAULT_CAPACITY
, status
);
59 UVector::UVector(UObjectDeleter
*d
, UKeyComparator
*c
, int32_t initialCapacity
, UErrorCode
&status
) :
66 _init(initialCapacity
, status
);
69 void UVector::_init(int32_t initialCapacity
, UErrorCode
&status
) {
70 if (U_FAILURE(status
)) {
73 // Fix bogus initialCapacity values; avoid malloc(0) and integer overflow
74 if ((initialCapacity
< 1) || (initialCapacity
> (int32_t)(INT32_MAX
/ sizeof(UHashTok
)))) {
75 initialCapacity
= DEFAULT_CAPACITY
;
77 elements
= (UHashTok
*)uprv_malloc(sizeof(UHashTok
)*initialCapacity
);
79 status
= U_MEMORY_ALLOCATION_ERROR
;
81 capacity
= initialCapacity
;
92 * Assign this object to another (make this a copy of 'other').
93 * Use the 'assign' function to assign each element.
95 void UVector::assign(const UVector
& other
, UTokenAssigner
*assign
, UErrorCode
&ec
) {
96 if (ensureCapacity(other
.count
, ec
)) {
97 setSize(other
.count
, ec
);
99 for (int32_t i
=0; i
<other
.count
; ++i
) {
100 if (elements
[i
].pointer
!= 0 && deleter
!= 0) {
101 (*deleter
)(elements
[i
].pointer
);
103 (*assign
)(&elements
[i
], &other
.elements
[i
]);
109 // This only does something sensible if this object has a non-null comparer
110 UBool
UVector::operator==(const UVector
& other
) {
112 if (count
!= other
.count
) return FALSE
;
113 if (comparer
!= NULL
) {
114 // Compare using this object's comparer
115 for (i
=0; i
<count
; ++i
) {
116 if (!(*comparer
)(elements
[i
], other
.elements
[i
])) {
124 void UVector::addElement(void* obj
, UErrorCode
&status
) {
125 if (ensureCapacity(count
+ 1, status
)) {
126 elements
[count
++].pointer
= obj
;
130 void UVector::addElement(int32_t elem
, UErrorCode
&status
) {
131 if (ensureCapacity(count
+ 1, status
)) {
132 elements
[count
].pointer
= NULL
; // Pointers may be bigger than ints.
133 elements
[count
].integer
= elem
;
138 void UVector::setElementAt(void* obj
, int32_t index
) {
139 if (0 <= index
&& index
< count
) {
140 if (elements
[index
].pointer
!= 0 && deleter
!= 0) {
141 (*deleter
)(elements
[index
].pointer
);
143 elements
[index
].pointer
= obj
;
145 /* else index out of range */
148 void UVector::setElementAt(int32_t elem
, int32_t index
) {
149 if (0 <= index
&& index
< count
) {
150 if (elements
[index
].pointer
!= 0 && deleter
!= 0) {
151 // TODO: this should be an error. mixing up ints and pointers.
152 (*deleter
)(elements
[index
].pointer
);
154 elements
[index
].pointer
= NULL
;
155 elements
[index
].integer
= elem
;
157 /* else index out of range */
160 void UVector::insertElementAt(void* obj
, int32_t index
, UErrorCode
&status
) {
161 // must have 0 <= index <= count
162 if (0 <= index
&& index
<= count
&& ensureCapacity(count
+ 1, status
)) {
163 for (int32_t i
=count
; i
>index
; --i
) {
164 elements
[i
] = elements
[i
-1];
166 elements
[index
].pointer
= obj
;
169 /* else index out of range */
172 void UVector::insertElementAt(int32_t elem
, int32_t index
, UErrorCode
&status
) {
173 // must have 0 <= index <= count
174 if (0 <= index
&& index
<= count
&& ensureCapacity(count
+ 1, status
)) {
175 for (int32_t i
=count
; i
>index
; --i
) {
176 elements
[i
] = elements
[i
-1];
178 elements
[index
].pointer
= NULL
;
179 elements
[index
].integer
= elem
;
182 /* else index out of range */
185 void* UVector::elementAt(int32_t index
) const {
186 return (0 <= index
&& index
< count
) ? elements
[index
].pointer
: 0;
189 int32_t UVector::elementAti(int32_t index
) const {
190 return (0 <= index
&& index
< count
) ? elements
[index
].integer
: 0;
193 UBool
UVector::containsAll(const UVector
& other
) const {
194 for (int32_t i
=0; i
<other
.size(); ++i
) {
195 if (indexOf(other
.elements
[i
]) < 0) {
202 UBool
UVector::containsNone(const UVector
& other
) const {
203 for (int32_t i
=0; i
<other
.size(); ++i
) {
204 if (indexOf(other
.elements
[i
]) >= 0) {
211 UBool
UVector::removeAll(const UVector
& other
) {
212 UBool changed
= FALSE
;
213 for (int32_t i
=0; i
<other
.size(); ++i
) {
214 int32_t j
= indexOf(other
.elements
[i
]);
223 UBool
UVector::retainAll(const UVector
& other
) {
224 UBool changed
= FALSE
;
225 for (int32_t j
=size()-1; j
>=0; --j
) {
226 int32_t i
= other
.indexOf(elements
[j
]);
235 void UVector::removeElementAt(int32_t index
) {
236 void* e
= orphanElementAt(index
);
237 if (e
!= 0 && deleter
!= 0) {
242 UBool
UVector::removeElement(void* obj
) {
243 int32_t i
= indexOf(obj
);
251 void UVector::removeAllElements(void) {
253 for (int32_t i
=0; i
<count
; ++i
) {
254 if (elements
[i
].pointer
!= 0) {
255 (*deleter
)(elements
[i
].pointer
);
262 UBool
UVector::equals(const UVector
&other
) const {
265 if (this->count
!= other
.count
) {
269 for (i
=0; i
<count
; i
++) {
270 if (elements
[i
].pointer
!= other
.elements
[i
].pointer
) {
276 for (i
=0; i
<count
; i
++) {
277 key
.pointer
= &other
.elements
[i
];
278 if (!(*comparer
)(key
, elements
[i
])) {
288 int32_t UVector::indexOf(void* obj
, int32_t startIndex
) const {
291 return indexOf(key
, startIndex
, HINT_KEY_POINTER
);
294 int32_t UVector::indexOf(int32_t obj
, int32_t startIndex
) const {
297 return indexOf(key
, startIndex
, HINT_KEY_INTEGER
);
300 // This only works if this object has a non-null comparer
301 int32_t UVector::indexOf(UHashTok key
, int32_t startIndex
, int8_t hint
) const {
304 for (i
=startIndex
; i
<count
; ++i
) {
305 if ((*comparer
)(key
, elements
[i
])) {
310 for (i
=startIndex
; i
<count
; ++i
) {
311 /* Pointers are not always the same size as ints so to perform
312 * a valid comparision we need to know whether we are being
313 * provided an int or a pointer. */
314 if (hint
& HINT_KEY_POINTER
) {
315 if (key
.pointer
== elements
[i
].pointer
) {
319 if (key
.integer
== elements
[i
].integer
) {
328 UBool
UVector::ensureCapacity(int32_t minimumCapacity
, UErrorCode
&status
) {
329 if (minimumCapacity
< 0) {
330 status
= U_ILLEGAL_ARGUMENT_ERROR
;
333 if (capacity
< minimumCapacity
) {
334 if (capacity
> (INT32_MAX
- 1) / 2) { // integer overflow check
335 status
= U_ILLEGAL_ARGUMENT_ERROR
;
338 int32_t newCap
= capacity
* 2;
339 if (newCap
< minimumCapacity
) {
340 newCap
= minimumCapacity
;
342 if (newCap
> (int32_t)(INT32_MAX
/ sizeof(UHashTok
))) { // integer overflow check
343 // We keep the original memory contents on bad minimumCapacity.
344 status
= U_ILLEGAL_ARGUMENT_ERROR
;
347 UHashTok
* newElems
= (UHashTok
*)uprv_realloc(elements
, sizeof(UHashTok
)*newCap
);
348 if (newElems
== NULL
) {
349 // We keep the original contents on the memory failure on realloc or bad minimumCapacity.
350 status
= U_MEMORY_ALLOCATION_ERROR
;
360 * Change the size of this vector as follows: If newSize is smaller,
361 * then truncate the array, possibly deleting held elements for i >=
362 * newSize. If newSize is larger, grow the array, filling in new
365 void UVector::setSize(int32_t newSize
, UErrorCode
&status
) {
370 if (newSize
> count
) {
371 if (!ensureCapacity(newSize
, status
)) {
375 empty
.pointer
= NULL
;
377 for (i
=count
; i
<newSize
; ++i
) {
381 /* Most efficient to count down */
382 for (i
=count
-1; i
>=newSize
; --i
) {
390 * Fill in the given array with all elements of this vector.
392 void** UVector::toArray(void** result
) const {
394 for (int i
=0; i
<count
; ++i
) {
395 *a
++ = elements
[i
].pointer
;
400 UObjectDeleter
*UVector::setDeleter(UObjectDeleter
*d
) {
401 UObjectDeleter
*old
= deleter
;
406 UKeyComparator
*UVector::setComparer(UKeyComparator
*d
) {
407 UKeyComparator
*old
= comparer
;
413 * Removes the element at the given index from this vector and
414 * transfer ownership of it to the caller. After this call, the
415 * caller owns the result and must delete it and the vector entry
416 * at 'index' is removed, shifting all subsequent entries back by
417 * one index and shortening the size of the vector by one. If the
418 * index is out of range or if there is no item at the given index
419 * then 0 is returned and the vector is unchanged.
421 void* UVector::orphanElementAt(int32_t index
) {
423 if (0 <= index
&& index
< count
) {
424 e
= elements
[index
].pointer
;
425 for (int32_t i
=index
; i
<count
-1; ++i
) {
426 elements
[i
] = elements
[i
+1];
430 /* else index out of range */
435 * Insert the given object into this vector at its sorted position
436 * as defined by 'compare'. The current elements are assumed to
439 void UVector::sortedInsert(void* obj
, USortComparator
*compare
, UErrorCode
& ec
) {
442 sortedInsert(tok
, compare
, ec
);
446 * Insert the given integer into this vector at its sorted position
447 * as defined by 'compare'. The current elements are assumed to
450 void UVector::sortedInsert(int32_t obj
, USortComparator
*compare
, UErrorCode
& ec
) {
453 sortedInsert(tok
, compare
, ec
);
456 // ASSUME elements[] IS CURRENTLY SORTED
457 void UVector::sortedInsert(UHashTok tok
, USortComparator
*compare
, UErrorCode
& ec
) {
458 // Perform a binary search for the location to insert tok at. Tok
459 // will be inserted between two elements a and b such that a <=
460 // tok && tok < b, where there is a 'virtual' elements[-1] always
461 // less than tok and a 'virtual' elements[count] always greater
463 int32_t min
= 0, max
= count
;
465 int32_t probe
= (min
+ max
) / 2;
466 int8_t c
= (*compare
)(elements
[probe
], tok
);
474 if (ensureCapacity(count
+ 1, ec
)) {
475 for (int32_t i
=count
; i
>min
; --i
) {
476 elements
[i
] = elements
[i
-1];
484 * Array sort comparator function.
485 * Used from UVector::sort()
486 * Conforms to function signature required for uprv_sortArray().
487 * This function is essentially just a wrapper, to make a
488 * UVector style comparator function usable with uprv_sortArray().
490 * The context pointer to this function is a pointer back
491 * (with some extra indirection) to the user supplied comparator.
494 static int32_t U_CALLCONV
495 sortComparator(const void *context
, const void *left
, const void *right
) {
496 USortComparator
*compare
= *static_cast<USortComparator
* const *>(context
);
497 UHashTok tok1
= *static_cast<const UHashTok
*>(left
);
498 UHashTok tok2
= *static_cast<const UHashTok
*>(right
);
499 int32_t result
= (*compare
)(tok1
, tok2
);
505 * Array sort comparison function for use from UVector::sorti()
506 * Compares int32_t vector elements.
508 static int32_t U_CALLCONV
509 sortiComparator(const void * /*context */, const void *left
, const void *right
) {
510 const UHashTok
*tok1
= static_cast<const UHashTok
*>(left
);
511 const UHashTok
*tok2
= static_cast<const UHashTok
*>(right
);
512 int32_t result
= tok1
->integer
< tok2
->integer
? -1 :
513 tok1
->integer
== tok2
->integer
? 0 : 1;
518 * Sort the vector, assuming it constains ints.
519 * (A more general sort would take a comparison function, but it's
520 * not clear whether UVector's USortComparator or
521 * UComparator from uprv_sortAray would be more appropriate.)
523 void UVector::sorti(UErrorCode
&ec
) {
525 uprv_sortArray(elements
, count
, sizeof(UHashTok
),
526 sortiComparator
, NULL
, FALSE
, &ec
);
532 * Sort with a user supplied comparator.
534 * The comparator function handling is confusing because the function type
535 * for UVector (as defined for sortedInsert()) is different from the signature
536 * required by uprv_sortArray(). This is handled by passing the
537 * the UVector sort function pointer via the context pointer to a
538 * sortArray() comparator function, which can then call back to
539 * the original user functtion.
541 * An additional twist is that it's not safe to pass a pointer-to-function
542 * as a (void *) data pointer, so instead we pass a (data) pointer to a
543 * pointer-to-function variable.
545 void UVector::sort(USortComparator
*compare
, UErrorCode
&ec
) {
547 uprv_sortArray(elements
, count
, sizeof(UHashTok
),
548 sortComparator
, &compare
, FALSE
, &ec
);