ICU-7197 add API for constructing UEnumerations.

X-SVN-Rev: 32137
This commit is contained in:
Steven R. Loomis 2012-08-09 00:04:51 +00:00
parent 9107a7bb38
commit b68d2f41fb
4 changed files with 241 additions and 12 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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<got_count;i++) {
c = uenum_next(u,&len, &status);
if(U_FAILURE(status)) {
log_err("%s:%d: FAIL: could not iterate to next after %d: %s\n", __FILE__, line, i, u_errorName(status));
return;
}
if(c==NULL) {
log_err("%s:%d: FAIL: got NULL for next after %d: %s\n", __FILE__, line, i, u_errorName(status));
return;
}
if(strcmp(c,compareToChar[i])) {
log_err("%s:%d: FAIL: string #%d expected '%s' got '%s'\n", __FILE__, line, i, compareToChar[i], c);
} else {
log_verbose("%s:%d: OK: string #%d got '%s'\n", __FILE__, line, i, c);
}
if(len!=strlen(compareToChar[i])) {
log_err("%s:%d: FAIL: string #%d expected len %d got %d\n", __FILE__, line, i, strlen(compareToChar[i]), len);
} else {
log_verbose("%s:%d: OK: string #%d got len %d\n", __FILE__, line, i, len);
}
}
}
/* now try U */
uenum_reset(u, &status);
if(U_FAILURE(status)) {
log_err("%s:%d: FAIL: could not reset again char strings enumeration: %s\n", __FILE__, line, u_errorName(status));
return;
}
for(i=0;i<got_count;i++) {
const UChar *ustr = uenum_unext(u,&len, &status);
if(U_FAILURE(status)) {
log_err("%s:%d: FAIL: could not iterate to unext after %d: %s\n", __FILE__, line, i, u_errorName(status));
return;
}
if(ustr==NULL) {
log_err("%s:%d: FAIL: got NULL for unext after %d: %s\n", __FILE__, line, i, u_errorName(status));
return;
}
if(compareToChar!=NULL) {
u_charsToUChars(compareToChar[i], buf, strlen(compareToChar[i])+1);
if(u_strncmp(ustr,buf,len)) {
int j;
log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__, line, i, compareToChar[i], austrdup(ustr));
for(j=0;ustr[j]&&buf[j];j++) {
log_verbose(" @ %d\t<U+%04X> vs <U+%04X>\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<U+%04X> vs <U+%04X>\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");
}