1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ******************************************************************************
5 * Copyright (C) 1999-2013, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ******************************************************************************
8 * Date Name Description
9 * 10/22/99 alan Creation.
10 **********************************************************************
11 */
12
13 #include "uvector.h"
14 #include "cmemory.h"
15 #include "uarrsort.h"
16 #include "uelement.h"
17
18 U_NAMESPACE_BEGIN
19
20 constexpr int32_t DEFAULT_CAPACITY = 8;
21
22 /*
23 * Constants for hinting whether a key is an integer
24 * or a pointer. If a hint bit is zero, then the associated
25 * token is assumed to be an integer. This is needed for iSeries
26 */
27 constexpr int8_t HINT_KEY_POINTER = 1;
28 constexpr int8_t HINT_KEY_INTEGER = 0;
29
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector)30 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector)
31
32 UVector::UVector(UErrorCode &status) :
33 UVector(nullptr, nullptr, DEFAULT_CAPACITY, status) {
34 }
35
UVector(int32_t initialCapacity,UErrorCode & status)36 UVector::UVector(int32_t initialCapacity, UErrorCode &status) :
37 UVector(nullptr, nullptr, initialCapacity, status) {
38 }
39
UVector(UObjectDeleter * d,UElementsAreEqual * c,UErrorCode & status)40 UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status) :
41 UVector(d, c, DEFAULT_CAPACITY, status) {
42 }
43
UVector(UObjectDeleter * d,UElementsAreEqual * c,int32_t initialCapacity,UErrorCode & status)44 UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status) :
45 deleter(d),
46 comparer(c)
47 {
48 if (U_FAILURE(status)) {
49 return;
50 }
51 // Fix bogus initialCapacity values; avoid malloc(0) and integer overflow
52 if ((initialCapacity < 1) || (initialCapacity > (int32_t)(INT32_MAX / sizeof(UElement)))) {
53 initialCapacity = DEFAULT_CAPACITY;
54 }
55 elements = (UElement *)uprv_malloc(sizeof(UElement)*initialCapacity);
56 if (elements == nullptr) {
57 status = U_MEMORY_ALLOCATION_ERROR;
58 } else {
59 capacity = initialCapacity;
60 }
61 }
62
~UVector()63 UVector::~UVector() {
64 removeAllElements();
65 uprv_free(elements);
66 elements = nullptr;
67 }
68
69 /**
70 * Assign this object to another (make this a copy of 'other').
71 * Use the 'assign' function to assign each element.
72 */
assign(const UVector & other,UElementAssigner * assign,UErrorCode & ec)73 void UVector::assign(const UVector& other, UElementAssigner *assign, UErrorCode &ec) {
74 if (ensureCapacity(other.count, ec)) {
75 setSize(other.count, ec);
76 if (U_SUCCESS(ec)) {
77 for (int32_t i=0; i<other.count; ++i) {
78 if (elements[i].pointer != nullptr && deleter != nullptr) {
79 (*deleter)(elements[i].pointer);
80 }
81 (*assign)(&elements[i], &other.elements[i]);
82 }
83 }
84 }
85 }
86
87 // This only does something sensible if this object has a non-null comparer
operator ==(const UVector & other) const88 bool UVector::operator==(const UVector& other) const {
89 U_ASSERT(comparer != nullptr);
90 if (count != other.count) return false;
91 if (comparer != nullptr) {
92 // Compare using this object's comparer
93 for (int32_t i=0; i<count; ++i) {
94 if (!(*comparer)(elements[i], other.elements[i])) {
95 return false;
96 }
97 }
98 }
99 return true;
100 }
101
102 // TODO: delete this function once all call sites have been migrated to the
103 // new addElement().
addElementX(void * obj,UErrorCode & status)104 void UVector::addElementX(void* obj, UErrorCode &status) {
105 if (ensureCapacityX(count + 1, status)) {
106 elements[count++].pointer = obj;
107 }
108 }
109
addElement(void * obj,UErrorCode & status)110 void UVector::addElement(void* obj, UErrorCode &status) {
111 U_ASSERT(deleter == nullptr);
112 if (ensureCapacity(count + 1, status)) {
113 elements[count++].pointer = obj;
114 }
115 }
116
adoptElement(void * obj,UErrorCode & status)117 void UVector::adoptElement(void* obj, UErrorCode &status) {
118 U_ASSERT(deleter != nullptr);
119 if (ensureCapacity(count + 1, status)) {
120 elements[count++].pointer = obj;
121 } else {
122 (*deleter)(obj);
123 }
124 }
addElement(int32_t elem,UErrorCode & status)125 void UVector::addElement(int32_t elem, UErrorCode &status) {
126 U_ASSERT(deleter == nullptr); // Usage error. Mixing up ints and pointers.
127 if (ensureCapacity(count + 1, status)) {
128 elements[count].pointer = nullptr; // Pointers may be bigger than ints.
129 elements[count].integer = elem;
130 count++;
131 }
132 }
133
setElementAt(void * obj,int32_t index)134 void UVector::setElementAt(void* obj, int32_t index) {
135 if (0 <= index && index < count) {
136 if (elements[index].pointer != nullptr && deleter != nullptr) {
137 (*deleter)(elements[index].pointer);
138 }
139 elements[index].pointer = obj;
140 } else {
141 /* index out of range */
142 if (deleter != nullptr) {
143 (*deleter)(obj);
144 }
145 }
146 }
147
setElementAt(int32_t elem,int32_t index)148 void UVector::setElementAt(int32_t elem, int32_t index) {
149 U_ASSERT(deleter == nullptr); // Usage error. Mixing up ints and pointers.
150 if (0 <= index && index < count) {
151 elements[index].pointer = nullptr;
152 elements[index].integer = elem;
153 }
154 /* else index out of range */
155 }
156
insertElementAt(void * obj,int32_t index,UErrorCode & status)157 void UVector::insertElementAt(void* obj, int32_t index, UErrorCode &status) {
158 if (ensureCapacity(count + 1, status)) {
159 if (0 <= index && index <= count) {
160 for (int32_t i=count; i>index; --i) {
161 elements[i] = elements[i-1];
162 }
163 elements[index].pointer = obj;
164 ++count;
165 } else {
166 /* index out of range */
167 status = U_ILLEGAL_ARGUMENT_ERROR;
168 }
169 }
170 if (U_FAILURE(status) && deleter != nullptr) {
171 (*deleter)(obj);
172 }
173 }
174
insertElementAt(int32_t elem,int32_t index,UErrorCode & status)175 void UVector::insertElementAt(int32_t elem, int32_t index, UErrorCode &status) {
176 U_ASSERT(deleter == nullptr); // Usage error. Mixing up ints and pointers.
177 // must have 0 <= index <= count
178 if (ensureCapacity(count + 1, status)) {
179 if (0 <= index && index <= count) {
180 for (int32_t i=count; i>index; --i) {
181 elements[i] = elements[i-1];
182 }
183 elements[index].pointer = nullptr;
184 elements[index].integer = elem;
185 ++count;
186 } else {
187 /* index out of range */
188 status = U_ILLEGAL_ARGUMENT_ERROR;
189 }
190 }
191 }
192
elementAt(int32_t index) const193 void* UVector::elementAt(int32_t index) const {
194 return (0 <= index && index < count) ? elements[index].pointer : 0;
195 }
196
elementAti(int32_t index) const197 int32_t UVector::elementAti(int32_t index) const {
198 return (0 <= index && index < count) ? elements[index].integer : 0;
199 }
200
containsAll(const UVector & other) const201 UBool UVector::containsAll(const UVector& other) const {
202 for (int32_t i=0; i<other.size(); ++i) {
203 if (indexOf(other.elements[i]) < 0) {
204 return FALSE;
205 }
206 }
207 return TRUE;
208 }
209
containsNone(const UVector & other) const210 UBool UVector::containsNone(const UVector& other) const {
211 for (int32_t i=0; i<other.size(); ++i) {
212 if (indexOf(other.elements[i]) >= 0) {
213 return FALSE;
214 }
215 }
216 return TRUE;
217 }
218
removeAll(const UVector & other)219 UBool UVector::removeAll(const UVector& other) {
220 UBool changed = FALSE;
221 for (int32_t i=0; i<other.size(); ++i) {
222 int32_t j = indexOf(other.elements[i]);
223 if (j >= 0) {
224 removeElementAt(j);
225 changed = TRUE;
226 }
227 }
228 return changed;
229 }
230
retainAll(const UVector & other)231 UBool UVector::retainAll(const UVector& other) {
232 UBool changed = FALSE;
233 for (int32_t j=size()-1; j>=0; --j) {
234 int32_t i = other.indexOf(elements[j]);
235 if (i < 0) {
236 removeElementAt(j);
237 changed = TRUE;
238 }
239 }
240 return changed;
241 }
242
removeElementAt(int32_t index)243 void UVector::removeElementAt(int32_t index) {
244 void* e = orphanElementAt(index);
245 if (e != nullptr && deleter != nullptr) {
246 (*deleter)(e);
247 }
248 }
249
removeElement(void * obj)250 UBool UVector::removeElement(void* obj) {
251 int32_t i = indexOf(obj);
252 if (i >= 0) {
253 removeElementAt(i);
254 return TRUE;
255 }
256 return FALSE;
257 }
258
removeAllElements(void)259 void UVector::removeAllElements(void) {
260 if (deleter != nullptr) {
261 for (int32_t i=0; i<count; ++i) {
262 if (elements[i].pointer != nullptr) {
263 (*deleter)(elements[i].pointer);
264 }
265 }
266 }
267 count = 0;
268 }
269
equals(const UVector & other) const270 UBool UVector::equals(const UVector &other) const {
271 int i;
272
273 if (this->count != other.count) {
274 return FALSE;
275 }
276 if (comparer == nullptr) {
277 for (i=0; i<count; i++) {
278 if (elements[i].pointer != other.elements[i].pointer) {
279 return FALSE;
280 }
281 }
282 } else {
283 UElement key;
284 for (i=0; i<count; i++) {
285 key.pointer = &other.elements[i];
286 if (!(*comparer)(key, elements[i])) {
287 return FALSE;
288 }
289 }
290 }
291 return TRUE;
292 }
293
294
295
indexOf(void * obj,int32_t startIndex) const296 int32_t UVector::indexOf(void* obj, int32_t startIndex) const {
297 UElement key;
298 key.pointer = obj;
299 return indexOf(key, startIndex, HINT_KEY_POINTER);
300 }
301
indexOf(int32_t obj,int32_t startIndex) const302 int32_t UVector::indexOf(int32_t obj, int32_t startIndex) const {
303 UElement key;
304 key.integer = obj;
305 return indexOf(key, startIndex, HINT_KEY_INTEGER);
306 }
307
indexOf(UElement key,int32_t startIndex,int8_t hint) const308 int32_t UVector::indexOf(UElement key, int32_t startIndex, int8_t hint) const {
309 if (comparer != nullptr) {
310 for (int32_t i=startIndex; i<count; ++i) {
311 if ((*comparer)(key, elements[i])) {
312 return i;
313 }
314 }
315 } else {
316 for (int32_t i=startIndex; i<count; ++i) {
317 /* Pointers are not always the same size as ints so to perform
318 * a valid comparison we need to know whether we are being
319 * provided an int or a pointer. */
320 if (hint & HINT_KEY_POINTER) {
321 if (key.pointer == elements[i].pointer) {
322 return i;
323 }
324 } else {
325 if (key.integer == elements[i].integer) {
326 return i;
327 }
328 }
329 }
330 }
331 return -1;
332 }
333
ensureCapacityX(int32_t minimumCapacity,UErrorCode & status)334 UBool UVector::ensureCapacityX(int32_t minimumCapacity, UErrorCode &status) {
335 if (minimumCapacity < 0) {
336 status = U_ILLEGAL_ARGUMENT_ERROR;
337 return FALSE;
338 }
339 if (capacity < minimumCapacity) {
340 if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check
341 status = U_ILLEGAL_ARGUMENT_ERROR;
342 return FALSE;
343 }
344 int32_t newCap = capacity * 2;
345 if (newCap < minimumCapacity) {
346 newCap = minimumCapacity;
347 }
348 if (newCap > (int32_t)(INT32_MAX / sizeof(UElement))) { // integer overflow check
349 // We keep the original memory contents on bad minimumCapacity.
350 status = U_ILLEGAL_ARGUMENT_ERROR;
351 return FALSE;
352 }
353 UElement* newElems = (UElement *)uprv_realloc(elements, sizeof(UElement)*newCap);
354 if (newElems == nullptr) {
355 // We keep the original contents on the memory failure on realloc or bad minimumCapacity.
356 status = U_MEMORY_ALLOCATION_ERROR;
357 return FALSE;
358 }
359 elements = newElems;
360 capacity = newCap;
361 }
362 return TRUE;
363 }
364
365
ensureCapacity(int32_t minimumCapacity,UErrorCode & status)366 UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) {
367 if (U_FAILURE(status)) {
368 return false;
369 }
370 if (minimumCapacity < 0) {
371 status = U_ILLEGAL_ARGUMENT_ERROR;
372 return false;
373 }
374 if (capacity < minimumCapacity) {
375 if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check
376 status = U_ILLEGAL_ARGUMENT_ERROR;
377 return false;
378 }
379 int32_t newCap = capacity * 2;
380 if (newCap < minimumCapacity) {
381 newCap = minimumCapacity;
382 }
383 if (newCap > (int32_t)(INT32_MAX / sizeof(UElement))) { // integer overflow check
384 // We keep the original memory contents on bad minimumCapacity.
385 status = U_ILLEGAL_ARGUMENT_ERROR;
386 return false;
387 }
388 UElement* newElems = (UElement *)uprv_realloc(elements, sizeof(UElement)*newCap);
389 if (newElems == nullptr) {
390 // We keep the original contents on the memory failure on realloc or bad minimumCapacity.
391 status = U_MEMORY_ALLOCATION_ERROR;
392 return false;
393 }
394 elements = newElems;
395 capacity = newCap;
396 }
397 return true;
398 }
399 /**
400 * Change the size of this vector as follows: If newSize is smaller,
401 * then truncate the array, possibly deleting held elements for i >=
402 * newSize. If newSize is larger, grow the array, filling in new
403 * slots with nullptr.
404 */
setSize(int32_t newSize,UErrorCode & status)405 void UVector::setSize(int32_t newSize, UErrorCode &status) {
406 if (!ensureCapacity(newSize, status)) {
407 return;
408 }
409 if (newSize > count) {
410 UElement empty;
411 empty.pointer = nullptr;
412 empty.integer = 0;
413 for (int32_t i=count; i<newSize; ++i) {
414 elements[i] = empty;
415 }
416 } else {
417 /* Most efficient to count down */
418 for (int32_t i=count-1; i>=newSize; --i) {
419 removeElementAt(i);
420 }
421 }
422 count = newSize;
423 }
424
425 /**
426 * Fill in the given array with all elements of this vector.
427 */
toArray(void ** result) const428 void** UVector::toArray(void** result) const {
429 void** a = result;
430 for (int i=0; i<count; ++i) {
431 *a++ = elements[i].pointer;
432 }
433 return result;
434 }
435
setDeleter(UObjectDeleter * d)436 UObjectDeleter *UVector::setDeleter(UObjectDeleter *d) {
437 UObjectDeleter *old = deleter;
438 deleter = d;
439 return old;
440 }
441
setComparer(UElementsAreEqual * d)442 UElementsAreEqual *UVector::setComparer(UElementsAreEqual *d) {
443 UElementsAreEqual *old = comparer;
444 comparer = d;
445 return old;
446 }
447
448 /**
449 * Removes the element at the given index from this vector and
450 * transfer ownership of it to the caller. After this call, the
451 * caller owns the result and must delete it and the vector entry
452 * at 'index' is removed, shifting all subsequent entries back by
453 * one index and shortening the size of the vector by one. If the
454 * index is out of range or if there is no item at the given index
455 * then 0 is returned and the vector is unchanged.
456 */
orphanElementAt(int32_t index)457 void* UVector::orphanElementAt(int32_t index) {
458 void* e = nullptr;
459 if (0 <= index && index < count) {
460 e = elements[index].pointer;
461 for (int32_t i=index; i<count-1; ++i) {
462 elements[i] = elements[i+1];
463 }
464 --count;
465 }
466 /* else index out of range */
467 return e;
468 }
469
470 /**
471 * Insert the given object into this vector at its sorted position
472 * as defined by 'compare'. The current elements are assumed to
473 * be sorted already.
474 */
sortedInsert(void * obj,UElementComparator * compare,UErrorCode & ec)475 void UVector::sortedInsert(void* obj, UElementComparator *compare, UErrorCode& ec) {
476 UElement e;
477 e.pointer = obj;
478 sortedInsert(e, compare, ec);
479 }
480
481 /**
482 * Insert the given integer into this vector at its sorted position
483 * as defined by 'compare'. The current elements are assumed to
484 * be sorted already.
485 */
sortedInsert(int32_t obj,UElementComparator * compare,UErrorCode & ec)486 void UVector::sortedInsert(int32_t obj, UElementComparator *compare, UErrorCode& ec) {
487 U_ASSERT(deleter == nullptr);
488 UElement e {};
489 e.integer = obj;
490 sortedInsert(e, compare, ec);
491 }
492
493 // ASSUME elements[] IS CURRENTLY SORTED
sortedInsert(UElement e,UElementComparator * compare,UErrorCode & ec)494 void UVector::sortedInsert(UElement e, UElementComparator *compare, UErrorCode& ec) {
495 // Perform a binary search for the location to insert tok at. Tok
496 // will be inserted between two elements a and b such that a <=
497 // tok && tok < b, where there is a 'virtual' elements[-1] always
498 // less than tok and a 'virtual' elements[count] always greater
499 // than tok.
500 if (!ensureCapacity(count + 1, ec)) {
501 if (deleter != nullptr) {
502 (*deleter)(e.pointer);
503 }
504 return;
505 }
506 int32_t min = 0, max = count;
507 while (min != max) {
508 int32_t probe = (min + max) / 2;
509 int32_t c = (*compare)(elements[probe], e);
510 if (c > 0) {
511 max = probe;
512 } else {
513 // assert(c <= 0);
514 min = probe + 1;
515 }
516 }
517 for (int32_t i=count; i>min; --i) {
518 elements[i] = elements[i-1];
519 }
520 elements[min] = e;
521 ++count;
522 }
523
524 /**
525 * Array sort comparator function.
526 * Used from UVector::sort()
527 * Conforms to function signature required for uprv_sortArray().
528 * This function is essentially just a wrapper, to make a
529 * UVector style comparator function usable with uprv_sortArray().
530 *
531 * The context pointer to this function is a pointer back
532 * (with some extra indirection) to the user supplied comparator.
533 *
534 */
535 static int32_t U_CALLCONV
sortComparator(const void * context,const void * left,const void * right)536 sortComparator(const void *context, const void *left, const void *right) {
537 UElementComparator *compare = *static_cast<UElementComparator * const *>(context);
538 UElement e1 = *static_cast<const UElement *>(left);
539 UElement e2 = *static_cast<const UElement *>(right);
540 int32_t result = (*compare)(e1, e2);
541 return result;
542 }
543
544
545 /**
546 * Array sort comparison function for use from UVector::sorti()
547 * Compares int32_t vector elements.
548 */
549 static int32_t U_CALLCONV
sortiComparator(const void *,const void * left,const void * right)550 sortiComparator(const void * /*context */, const void *left, const void *right) {
551 const UElement *e1 = static_cast<const UElement *>(left);
552 const UElement *e2 = static_cast<const UElement *>(right);
553 int32_t result = e1->integer < e2->integer? -1 :
554 e1->integer == e2->integer? 0 : 1;
555 return result;
556 }
557
558 /**
559 * Sort the vector, assuming it contains ints.
560 * (A more general sort would take a comparison function, but it's
561 * not clear whether UVector's UElementComparator or
562 * UComparator from uprv_sortAray would be more appropriate.)
563 */
sorti(UErrorCode & ec)564 void UVector::sorti(UErrorCode &ec) {
565 if (U_SUCCESS(ec)) {
566 uprv_sortArray(elements, count, sizeof(UElement),
567 sortiComparator, nullptr, FALSE, &ec);
568 }
569 }
570
571
572 /**
573 * Sort with a user supplied comparator.
574 *
575 * The comparator function handling is confusing because the function type
576 * for UVector (as defined for sortedInsert()) is different from the signature
577 * required by uprv_sortArray(). This is handled by passing the
578 * the UVector sort function pointer via the context pointer to a
579 * sortArray() comparator function, which can then call back to
580 * the original user function.
581 *
582 * An additional twist is that it's not safe to pass a pointer-to-function
583 * as a (void *) data pointer, so instead we pass a (data) pointer to a
584 * pointer-to-function variable.
585 */
sort(UElementComparator * compare,UErrorCode & ec)586 void UVector::sort(UElementComparator *compare, UErrorCode &ec) {
587 if (U_SUCCESS(ec)) {
588 uprv_sortArray(elements, count, sizeof(UElement),
589 sortComparator, &compare, FALSE, &ec);
590 }
591 }
592
593
594 /**
595 * Stable sort with a user supplied comparator of type UComparator.
596 */
sortWithUComparator(UComparator * compare,const void * context,UErrorCode & ec)597 void UVector::sortWithUComparator(UComparator *compare, const void *context, UErrorCode &ec) {
598 if (U_SUCCESS(ec)) {
599 uprv_sortArray(elements, count, sizeof(UElement),
600 compare, context, TRUE, &ec);
601 }
602 }
603
604 U_NAMESPACE_END
605
606