Home | History | Annotate | Download | only in common
      1 /*
      2 ******************************************************************************
      3 * Copyright (C) 1999-2010, International Business Machines Corporation and   *
      4 * others. All Rights Reserved.                                               *
      5 ******************************************************************************
      6 *   Date        Name        Description
      7 *   10/22/99    alan        Creation.
      8 **********************************************************************
      9 */
     10 
     11 #include "uvectr32.h"
     12 #include "cmemory.h"
     13 #include "putilimp.h"
     14 
     15 U_NAMESPACE_BEGIN
     16 
     17 #define DEFAULT_CAPACITY 8
     18 
     19 /*
     20  * Constants for hinting whether a key is an integer
     21  * or a pointer.  If a hint bit is zero, then the associated
     22  * token is assumed to be an integer. This is needed for iSeries
     23  */
     24 
     25 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector32)
     26 
     27 UVector32::UVector32(UErrorCode &status) :
     28     count(0),
     29     capacity(0),
     30     maxCapacity(0),
     31     elements(NULL)
     32 {
     33     _init(DEFAULT_CAPACITY, status);
     34 }
     35 
     36 UVector32::UVector32(int32_t initialCapacity, UErrorCode &status) :
     37     count(0),
     38     capacity(0),
     39     maxCapacity(0),
     40     elements(0)
     41 {
     42     _init(initialCapacity, status);
     43 }
     44 
     45 
     46 
     47 void UVector32::_init(int32_t initialCapacity, UErrorCode &status) {
     48     // Fix bogus initialCapacity values; avoid malloc(0)
     49     if (initialCapacity < 1) {
     50         initialCapacity = DEFAULT_CAPACITY;
     51     }
     52     if (maxCapacity>0 && maxCapacity<initialCapacity) {
     53         initialCapacity = maxCapacity;
     54     }
     55     if (initialCapacity > (int32_t)(INT32_MAX / sizeof(int32_t))) {
     56         initialCapacity = uprv_min(DEFAULT_CAPACITY, maxCapacity);
     57     }
     58     elements = (int32_t *)uprv_malloc(sizeof(int32_t)*initialCapacity);
     59     if (elements == 0) {
     60         status = U_MEMORY_ALLOCATION_ERROR;
     61     } else {
     62         capacity = initialCapacity;
     63     }
     64 }
     65 
     66 UVector32::~UVector32() {
     67     uprv_free(elements);
     68     elements = 0;
     69 }
     70 
     71 /**
     72  * Assign this object to another (make this a copy of 'other').
     73  */
     74 void UVector32::assign(const UVector32& other, UErrorCode &ec) {
     75     if (ensureCapacity(other.count, ec)) {
     76         setSize(other.count);
     77         for (int32_t i=0; i<other.count; ++i) {
     78             elements[i] = other.elements[i];
     79         }
     80     }
     81 }
     82 
     83 
     84 UBool UVector32::operator==(const UVector32& other) {
     85     int32_t i;
     86     if (count != other.count) return FALSE;
     87     for (i=0; i<count; ++i) {
     88         if (elements[i] != other.elements[i]) {
     89             return FALSE;
     90         }
     91     }
     92     return TRUE;
     93 }
     94 
     95 
     96 void UVector32::setElementAt(int32_t elem, int32_t index) {
     97     if (0 <= index && index < count) {
     98         elements[index] = elem;
     99     }
    100     /* else index out of range */
    101 }
    102 
    103 void UVector32::insertElementAt(int32_t elem, int32_t index, UErrorCode &status) {
    104     // must have 0 <= index <= count
    105     if (0 <= index && index <= count && ensureCapacity(count + 1, status)) {
    106         for (int32_t i=count; i>index; --i) {
    107             elements[i] = elements[i-1];
    108         }
    109         elements[index] = elem;
    110         ++count;
    111     }
    112     /* else index out of range */
    113 }
    114 
    115 UBool UVector32::containsAll(const UVector32& other) const {
    116     for (int32_t i=0; i<other.size(); ++i) {
    117         if (indexOf(other.elements[i]) < 0) {
    118             return FALSE;
    119         }
    120     }
    121     return TRUE;
    122 }
    123 
    124 UBool UVector32::containsNone(const UVector32& other) const {
    125     for (int32_t i=0; i<other.size(); ++i) {
    126         if (indexOf(other.elements[i]) >= 0) {
    127             return FALSE;
    128         }
    129     }
    130     return TRUE;
    131 }
    132 
    133 UBool UVector32::removeAll(const UVector32& other) {
    134     UBool changed = FALSE;
    135     for (int32_t i=0; i<other.size(); ++i) {
    136         int32_t j = indexOf(other.elements[i]);
    137         if (j >= 0) {
    138             removeElementAt(j);
    139             changed = TRUE;
    140         }
    141     }
    142     return changed;
    143 }
    144 
    145 UBool UVector32::retainAll(const UVector32& other) {
    146     UBool changed = FALSE;
    147     for (int32_t j=size()-1; j>=0; --j) {
    148         int32_t i = other.indexOf(elements[j]);
    149         if (i < 0) {
    150             removeElementAt(j);
    151             changed = TRUE;
    152         }
    153     }
    154     return changed;
    155 }
    156 
    157 void UVector32::removeElementAt(int32_t index) {
    158     if (index >= 0) {
    159         for (int32_t i=index; i<count-1; ++i) {
    160             elements[i] = elements[i+1];
    161         }
    162         --count;
    163     }
    164 }
    165 
    166 void UVector32::removeAllElements(void) {
    167     count = 0;
    168 }
    169 
    170 UBool   UVector32::equals(const UVector32 &other) const {
    171     int      i;
    172 
    173     if (this->count != other.count) {
    174         return FALSE;
    175     }
    176     for (i=0; i<count; i++) {
    177         if (elements[i] != other.elements[i]) {
    178             return FALSE;
    179         }
    180     }
    181     return TRUE;
    182 }
    183 
    184 
    185 
    186 
    187 int32_t UVector32::indexOf(int32_t key, int32_t startIndex) const {
    188     int32_t i;
    189     for (i=startIndex; i<count; ++i) {
    190         if (key == elements[i]) {
    191             return i;
    192         }
    193     }
    194     return -1;
    195 }
    196 
    197 
    198 UBool UVector32::expandCapacity(int32_t minimumCapacity, UErrorCode &status) {
    199     if (minimumCapacity < 0) {
    200         status = U_ILLEGAL_ARGUMENT_ERROR;
    201         return FALSE;
    202     }
    203     if (capacity >= minimumCapacity) {
    204         return TRUE;
    205     }
    206     if (maxCapacity>0 && minimumCapacity>maxCapacity) {
    207         status = U_BUFFER_OVERFLOW_ERROR;
    208         return FALSE;
    209     }
    210     if (capacity > (INT32_MAX - 1) / 2) {  // integer overflow check
    211         status = U_ILLEGAL_ARGUMENT_ERROR;
    212         return FALSE;
    213     }
    214     int32_t newCap = capacity * 2;
    215     if (newCap < minimumCapacity) {
    216         newCap = minimumCapacity;
    217     }
    218     if (maxCapacity > 0 && newCap > maxCapacity) {
    219         newCap = maxCapacity;
    220     }
    221     if (newCap > (int32_t)(INT32_MAX / sizeof(int32_t))) {  // integer overflow check
    222         // We keep the original memory contents on bad minimumCapacity/maxCapacity.
    223         status = U_ILLEGAL_ARGUMENT_ERROR;
    224         return FALSE;
    225     }
    226     int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*newCap);
    227     if (newElems == NULL) {
    228         // We keep the original contents on the memory failure on realloc.
    229         status = U_MEMORY_ALLOCATION_ERROR;
    230         return FALSE;
    231     }
    232     elements = newElems;
    233     capacity = newCap;
    234     return TRUE;
    235 }
    236 
    237 void UVector32::setMaxCapacity(int32_t limit) {
    238     U_ASSERT(limit >= 0);
    239     if (limit < 0) {
    240         limit = 0;
    241     }
    242     if (limit > (int32_t)(INT32_MAX / sizeof(int32_t))) {  // integer overflow check for realloc
    243         //  Something is very wrong, don't realloc, leave capacity and maxCapacity unchanged
    244         return;
    245     }
    246     maxCapacity = limit;
    247     if (capacity <= maxCapacity || maxCapacity == 0) {
    248         // Current capacity is within the new limit.
    249         return;
    250     }
    251 
    252     // New maximum capacity is smaller than the current size.
    253     // Realloc the storage to the new, smaller size.
    254     int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*maxCapacity);
    255     if (newElems == NULL) {
    256         // Realloc to smaller failed.
    257         //   Just keep what we had.  No need to call it a failure.
    258         return;
    259     }
    260     elements = newElems;
    261     capacity = maxCapacity;
    262     if (count > capacity) {
    263         count = capacity;
    264     }
    265 }
    266 
    267 /**
    268  * Change the size of this vector as follows: If newSize is smaller,
    269  * then truncate the array, possibly deleting held elements for i >=
    270  * newSize.  If newSize is larger, grow the array, filling in new
    271  * slots with NULL.
    272  */
    273 void UVector32::setSize(int32_t newSize) {
    274     int32_t i;
    275     if (newSize < 0) {
    276         return;
    277     }
    278     if (newSize > count) {
    279         UErrorCode ec = U_ZERO_ERROR;
    280         if (!ensureCapacity(newSize, ec)) {
    281             return;
    282         }
    283         for (i=count; i<newSize; ++i) {
    284             elements[i] = 0;
    285         }
    286     }
    287     count = newSize;
    288 }
    289 
    290 
    291 
    292 
    293 /**
    294  * Insert the given integer into this vector at its sorted position
    295  * as defined by 'compare'.  The current elements are assumed to
    296  * be sorted already.
    297  */
    298 void UVector32::sortedInsert(int32_t tok, UErrorCode& ec) {
    299     // Perform a binary search for the location to insert tok at.  Tok
    300     // will be inserted between two elements a and b such that a <=
    301     // tok && tok < b, where there is a 'virtual' elements[-1] always
    302     // less than tok and a 'virtual' elements[count] always greater
    303     // than tok.
    304     int32_t min = 0, max = count;
    305     while (min != max) {
    306         int32_t probe = (min + max) / 2;
    307         //int8_t c = (*compare)(elements[probe], tok);
    308         //if (c > 0) {
    309         if (elements[probe] > tok) {
    310             max = probe;
    311         } else {
    312             // assert(c <= 0);
    313             min = probe + 1;
    314         }
    315     }
    316     if (ensureCapacity(count + 1, ec)) {
    317         for (int32_t i=count; i>min; --i) {
    318             elements[i] = elements[i-1];
    319         }
    320         elements[min] = tok;
    321         ++count;
    322     }
    323 }
    324 
    325 
    326 
    327 
    328 
    329 U_NAMESPACE_END
    330 
    331