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