Coverage Report

Created: 2025-06-24 06:43

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