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 | |
30 | UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector) |
31 | |
32 | UVector::UVector(UErrorCode &status) : |
33 | UVector(nullptr, nullptr, DEFAULT_CAPACITY, status) { |
34 | } |
35 | |
36 | UVector::UVector(int32_t initialCapacity, UErrorCode &status) : |
37 | UVector(nullptr, nullptr, initialCapacity, status) { |
38 | } |
39 | |
40 | UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status) : |
41 | UVector(d, c, DEFAULT_CAPACITY, status) { |
42 | } |
43 | |
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 | |
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 | */ |
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 |
88 | 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 | 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 | |
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 | } |
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 | |
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 | |
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 | |
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 | |
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 | |
185 | void* UVector::elementAt(int32_t index) const { |
186 | return (0 <= index && index < count) ? elements[index].pointer : 0; |
187 | } |
188 | |
189 | int32_t UVector::elementAti(int32_t index) const { |
190 | return (0 <= index && index < count) ? elements[index].integer : 0; |
191 | } |
192 | |
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) { |
196 | return false; |
197 | } |
198 | } |
199 | return true; |
200 | } |
201 | |
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) { |
205 | return false; |
206 | } |
207 | } |
208 | return true; |
209 | } |
210 | |
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 | |
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 | |
235 | void UVector::removeElementAt(int32_t index) { |
236 | void* e = orphanElementAt(index); |
237 | if (e != nullptr && deleter != nullptr) { |
238 | (*deleter)(e); |
239 | } |
240 | } |
241 | |
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 | |
251 | void UVector::removeAllElements() { |
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 | |
262 | 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 | |
288 | 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 | |
294 | 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 | |
300 | 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 | |
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 | */ |
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 | */ |
389 | 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 | |
397 | UObjectDeleter *UVector::setDeleter(UObjectDeleter *d) { |
398 | UObjectDeleter *old = deleter; |
399 | deleter = d; |
400 | return old; |
401 | } |
402 | |
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 | */ |
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 | */ |
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 | */ |
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 |
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 |
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 |
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 | */ |
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 | */ |
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 | */ |
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 | |