X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b75a7d8f3b4adbae880cab104ce2c6a50eee4db2..a01113dcd0f39d5da295ef82785beff9ed86fe38:/icuSources/common/ustrenum.cpp diff --git a/icuSources/common/ustrenum.cpp b/icuSources/common/ustrenum.cpp index 2fe2ef1a..ed23eaa2 100644 --- a/icuSources/common/ustrenum.cpp +++ b/icuSources/common/ustrenum.cpp @@ -1,6 +1,8 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ********************************************************************** -* Copyright (c) 2002, International Business Machines +* Copyright (c) 2002-2014, International Business Machines * Corporation and others. All Rights Reserved. ********************************************************************** * Author: Alan Liu @@ -8,14 +10,180 @@ * Since: ICU 2.4 ********************************************************************** */ +#include "utypeinfo.h" // for 'typeid' to work + #include "unicode/ustring.h" #include "unicode/strenum.h" +#include "unicode/putil.h" #include "uenumimp.h" #include "ustrenum.h" #include "cstring.h" #include "cmemory.h" +#include "uassert.h" + +U_NAMESPACE_BEGIN +// StringEnumeration implementation ---------------------------------------- *** + +StringEnumeration::StringEnumeration() + : chars(charsBuffer), charsCapacity(sizeof(charsBuffer)) { +} + +StringEnumeration::~StringEnumeration() { + if (chars != NULL && chars != charsBuffer) { + uprv_free(chars); + } +} + +// StringEnumeration base class clone() default implementation, does not clone +StringEnumeration * +StringEnumeration::clone() const { + return NULL; +} + +const char * +StringEnumeration::next(int32_t *resultLength, UErrorCode &status) { + const UnicodeString *s=snext(status); + if(U_SUCCESS(status) && s!=NULL) { + unistr=*s; + ensureCharsCapacity(unistr.length()+1, status); + if(U_SUCCESS(status)) { + if(resultLength!=NULL) { + *resultLength=unistr.length(); + } + unistr.extract(0, INT32_MAX, chars, charsCapacity, US_INV); + return chars; + } + } + + return NULL; +} + +const UChar * +StringEnumeration::unext(int32_t *resultLength, UErrorCode &status) { + const UnicodeString *s=snext(status); + if(U_SUCCESS(status) && s!=NULL) { + unistr=*s; + if(resultLength!=NULL) { + *resultLength=unistr.length(); + } + return unistr.getTerminatedBuffer(); + } + + return NULL; +} + +const UnicodeString * +StringEnumeration::snext(UErrorCode &status) { + int32_t length; + const char *s=next(&length, status); + return setChars(s, length, status); +} + +void +StringEnumeration::ensureCharsCapacity(int32_t capacity, UErrorCode &status) { + if(U_SUCCESS(status) && capacity>charsCapacity) { + if(capacity<(charsCapacity+charsCapacity/2)) { + // avoid allocation thrashing + capacity=charsCapacity+charsCapacity/2; + } + if(chars!=charsBuffer) { + uprv_free(chars); + } + chars=(char *)uprv_malloc(capacity); + if(chars==NULL) { + chars=charsBuffer; + charsCapacity=sizeof(charsBuffer); + status=U_MEMORY_ALLOCATION_ERROR; + } else { + charsCapacity=capacity; + } + } +} + +UnicodeString * +StringEnumeration::setChars(const char *s, int32_t length, UErrorCode &status) { + if(U_SUCCESS(status) && s!=NULL) { + if(length<0) { + length=(int32_t)uprv_strlen(s); + } + + UChar *buffer=unistr.getBuffer(length+1); + if(buffer!=NULL) { + u_charsToUChars(s, buffer, length); + buffer[length]=0; + unistr.releaseBuffer(length); + return &unistr; + } else { + status=U_MEMORY_ALLOCATION_ERROR; + } + } + + return NULL; +} +UBool +StringEnumeration::operator==(const StringEnumeration& that)const { + return typeid(*this) == typeid(that); +} -#define THIS(en) ((StringEnumeration*)(en->context)) +UBool +StringEnumeration::operator!=(const StringEnumeration& that)const { + return !operator==(that); +} + +// UStringEnumeration implementation --------------------------------------- *** + +UStringEnumeration * U_EXPORT2 +UStringEnumeration::fromUEnumeration( + UEnumeration *uenumToAdopt, UErrorCode &status) { + if (U_FAILURE(status)) { + uenum_close(uenumToAdopt); + return NULL; + } + UStringEnumeration *result = new UStringEnumeration(uenumToAdopt); + if (result == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + uenum_close(uenumToAdopt); + return NULL; + } + return result; +} + +UStringEnumeration::UStringEnumeration(UEnumeration* _uenum) : + uenum(_uenum) { + U_ASSERT(_uenum != 0); +} + +UStringEnumeration::~UStringEnumeration() { + uenum_close(uenum); +} + +int32_t UStringEnumeration::count(UErrorCode& status) const { + return uenum_count(uenum, &status); +} + +const char *UStringEnumeration::next(int32_t *resultLength, UErrorCode &status) { + return uenum_next(uenum, resultLength, &status); +} + +const UnicodeString* UStringEnumeration::snext(UErrorCode& status) { + int32_t length; + const UChar* str = uenum_unext(uenum, &length, &status); + if (str == 0 || U_FAILURE(status)) { + return 0; + } + return &unistr.setTo(str, length); +} + +void UStringEnumeration::reset(UErrorCode& status) { + uenum_reset(uenum, &status); +} + +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration) +U_NAMESPACE_END + +// C wrapper --------------------------------------------------------------- *** + +#define THIS(en) ((icu::StringEnumeration*)(en->context)) U_CDECL_BEGIN @@ -74,7 +242,7 @@ ustrenum_reset(UEnumeration* en, * Pseudo-vtable for UEnumeration wrapper around StringEnumeration. * The StringEnumeration pointer will be stored in 'context'. */ -static const UEnumeration TEMPLATE = { +static const UEnumeration USTRENUM_VT = { NULL, NULL, // store StringEnumeration pointer here ustrenum_close, @@ -92,14 +260,14 @@ U_CDECL_END * delete it (regardless of error status). */ U_CAPI UEnumeration* U_EXPORT2 -uenum_openStringEnumeration(StringEnumeration* adopted, UErrorCode* ec) { +uenum_openFromStringEnumeration(icu::StringEnumeration* adopted, UErrorCode* ec) { UEnumeration* result = NULL; if (U_SUCCESS(*ec) && adopted != NULL) { result = (UEnumeration*) uprv_malloc(sizeof(UEnumeration)); if (result == NULL) { *ec = U_MEMORY_ALLOCATION_ERROR; } else { - uprv_memcpy(result, &TEMPLATE, sizeof(TEMPLATE)); + uprv_memcpy(result, &USTRENUM_VT, sizeof(USTRENUM_VT)); result->context = adopted; } } @@ -109,4 +277,122 @@ uenum_openStringEnumeration(StringEnumeration* adopted, UErrorCode* ec) { return result; } -//eof +// C wrapper --------------------------------------------------------------- *** + +U_CDECL_BEGIN + +typedef struct UCharStringEnumeration { + UEnumeration uenum; + int32_t index, count; +} UCharStringEnumeration; + +static void U_CALLCONV +ucharstrenum_close(UEnumeration* en) { + uprv_free(en); +} + +static int32_t U_CALLCONV +ucharstrenum_count(UEnumeration* en, + UErrorCode* /*ec*/) { + return ((UCharStringEnumeration*)en)->count; +} + +static const UChar* U_CALLCONV +ucharstrenum_unext(UEnumeration* en, + int32_t* resultLength, + UErrorCode* /*ec*/) { + UCharStringEnumeration *e = (UCharStringEnumeration*) en; + if (e->index >= e->count) { + return NULL; + } + const UChar* result = ((const UChar**)e->uenum.context)[e->index++]; + if (resultLength) { + *resultLength = (int32_t)u_strlen(result); + } + return result; +} + + +static const char* U_CALLCONV +ucharstrenum_next(UEnumeration* en, + int32_t* resultLength, + UErrorCode* /*ec*/) { + UCharStringEnumeration *e = (UCharStringEnumeration*) en; + if (e->index >= e->count) { + return NULL; + } + const char* result = ((const char**)e->uenum.context)[e->index++]; + if (resultLength) { + *resultLength = (int32_t)uprv_strlen(result); + } + return result; +} + +static void U_CALLCONV +ucharstrenum_reset(UEnumeration* en, + UErrorCode* /*ec*/) { + ((UCharStringEnumeration*)en)->index = 0; +} + +static const UEnumeration UCHARSTRENUM_VT = { + NULL, + NULL, // store StringEnumeration pointer here + ucharstrenum_close, + ucharstrenum_count, + uenum_unextDefault, + ucharstrenum_next, + ucharstrenum_reset +}; + +static const UEnumeration UCHARSTRENUM_U_VT = { + NULL, + NULL, // store StringEnumeration pointer here + ucharstrenum_close, + ucharstrenum_count, + ucharstrenum_unext, + uenum_nextDefault, + ucharstrenum_reset +}; + +U_CDECL_END + +U_CAPI UEnumeration* U_EXPORT2 +uenum_openCharStringsEnumeration(const char* const strings[], int32_t count, + UErrorCode* ec) { + UCharStringEnumeration* result = NULL; + if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) { + result = (UCharStringEnumeration*) uprv_malloc(sizeof(UCharStringEnumeration)); + if (result == NULL) { + *ec = U_MEMORY_ALLOCATION_ERROR; + } else { + U_ASSERT((char*)result==(char*)(&result->uenum)); + uprv_memcpy(result, &UCHARSTRENUM_VT, sizeof(UCHARSTRENUM_VT)); + result->uenum.context = (void*)strings; + result->index = 0; + result->count = count; + } + } + return (UEnumeration*) result; +} + +U_CAPI UEnumeration* U_EXPORT2 +uenum_openUCharStringsEnumeration(const UChar* const strings[], int32_t count, + UErrorCode* ec) { + UCharStringEnumeration* result = NULL; + if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) { + result = (UCharStringEnumeration*) uprv_malloc(sizeof(UCharStringEnumeration)); + if (result == NULL) { + *ec = U_MEMORY_ALLOCATION_ERROR; + } else { + U_ASSERT((char*)result==(char*)(&result->uenum)); + uprv_memcpy(result, &UCHARSTRENUM_U_VT, sizeof(UCHARSTRENUM_U_VT)); + result->uenum.context = (void*)strings; + result->index = 0; + result->count = count; + } + } + return (UEnumeration*) result; +} + + +// end C Wrapper