]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/cintltst/custrtst.c
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / test / cintltst / custrtst.c
CommitLineData
b75a7d8f
A
1/*
2******************************************************************************
3*
4* Copyright (C) 2002-2003, International Business Machines
5* Corporation and others. All Rights Reserved.
6*
7******************************************************************************
8* file name: custrtst.c
9* encoding: US-ASCII
10* tab size: 8 (not used)
11* indentation:4
12*
13* created on: 2002oct09
14* created by: Markus W. Scherer
15*
16* Tests of ustring.h Unicode string API functions.
17*/
18
19#include "unicode/utypes.h"
20#include "unicode/ustring.h"
21#include "unicode/uloc.h"
22#include "unicode/ucnv.h"
23#include "unicode/uiter.h"
24#include "cintltst.h"
25#include "cucdtst.h"
26#include <string.h>
27#include <stdlib.h>
28
29#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
30
31/* get the sign of an integer */
32#define _SIGN(value) ((value)==0 ? 0 : ((int32_t)(value)>>31)|1)
33
34/* test setup --------------------------------------------------------------- */
35
36static void setUpDataTable(void);
37static void TestStringCopy(void);
38static void TestStringFunctions(void);
39static void TestStringSearching(void);
40static void TestSurrogateSearching(void);
41static void TestUnescape(void);
42static void TestCountChar32(void);
43static void TestUCharIterator(void);
44static void TestUNormIterator(void);
45
46void addUStringTest(TestNode** root);
47
48void addUStringTest(TestNode** root)
49{
50 addTest(root, &TestStringCopy, "tsutil/custrtst/TestStringCopy");
51 addTest(root, &TestStringFunctions, "tsutil/custrtst/TestStringFunctions");
52 addTest(root, &TestStringSearching, "tsutil/custrtst/TestStringSearching");
53 addTest(root, &TestSurrogateSearching, "tsutil/custrtst/TestSurrogateSearching");
54 addTest(root, &TestUnescape, "tsutil/custrtst/TestUnescape");
55 addTest(root, &TestCountChar32, "tsutil/custrtst/TestCountChar32");
56 addTest(root, &TestUCharIterator, "tsutil/custrtst/TestUCharIterator");
57 addTest(root, &TestUNormIterator, "tsutil/custrtst/TestUNormIterator");
58
59 /* cstrcase.c functions, declared in cucdtst.h */
60 addTest(root, &TestCaseLower, "tsutil/custrtst/TestCaseLower");
61 addTest(root, &TestCaseUpper, "tsutil/custrtst/TestCaseUpper");
62#if !UCONFIG_NO_BREAK_ITERATION
63 addTest(root, &TestCaseTitle, "tsutil/custrtst/TestCaseTitle");
64#endif
65 addTest(root, &TestCaseFolding, "tsutil/custrtst/TestCaseFolding");
66 addTest(root, &TestCaseCompare, "tsutil/custrtst/TestCaseCompare");
67}
68
69/* test data for TestStringFunctions ---------------------------------------- */
70
71UChar*** dataTable = NULL;
72
73static const char* raw[3][4] = {
74
75 /* First String */
76 { "English_", "French_", "Croatian_", "English_"},
77 /* Second String */
78 { "United States", "France", "Croatia", "Unites States"},
79
80 /* Concatenated string */
81 { "English_United States", "French_France", "Croatian_Croatia", "English_United States"}
82};
83
84static void setUpDataTable()
85{
86 int32_t i,j;
87 if(dataTable == NULL) {
88 dataTable = (UChar***)calloc(sizeof(UChar**),3);
89
90 for (i = 0; i < 3; i++) {
91 dataTable[i] = (UChar**)calloc(sizeof(UChar*),4);
92 for (j = 0; j < 4; j++){
93 dataTable[i][j] = (UChar*) malloc(sizeof(UChar)*(strlen(raw[i][j])+1));
94 u_uastrcpy(dataTable[i][j],raw[i][j]);
95 }
96 }
97 }
98}
99
100static void cleanUpDataTable()
101{
102 int32_t i,j;
103 if(dataTable != NULL) {
104 for (i=0; i<3; i++) {
105 for(j = 0; j<4; j++) {
106 free(dataTable[i][j]);
107 }
108 free(dataTable[i]);
109 }
110 free(dataTable);
111 }
112 dataTable = NULL;
113}
114
115/*Tests for u_strcat(),u_strcmp(), u_strlen(), u_strcpy(),u_strncat(),u_strncmp(),u_strncpy, u_uastrcpy(),u_austrcpy(), u_uastrncpy(); */
116static void TestStringFunctions()
117{
118 int32_t i,j,k;
119 UChar temp[512];
120 UChar nullTemp[512];
121 char test[512];
122 char tempOut[512];
123
124 setUpDataTable();
125
126 log_verbose("Testing u_strlen()\n");
127 if( u_strlen(dataTable[0][0])!= u_strlen(dataTable[0][3]) || u_strlen(dataTable[0][0]) == u_strlen(dataTable[0][2]))
128 log_err("There is an error in u_strlen()");
129
130 log_verbose("Testing u_memcpy() and u_memcmp()\n");
131
132 for(i=0;i<3;++i)
133 {
134 for(j=0;j<4;++j)
135 {
136 log_verbose("Testing %s\n", u_austrcpy(tempOut, dataTable[i][j]));
137 temp[0] = 0;
138 temp[7] = 0xA4; /* Mark the end */
139 u_memcpy(temp,dataTable[i][j], 7);
140
141 if(temp[7] != 0xA4)
142 log_err("an error occured in u_memcpy()\n");
143 if(u_memcmp(temp, dataTable[i][j], 7)!=0)
144 log_err("an error occured in u_memcpy() or u_memcmp()\n");
145 }
146 }
147 if(u_memcmp(dataTable[0][0], dataTable[1][1], 7)==0)
148 log_err("an error occured in u_memcmp()\n");
149
150 log_verbose("Testing u_memset()\n");
151 nullTemp[0] = 0;
152 nullTemp[7] = 0;
153 u_memset(nullTemp, 0xa4, 7);
154 for (i = 0; i < 7; i++) {
155 if(nullTemp[i] != 0xa4) {
156 log_err("an error occured in u_memset()\n");
157 }
158 }
159 if(nullTemp[7] != 0) {
160 log_err("u_memset() went too far\n");
161 }
162
163 u_memset(nullTemp, 0, 7);
164 nullTemp[7] = 0xa4;
165 temp[7] = 0;
166 u_memcpy(temp,nullTemp, 7);
167 if(u_memcmp(temp, nullTemp, 7)!=0 || temp[7]!=0)
168 log_err("an error occured in u_memcpy() or u_memcmp()\n");
169
170
171 log_verbose("Testing u_memmove()\n");
172 for (i = 0; i < 7; i++) {
173 temp[i] = (UChar)i;
174 }
175 u_memmove(temp + 1, temp, 7);
176 if(temp[0] != 0) {
177 log_err("an error occured in u_memmove()\n");
178 }
179 for (i = 1; i <= 7; i++) {
180 if(temp[i] != (i - 1)) {
181 log_err("an error occured in u_memmove()\n");
182 }
183 }
184
185 log_verbose("Testing u_strcpy() and u_strcmp()\n");
186
187 for(i=0;i<3;++i)
188 {
189 for(j=0;j<4;++j)
190 {
191 log_verbose("Testing %s\n", u_austrcpy(tempOut, dataTable[i][j]));
192 temp[0] = 0;
193 u_strcpy(temp,dataTable[i][j]);
194
195 if(u_strcmp(temp,dataTable[i][j])!=0)
196 log_err("something threw an error in u_strcpy() or u_strcmp()\n");
197 }
198 }
199 if(u_strcmp(dataTable[0][0], dataTable[1][1])==0)
200 log_err("an error occured in u_memcmp()\n");
201
202 log_verbose("testing u_strcat()\n");
203 i=0;
204 for(j=0; j<2;++j)
205 {
206 u_uastrcpy(temp, "");
207 u_strcpy(temp,dataTable[i][j]);
208 u_strcat(temp,dataTable[i+1][j]);
209 if(u_strcmp(temp,dataTable[i+2][j])!=0)
210 log_err("something threw an error in u_strcat()\n");
211
212 }
213 log_verbose("Testing u_strncmp()\n");
214 for(i=0,j=0;j<4; ++j)
215 {
216 k=u_strlen(dataTable[i][j]);
217 if(u_strncmp(dataTable[i][j],dataTable[i+2][j],k)!=0)
218 log_err("Something threw an error in u_strncmp\n");
219 }
220 if(u_strncmp(dataTable[0][0], dataTable[1][1], 7)==0)
221 log_err("an error occured in u_memcmp()\n");
222
223
224 log_verbose("Testing u_strncat\n");
225 for(i=0,j=0;j<4; ++j)
226 {
227 k=u_strlen(dataTable[i][j]);
228
229 u_uastrcpy(temp,"");
230
231 if(u_strcmp(u_strncat(temp,dataTable[i+2][j],k),dataTable[i][j])!=0)
232 log_err("something threw an error in u_strncat or u_uastrcpy()\n");
233
234 }
235
236 log_verbose("Testing u_strncpy() and u_uastrcpy()\n");
237 for(i=2,j=0;j<4; ++j)
238 {
239 k=u_strlen(dataTable[i][j]);
240 u_strncpy(temp, dataTable[i][j],k);
241 temp[k] = 0xa4;
242
243 if(u_strncmp(temp, dataTable[i][j],k)!=0)
244 log_err("something threw an error in u_strncpy()\n");
245
246 if(temp[k] != 0xa4)
247 log_err("something threw an error in u_strncpy()\n");
248
249 u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1);
250 u_uastrncpy(temp, raw[i][j], k-1);
251 if(u_strncmp(temp, dataTable[i][j],k-1)!=0)
252 log_err("something threw an error in u_uastrncpy(k-1)\n");
253
254 if(temp[k-1] != 0x3F)
255 log_err("something threw an error in u_uastrncpy(k-1)\n");
256
257 u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1);
258 u_uastrncpy(temp, raw[i][j], k+1);
259 if(u_strcmp(temp, dataTable[i][j])!=0)
260 log_err("something threw an error in u_uastrncpy(k+1)\n");
261
262 if(temp[k] != 0)
263 log_err("something threw an error in u_uastrncpy(k+1)\n");
264
265 u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1);
266 u_uastrncpy(temp, raw[i][j], k);
267 if(u_strncmp(temp, dataTable[i][j], k)!=0)
268 log_err("something threw an error in u_uastrncpy(k)\n");
269
270 if(temp[k] != 0x3F)
271 log_err("something threw an error in u_uastrncpy(k)\n");
272 }
273
274 log_verbose("Testing u_strchr() and u_memchr()\n");
275
276 for(i=2,j=0;j<4;j++)
277 {
278 UChar saveVal = dataTable[i][j][0];
279 UChar *findPtr = u_strchr(dataTable[i][j], 0x005F);
280 int32_t dataSize = (int32_t)(u_strlen(dataTable[i][j]) + 1);
281
282 log_verbose("%s ", u_austrcpy(tempOut, findPtr));
283
284 if (findPtr == NULL || *findPtr != 0x005F) {
285 log_err("u_strchr can't find '_' in the string\n");
286 }
287
288 findPtr = u_strchr32(dataTable[i][j], 0x005F);
289 if (findPtr == NULL || *findPtr != 0x005F) {
290 log_err("u_strchr32 can't find '_' in the string\n");
291 }
292
293 findPtr = u_strchr(dataTable[i][j], 0);
294 if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
295 log_err("u_strchr can't find NULL in the string\n");
296 }
297
298 findPtr = u_strchr32(dataTable[i][j], 0);
299 if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
300 log_err("u_strchr32 can't find NULL in the string\n");
301 }
302
303 findPtr = u_memchr(dataTable[i][j], 0, dataSize);
304 if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
305 log_err("u_memchr can't find NULL in the string\n");
306 }
307
308 findPtr = u_memchr32(dataTable[i][j], 0, dataSize);
309 if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
310 log_err("u_memchr32 can't find NULL in the string\n");
311 }
312
313 dataTable[i][j][0] = 0;
314 /* Make sure we skip over the NULL termination */
315 findPtr = u_memchr(dataTable[i][j], 0x005F, dataSize);
316 if (findPtr == NULL || *findPtr != 0x005F) {
317 log_err("u_memchr can't find '_' in the string\n");
318 }
319
320 findPtr = u_memchr32(dataTable[i][j], 0x005F, dataSize);
321 if (findPtr == NULL || *findPtr != 0x005F) {
322 log_err("u_memchr32 can't find '_' in the string\n");
323 }
324 findPtr = u_memchr32(dataTable[i][j], 0xFFFD, dataSize);
325 if (findPtr != NULL) {
326 log_err("Should have found NULL when the character is not there.\n");
327 }
328 dataTable[i][j][0] = saveVal; /* Put it back for the other tests */
329 }
330
331 /*
332 * test that u_strchr32()
333 * does not find surrogate code points when they are part of matched pairs
334 * (= part of supplementary code points)
335 * Jitterbug 1542
336 */
337 {
338 static const UChar s[]={
339 /* 0 1 2 3 4 5 6 7 8 9 */
340 0x0061, 0xd841, 0xdc02, 0xd841, 0x0062, 0xdc02, 0xd841, 0xdc02, 0x0063, 0
341 };
342
343 if(u_strchr32(s, 0xd841)!=(s+3) || u_strchr32(s, 0xdc02)!=(s+5)) {
344 log_err("error: u_strchr32(surrogate) finds a partial supplementary code point\n");
345 }
346 if(u_memchr32(s, 0xd841, 9)!=(s+3) || u_memchr32(s, 0xdc02, 9)!=(s+5)) {
347 log_err("error: u_memchr32(surrogate) finds a partial supplementary code point\n");
348 }
349 }
350
351 log_verbose("Testing u_austrcpy()");
352 u_austrcpy(test,dataTable[0][0]);
353 if(strcmp(test,raw[0][0])!=0)
354 log_err("There is an error in u_austrcpy()");
355
356
357 log_verbose("Testing u_strtok_r()");
358 {
359 const char tokString[] = " , 1 2 3 AHHHHH! 5.5 6 7 , 8\n";
360 const char *tokens[] = {",", "1", "2", "3", "AHHHHH!", "5.5", "6", "7", "8\n"};
361 UChar delimBuf[sizeof(test)];
362 UChar currTokenBuf[sizeof(tokString)];
363 UChar *state;
364 uint32_t currToken = 0;
365 UChar *ptr;
366
367 u_uastrcpy(temp, tokString);
368 u_uastrcpy(delimBuf, " ");
369
370 ptr = u_strtok_r(temp, delimBuf, &state);
371 u_uastrcpy(delimBuf, " ,");
372 while (ptr != NULL) {
373 u_uastrcpy(currTokenBuf, tokens[currToken]);
374 if (u_strcmp(ptr, currTokenBuf) != 0) {
375 log_err("u_strtok_r mismatch at %d. Got: %s, Expected: %s\n", currToken, ptr, tokens[currToken]);
376 }
377 ptr = u_strtok_r(NULL, delimBuf, &state);
378 currToken++;
379 }
380
381 if (currToken != sizeof(tokens)/sizeof(tokens[0])) {
382 log_err("Didn't get correct number of tokens\n");
383 }
384 state = delimBuf; /* Give it an "invalid" saveState */
385 u_uastrcpy(currTokenBuf, "");
386 if (u_strtok_r(currTokenBuf, delimBuf, &state) != NULL) {
387 log_err("Didn't get NULL for empty string\n");
388 }
389 if (state != NULL) {
390 log_err("State should be NULL for empty string\n");
391 }
392 state = delimBuf; /* Give it an "invalid" saveState */
393 u_uastrcpy(currTokenBuf, ", ,");
394 if (u_strtok_r(currTokenBuf, delimBuf, &state) != NULL) {
395 log_err("Didn't get NULL for a string of delimiters\n");
396 }
397 if (state != NULL) {
398 log_err("State should be NULL for a string of delimiters\n");
399 }
400
401 state = delimBuf; /* Give it an "invalid" saveState */
402 u_uastrcpy(currTokenBuf, "q, ,");
403 if (u_strtok_r(currTokenBuf, delimBuf, &state) == NULL) {
404 log_err("Got NULL for a string that does not begin with delimiters\n");
405 }
406 if (u_strtok_r(NULL, delimBuf, &state) != NULL) {
407 log_err("Didn't get NULL for a string that ends in delimiters\n");
408 }
409 if (state != NULL) {
410 log_err("State should be NULL for empty string\n");
411 }
412
413 state = delimBuf; /* Give it an "invalid" saveState */
414 u_uastrcpy(currTokenBuf, tokString);
415 u_uastrcpy(temp, tokString);
416 u_uastrcpy(delimBuf, "q"); /* Give it a delimiter that it can't find. */
417 ptr = u_strtok_r(currTokenBuf, delimBuf, &state);
418 if (ptr == NULL || u_strcmp(ptr, temp) != 0) {
419 log_err("Should have recieved the same string when there are no delimiters\n");
420 }
421 if (u_strtok_r(NULL, delimBuf, &state) != NULL) {
422 log_err("Should not have found another token in a one token string\n");
423 }
424 }
425
426 /* test u_strcmpCodePointOrder() */
427 {
428 /* these strings are in ascending order */
429 static const UChar strings[][4]={
430 { 0x61, 0 }, /* U+0061 */
431 { 0x20ac, 0xd801, 0 }, /* U+20ac U+d801 */
432 { 0x20ac, 0xd800, 0xdc00, 0 }, /* U+20ac U+10000 */
433 { 0xd800, 0 }, /* U+d800 */
434 { 0xd800, 0xff61, 0 }, /* U+d800 U+ff61 */
435 { 0xdfff, 0 }, /* U+dfff */
436 { 0xff61, 0xdfff, 0 }, /* U+ff61 U+dfff */
437 { 0xff61, 0xd800, 0xdc02, 0 }, /* U+ff61 U+10002 */
438 { 0xd800, 0xdc02, 0 }, /* U+10002 */
439 { 0xd84d, 0xdc56, 0 } /* U+23456 */
440 };
441
442 UCharIterator iter1, iter2;
443 int32_t len1, len2, r1, r2;
444
445 for(i=0; i<(sizeof(strings)/sizeof(strings[0])-1); ++i) {
446 if(u_strcmpCodePointOrder(strings[i], strings[i+1])>=0) {
447 log_err("error: u_strcmpCodePointOrder() fails for string %d and the following one\n", i);
448 }
449 if(u_strncmpCodePointOrder(strings[i], strings[i+1], 10)>=0) {
450 log_err("error: u_strncmpCodePointOrder() fails for string %d and the following one\n", i);
451 }
452
453 /* There are at least 2 UChars in each string - verify that strncmp()==memcmp(). */
454 if(u_strncmpCodePointOrder(strings[i], strings[i+1], 2)!=u_memcmpCodePointOrder(strings[i], strings[i+1], 2)) {
455 log_err("error: u_strncmpCodePointOrder(2)!=u_memcmpCodePointOrder(2) for string %d and the following one\n", i);
456 }
457
458 /* test u_strCompare(TRUE) */
459 len1=u_strlen(strings[i]);
460 len2=u_strlen(strings[i+1]);
461 if( u_strCompare(strings[i], -1, strings[i+1], -1, TRUE)>=0 ||
462 u_strCompare(strings[i], -1, strings[i+1], len2, TRUE)>=0 ||
463 u_strCompare(strings[i], len1, strings[i+1], -1, TRUE)>=0 ||
464 u_strCompare(strings[i], len1, strings[i+1], len2, TRUE)>=0
465 ) {
466 log_err("error: u_strCompare(code point order) fails for string %d and the following one\n", i);
467 }
468
469 /* test u_strCompare(FALSE) */
470 r1=u_strCompare(strings[i], -1, strings[i+1], -1, FALSE);
471 r2=u_strcmp(strings[i], strings[i+1]);
472 if(_SIGN(r1)!=_SIGN(r2)) {
473 log_err("error: u_strCompare(code unit order)!=u_strcmp() for string %d and the following one\n", i);
474 }
475
476 /* test u_strCompareIter() */
477 uiter_setString(&iter1, strings[i], len1);
478 uiter_setString(&iter2, strings[i+1], len2);
479 if(u_strCompareIter(&iter1, &iter2, TRUE)>=0) {
480 log_err("error: u_strCompareIter(code point order) fails for string %d and the following one\n", i);
481 }
482 r1=u_strCompareIter(&iter1, &iter2, FALSE);
483 if(_SIGN(r1)!=_SIGN(u_strcmp(strings[i], strings[i+1]))) {
484 log_err("error: u_strCompareIter(code unit order)!=u_strcmp() for string %d and the following one\n", i);
485 }
486 }
487 }
488
489 cleanUpDataTable();
490}
491
492static void TestStringSearching()
493{
494 const UChar testString[] = {0x0061, 0x0062, 0x0063, 0x0064, 0x0064, 0x0061, 0};
495 const UChar testSurrogateString[] = {0xdbff, 0x0061, 0x0062, 0xdbff, 0xdfff, 0x0063, 0x0064, 0x0064, 0xdbff, 0xdfff, 0xdb00, 0xdf00, 0x0061, 0};
496 const UChar surrMatchSet1[] = {0xdbff, 0xdfff, 0};
497 const UChar surrMatchSet2[] = {0x0061, 0x0062, 0xdbff, 0xdfff, 0};
498 const UChar surrMatchSet3[] = {0xdb00, 0xdf00, 0xdbff, 0xdfff, 0};
499 const UChar surrMatchSet4[] = {0x0000};
500 const UChar surrMatchSetBad[] = {0xdbff, 0x0061, 0};
501 const UChar surrMatchSetBad2[] = {0x0061, 0xdbff, 0};
502 const UChar surrMatchSetBad3[] = {0xdbff, 0x0061, 0x0062, 0xdbff, 0xdfff, 0}; /* has partial surrogate */
503 const UChar
504 empty[] = { 0 },
505 a[] = { 0x61, 0 },
506 ab[] = { 0x61, 0x62, 0 },
507 ba[] = { 0x62, 0x61, 0 },
508 abcd[] = { 0x61, 0x62, 0x63, 0x64, 0 },
509 cd[] = { 0x63, 0x64, 0 },
510 dc[] = { 0x64, 0x63, 0 },
511 cdh[] = { 0x63, 0x64, 0x68, 0 },
512 f[] = { 0x66, 0 },
513 fg[] = { 0x66, 0x67, 0 },
514 gf[] = { 0x67, 0x66, 0 };
515
516 log_verbose("Testing u_strpbrk()");
517
518 if (u_strpbrk(testString, a) != &testString[0]) {
519 log_err("u_strpbrk couldn't find first letter a.\n");
520 }
521 if (u_strpbrk(testString, dc) != &testString[2]) {
522 log_err("u_strpbrk couldn't find d or c.\n");
523 }
524 if (u_strpbrk(testString, cd) != &testString[2]) {
525 log_err("u_strpbrk couldn't find c or d.\n");
526 }
527 if (u_strpbrk(testString, cdh) != &testString[2]) {
528 log_err("u_strpbrk couldn't find c, d or h.\n");
529 }
530 if (u_strpbrk(testString, f) != NULL) {
531 log_err("u_strpbrk didn't return NULL for \"f\".\n");
532 }
533 if (u_strpbrk(testString, fg) != NULL) {
534 log_err("u_strpbrk didn't return NULL for \"fg\".\n");
535 }
536 if (u_strpbrk(testString, gf) != NULL) {
537 log_err("u_strpbrk didn't return NULL for \"gf\".\n");
538 }
539 if (u_strpbrk(testString, empty) != NULL) {
540 log_err("u_strpbrk didn't return NULL for \"\".\n");
541 }
542
543 log_verbose("Testing u_strpbrk() with surrogates");
544
545 if (u_strpbrk(testSurrogateString, a) != &testSurrogateString[1]) {
546 log_err("u_strpbrk couldn't find first letter a.\n");
547 }
548 if (u_strpbrk(testSurrogateString, dc) != &testSurrogateString[5]) {
549 log_err("u_strpbrk couldn't find d or c.\n");
550 }
551 if (u_strpbrk(testSurrogateString, cd) != &testSurrogateString[5]) {
552 log_err("u_strpbrk couldn't find c or d.\n");
553 }
554 if (u_strpbrk(testSurrogateString, cdh) != &testSurrogateString[5]) {
555 log_err("u_strpbrk couldn't find c, d or h.\n");
556 }
557 if (u_strpbrk(testSurrogateString, f) != NULL) {
558 log_err("u_strpbrk didn't return NULL for \"f\".\n");
559 }
560 if (u_strpbrk(testSurrogateString, fg) != NULL) {
561 log_err("u_strpbrk didn't return NULL for \"fg\".\n");
562 }
563 if (u_strpbrk(testSurrogateString, gf) != NULL) {
564 log_err("u_strpbrk didn't return NULL for \"gf\".\n");
565 }
566 if (u_strpbrk(testSurrogateString, surrMatchSet1) != &testSurrogateString[3]) {
567 log_err("u_strpbrk couldn't find \"0xdbff, 0xdfff\".\n");
568 }
569 if (u_strpbrk(testSurrogateString, surrMatchSet2) != &testSurrogateString[1]) {
570 log_err("u_strpbrk couldn't find \"0xdbff, a, b, 0xdbff, 0xdfff\".\n");
571 }
572 if (u_strpbrk(testSurrogateString, surrMatchSet3) != &testSurrogateString[3]) {
573 log_err("u_strpbrk couldn't find \"0xdb00, 0xdf00, 0xdbff, 0xdfff\".\n");
574 }
575 if (u_strpbrk(testSurrogateString, surrMatchSet4) != NULL) {
576 log_err("u_strpbrk should have returned NULL for empty string.\n");
577 }
578 if (u_strpbrk(testSurrogateString, surrMatchSetBad) != &testSurrogateString[0]) {
579 log_err("u_strpbrk should have found bad surrogate.\n");
580 }
581
582 log_verbose("Testing u_strcspn()");
583
584 if (u_strcspn(testString, a) != 0) {
585 log_err("u_strcspn couldn't find first letter a.\n");
586 }
587 if (u_strcspn(testString, dc) != 2) {
588 log_err("u_strcspn couldn't find d or c.\n");
589 }
590 if (u_strcspn(testString, cd) != 2) {
591 log_err("u_strcspn couldn't find c or d.\n");
592 }
593 if (u_strcspn(testString, cdh) != 2) {
594 log_err("u_strcspn couldn't find c, d or h.\n");
595 }
596 if (u_strcspn(testString, f) != u_strlen(testString)) {
597 log_err("u_strcspn didn't return NULL for \"f\".\n");
598 }
599 if (u_strcspn(testString, fg) != u_strlen(testString)) {
600 log_err("u_strcspn didn't return NULL for \"fg\".\n");
601 }
602 if (u_strcspn(testString, gf) != u_strlen(testString)) {
603 log_err("u_strcspn didn't return NULL for \"gf\".\n");
604 }
605
606 log_verbose("Testing u_strcspn() with surrogates");
607
608 if (u_strcspn(testSurrogateString, a) != 1) {
609 log_err("u_strcspn couldn't find first letter a.\n");
610 }
611 if (u_strcspn(testSurrogateString, dc) != 5) {
612 log_err("u_strcspn couldn't find d or c.\n");
613 }
614 if (u_strcspn(testSurrogateString, cd) != 5) {
615 log_err("u_strcspn couldn't find c or d.\n");
616 }
617 if (u_strcspn(testSurrogateString, cdh) != 5) {
618 log_err("u_strcspn couldn't find c, d or h.\n");
619 }
620 if (u_strcspn(testSurrogateString, f) != u_strlen(testSurrogateString)) {
621 log_err("u_strcspn didn't return NULL for \"f\".\n");
622 }
623 if (u_strcspn(testSurrogateString, fg) != u_strlen(testSurrogateString)) {
624 log_err("u_strcspn didn't return NULL for \"fg\".\n");
625 }
626 if (u_strcspn(testSurrogateString, gf) != u_strlen(testSurrogateString)) {
627 log_err("u_strcspn didn't return NULL for \"gf\".\n");
628 }
629 if (u_strcspn(testSurrogateString, surrMatchSet1) != 3) {
630 log_err("u_strcspn couldn't find \"0xdbff, 0xdfff\".\n");
631 }
632 if (u_strcspn(testSurrogateString, surrMatchSet2) != 1) {
633 log_err("u_strcspn couldn't find \"a, b, 0xdbff, 0xdfff\".\n");
634 }
635 if (u_strcspn(testSurrogateString, surrMatchSet3) != 3) {
636 log_err("u_strcspn couldn't find \"0xdb00, 0xdf00, 0xdbff, 0xdfff\".\n");
637 }
638 if (u_strcspn(testSurrogateString, surrMatchSet4) != u_strlen(testSurrogateString)) {
639 log_err("u_strcspn should have returned strlen for empty string.\n");
640 }
641
642
643 log_verbose("Testing u_strspn()");
644
645 if (u_strspn(testString, a) != 1) {
646 log_err("u_strspn couldn't skip first letter a.\n");
647 }
648 if (u_strspn(testString, ab) != 2) {
649 log_err("u_strspn couldn't skip a or b.\n");
650 }
651 if (u_strspn(testString, ba) != 2) {
652 log_err("u_strspn couldn't skip a or b.\n");
653 }
654 if (u_strspn(testString, f) != 0) {
655 log_err("u_strspn didn't return 0 for \"f\".\n");
656 }
657 if (u_strspn(testString, dc) != 0) {
658 log_err("u_strspn couldn't find first letter a (skip d or c).\n");
659 }
660 if (u_strspn(testString, abcd) != u_strlen(testString)) {
661 log_err("u_strspn couldn't skip over the whole string.\n");
662 }
663 if (u_strspn(testString, empty) != 0) {
664 log_err("u_strspn should have returned 0 for empty string.\n");
665 }
666
667 log_verbose("Testing u_strspn() with surrogates");
668 if (u_strspn(testSurrogateString, surrMatchSetBad) != 2) {
669 log_err("u_strspn couldn't skip 0xdbff or a.\n");
670 }
671 if (u_strspn(testSurrogateString, surrMatchSetBad2) != 2) {
672 log_err("u_strspn couldn't skip 0xdbff or a.\n");
673 }
674 if (u_strspn(testSurrogateString, f) != 0) {
675 log_err("u_strspn couldn't skip d or c (skip first letter).\n");
676 }
677 if (u_strspn(testSurrogateString, dc) != 0) {
678 log_err("u_strspn couldn't skip d or c (skip first letter).\n");
679 }
680 if (u_strspn(testSurrogateString, cd) != 0) {
681 log_err("u_strspn couldn't skip d or c (skip first letter).\n");
682 }
683 if (u_strspn(testSurrogateString, testSurrogateString) != u_strlen(testSurrogateString)) {
684 log_err("u_strspn couldn't skip whole string.\n");
685 }
686 if (u_strspn(testSurrogateString, surrMatchSet1) != 0) {
687 log_err("u_strspn couldn't skip \"0xdbff, 0xdfff\" (get first letter).\n");
688 }
689 if (u_strspn(testSurrogateString, surrMatchSetBad3) != 5) {
690 log_err("u_strspn couldn't skip \"0xdbff, a, b, 0xdbff, 0xdfff\".\n");
691 }
692 if (u_strspn(testSurrogateString, surrMatchSet4) != 0) {
693 log_err("u_strspn should have returned 0 for empty string.\n");
694 }
695}
696
697/*
698 * All binary Unicode string searches should behave the same for equivalent input.
699 * See Jitterbug 2145.
700 * There are some new functions, too - just test them all.
701 */
702static void
703TestSurrogateSearching() {
704 static const UChar s[]={
705 /* 0 1 2 3 4 5 6 7 8 9 10 11 */
706 0x61, 0xd801, 0xdc02, 0x61, 0xdc02, 0x61, 0xd801, 0x61, 0xd801, 0xdc02, 0x61, 0
707 }, sub_a[]={
708 0x61, 0
709 }, sub_b[]={
710 0x62, 0
711 }, sub_lead[]={
712 0xd801, 0
713 }, sub_trail[]={
714 0xdc02, 0
715 }, sub_supp[]={
716 0xd801, 0xdc02, 0
717 }, sub_supp2[]={
718 0xd801, 0xdc03, 0
719 }, sub_a_lead[]={
720 0x61, 0xd801, 0
721 }, sub_trail_a[]={
722 0xdc02, 0x61, 0
723 }, sub_aba[]={
724 0x61, 0x62, 0x61, 0
725 };
726 static const UChar a=0x61, b=0x62, lead=0xd801, trail=0xdc02, nul=0;
727 static const UChar32 supp=0x10402, supp2=0x10403, ill=0x123456;
728
729 const UChar *first, *last;
730
731 /* search for NUL code point: find end of string */
732 first=s+u_strlen(s);
733
734 if(
735 first!=u_strchr(s, nul) ||
736 first!=u_strchr32(s, nul) ||
737 first!=u_memchr(s, nul, LENGTHOF(s)) ||
738 first!=u_memchr32(s, nul, LENGTHOF(s)) ||
739 first!=u_strrchr(s, nul) ||
740 first!=u_strrchr32(s, nul) ||
741 first!=u_memrchr(s, nul, LENGTHOF(s)) ||
742 first!=u_memrchr32(s, nul, LENGTHOF(s))
743 ) {
744 log_err("error: one of the u_str[|mem][r]chr[32](s, nul) does not find the terminator of s\n");
745 }
746
747 /* search for empty substring: find beginning of string */
748 if(
749 s!=u_strstr(s, &nul) ||
750 s!=u_strFindFirst(s, -1, &nul, -1) ||
751 s!=u_strFindFirst(s, -1, &nul, 0) ||
752 s!=u_strFindFirst(s, LENGTHOF(s), &nul, -1) ||
753 s!=u_strFindFirst(s, LENGTHOF(s), &nul, 0) ||
754 s!=u_strrstr(s, &nul) ||
755 s!=u_strFindLast(s, -1, &nul, -1) ||
756 s!=u_strFindLast(s, -1, &nul, 0) ||
757 s!=u_strFindLast(s, LENGTHOF(s), &nul, -1) ||
758 s!=u_strFindLast(s, LENGTHOF(s), &nul, 0)
759 ) {
760 log_err("error: one of the u_str[str etc](s, \"\") does not find s itself\n");
761 }
762
763 /* find 'a' in s[1..10[ */
764 first=s+3;
765 last=s+7;
766 if(
767 first!=u_strchr(s+1, a) ||
768 first!=u_strchr32(s+1, a) ||
769 first!=u_memchr(s+1, a, 9) ||
770 first!=u_memchr32(s+1, a, 9) ||
771 first!=u_strstr(s+1, sub_a) ||
772 first!=u_strFindFirst(s+1, -1, sub_a, -1) ||
773 first!=u_strFindFirst(s+1, -1, &a, 1) ||
774 first!=u_strFindFirst(s+1, 9, sub_a, -1) ||
775 first!=u_strFindFirst(s+1, 9, &a, 1) ||
776 (s+10)!=u_strrchr(s+1, a) ||
777 (s+10)!=u_strrchr32(s+1, a) ||
778 last!=u_memrchr(s+1, a, 9) ||
779 last!=u_memrchr32(s+1, a, 9) ||
780 (s+10)!=u_strrstr(s+1, sub_a) ||
781 (s+10)!=u_strFindLast(s+1, -1, sub_a, -1) ||
782 (s+10)!=u_strFindLast(s+1, -1, &a, 1) ||
783 last!=u_strFindLast(s+1, 9, sub_a, -1) ||
784 last!=u_strFindLast(s+1, 9, &a, 1)
785 ) {
786 log_err("error: one of the u_str[chr etc]('a') does not find the correct place\n");
787 }
788
789 /* do not find 'b' in s[1..10[ */
790 if(
791 NULL!=u_strchr(s+1, b) ||
792 NULL!=u_strchr32(s+1, b) ||
793 NULL!=u_memchr(s+1, b, 9) ||
794 NULL!=u_memchr32(s+1, b, 9) ||
795 NULL!=u_strstr(s+1, sub_b) ||
796 NULL!=u_strFindFirst(s+1, -1, sub_b, -1) ||
797 NULL!=u_strFindFirst(s+1, -1, &b, 1) ||
798 NULL!=u_strFindFirst(s+1, 9, sub_b, -1) ||
799 NULL!=u_strFindFirst(s+1, 9, &b, 1) ||
800 NULL!=u_strrchr(s+1, b) ||
801 NULL!=u_strrchr32(s+1, b) ||
802 NULL!=u_memrchr(s+1, b, 9) ||
803 NULL!=u_memrchr32(s+1, b, 9) ||
804 NULL!=u_strrstr(s+1, sub_b) ||
805 NULL!=u_strFindLast(s+1, -1, sub_b, -1) ||
806 NULL!=u_strFindLast(s+1, -1, &b, 1) ||
807 NULL!=u_strFindLast(s+1, 9, sub_b, -1) ||
808 NULL!=u_strFindLast(s+1, 9, &b, 1)
809 ) {
810 log_err("error: one of the u_str[chr etc]('b') incorrectly finds something\n");
811 }
812
813 /* do not find a non-code point in s[1..10[ */
814 if(
815 NULL!=u_strchr32(s+1, ill) ||
816 NULL!=u_memchr32(s+1, ill, 9) ||
817 NULL!=u_strrchr32(s+1, ill) ||
818 NULL!=u_memrchr32(s+1, ill, 9)
819 ) {
820 log_err("error: one of the u_str[chr etc](illegal code point) incorrectly finds something\n");
821 }
822
823 /* find U+d801 in s[1..10[ */
824 first=s+6;
825 if(
826 first!=u_strchr(s+1, lead) ||
827 first!=u_strchr32(s+1, lead) ||
828 first!=u_memchr(s+1, lead, 9) ||
829 first!=u_memchr32(s+1, lead, 9) ||
830 first!=u_strstr(s+1, sub_lead) ||
831 first!=u_strFindFirst(s+1, -1, sub_lead, -1) ||
832 first!=u_strFindFirst(s+1, -1, &lead, 1) ||
833 first!=u_strFindFirst(s+1, 9, sub_lead, -1) ||
834 first!=u_strFindFirst(s+1, 9, &lead, 1) ||
835 first!=u_strrchr(s+1, lead) ||
836 first!=u_strrchr32(s+1, lead) ||
837 first!=u_memrchr(s+1, lead, 9) ||
838 first!=u_memrchr32(s+1, lead, 9) ||
839 first!=u_strrstr(s+1, sub_lead) ||
840 first!=u_strFindLast(s+1, -1, sub_lead, -1) ||
841 first!=u_strFindLast(s+1, -1, &lead, 1) ||
842 first!=u_strFindLast(s+1, 9, sub_lead, -1) ||
843 first!=u_strFindLast(s+1, 9, &lead, 1)
844 ) {
845 log_err("error: one of the u_str[chr etc](U+d801) does not find the correct place\n");
846 }
847
848 /* find U+dc02 in s[1..10[ */
849 first=s+4;
850 if(
851 first!=u_strchr(s+1, trail) ||
852 first!=u_strchr32(s+1, trail) ||
853 first!=u_memchr(s+1, trail, 9) ||
854 first!=u_memchr32(s+1, trail, 9) ||
855 first!=u_strstr(s+1, sub_trail) ||
856 first!=u_strFindFirst(s+1, -1, sub_trail, -1) ||
857 first!=u_strFindFirst(s+1, -1, &trail, 1) ||
858 first!=u_strFindFirst(s+1, 9, sub_trail, -1) ||
859 first!=u_strFindFirst(s+1, 9, &trail, 1) ||
860 first!=u_strrchr(s+1, trail) ||
861 first!=u_strrchr32(s+1, trail) ||
862 first!=u_memrchr(s+1, trail, 9) ||
863 first!=u_memrchr32(s+1, trail, 9) ||
864 first!=u_strrstr(s+1, sub_trail) ||
865 first!=u_strFindLast(s+1, -1, sub_trail, -1) ||
866 first!=u_strFindLast(s+1, -1, &trail, 1) ||
867 first!=u_strFindLast(s+1, 9, sub_trail, -1) ||
868 first!=u_strFindLast(s+1, 9, &trail, 1)
869 ) {
870 log_err("error: one of the u_str[chr etc](U+dc02) does not find the correct place\n");
871 }
872
873 /* find U+10402 in s[1..10[ */
874 first=s+1;
875 last=s+8;
876 if(
877 first!=u_strchr32(s+1, supp) ||
878 first!=u_memchr32(s+1, supp, 9) ||
879 first!=u_strstr(s+1, sub_supp) ||
880 first!=u_strFindFirst(s+1, -1, sub_supp, -1) ||
881 first!=u_strFindFirst(s+1, -1, sub_supp, 2) ||
882 first!=u_strFindFirst(s+1, 9, sub_supp, -1) ||
883 first!=u_strFindFirst(s+1, 9, sub_supp, 2) ||
884 last!=u_strrchr32(s+1, supp) ||
885 last!=u_memrchr32(s+1, supp, 9) ||
886 last!=u_strrstr(s+1, sub_supp) ||
887 last!=u_strFindLast(s+1, -1, sub_supp, -1) ||
888 last!=u_strFindLast(s+1, -1, sub_supp, 2) ||
889 last!=u_strFindLast(s+1, 9, sub_supp, -1) ||
890 last!=u_strFindLast(s+1, 9, sub_supp, 2)
891 ) {
892 log_err("error: one of the u_str[chr etc](U+10402) does not find the correct place\n");
893 }
894
895 /* do not find U+10402 in a single UChar */
896 if(
897 NULL!=u_memchr32(s+1, supp, 1) ||
898 NULL!=u_strFindFirst(s+1, 1, sub_supp, -1) ||
899 NULL!=u_strFindFirst(s+1, 1, sub_supp, 2) ||
900 NULL!=u_memrchr32(s+1, supp, 1) ||
901 NULL!=u_strFindLast(s+1, 1, sub_supp, -1) ||
902 NULL!=u_strFindLast(s+1, 1, sub_supp, 2) ||
903 NULL!=u_memrchr32(s+2, supp, 1) ||
904 NULL!=u_strFindLast(s+2, 1, sub_supp, -1) ||
905 NULL!=u_strFindLast(s+2, 1, sub_supp, 2)
906 ) {
907 log_err("error: one of the u_str[chr etc](U+10402) incorrectly finds a supplementary c.p. in a single UChar\n");
908 }
909
910 /* do not find U+10403 in s[1..10[ */
911 if(
912 NULL!=u_strchr32(s+1, supp2) ||
913 NULL!=u_memchr32(s+1, supp2, 9) ||
914 NULL!=u_strstr(s+1, sub_supp2) ||
915 NULL!=u_strFindFirst(s+1, -1, sub_supp2, -1) ||
916 NULL!=u_strFindFirst(s+1, -1, sub_supp2, 2) ||
917 NULL!=u_strFindFirst(s+1, 9, sub_supp2, -1) ||
918 NULL!=u_strFindFirst(s+1, 9, sub_supp2, 2) ||
919 NULL!=u_strrchr32(s+1, supp2) ||
920 NULL!=u_memrchr32(s+1, supp2, 9) ||
921 NULL!=u_strrstr(s+1, sub_supp2) ||
922 NULL!=u_strFindLast(s+1, -1, sub_supp2, -1) ||
923 NULL!=u_strFindLast(s+1, -1, sub_supp2, 2) ||
924 NULL!=u_strFindLast(s+1, 9, sub_supp2, -1) ||
925 NULL!=u_strFindLast(s+1, 9, sub_supp2, 2)
926 ) {
927 log_err("error: one of the u_str[chr etc](U+10403) incorrectly finds something\n");
928 }
929
930 /* find <0061 d801> in s[1..10[ */
931 first=s+5;
932 if(
933 first!=u_strstr(s+1, sub_a_lead) ||
934 first!=u_strFindFirst(s+1, -1, sub_a_lead, -1) ||
935 first!=u_strFindFirst(s+1, -1, sub_a_lead, 2) ||
936 first!=u_strFindFirst(s+1, 9, sub_a_lead, -1) ||
937 first!=u_strFindFirst(s+1, 9, sub_a_lead, 2) ||
938 first!=u_strrstr(s+1, sub_a_lead) ||
939 first!=u_strFindLast(s+1, -1, sub_a_lead, -1) ||
940 first!=u_strFindLast(s+1, -1, sub_a_lead, 2) ||
941 first!=u_strFindLast(s+1, 9, sub_a_lead, -1) ||
942 first!=u_strFindLast(s+1, 9, sub_a_lead, 2)
943 ) {
944 log_err("error: one of the u_str[str etc](<0061 d801>) does not find the correct place\n");
945 }
946
947 /* find <dc02 0061> in s[1..10[ */
948 first=s+4;
949 if(
950 first!=u_strstr(s+1, sub_trail_a) ||
951 first!=u_strFindFirst(s+1, -1, sub_trail_a, -1) ||
952 first!=u_strFindFirst(s+1, -1, sub_trail_a, 2) ||
953 first!=u_strFindFirst(s+1, 9, sub_trail_a, -1) ||
954 first!=u_strFindFirst(s+1, 9, sub_trail_a, 2) ||
955 first!=u_strrstr(s+1, sub_trail_a) ||
956 first!=u_strFindLast(s+1, -1, sub_trail_a, -1) ||
957 first!=u_strFindLast(s+1, -1, sub_trail_a, 2) ||
958 first!=u_strFindLast(s+1, 9, sub_trail_a, -1) ||
959 first!=u_strFindLast(s+1, 9, sub_trail_a, 2)
960 ) {
961 log_err("error: one of the u_str[str etc](<dc02 0061>) does not find the correct place\n");
962 }
963
964 /* do not find "aba" in s[1..10[ */
965 if(
966 NULL!=u_strstr(s+1, sub_aba) ||
967 NULL!=u_strFindFirst(s+1, -1, sub_aba, -1) ||
968 NULL!=u_strFindFirst(s+1, -1, sub_aba, 3) ||
969 NULL!=u_strFindFirst(s+1, 9, sub_aba, -1) ||
970 NULL!=u_strFindFirst(s+1, 9, sub_aba, 3) ||
971 NULL!=u_strrstr(s+1, sub_aba) ||
972 NULL!=u_strFindLast(s+1, -1, sub_aba, -1) ||
973 NULL!=u_strFindLast(s+1, -1, sub_aba, 3) ||
974 NULL!=u_strFindLast(s+1, 9, sub_aba, -1) ||
975 NULL!=u_strFindLast(s+1, 9, sub_aba, 3)
976 ) {
977 log_err("error: one of the u_str[str etc](\"aba\") incorrectly finds something\n");
978 }
979}
980
981static void TestStringCopy()
982{
983 UChar temp[40];
984 UChar *result=0;
985 UChar subString[5];
986 UChar uchars[]={0x61, 0x62, 0x63, 0x00};
987 char charOut[40];
988 char chars[]="abc"; /* needs default codepage */
989
990 log_verbose("Testing u_uastrncpy() and u_uastrcpy()");
991
992 u_uastrcpy(temp, "abc");
993 if(u_strcmp(temp, uchars) != 0) {
994 log_err("There is an error in u_uastrcpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp));
995 }
996
997 temp[0] = 0xFB; /* load garbage into it */
998 temp[1] = 0xFB;
999 temp[2] = 0xFB;
1000 temp[3] = 0xFB;
1001
1002 u_uastrncpy(temp, "abcabcabc", 3);
1003 if(u_strncmp(uchars, temp, 3) != 0){
1004 log_err("There is an error in u_uastrncpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp));
1005 }
1006 if(temp[3] != 0xFB) {
1007 log_err("u_uastrncpy wrote past it's bounds. Expected undisturbed byte at 3\n");
1008 }
1009
1010 charOut[0] = (char)0x7B; /* load garbage into it */
1011 charOut[1] = (char)0x7B;
1012 charOut[2] = (char)0x7B;
1013 charOut[3] = (char)0x7B;
1014
1015 temp[0] = 0x0061;
1016 temp[1] = 0x0062;
1017 temp[2] = 0x0063;
1018 temp[3] = 0x0061;
1019 temp[4] = 0x0062;
1020 temp[5] = 0x0063;
1021 temp[6] = 0x0000;
1022
1023 u_austrncpy(charOut, temp, 3);
1024 if(strncmp(chars, charOut, 3) != 0){
1025 log_err("There is an error in u_austrncpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp));
1026 }
1027 if(charOut[3] != (char)0x7B) {
1028 log_err("u_austrncpy wrote past it's bounds. Expected undisturbed byte at 3\n");
1029 }
1030
1031 /*Testing u_strchr()*/
1032 log_verbose("Testing u_strchr\n");
1033 temp[0]=0x42;
1034 temp[1]=0x62;
1035 temp[2]=0x62;
1036 temp[3]=0x63;
1037 temp[4]=0xd841;
1038 temp[5]=0xd841;
1039 temp[6]=0xdc02;
1040 temp[7]=0;
1041 result=u_strchr(temp, (UChar)0x62);
1042 if(result != temp+1){
1043 log_err("There is an error in u_strchr() Expected match at position 1 Got %ld (pointer 0x%lx)\n", result-temp, result);
1044 }
1045 /*Testing u_strstr()*/
1046 log_verbose("Testing u_strstr\n");
1047 subString[0]=0x62;
1048 subString[1]=0x63;
1049 subString[2]=0;
1050 result=u_strstr(temp, subString);
1051 if(result != temp+2){
1052 log_err("There is an error in u_strstr() Expected match at position 2 Got %ld (pointer 0x%lx)\n", result-temp, result);
1053 }
1054 result=u_strstr(temp, subString+2); /* subString+2 is an empty string */
1055 if(result != temp){
1056 log_err("There is an error in u_strstr() Expected match at position 0 Got %ld (pointer 0x%lx)\n", result-temp, result);
1057 }
1058 result=u_strstr(subString, temp);
1059 if(result != NULL){
1060 log_err("There is an error in u_strstr() Expected NULL \"not found\" Got non-NULL \"found\" result\n");
1061 }
1062
1063 /*Testing u_strchr32*/
1064 log_verbose("Testing u_strchr32\n");
1065 result=u_strchr32(temp, (UChar32)0x62);
1066 if(result != temp+1){
1067 log_err("There is an error in u_strchr32() Expected match at position 1 Got %ld (pointer 0x%lx)\n", result-temp, result);
1068 }
1069 result=u_strchr32(temp, (UChar32)0xfb);
1070 if(result != NULL){
1071 log_err("There is an error in u_strchr32() Expected NULL \"not found\" Got non-NULL \"found\" result\n");
1072 }
1073 result=u_strchr32(temp, (UChar32)0x20402);
1074 if(result != temp+5){
1075 log_err("There is an error in u_strchr32() Expected match at position 5 Got %ld (pointer 0x%lx)\n", result-temp, result);
1076 }
1077
1078 temp[7]=0xfc00;
1079 result=u_memchr32(temp, (UChar32)0x20402, 7);
1080 if(result != temp+5){
1081 log_err("There is an error in u_memchr32() Expected match at position 5 Got %ld (pointer 0x%lx)\n", result-temp, result);
1082 }
1083 result=u_memchr32(temp, (UChar32)0x20402, 6);
1084 if(result != NULL){
1085 log_err("There is an error in u_memchr32() Expected no match Got %ld (pointer 0x%lx)\n", result-temp, result);
1086 }
1087 result=u_memchr32(temp, (UChar32)0x20402, 1);
1088 if(result != NULL){
1089 log_err("There is an error in u_memchr32() Expected no match Got %ld (pointer 0x%lx)\n", result-temp, result);
1090 }
1091 result=u_memchr32(temp, (UChar32)0xfc00, 8);
1092 if(result != temp+7){
1093 log_err("There is an error in u_memchr32() Expected match at position 7 Got %ld (pointer 0x%lx)\n", result-temp, result);
1094 }
1095}
1096
1097/* test u_unescape() and u_unescapeAt() ------------------------------------- */
1098
1099static void
1100TestUnescape() {
1101 static UChar buffer[200];
1102
1103 static const char* input =
1104 "Sch\\u00f6nes Auto: \\u20ac 11240.\\fPrivates Zeichen: \\U00102345\\e\\cC\\n \\x1b\\x{263a}";
1105
1106 static const UChar expect[]={
1107 0x53, 0x63, 0x68, 0xf6, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x3a, 0x20,
1108 0x20ac, 0x20, 0x31, 0x31, 0x32, 0x34, 0x30, 0x2e, 0x0c,
1109 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x73, 0x20,
1110 0x5a, 0x65, 0x69, 0x63, 0x68, 0x65, 0x6e, 0x3a, 0x20, 0xdbc8, 0xdf45, 0x1b, 0x03, 0x0a, 0x20, 0x1b, 0x263A, 0
1111 };
1112 static const int32_t explength = sizeof(expect)/sizeof(expect[0])-1;
1113 int32_t length;
1114
1115 /* test u_unescape() */
1116 length=u_unescape(input, buffer, sizeof(buffer)/sizeof(buffer[0]));
1117 if(length!=explength || u_strcmp(buffer, expect)!=0) {
1118 log_err("failure in u_unescape(): length %d!=%d and/or incorrect result string\n", length,
1119 explength);
1120 }
1121
1122 /* try preflighting */
1123 length=u_unescape(input, NULL, sizeof(buffer)/sizeof(buffer[0]));
1124 if(length!=explength || u_strcmp(buffer, expect)!=0) {
1125 log_err("failure in u_unescape(preflighting): length %d!=%d\n", length, explength);
1126 }
1127
1128 /* ### TODO: test u_unescapeAt() */
1129}
1130
1131/* test code point counting functions --------------------------------------- */
1132
1133/* reference implementation of u_strHasMoreChar32Than() */
1134static int32_t
1135_refStrHasMoreChar32Than(const UChar *s, int32_t length, int32_t number) {
1136 int32_t count=u_countChar32(s, length);
1137 return count>number;
1138}
1139
1140/* compare the real function against the reference */
1141static void
1142_testStrHasMoreChar32Than(const UChar *s, int32_t i, int32_t length, int32_t number) {
1143 if(u_strHasMoreChar32Than(s, length, number)!=_refStrHasMoreChar32Than(s, length, number)) {
1144 log_err("u_strHasMoreChar32Than(s+%d, %d, %d)=%hd is wrong\n",
1145 i, length, number, u_strHasMoreChar32Than(s, length, number));
1146 }
1147}
1148
1149static void
1150TestCountChar32() {
1151 static const UChar string[]={
1152 0x61, 0x62, 0xd800, 0xdc00,
1153 0xd801, 0xdc01, 0x63, 0xd802,
1154 0x64, 0xdc03, 0x65, 0x66,
1155 0xd804, 0xdc04, 0xd805, 0xdc05,
1156 0x67
1157 };
1158 UChar buffer[100];
1159 int32_t i, length, number;
1160
1161 /* test u_strHasMoreChar32Than() with length>=0 */
1162 length=LENGTHOF(string);
1163 while(length>=0) {
1164 for(i=0; i<=length; ++i) {
1165 for(number=-1; number<=((length-i)+2); ++number) {
1166 _testStrHasMoreChar32Than(string+i, i, length-i, number);
1167 }
1168 }
1169 --length;
1170 }
1171
1172 /* test u_strHasMoreChar32Than() with NUL-termination (length=-1) */
1173 length=LENGTHOF(string);
1174 u_memcpy(buffer, string, length);
1175 while(length>=0) {
1176 buffer[length]=0;
1177 for(i=0; i<=length; ++i) {
1178 for(number=-1; number<=((length-i)+2); ++number) {
1179 _testStrHasMoreChar32Than(string+i, i, -1, number);
1180 }
1181 }
1182 --length;
1183 }
1184
1185 /* test u_strHasMoreChar32Than() with NULL string (bad input) */
1186 for(length=-1; length<=1; ++length) {
1187 for(i=0; i<=length; ++i) {
1188 for(number=-2; number<=2; ++number) {
1189 _testStrHasMoreChar32Than(NULL, 0, length, number);
1190 }
1191 }
1192 }
1193}
1194
1195/* UCharIterator ------------------------------------------------------------ */
1196
1197/*
1198 * Compare results from two iterators, should be same.
1199 * Assume that the text is not empty and that
1200 * iteration start==0 and iteration limit==length.
1201 */
1202static void
1203compareIterators(UCharIterator *iter1, const char *n1,
1204 UCharIterator *iter2, const char *n2) {
1205 int32_t i, pos1, pos2, middle, length;
1206 UChar32 c1, c2;
1207
1208 /* compare lengths */
1209 length=iter1->getIndex(iter1, UITER_LENGTH);
1210 pos2=iter2->getIndex(iter2, UITER_LENGTH);
1211 if(length!=pos2) {
1212 log_err("%s->getIndex(length)=%d != %d=%s->getIndex(length)\n", n1, length, pos2, n2);
1213 return;
1214 }
1215
1216 /* set into the middle */
1217 middle=length/2;
1218
1219 pos1=iter1->move(iter1, middle, UITER_ZERO);
1220 if(pos1!=middle) {
1221 log_err("%s->move(from 0 to middle %d)=%d does not move to the middle\n", n1, middle, pos1);
1222 return;
1223 }
1224
1225 pos2=iter2->move(iter2, middle, UITER_ZERO);
1226 if(pos2!=middle) {
1227 log_err("%s->move(from 0 to middle %d)=%d does not move to the middle\n", n2, middle, pos2);
1228 return;
1229 }
1230
1231 /* test current() */
1232 c1=iter1->current(iter1);
1233 c2=iter2->current(iter2);
1234 if(c1!=c2) {
1235 log_err("%s->current()=U+%04x != U+%04x=%s->current() at middle=%d\n", n1, c1, c2, n2, middle);
1236 return;
1237 }
1238
1239 /* move forward 3 UChars */
1240 for(i=0; i<3; ++i) {
1241 c1=iter1->next(iter1);
1242 c2=iter2->next(iter2);
1243 if(c1!=c2) {
1244 log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1245 return;
1246 }
1247 }
1248
1249 /* move backward 5 UChars */
1250 for(i=0; i<5; ++i) {
1251 c1=iter1->previous(iter1);
1252 c2=iter2->previous(iter2);
1253 if(c1!=c2) {
1254 log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1255 return;
1256 }
1257 }
1258
1259 /* iterate forward from the beginning */
1260 pos1=iter1->move(iter1, 0, UITER_START);
1261 if(pos1<0) {
1262 log_err("%s->move(start) failed\n", n1);
1263 return;
1264 }
1265 if(!iter1->hasNext(iter1)) {
1266 log_err("%s->hasNext() at the start returns FALSE\n", n1);
1267 return;
1268 }
1269
1270 pos2=iter2->move(iter2, 0, UITER_START);
1271 if(pos2<0) {
1272 log_err("%s->move(start) failed\n", n2);
1273 return;
1274 }
1275 if(!iter2->hasNext(iter2)) {
1276 log_err("%s->hasNext() at the start returns FALSE\n", n2);
1277 return;
1278 }
1279
1280 do {
1281 c1=iter1->next(iter1);
1282 c2=iter2->next(iter2);
1283 if(c1!=c2) {
1284 log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1285 return;
1286 }
1287 } while(c1>=0);
1288
1289 if(iter1->hasNext(iter1)) {
1290 log_err("%s->hasNext() at the end returns TRUE\n", n1);
1291 return;
1292 }
1293 if(iter2->hasNext(iter2)) {
1294 log_err("%s->hasNext() at the end returns TRUE\n", n2);
1295 return;
1296 }
1297
1298 /* back to the middle */
1299 pos1=iter1->move(iter1, middle, UITER_ZERO);
1300 if(pos1!=middle) {
1301 log_err("%s->move(from end to middle %d)=%d does not move to the middle\n", n1, middle, pos1);
1302 return;
1303 }
1304
1305 pos2=iter2->move(iter2, middle, UITER_ZERO);
1306 if(pos2!=middle) {
1307 log_err("%s->move(from end to middle %d)=%d does not move to the middle\n", n2, middle, pos2);
1308 return;
1309 }
1310
1311 /* move to index 1 */
1312 pos1=iter1->move(iter1, 1, UITER_ZERO);
1313 if(pos1!=1) {
1314 log_err("%s->move(from middle %d to 1)=%d does not move to 1\n", n1, middle, pos1);
1315 return;
1316 }
1317
1318 pos2=iter2->move(iter2, 1, UITER_ZERO);
1319 if(pos2!=1) {
1320 log_err("%s->move(from middle %d to 1)=%d does not move to 1\n", n2, middle, pos2);
1321 return;
1322 }
1323
1324 /* iterate backward from the end */
1325 pos1=iter1->move(iter1, 0, UITER_LIMIT);
1326 if(pos1<0) {
1327 log_err("%s->move(limit) failed\n", n1);
1328 return;
1329 }
1330 if(!iter1->hasPrevious(iter1)) {
1331 log_err("%s->hasPrevious() at the end returns FALSE\n", n1);
1332 return;
1333 }
1334
1335 pos2=iter2->move(iter2, 0, UITER_LIMIT);
1336 if(pos2<0) {
1337 log_err("%s->move(limit) failed\n", n2);
1338 return;
1339 }
1340 if(!iter2->hasPrevious(iter2)) {
1341 log_err("%s->hasPrevious() at the end returns FALSE\n", n2);
1342 return;
1343 }
1344
1345 do {
1346 c1=iter1->previous(iter1);
1347 c2=iter2->previous(iter2);
1348 if(c1!=c2) {
1349 log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1350 return;
1351 }
1352 } while(c1>=0);
1353
1354 if(iter1->hasPrevious(iter1)) {
1355 log_err("%s->hasPrevious() at the start returns TRUE\n", n1);
1356 return;
1357 }
1358 if(iter2->hasPrevious(iter2)) {
1359 log_err("%s->hasPrevious() at the start returns TRUE\n", n2);
1360 return;
1361 }
1362}
1363
1364/*
1365 * Test the iterator's getState() and setState() functions.
1366 * iter1 and iter2 must be set up for the same iterator type and the same string
1367 * but may be physically different structs (different addresses).
1368 *
1369 * Assume that the text is not empty and that
1370 * iteration start==0 and iteration limit==length.
1371 * It must be 2<=middle<=length-2.
1372 */
1373static void
1374testIteratorState(UCharIterator *iter1, UCharIterator *iter2, const char *n, int32_t middle) {
1375 UChar32 u[4];
1376
1377 UErrorCode errorCode;
1378 UChar32 c;
1379 uint32_t state;
1380 int32_t i, j;
1381
1382 /* get four UChars from the middle of the string */
1383 iter1->move(iter1, middle-2, UITER_ZERO);
1384 for(i=0; i<4; ++i) {
1385 c=iter1->next(iter1);
1386 if(c<0) {
1387 /* the test violates the assumptions, see comment above */
1388 log_err("test error: %s[%d]=%d\n", n, middle-2+i, c);
1389 return;
1390 }
1391 u[i]=c;
1392 }
1393
1394 /* move to the middle and get the state */
1395 iter1->move(iter1, -2, UITER_CURRENT);
1396 state=uiter_getState(iter1);
1397
1398 /* set the state into the second iterator and compare the results */
1399 errorCode=U_ZERO_ERROR;
1400 uiter_setState(iter2, state, &errorCode);
1401 if(U_FAILURE(errorCode)) {
1402 log_err("%s->setState(0x%x) failed: %s\n", n, state, u_errorName(errorCode));
1403 return;
1404 }
1405
1406 c=iter2->current(iter2);
1407 if(c!=u[2]) {
1408 log_err("%s->current(at %d)=U+%04x!=U+%04x\n", n, middle, c, u[2]);
1409 }
1410
1411 c=iter2->previous(iter2);
1412 if(c!=u[1]) {
1413 log_err("%s->previous(at %d)=U+%04x!=U+%04x\n", n, middle-1, c, u[1]);
1414 }
1415
1416 iter2->move(iter2, 2, UITER_CURRENT);
1417 c=iter2->next(iter2);
1418 if(c!=u[3]) {
1419 log_err("%s->next(at %d)=U+%04x!=U+%04x\n", n, middle+1, c, u[3]);
1420 }
1421
1422 iter2->move(iter2, -3, UITER_CURRENT);
1423 c=iter2->previous(iter2);
1424 if(c!=u[0]) {
1425 log_err("%s->previous(at %d)=U+%04x!=U+%04x\n", n, middle-2, c, u[0]);
1426 }
1427
1428 /* move the second iterator back to the middle */
1429 iter2->move(iter2, 1, UITER_CURRENT);
1430 iter2->next(iter2);
1431
1432 /* check that both are in the middle */
1433 i=iter1->getIndex(iter1, UITER_CURRENT);
1434 j=iter2->getIndex(iter2, UITER_CURRENT);
1435 if(i!=middle) {
1436 log_err("%s->getIndex(current)=%d!=%d as expected\n", n, i, middle);
1437 }
1438 if(i!=j) {
1439 log_err("%s->getIndex(current)=%d!=%d after setState()\n", n, j, i);
1440 }
1441
1442 /* compare lengths */
1443 i=iter1->getIndex(iter1, UITER_LENGTH);
1444 j=iter2->getIndex(iter2, UITER_LENGTH);
1445 if(i!=j) {
1446 log_err("%s->getIndex(length)=%d!=%d before/after setState()\n", n, i, j);
1447 }
1448}
1449
1450static void
1451TestUCharIterator() {
1452 static const UChar text[]={
1453 0x61, 0x62, 0x63, 0xd801, 0xdffd, 0x78, 0x79, 0x7a, 0
1454 };
1455 char bytes[40];
1456
1457 UCharIterator iter, iter1, iter2;
1458 UConverter *cnv;
1459 UErrorCode errorCode;
1460 int32_t length;
1461
1462 /* simple API/code coverage - test NOOP UCharIterator */
1463 uiter_setString(&iter, NULL, 0);
1464 if( iter.current(&iter)!=-1 || iter.next(&iter)!=-1 || iter.previous(&iter)!=-1 ||
1465 iter.move(&iter, 1, UITER_CURRENT) || iter.getIndex(&iter, UITER_CURRENT)!=0 ||
1466 iter.hasNext(&iter) || iter.hasPrevious(&iter)
1467 ) {
1468 log_err("NOOP UCharIterator behaves unexpectedly\n");
1469 }
1470
1471 /* test get/set state */
1472 length=LENGTHOF(text)-1;
1473 uiter_setString(&iter1, text, -1);
1474 uiter_setString(&iter2, text, length);
1475 testIteratorState(&iter1, &iter2, "UTF16IteratorState", length/2);
1476 testIteratorState(&iter1, &iter2, "UTF16IteratorStatePlus1", length/2+1);
1477
1478 /* compare the same string between UTF-16 and UTF-8 UCharIterators ------ */
1479 errorCode=U_ZERO_ERROR;
1480 u_strToUTF8(bytes, sizeof(bytes), &length, text, -1, &errorCode);
1481 if(U_FAILURE(errorCode)) {
1482 log_err("u_strToUTF8() failed, %s\n", u_errorName(errorCode));
1483 return;
1484 }
1485
1486 uiter_setString(&iter1, text, -1);
1487 uiter_setUTF8(&iter2, bytes, length);
1488 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator");
1489
1490 /* try again with length=-1 */
1491 uiter_setUTF8(&iter2, bytes, -1);
1492 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator_1");
1493
1494 /* test get/set state */
1495 length=LENGTHOF(text)-1;
1496 uiter_setUTF8(&iter1, bytes, -1);
1497 testIteratorState(&iter1, &iter2, "UTF8IteratorState", length/2);
1498 testIteratorState(&iter1, &iter2, "UTF8IteratorStatePlus1", length/2+1);
1499
1500 /* compare the same string between UTF-16 and UTF-16BE UCharIterators --- */
1501 errorCode=U_ZERO_ERROR;
1502 cnv=ucnv_open("UTF-16BE", &errorCode);
1503 length=ucnv_fromUChars(cnv, bytes, sizeof(bytes), text, -1, &errorCode);
1504 ucnv_close(cnv);
1505 if(U_FAILURE(errorCode)) {
1506 log_err("ucnv_fromUChars(UTF-16BE) failed, %s\n", u_errorName(errorCode));
1507 return;
1508 }
1509
1510 /* terminate with a _pair_ of 0 bytes - a UChar NUL in UTF-16BE (length is known to be ok) */
1511 bytes[length]=bytes[length+1]=0;
1512
1513 uiter_setString(&iter1, text, -1);
1514 uiter_setUTF16BE(&iter2, bytes, length);
1515 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator");
1516
1517 /* try again with length=-1 */
1518 uiter_setUTF16BE(&iter2, bytes, -1);
1519 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator_1");
1520
1521 /* try again after moving the bytes up one, and with length=-1 */
1522 memmove(bytes+1, bytes, length+2);
1523 uiter_setUTF16BE(&iter2, bytes+1, -1);
1524 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIteratorMoved1");
1525
1526 /* ### TODO test other iterators: CharacterIterator, Replaceable */
1527}
1528
1529#if UCONFIG_NO_COLLATION
1530
1531static void
1532TestUNormIterator() {
1533 /* test nothing */
1534}
1535
1536#else
1537
1538#include "unicode/unorm.h"
1539#include "unorm_it.h"
1540
1541/*
1542 * Compare results from two iterators, should be same.
1543 * Assume that the text is not empty and that
1544 * iteration start==0 and iteration limit==length.
1545 *
1546 * Modified version of compareIterators() but does not assume that indexes
1547 * are available.
1548 */
1549static void
1550compareIterNoIndexes(UCharIterator *iter1, const char *n1,
1551 UCharIterator *iter2, const char *n2,
1552 int32_t middle) {
1553 uint32_t state;
1554 int32_t i;
1555 UChar32 c1, c2;
1556 UErrorCode errorCode;
1557
1558 /* set into the middle */
1559 iter1->move(iter1, middle, UITER_ZERO);
1560 iter2->move(iter2, middle, UITER_ZERO);
1561
1562 /* test current() */
1563 c1=iter1->current(iter1);
1564 c2=iter2->current(iter2);
1565 if(c1!=c2) {
1566 log_err("%s->current()=U+%04x != U+%04x=%s->current() at middle=%d\n", n1, c1, c2, n2, middle);
1567 return;
1568 }
1569
1570 /* move forward 3 UChars */
1571 for(i=0; i<3; ++i) {
1572 c1=iter1->next(iter1);
1573 c2=iter2->next(iter2);
1574 if(c1!=c2) {
1575 log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1576 return;
1577 }
1578 }
1579
1580 /* move backward 5 UChars */
1581 for(i=0; i<5; ++i) {
1582 c1=iter1->previous(iter1);
1583 c2=iter2->previous(iter2);
1584 if(c1!=c2) {
1585 log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1586 return;
1587 }
1588 }
1589
1590 /* iterate forward from the beginning */
1591 iter1->move(iter1, 0, UITER_START);
1592 if(!iter1->hasNext(iter1)) {
1593 log_err("%s->hasNext() at the start returns FALSE\n", n1);
1594 return;
1595 }
1596
1597 iter2->move(iter2, 0, UITER_START);
1598 if(!iter2->hasNext(iter2)) {
1599 log_err("%s->hasNext() at the start returns FALSE\n", n2);
1600 return;
1601 }
1602
1603 do {
1604 c1=iter1->next(iter1);
1605 c2=iter2->next(iter2);
1606 if(c1!=c2) {
1607 log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1608 return;
1609 }
1610 } while(c1>=0);
1611
1612 if(iter1->hasNext(iter1)) {
1613 log_err("%s->hasNext() at the end returns TRUE\n", n1);
1614 return;
1615 }
1616 if(iter2->hasNext(iter2)) {
1617 log_err("%s->hasNext() at the end returns TRUE\n", n2);
1618 return;
1619 }
1620
1621 /* back to the middle */
1622 iter1->move(iter1, middle, UITER_ZERO);
1623 iter2->move(iter2, middle, UITER_ZERO);
1624
1625 /* try get/set state */
1626 while((state=uiter_getState(iter2))==UITER_NO_STATE) {
1627 if(!iter2->hasNext(iter2)) {
1628 log_err("%s has no known state from middle=%d to the end\n", n2, middle);
1629 return;
1630 }
1631 iter2->next(iter2);
1632 }
1633
1634 errorCode=U_ZERO_ERROR;
1635
1636 c2=iter2->current(iter2);
1637 iter2->move(iter2, 0, UITER_ZERO);
1638 uiter_setState(iter2, state, &errorCode);
1639 c1=iter2->current(iter2);
1640 if(U_FAILURE(errorCode) || c1!=c2) {
1641 log_err("%s->current() differs across get/set state, U+%04x vs. U+%04x\n", n2, c2, c1);
1642 return;
1643 }
1644
1645 c2=iter2->previous(iter2);
1646 iter2->move(iter2, 0, UITER_ZERO);
1647 uiter_setState(iter2, state, &errorCode);
1648 c1=iter2->previous(iter2);
1649 if(U_FAILURE(errorCode) || c1!=c2) {
1650 log_err("%s->previous() differs across get/set state, U+%04x vs. U+%04x\n", n2, c2, c1);
1651 return;
1652 }
1653
1654 /* iterate backward from the end */
1655 iter1->move(iter1, 0, UITER_LIMIT);
1656 if(!iter1->hasPrevious(iter1)) {
1657 log_err("%s->hasPrevious() at the end returns FALSE\n", n1);
1658 return;
1659 }
1660
1661 iter2->move(iter2, 0, UITER_LIMIT);
1662 if(!iter2->hasPrevious(iter2)) {
1663 log_err("%s->hasPrevious() at the end returns FALSE\n", n2);
1664 return;
1665 }
1666
1667 do {
1668 c1=iter1->previous(iter1);
1669 c2=iter2->previous(iter2);
1670 if(c1!=c2) {
1671 log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1672 return;
1673 }
1674 } while(c1>=0);
1675
1676 if(iter1->hasPrevious(iter1)) {
1677 log_err("%s->hasPrevious() at the start returns TRUE\n", n1);
1678 return;
1679 }
1680 if(iter2->hasPrevious(iter2)) {
1681 log_err("%s->hasPrevious() at the start returns TRUE\n", n2);
1682 return;
1683 }
1684}
1685
1686/* n2 must have a digit 1 at the end, will be incremented with the normalization mode */
1687static void
1688testUNormIteratorWithText(const UChar *text, int32_t textLength, int32_t middle,
1689 const char *name1, const char *n2) {
1690 UChar buffer[300];
1691 char name2[40];
1692
1693 UCharIterator iter1, iter2, *iter;
1694 UNormIterator *uni;
1695
1696 UNormalizationMode mode;
1697 UErrorCode errorCode;
1698 int32_t length;
1699
1700 /* open a normalizing iterator */
1701 errorCode=U_ZERO_ERROR;
1702 uni=unorm_openIter(NULL, 0, &errorCode);
1703 if(U_FAILURE(errorCode)) {
1704 log_err("unorm_openIter() fails: %s\n", u_errorName(errorCode));
1705 return;
1706 }
1707
1708 /* set iterator 2 to the original text */
1709 uiter_setString(&iter2, text, textLength);
1710
1711 strcpy(name2, n2);
1712
1713 /* test the normalizing iterator for each mode */
1714 for(mode=UNORM_NONE; mode<UNORM_MODE_COUNT; ++mode) {
1715 length=unorm_normalize(text, textLength, mode, 0, buffer, LENGTHOF(buffer), &errorCode);
1716 if(U_FAILURE(errorCode)) {
1717 log_err("unorm_normalize(mode %d) failed: %s\n", mode, u_errorName(errorCode));
1718 break;
1719 }
1720
1721 /* set iterator 1 to the normalized text */
1722 uiter_setString(&iter1, buffer, length);
1723
1724 /* set the normalizing iterator to use iter2 */
1725 iter=unorm_setIter(uni, &iter2, mode, &errorCode);
1726 if(U_FAILURE(errorCode)) {
1727 log_err("unorm_setIter(mode %d) failed: %s\n", mode, u_errorName(errorCode));
1728 break;
1729 }
1730
1731 compareIterNoIndexes(&iter1, name1, iter, name2, middle);
1732 ++name2[strlen(name2)-1];
1733 }
1734
1735 unorm_closeIter(uni);
1736}
1737
1738static void
1739TestUNormIterator() {
1740 static const UChar text[]={ /* must contain <00C5 0327> see u_strchr() below */
1741 0x61, /* 'a' */
1742 0xe4, 0x61, 0x308, /* variations of 'a'+umlaut */
1743 0xc5, 0x327, 0x41, 0x30a, 0x327, 0x41, 0x327, 0x30a, /* variations of 'A'+ring+cedilla */
1744 0xfb03, 0xfb00, 0x69, 0x66, 0x66, 0x69, 0x66, 0xfb01 /* variations of 'ffi' */
1745 };
1746 static const UChar surrogateText[]={
1747 0x6e, 0xd900, 0x6a, 0xdc00, 0xd900, 0xdc00, 0x61
1748 };
1749
1750 UChar longText[300];
1751 int32_t i, middle, length;
1752
1753 length=LENGTHOF(text);
1754 testUNormIteratorWithText(text, length, length/2, "UCharIter", "UNormIter1");
1755 testUNormIteratorWithText(text, length, length, "UCharIterEnd", "UNormIterEnd1");
1756
1757 /* test again, this time with an insane string to cause internal buffer overflows */
1758 middle=u_strchr(text, 0x327)-text; /* see comment at text[] */
1759 memcpy(longText, text, middle*U_SIZEOF_UCHAR);
1760 for(i=0; i<150; ++i) {
1761 longText[middle+i]=0x30a; /* insert many rings between 'A-ring' and cedilla */
1762 }
1763 memcpy(longText+middle+i, text+middle, (LENGTHOF(text)-middle)*U_SIZEOF_UCHAR);
1764
1765 length=LENGTHOF(text)+i;
1766 testUNormIteratorWithText(longText, length, length/2, "UCharIterLong", "UNormIterLong1");
1767 testUNormIteratorWithText(longText, length, length, "UCharIterLongEnd", "UNormIterLongEnd1");
1768
1769 length=LENGTHOF(surrogateText);
1770 testUNormIteratorWithText(surrogateText, length, length/2, "UCharIterSurr", "UNormIterSurr1");
1771 testUNormIteratorWithText(surrogateText, length, length, "UCharIterSurrEnd", "UNormIterSurrEnd1");
1772}
1773
1774#endif