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 (void)status
; // suppress compiler warnings about unused variable
63 return cont
->maxIndex
;
66 static const UChar
* U_CALLCONV
67 chArrayUNext(UEnumeration
*en
, int32_t *resultLength
, UErrorCode
*status
) {
68 (void)status
; // suppress compiler warnings about unused variable
69 if(cont
->currIndex
>= cont
->maxIndex
) {
73 if(cont
->currUChar
== NULL
) {
74 cont
->currUChar
= (UChar
*)malloc(1024*sizeof(UChar
));
77 cont
->currChar
= (cont
->array
)[cont
->currIndex
];
78 *resultLength
= (int32_t)strlen(cont
->currChar
);
79 u_charsToUChars(cont
->currChar
, cont
->currUChar
, *resultLength
);
81 return cont
->currUChar
;
84 static const char* U_CALLCONV
85 chArrayNext(UEnumeration
*en
, int32_t *resultLength
, UErrorCode
*status
) {
86 (void)status
; // suppress compiler warnings about unused variable
87 if(cont
->currIndex
>= cont
->maxIndex
) {
91 cont
->currChar
= (cont
->array
)[cont
->currIndex
];
92 *resultLength
= (int32_t)strlen(cont
->currChar
);
94 return cont
->currChar
;
97 static void U_CALLCONV
98 chArrayReset(UEnumeration
*en
, UErrorCode
*status
) {
99 (void)status
; // suppress compiler warnings about unused variable
103 chArrayContext myCont
= {
109 UEnumeration chEnum
= {
119 static const UEnumeration emptyEnumerator
= {
129 static const UEnumeration emptyPartialEnumerator
= {
139 /********************************************************************/
140 static const UChar _first
[] = {102,105,114,115,116,0}; /* "first" */
141 static const UChar _second
[]= {115,101,99,111,110,100,0}; /* "second" */
142 static const UChar _third
[] = {116,104,105,114,100,0}; /* "third" */
143 static const UChar _fourth
[]= {102,111,117,114,116,104,0};/* "fourth" */
145 static const UChar
* test2
[] = {
146 _first
, _second
, _third
, _fourth
149 struct uchArrayContext
{
156 typedef struct uchArrayContext uchArrayContext
;
158 #define ucont ((uchArrayContext *)en->context)
160 static void U_CALLCONV
161 uchArrayClose(UEnumeration
*en
) {
165 static int32_t U_CALLCONV
166 uchArrayCount(UEnumeration
*en
, UErrorCode
*status
) {
167 (void)status
; // suppress compiler warnings about unused variable
168 return ucont
->maxIndex
;
171 static const UChar
* U_CALLCONV
172 uchArrayUNext(UEnumeration
*en
, int32_t *resultLength
, UErrorCode
*status
) {
173 (void)status
; // suppress compiler warnings about unused variable
174 if(ucont
->currIndex
>= ucont
->maxIndex
) {
178 ucont
->currUChar
= (ucont
->array
)[ucont
->currIndex
];
179 *resultLength
= u_strlen(ucont
->currUChar
);
181 return ucont
->currUChar
;
184 static void U_CALLCONV
185 uchArrayReset(UEnumeration
*en
, UErrorCode
*status
) {
186 (void)status
; // suppress compiler warnings about unused variable
187 ucont
->currIndex
= 0;
190 uchArrayContext myUCont
= {
195 UEnumeration uchEnum
= {
205 /********************************************************************/
207 static UEnumeration
*getchArrayEnum(const char** source
, int32_t size
) {
208 UEnumeration
*en
= (UEnumeration
*)malloc(sizeof(UEnumeration
));
209 memcpy(en
, &chEnum
, sizeof(UEnumeration
));
210 cont
->array
= (char **)source
;
211 cont
->maxIndex
= size
;
215 static void EnumerationTest(void) {
216 UErrorCode status
= U_ZERO_ERROR
;
218 UEnumeration
*en
= getchArrayEnum(test1
, UPRV_LENGTHOF(test1
));
219 const char *string
= NULL
;
220 const UChar
*uString
= NULL
;
221 while ((string
= uenum_next(en
, &len
, &status
))) {
222 log_verbose("read \"%s\", length %i\n", string
, len
);
224 uenum_reset(en
, &status
);
225 while ((uString
= uenum_unext(en
, &len
, &status
))) {
226 log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString
, len
), len
);
232 static void EmptyEnumerationTest(void) {
233 UErrorCode status
= U_ZERO_ERROR
;
234 UEnumeration
*emptyEnum
= uprv_malloc(sizeof(UEnumeration
));
236 uprv_memcpy(emptyEnum
, &emptyEnumerator
, sizeof(UEnumeration
));
237 if (uenum_count(emptyEnum
, &status
) != -1 || status
!= U_UNSUPPORTED_ERROR
) {
238 log_err("uenum_count failed\n");
240 status
= U_ZERO_ERROR
;
241 if (uenum_next(emptyEnum
, NULL
, &status
) != NULL
|| status
!= U_UNSUPPORTED_ERROR
) {
242 log_err("uenum_next failed\n");
244 status
= U_ZERO_ERROR
;
245 if (uenum_unext(emptyEnum
, NULL
, &status
) != NULL
|| status
!= U_UNSUPPORTED_ERROR
) {
246 log_err("uenum_unext failed\n");
248 status
= U_ZERO_ERROR
;
249 uenum_reset(emptyEnum
, &status
);
250 if (status
!= U_UNSUPPORTED_ERROR
) {
251 log_err("uenum_reset failed\n");
253 uenum_close(emptyEnum
);
255 status
= U_ZERO_ERROR
;
256 if (uenum_next(NULL
, NULL
, &status
) != NULL
|| status
!= U_ZERO_ERROR
) {
257 log_err("uenum_next(NULL) failed\n");
259 status
= U_ZERO_ERROR
;
260 if (uenum_unext(NULL
, NULL
, &status
) != NULL
|| status
!= U_ZERO_ERROR
) {
261 log_err("uenum_unext(NULL) failed\n");
263 status
= U_ZERO_ERROR
;
264 uenum_reset(NULL
, &status
);
265 if (status
!= U_ZERO_ERROR
) {
266 log_err("uenum_reset(NULL) failed\n");
269 emptyEnum
= uprv_malloc(sizeof(UEnumeration
));
270 uprv_memcpy(emptyEnum
, &emptyPartialEnumerator
, sizeof(UEnumeration
));
271 status
= U_ZERO_ERROR
;
272 if (uenum_unext(emptyEnum
, NULL
, &status
) != NULL
|| status
!= U_UNSUPPORTED_ERROR
) {
273 log_err("partial uenum_unext failed\n");
275 uenum_close(emptyEnum
);
278 static UEnumeration
*getuchArrayEnum(const UChar
** source
, int32_t size
) {
279 UEnumeration
*en
= (UEnumeration
*)malloc(sizeof(UEnumeration
));
280 memcpy(en
, &uchEnum
, sizeof(UEnumeration
));
281 ucont
->array
= (UChar
**)source
;
282 ucont
->maxIndex
= size
;
286 static void DefaultNextTest(void) {
287 UErrorCode status
= U_ZERO_ERROR
;
289 UEnumeration
*en
= getuchArrayEnum(test2
, UPRV_LENGTHOF(test2
));
290 const char *string
= NULL
;
291 const UChar
*uString
= NULL
;
292 while ((uString
= uenum_unext(en
, &len
, &status
))) {
293 log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString
, len
), len
);
295 if (U_FAILURE(status
)) {
296 log_err("FAIL: uenum_unext => %s\n", u_errorName(status
));
298 uenum_reset(en
, &status
);
299 while ((string
= uenum_next(en
, &len
, &status
))) {
300 log_verbose("read \"%s\", length %i\n", string
, len
);
302 if (U_FAILURE(status
)) {
303 log_err("FAIL: uenum_next => %s\n", u_errorName(status
));
309 static void verifyEnumeration(int line
, UEnumeration
*u
, const char * const * compareToChar
, const UChar
* const * compareToUChar
, int32_t expect_count
) {
310 UErrorCode status
= U_ZERO_ERROR
;
311 int32_t got_count
,i
,len
;
315 log_verbose("%s:%d: verifying enumeration..\n", __FILE__
, line
);
317 uenum_reset(u
, &status
);
318 if(U_FAILURE(status
)) {
319 log_err("%s:%d: FAIL: could not reset char strings enumeration: %s\n", __FILE__
, line
, u_errorName(status
));
323 got_count
= uenum_count(u
, &status
);
324 if(U_FAILURE(status
)) {
325 log_err("%s:%d: FAIL: could not count char strings enumeration: %s\n", __FILE__
, line
, u_errorName(status
));
329 if(got_count
!=expect_count
) {
330 log_err("%s:%d: FAIL: expect count %d got %d\n", __FILE__
, line
, expect_count
, got_count
);
332 log_verbose("%s:%d: OK: got count %d\n", __FILE__
, line
, got_count
);
335 if(compareToChar
!=NULL
) { /* else, not invariant */
336 for(i
=0;i
<got_count
;i
++) {
337 c
= uenum_next(u
,&len
, &status
);
338 if(U_FAILURE(status
)) {
339 log_err("%s:%d: FAIL: could not iterate to next after %d: %s\n", __FILE__
, line
, i
, u_errorName(status
));
343 log_err("%s:%d: FAIL: got NULL for next after %d: %s\n", __FILE__
, line
, i
, u_errorName(status
));
347 if(strcmp(c
,compareToChar
[i
])) {
348 log_err("%s:%d: FAIL: string #%d expected '%s' got '%s'\n", __FILE__
, line
, i
, compareToChar
[i
], c
);
350 log_verbose("%s:%d: OK: string #%d got '%s'\n", __FILE__
, line
, i
, c
);
353 if(len
!=(int32_t)strlen(compareToChar
[i
])) {
354 log_err("%s:%d: FAIL: string #%d expected len %d got %d\n", __FILE__
, line
, i
, strlen(compareToChar
[i
]), len
);
356 log_verbose("%s:%d: OK: string #%d got len %d\n", __FILE__
, line
, i
, len
);
362 uenum_reset(u
, &status
);
363 if(U_FAILURE(status
)) {
364 log_err("%s:%d: FAIL: could not reset again char strings enumeration: %s\n", __FILE__
, line
, u_errorName(status
));
368 for(i
=0;i
<got_count
;i
++) {
369 const UChar
*ustr
= uenum_unext(u
,&len
, &status
);
370 if(U_FAILURE(status
)) {
371 log_err("%s:%d: FAIL: could not iterate to unext after %d: %s\n", __FILE__
, line
, i
, u_errorName(status
));
375 log_err("%s:%d: FAIL: got NULL for unext after %d: %s\n", __FILE__
, line
, i
, u_errorName(status
));
378 if(compareToChar
!=NULL
) {
379 u_charsToUChars(compareToChar
[i
], buf
, (int32_t)strlen(compareToChar
[i
])+1);
380 if(u_strncmp(ustr
,buf
,len
)) {
382 log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__
, line
, i
, compareToChar
[i
], austrdup(ustr
));
383 for(j
=0;ustr
[j
]&&buf
[j
];j
++) {
384 log_verbose(" @ %d\t<U+%04X> vs <U+%04X>\n", j
, ustr
[j
],buf
[j
]);
387 log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__
, line
, i
, compareToChar
[i
]);
390 if(len
!=(int32_t)strlen(compareToChar
[i
])) {
391 log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__
, line
, i
, strlen(compareToChar
[i
]), len
);
393 log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__
, line
, i
, len
);
397 if(compareToUChar
!=NULL
) {
398 if(u_strcmp(ustr
,compareToUChar
[i
])) {
400 log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__
, line
, i
, austrdup(compareToUChar
[i
]), austrdup(ustr
));
401 for(j
=0;ustr
[j
]&&compareToUChar
[j
];j
++) {
402 log_verbose(" @ %d\t<U+%04X> vs <U+%04X>\n", j
, ustr
[j
],compareToUChar
[j
]);
405 log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__
, line
, i
, austrdup(compareToUChar
[i
]));
408 if(len
!=u_strlen(compareToUChar
[i
])) {
409 log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__
, line
, i
, u_strlen(compareToUChar
[i
]), len
);
411 log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__
, line
, i
, len
);
421 static void TestCharStringsEnumeration(void) {
422 UErrorCode status
= U_ZERO_ERROR
;
424 /* //! [uenum_openCharStringsEnumeration] */
425 const char* strings
[] = { "Firstly", "Secondly", "Thirdly", "Fourthly" };
426 UEnumeration
*u
= uenum_openCharStringsEnumeration(strings
, 4, &status
);
427 /* //! [uenum_openCharStringsEnumeration] */
428 if(U_FAILURE(status
)) {
429 log_err("FAIL: could not open char strings enumeration: %s\n", u_errorName(status
));
433 verifyEnumeration(__LINE__
, u
, strings
, NULL
, 4);
438 static void TestUCharStringsEnumeration(void) {
439 UErrorCode status
= U_ZERO_ERROR
;
440 /* //! [uenum_openUCharStringsEnumeration] */
441 static const UChar nko_1
[] = {0x07c1,0}, nko_2
[] = {0x07c2,0}, nko_3
[] = {0x07c3,0}, nko_4
[] = {0x07c4,0};
442 static const UChar
* ustrings
[] = { nko_1
, nko_2
, nko_3
, nko_4
};
443 UEnumeration
*u
= uenum_openUCharStringsEnumeration(ustrings
, 4, &status
);
444 /* //! [uenum_openUCharStringsEnumeration] */
445 if(U_FAILURE(status
)) {
446 log_err("FAIL: could not open uchar strings enumeration: %s\n", u_errorName(status
));
450 verifyEnumeration(__LINE__
, u
, NULL
, ustrings
, 4);
454 u
= uenum_openUCharStringsEnumeration(test2
, 4, &status
);
455 if(U_FAILURE(status
)) {
456 log_err("FAIL: could not reopen uchar strings enumeration: %s\n", u_errorName(status
));
459 verifyEnumeration(__LINE__
, u
, test1
, NULL
, 4); /* same string */
464 void addEnumerationTest(TestNode
** root
);
466 void addEnumerationTest(TestNode
** root
)
468 addTest(root
, &EnumerationTest
, "tsutil/uenumtst/EnumerationTest");
469 addTest(root
, &EmptyEnumerationTest
, "tsutil/uenumtst/EmptyEnumerationTest");
470 addTest(root
, &DefaultNextTest
, "tsutil/uenumtst/DefaultNextTest");
471 addTest(root
, &TestCharStringsEnumeration
, "tsutil/uenumtst/TestCharStringsEnumeration");
472 addTest(root
, &TestUCharStringsEnumeration
, "tsutil/uenumtst/TestUCharStringsEnumeration");