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
addElement(void * obj,UErrorCode & status)102 void UVector::addElement(void* obj, UErrorCode &status) {
103 U_ASSERT(deleter == nullptr);
104 if (ensureCapacity(count + 1, status)) {
105 elements[count++].pointer = obj;
106 }
107 }
108
adoptElement(void * obj,UErrorCode & status)109 void UVector::adoptElement(void* obj, UErrorCode &status) {
110 U_ASSERT(deleter != nullptr);
111 if (ensureCapacity(count + 1, status)) {
112 elements[count++].pointer = obj;
113 } else {
114 (*deleter)(obj);
115 }
116 }
addElement(int32_t elem,UErrorCode & status)117 void UVector::addElement(int32_t elem, UErrorCode &status) {
118 U_ASSERT(deleter == nullptr); // Usage error. Mixing up ints and pointers.
119 if (ensureCapacity(count + 1, status)) {
120 elements[count].pointer = nullptr; // Pointers may be bigger than ints.
121 elements[count].integer = elem;
122 count++;
123 }
124 }
125
setElementAt(void * obj,int32_t index)126 void UVector::setElementAt(void* obj, int32_t index) {
127 if (0 <= index && index < count) {
128 if (elements[index].pointer != nullptr && deleter != nullptr) {
129 (*deleter)(elements[index].pointer);
130 }
131 elements[index].pointer = obj;
132 } else {
133 /* index out of range */
134 if (deleter != nullptr) {
135 (*deleter)(obj);
136 }
137 }
138 }
139
setElementAt(int32_t elem,int32_t index)140 void UVector::setElementAt(int32_t elem, int32_t index) {
141 U_ASSERT(deleter == nullptr); // Usage error. Mixing up ints and pointers.
142 if (0 <= index && index < count) {
143 elements[index].pointer = nullptr;
144 elements[index].integer = elem;
145 }
146 /* else index out of range */
147 }
148
insertElementAt(void * obj,int32_t index,UErrorCode & status)149 void UVector::insertElementAt(void* obj, int32_t index, UErrorCode &status) {
150 if (ensureCapacity(count + 1, status)) {
151 if (0 <= index && index <= count) {
152 for (int32_t i=count; i>index; --i) {
153 elements[i] = elements[i-1];
154 }
155 elements[index].pointer = obj;
156 ++count;
157 } else {
158 /* index out of range */
159 status = U_ILLEGAL_ARGUMENT_ERROR;
160 }
161 }
162 if (U_FAILURE(status) && deleter != nullptr) {
163 (*deleter)(obj);
164 }
165 }
166
insertElementAt(int32_t elem,int32_t index,UErrorCode & status)167 void UVector::insertElementAt(int32_t elem, int32_t index, UErrorCode &status) {
168 U_ASSERT(deleter == nullptr); // Usage error. Mixing up ints and pointers.
169 // must have 0 <= index <= count
170 if (ensureCapacity(count + 1, status)) {
171 if (0 <= index && index <= count) {
172 for (int32_t i=count; i>index; --i) {
173 elements[i] = elements[i-1];
174 }
175 elements[index].pointer = nullptr;
176 elements[index].integer = elem;
177 ++count;
178 } else {
179 /* index out of range */
180 status = U_ILLEGAL_ARGUMENT_ERROR;
181 }
182 }
183 }
184
elementAt(int32_t index) const185 void* UVector::elementAt(int32_t index) const {
186 return (0 <= index && index < count) ? elements[index].pointer : 0;
187 }
188
elementAti(int32_t index) const189 int32_t UVector::elementAti(int32_t index) const {
190 return (0 <= index && index < count) ? elements[index].integer : 0;
191 }
192
containsAll(const UVector & other) const193 UBool UVector::containsAll(const UVector& other) const {
194 for (int32_t i=0; i<other.size(); ++i) {
195 if (indexOf(other.elements[i]) < 0) {
196 return false;
197 }
198 }
199 return true;
200 }
201
containsNone(const UVector & other) const202 UBool UVector::containsNone(const UVector& other) const {
203 for (int32_t i=0; i<other.size(); ++i) {
204 if (indexOf(other.elements[i]) >= 0) {
205 return false;
206 }
207 }
208 return true;
209 }
210
removeAll(const UVector & other)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]);
215 if (j >= 0) {
216 removeElementAt(j);
217 changed = true;
218 }
219 }
220 return changed;
221 }
222
retainAll(const UVector & other)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]);
227 if (i < 0) {
228 removeElementAt(j);
229 changed = true;
230 }
231 }
232 return changed;
233 }
234
removeElementAt(int32_t index)235 void UVector::removeElementAt(int32_t index) {
236 void* e = orphanElementAt(index);
237 if (e != nullptr && deleter != nullptr) {
238 (*deleter)(e);
239 }
240 }
241
removeElement(void * obj)242 UBool UVector::removeElement(void* obj) {
243 int32_t i = indexOf(obj);
244 if (i >= 0) {
245 removeElementAt(i);
246 return true;
247 }
248 return false;
249 }
250
removeAllElements(void)251 void UVector::removeAllElements(void) {
252 if (deleter != nullptr) {
253 for (int32_t i=0; i<count; ++i) {
254 if (elements[i].pointer != nullptr) {
255 (*deleter)(elements[i].pointer);
256 }
257 }
258 }
259 count = 0;
260 }
261
equals(const UVector & other) const262 UBool UVector::equals(const UVector &other) const {
263 int i;
264
265 if (this->count != other.count) {
266 return false;
267 }
268 if (comparer == nullptr) {
269 for (i=0; i<count; i++) {
270 if (elements[i].pointer != other.elements[i].pointer) {
271 return false;
272 }
273 }
274 } else {
275 UElement key;
276 for (i=0; i<count; i++) {
277 key.pointer = &other.elements[i];
278 if (!(*comparer)(key, elements[i])) {
279 return false;
280 }
281 }
282 }
283 return true;
284 }
285
286
287
indexOf(void * obj,int32_t startIndex) const288 int32_t UVector::indexOf(void* obj, int32_t startIndex) const {
289 UElement key;
290 key.pointer = obj;
291 return indexOf(key, startIndex, HINT_KEY_POINTER);
292 }
293
indexOf(int32_t obj,int32_t startIndex) const294 int32_t UVector::indexOf(int32_t obj, int32_t startIndex) const {
295 UElement key;
296 key.integer = obj;
297 return indexOf(key, startIndex, HINT_KEY_INTEGER);
298 }
299
indexOf(UElement key,int32_t startIndex,int8_t hint) const300 int32_t UVector::indexOf(UElement key, int32_t startIndex, int8_t hint) const {
301 if (comparer != nullptr) {
302 for (int32_t i=startIndex; i<count; ++i) {
303 if ((*comparer)(key, elements[i])) {
304 return i;
305 }
306 }
307 } else {
308 for (int32_t i=startIndex; i<count; ++i) {
309 /* Pointers are not always the same size as ints so to perform
310 * a valid comparison we need to know whether we are being
311 * provided an int or a pointer. */
312 if (hint & HINT_KEY_POINTER) {
313 if (key.pointer == elements[i].pointer) {
314 return i;
315 }
316 } else {
317 if (key.integer == elements[i].integer) {
318 return i;
319 }
320 }
321 }
322 }
323 return -1;
324 }
325
ensureCapacity(int32_t minimumCapacity,UErrorCode & status)326 UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) {
327 if (U_FAILURE(status)) {
328 return false;
329 }
330 if (minimumCapacity < 0) {
331 status = U_ILLEGAL_ARGUMENT_ERROR;
332 return false;
333 }
334 if (capacity < minimumCapacity) {
335 if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check
336 status = U_ILLEGAL_ARGUMENT_ERROR;
337 return false;
338 }
339 int32_t newCap = capacity * 2;
340 if (newCap < minimumCapacity) {
341 newCap = minimumCapacity;
342 }
343 if (newCap > (int32_t)(INT32_MAX / sizeof(UElement))) { // integer overflow check
344 // We keep the original memory contents on bad minimumCapacity.
345 status = U_ILLEGAL_ARGUMENT_ERROR;
346 return false;
347 }
348 UElement* newElems = (UElement *)uprv_realloc(elements, sizeof(UElement)*newCap);
349 if (newElems == nullptr) {
350 // We keep the original contents on the memory failure on realloc or bad minimumCapacity.
351 status = U_MEMORY_ALLOCATION_ERROR;
352 return false;
353 }
354 elements = newElems;
355 capacity = newCap;
356 }
357 return true;
358 }
359
360 /**
361 * Change the size of this vector as follows: If newSize is smaller,
362 * then truncate the array, possibly deleting held elements for i >=
363 * newSize. If newSize is larger, grow the array, filling in new
364 * slots with nullptr.
365 */
setSize(int32_t newSize,UErrorCode & status)366 void UVector::setSize(int32_t newSize, UErrorCode &status) {
367 if (!ensureCapacity(newSize, status)) {
368 return;
369 }
370 if (newSize > count) {
371 UElement empty;
372 empty.pointer = nullptr;
373 empty.integer = 0;
374 for (int32_t i=count; i<newSize; ++i) {
375 elements[i] = empty;
376 }
377 } else {
378 /* Most efficient to count down */
379 for (int32_t i=count-1; i>=newSize; --i) {
380 removeElementAt(i);
381 }
382 }
383 count = newSize;
384 }
385
386 /**
387 * Fill in the given array with all elements of this vector.
388 */
toArray(void ** result) const389 void** UVector::toArray(void** result) const {
390 void** a = result;
391 for (int i=0; i<count; ++i) {
392 *a++ = elements[i].pointer;
393 }
394 return result;
395 }
396
setDeleter(UObjectDeleter * d)397 UObjectDeleter *UVector::setDeleter(UObjectDeleter *d) {
398 UObjectDeleter *old = deleter;
399 deleter = d;
400 return old;
401 }
402
setComparer(UElementsAreEqual * d)403 UElementsAreEqual *UVector::setComparer(UElementsAreEqual *d) {
404 UElementsAreEqual *old = comparer;
405 comparer = d;
406 return old;
407 }
408
409 /**
410 * Removes the element at the given index from this vector and
411 * transfer ownership of it to the caller. After this call, the
412 * caller owns the result and must delete it and the vector entry
413 * at 'index' is removed, shifting all subsequent entries back by
414 * one index and shortening the size of the vector by one. If the
415 * index is out of range or if there is no item at the given index
416 * then 0 is returned and the vector is unchanged.
417 */
orphanElementAt(int32_t index)418 void* UVector::orphanElementAt(int32_t index) {
419 void* e = nullptr;
420 if (0 <= index && index < count) {
421 e = elements[index].pointer;
422 for (int32_t i=index; i<count-1; ++i) {
423 elements[i] = elements[i+1];
424 }
425 --count;
426 }
427 /* else index out of range */
428 return e;
429 }
430
431 /**
432 * Insert the given object into this vector at its sorted position
433 * as defined by 'compare'. The current elements are assumed to
434 * be sorted already.
435 */
sortedInsert(void * obj,UElementComparator * compare,UErrorCode & ec)436 void UVector::sortedInsert(void* obj, UElementComparator *compare, UErrorCode& ec) {
437 UElement e;
438 e.pointer = obj;
439 sortedInsert(e, compare, ec);
440 }
441
442 /**
443 * Insert the given integer into this vector at its sorted position
444 * as defined by 'compare'. The current elements are assumed to
445 * be sorted already.
446 */
sortedInsert(int32_t obj,UElementComparator * compare,UErrorCode & ec)447 void UVector::sortedInsert(int32_t obj, UElementComparator *compare, UErrorCode& ec) {
448 U_ASSERT(deleter == nullptr);
449 UElement e {};
450 e.integer = obj;
451 sortedInsert(e, compare, ec);
452 }
453
454 // ASSUME elements[] IS CURRENTLY SORTED
sortedInsert(UElement e,UElementComparator * compare,UErrorCode & ec)455 void UVector::sortedInsert(UElement e, UElementComparator *compare, UErrorCode& ec) {
456 // Perform a binary search for the location to insert tok at. Tok
457 // will be inserted between two elements a and b such that a <=
458 // tok && tok < b, where there is a 'virtual' elements[-1] always
459 // less than tok and a 'virtual' elements[count] always greater
460 // than tok.
461 if (!ensureCapacity(count + 1, ec)) {
462 if (deleter != nullptr) {
463 (*deleter)(e.pointer);
464 }
465 return;
466 }
467 int32_t min = 0, max = count;
468 while (min != max) {
469 int32_t probe = (min + max) / 2;
470 int32_t c = (*compare)(elements[probe], e);
471 if (c > 0) {
472 max = probe;
473 } else {
474 // assert(c <= 0);
475 min = probe + 1;
476 }
477 }
478 for (int32_t i=count; i>min; --i) {
479 elements[i] = elements[i-1];
480 }
481 elements[min] = e;
482 ++count;
483 }
484
485 /**
486 * Array sort comparator function.
487 * Used from UVector::sort()
488 * Conforms to function signature required for uprv_sortArray().
489 * This function is essentially just a wrapper, to make a
490 * UVector style comparator function usable with uprv_sortArray().
491 *
492 * The context pointer to this function is a pointer back
493 * (with some extra indirection) to the user supplied comparator.
494 *
495 */
496 static int32_t U_CALLCONV
sortComparator(const void * context,const void * left,const void * right)497 sortComparator(const void *context, const void *left, const void *right) {
498 UElementComparator *compare = *static_cast<UElementComparator * const *>(context);
499 UElement e1 = *static_cast<const UElement *>(left);
500 UElement e2 = *static_cast<const UElement *>(right);
501 int32_t result = (*compare)(e1, e2);
502 return result;
503 }
504
505
506 /**
507 * Array sort comparison function for use from UVector::sorti()
508 * Compares int32_t vector elements.
509 */
510 static int32_t U_CALLCONV
sortiComparator(const void *,const void * left,const void * right)511 sortiComparator(const void * /*context */, const void *left, const void *right) {
512 const UElement *e1 = static_cast<const UElement *>(left);
513 const UElement *e2 = static_cast<const UElement *>(right);
514 int32_t result = e1->integer < e2->integer? -1 :
515 e1->integer == e2->integer? 0 : 1;
516 return result;
517 }
518
519 /**
520 * Sort the vector, assuming it contains ints.
521 * (A more general sort would take a comparison function, but it's
522 * not clear whether UVector's UElementComparator or
523 * UComparator from uprv_sortAray would be more appropriate.)
524 */
sorti(UErrorCode & ec)525 void UVector::sorti(UErrorCode &ec) {
526 if (U_SUCCESS(ec)) {
527 uprv_sortArray(elements, count, sizeof(UElement),
528 sortiComparator, nullptr, false, &ec);
529 }
530 }
531
532
533 /**
534 * Sort with a user supplied comparator.
535 *
536 * The comparator function handling is confusing because the function type
537 * for UVector (as defined for sortedInsert()) is different from the signature
538 * required by uprv_sortArray(). This is handled by passing the
539 * the UVector sort function pointer via the context pointer to a
540 * sortArray() comparator function, which can then call back to
541 * the original user function.
542 *
543 * An additional twist is that it's not safe to pass a pointer-to-function
544 * as a (void *) data pointer, so instead we pass a (data) pointer to a
545 * pointer-to-function variable.
546 */
sort(UElementComparator * compare,UErrorCode & ec)547 void UVector::sort(UElementComparator *compare, UErrorCode &ec) {
548 if (U_SUCCESS(ec)) {
549 uprv_sortArray(elements, count, sizeof(UElement),
550 sortComparator, &compare, false, &ec);
551 }
552 }
553
554
555 /**
556 * Stable sort with a user supplied comparator of type UComparator.
557 */
sortWithUComparator(UComparator * compare,const void * context,UErrorCode & ec)558 void UVector::sortWithUComparator(UComparator *compare, const void *context, UErrorCode &ec) {
559 if (U_SUCCESS(ec)) {
560 uprv_sortArray(elements, count, sizeof(UElement),
561 compare, context, true, &ec);
562 }
563 }
564
565 U_NAMESPACE_END
566
567