Home | History | Annotate | Download | only in common
      1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 ******************************************************************************
      5 * Copyright (C) 1999-2015, International Business Machines Corporation and
      6 * others. All Rights Reserved.
      7 ******************************************************************************
      8 */
      9 
     10 #include "uvectr64.h"
     11 #include "cmemory.h"
     12 #include "putilimp.h"
     13 
     14 U_NAMESPACE_BEGIN
     15 
     16 #define DEFAULT_CAPACITY 8
     17 
     18 /*
     19  * Constants for hinting whether a key is an integer
     20  * or a pointer.  If a hint bit is zero, then the associated
     21  * token is assumed to be an integer. This is needed for iSeries
     22  */
     23 
     24 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector64)
     25 
     26 UVector64::UVector64(UErrorCode &status) :
     27     count(0),
     28     capacity(0),
     29     maxCapacity(0),
     30     elements(NULL)
     31 {
     32     _init(DEFAULT_CAPACITY, status);
     33 }
     34 
     35 UVector64::UVector64(int32_t initialCapacity, UErrorCode &status) :
     36     count(0),
     37     capacity(0),
     38     maxCapacity(0),
     39     elements(0)
     40 {
     41     _init(initialCapacity, status);
     42 }
     43 
     44 
     45 
     46 void UVector64::_init(int32_t initialCapacity, UErrorCode &status) {
     47     // Fix bogus initialCapacity values; avoid malloc(0)
     48     if (initialCapacity < 1) {
     49         initialCapacity = DEFAULT_CAPACITY;
     50     }
     51     if (maxCapacity>0 && maxCapacity<initialCapacity) {
     52         initialCapacity = maxCapacity;
     53     }
     54     if (initialCapacity > (int32_t)(INT32_MAX / sizeof(int64_t))) {
     55         initialCapacity = uprv_min(DEFAULT_CAPACITY, maxCapacity);
     56     }
     57     elements = (int64_t *)uprv_malloc(sizeof(int64_t)*initialCapacity);
     58     if (elements == 0) {
     59         status = U_MEMORY_ALLOCATION_ERROR;
     60     } else {
     61         capacity = initialCapacity;
     62     }
     63 }
     64 
     65 UVector64::~UVector64() {
     66     uprv_free(elements);
     67     elements = 0;
     68 }
     69 
     70 /**
     71  * Assign this object to another (make this a copy of 'other').
     72  */
     73 void UVector64::assign(const UVector64& other, UErrorCode &ec) {
     74     if (ensureCapacity(other.count, ec)) {
     75         setSize(other.count);
     76         for (int32_t i=0; i<other.count; ++i) {
     77             elements[i] = other.elements[i];
     78         }
     79     }
     80 }
     81 
     82 
     83 UBool UVector64::operator==(const UVector64& other) {
     84     int32_t i;
     85     if (count != other.count) return FALSE;
     86     for (i=0; i<count; ++i) {
     87         if (elements[i] != other.elements[i]) {
     88             return FALSE;
     89         }
     90     }
     91     return TRUE;
     92 }
     93 
     94 
     95 void UVector64::setElementAt(int64_t elem, int32_t index) {
     96     if (0 <= index && index < count) {
     97         elements[index] = elem;
     98     }
     99     /* else index out of range */
    100 }
    101 
    102 void UVector64::insertElementAt(int64_t elem, int32_t index, UErrorCode &status) {
    103     // must have 0 <= index <= count
    104     if (0 <= index && index <= count && ensureCapacity(count + 1, status)) {
    105         for (int32_t i=count; i>index; --i) {
    106             elements[i] = elements[i-1];
    107         }
    108         elements[index] = elem;
    109         ++count;
    110     }
    111     /* else index out of range */
    112 }
    113 
    114 void UVector64::removeAllElements(void) {
    115     count = 0;
    116 }
    117 
    118 UBool UVector64::expandCapacity(int32_t minimumCapacity, UErrorCode &status) {
    119     if (U_FAILURE(status)) {
    120         return FALSE;
    121     }
    122     if (minimumCapacity < 0) {
    123         status = U_ILLEGAL_ARGUMENT_ERROR;
    124         return FALSE;
    125     }
    126     if (capacity >= minimumCapacity) {
    127         return TRUE;
    128     }
    129     if (maxCapacity>0 && minimumCapacity>maxCapacity) {
    130         status = U_BUFFER_OVERFLOW_ERROR;
    131         return FALSE;
    132     }
    133     if (capacity > (INT32_MAX - 1) / 2) {  // integer overflow check
    134         status = U_ILLEGAL_ARGUMENT_ERROR;
    135         return FALSE;
    136     }
    137     int32_t newCap = capacity * 2;
    138     if (newCap < minimumCapacity) {
    139         newCap = minimumCapacity;
    140     }
    141     if (maxCapacity > 0 && newCap > maxCapacity) {
    142         newCap = maxCapacity;
    143     }
    144     if (newCap > (int32_t)(INT32_MAX / sizeof(int64_t))) {  // integer overflow check
    145         // We keep the original memory contents on bad minimumCapacity/maxCapacity.
    146         status = U_ILLEGAL_ARGUMENT_ERROR;
    147         return FALSE;
    148     }
    149     int64_t* newElems = (int64_t *)uprv_realloc(elements, sizeof(int64_t)*newCap);
    150     if (newElems == NULL) {
    151         // We keep the original contents on the memory failure on realloc.
    152         status = U_MEMORY_ALLOCATION_ERROR;
    153         return FALSE;
    154     }
    155     elements = newElems;
    156     capacity = newCap;
    157     return TRUE;
    158 }
    159 
    160 void UVector64::setMaxCapacity(int32_t limit) {
    161     U_ASSERT(limit >= 0);
    162     if (limit < 0) {
    163         limit = 0;
    164     }
    165     if (limit > (int32_t)(INT32_MAX / sizeof(int64_t))) {  // integer overflow check for realloc
    166         //  Something is very wrong, don't realloc, leave capacity and maxCapacity unchanged
    167         return;
    168     }
    169     maxCapacity = limit;
    170     if (capacity <= maxCapacity || maxCapacity == 0) {
    171         // Current capacity is within the new limit.
    172         return;
    173     }
    174 
    175     // New maximum capacity is smaller than the current size.
    176     // Realloc the storage to the new, smaller size.
    177     int64_t* newElems = (int64_t *)uprv_realloc(elements, sizeof(int64_t)*maxCapacity);
    178     if (newElems == NULL) {
    179         // Realloc to smaller failed.
    180         //   Just keep what we had.  No need to call it a failure.
    181         return;
    182     }
    183     elements = newElems;
    184     capacity = maxCapacity;
    185     if (count > capacity) {
    186         count = capacity;
    187     }
    188 }
    189 
    190 /**
    191  * Change the size of this vector as follows: If newSize is smaller,
    192  * then truncate the array, possibly deleting held elements for i >=
    193  * newSize.  If newSize is larger, grow the array, filling in new
    194  * slots with NULL.
    195  */
    196 void UVector64::setSize(int32_t newSize) {
    197     int32_t i;
    198     if (newSize < 0) {
    199         return;
    200     }
    201     if (newSize > count) {
    202         UErrorCode ec = U_ZERO_ERROR;
    203         if (!ensureCapacity(newSize, ec)) {
    204             return;
    205         }
    206         for (i=count; i<newSize; ++i) {
    207             elements[i] = 0;
    208         }
    209     }
    210     count = newSize;
    211 }
    212 
    213 U_NAMESPACE_END
    214 
    215