X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/46f4442e9a5a4f3b98b7c1083586332f6a8a99a4..ef6cf650f4a75c3f97de06b51fa104f2069b9ea2:/icuSources/common/uvector.cpp diff --git a/icuSources/common/uvector.cpp b/icuSources/common/uvector.cpp index 2c9efbc2..d8a4283d 100644 --- a/icuSources/common/uvector.cpp +++ b/icuSources/common/uvector.cpp @@ -1,7 +1,7 @@ /* ****************************************************************************** -* Copyright (C) 1999-2004, International Business Machines Corporation and * -* others. All Rights Reserved. * +* Copyright (C) 1999-2013, International Business Machines Corporation and +* others. All Rights Reserved. ****************************************************************************** * Date Name Description * 10/22/99 alan Creation. @@ -10,10 +10,12 @@ #include "uvector.h" #include "cmemory.h" +#include "uarrsort.h" +#include "uelement.h" U_NAMESPACE_BEGIN -#define DEFUALT_CAPACITY 8 +#define DEFAULT_CAPACITY 8 /* * Constants for hinting whether a key is an integer @@ -32,7 +34,7 @@ UVector::UVector(UErrorCode &status) : deleter(0), comparer(0) { - _init(DEFUALT_CAPACITY, status); + _init(DEFAULT_CAPACITY, status); } UVector::UVector(int32_t initialCapacity, UErrorCode &status) : @@ -45,17 +47,17 @@ UVector::UVector(int32_t initialCapacity, UErrorCode &status) : _init(initialCapacity, status); } -UVector::UVector(UObjectDeleter *d, UKeyComparator *c, UErrorCode &status) : +UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status) : count(0), capacity(0), elements(0), deleter(d), comparer(c) { - _init(DEFUALT_CAPACITY, status); + _init(DEFAULT_CAPACITY, status); } -UVector::UVector(UObjectDeleter *d, UKeyComparator *c, int32_t initialCapacity, UErrorCode &status) : +UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status) : count(0), capacity(0), elements(0), @@ -69,11 +71,11 @@ void UVector::_init(int32_t initialCapacity, UErrorCode &status) { if (U_FAILURE(status)) { return; } - // Fix bogus initialCapacity values; avoid malloc(0) - if (initialCapacity < 1) { - initialCapacity = DEFUALT_CAPACITY; + // Fix bogus initialCapacity values; avoid malloc(0) and integer overflow + if ((initialCapacity < 1) || (initialCapacity > (int32_t)(INT32_MAX / sizeof(UElement)))) { + initialCapacity = DEFAULT_CAPACITY; } - elements = (UHashTok *)uprv_malloc(sizeof(UHashTok)*initialCapacity); + elements = (UElement *)uprv_malloc(sizeof(UElement)*initialCapacity); if (elements == 0) { status = U_MEMORY_ALLOCATION_ERROR; } else { @@ -91,7 +93,7 @@ UVector::~UVector() { * Assign this object to another (make this a copy of 'other'). * Use the 'assign' function to assign each element. */ -void UVector::assign(const UVector& other, UTokenAssigner *assign, UErrorCode &ec) { +void UVector::assign(const UVector& other, UElementAssigner *assign, UErrorCode &ec) { if (ensureCapacity(other.count, ec)) { setSize(other.count, ec); if (U_SUCCESS(ec)) { @@ -271,7 +273,7 @@ UBool UVector::equals(const UVector &other) const { } } } else { - UHashTok key; + UElement key; for (i=0; i (INT32_MAX - 1) / 2) { // integer overflow check + status = U_ILLEGAL_ARGUMENT_ERROR; + return FALSE; + } int32_t newCap = capacity * 2; if (newCap < minimumCapacity) { newCap = minimumCapacity; } - UHashTok* newElems = (UHashTok *)uprv_realloc(elements, sizeof(UHashTok)*newCap); + if (newCap > (int32_t)(INT32_MAX / sizeof(UElement))) { // integer overflow check + // We keep the original memory contents on bad minimumCapacity. + status = U_ILLEGAL_ARGUMENT_ERROR; + return FALSE; + } + UElement* newElems = (UElement *)uprv_realloc(elements, sizeof(UElement)*newCap); if (newElems == NULL) { - // We keep the original contents on the memory failure on realloc. + // We keep the original contents on the memory failure on realloc or bad minimumCapacity. status = U_MEMORY_ALLOCATION_ERROR; return FALSE; } @@ -357,7 +372,7 @@ void UVector::setSize(int32_t newSize, UErrorCode &status) { if (!ensureCapacity(newSize, status)) { return; } - UHashTok empty; + UElement empty; empty.pointer = NULL; empty.integer = 0; for (i=count; i 0) { max = probe; } else { @@ -461,10 +476,90 @@ void UVector::sortedInsert(UHashTok tok, USortComparator *compare, UErrorCode& e for (int32_t i=count; i>min; --i) { elements[i] = elements[i-1]; } - elements[min] = tok; + elements[min] = e; ++count; } } +/** + * Array sort comparator function. + * Used from UVector::sort() + * Conforms to function signature required for uprv_sortArray(). + * This function is essentially just a wrapper, to make a + * UVector style comparator function usable with uprv_sortArray(). + * + * The context pointer to this function is a pointer back + * (with some extra indirection) to the user supplied comparator. + * + */ +static int32_t U_CALLCONV +sortComparator(const void *context, const void *left, const void *right) { + UElementComparator *compare = *static_cast(context); + UElement e1 = *static_cast(left); + UElement e2 = *static_cast(right); + int32_t result = (*compare)(e1, e2); + return result; +} + + +/** + * Array sort comparison function for use from UVector::sorti() + * Compares int32_t vector elements. + */ +static int32_t U_CALLCONV +sortiComparator(const void * /*context */, const void *left, const void *right) { + const UElement *e1 = static_cast(left); + const UElement *e2 = static_cast(right); + int32_t result = e1->integer < e2->integer? -1 : + e1->integer == e2->integer? 0 : 1; + return result; +} + +/** + * Sort the vector, assuming it constains ints. + * (A more general sort would take a comparison function, but it's + * not clear whether UVector's UElementComparator or + * UComparator from uprv_sortAray would be more appropriate.) + */ +void UVector::sorti(UErrorCode &ec) { + if (U_SUCCESS(ec)) { + uprv_sortArray(elements, count, sizeof(UElement), + sortiComparator, NULL, FALSE, &ec); + } +} + + +/** + * Sort with a user supplied comparator. + * + * The comparator function handling is confusing because the function type + * for UVector (as defined for sortedInsert()) is different from the signature + * required by uprv_sortArray(). This is handled by passing the + * the UVector sort function pointer via the context pointer to a + * sortArray() comparator function, which can then call back to + * the original user functtion. + * + * An additional twist is that it's not safe to pass a pointer-to-function + * as a (void *) data pointer, so instead we pass a (data) pointer to a + * pointer-to-function variable. + */ +void UVector::sort(UElementComparator *compare, UErrorCode &ec) { + if (U_SUCCESS(ec)) { + uprv_sortArray(elements, count, sizeof(UElement), + sortComparator, &compare, FALSE, &ec); + } +} + + +/** + * Stable sort with a user supplied comparator of type UComparator. + */ +void UVector::sortWithUComparator(UComparator *compare, const void *context, UErrorCode &ec) { + if (U_SUCCESS(ec)) { + uprv_sortArray(elements, count, sizeof(UElement), + compare, context, TRUE, &ec); + } +} + U_NAMESPACE_END