diff --git a/icu4c/source/common/unicode/uenum.h b/icu4c/source/common/unicode/uenum.h index 21e82b2384a..393f4c4caf4 100644 --- a/icu4c/source/common/unicode/uenum.h +++ b/icu4c/source/common/unicode/uenum.h @@ -171,4 +171,39 @@ uenum_openFromStringEnumeration(icu::StringEnumeration* adopted, UErrorCode* ec) #endif +#ifndef U_HIDE_DRAFT_API +/** + * Given an array of const UChar* strings, return a UEnumeration. String pointers from 0..count-1 must not be null. + * Do not free or modify either the string array or the characters it points to until this object has been destroyed with uenum_close. + * \snippet test/cintltst/uenumtst.c uenum_openUCharStringsEnumeration + * @param strings array of const UChar* strings (each null terminated). All storage is owned by the caller. + * @param count length of the array + * @param ec error code + * @return the new UEnumeration object. Caller is responsible for calling uenum_close to free memory. + * @see uenum_close + * @draft ICU 50 + */ +U_CAPI UEnumeration* U_EXPORT2 +uenum_openUCharStringsEnumeration(const UChar* const strings[], int32_t count, + UErrorCode* ec); +#endif + +/* Note: next function is not hidden as draft, as it is used internally (it was formerly an internal function). */ + +/** + * Given an array of const char* strings (invariant chars only), return a UEnumeration. String pointers from 0..count-1 must not be null. + * Do not free or modify either the string array or the characters it points to until this object has been destroyed with uenum_close. + * \snippet test/cintltst/uenumtst.c uenum_openCharStringsEnumeration + * @param strings array of char* strings (each null terminated). All storage is owned by the caller. + * @param count length of the array + * @param ec error code + * @return the new UEnumeration object. Caller is responsible for calling uenum_close to free memory + * @see uenum_close + * @draft ICU 50 + */ +U_CAPI UEnumeration* U_EXPORT2 +uenum_openCharStringsEnumeration(const char* const strings[], int32_t count, + UErrorCode* ec); + + #endif diff --git a/icu4c/source/common/ustrenum.cpp b/icu4c/source/common/ustrenum.cpp index 3956615db31..01b6a6fbd10 100644 --- a/icu4c/source/common/ustrenum.cpp +++ b/icu4c/source/common/ustrenum.cpp @@ -270,6 +270,22 @@ ucharstrenum_count(UEnumeration* en, 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, @@ -301,10 +317,20 @@ static const UEnumeration UCHARSTRENUM_VT = { 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, +uenum_openCharStringsEnumeration(const char* const strings[], int32_t count, UErrorCode* ec) { UCharStringEnumeration* result = NULL; if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) { @@ -322,4 +348,24 @@ uenum_openCharStringsEnumeration(const char* const* strings, int32_t 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 diff --git a/icu4c/source/common/ustrenum.h b/icu4c/source/common/ustrenum.h index 21b168316b8..ef5863aed01 100644 --- a/icu4c/source/common/ustrenum.h +++ b/icu4c/source/common/ustrenum.h @@ -1,6 +1,6 @@ /* ********************************************************************** -* Copyright (c) 2002-2009, International Business Machines +* Copyright (c) 2002-2012, International Business Machines * Corporation and others. All Rights Reserved. ********************************************************************** * Author: Alan Liu @@ -14,15 +14,6 @@ #include "unicode/uenum.h" #include "unicode/strenum.h" -/** - * 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* const* strings, int32_t count, - UErrorCode* ec); - //---------------------------------------------------------------------- U_NAMESPACE_BEGIN diff --git a/icu4c/source/test/cintltst/uenumtst.c b/icu4c/source/test/cintltst/uenumtst.c index 2d9ed6c0ab8..a1772898030 100644 --- a/icu4c/source/test/cintltst/uenumtst.c +++ b/icu4c/source/test/cintltst/uenumtst.c @@ -1,7 +1,7 @@ /* ******************************************************************************* * -* Copyright (C) 2002-2003, International Business Machines +* Copyright (C) 2002-2012, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -297,6 +297,161 @@ static void DefaultNextTest(void) { uenum_close(en); } +static void verifyEnumeration(int line, UEnumeration *u, const char * const * compareToChar, const UChar * const * compareToUChar, int32_t expect_count) { + UErrorCode status = U_ZERO_ERROR; + int32_t got_count,i,len; + const char *c; + UChar buf[1024]; + + log_verbose("%s:%d: verifying enumeration..\n", __FILE__, line); + + uenum_reset(u, &status); + if(U_FAILURE(status)) { + log_err("%s:%d: FAIL: could not reset char strings enumeration: %s\n", __FILE__, line, u_errorName(status)); + return; + } + + got_count = uenum_count(u, &status); + if(U_FAILURE(status)) { + log_err("%s:%d: FAIL: could not count char strings enumeration: %s\n", __FILE__, line, u_errorName(status)); + return; + } + + if(got_count!=expect_count) { + log_err("%s:%d: FAIL: expect count %d got %d\n", __FILE__, line, expect_count, got_count); + } else { + log_verbose("%s:%d: OK: got count %d\n", __FILE__, line, got_count); + } + + if(compareToChar!=NULL) { /* else, not invariant */ + for(i=0;i vs \n", j, ustr[j],buf[j]); + } + } else { + log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, compareToChar[i]); + } + + if(len!=strlen(compareToChar[i])) { + log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, line, i, strlen(compareToChar[i]), len); + } else { + log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, len); + } + } + + if(compareToUChar!=NULL) { + if(u_strcmp(ustr,compareToUChar[i])) { + int j; + log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__, line, i, austrdup(compareToUChar[i]), austrdup(ustr)); + for(j=0;ustr[j]&&compareToUChar[j];j++) { + log_verbose(" @ %d\t vs \n", j, ustr[j],compareToUChar[j]); + } + } else { + log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, austrdup(compareToUChar[i])); + } + + if(len!=u_strlen(compareToUChar[i])) { + log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, line, i, u_strlen(compareToUChar[i]), len); + } else { + log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, len); + } + } + } +} + + + + + +static void TestCharStringsEnumeration(void) { + UErrorCode status = U_ZERO_ERROR; + + /* //! [uenum_openCharStringsEnumeration] */ + const char* strings[] = { "Firstly", "Secondly", "Thirdly", "Fourthly" }; + UEnumeration *u = uenum_openCharStringsEnumeration(strings, 4, &status); + /* //! [uenum_openCharStringsEnumeration] */ + if(U_FAILURE(status)) { + log_err("FAIL: could not open char strings enumeration: %s\n", u_errorName(status)); + return; + } + + verifyEnumeration(__LINE__, u, strings, NULL, 4); + + uenum_close(u); +} + +static void TestUCharStringsEnumeration(void) { + UErrorCode status = U_ZERO_ERROR; + /* //! [uenum_openUCharStringsEnumeration] */ + static const UChar nko_1[] = {0x07c1,0}, nko_2[] = {0x07c2}, nko_3[] = {0x07c3,0}, nko_4[] = {0x07c4,0}; + static const UChar* ustrings[] = { nko_1, nko_2, nko_3, nko_4 }; + UEnumeration *u = uenum_openUCharStringsEnumeration(ustrings, 4, &status); + /* //! [uenum_openUCharStringsEnumeration] */ + if(U_FAILURE(status)) { + log_err("FAIL: could not open uchar strings enumeration: %s\n", u_errorName(status)); + return; + } + + verifyEnumeration(__LINE__, u, NULL, ustrings, 4); + uenum_close(u); + + + u = uenum_openUCharStringsEnumeration(test2, 4, &status); + if(U_FAILURE(status)) { + log_err("FAIL: could not reopen uchar strings enumeration: %s\n", u_errorName(status)); + return; + } + verifyEnumeration(__LINE__, u, test1, NULL, 4); /* same string */ + uenum_close(u); + +} + void addEnumerationTest(TestNode** root); void addEnumerationTest(TestNode** root) @@ -304,4 +459,6 @@ void addEnumerationTest(TestNode** root) addTest(root, &EnumerationTest, "tsutil/uenumtst/EnumerationTest"); addTest(root, &EmptyEnumerationTest, "tsutil/uenumtst/EmptyEnumerationTest"); addTest(root, &DefaultNextTest, "tsutil/uenumtst/DefaultNextTest"); + addTest(root, &TestCharStringsEnumeration, "tsutil/uenumtst/TestCharStringsEnumeration"); + addTest(root, &TestUCharStringsEnumeration, "tsutil/uenumtst/TestUCharStringsEnumeration"); }