Coverage Report

Created: 2025-06-24 06:54

/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