• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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];
quikU2C(const UChar * str,int32_t len)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
chArrayClose(UEnumeration * en)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
chArrayCount(UEnumeration * en,UErrorCode * status)59 chArrayCount(UEnumeration *en, UErrorCode *status) {
60     return cont->maxIndex;
61 }
62 
63 static const UChar* U_CALLCONV
chArrayUNext(UEnumeration * en,int32_t * resultLength,UErrorCode * status)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
chArrayNext(UEnumeration * en,int32_t * resultLength,UErrorCode * status)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
chArrayReset(UEnumeration * en,UErrorCode * status)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
uchArrayClose(UEnumeration * en)155 uchArrayClose(UEnumeration *en) {
156     free(en);
157 }
158 
159 static int32_t U_CALLCONV
uchArrayCount(UEnumeration * en,UErrorCode * status)160 uchArrayCount(UEnumeration *en, UErrorCode *status) {
161     return ucont->maxIndex;
162 }
163 
164 static const UChar* U_CALLCONV
uchArrayUNext(UEnumeration * en,int32_t * resultLength,UErrorCode * status)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
uchArrayReset(UEnumeration * en,UErrorCode * status)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 
getchArrayEnum(const char ** source,int32_t size)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 
EnumerationTest(void)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), len);
218     }
219 
220     uenum_close(en);
221 }
222 
EmptyEnumerationTest(void)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 
getuchArrayEnum(const UChar ** source,int32_t size)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 
DefaultNextTest(void)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), len);
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 
verifyEnumeration(int line,UEnumeration * u,const char * const * compareToChar,const UChar * const * compareToUChar,int32_t expect_count)300 static void verifyEnumeration(int line, UEnumeration *u, const char * const * compareToChar, 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", __FILE__, 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", __FILE__, 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_count, 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__, line, 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__, line, 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__, line, 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, compareToChar[i]);
379       }
380 
381       if(len!=strlen(compareToChar[i])) {
382         log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, line, i, strlen(compareToChar[i]), len);
383       } else {
384         log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, len);
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__, line, 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],compareToUChar[j]);
394         }
395       } else {
396         log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, austrdup(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__, line, i, u_strlen(compareToUChar[i]), len);
401       } else {
402         log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, len);
403       }
404     }
405   }
406 }
407 
408 
409 
410 
411 
TestCharStringsEnumeration(void)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(status));
421     return;
422   }
423 
424   verifyEnumeration(__LINE__, u, strings, NULL, 4);
425 
426   uenum_close(u);
427 }
428 
TestUCharStringsEnumeration(void)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[] = {0x07c3,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_errorName(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 
addEnumerationTest(TestNode ** root)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/TestCharStringsEnumeration");
463     addTest(root, &TestUCharStringsEnumeration, "tsutil/uenumtst/TestUCharStringsEnumeration");
464 }
465