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