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