diff --git a/icu4c/source/common/ustrenum.cpp b/icu4c/source/common/ustrenum.cpp index 2bf12bfe03b..0996b8d1d6c 100644 --- a/icu4c/source/common/ustrenum.cpp +++ b/icu4c/source/common/ustrenum.cpp @@ -14,6 +14,7 @@ #include "ustrenum.h" #include "cstring.h" #include "cmemory.h" +#include "uassert.h" // StringEnumeration implementation ---------------------------------------- *** @@ -109,6 +110,36 @@ StringEnumeration::setChars(const char *s, int32_t length, UErrorCode &status) { return NULL; } +// UStringEnumeration implementation --------------------------------------- *** + +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 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/*, StringEnumeration*/) + // C wrapper --------------------------------------------------------------- *** #define THIS(en) ((StringEnumeration*)(en->context)) @@ -170,7 +201,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, @@ -195,7 +226,7 @@ uenum_openStringEnumeration(StringEnumeration* adopted, UErrorCode* ec) { 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; } } @@ -205,4 +236,129 @@ uenum_openStringEnumeration(StringEnumeration* adopted, UErrorCode* ec) { return result; } +// 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 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 = 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 +}; + +U_CDECL_END + +U_CAPI UEnumeration* U_EXPORT2 +uenum_openCharStringsEnumeration(const char** 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 = strings; + result->index = 0; + result->count = count; + } + } + return (UEnumeration*) result; +} + +// The following has not been tested and is not used yet. [alan] +// +// // StringArrayEnumeration implementation ----------------------------------- *** +// +// StringArrayEnumeration::StringArrayEnumeration(const UChar** _strings, int32_t _count, +// UErrorCode& status) : +// strings(0), stringCount(-1), pos(0) { +// if (U_SUCCESS(status)) { +// if ((_count > 0 && _strings == 0) || +// (_count < 0)) { +// status = U_ILLEGAL_ARGUMENT_ERROR; +// } else { +// stringCount = _count; +// strings = _strings; +// } +// } +// } +// +// StringArrayEnumeration::~StringArrayEnumeration() { +// // nothing to do; strings is an alias +// } +// +// StringEnumeration *StringArrayEnumeration::clone() const { +// UErrorCode ec = U_ZERO_ERROR; +// StringEnumeration *e = new StringArrayEnumeration(strings, stringCount, ec); +// if (U_FAILURE(ec)) { +// delete e; +// e = NULL; +// } +// return e; +// } +// +// int32_t StringArrayEnumeration::count(UErrorCode& /*status*/) const { +// return stringCount; +// } +// +// const UnicodeString* StringArrayEnumeration::snext(UErrorCode& status) { +// if (U_FAILURE(status)) { +// return NULL; +// } +// if (pos < stringCount) { +// return &unistr.setTo(strings[pos++], -1); +// } else { +// return NULL; +// } +// } +// +// void StringArrayEnumeration::reset(UErrorCode& /*status*/) { +// pos = 0; +// } +// +// UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringArrayEnumeration/*, StringEnumeration*/) + //eof diff --git a/icu4c/source/common/ustrenum.h b/icu4c/source/common/ustrenum.h index ba3a135f9f4..4f9c20a7d97 100644 --- a/icu4c/source/common/ustrenum.h +++ b/icu4c/source/common/ustrenum.h @@ -22,6 +22,143 @@ U_CAPI UEnumeration* U_EXPORT2 uenum_openStringEnumeration(StringEnumeration* adopted, UErrorCode* ec); +/** + * Given an array of const char* strings (invariant chars only), + * return a UEnumeration. Must have strings[i] != 0 for i in + * 0..count-1. + */ +U_CAPI UEnumeration* U_EXPORT2 +uenum_openCharStringsEnumeration(const char** strings, int32_t count, + UErrorCode* ec); + +//---------------------------------------------------------------------- + +/** + * A wrapper to make a UEnumeration into a StringEnumeration. The + * wrapper adopts the UEnumeration is wraps. + */ +class U_COMMON_API UStringEnumeration : public StringEnumeration { + + public: + /** + * Constructor. This constructor adopts its UEnumeration + * argument. + * @param uenum a UEnumeration object. This object takes + * ownership of 'uenum' and will close it in its destructor. The + * caller must not call uenum_close on 'uenum' after calling this + * constructor. + */ + UStringEnumeration(UEnumeration* uenum); + + /** + * Destructor. This closes the UEnumeration passed in to the + * constructor. + */ + virtual ~UStringEnumeration(); + + /** + * Return the number of elements that the iterator traverses. + * @param status the error code. + * @return number of elements in the iterator. + */ + virtual int32_t count(UErrorCode& status) const; + + /** + * Returns the next element a UnicodeString*. If there are no + * more elements, returns NULL. + * @param status the error code. + * @return a pointer to the string, or NULL. + */ + virtual const UnicodeString* snext(UErrorCode& status); + + /** + * Resets the iterator. + * @param status the error code. + */ + virtual void reset(UErrorCode& status); + + /** + * ICU4C "poor man's RTTI", returns a UClassID for the actual ICU class. + */ + virtual UClassID getDynamicClassID() const; + + /** + * ICU4C "poor man's RTTI", returns a UClassID for this ICU class. + */ + static UClassID getStaticClassID(); + + private: + UEnumeration *uenum; // owned +}; + +//---------------------------------------------------------------------- + +// The following has not been tested and is not used yet. [alan] +// +// /** +// * A StringEnumeration over a fixed array of const UChar* strings. +// */ +// class U_COMMON_API StringArrayEnumeration : public StringEnumeration { +// +// public: +// /** +// * Constructor. +// * @param strings pointer to array of const UChar*. If 'count' == +// * 0, then this pointer is ignored. May be NULL if 'count' == 0. +// * @param count number of elements of strings, or 0. If 0, then +// * 'strings' is ignored. +// */ +// StringArrayEnumeration(const UChar** strings, int32_t count, +// UErrorCode& status); +// +// /** +// * Destructor. +// */ +// virtual ~StringArrayEnumeration(); +// +// /** +// * Clone this object. +// * @return a clone of this object +// */ +// virtual StringEnumeration *clone() const; +// +// /** +// * Return the number of elements that the iterator traverses. +// * @param status the error code. +// * @return number of elements in the iterator. +// */ +// virtual int32_t count(UErrorCode& status) const; +// +// /** +// * Returns the next element a UnicodeString*. If there are no +// * more elements, returns NULL. +// * @param status the error code. +// * @return a pointer to the string, or NULL. +// */ +// virtual const UnicodeString* snext(UErrorCode& status); +// +// /** +// * Resets the iterator. +// * @param status the error code. +// */ +// virtual void reset(UErrorCode& status); +// +// /** +// * ICU4C "poor man's RTTI", returns a UClassID for the actual ICU class. +// */ +// virtual UClassID getDynamicClassID() const; +// +// /** +// * ICU4C "poor man's RTTI", returns a UClassID for this ICU class. +// */ +// static UClassID getStaticClassID(); +// +// private: +// const UChar** strings; +// int32_t stringCount; +// int32_t pos; +// }; + /* _USTRENUM_H_ */ #endif /*eof*/