1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 2002-2016, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
10 * file name: uenumtst.c
12 * tab size: 8 (not used)
15 * created on: 2002jul08
16 * created by: Vladimir Weinstein
23 #include "unicode/ustring.h"
25 static char quikBuf
[256];
26 static char* quikU2C(const UChar
* str
, int32_t len
) {
27 u_UCharsToChars(str
, quikBuf
, len
);
32 static const char* test1
[] = {
39 struct chArrayContext
{
47 typedef struct chArrayContext chArrayContext
;
49 #define cont ((chArrayContext *)en->context)
51 static void U_CALLCONV
52 chArrayClose(UEnumeration
*en
) {
53 if(cont
->currUChar
!= NULL
) {
54 free(cont
->currUChar
);
55 cont
->currUChar
= NULL
;
60 static int32_t U_CALLCONV
61 chArrayCount(UEnumeration
*en
, UErrorCode
*status
) {
62 return cont
->maxIndex
;
65 static const UChar
* U_CALLCONV
66 chArrayUNext(UEnumeration
*en
, int32_t *resultLength
, UErrorCode
*status
) {
67 if(cont
->currIndex
>= cont
->maxIndex
) {
71 if(cont
->currUChar
== NULL
) {
72 cont
->currUChar
= (UChar
*)malloc(1024*sizeof(UChar
));
75 cont
->currChar
= (cont
->array
)[cont
->currIndex
];
76 *resultLength
= (int32_t)strlen(cont
->currChar
);
77 u_charsToUChars(cont
->currChar
, cont
->currUChar
, *resultLength
);
79 return cont
->currUChar
;
82 static const char* U_CALLCONV
83 chArrayNext(UEnumeration
*en
, int32_t *resultLength
, UErrorCode
*status
) {
84 if(cont
->currIndex
>= cont
->maxIndex
) {
88 cont
->currChar
= (cont
->array
)[cont
->currIndex
];
89 *resultLength
= (int32_t)strlen(cont
->currChar
);
91 return cont
->currChar
;
94 static void U_CALLCONV
95 chArrayReset(UEnumeration
*en
, UErrorCode
*status
) {
99 chArrayContext myCont
= {
105 UEnumeration chEnum
= {
115 static const UEnumeration emptyEnumerator
= {
125 static const UEnumeration emptyPartialEnumerator
= {
135 /********************************************************************/
136 static const UChar _first
[] = {102,105,114,115,116,0}; /* "first" */
137 static const UChar _second
[]= {115,101,99,111,110,100,0}; /* "second" */
138 static const UChar _third
[] = {116,104,105,114,100,0}; /* "third" */
139 static const UChar _fourth
[]= {102,111,117,114,116,104,0};/* "fourth" */
141 static const UChar
* test2
[] = {
142 _first
, _second
, _third
, _fourth
145 struct uchArrayContext
{
152 typedef struct uchArrayContext uchArrayContext
;
154 #define ucont ((uchArrayContext *)en->context)
156 static void U_CALLCONV
157 uchArrayClose(UEnumeration
*en
) {
161 static int32_t U_CALLCONV
162 uchArrayCount(UEnumeration
*en
, UErrorCode
*status
) {
163 return ucont
->maxIndex
;
166 static const UChar
* U_CALLCONV
167 uchArrayUNext(UEnumeration
*en
, int32_t *resultLength
, UErrorCode
*status
) {
168 if(ucont
->currIndex
>= ucont
->maxIndex
) {
172 ucont
->currUChar
= (ucont
->array
)[ucont
->currIndex
];
173 *resultLength
= u_strlen(ucont
->currUChar
);
175 return ucont
->currUChar
;
178 static void U_CALLCONV
179 uchArrayReset(UEnumeration
*en
, UErrorCode
*status
) {
180 ucont
->currIndex
= 0;
183 uchArrayContext myUCont
= {
188 UEnumeration uchEnum
= {
198 /********************************************************************/
200 static UEnumeration
*getchArrayEnum(const char** source
, int32_t size
) {
201 UEnumeration
*en
= (UEnumeration
*)malloc(sizeof(UEnumeration
));
202 memcpy(en
, &chEnum
, sizeof(UEnumeration
));
203 cont
->array
= (char **)source
;
204 cont
->maxIndex
= size
;
208 static void EnumerationTest(void) {
209 UErrorCode status
= U_ZERO_ERROR
;
211 UEnumeration
*en
= getchArrayEnum(test1
, UPRV_LENGTHOF(test1
));
212 const char *string
= NULL
;
213 const UChar
*uString
= NULL
;
214 while ((string
= uenum_next(en
, &len
, &status
))) {
215 log_verbose("read \"%s\", length %i\n", string
, len
);
217 uenum_reset(en
, &status
);
218 while ((uString
= uenum_unext(en
, &len
, &status
))) {
219 log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString
, len
), len
);
225 static void EmptyEnumerationTest(void) {
226 UErrorCode status
= U_ZERO_ERROR
;
227 UEnumeration
*emptyEnum
= uprv_malloc(sizeof(UEnumeration
));
229 uprv_memcpy(emptyEnum
, &emptyEnumerator
, sizeof(UEnumeration
));
230 if (uenum_count(emptyEnum
, &status
) != -1 || status
!= U_UNSUPPORTED_ERROR
) {
231 log_err("uenum_count failed\n");
233 status
= U_ZERO_ERROR
;
234 if (uenum_next(emptyEnum
, NULL
, &status
) != NULL
|| status
!= U_UNSUPPORTED_ERROR
) {
235 log_err("uenum_next failed\n");
237 status
= U_ZERO_ERROR
;
238 if (uenum_unext(emptyEnum
, NULL
, &status
) != NULL
|| status
!= U_UNSUPPORTED_ERROR
) {
239 log_err("uenum_unext failed\n");
241 status
= U_ZERO_ERROR
;
242 uenum_reset(emptyEnum
, &status
);
243 if (status
!= U_UNSUPPORTED_ERROR
) {
244 log_err("uenum_reset failed\n");
246 uenum_close(emptyEnum
);
248 status
= U_ZERO_ERROR
;
249 if (uenum_next(NULL
, NULL
, &status
) != NULL
|| status
!= U_ZERO_ERROR
) {
250 log_err("uenum_next(NULL) failed\n");
252 status
= U_ZERO_ERROR
;
253 if (uenum_unext(NULL
, NULL
, &status
) != NULL
|| status
!= U_ZERO_ERROR
) {
254 log_err("uenum_unext(NULL) failed\n");
256 status
= U_ZERO_ERROR
;
257 uenum_reset(NULL
, &status
);
258 if (status
!= U_ZERO_ERROR
) {
259 log_err("uenum_reset(NULL) failed\n");
262 emptyEnum
= uprv_malloc(sizeof(UEnumeration
));
263 uprv_memcpy(emptyEnum
, &emptyPartialEnumerator
, sizeof(UEnumeration
));
264 status
= U_ZERO_ERROR
;
265 if (uenum_unext(emptyEnum
, NULL
, &status
) != NULL
|| status
!= U_UNSUPPORTED_ERROR
) {
266 log_err("partial uenum_unext failed\n");
268 uenum_close(emptyEnum
);
271 static UEnumeration
*getuchArrayEnum(const UChar
** source
, int32_t size
) {
272 UEnumeration
*en
= (UEnumeration
*)malloc(sizeof(UEnumeration
));
273 memcpy(en
, &uchEnum
, sizeof(UEnumeration
));
274 ucont
->array
= (UChar
**)source
;
275 ucont
->maxIndex
= size
;
279 static void DefaultNextTest(void) {
280 UErrorCode status
= U_ZERO_ERROR
;
282 UEnumeration
*en
= getuchArrayEnum(test2
, UPRV_LENGTHOF(test2
));
283 const char *string
= NULL
;
284 const UChar
*uString
= NULL
;
285 while ((uString
= uenum_unext(en
, &len
, &status
))) {
286 log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString
, len
), len
);
288 if (U_FAILURE(status
)) {
289 log_err("FAIL: uenum_unext => %s\n", u_errorName(status
));
291 uenum_reset(en
, &status
);
292 while ((string
= uenum_next(en
, &len
, &status
))) {
293 log_verbose("read \"%s\", length %i\n", string
, len
);
295 if (U_FAILURE(status
)) {
296 log_err("FAIL: uenum_next => %s\n", u_errorName(status
));
302 static void verifyEnumeration(int line
, UEnumeration
*u
, const char * const * compareToChar
, const UChar
* const * compareToUChar
, int32_t expect_count
) {
303 UErrorCode status
= U_ZERO_ERROR
;
304 int32_t got_count
,i
,len
;
308 log_verbose("%s:%d: verifying enumeration..\n", __FILE__
, line
);
310 uenum_reset(u
, &status
);
311 if(U_FAILURE(status
)) {
312 log_err("%s:%d: FAIL: could not reset char strings enumeration: %s\n", __FILE__
, line
, u_errorName(status
));
316 got_count
= uenum_count(u
, &status
);
317 if(U_FAILURE(status
)) {
318 log_err("%s:%d: FAIL: could not count char strings enumeration: %s\n", __FILE__
, line
, u_errorName(status
));
322 if(got_count
!=expect_count
) {
323 log_err("%s:%d: FAIL: expect count %d got %d\n", __FILE__
, line
, expect_count
, got_count
);
325 log_verbose("%s:%d: OK: got count %d\n", __FILE__
, line
, got_count
);
328 if(compareToChar
!=NULL
) { /* else, not invariant */
329 for(i
=0;i
<got_count
;i
++) {
330 c
= uenum_next(u
,&len
, &status
);
331 if(U_FAILURE(status
)) {
332 log_err("%s:%d: FAIL: could not iterate to next after %d: %s\n", __FILE__
, line
, i
, u_errorName(status
));
336 log_err("%s:%d: FAIL: got NULL for next after %d: %s\n", __FILE__
, line
, i
, u_errorName(status
));
340 if(strcmp(c
,compareToChar
[i
])) {
341 log_err("%s:%d: FAIL: string #%d expected '%s' got '%s'\n", __FILE__
, line
, i
, compareToChar
[i
], c
);
343 log_verbose("%s:%d: OK: string #%d got '%s'\n", __FILE__
, line
, i
, c
);
346 if(len
!=strlen(compareToChar
[i
])) {
347 log_err("%s:%d: FAIL: string #%d expected len %d got %d\n", __FILE__
, line
, i
, strlen(compareToChar
[i
]), len
);
349 log_verbose("%s:%d: OK: string #%d got len %d\n", __FILE__
, line
, i
, len
);
355 uenum_reset(u
, &status
);
356 if(U_FAILURE(status
)) {
357 log_err("%s:%d: FAIL: could not reset again char strings enumeration: %s\n", __FILE__
, line
, u_errorName(status
));
361 for(i
=0;i
<got_count
;i
++) {
362 const UChar
*ustr
= uenum_unext(u
,&len
, &status
);
363 if(U_FAILURE(status
)) {
364 log_err("%s:%d: FAIL: could not iterate to unext after %d: %s\n", __FILE__
, line
, i
, u_errorName(status
));
368 log_err("%s:%d: FAIL: got NULL for unext after %d: %s\n", __FILE__
, line
, i
, u_errorName(status
));
371 if(compareToChar
!=NULL
) {
372 u_charsToUChars(compareToChar
[i
], buf
, (int32_t)strlen(compareToChar
[i
])+1);
373 if(u_strncmp(ustr
,buf
,len
)) {
375 log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__
, line
, i
, compareToChar
[i
], austrdup(ustr
));
376 for(j
=0;ustr
[j
]&&buf
[j
];j
++) {
377 log_verbose(" @ %d\t<U+%04X> vs <U+%04X>\n", j
, ustr
[j
],buf
[j
]);
380 log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__
, line
, i
, compareToChar
[i
]);
383 if(len
!=strlen(compareToChar
[i
])) {
384 log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__
, line
, i
, strlen(compareToChar
[i
]), len
);
386 log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__
, line
, i
, len
);
390 if(compareToUChar
!=NULL
) {
391 if(u_strcmp(ustr
,compareToUChar
[i
])) {
393 log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__
, line
, i
, austrdup(compareToUChar
[i
]), austrdup(ustr
));
394 for(j
=0;ustr
[j
]&&compareToUChar
[j
];j
++) {
395 log_verbose(" @ %d\t<U+%04X> vs <U+%04X>\n", j
, ustr
[j
],compareToUChar
[j
]);
398 log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__
, line
, i
, austrdup(compareToUChar
[i
]));
401 if(len
!=u_strlen(compareToUChar
[i
])) {
402 log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__
, line
, i
, u_strlen(compareToUChar
[i
]), len
);
404 log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__
, line
, i
, len
);
414 static void TestCharStringsEnumeration(void) {
415 UErrorCode status
= U_ZERO_ERROR
;
417 /* //! [uenum_openCharStringsEnumeration] */
418 const char* strings
[] = { "Firstly", "Secondly", "Thirdly", "Fourthly" };
419 UEnumeration
*u
= uenum_openCharStringsEnumeration(strings
, 4, &status
);
420 /* //! [uenum_openCharStringsEnumeration] */
421 if(U_FAILURE(status
)) {
422 log_err("FAIL: could not open char strings enumeration: %s\n", u_errorName(status
));
426 verifyEnumeration(__LINE__
, u
, strings
, NULL
, 4);
431 static void TestUCharStringsEnumeration(void) {
432 UErrorCode status
= U_ZERO_ERROR
;
433 /* //! [uenum_openUCharStringsEnumeration] */
434 static const UChar nko_1
[] = {0x07c1,0}, nko_2
[] = {0x07c2,0}, nko_3
[] = {0x07c3,0}, nko_4
[] = {0x07c4,0};
435 static const UChar
* ustrings
[] = { nko_1
, nko_2
, nko_3
, nko_4
};
436 UEnumeration
*u
= uenum_openUCharStringsEnumeration(ustrings
, 4, &status
);
437 /* //! [uenum_openUCharStringsEnumeration] */
438 if(U_FAILURE(status
)) {
439 log_err("FAIL: could not open uchar strings enumeration: %s\n", u_errorName(status
));
443 verifyEnumeration(__LINE__
, u
, NULL
, ustrings
, 4);
447 u
= uenum_openUCharStringsEnumeration(test2
, 4, &status
);
448 if(U_FAILURE(status
)) {
449 log_err("FAIL: could not reopen uchar strings enumeration: %s\n", u_errorName(status
));
452 verifyEnumeration(__LINE__
, u
, test1
, NULL
, 4); /* same string */
457 void addEnumerationTest(TestNode
** root
);
459 void addEnumerationTest(TestNode
** root
)
461 addTest(root
, &EnumerationTest
, "tsutil/uenumtst/EnumerationTest");
462 addTest(root
, &EmptyEnumerationTest
, "tsutil/uenumtst/EmptyEnumerationTest");
463 addTest(root
, &DefaultNextTest
, "tsutil/uenumtst/DefaultNextTest");
464 addTest(root
, &TestCharStringsEnumeration
, "tsutil/uenumtst/TestCharStringsEnumeration");
465 addTest(root
, &TestUCharStringsEnumeration
, "tsutil/uenumtst/TestUCharStringsEnumeration");