1 // © 2016 and later: Unicode, Inc. and others. 
   2 // License & terms of use: http://www.unicode.org/copyright.html 
   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 ********************************************************************** 
  20 #define DEFAULT_CAPACITY 8 
  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 
  27 #define HINT_KEY_POINTER   (1) 
  28 #define HINT_KEY_INTEGER   (0) 
  30 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector
) 
  32 UVector::UVector(UErrorCode 
&status
) : 
  39     _init(DEFAULT_CAPACITY
, status
); 
  42 UVector::UVector(int32_t initialCapacity
, UErrorCode 
&status
) : 
  49     _init(initialCapacity
, status
); 
  52 UVector::UVector(UObjectDeleter 
*d
, UElementsAreEqual 
*c
, UErrorCode 
&status
) : 
  59     _init(DEFAULT_CAPACITY
, status
); 
  62 UVector::UVector(UObjectDeleter 
*d
, UElementsAreEqual 
*c
, int32_t initialCapacity
, UErrorCode 
&status
) : 
  69     _init(initialCapacity
, status
); 
  72 void UVector::_init(int32_t initialCapacity
, UErrorCode 
&status
) { 
  73     if (U_FAILURE(status
)) { 
  76     // Fix bogus initialCapacity values; avoid malloc(0) and integer overflow 
  77     if ((initialCapacity 
< 1) || (initialCapacity 
> (int32_t)(INT32_MAX 
/ sizeof(UElement
)))) { 
  78         initialCapacity 
= DEFAULT_CAPACITY
; 
  80     elements 
= (UElement 
*)uprv_malloc(sizeof(UElement
)*initialCapacity
); 
  82         status 
= U_MEMORY_ALLOCATION_ERROR
; 
  84         capacity 
= initialCapacity
; 
  95  * Assign this object to another (make this a copy of 'other'). 
  96  * Use the 'assign' function to assign each element. 
  98 void UVector::assign(const UVector
& other
, UElementAssigner 
*assign
, UErrorCode 
&ec
) { 
  99     if (ensureCapacity(other
.count
, ec
)) { 
 100         setSize(other
.count
, ec
); 
 102             for (int32_t i
=0; i
<other
.count
; ++i
) { 
 103                 if (elements
[i
].pointer 
!= 0 && deleter 
!= 0) { 
 104                     (*deleter
)(elements
[i
].pointer
); 
 106                 (*assign
)(&elements
[i
], &other
.elements
[i
]); 
 112 // This only does something sensible if this object has a non-null comparer 
 113 UBool 
UVector::operator==(const UVector
& other
) { 
 115     if (count 
!= other
.count
) return FALSE
; 
 116     if (comparer 
!= NULL
) { 
 117         // Compare using this object's comparer 
 118         for (i
=0; i
<count
; ++i
) { 
 119             if (!(*comparer
)(elements
[i
], other
.elements
[i
])) { 
 127 void UVector::addElement(void* obj
, UErrorCode 
&status
) { 
 128     if (ensureCapacity(count 
+ 1, status
)) { 
 129         elements
[count
++].pointer 
= obj
; 
 133 void UVector::addElement(int32_t elem
, UErrorCode 
&status
) { 
 134     if (ensureCapacity(count 
+ 1, status
)) { 
 135         elements
[count
].pointer 
= NULL
;     // Pointers may be bigger than ints. 
 136         elements
[count
].integer 
= elem
; 
 141 void UVector::setElementAt(void* obj
, int32_t index
) { 
 142     if (0 <= index 
&& index 
< count
) { 
 143         if (elements
[index
].pointer 
!= 0 && deleter 
!= 0) { 
 144             (*deleter
)(elements
[index
].pointer
); 
 146         elements
[index
].pointer 
= obj
; 
 148     /* else index out of range */ 
 151 void UVector::setElementAt(int32_t elem
, int32_t index
) { 
 152     if (0 <= index 
&& index 
< count
) { 
 153         if (elements
[index
].pointer 
!= 0 && deleter 
!= 0) { 
 154             // TODO:  this should be an error.  mixing up ints and pointers. 
 155             (*deleter
)(elements
[index
].pointer
); 
 157         elements
[index
].pointer 
= NULL
; 
 158         elements
[index
].integer 
= elem
; 
 160     /* else index out of range */ 
 163 void UVector::insertElementAt(void* obj
, int32_t index
, UErrorCode 
&status
) { 
 164     // must have 0 <= index <= count 
 165     if (0 <= index 
&& index 
<= count 
&& ensureCapacity(count 
+ 1, status
)) { 
 166         for (int32_t i
=count
; i
>index
; --i
) { 
 167             elements
[i
] = elements
[i
-1]; 
 169         elements
[index
].pointer 
= obj
; 
 172     /* else index out of range */ 
 175 void UVector::insertElementAt(int32_t elem
, int32_t index
, UErrorCode 
&status
) { 
 176     // must have 0 <= index <= count 
 177     if (0 <= index 
&& index 
<= count 
&& ensureCapacity(count 
+ 1, status
)) { 
 178         for (int32_t i
=count
; i
>index
; --i
) { 
 179             elements
[i
] = elements
[i
-1]; 
 181         elements
[index
].pointer 
= NULL
; 
 182         elements
[index
].integer 
= elem
; 
 185     /* else index out of range */ 
 188 void* UVector::elementAt(int32_t index
) const { 
 189     return (0 <= index 
&& index 
< count
) ? elements
[index
].pointer 
: 0; 
 192 int32_t UVector::elementAti(int32_t index
) const { 
 193     return (0 <= index 
&& index 
< count
) ? elements
[index
].integer 
: 0; 
 196 UBool 
UVector::containsAll(const UVector
& other
) const { 
 197     for (int32_t i
=0; i
<other
.size(); ++i
) { 
 198         if (indexOf(other
.elements
[i
]) < 0) { 
 205 UBool 
UVector::containsNone(const UVector
& other
) const { 
 206     for (int32_t i
=0; i
<other
.size(); ++i
) { 
 207         if (indexOf(other
.elements
[i
]) >= 0) { 
 214 UBool 
UVector::removeAll(const UVector
& other
) { 
 215     UBool changed 
= FALSE
; 
 216     for (int32_t i
=0; i
<other
.size(); ++i
) { 
 217         int32_t j 
= indexOf(other
.elements
[i
]); 
 226 UBool 
UVector::retainAll(const UVector
& other
) { 
 227     UBool changed 
= FALSE
; 
 228     for (int32_t j
=size()-1; j
>=0; --j
) { 
 229         int32_t i 
= other
.indexOf(elements
[j
]); 
 238 void UVector::removeElementAt(int32_t index
) { 
 239     void* e 
= orphanElementAt(index
); 
 240     if (e 
!= 0 && deleter 
!= 0) { 
 245 UBool 
UVector::removeElement(void* obj
) { 
 246     int32_t i 
= indexOf(obj
); 
 254 void UVector::removeAllElements(void) { 
 256         for (int32_t i
=0; i
<count
; ++i
) { 
 257             if (elements
[i
].pointer 
!= 0) { 
 258                 (*deleter
)(elements
[i
].pointer
); 
 265 UBool   
UVector::equals(const UVector 
&other
) const { 
 268     if (this->count 
!= other
.count
) { 
 272         for (i
=0; i
<count
; i
++) { 
 273             if (elements
[i
].pointer 
!= other
.elements
[i
].pointer
) { 
 279         for (i
=0; i
<count
; i
++) { 
 280             key
.pointer 
= &other
.elements
[i
]; 
 281             if (!(*comparer
)(key
, elements
[i
])) { 
 291 int32_t UVector::indexOf(void* obj
, int32_t startIndex
) const { 
 294     return indexOf(key
, startIndex
, HINT_KEY_POINTER
); 
 297 int32_t UVector::indexOf(int32_t obj
, int32_t startIndex
) const { 
 300     return indexOf(key
, startIndex
, HINT_KEY_INTEGER
); 
 303 // This only works if this object has a non-null comparer 
 304 int32_t UVector::indexOf(UElement key
, int32_t startIndex
, int8_t hint
) const { 
 307         for (i
=startIndex
; i
<count
; ++i
) { 
 308             if ((*comparer
)(key
, elements
[i
])) { 
 313         for (i
=startIndex
; i
<count
; ++i
) { 
 314             /* Pointers are not always the same size as ints so to perform 
 315              * a valid comparision we need to know whether we are being 
 316              * provided an int or a pointer. */ 
 317             if (hint 
& HINT_KEY_POINTER
) { 
 318                 if (key
.pointer 
== elements
[i
].pointer
) { 
 322                 if (key
.integer 
== elements
[i
].integer
) { 
 331 UBool 
UVector::ensureCapacity(int32_t minimumCapacity
, UErrorCode 
&status
) { 
 332         if (minimumCapacity 
< 0) { 
 333         status 
= U_ILLEGAL_ARGUMENT_ERROR
; 
 336     if (capacity 
< minimumCapacity
) { 
 337         if (capacity 
> (INT32_MAX 
- 1) / 2) {           // integer overflow check 
 338                 status 
= U_ILLEGAL_ARGUMENT_ERROR
; 
 341         int32_t newCap 
= capacity 
* 2; 
 342         if (newCap 
< minimumCapacity
) { 
 343             newCap 
= minimumCapacity
; 
 345         if (newCap 
> (int32_t)(INT32_MAX 
/ sizeof(UElement
))) { // integer overflow check 
 346                 // We keep the original memory contents on bad minimumCapacity. 
 347                 status 
= U_ILLEGAL_ARGUMENT_ERROR
; 
 350         UElement
* newElems 
= (UElement 
*)uprv_realloc(elements
, sizeof(UElement
)*newCap
); 
 351         if (newElems 
== NULL
) { 
 352             // We keep the original contents on the memory failure on realloc or bad minimumCapacity. 
 353             status 
= U_MEMORY_ALLOCATION_ERROR
; 
 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 
 368 void UVector::setSize(int32_t newSize
, UErrorCode 
&status
) { 
 373     if (newSize 
> count
) { 
 374         if (!ensureCapacity(newSize
, status
)) { 
 378         empty
.pointer 
= NULL
; 
 380         for (i
=count
; i
<newSize
; ++i
) { 
 384         /* Most efficient to count down */ 
 385         for (i
=count
-1; i
>=newSize
; --i
) { 
 393  * Fill in the given array with all elements of this vector. 
 395 void** UVector::toArray(void** result
) const { 
 397     for (int i
=0; i
<count
; ++i
) { 
 398         *a
++ = elements
[i
].pointer
; 
 403 UObjectDeleter 
*UVector::setDeleter(UObjectDeleter 
*d
) { 
 404     UObjectDeleter 
*old 
= deleter
; 
 409 UElementsAreEqual 
*UVector::setComparer(UElementsAreEqual 
*d
) { 
 410     UElementsAreEqual 
*old 
= comparer
; 
 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. 
 424 void* UVector::orphanElementAt(int32_t index
) { 
 426     if (0 <= index 
&& index 
< count
) { 
 427         e 
= elements
[index
].pointer
; 
 428         for (int32_t i
=index
; i
<count
-1; ++i
) { 
 429             elements
[i
] = elements
[i
+1]; 
 433     /* else index out of range */ 
 438  * Insert the given object into this vector at its sorted position 
 439  * as defined by 'compare'.  The current elements are assumed to 
 442 void UVector::sortedInsert(void* obj
, UElementComparator 
*compare
, UErrorCode
& ec
) { 
 445     sortedInsert(e
, compare
, ec
); 
 449  * Insert the given integer into this vector at its sorted position 
 450  * as defined by 'compare'.  The current elements are assumed to 
 453 void UVector::sortedInsert(int32_t obj
, UElementComparator 
*compare
, UErrorCode
& ec
) { 
 456     sortedInsert(e
, compare
, ec
); 
 459 // ASSUME elements[] IS CURRENTLY SORTED 
 460 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 
 466     int32_t min 
= 0, max 
= count
; 
 468         int32_t probe 
= (min 
+ max
) / 2; 
 469         int8_t c 
= (*compare
)(elements
[probe
], e
); 
 477     if (ensureCapacity(count 
+ 1, ec
)) { 
 478         for (int32_t i
=count
; i
>min
; --i
) { 
 479             elements
[i
] = elements
[i
-1]; 
 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(). 
 493   *  The context pointer to this function is a pointer back 
 494   *  (with some extra indirection) to the user supplied comparator. 
 497 static int32_t U_CALLCONV
 
 498 sortComparator(const void *context
, const void *left
, const void *right
) { 
 499     UElementComparator 
*compare 
= *static_cast<UElementComparator 
* const *>(context
); 
 500     UElement e1 
= *static_cast<const UElement 
*>(left
); 
 501     UElement e2 
= *static_cast<const UElement 
*>(right
); 
 502     int32_t result 
= (*compare
)(e1
, e2
); 
 508   *  Array sort comparison function for use from UVector::sorti() 
 509   *  Compares int32_t vector elements. 
 511 static int32_t U_CALLCONV
 
 512 sortiComparator(const void * /*context */, const void *left
, const void *right
) { 
 513     const UElement 
*e1 
= static_cast<const UElement 
*>(left
); 
 514     const UElement 
*e2 
= static_cast<const UElement 
*>(right
); 
 515     int32_t result 
= e1
->integer 
< e2
->integer
? -1 : 
 516                      e1
->integer 
== e2
->integer
? 0 : 1; 
 521   * Sort the vector, assuming it constains 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.) 
 526 void UVector::sorti(UErrorCode 
&ec
) { 
 528         uprv_sortArray(elements
, count
, sizeof(UElement
), 
 529                        sortiComparator
, NULL
,  FALSE
, &ec
); 
 535  *  Sort with a user supplied comparator. 
 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 functtion. 
 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. 
 548 void UVector::sort(UElementComparator 
*compare
, UErrorCode 
&ec
) { 
 550         uprv_sortArray(elements
, count
, sizeof(UElement
), 
 551                        sortComparator
, &compare
, FALSE
, &ec
); 
 557  *  Stable sort with a user supplied comparator of type UComparator. 
 559 void UVector::sortWithUComparator(UComparator 
*compare
, const void *context
, UErrorCode 
&ec
) { 
 561         uprv_sortArray(elements
, count
, sizeof(UElement
), 
 562                        compare
, context
, TRUE
, &ec
);