OLD | NEW |
| (Empty) |
1 /* | |
2 ******************************************************************************* | |
3 * | |
4 * Copyright (C) 2002-2015, International Business Machines | |
5 * Corporation and others. All Rights Reserved. | |
6 * | |
7 ******************************************************************************* | |
8 * file name: uenumtst.c | |
9 * encoding: US-ASCII | |
10 * tab size: 8 (not used) | |
11 * indentation:2 | |
12 * | |
13 * created on: 2002jul08 | |
14 * created by: Vladimir Weinstein | |
15 */ | |
16 | |
17 #include "cintltst.h" | |
18 #include "uenumimp.h" | |
19 #include "cmemory.h" | |
20 #include "cstring.h" | |
21 #include "unicode/ustring.h" | |
22 | |
23 static char quikBuf[256]; | |
24 static char* quikU2C(const UChar* str, int32_t len) { | |
25 u_UCharsToChars(str, quikBuf, len); | |
26 quikBuf[len] = 0; | |
27 return quikBuf; | |
28 } | |
29 | |
30 static const char* test1[] = { | |
31 "first", | |
32 "second", | |
33 "third", | |
34 "fourth" | |
35 }; | |
36 | |
37 struct chArrayContext { | |
38 int32_t currIndex; | |
39 int32_t maxIndex; | |
40 char *currChar; | |
41 UChar *currUChar; | |
42 char **array; | |
43 }; | |
44 | |
45 typedef struct chArrayContext chArrayContext; | |
46 | |
47 #define cont ((chArrayContext *)en->context) | |
48 | |
49 static void U_CALLCONV | |
50 chArrayClose(UEnumeration *en) { | |
51 if(cont->currUChar != NULL) { | |
52 free(cont->currUChar); | |
53 cont->currUChar = NULL; | |
54 } | |
55 free(en); | |
56 } | |
57 | |
58 static int32_t U_CALLCONV | |
59 chArrayCount(UEnumeration *en, UErrorCode *status) { | |
60 return cont->maxIndex; | |
61 } | |
62 | |
63 static const UChar* U_CALLCONV | |
64 chArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { | |
65 if(cont->currIndex >= cont->maxIndex) { | |
66 return NULL; | |
67 } | |
68 | |
69 if(cont->currUChar == NULL) { | |
70 cont->currUChar = (UChar *)malloc(1024*sizeof(UChar)); | |
71 } | |
72 | |
73 cont->currChar = (cont->array)[cont->currIndex]; | |
74 *resultLength = (int32_t)strlen(cont->currChar); | |
75 u_charsToUChars(cont->currChar, cont->currUChar, *resultLength); | |
76 cont->currIndex++; | |
77 return cont->currUChar; | |
78 } | |
79 | |
80 static const char* U_CALLCONV | |
81 chArrayNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { | |
82 if(cont->currIndex >= cont->maxIndex) { | |
83 return NULL; | |
84 } | |
85 | |
86 cont->currChar = (cont->array)[cont->currIndex]; | |
87 *resultLength = (int32_t)strlen(cont->currChar); | |
88 cont->currIndex++; | |
89 return cont->currChar; | |
90 } | |
91 | |
92 static void U_CALLCONV | |
93 chArrayReset(UEnumeration *en, UErrorCode *status) { | |
94 cont->currIndex = 0; | |
95 } | |
96 | |
97 chArrayContext myCont = { | |
98 0, 0, | |
99 NULL, NULL, | |
100 NULL | |
101 }; | |
102 | |
103 UEnumeration chEnum = { | |
104 NULL, | |
105 &myCont, | |
106 chArrayClose, | |
107 chArrayCount, | |
108 chArrayUNext, | |
109 chArrayNext, | |
110 chArrayReset | |
111 }; | |
112 | |
113 static const UEnumeration emptyEnumerator = { | |
114 NULL, | |
115 NULL, | |
116 NULL, | |
117 NULL, | |
118 NULL, | |
119 NULL, | |
120 NULL, | |
121 }; | |
122 | |
123 static const UEnumeration emptyPartialEnumerator = { | |
124 NULL, | |
125 NULL, | |
126 NULL, | |
127 NULL, | |
128 uenum_unextDefault, | |
129 NULL, | |
130 NULL, | |
131 }; | |
132 | |
133 /********************************************************************/ | |
134 static const UChar _first[] = {102,105,114,115,116,0}; /* "first" */ | |
135 static const UChar _second[]= {115,101,99,111,110,100,0}; /* "second" */ | |
136 static const UChar _third[] = {116,104,105,114,100,0}; /* "third" */ | |
137 static const UChar _fourth[]= {102,111,117,114,116,104,0};/* "fourth" */ | |
138 | |
139 static const UChar* test2[] = { | |
140 _first, _second, _third, _fourth | |
141 }; | |
142 | |
143 struct uchArrayContext { | |
144 int32_t currIndex; | |
145 int32_t maxIndex; | |
146 UChar *currUChar; | |
147 UChar **array; | |
148 }; | |
149 | |
150 typedef struct uchArrayContext uchArrayContext; | |
151 | |
152 #define ucont ((uchArrayContext *)en->context) | |
153 | |
154 static void U_CALLCONV | |
155 uchArrayClose(UEnumeration *en) { | |
156 free(en); | |
157 } | |
158 | |
159 static int32_t U_CALLCONV | |
160 uchArrayCount(UEnumeration *en, UErrorCode *status) { | |
161 return ucont->maxIndex; | |
162 } | |
163 | |
164 static const UChar* U_CALLCONV | |
165 uchArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { | |
166 if(ucont->currIndex >= ucont->maxIndex) { | |
167 return NULL; | |
168 } | |
169 | |
170 ucont->currUChar = (ucont->array)[ucont->currIndex]; | |
171 *resultLength = u_strlen(ucont->currUChar); | |
172 ucont->currIndex++; | |
173 return ucont->currUChar; | |
174 } | |
175 | |
176 static void U_CALLCONV | |
177 uchArrayReset(UEnumeration *en, UErrorCode *status) { | |
178 ucont->currIndex = 0; | |
179 } | |
180 | |
181 uchArrayContext myUCont = { | |
182 0, 0, | |
183 NULL, NULL | |
184 }; | |
185 | |
186 UEnumeration uchEnum = { | |
187 NULL, | |
188 &myUCont, | |
189 uchArrayClose, | |
190 uchArrayCount, | |
191 uchArrayUNext, | |
192 uenum_nextDefault, | |
193 uchArrayReset | |
194 }; | |
195 | |
196 /********************************************************************/ | |
197 | |
198 static UEnumeration *getchArrayEnum(const char** source, int32_t size) { | |
199 UEnumeration *en = (UEnumeration *)malloc(sizeof(UEnumeration)); | |
200 memcpy(en, &chEnum, sizeof(UEnumeration)); | |
201 cont->array = (char **)source; | |
202 cont->maxIndex = size; | |
203 return en; | |
204 } | |
205 | |
206 static void EnumerationTest(void) { | |
207 UErrorCode status = U_ZERO_ERROR; | |
208 int32_t len = 0; | |
209 UEnumeration *en = getchArrayEnum(test1, sizeof(test1)/sizeof(test1[0])); | |
210 const char *string = NULL; | |
211 const UChar *uString = NULL; | |
212 while ((string = uenum_next(en, &len, &status))) { | |
213 log_verbose("read \"%s\", length %i\n", string, len); | |
214 } | |
215 uenum_reset(en, &status); | |
216 while ((uString = uenum_unext(en, &len, &status))) { | |
217 log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString, len), l
en); | |
218 } | |
219 | |
220 uenum_close(en); | |
221 } | |
222 | |
223 static void EmptyEnumerationTest(void) { | |
224 UErrorCode status = U_ZERO_ERROR; | |
225 UEnumeration *emptyEnum = uprv_malloc(sizeof(UEnumeration)); | |
226 | |
227 uprv_memcpy(emptyEnum, &emptyEnumerator, sizeof(UEnumeration)); | |
228 if (uenum_count(emptyEnum, &status) != -1 || status != U_UNSUPPORTED_ERROR)
{ | |
229 log_err("uenum_count failed\n"); | |
230 } | |
231 status = U_ZERO_ERROR; | |
232 if (uenum_next(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_
ERROR) { | |
233 log_err("uenum_next failed\n"); | |
234 } | |
235 status = U_ZERO_ERROR; | |
236 if (uenum_unext(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED
_ERROR) { | |
237 log_err("uenum_unext failed\n"); | |
238 } | |
239 status = U_ZERO_ERROR; | |
240 uenum_reset(emptyEnum, &status); | |
241 if (status != U_UNSUPPORTED_ERROR) { | |
242 log_err("uenum_reset failed\n"); | |
243 } | |
244 uenum_close(emptyEnum); | |
245 | |
246 status = U_ZERO_ERROR; | |
247 if (uenum_next(NULL, NULL, &status) != NULL || status != U_ZERO_ERROR) { | |
248 log_err("uenum_next(NULL) failed\n"); | |
249 } | |
250 status = U_ZERO_ERROR; | |
251 if (uenum_unext(NULL, NULL, &status) != NULL || status != U_ZERO_ERROR) { | |
252 log_err("uenum_unext(NULL) failed\n"); | |
253 } | |
254 status = U_ZERO_ERROR; | |
255 uenum_reset(NULL, &status); | |
256 if (status != U_ZERO_ERROR) { | |
257 log_err("uenum_reset(NULL) failed\n"); | |
258 } | |
259 | |
260 emptyEnum = uprv_malloc(sizeof(UEnumeration)); | |
261 uprv_memcpy(emptyEnum, &emptyPartialEnumerator, sizeof(UEnumeration)); | |
262 status = U_ZERO_ERROR; | |
263 if (uenum_unext(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED
_ERROR) { | |
264 log_err("partial uenum_unext failed\n"); | |
265 } | |
266 uenum_close(emptyEnum); | |
267 } | |
268 | |
269 static UEnumeration *getuchArrayEnum(const UChar** source, int32_t size) { | |
270 UEnumeration *en = (UEnumeration *)malloc(sizeof(UEnumeration)); | |
271 memcpy(en, &uchEnum, sizeof(UEnumeration)); | |
272 ucont->array = (UChar **)source; | |
273 ucont->maxIndex = size; | |
274 return en; | |
275 } | |
276 | |
277 static void DefaultNextTest(void) { | |
278 UErrorCode status = U_ZERO_ERROR; | |
279 int32_t len = 0; | |
280 UEnumeration *en = getuchArrayEnum(test2, sizeof(test2)/sizeof(test2[0])); | |
281 const char *string = NULL; | |
282 const UChar *uString = NULL; | |
283 while ((uString = uenum_unext(en, &len, &status))) { | |
284 log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString, len), l
en); | |
285 } | |
286 if (U_FAILURE(status)) { | |
287 log_err("FAIL: uenum_unext => %s\n", u_errorName(status)); | |
288 } | |
289 uenum_reset(en, &status); | |
290 while ((string = uenum_next(en, &len, &status))) { | |
291 log_verbose("read \"%s\", length %i\n", string, len); | |
292 } | |
293 if (U_FAILURE(status)) { | |
294 log_err("FAIL: uenum_next => %s\n", u_errorName(status)); | |
295 } | |
296 | |
297 uenum_close(en); | |
298 } | |
299 | |
300 static void verifyEnumeration(int line, UEnumeration *u, const char * const * co
mpareToChar, const UChar * const * compareToUChar, int32_t expect_count) { | |
301 UErrorCode status = U_ZERO_ERROR; | |
302 int32_t got_count,i,len; | |
303 const char *c; | |
304 UChar buf[1024]; | |
305 | |
306 log_verbose("%s:%d: verifying enumeration..\n", __FILE__, line); | |
307 | |
308 uenum_reset(u, &status); | |
309 if(U_FAILURE(status)) { | |
310 log_err("%s:%d: FAIL: could not reset char strings enumeration: %s\n", __FIL
E__, line, u_errorName(status)); | |
311 return; | |
312 } | |
313 | |
314 got_count = uenum_count(u, &status); | |
315 if(U_FAILURE(status)) { | |
316 log_err("%s:%d: FAIL: could not count char strings enumeration: %s\n", __FIL
E__, line, u_errorName(status)); | |
317 return; | |
318 } | |
319 | |
320 if(got_count!=expect_count) { | |
321 log_err("%s:%d: FAIL: expect count %d got %d\n", __FILE__, line, expect_coun
t, got_count); | |
322 } else { | |
323 log_verbose("%s:%d: OK: got count %d\n", __FILE__, line, got_count); | |
324 } | |
325 | |
326 if(compareToChar!=NULL) { /* else, not invariant */ | |
327 for(i=0;i<got_count;i++) { | |
328 c = uenum_next(u,&len, &status); | |
329 if(U_FAILURE(status)) { | |
330 log_err("%s:%d: FAIL: could not iterate to next after %d: %s\n", __FILE_
_, line, i, u_errorName(status)); | |
331 return; | |
332 } | |
333 if(c==NULL) { | |
334 log_err("%s:%d: FAIL: got NULL for next after %d: %s\n", __FILE__, line,
i, u_errorName(status)); | |
335 return; | |
336 } | |
337 | |
338 if(strcmp(c,compareToChar[i])) { | |
339 log_err("%s:%d: FAIL: string #%d expected '%s' got '%s'\n", __FILE__, li
ne, i, compareToChar[i], c); | |
340 } else { | |
341 log_verbose("%s:%d: OK: string #%d got '%s'\n", __FILE__, line, i, c); | |
342 } | |
343 | |
344 if(len!=strlen(compareToChar[i])) { | |
345 log_err("%s:%d: FAIL: string #%d expected len %d got %d\n", __FILE__, li
ne, i, strlen(compareToChar[i]), len); | |
346 } else { | |
347 log_verbose("%s:%d: OK: string #%d got len %d\n", __FILE__, line, i, len
); | |
348 } | |
349 } | |
350 } | |
351 | |
352 /* now try U */ | |
353 uenum_reset(u, &status); | |
354 if(U_FAILURE(status)) { | |
355 log_err("%s:%d: FAIL: could not reset again char strings enumeration: %s\n",
__FILE__, line, u_errorName(status)); | |
356 return; | |
357 } | |
358 | |
359 for(i=0;i<got_count;i++) { | |
360 const UChar *ustr = uenum_unext(u,&len, &status); | |
361 if(U_FAILURE(status)) { | |
362 log_err("%s:%d: FAIL: could not iterate to unext after %d: %s\n", __FILE__
, line, i, u_errorName(status)); | |
363 return; | |
364 } | |
365 if(ustr==NULL) { | |
366 log_err("%s:%d: FAIL: got NULL for unext after %d: %s\n", __FILE__, line,
i, u_errorName(status)); | |
367 return; | |
368 } | |
369 if(compareToChar!=NULL) { | |
370 u_charsToUChars(compareToChar[i], buf, strlen(compareToChar[i])+1); | |
371 if(u_strncmp(ustr,buf,len)) { | |
372 int j; | |
373 log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__, l
ine, i, compareToChar[i], austrdup(ustr)); | |
374 for(j=0;ustr[j]&&buf[j];j++) { | |
375 log_verbose(" @ %d\t<U+%04X> vs <U+%04X>\n", j, ustr[j],buf[j]); | |
376 } | |
377 } else { | |
378 log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, comp
areToChar[i]); | |
379 } | |
380 | |
381 if(len!=strlen(compareToChar[i])) { | |
382 log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, l
ine, i, strlen(compareToChar[i]), len); | |
383 } else { | |
384 log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, le
n); | |
385 } | |
386 } | |
387 | |
388 if(compareToUChar!=NULL) { | |
389 if(u_strcmp(ustr,compareToUChar[i])) { | |
390 int j; | |
391 log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__, l
ine, i, austrdup(compareToUChar[i]), austrdup(ustr)); | |
392 for(j=0;ustr[j]&&compareToUChar[j];j++) { | |
393 log_verbose(" @ %d\t<U+%04X> vs <U+%04X>\n", j, ustr[j],compareToUCha
r[j]); | |
394 } | |
395 } else { | |
396 log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, aust
rdup(compareToUChar[i])); | |
397 } | |
398 | |
399 if(len!=u_strlen(compareToUChar[i])) { | |
400 log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, l
ine, i, u_strlen(compareToUChar[i]), len); | |
401 } else { | |
402 log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, le
n); | |
403 } | |
404 } | |
405 } | |
406 } | |
407 | |
408 | |
409 | |
410 | |
411 | |
412 static void TestCharStringsEnumeration(void) { | |
413 UErrorCode status = U_ZERO_ERROR; | |
414 | |
415 /* //! [uenum_openCharStringsEnumeration] */ | |
416 const char* strings[] = { "Firstly", "Secondly", "Thirdly", "Fourthly" }; | |
417 UEnumeration *u = uenum_openCharStringsEnumeration(strings, 4, &status); | |
418 /* //! [uenum_openCharStringsEnumeration] */ | |
419 if(U_FAILURE(status)) { | |
420 log_err("FAIL: could not open char strings enumeration: %s\n", u_errorName(s
tatus)); | |
421 return; | |
422 } | |
423 | |
424 verifyEnumeration(__LINE__, u, strings, NULL, 4); | |
425 | |
426 uenum_close(u); | |
427 } | |
428 | |
429 static void TestUCharStringsEnumeration(void) { | |
430 UErrorCode status = U_ZERO_ERROR; | |
431 /* //! [uenum_openUCharStringsEnumeration] */ | |
432 static const UChar nko_1[] = {0x07c1,0}, nko_2[] = {0x07c2,0}, nko_3[] = {0x07
c3,0}, nko_4[] = {0x07c4,0}; | |
433 static const UChar* ustrings[] = { nko_1, nko_2, nko_3, nko_4 }; | |
434 UEnumeration *u = uenum_openUCharStringsEnumeration(ustrings, 4, &status); | |
435 /* //! [uenum_openUCharStringsEnumeration] */ | |
436 if(U_FAILURE(status)) { | |
437 log_err("FAIL: could not open uchar strings enumeration: %s\n", u_errorName(
status)); | |
438 return; | |
439 } | |
440 | |
441 verifyEnumeration(__LINE__, u, NULL, ustrings, 4); | |
442 uenum_close(u); | |
443 | |
444 | |
445 u = uenum_openUCharStringsEnumeration(test2, 4, &status); | |
446 if(U_FAILURE(status)) { | |
447 log_err("FAIL: could not reopen uchar strings enumeration: %s\n", u_errorNam
e(status)); | |
448 return; | |
449 } | |
450 verifyEnumeration(__LINE__, u, test1, NULL, 4); /* same string */ | |
451 uenum_close(u); | |
452 | |
453 } | |
454 | |
455 void addEnumerationTest(TestNode** root); | |
456 | |
457 void addEnumerationTest(TestNode** root) | |
458 { | |
459 addTest(root, &EnumerationTest, "tsutil/uenumtst/EnumerationTest"); | |
460 addTest(root, &EmptyEnumerationTest, "tsutil/uenumtst/EmptyEnumerationTest")
; | |
461 addTest(root, &DefaultNextTest, "tsutil/uenumtst/DefaultNextTest"); | |
462 addTest(root, &TestCharStringsEnumeration, "tsutil/uenumtst/TestCharStringsE
numeration"); | |
463 addTest(root, &TestUCharStringsEnumeration, "tsutil/uenumtst/TestUCharString
sEnumeration"); | |
464 } | |
OLD | NEW |