/src/icu/icu4c/source/common/uvector.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 42.9M | UVector(nullptr, nullptr, DEFAULT_CAPACITY, status) { |
34 | 42.9M | } |
35 | | |
36 | | UVector::UVector(int32_t initialCapacity, UErrorCode &status) : |
37 | 0 | UVector(nullptr, nullptr, initialCapacity, status) { |
38 | 0 | } |
39 | | |
40 | | UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status) : |
41 | 161k | UVector(d, c, DEFAULT_CAPACITY, status) { |
42 | 161k | } |
43 | | |
44 | | UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status) : |
45 | 43.2M | deleter(d), |
46 | 43.2M | comparer(c) |
47 | 43.2M | { |
48 | 43.2M | if (U_FAILURE(status)) { |
49 | 43 | return; |
50 | 43 | } |
51 | | // Fix bogus initialCapacity values; avoid malloc(0) and integer overflow |
52 | 43.2M | if ((initialCapacity < 1) || (initialCapacity > static_cast<int32_t>(INT32_MAX / sizeof(UElement)))) { |
53 | 0 | initialCapacity = DEFAULT_CAPACITY; |
54 | 0 | } |
55 | 43.2M | elements = static_cast<UElement*>(uprv_malloc(sizeof(UElement) * initialCapacity)); |
56 | 43.2M | if (elements == nullptr) { |
57 | 0 | status = U_MEMORY_ALLOCATION_ERROR; |
58 | 43.2M | } else { |
59 | 43.2M | capacity = initialCapacity; |
60 | 43.2M | } |
61 | 43.2M | } |
62 | | |
63 | 43.2M | UVector::~UVector() { |
64 | 43.2M | removeAllElements(); |
65 | 43.2M | uprv_free(elements); |
66 | 43.2M | elements = nullptr; |
67 | 43.2M | } |
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 | 90.9k | void UVector::assign(const UVector& other, UElementAssigner *assign, UErrorCode &ec) { |
74 | 90.9k | if (ensureCapacity(other.count, ec)) { |
75 | 90.9k | setSize(other.count, ec); |
76 | 90.9k | if (U_SUCCESS(ec)) { |
77 | 3.74M | for (int32_t i=0; i<other.count; ++i) { |
78 | 3.65M | if (elements[i].pointer != nullptr && deleter != nullptr) { |
79 | 279k | (*deleter)(elements[i].pointer); |
80 | 279k | } |
81 | 3.65M | (*assign)(&elements[i], &other.elements[i]); |
82 | 3.65M | } |
83 | 90.9k | } |
84 | 90.9k | } |
85 | 90.9k | } |
86 | | |
87 | | // This only does something sensible if this object has a non-null comparer |
88 | 0 | bool UVector::operator==(const UVector& other) const { |
89 | 0 | U_ASSERT(comparer != nullptr); |
90 | 0 | if (count != other.count) return false; |
91 | 0 | if (comparer != nullptr) { |
92 | | // Compare using this object's comparer |
93 | 0 | for (int32_t i=0; i<count; ++i) { |
94 | 0 | if (!(*comparer)(elements[i], other.elements[i])) { |
95 | 0 | return false; |
96 | 0 | } |
97 | 0 | } |
98 | 0 | } |
99 | 0 | return true; |
100 | 0 | } |
101 | | |
102 | 3.73M | void UVector::addElement(void* obj, UErrorCode &status) { |
103 | 3.73M | U_ASSERT(deleter == nullptr); |
104 | 3.73M | if (ensureCapacity(count + 1, status)) { |
105 | 3.73M | elements[count++].pointer = obj; |
106 | 3.73M | } |
107 | 3.73M | } |
108 | | |
109 | 15.5M | void UVector::adoptElement(void* obj, UErrorCode &status) { |
110 | 15.5M | U_ASSERT(deleter != nullptr); |
111 | 15.5M | if (ensureCapacity(count + 1, status)) { |
112 | 15.5M | elements[count++].pointer = obj; |
113 | 15.5M | } else { |
114 | 0 | (*deleter)(obj); |
115 | 0 | } |
116 | 15.5M | } |
117 | 988k | void UVector::addElement(int32_t elem, UErrorCode &status) { |
118 | 988k | U_ASSERT(deleter == nullptr); // Usage error. Mixing up ints and pointers. |
119 | 988k | if (ensureCapacity(count + 1, status)) { |
120 | 988k | elements[count].pointer = nullptr; // Pointers may be bigger than ints. |
121 | 988k | elements[count].integer = elem; |
122 | 988k | count++; |
123 | 988k | } |
124 | 988k | } |
125 | | |
126 | 869M | void UVector::setElementAt(void* obj, int32_t index) { |
127 | 869M | if (0 <= index && index < count) { |
128 | 869M | if (elements[index].pointer != nullptr && deleter != nullptr) { |
129 | 0 | (*deleter)(elements[index].pointer); |
130 | 0 | } |
131 | 869M | elements[index].pointer = obj; |
132 | 869M | } else { |
133 | | /* index out of range */ |
134 | 0 | if (deleter != nullptr) { |
135 | 0 | (*deleter)(obj); |
136 | 0 | } |
137 | 0 | } |
138 | 869M | } |
139 | | |
140 | 0 | void UVector::setElementAt(int32_t elem, int32_t index) { |
141 | 0 | U_ASSERT(deleter == nullptr); // Usage error. Mixing up ints and pointers. |
142 | 0 | if (0 <= index && index < count) { |
143 | 0 | elements[index].pointer = nullptr; |
144 | 0 | elements[index].integer = elem; |
145 | 0 | } |
146 | | /* else index out of range */ |
147 | 0 | } |
148 | | |
149 | 11.4M | void UVector::insertElementAt(void* obj, int32_t index, UErrorCode &status) { |
150 | 11.4M | if (ensureCapacity(count + 1, status)) { |
151 | 11.4M | if (0 <= index && index <= count) { |
152 | 11.4M | for (int32_t i=count; i>index; --i) { |
153 | 1.77k | elements[i] = elements[i-1]; |
154 | 1.77k | } |
155 | 11.4M | elements[index].pointer = obj; |
156 | 11.4M | ++count; |
157 | 11.4M | } else { |
158 | | /* index out of range */ |
159 | 0 | status = U_ILLEGAL_ARGUMENT_ERROR; |
160 | 0 | } |
161 | 11.4M | } |
162 | 11.4M | if (U_FAILURE(status) && deleter != nullptr) { |
163 | 0 | (*deleter)(obj); |
164 | 0 | } |
165 | 11.4M | } |
166 | | |
167 | 98.8k | void UVector::insertElementAt(int32_t elem, int32_t index, UErrorCode &status) { |
168 | 98.8k | U_ASSERT(deleter == nullptr); // Usage error. Mixing up ints and pointers. |
169 | | // must have 0 <= index <= count |
170 | 98.8k | if (ensureCapacity(count + 1, status)) { |
171 | 98.8k | if (0 <= index && index <= count) { |
172 | 216k | for (int32_t i=count; i>index; --i) { |
173 | 117k | elements[i] = elements[i-1]; |
174 | 117k | } |
175 | 98.8k | elements[index].pointer = nullptr; |
176 | 98.8k | elements[index].integer = elem; |
177 | 98.8k | ++count; |
178 | 98.8k | } else { |
179 | | /* index out of range */ |
180 | 0 | status = U_ILLEGAL_ARGUMENT_ERROR; |
181 | 0 | } |
182 | 98.8k | } |
183 | 98.8k | } |
184 | | |
185 | 6.45G | void* UVector::elementAt(int32_t index) const { |
186 | 6.45G | return (0 <= index && index < count) ? elements[index].pointer : nullptr; |
187 | 6.45G | } |
188 | | |
189 | 9.88M | int32_t UVector::elementAti(int32_t index) const { |
190 | 9.88M | return (0 <= index && index < count) ? elements[index].integer : 0; |
191 | 9.88M | } |
192 | | |
193 | 0 | UBool UVector::containsAll(const UVector& other) const { |
194 | 0 | for (int32_t i=0; i<other.size(); ++i) { |
195 | 0 | if (indexOf(other.elements[i]) < 0) { |
196 | 0 | return false; |
197 | 0 | } |
198 | 0 | } |
199 | 0 | return true; |
200 | 0 | } |
201 | | |
202 | 0 | UBool UVector::containsNone(const UVector& other) const { |
203 | 0 | for (int32_t i=0; i<other.size(); ++i) { |
204 | 0 | if (indexOf(other.elements[i]) >= 0) { |
205 | 0 | return false; |
206 | 0 | } |
207 | 0 | } |
208 | 0 | return true; |
209 | 0 | } |
210 | | |
211 | 3.91k | UBool UVector::removeAll(const UVector& other) { |
212 | 3.91k | UBool changed = false; |
213 | 23.7k | for (int32_t i=0; i<other.size(); ++i) { |
214 | 19.8k | int32_t j = indexOf(other.elements[i]); |
215 | 19.8k | if (j >= 0) { |
216 | 6.25k | removeElementAt(j); |
217 | 6.25k | changed = true; |
218 | 6.25k | } |
219 | 19.8k | } |
220 | 3.91k | return changed; |
221 | 3.91k | } |
222 | | |
223 | 2.03k | UBool UVector::retainAll(const UVector& other) { |
224 | 2.03k | UBool changed = false; |
225 | 16.4k | for (int32_t j=size()-1; j>=0; --j) { |
226 | 14.3k | int32_t i = other.indexOf(elements[j]); |
227 | 14.3k | if (i < 0) { |
228 | 10.7k | removeElementAt(j); |
229 | 10.7k | changed = true; |
230 | 10.7k | } |
231 | 14.3k | } |
232 | 2.03k | return changed; |
233 | 2.03k | } |
234 | | |
235 | 99.2M | void UVector::removeElementAt(int32_t index) { |
236 | 99.2M | void* e = orphanElementAt(index); |
237 | 99.2M | if (e != nullptr && deleter != nullptr) { |
238 | 218k | (*deleter)(e); |
239 | 218k | } |
240 | 99.2M | } |
241 | | |
242 | 0 | UBool UVector::removeElement(void* obj) { |
243 | 0 | int32_t i = indexOf(obj); |
244 | 0 | if (i >= 0) { |
245 | 0 | removeElementAt(i); |
246 | 0 | return true; |
247 | 0 | } |
248 | 0 | return false; |
249 | 0 | } |
250 | | |
251 | 43.4M | void UVector::removeAllElements() { |
252 | 43.4M | if (deleter != nullptr) { |
253 | 23.4M | for (int32_t i=0; i<count; ++i) { |
254 | 22.7M | if (elements[i].pointer != nullptr) { |
255 | 22.7M | (*deleter)(elements[i].pointer); |
256 | 22.7M | } |
257 | 22.7M | } |
258 | 628k | } |
259 | 43.4M | count = 0; |
260 | 43.4M | } |
261 | | |
262 | 628M | UBool UVector::equals(const UVector &other) const { |
263 | 628M | int i; |
264 | | |
265 | 628M | if (this->count != other.count) { |
266 | 407M | return false; |
267 | 407M | } |
268 | 221M | if (comparer == nullptr) { |
269 | 346M | for (i=0; i<count; i++) { |
270 | 344M | if (elements[i].pointer != other.elements[i].pointer) { |
271 | 219M | return false; |
272 | 219M | } |
273 | 344M | } |
274 | 221M | } else { |
275 | 0 | UElement key; |
276 | 0 | for (i=0; i<count; i++) { |
277 | 0 | key.pointer = &other.elements[i]; |
278 | 0 | if (!(*comparer)(key, elements[i])) { |
279 | 0 | return false; |
280 | 0 | } |
281 | 0 | } |
282 | 0 | } |
283 | 1.67M | return true; |
284 | 221M | } |
285 | | |
286 | | |
287 | | |
288 | 12.4M | int32_t UVector::indexOf(void* obj, int32_t startIndex) const { |
289 | 12.4M | UElement key; |
290 | 12.4M | key.pointer = obj; |
291 | 12.4M | return indexOf(key, startIndex, HINT_KEY_POINTER); |
292 | 12.4M | } |
293 | | |
294 | 0 | int32_t UVector::indexOf(int32_t obj, int32_t startIndex) const { |
295 | 0 | UElement key; |
296 | 0 | key.integer = obj; |
297 | 0 | return indexOf(key, startIndex, HINT_KEY_INTEGER); |
298 | 0 | } |
299 | | |
300 | 12.5M | int32_t UVector::indexOf(UElement key, int32_t startIndex, int8_t hint) const { |
301 | 12.5M | if (comparer != nullptr) { |
302 | 362M | for (int32_t i=startIndex; i<count; ++i) { |
303 | 358M | if ((*comparer)(key, elements[i])) { |
304 | 3.60M | return i; |
305 | 3.60M | } |
306 | 358M | } |
307 | 8.16M | } else { |
308 | 103M | 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 | 99.8M | if (hint & HINT_KEY_POINTER) { |
313 | 99.8M | if (key.pointer == elements[i].pointer) { |
314 | 298k | return i; |
315 | 298k | } |
316 | 99.8M | } else { |
317 | 0 | if (key.integer == elements[i].integer) { |
318 | 0 | return i; |
319 | 0 | } |
320 | 0 | } |
321 | 99.8M | } |
322 | 4.34M | } |
323 | 8.60M | return -1; |
324 | 12.5M | } |
325 | | |
326 | 54.5M | UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { |
327 | 54.5M | if (U_FAILURE(status)) { |
328 | 3 | return false; |
329 | 3 | } |
330 | 54.5M | if (minimumCapacity < 0) { |
331 | 0 | status = U_ILLEGAL_ARGUMENT_ERROR; |
332 | 0 | return false; |
333 | 0 | } |
334 | 54.5M | if (capacity < minimumCapacity) { |
335 | 4.32M | if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check |
336 | 0 | status = U_ILLEGAL_ARGUMENT_ERROR; |
337 | 0 | return false; |
338 | 0 | } |
339 | 4.32M | int32_t newCap = capacity * 2; |
340 | 4.32M | if (newCap < minimumCapacity) { |
341 | 1.44M | newCap = minimumCapacity; |
342 | 1.44M | } |
343 | 4.32M | if (newCap > static_cast<int32_t>(INT32_MAX / sizeof(UElement))) { // integer overflow check |
344 | | // We keep the original memory contents on bad minimumCapacity. |
345 | 0 | status = U_ILLEGAL_ARGUMENT_ERROR; |
346 | 0 | return false; |
347 | 0 | } |
348 | 4.32M | UElement* newElems = static_cast<UElement*>(uprv_realloc(elements, sizeof(UElement) * newCap)); |
349 | 4.32M | if (newElems == nullptr) { |
350 | | // We keep the original contents on the memory failure on realloc or bad minimumCapacity. |
351 | 0 | status = U_MEMORY_ALLOCATION_ERROR; |
352 | 0 | return false; |
353 | 0 | } |
354 | 4.32M | elements = newElems; |
355 | 4.32M | capacity = newCap; |
356 | 4.32M | } |
357 | 54.5M | return true; |
358 | 54.5M | } |
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 | 18.1M | void UVector::setSize(int32_t newSize, UErrorCode &status) { |
367 | 18.1M | if (!ensureCapacity(newSize, status)) { |
368 | 0 | return; |
369 | 0 | } |
370 | 18.1M | if (newSize > count) { |
371 | 9.08M | UElement empty; |
372 | 9.08M | empty.pointer = nullptr; |
373 | 9.08M | empty.integer = 0; |
374 | 343M | for (int32_t i=count; i<newSize; ++i) { |
375 | 334M | elements[i] = empty; |
376 | 334M | } |
377 | 9.08M | } else { |
378 | | /* Most efficient to count down */ |
379 | 107M | for (int32_t i=count-1; i>=newSize; --i) { |
380 | 98.1M | removeElementAt(i); |
381 | 98.1M | } |
382 | 9.01M | } |
383 | 18.1M | count = newSize; |
384 | 18.1M | } |
385 | | |
386 | | /** |
387 | | * Fill in the given array with all elements of this vector. |
388 | | */ |
389 | 18.0M | void** UVector::toArray(void** result) const { |
390 | 18.0M | void** a = result; |
391 | 985M | for (int i=0; i<count; ++i) { |
392 | 967M | *a++ = elements[i].pointer; |
393 | 967M | } |
394 | 18.0M | return result; |
395 | 18.0M | } |
396 | | |
397 | 187k | UObjectDeleter *UVector::setDeleter(UObjectDeleter *d) { |
398 | 187k | UObjectDeleter *old = deleter; |
399 | 187k | deleter = d; |
400 | 187k | return old; |
401 | 187k | } |
402 | | |
403 | 144k | UElementsAreEqual *UVector::setComparer(UElementsAreEqual *d) { |
404 | 144k | UElementsAreEqual *old = comparer; |
405 | 144k | comparer = d; |
406 | 144k | return old; |
407 | 144k | } |
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 | 99.7M | void* UVector::orphanElementAt(int32_t index) { |
419 | 99.7M | void* e = nullptr; |
420 | 99.7M | if (0 <= index && index < count) { |
421 | 99.7M | e = elements[index].pointer; |
422 | 107M | for (int32_t i=index; i<count-1; ++i) { |
423 | 7.72M | elements[i] = elements[i+1]; |
424 | 7.72M | } |
425 | 99.7M | --count; |
426 | 99.7M | } |
427 | | /* else index out of range */ |
428 | 99.7M | return e; |
429 | 99.7M | } |
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 | 4.55M | void UVector::sortedInsert(void* obj, UElementComparator *compare, UErrorCode& ec) { |
437 | 4.55M | UElement e; |
438 | 4.55M | e.pointer = obj; |
439 | 4.55M | sortedInsert(e, compare, ec); |
440 | 4.55M | } |
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 | 0 | void UVector::sortedInsert(int32_t obj, UElementComparator *compare, UErrorCode& ec) { |
448 | 0 | U_ASSERT(deleter == nullptr); |
449 | 0 | UElement e {}; |
450 | 0 | e.integer = obj; |
451 | 0 | sortedInsert(e, compare, ec); |
452 | 0 | } |
453 | | |
454 | | // ASSUME elements[] IS CURRENTLY SORTED |
455 | 4.55M | 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 | 4.55M | if (!ensureCapacity(count + 1, ec)) { |
462 | 0 | if (deleter != nullptr) { |
463 | 0 | (*deleter)(e.pointer); |
464 | 0 | } |
465 | 0 | return; |
466 | 0 | } |
467 | 4.55M | int32_t min = 0, max = count; |
468 | 25.2M | while (min != max) { |
469 | 20.6M | int32_t probe = (min + max) / 2; |
470 | 20.6M | int32_t c = (*compare)(elements[probe], e); |
471 | 20.6M | if (c > 0) { |
472 | 6.05M | max = probe; |
473 | 14.6M | } else { |
474 | | // assert(c <= 0); |
475 | 14.6M | min = probe + 1; |
476 | 14.6M | } |
477 | 20.6M | } |
478 | 64.8M | for (int32_t i=count; i>min; --i) { |
479 | 60.2M | elements[i] = elements[i-1]; |
480 | 60.2M | } |
481 | 4.55M | elements[min] = e; |
482 | 4.55M | ++count; |
483 | 4.55M | } |
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 | 188M | sortComparator(const void *context, const void *left, const void *right) { |
498 | 188M | UElementComparator *compare = *static_cast<UElementComparator * const *>(context); |
499 | 188M | UElement e1 = *static_cast<const UElement *>(left); |
500 | 188M | UElement e2 = *static_cast<const UElement *>(right); |
501 | 188M | int32_t result = (*compare)(e1, e2); |
502 | 188M | return result; |
503 | 188M | } |
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 | 0 | sortiComparator(const void * /*context */, const void *left, const void *right) { |
512 | 0 | const UElement *e1 = static_cast<const UElement *>(left); |
513 | 0 | const UElement *e2 = static_cast<const UElement *>(right); |
514 | 0 | int32_t result = e1->integer < e2->integer? -1 : |
515 | 0 | e1->integer == e2->integer? 0 : 1; |
516 | 0 | return result; |
517 | 0 | } |
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 | 0 | void UVector::sorti(UErrorCode &ec) { |
526 | 0 | if (U_SUCCESS(ec)) { |
527 | 0 | uprv_sortArray(elements, count, sizeof(UElement), |
528 | 0 | sortiComparator, nullptr, false, &ec); |
529 | 0 | } |
530 | 0 | } |
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 | 15.3k | void UVector::sort(UElementComparator *compare, UErrorCode &ec) { |
548 | 15.3k | if (U_SUCCESS(ec)) { |
549 | 15.3k | uprv_sortArray(elements, count, sizeof(UElement), |
550 | 15.3k | sortComparator, &compare, false, &ec); |
551 | 15.3k | } |
552 | 15.3k | } |
553 | | |
554 | | |
555 | | /** |
556 | | * Stable sort with a user supplied comparator of type UComparator. |
557 | | */ |
558 | 0 | void UVector::sortWithUComparator(UComparator *compare, const void *context, UErrorCode &ec) { |
559 | 0 | if (U_SUCCESS(ec)) { |
560 | 0 | uprv_sortArray(elements, count, sizeof(UElement), |
561 | 0 | compare, context, true, &ec); |
562 | 0 | } |
563 | 0 | } |
564 | | |
565 | | U_NAMESPACE_END |
566 | | |