2 ******************************************************************************
3 * Copyright (C) 1999-2004, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 ******************************************************************************
6 * Date Name Description
7 * 10/22/99 alan Creation.
8 **********************************************************************
16 #define DEFUALT_CAPACITY 8
19 * Constants for hinting whether a key is an integer
20 * or a pointer. If a hint bit is zero, then the associated
21 * token is assumed to be an integer. This is needed for iSeries
23 #define HINT_KEY_POINTER (1)
24 #define HINT_KEY_INTEGER (0)
26 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector
)
28 UVector::UVector(UErrorCode
&status
) :
35 _init(DEFUALT_CAPACITY
, status
);
38 UVector::UVector(int32_t initialCapacity
, UErrorCode
&status
) :
45 _init(initialCapacity
, status
);
48 UVector::UVector(UObjectDeleter
*d
, UKeyComparator
*c
, UErrorCode
&status
) :
55 _init(DEFUALT_CAPACITY
, status
);
58 UVector::UVector(UObjectDeleter
*d
, UKeyComparator
*c
, int32_t initialCapacity
, UErrorCode
&status
) :
65 _init(initialCapacity
, status
);
68 void UVector::_init(int32_t initialCapacity
, UErrorCode
&status
) {
69 if (U_FAILURE(status
)) {
72 // Fix bogus initialCapacity values; avoid malloc(0)
73 if (initialCapacity
< 1) {
74 initialCapacity
= DEFUALT_CAPACITY
;
76 elements
= (UHashTok
*)uprv_malloc(sizeof(UHashTok
)*initialCapacity
);
78 status
= U_MEMORY_ALLOCATION_ERROR
;
80 capacity
= initialCapacity
;
91 * Assign this object to another (make this a copy of 'other').
92 * Use the 'assign' function to assign each element.
94 void UVector::assign(const UVector
& other
, UTokenAssigner
*assign
, UErrorCode
&ec
) {
95 if (ensureCapacity(other
.count
, ec
)) {
97 for (int32_t i
=0; i
<other
.count
; ++i
) {
98 if (elements
[i
].pointer
!= 0 && deleter
!= 0) {
99 (*deleter
)(elements
[i
].pointer
);
101 (*assign
)(&elements
[i
], &other
.elements
[i
]);
106 // This only does something sensible if this object has a non-null comparer
107 UBool
UVector::operator==(const UVector
& other
) {
109 if (count
!= other
.count
) return FALSE
;
110 if (comparer
!= NULL
) {
111 // Compare using this object's comparer
112 for (i
=0; i
<count
; ++i
) {
113 if (!(*comparer
)(elements
[i
], other
.elements
[i
])) {
121 void UVector::addElement(void* obj
, UErrorCode
&status
) {
122 if (ensureCapacity(count
+ 1, status
)) {
123 elements
[count
++].pointer
= obj
;
127 void UVector::addElement(int32_t elem
, UErrorCode
&status
) {
128 if (ensureCapacity(count
+ 1, status
)) {
129 elements
[count
].pointer
= NULL
; // Pointers may be bigger than ints.
130 elements
[count
].integer
= elem
;
135 void UVector::setElementAt(void* obj
, int32_t index
) {
136 if (0 <= index
&& index
< count
) {
137 if (elements
[index
].pointer
!= 0 && deleter
!= 0) {
138 (*deleter
)(elements
[index
].pointer
);
140 elements
[index
].pointer
= obj
;
142 /* else index out of range */
145 void UVector::setElementAt(int32_t elem
, int32_t index
) {
146 if (0 <= index
&& index
< count
) {
147 if (elements
[index
].pointer
!= 0 && deleter
!= 0) {
148 // TODO: this should be an error. mixing up ints and pointers.
149 (*deleter
)(elements
[index
].pointer
);
151 elements
[index
].pointer
= NULL
;
152 elements
[index
].integer
= elem
;
154 /* else index out of range */
157 void UVector::insertElementAt(void* obj
, int32_t index
, UErrorCode
&status
) {
158 // must have 0 <= index <= count
159 if (0 <= index
&& index
<= count
&& ensureCapacity(count
+ 1, status
)) {
160 for (int32_t i
=count
; i
>index
; --i
) {
161 elements
[i
] = elements
[i
-1];
163 elements
[index
].pointer
= obj
;
166 /* else index out of range */
169 void UVector::insertElementAt(int32_t elem
, int32_t index
, UErrorCode
&status
) {
170 // must have 0 <= index <= count
171 if (0 <= index
&& index
<= count
&& ensureCapacity(count
+ 1, status
)) {
172 for (int32_t i
=count
; i
>index
; --i
) {
173 elements
[i
] = elements
[i
-1];
175 elements
[index
].pointer
= NULL
;
176 elements
[index
].integer
= elem
;
179 /* else index out of range */
182 void* UVector::elementAt(int32_t index
) const {
183 return (0 <= index
&& index
< count
) ? elements
[index
].pointer
: 0;
186 int32_t UVector::elementAti(int32_t index
) const {
187 return (0 <= index
&& index
< count
) ? elements
[index
].integer
: 0;
190 UBool
UVector::containsAll(const UVector
& other
) const {
191 for (int32_t i
=0; i
<other
.size(); ++i
) {
192 if (indexOf(other
.elements
[i
]) < 0) {
199 UBool
UVector::containsNone(const UVector
& other
) const {
200 for (int32_t i
=0; i
<other
.size(); ++i
) {
201 if (indexOf(other
.elements
[i
]) >= 0) {
208 UBool
UVector::removeAll(const UVector
& other
) {
209 UBool changed
= FALSE
;
210 for (int32_t i
=0; i
<other
.size(); ++i
) {
211 int32_t j
= indexOf(other
.elements
[i
]);
220 UBool
UVector::retainAll(const UVector
& other
) {
221 UBool changed
= FALSE
;
222 for (int32_t j
=size()-1; j
>=0; --j
) {
223 int32_t i
= other
.indexOf(elements
[j
]);
232 void UVector::removeElementAt(int32_t index
) {
233 void* e
= orphanElementAt(index
);
234 if (e
!= 0 && deleter
!= 0) {
239 UBool
UVector::removeElement(void* obj
) {
240 int32_t i
= indexOf(obj
);
248 void UVector::removeAllElements(void) {
250 for (int32_t i
=0; i
<count
; ++i
) {
251 if (elements
[i
].pointer
!= 0) {
252 (*deleter
)(elements
[i
].pointer
);
259 UBool
UVector::equals(const UVector
&other
) const {
262 if (this->count
!= other
.count
) {
266 for (i
=0; i
<count
; i
++) {
267 if (elements
[i
].pointer
!= other
.elements
[i
].pointer
) {
273 for (i
=0; i
<count
; i
++) {
274 key
.pointer
= &other
.elements
[i
];
275 if (!(*comparer
)(key
, elements
[i
])) {
285 int32_t UVector::indexOf(void* obj
, int32_t startIndex
) const {
288 return indexOf(key
, startIndex
, HINT_KEY_POINTER
);
291 int32_t UVector::indexOf(int32_t obj
, int32_t startIndex
) const {
294 return indexOf(key
, startIndex
, HINT_KEY_INTEGER
);
297 // This only works if this object has a non-null comparer
298 int32_t UVector::indexOf(UHashTok key
, int32_t startIndex
, int8_t hint
) const {
301 for (i
=startIndex
; i
<count
; ++i
) {
302 if ((*comparer
)(key
, elements
[i
])) {
307 for (i
=startIndex
; i
<count
; ++i
) {
308 /* Pointers are not always the same size as ints so to perform
309 * a valid comparision we need to know whether we are being
310 * provided an int or a pointer. */
311 if (hint
& HINT_KEY_POINTER
) {
312 if (key
.pointer
== elements
[i
].pointer
) {
316 if (key
.integer
== elements
[i
].integer
) {
325 UBool
UVector::ensureCapacity(int32_t minimumCapacity
, UErrorCode
&status
) {
326 if (capacity
>= minimumCapacity
) {
329 int32_t newCap
= capacity
* 2;
330 if (newCap
< minimumCapacity
) {
331 newCap
= minimumCapacity
;
333 UHashTok
* newElems
= (UHashTok
*)uprv_malloc(sizeof(UHashTok
)*newCap
);
335 status
= U_MEMORY_ALLOCATION_ERROR
;
338 uprv_memcpy(newElems
, elements
, sizeof(elements
[0]) * count
);
347 * Change the size of this vector as follows: If newSize is smaller,
348 * then truncate the array, possibly deleting held elements for i >=
349 * newSize. If newSize is larger, grow the array, filling in new
352 void UVector::setSize(int32_t newSize
) {
357 if (newSize
> count
) {
358 UErrorCode ec
= U_ZERO_ERROR
;
359 if (!ensureCapacity(newSize
, ec
)) {
363 empty
.pointer
= NULL
;
365 for (i
=count
; i
<newSize
; ++i
) {
369 /* Most efficient to count down */
370 for (i
=count
-1; i
>=newSize
; --i
) {
378 * Fill in the given array with all elements of this vector.
380 void** UVector::toArray(void** result
) const {
382 for (int i
=0; i
<count
; ++i
) {
383 *a
++ = elements
[i
].pointer
;
388 UObjectDeleter
*UVector::setDeleter(UObjectDeleter
*d
) {
389 UObjectDeleter
*old
= deleter
;
394 UKeyComparator
*UVector::setComparer(UKeyComparator
*d
) {
395 UKeyComparator
*old
= comparer
;
401 * Removes the element at the given index from this vector and
402 * transfer ownership of it to the caller. After this call, the
403 * caller owns the result and must delete it and the vector entry
404 * at 'index' is removed, shifting all subsequent entries back by
405 * one index and shortening the size of the vector by one. If the
406 * index is out of range or if there is no item at the given index
407 * then 0 is returned and the vector is unchanged.
409 void* UVector::orphanElementAt(int32_t index
) {
411 if (0 <= index
&& index
< count
) {
412 e
= elements
[index
].pointer
;
413 for (int32_t i
=index
; i
<count
-1; ++i
) {
414 elements
[i
] = elements
[i
+1];
418 /* else index out of range */
423 * Insert the given object into this vector at its sorted position
424 * as defined by 'compare'. The current elements are assumed to
427 void UVector::sortedInsert(void* obj
, USortComparator
*compare
, UErrorCode
& ec
) {
430 sortedInsert(tok
, compare
, ec
);
434 * Insert the given integer into this vector at its sorted position
435 * as defined by 'compare'. The current elements are assumed to
438 void UVector::sortedInsert(int32_t obj
, USortComparator
*compare
, UErrorCode
& ec
) {
441 sortedInsert(tok
, compare
, ec
);
444 // ASSUME elements[] IS CURRENTLY SORTED
445 void UVector::sortedInsert(UHashTok tok
, USortComparator
*compare
, UErrorCode
& ec
) {
446 // Perform a binary search for the location to insert tok at. Tok
447 // will be inserted between two elements a and b such that a <=
448 // tok && tok < b, where there is a 'virtual' elements[-1] always
449 // less than tok and a 'virtual' elements[count] always greater
451 int32_t min
= 0, max
= count
;
453 int32_t probe
= (min
+ max
) / 2;
454 int8_t c
= (*compare
)(elements
[probe
], tok
);
462 if (ensureCapacity(count
+ 1, ec
)) {
463 for (int32_t i
=count
; i
>min
; --i
) {
464 elements
[i
] = elements
[i
-1];
471 UStack::UStack(UErrorCode
&status
) :
476 UStack::UStack(int32_t initialCapacity
, UErrorCode
&status
) :
477 UVector(initialCapacity
, status
)
481 UStack::UStack(UObjectDeleter
*d
, UKeyComparator
*c
, UErrorCode
&status
) :
482 UVector(d
, c
, status
)
486 UStack::UStack(UObjectDeleter
*d
, UKeyComparator
*c
, int32_t initialCapacity
, UErrorCode
&status
) :
487 UVector(d
, c
, initialCapacity
, status
)
493 void* UStack::pop(void) {
494 int32_t n
= size() - 1;
497 result
= elementAt(n
);
503 int32_t UStack::popi(void) {
504 int32_t n
= size() - 1;
507 result
= elementAti(n
);
513 int32_t UStack::search(void* obj
) const {
514 int32_t i
= indexOf(obj
);
515 return (i
>= 0) ? size() - i
: i
;