michael@0: /* michael@0: ****************************************************************************** michael@0: * Copyright (C) 1999-2010, International Business Machines Corporation and * michael@0: * others. All Rights Reserved. * michael@0: ****************************************************************************** michael@0: * Date Name Description michael@0: * 10/22/99 alan Creation. michael@0: ********************************************************************** michael@0: */ michael@0: michael@0: #include "uvectr32.h" michael@0: #include "cmemory.h" michael@0: #include "putilimp.h" michael@0: michael@0: U_NAMESPACE_BEGIN michael@0: michael@0: #define DEFAULT_CAPACITY 8 michael@0: michael@0: /* michael@0: * Constants for hinting whether a key is an integer michael@0: * or a pointer. If a hint bit is zero, then the associated michael@0: * token is assumed to be an integer. This is needed for iSeries michael@0: */ michael@0: michael@0: UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector32) michael@0: michael@0: UVector32::UVector32(UErrorCode &status) : michael@0: count(0), michael@0: capacity(0), michael@0: maxCapacity(0), michael@0: elements(NULL) michael@0: { michael@0: _init(DEFAULT_CAPACITY, status); michael@0: } michael@0: michael@0: UVector32::UVector32(int32_t initialCapacity, UErrorCode &status) : michael@0: count(0), michael@0: capacity(0), michael@0: maxCapacity(0), michael@0: elements(0) michael@0: { michael@0: _init(initialCapacity, status); michael@0: } michael@0: michael@0: michael@0: michael@0: void UVector32::_init(int32_t initialCapacity, UErrorCode &status) { michael@0: // Fix bogus initialCapacity values; avoid malloc(0) michael@0: if (initialCapacity < 1) { michael@0: initialCapacity = DEFAULT_CAPACITY; michael@0: } michael@0: if (maxCapacity>0 && maxCapacity (int32_t)(INT32_MAX / sizeof(int32_t))) { michael@0: initialCapacity = uprv_min(DEFAULT_CAPACITY, maxCapacity); michael@0: } michael@0: elements = (int32_t *)uprv_malloc(sizeof(int32_t)*initialCapacity); michael@0: if (elements == 0) { michael@0: status = U_MEMORY_ALLOCATION_ERROR; michael@0: } else { michael@0: capacity = initialCapacity; michael@0: } michael@0: } michael@0: michael@0: UVector32::~UVector32() { michael@0: uprv_free(elements); michael@0: elements = 0; michael@0: } michael@0: michael@0: /** michael@0: * Assign this object to another (make this a copy of 'other'). michael@0: */ michael@0: void UVector32::assign(const UVector32& other, UErrorCode &ec) { michael@0: if (ensureCapacity(other.count, ec)) { michael@0: setSize(other.count); michael@0: for (int32_t i=0; iindex; --i) { michael@0: elements[i] = elements[i-1]; michael@0: } michael@0: elements[index] = elem; michael@0: ++count; michael@0: } michael@0: /* else index out of range */ michael@0: } michael@0: michael@0: UBool UVector32::containsAll(const UVector32& other) const { michael@0: for (int32_t i=0; i= 0) { michael@0: return FALSE; michael@0: } michael@0: } michael@0: return TRUE; michael@0: } michael@0: michael@0: UBool UVector32::removeAll(const UVector32& other) { michael@0: UBool changed = FALSE; michael@0: for (int32_t i=0; i= 0) { michael@0: removeElementAt(j); michael@0: changed = TRUE; michael@0: } michael@0: } michael@0: return changed; michael@0: } michael@0: michael@0: UBool UVector32::retainAll(const UVector32& other) { michael@0: UBool changed = FALSE; michael@0: for (int32_t j=size()-1; j>=0; --j) { michael@0: int32_t i = other.indexOf(elements[j]); michael@0: if (i < 0) { michael@0: removeElementAt(j); michael@0: changed = TRUE; michael@0: } michael@0: } michael@0: return changed; michael@0: } michael@0: michael@0: void UVector32::removeElementAt(int32_t index) { michael@0: if (index >= 0) { michael@0: for (int32_t i=index; icount != other.count) { michael@0: return FALSE; michael@0: } michael@0: for (i=0; i= minimumCapacity) { michael@0: return TRUE; michael@0: } michael@0: if (maxCapacity>0 && minimumCapacity>maxCapacity) { michael@0: status = U_BUFFER_OVERFLOW_ERROR; michael@0: return FALSE; michael@0: } michael@0: if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check michael@0: status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: return FALSE; michael@0: } michael@0: int32_t newCap = capacity * 2; michael@0: if (newCap < minimumCapacity) { michael@0: newCap = minimumCapacity; michael@0: } michael@0: if (maxCapacity > 0 && newCap > maxCapacity) { michael@0: newCap = maxCapacity; michael@0: } michael@0: if (newCap > (int32_t)(INT32_MAX / sizeof(int32_t))) { // integer overflow check michael@0: // We keep the original memory contents on bad minimumCapacity/maxCapacity. michael@0: status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: return FALSE; michael@0: } michael@0: int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*newCap); michael@0: if (newElems == NULL) { michael@0: // We keep the original contents on the memory failure on realloc. michael@0: status = U_MEMORY_ALLOCATION_ERROR; michael@0: return FALSE; michael@0: } michael@0: elements = newElems; michael@0: capacity = newCap; michael@0: return TRUE; michael@0: } michael@0: michael@0: void UVector32::setMaxCapacity(int32_t limit) { michael@0: U_ASSERT(limit >= 0); michael@0: if (limit < 0) { michael@0: limit = 0; michael@0: } michael@0: if (limit > (int32_t)(INT32_MAX / sizeof(int32_t))) { // integer overflow check for realloc michael@0: // Something is very wrong, don't realloc, leave capacity and maxCapacity unchanged michael@0: return; michael@0: } michael@0: maxCapacity = limit; michael@0: if (capacity <= maxCapacity || maxCapacity == 0) { michael@0: // Current capacity is within the new limit. michael@0: return; michael@0: } michael@0: michael@0: // New maximum capacity is smaller than the current size. michael@0: // Realloc the storage to the new, smaller size. michael@0: int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*maxCapacity); michael@0: if (newElems == NULL) { michael@0: // Realloc to smaller failed. michael@0: // Just keep what we had. No need to call it a failure. michael@0: return; michael@0: } michael@0: elements = newElems; michael@0: capacity = maxCapacity; michael@0: if (count > capacity) { michael@0: count = capacity; michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Change the size of this vector as follows: If newSize is smaller, michael@0: * then truncate the array, possibly deleting held elements for i >= michael@0: * newSize. If newSize is larger, grow the array, filling in new michael@0: * slots with NULL. michael@0: */ michael@0: void UVector32::setSize(int32_t newSize) { michael@0: int32_t i; michael@0: if (newSize < 0) { michael@0: return; michael@0: } michael@0: if (newSize > count) { michael@0: UErrorCode ec = U_ZERO_ERROR; michael@0: if (!ensureCapacity(newSize, ec)) { michael@0: return; michael@0: } michael@0: for (i=count; i 0) { michael@0: if (elements[probe] > tok) { michael@0: max = probe; michael@0: } else { michael@0: // assert(c <= 0); michael@0: min = probe + 1; michael@0: } michael@0: } michael@0: if (ensureCapacity(count + 1, ec)) { michael@0: for (int32_t i=count; i>min; --i) { michael@0: elements[i] = elements[i-1]; michael@0: } michael@0: elements[min] = tok; michael@0: ++count; michael@0: } michael@0: } michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: U_NAMESPACE_END michael@0: