1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2007, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 /******************************************************************************** 7 * 8 * File CNORMTST.C 9 * 10 * Modification History: 11 * Name Description 12 * Madhu Katragadda Ported for C API 13 * synwee added test for quick check 14 * synwee added test for checkFCD 15 *********************************************************************************/ 16 /*tests for u_normalization*/ 17 #include "unicode/utypes.h" 18 #include "unicode/unorm.h" 19 #include "unormimp.h" 20 #include "cintltst.h" 21 22 #if UCONFIG_NO_NORMALIZATION 23 24 void addNormTest(TestNode** root) { 25 /* no normalization - nothing to do */ 26 } 27 28 #else 29 30 #include <stdlib.h> 31 #include <time.h> 32 #include "unicode/uchar.h" 33 #include "unicode/ustring.h" 34 #include "unicode/unorm.h" 35 #include "cnormtst.h" 36 37 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof ((array)[0])) 38 39 static void 40 TestAPI(void); 41 42 static void 43 TestNormCoverage(void); 44 45 static void 46 TestConcatenate(void); 47 48 static void 49 TestNextPrevious(void); 50 51 static void TestIsNormalized(void); 52 53 static void 54 TestFCNFKCClosure(void); 55 56 static void 57 TestQuickCheckPerCP(void); 58 59 static void 60 TestComposition(void); 61 62 const static char* canonTests[][3] = { 63 /* Input*/ /*Decomposed*/ /*Composed*/ 64 { "cat", "cat", "cat" }, 65 { "\\u00e0ardvark", "a\\u0300ardvark", "\\u00e0ardvark", }, 66 67 { "\\u1e0a", "D\\u0307", "\\u1e0a" }, /* D-dot_above*/ 68 { "D\\u0307", "D\\u0307", "\\u1e0a" }, /* D dot_above*/ 69 70 { "\\u1e0c\\u0307", "D\\u0323\\u0307", "\\u1e0c\\u0307" }, /* D-dot_below dot_above*/ 71 { "\\u1e0a\\u0323", "D\\u0323\\u0307", "\\u1e0c\\u0307" }, /* D-dot_above dot_below */ 72 { "D\\u0307\\u0323", "D\\u0323\\u0307", "\\u1e0c\\u0307" }, /* D dot_below dot_above */ 73 74 { "\\u1e10\\u0307\\u0323", "D\\u0327\\u0323\\u0307", "\\u1e10\\u0323\\u0307" }, /*D dot_below cedilla dot_above*/ 75 { "D\\u0307\\u0328\\u0323", "D\\u0328\\u0323\\u0307", "\\u1e0c\\u0328\\u0307" }, /* D dot_above ogonek dot_below*/ 76 77 { "\\u1E14", "E\\u0304\\u0300", "\\u1E14" }, /* E-macron-grave*/ 78 { "\\u0112\\u0300", "E\\u0304\\u0300", "\\u1E14" }, /* E-macron + grave*/ 79 { "\\u00c8\\u0304", "E\\u0300\\u0304", "\\u00c8\\u0304" }, /* E-grave + macron*/ 80 81 { "\\u212b", "A\\u030a", "\\u00c5" }, /* angstrom_sign*/ 82 { "\\u00c5", "A\\u030a", "\\u00c5" }, /* A-ring*/ 83 84 { "\\u00C4ffin", "A\\u0308ffin", "\\u00C4ffin" }, 85 { "\\u00C4\\uFB03n", "A\\u0308\\uFB03n", "\\u00C4\\uFB03n" }, 86 87 { "Henry IV", "Henry IV", "Henry IV" }, 88 { "Henry \\u2163", "Henry \\u2163", "Henry \\u2163" }, 89 90 { "\\u30AC", "\\u30AB\\u3099", "\\u30AC" }, /* ga (Katakana)*/ 91 { "\\u30AB\\u3099", "\\u30AB\\u3099", "\\u30AC" }, /*ka + ten*/ 92 { "\\uFF76\\uFF9E", "\\uFF76\\uFF9E", "\\uFF76\\uFF9E" }, /* hw_ka + hw_ten*/ 93 { "\\u30AB\\uFF9E", "\\u30AB\\uFF9E", "\\u30AB\\uFF9E" }, /* ka + hw_ten*/ 94 { "\\uFF76\\u3099", "\\uFF76\\u3099", "\\uFF76\\u3099" }, /* hw_ka + ten*/ 95 { "A\\u0300\\u0316", "A\\u0316\\u0300", "\\u00C0\\u0316" } /* hw_ka + ten*/ 96 }; 97 98 const static char* compatTests[][3] = { 99 /* Input*/ /*Decomposed */ /*Composed*/ 100 { "cat", "cat", "cat" }, 101 102 { "\\uFB4f", "\\u05D0\\u05DC", "\\u05D0\\u05DC" }, /* Alef-Lamed vs. Alef, Lamed*/ 103 104 { "\\u00C4ffin", "A\\u0308ffin", "\\u00C4ffin" }, 105 { "\\u00C4\\uFB03n", "A\\u0308ffin", "\\u00C4ffin" }, /* ffi ligature -> f + f + i*/ 106 107 { "Henry IV", "Henry IV", "Henry IV" }, 108 { "Henry \\u2163", "Henry IV", "Henry IV" }, 109 110 { "\\u30AC", "\\u30AB\\u3099", "\\u30AC" }, /* ga (Katakana)*/ 111 { "\\u30AB\\u3099", "\\u30AB\\u3099", "\\u30AC" }, /*ka + ten*/ 112 113 { "\\uFF76\\u3099", "\\u30AB\\u3099", "\\u30AC" }, /* hw_ka + ten*/ 114 115 /*These two are broken in Unicode 2.1.2 but fixed in 2.1.5 and later*/ 116 { "\\uFF76\\uFF9E", "\\u30AB\\u3099", "\\u30AC" }, /* hw_ka + hw_ten*/ 117 { "\\u30AB\\uFF9E", "\\u30AB\\u3099", "\\u30AC" } /* ka + hw_ten*/ 118 119 }; 120 121 void addNormTest(TestNode** root); 122 123 void addNormTest(TestNode** root) 124 { 125 addTest(root, &TestAPI, "tscoll/cnormtst/TestAPI"); 126 addTest(root, &TestDecomp, "tscoll/cnormtst/TestDecomp"); 127 addTest(root, &TestCompatDecomp, "tscoll/cnormtst/TestCompatDecomp"); 128 addTest(root, &TestCanonDecompCompose, "tscoll/cnormtst/TestCanonDecompCompose"); 129 addTest(root, &TestCompatDecompCompose, "tscoll/cnormtst/CompatDecompCompose"); 130 addTest(root, &TestNull, "tscoll/cnormtst/TestNull"); 131 addTest(root, &TestQuickCheck, "tscoll/cnormtst/TestQuickCheck"); 132 addTest(root, &TestQuickCheckPerCP, "tscoll/cnormtst/TestQuickCheckPerCP"); 133 addTest(root, &TestIsNormalized, "tscoll/cnormtst/TestIsNormalized"); 134 addTest(root, &TestCheckFCD, "tscoll/cnormtst/TestCheckFCD"); 135 addTest(root, &TestNormCoverage, "tscoll/cnormtst/TestNormCoverage"); 136 addTest(root, &TestConcatenate, "tscoll/cnormtst/TestConcatenate"); 137 addTest(root, &TestNextPrevious, "tscoll/cnormtst/TestNextPrevious"); 138 addTest(root, &TestFCNFKCClosure, "tscoll/cnormtst/TestFCNFKCClosure"); 139 addTest(root, &TestComposition, "tscoll/cnormtst/TestComposition"); 140 } 141 142 void TestDecomp() 143 { 144 UErrorCode status = U_ZERO_ERROR; 145 int32_t x, neededLen, resLen; 146 UChar *source=NULL, *result=NULL; 147 status = U_ZERO_ERROR; 148 resLen=0; 149 log_verbose("Testing unorm_normalize with Decomp canonical\n"); 150 for(x=0; x < LENGTHOF(canonTests); x++) 151 { 152 source=CharsToUChars(canonTests[x][0]); 153 neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFD, 0, NULL, 0, &status); 154 if(status==U_BUFFER_OVERFLOW_ERROR) 155 { 156 status=U_ZERO_ERROR; 157 resLen=neededLen+1; 158 result=(UChar*)malloc(sizeof(UChar*) * resLen); 159 unorm_normalize(source, u_strlen(source), UNORM_NFD, 0, result, resLen, &status); 160 } 161 if(U_FAILURE(status)){ 162 log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source), myErrorName(status) ); 163 } else { 164 assertEqual(result, canonTests[x][1], x); 165 } 166 free(result); 167 free(source); 168 } 169 } 170 171 void TestCompatDecomp() 172 { 173 UErrorCode status = U_ZERO_ERROR; 174 int32_t x, neededLen, resLen; 175 UChar *source=NULL, *result=NULL; 176 status = U_ZERO_ERROR; 177 resLen=0; 178 log_verbose("Testing unorm_normalize with Decomp compat\n"); 179 for(x=0; x < LENGTHOF(compatTests); x++) 180 { 181 source=CharsToUChars(compatTests[x][0]); 182 neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFKD, 0, NULL, 0, &status); 183 if(status==U_BUFFER_OVERFLOW_ERROR) 184 { 185 status=U_ZERO_ERROR; 186 resLen=neededLen+1; 187 result=(UChar*)malloc(sizeof(UChar*) * resLen); 188 unorm_normalize(source, u_strlen(source), UNORM_NFKD, 0, result, resLen, &status); 189 } 190 if(U_FAILURE(status)){ 191 log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source), myErrorName(status) ); 192 } else { 193 assertEqual(result, compatTests[x][1], x); 194 } 195 free(result); 196 free(source); 197 } 198 } 199 200 void TestCanonDecompCompose() 201 { 202 UErrorCode status = U_ZERO_ERROR; 203 int32_t x, neededLen, resLen; 204 UChar *source=NULL, *result=NULL; 205 status = U_ZERO_ERROR; 206 resLen=0; 207 log_verbose("Testing unorm_normalize with Decomp can compose compat\n"); 208 for(x=0; x < LENGTHOF(canonTests); x++) 209 { 210 source=CharsToUChars(canonTests[x][0]); 211 neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFC, 0, NULL, 0, &status); 212 if(status==U_BUFFER_OVERFLOW_ERROR) 213 { 214 status=U_ZERO_ERROR; 215 resLen=neededLen+1; 216 result=(UChar*)malloc(sizeof(UChar*) * resLen); 217 unorm_normalize(source, u_strlen(source), UNORM_NFC, 0, result, resLen, &status); 218 } 219 if(U_FAILURE(status)){ 220 log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source),myErrorName(status) ); 221 } else { 222 assertEqual(result, canonTests[x][2], x); 223 } 224 free(result); 225 free(source); 226 } 227 } 228 229 void TestCompatDecompCompose() 230 { 231 UErrorCode status = U_ZERO_ERROR; 232 int32_t x, neededLen, resLen; 233 UChar *source=NULL, *result=NULL; 234 status = U_ZERO_ERROR; 235 resLen=0; 236 log_verbose("Testing unorm_normalize with compat decomp compose can\n"); 237 for(x=0; x < LENGTHOF(compatTests); x++) 238 { 239 source=CharsToUChars(compatTests[x][0]); 240 neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFKC, 0, NULL, 0, &status); 241 if(status==U_BUFFER_OVERFLOW_ERROR) 242 { 243 status=U_ZERO_ERROR; 244 resLen=neededLen+1; 245 result=(UChar*)malloc(sizeof(UChar*) * resLen); 246 unorm_normalize(source, u_strlen(source), UNORM_NFKC, 0, result, resLen, &status); 247 } 248 if(U_FAILURE(status)){ 249 log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source), myErrorName(status) ); 250 } else { 251 assertEqual(result, compatTests[x][2], x); 252 } 253 free(result); 254 free(source); 255 } 256 } 257 258 259 /* 260 static void assertEqual(const UChar* result, const UChar* expected, int32_t index) 261 { 262 if(u_strcmp(result, expected)!=0){ 263 log_err("ERROR in decomposition at index = %d. EXPECTED: %s , GOT: %s\n", index, austrdup(expected), 264 austrdup(result) ); 265 } 266 } 267 */ 268 269 static void assertEqual(const UChar* result, const char* expected, int32_t index) 270 { 271 UChar *expectedUni = CharsToUChars(expected); 272 if(u_strcmp(result, expectedUni)!=0){ 273 log_err("ERROR in decomposition at index = %d. EXPECTED: %s , GOT: %s\n", index, expected, 274 austrdup(result) ); 275 } 276 free(expectedUni); 277 } 278 279 static void TestNull_check(UChar *src, int32_t srcLen, 280 UChar *exp, int32_t expLen, 281 UNormalizationMode mode, 282 const char *name) 283 { 284 UErrorCode status = U_ZERO_ERROR; 285 int32_t len, i; 286 287 UChar result[50]; 288 289 290 status = U_ZERO_ERROR; 291 292 for(i=0;i<50;i++) 293 { 294 result[i] = 0xFFFD; 295 } 296 297 len = unorm_normalize(src, srcLen, mode, 0, result, 50, &status); 298 299 if(U_FAILURE(status)) { 300 log_err("unorm_normalize(%s) with 0x0000 failed: %s\n", name, u_errorName(status)); 301 } else if (len != expLen) { 302 log_err("unorm_normalize(%s) with 0x0000 failed: Expected len %d, got %d\n", name, expLen, len); 303 } 304 305 { 306 for(i=0;i<len;i++){ 307 if(exp[i] != result[i]) { 308 log_err("unorm_normalize(%s): @%d, expected \\u%04X got \\u%04X\n", 309 name, 310 i, 311 exp[i], 312 result[i]); 313 return; 314 } 315 log_verbose(" %d: \\u%04X\n", i, result[i]); 316 } 317 } 318 319 log_verbose("unorm_normalize(%s) with 0x0000: OK\n", name); 320 } 321 322 void TestNull() 323 { 324 325 UChar source_comp[] = { 0x0061, 0x0000, 0x0044, 0x0307 }; 326 int32_t source_comp_len = 4; 327 UChar expect_comp[] = { 0x0061, 0x0000, 0x1e0a }; 328 int32_t expect_comp_len = 3; 329 330 UChar source_dcmp[] = { 0x1e0A, 0x0000, 0x0929 }; 331 int32_t source_dcmp_len = 3; 332 UChar expect_dcmp[] = { 0x0044, 0x0307, 0x0000, 0x0928, 0x093C }; 333 int32_t expect_dcmp_len = 5; 334 335 TestNull_check(source_comp, 336 source_comp_len, 337 expect_comp, 338 expect_comp_len, 339 UNORM_NFC, 340 "UNORM_NFC"); 341 342 TestNull_check(source_dcmp, 343 source_dcmp_len, 344 expect_dcmp, 345 expect_dcmp_len, 346 UNORM_NFD, 347 "UNORM_NFD"); 348 349 TestNull_check(source_comp, 350 source_comp_len, 351 expect_comp, 352 expect_comp_len, 353 UNORM_NFKC, 354 "UNORM_NFKC"); 355 356 357 } 358 359 static void TestQuickCheckResultNO() 360 { 361 const UChar CPNFD[] = {0x00C5, 0x0407, 0x1E00, 0x1F57, 0x220C, 362 0x30AE, 0xAC00, 0xD7A3, 0xFB36, 0xFB4E}; 363 const UChar CPNFC[] = {0x0340, 0x0F93, 0x1F77, 0x1FBB, 0x1FEB, 364 0x2000, 0x232A, 0xF900, 0xFA1E, 0xFB4E}; 365 const UChar CPNFKD[] = {0x00A0, 0x02E4, 0x1FDB, 0x24EA, 0x32FE, 366 0xAC00, 0xFB4E, 0xFA10, 0xFF3F, 0xFA2D}; 367 const UChar CPNFKC[] = {0x00A0, 0x017F, 0x2000, 0x24EA, 0x32FE, 368 0x33FE, 0xFB4E, 0xFA10, 0xFF3F, 0xFA2D}; 369 370 371 const int SIZE = 10; 372 373 int count = 0; 374 UErrorCode error = U_ZERO_ERROR; 375 376 for (; count < SIZE; count ++) 377 { 378 if (unorm_quickCheck(&(CPNFD[count]), 1, UNORM_NFD, &error) != 379 UNORM_NO) 380 { 381 log_err("ERROR in NFD quick check at U+%04x\n", CPNFD[count]); 382 return; 383 } 384 if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) != 385 UNORM_NO) 386 { 387 log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]); 388 return; 389 } 390 if (unorm_quickCheck(&(CPNFKD[count]), 1, UNORM_NFKD, &error) != 391 UNORM_NO) 392 { 393 log_err("ERROR in NFKD quick check at U+%04x\n", CPNFKD[count]); 394 return; 395 } 396 if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) != 397 UNORM_NO) 398 { 399 log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]); 400 return; 401 } 402 } 403 } 404 405 406 static void TestQuickCheckResultYES() 407 { 408 const UChar CPNFD[] = {0x00C6, 0x017F, 0x0F74, 0x1000, 0x1E9A, 409 0x2261, 0x3075, 0x4000, 0x5000, 0xF000}; 410 const UChar CPNFC[] = {0x0400, 0x0540, 0x0901, 0x1000, 0x1500, 411 0x1E9A, 0x3000, 0x4000, 0x5000, 0xF000}; 412 const UChar CPNFKD[] = {0x00AB, 0x02A0, 0x1000, 0x1027, 0x2FFB, 413 0x3FFF, 0x4FFF, 0xA000, 0xF000, 0xFA27}; 414 const UChar CPNFKC[] = {0x00B0, 0x0100, 0x0200, 0x0A02, 0x1000, 415 0x2010, 0x3030, 0x4000, 0xA000, 0xFA0E}; 416 417 const int SIZE = 10; 418 int count = 0; 419 UErrorCode error = U_ZERO_ERROR; 420 421 UChar cp = 0; 422 while (cp < 0xA0) 423 { 424 if (unorm_quickCheck(&cp, 1, UNORM_NFD, &error) != UNORM_YES) 425 { 426 log_err("ERROR in NFD quick check at U+%04x\n", cp); 427 return; 428 } 429 if (unorm_quickCheck(&cp, 1, UNORM_NFC, &error) != 430 UNORM_YES) 431 { 432 log_err("ERROR in NFC quick check at U+%04x\n", cp); 433 return; 434 } 435 if (unorm_quickCheck(&cp, 1, UNORM_NFKD, &error) != UNORM_YES) 436 { 437 log_err("ERROR in NFKD quick check at U+%04x\n", cp); 438 return; 439 } 440 if (unorm_quickCheck(&cp, 1, UNORM_NFKC, &error) != 441 UNORM_YES) 442 { 443 log_err("ERROR in NFKC quick check at U+%04x\n", cp); 444 return; 445 } 446 cp ++; 447 } 448 449 for (; count < SIZE; count ++) 450 { 451 if (unorm_quickCheck(&(CPNFD[count]), 1, UNORM_NFD, &error) != 452 UNORM_YES) 453 { 454 log_err("ERROR in NFD quick check at U+%04x\n", CPNFD[count]); 455 return; 456 } 457 if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) 458 != UNORM_YES) 459 { 460 log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]); 461 return; 462 } 463 if (unorm_quickCheck(&(CPNFKD[count]), 1, UNORM_NFKD, &error) != 464 UNORM_YES) 465 { 466 log_err("ERROR in NFKD quick check at U+%04x\n", CPNFKD[count]); 467 return; 468 } 469 if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) != 470 UNORM_YES) 471 { 472 log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]); 473 return; 474 } 475 } 476 } 477 478 static void TestQuickCheckResultMAYBE() 479 { 480 const UChar CPNFC[] = {0x0306, 0x0654, 0x0BBE, 0x102E, 0x1161, 481 0x116A, 0x1173, 0x1175, 0x3099, 0x309A}; 482 const UChar CPNFKC[] = {0x0300, 0x0654, 0x0655, 0x09D7, 0x0B3E, 483 0x0DCF, 0xDDF, 0x102E, 0x11A8, 0x3099}; 484 485 486 const int SIZE = 10; 487 488 int count = 0; 489 UErrorCode error = U_ZERO_ERROR; 490 491 /* NFD and NFKD does not have any MAYBE codepoints */ 492 for (; count < SIZE; count ++) 493 { 494 if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) != 495 UNORM_MAYBE) 496 { 497 log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]); 498 return; 499 } 500 if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) != 501 UNORM_MAYBE) 502 { 503 log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]); 504 return; 505 } 506 } 507 } 508 509 static void TestQuickCheckStringResult() 510 { 511 int count; 512 UChar *d = NULL; 513 UChar *c = NULL; 514 UErrorCode error = U_ZERO_ERROR; 515 516 for (count = 0; count < LENGTHOF(canonTests); count ++) 517 { 518 d = CharsToUChars(canonTests[count][1]); 519 c = CharsToUChars(canonTests[count][2]); 520 if (unorm_quickCheck(d, u_strlen(d), UNORM_NFD, &error) != 521 UNORM_YES) 522 { 523 log_err("ERROR in NFD quick check for string at count %d\n", count); 524 return; 525 } 526 527 if (unorm_quickCheck(c, u_strlen(c), UNORM_NFC, &error) == 528 UNORM_NO) 529 { 530 log_err("ERROR in NFC quick check for string at count %d\n", count); 531 return; 532 } 533 534 free(d); 535 free(c); 536 } 537 538 for (count = 0; count < LENGTHOF(compatTests); count ++) 539 { 540 d = CharsToUChars(compatTests[count][1]); 541 c = CharsToUChars(compatTests[count][2]); 542 if (unorm_quickCheck(d, u_strlen(d), UNORM_NFKD, &error) != 543 UNORM_YES) 544 { 545 log_err("ERROR in NFKD quick check for string at count %d\n", count); 546 return; 547 } 548 549 if (unorm_quickCheck(c, u_strlen(c), UNORM_NFKC, &error) != 550 UNORM_YES) 551 { 552 log_err("ERROR in NFKC quick check for string at count %d\n", count); 553 return; 554 } 555 556 free(d); 557 free(c); 558 } 559 } 560 561 void TestQuickCheck() 562 { 563 TestQuickCheckResultNO(); 564 TestQuickCheckResultYES(); 565 TestQuickCheckResultMAYBE(); 566 TestQuickCheckStringResult(); 567 } 568 569 /* 570 * The intltest/NormalizerConformanceTest tests a lot of strings that _are_ 571 * normalized, and some that are not. 572 * Here we pick some specific cases and test the C API. 573 */ 574 static void TestIsNormalized(void) { 575 static const UChar notNFC[][8]={ /* strings that are not in NFC */ 576 { 0x62, 0x61, 0x300, 0x63, 0 }, /* 0061 0300 compose */ 577 { 0xfb1d, 0 }, /* excluded from composition */ 578 { 0x0627, 0x0653, 0 }, /* 0627 0653 compose */ 579 { 0x3071, 0x306f, 0x309a, 0x3073, 0 } /* 306F 309A compose */ 580 }; 581 static const UChar notNFKC[][8]={ /* strings that are not in NFKC */ 582 { 0x1100, 0x1161, 0 }, /* Jamo compose */ 583 { 0x1100, 0x314f, 0 }, /* compatibility Jamo compose */ 584 { 0x03b1, 0x1f00, 0x0345, 0x03b3, 0 } /* 1F00 0345 compose */ 585 }; 586 587 int32_t i; 588 UErrorCode errorCode; 589 590 /* API test */ 591 592 /* normal case with length>=0 (length -1 used for special cases below) */ 593 errorCode=U_ZERO_ERROR; 594 if(!unorm_isNormalized(notNFC[0]+2, 1, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) { 595 log_err("error: !isNormalized(<U+0300>, NFC) (%s)\n", u_errorName(errorCode)); 596 } 597 598 /* incoming U_FAILURE */ 599 errorCode=U_TRUNCATED_CHAR_FOUND; 600 (void)unorm_isNormalized(notNFC[0]+2, 1, UNORM_NFC, &errorCode); 601 if(errorCode!=U_TRUNCATED_CHAR_FOUND) { 602 log_err("error: isNormalized(U_TRUNCATED_CHAR_FOUND) changed the error code to %s\n", u_errorName(errorCode)); 603 } 604 605 /* NULL source */ 606 errorCode=U_ZERO_ERROR; 607 (void)unorm_isNormalized(NULL, 1, UNORM_NFC, &errorCode); 608 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 609 log_err("error: isNormalized(NULL) did not set U_ILLEGAL_ARGUMENT_ERROR but %s\n", u_errorName(errorCode)); 610 } 611 612 /* bad length */ 613 errorCode=U_ZERO_ERROR; 614 (void)unorm_isNormalized(notNFC[0]+2, -2, UNORM_NFC, &errorCode); 615 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 616 log_err("error: isNormalized([-2]) did not set U_ILLEGAL_ARGUMENT_ERROR but %s\n", u_errorName(errorCode)); 617 } 618 619 /* specific cases */ 620 for(i=0; i<LENGTHOF(notNFC); ++i) { 621 errorCode=U_ZERO_ERROR; 622 if(unorm_isNormalized(notNFC[i], -1, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) { 623 log_err("error: isNormalized(notNFC[%d], NFC) is wrong (%s)\n", i, u_errorName(errorCode)); 624 } 625 errorCode=U_ZERO_ERROR; 626 if(unorm_isNormalized(notNFC[i], -1, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) { 627 log_err("error: isNormalized(notNFC[%d], NFKC) is wrong (%s)\n", i, u_errorName(errorCode)); 628 } 629 } 630 for(i=0; i<LENGTHOF(notNFKC); ++i) { 631 errorCode=U_ZERO_ERROR; 632 if(unorm_isNormalized(notNFKC[i], -1, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) { 633 log_err("error: isNormalized(notNFKC[%d], NFKC) is wrong (%s)\n", i, u_errorName(errorCode)); 634 } 635 } 636 } 637 638 void TestCheckFCD() 639 { 640 UErrorCode status = U_ZERO_ERROR; 641 static const UChar FAST_[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 642 0x0A}; 643 static const UChar FALSE_[] = {0x0001, 0x0002, 0x02EA, 0x03EB, 0x0300, 0x0301, 644 0x02B9, 0x0314, 0x0315, 0x0316}; 645 static const UChar TRUE_[] = {0x0030, 0x0040, 0x0440, 0x056D, 0x064F, 0x06E7, 646 0x0050, 0x0730, 0x09EE, 0x1E10}; 647 648 static const UChar datastr[][5] = 649 { {0x0061, 0x030A, 0x1E05, 0x0302, 0}, 650 {0x0061, 0x030A, 0x00E2, 0x0323, 0}, 651 {0x0061, 0x0323, 0x00E2, 0x0323, 0}, 652 {0x0061, 0x0323, 0x1E05, 0x0302, 0} }; 653 static const UBool result[] = {UNORM_YES, UNORM_NO, UNORM_NO, UNORM_YES}; 654 655 static const UChar datachar[] = {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 656 0x6a, 657 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 658 0xea, 659 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 660 0x0307, 0x0308, 0x0309, 0x030a, 661 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 662 0x0327, 0x0328, 0x0329, 0x032a, 663 0x1e00, 0x1e01, 0x1e02, 0x1e03, 0x1e04, 0x1e05, 0x1e06, 664 0x1e07, 0x1e08, 0x1e09, 0x1e0a}; 665 666 int count = 0; 667 668 if (unorm_quickCheck(FAST_, 10, UNORM_FCD, &status) != UNORM_YES) 669 log_err("unorm_quickCheck(FCD) failed: expected value for fast unorm_quickCheck is UNORM_YES\n"); 670 if (unorm_quickCheck(FALSE_, 10, UNORM_FCD, &status) != UNORM_NO) 671 log_err("unorm_quickCheck(FCD) failed: expected value for error unorm_quickCheck is UNORM_NO\n"); 672 if (unorm_quickCheck(TRUE_, 10, UNORM_FCD, &status) != UNORM_YES) 673 log_err("unorm_quickCheck(FCD) failed: expected value for correct unorm_quickCheck is UNORM_YES\n"); 674 675 if (U_FAILURE(status)) 676 log_err("unorm_quickCheck(FCD) failed: %s\n", u_errorName(status)); 677 678 while (count < 4) 679 { 680 UBool fcdresult = unorm_quickCheck(datastr[count], 4, UNORM_FCD, &status); 681 if (U_FAILURE(status)) { 682 log_err("unorm_quickCheck(FCD) failed: exception occured at data set %d\n", count); 683 break; 684 } 685 else { 686 if (result[count] != fcdresult) { 687 log_err("unorm_quickCheck(FCD) failed: Data set %d expected value %d\n", count, 688 result[count]); 689 } 690 } 691 count ++; 692 } 693 694 /* random checks of long strings */ 695 status = U_ZERO_ERROR; 696 srand((unsigned)time( NULL )); 697 698 for (count = 0; count < 50; count ++) 699 { 700 int size = 0; 701 UBool testresult = UNORM_YES; 702 UChar data[20]; 703 UChar norm[100]; 704 UChar nfd[100]; 705 int normsize = 0; 706 int nfdsize = 0; 707 708 while (size != 19) { 709 data[size] = datachar[(rand() * 50) / RAND_MAX]; 710 log_verbose("0x%x", data[size]); 711 normsize += unorm_normalize(data + size, 1, UNORM_NFD, 0, 712 norm + normsize, 100 - normsize, &status); 713 if (U_FAILURE(status)) { 714 log_err("unorm_quickCheck(FCD) failed: exception occured at data generation\n"); 715 break; 716 } 717 size ++; 718 } 719 log_verbose("\n"); 720 721 nfdsize = unorm_normalize(data, size, UNORM_NFD, 0, 722 nfd, 100, &status); 723 if (U_FAILURE(status)) { 724 log_err("unorm_quickCheck(FCD) failed: exception occured at normalized data generation\n"); 725 } 726 727 if (nfdsize != normsize || u_memcmp(nfd, norm, nfdsize) != 0) { 728 testresult = UNORM_NO; 729 } 730 if (testresult == UNORM_YES) { 731 log_verbose("result UNORM_YES\n"); 732 } 733 else { 734 log_verbose("result UNORM_NO\n"); 735 } 736 737 if (unorm_quickCheck(data, size, UNORM_FCD, &status) != testresult || U_FAILURE(status)) { 738 log_err("unorm_quickCheck(FCD) failed: expected %d for random data\n", testresult); 739 } 740 } 741 } 742 743 static void 744 TestAPI() { 745 static const UChar in[]={ 0x68, 0xe4 }; 746 UChar out[20]={ 0xffff, 0xffff, 0xffff, 0xffff }; 747 UErrorCode errorCode; 748 int32_t length; 749 750 /* try preflighting */ 751 errorCode=U_ZERO_ERROR; 752 length=unorm_normalize(in, 2, UNORM_NFD, 0, NULL, 0, &errorCode); 753 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=3) { 754 log_err("unorm_normalize(pure preflighting NFD)=%ld failed with %s\n", length, u_errorName(errorCode)); 755 return; 756 } 757 758 errorCode=U_ZERO_ERROR; 759 length=unorm_normalize(in, 2, UNORM_NFD, 0, out, 3, &errorCode); 760 if(U_FAILURE(errorCode)) { 761 log_err("unorm_normalize(NFD)=%ld failed with %s\n", length, u_errorName(errorCode)); 762 return; 763 } 764 if(length!=3 || out[2]!=0x308 || out[3]!=0xffff) { 765 log_err("unorm_normalize(NFD ma<umlaut>)=%ld failed with out[]=U+%04x U+%04x U+%04x U+%04x\n", length, out[0], out[1], out[2], out[3]); 766 return; 767 } 768 } 769 770 /* test cases to improve test code coverage */ 771 enum { 772 HANGUL_K_KIYEOK=0x3131, /* NFKD->Jamo L U+1100 */ 773 HANGUL_K_WEO=0x315d, /* NFKD->Jamo V U+116f */ 774 HANGUL_K_KIYEOK_SIOS=0x3133, /* NFKD->Jamo T U+11aa */ 775 776 HANGUL_KIYEOK=0x1100, /* Jamo L U+1100 */ 777 HANGUL_WEO=0x116f, /* Jamo V U+116f */ 778 HANGUL_KIYEOK_SIOS=0x11aa, /* Jamo T U+11aa */ 779 780 HANGUL_AC00=0xac00, /* Hangul syllable = Jamo LV U+ac00 */ 781 HANGUL_SYLLABLE=0xac00+14*28+3, /* Hangul syllable = U+1100 * U+116f * U+11aa */ 782 783 MUSICAL_VOID_NOTEHEAD=0x1d157, 784 MUSICAL_HALF_NOTE=0x1d15e, /* NFC/NFD->Notehead+Stem */ 785 MUSICAL_STEM=0x1d165, /* cc=216 */ 786 MUSICAL_STACCATO=0x1d17c /* cc=220 */ 787 }; 788 789 static void 790 TestNormCoverage() { 791 UChar input[1000], expect[1000], output[1000]; 792 UErrorCode errorCode; 793 int32_t i, length, inLength, expectLength, hangulPrefixLength, preflightLength; 794 795 /* create a long and nasty string with NFKC-unsafe characters */ 796 inLength=0; 797 798 /* 3 Jamos L/V/T, all 8 combinations normal/compatibility */ 799 input[inLength++]=HANGUL_KIYEOK; 800 input[inLength++]=HANGUL_WEO; 801 input[inLength++]=HANGUL_KIYEOK_SIOS; 802 803 input[inLength++]=HANGUL_KIYEOK; 804 input[inLength++]=HANGUL_WEO; 805 input[inLength++]=HANGUL_K_KIYEOK_SIOS; 806 807 input[inLength++]=HANGUL_KIYEOK; 808 input[inLength++]=HANGUL_K_WEO; 809 input[inLength++]=HANGUL_KIYEOK_SIOS; 810 811 input[inLength++]=HANGUL_KIYEOK; 812 input[inLength++]=HANGUL_K_WEO; 813 input[inLength++]=HANGUL_K_KIYEOK_SIOS; 814 815 input[inLength++]=HANGUL_K_KIYEOK; 816 input[inLength++]=HANGUL_WEO; 817 input[inLength++]=HANGUL_KIYEOK_SIOS; 818 819 input[inLength++]=HANGUL_K_KIYEOK; 820 input[inLength++]=HANGUL_WEO; 821 input[inLength++]=HANGUL_K_KIYEOK_SIOS; 822 823 input[inLength++]=HANGUL_K_KIYEOK; 824 input[inLength++]=HANGUL_K_WEO; 825 input[inLength++]=HANGUL_KIYEOK_SIOS; 826 827 input[inLength++]=HANGUL_K_KIYEOK; 828 input[inLength++]=HANGUL_K_WEO; 829 input[inLength++]=HANGUL_K_KIYEOK_SIOS; 830 831 /* Hangul LV with normal/compatibility Jamo T */ 832 input[inLength++]=HANGUL_AC00; 833 input[inLength++]=HANGUL_KIYEOK_SIOS; 834 835 input[inLength++]=HANGUL_AC00; 836 input[inLength++]=HANGUL_K_KIYEOK_SIOS; 837 838 /* compatibility Jamo L, V */ 839 input[inLength++]=HANGUL_K_KIYEOK; 840 input[inLength++]=HANGUL_K_WEO; 841 842 hangulPrefixLength=inLength; 843 844 input[inLength++]=UTF16_LEAD(MUSICAL_HALF_NOTE); 845 input[inLength++]=UTF16_TRAIL(MUSICAL_HALF_NOTE); 846 for(i=0; i<200; ++i) { 847 input[inLength++]=UTF16_LEAD(MUSICAL_STACCATO); 848 input[inLength++]=UTF16_TRAIL(MUSICAL_STACCATO); 849 input[inLength++]=UTF16_LEAD(MUSICAL_STEM); 850 input[inLength++]=UTF16_TRAIL(MUSICAL_STEM); 851 } 852 853 /* (compatibility) Jamo L, T do not compose */ 854 input[inLength++]=HANGUL_K_KIYEOK; 855 input[inLength++]=HANGUL_K_KIYEOK_SIOS; 856 857 /* quick checks */ 858 errorCode=U_ZERO_ERROR; 859 if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFD, &errorCode) || U_FAILURE(errorCode)) { 860 log_err("error unorm_quickCheck(long input, UNORM_NFD)!=NO (%s)\n", u_errorName(errorCode)); 861 } 862 errorCode=U_ZERO_ERROR; 863 if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFKD, &errorCode) || U_FAILURE(errorCode)) { 864 log_err("error unorm_quickCheck(long input, UNORM_NFKD)!=NO (%s)\n", u_errorName(errorCode)); 865 } 866 errorCode=U_ZERO_ERROR; 867 if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) { 868 log_err("error unorm_quickCheck(long input, UNORM_NFC)!=NO (%s)\n", u_errorName(errorCode)); 869 } 870 errorCode=U_ZERO_ERROR; 871 if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) { 872 log_err("error unorm_quickCheck(long input, UNORM_NFKC)!=NO (%s)\n", u_errorName(errorCode)); 873 } 874 errorCode=U_ZERO_ERROR; 875 if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_FCD, &errorCode) || U_FAILURE(errorCode)) { 876 log_err("error unorm_quickCheck(long input, UNORM_FCD)!=NO (%s)\n", u_errorName(errorCode)); 877 } 878 879 /* NFKC */ 880 expectLength=0; 881 expect[expectLength++]=HANGUL_SYLLABLE; 882 883 expect[expectLength++]=HANGUL_SYLLABLE; 884 885 expect[expectLength++]=HANGUL_SYLLABLE; 886 887 expect[expectLength++]=HANGUL_SYLLABLE; 888 889 expect[expectLength++]=HANGUL_SYLLABLE; 890 891 expect[expectLength++]=HANGUL_SYLLABLE; 892 893 expect[expectLength++]=HANGUL_SYLLABLE; 894 895 expect[expectLength++]=HANGUL_SYLLABLE; 896 897 expect[expectLength++]=HANGUL_AC00+3; 898 899 expect[expectLength++]=HANGUL_AC00+3; 900 901 expect[expectLength++]=HANGUL_AC00+14*28; 902 903 expect[expectLength++]=UTF16_LEAD(MUSICAL_VOID_NOTEHEAD); 904 expect[expectLength++]=UTF16_TRAIL(MUSICAL_VOID_NOTEHEAD); 905 expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM); 906 expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM); 907 for(i=0; i<200; ++i) { 908 expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM); 909 expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM); 910 } 911 for(i=0; i<200; ++i) { 912 expect[expectLength++]=UTF16_LEAD(MUSICAL_STACCATO); 913 expect[expectLength++]=UTF16_TRAIL(MUSICAL_STACCATO); 914 } 915 916 expect[expectLength++]=HANGUL_KIYEOK; 917 expect[expectLength++]=HANGUL_KIYEOK_SIOS; 918 919 /* try destination overflow first */ 920 errorCode=U_ZERO_ERROR; 921 preflightLength=unorm_normalize(input, inLength, 922 UNORM_NFKC, 0, 923 output, 100, /* too short */ 924 &errorCode); 925 if(errorCode!=U_BUFFER_OVERFLOW_ERROR) { 926 log_err("error unorm_normalize(long input, output too short, UNORM_NFKC) did not overflow but %s\n", u_errorName(errorCode)); 927 } 928 929 /* real NFKC */ 930 errorCode=U_ZERO_ERROR; 931 length=unorm_normalize(input, inLength, 932 UNORM_NFKC, 0, 933 output, sizeof(output)/U_SIZEOF_UCHAR, 934 &errorCode); 935 if(U_FAILURE(errorCode)) { 936 log_err("error unorm_normalize(long input, UNORM_NFKC) failed with %s\n", u_errorName(errorCode)); 937 } else if(length!=expectLength || u_memcmp(output, expect, length)!=0) { 938 log_err("error unorm_normalize(long input, UNORM_NFKC) produced wrong result\n"); 939 for(i=0; i<length; ++i) { 940 if(output[i]!=expect[i]) { 941 log_err(" NFKC[%d]==U+%04lx expected U+%04lx\n", i, output[i], expect[i]); 942 break; 943 } 944 } 945 } 946 if(length!=preflightLength) { 947 log_err("error unorm_normalize(long input, UNORM_NFKC)==%ld but preflightLength==%ld\n", length, preflightLength); 948 } 949 950 /* FCD */ 951 u_memcpy(expect, input, hangulPrefixLength); 952 expectLength=hangulPrefixLength; 953 954 expect[expectLength++]=UTF16_LEAD(MUSICAL_VOID_NOTEHEAD); 955 expect[expectLength++]=UTF16_TRAIL(MUSICAL_VOID_NOTEHEAD); 956 expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM); 957 expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM); 958 for(i=0; i<200; ++i) { 959 expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM); 960 expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM); 961 } 962 for(i=0; i<200; ++i) { 963 expect[expectLength++]=UTF16_LEAD(MUSICAL_STACCATO); 964 expect[expectLength++]=UTF16_TRAIL(MUSICAL_STACCATO); 965 } 966 967 expect[expectLength++]=HANGUL_K_KIYEOK; 968 expect[expectLength++]=HANGUL_K_KIYEOK_SIOS; 969 970 errorCode=U_ZERO_ERROR; 971 length=unorm_normalize(input, inLength, 972 UNORM_FCD, 0, 973 output, sizeof(output)/U_SIZEOF_UCHAR, 974 &errorCode); 975 if(U_FAILURE(errorCode)) { 976 log_err("error unorm_normalize(long input, UNORM_FCD) failed with %s\n", u_errorName(errorCode)); 977 } else if(length!=expectLength || u_memcmp(output, expect, length)!=0) { 978 log_err("error unorm_normalize(long input, UNORM_FCD) produced wrong result\n"); 979 for(i=0; i<length; ++i) { 980 if(output[i]!=expect[i]) { 981 log_err(" FCD[%d]==U+%04lx expected U+%04lx\n", i, output[i], expect[i]); 982 break; 983 } 984 } 985 } 986 } 987 988 /* API test for unorm_concatenate() - for real test strings see intltest/tstnorm.cpp */ 989 static void 990 TestConcatenate(void) { 991 /* "re + 'sume'" */ 992 static const UChar 993 left[]={ 994 0x72, 0x65, 0 995 }, 996 right[]={ 997 0x301, 0x73, 0x75, 0x6d, 0xe9, 0 998 }, 999 expect[]={ 1000 0x72, 0xe9, 0x73, 0x75, 0x6d, 0xe9, 0 1001 }; 1002 1003 UChar buffer[100]; 1004 UErrorCode errorCode; 1005 int32_t length; 1006 1007 /* left with length, right NUL-terminated */ 1008 errorCode=U_ZERO_ERROR; 1009 length=unorm_concatenate(left, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode); 1010 if(U_FAILURE(errorCode) || length!=6 || 0!=u_memcmp(buffer, expect, length)) { 1011 log_err("error: unorm_concatenate()=%ld (expect 6) failed with %s\n", length, u_errorName(errorCode)); 1012 } 1013 1014 /* preflighting */ 1015 errorCode=U_ZERO_ERROR; 1016 length=unorm_concatenate(left, 2, right, -1, NULL, 0, UNORM_NFC, 0, &errorCode); 1017 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=6) { 1018 log_err("error: unorm_concatenate(preflighting)=%ld (expect 6) failed with %s\n", length, u_errorName(errorCode)); 1019 } 1020 1021 buffer[2]=0x5555; 1022 errorCode=U_ZERO_ERROR; 1023 length=unorm_concatenate(left, 2, right, -1, buffer, 1, UNORM_NFC, 0, &errorCode); 1024 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=6 || buffer[2]!=0x5555) { 1025 log_err("error: unorm_concatenate(preflighting 2)=%ld (expect 6) failed with %s\n", length, u_errorName(errorCode)); 1026 } 1027 1028 /* enter with U_FAILURE */ 1029 buffer[2]=0xaaaa; 1030 errorCode=U_UNEXPECTED_TOKEN; 1031 length=unorm_concatenate(left, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode); 1032 if(errorCode!=U_UNEXPECTED_TOKEN || buffer[2]!=0xaaaa) { 1033 log_err("error: unorm_concatenate(failure)=%ld failed with %s\n", length, u_errorName(errorCode)); 1034 } 1035 1036 /* illegal arguments */ 1037 buffer[2]=0xaaaa; 1038 errorCode=U_ZERO_ERROR; 1039 length=unorm_concatenate(NULL, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode); 1040 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[2]!=0xaaaa) { 1041 log_err("error: unorm_concatenate(left=NULL)=%ld failed with %s\n", length, u_errorName(errorCode)); 1042 } 1043 1044 errorCode=U_ZERO_ERROR; 1045 length=unorm_concatenate(left, 2, right, -1, NULL, 100, UNORM_NFC, 0, &errorCode); 1046 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 1047 log_err("error: unorm_concatenate(buffer=NULL)=%ld failed with %s\n", length, u_errorName(errorCode)); 1048 } 1049 } 1050 1051 enum { 1052 _PLUS=0x2b 1053 }; 1054 1055 static const char *const _modeString[UNORM_MODE_COUNT]={ 1056 "0", "NONE", "NFD", "NFKD", "NFC", "NFKC", "FCD" 1057 }; 1058 1059 static void 1060 _testIter(const UChar *src, int32_t srcLength, 1061 UCharIterator *iter, UNormalizationMode mode, UBool forward, 1062 const UChar *out, int32_t outLength, 1063 const int32_t *srcIndexes, int32_t srcIndexesLength) { 1064 UChar buffer[4]; 1065 const UChar *expect, *outLimit, *in; 1066 int32_t length, i, expectLength, expectIndex, prevIndex, index, inLength; 1067 UErrorCode errorCode; 1068 UBool neededToNormalize, expectNeeded; 1069 1070 errorCode=U_ZERO_ERROR; 1071 outLimit=out+outLength; 1072 if(forward) { 1073 expect=out; 1074 i=index=0; 1075 } else { 1076 expect=outLimit; 1077 i=srcIndexesLength-2; 1078 index=srcLength; 1079 } 1080 1081 for(;;) { 1082 prevIndex=index; 1083 if(forward) { 1084 if(!iter->hasNext(iter)) { 1085 return; 1086 } 1087 length=unorm_next(iter, 1088 buffer, sizeof(buffer)/U_SIZEOF_UCHAR, 1089 mode, 0, 1090 (UBool)(out!=NULL), &neededToNormalize, 1091 &errorCode); 1092 expectIndex=srcIndexes[i+1]; 1093 in=src+prevIndex; 1094 inLength=expectIndex-prevIndex; 1095 1096 if(out!=NULL) { 1097 /* get output piece from between plus signs */ 1098 expectLength=0; 1099 while((expect+expectLength)!=outLimit && expect[expectLength]!=_PLUS) { 1100 ++expectLength; 1101 } 1102 expectNeeded=(UBool)(0!=u_memcmp(buffer, in, inLength)); 1103 } else { 1104 expect=in; 1105 expectLength=inLength; 1106 expectNeeded=FALSE; 1107 } 1108 } else { 1109 if(!iter->hasPrevious(iter)) { 1110 return; 1111 } 1112 length=unorm_previous(iter, 1113 buffer, sizeof(buffer)/U_SIZEOF_UCHAR, 1114 mode, 0, 1115 (UBool)(out!=NULL), &neededToNormalize, 1116 &errorCode); 1117 expectIndex=srcIndexes[i]; 1118 in=src+expectIndex; 1119 inLength=prevIndex-expectIndex; 1120 1121 if(out!=NULL) { 1122 /* get output piece from between plus signs */ 1123 expectLength=0; 1124 while(expect!=out && expect[-1]!=_PLUS) { 1125 ++expectLength; 1126 --expect; 1127 } 1128 expectNeeded=(UBool)(0!=u_memcmp(buffer, in, inLength)); 1129 } else { 1130 expect=in; 1131 expectLength=inLength; 1132 expectNeeded=FALSE; 1133 } 1134 } 1135 index=iter->getIndex(iter, UITER_CURRENT); 1136 1137 if(U_FAILURE(errorCode)) { 1138 log_err("error unorm iteration (next/previous %d %s)[%d]: %s\n", 1139 forward, _modeString[mode], i, u_errorName(errorCode)); 1140 return; 1141 } 1142 if(expectIndex!=index) { 1143 log_err("error unorm iteration (next/previous %d %s): index[%d] wrong, got %d expected %d\n", 1144 forward, _modeString[mode], i, index, expectIndex); 1145 return; 1146 } 1147 if(expectLength!=length) { 1148 log_err("error unorm iteration (next/previous %d %s): length[%d] wrong, got %d expected %d\n", 1149 forward, _modeString[mode], i, length, expectLength); 1150 return; 1151 } 1152 if(0!=u_memcmp(expect, buffer, length)) { 1153 log_err("error unorm iteration (next/previous %d %s): output string[%d] wrong\n", 1154 forward, _modeString[mode], i); 1155 return; 1156 } 1157 if(neededToNormalize!=expectNeeded) { 1158 } 1159 1160 if(forward) { 1161 expect+=expectLength+1; /* go after the + */ 1162 ++i; 1163 } else { 1164 --expect; /* go before the + */ 1165 --i; 1166 } 1167 } 1168 } 1169 1170 static void 1171 TestNextPrevious() { 1172 static const UChar 1173 src[]={ /* input string */ 1174 0xa0, 0xe4, 0x63, 0x302, 0x327, 0xac00, 0x3133 1175 }, 1176 nfd[]={ /* + separates expected output pieces */ 1177 0xa0, _PLUS, 0x61, 0x308, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0x1100, 0x1161, _PLUS, 0x3133 1178 }, 1179 nfkd[]={ 1180 0x20, _PLUS, 0x61, 0x308, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0x1100, 0x1161, _PLUS, 0x11aa 1181 }, 1182 nfc[]={ 1183 0xa0, _PLUS, 0xe4, _PLUS, 0xe7, 0x302, _PLUS, 0xac00, _PLUS, 0x3133 1184 }, 1185 nfkc[]={ 1186 0x20, _PLUS, 0xe4, _PLUS, 0xe7, 0x302, _PLUS, 0xac03 1187 }, 1188 fcd[]={ 1189 0xa0, _PLUS, 0xe4, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0xac00, _PLUS, 0x3133 1190 }; 1191 1192 /* expected iterator indexes in the source string for each iteration piece */ 1193 static const int32_t 1194 nfdIndexes[]={ 1195 0, 1, 2, 5, 6, 7 1196 }, 1197 nfkdIndexes[]={ 1198 0, 1, 2, 5, 6, 7 1199 }, 1200 nfcIndexes[]={ 1201 0, 1, 2, 5, 6, 7 1202 }, 1203 nfkcIndexes[]={ 1204 0, 1, 2, 5, 7 1205 }, 1206 fcdIndexes[]={ 1207 0, 1, 2, 5, 6, 7 1208 }; 1209 1210 UCharIterator iter; 1211 1212 UChar buffer[4]; 1213 int32_t length; 1214 1215 UBool neededToNormalize; 1216 UErrorCode errorCode; 1217 1218 uiter_setString(&iter, src, sizeof(src)/U_SIZEOF_UCHAR); 1219 1220 /* test iteration with doNormalize */ 1221 iter.index=0; 1222 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, TRUE, nfd, sizeof(nfd)/U_SIZEOF_UCHAR, nfdIndexes, sizeof(nfdIndexes)/4); 1223 iter.index=0; 1224 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, TRUE, nfkd, sizeof(nfkd)/U_SIZEOF_UCHAR, nfkdIndexes, sizeof(nfkdIndexes)/4); 1225 iter.index=0; 1226 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, TRUE, nfc, sizeof(nfc)/U_SIZEOF_UCHAR, nfcIndexes, sizeof(nfcIndexes)/4); 1227 iter.index=0; 1228 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, TRUE, nfkc, sizeof(nfkc)/U_SIZEOF_UCHAR, nfkcIndexes, sizeof(nfkcIndexes)/4); 1229 iter.index=0; 1230 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, TRUE, fcd, sizeof(fcd)/U_SIZEOF_UCHAR, fcdIndexes, sizeof(fcdIndexes)/4); 1231 1232 iter.index=iter.length; 1233 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, FALSE, nfd, sizeof(nfd)/U_SIZEOF_UCHAR, nfdIndexes, sizeof(nfdIndexes)/4); 1234 iter.index=iter.length; 1235 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, FALSE, nfkd, sizeof(nfkd)/U_SIZEOF_UCHAR, nfkdIndexes, sizeof(nfkdIndexes)/4); 1236 iter.index=iter.length; 1237 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, FALSE, nfc, sizeof(nfc)/U_SIZEOF_UCHAR, nfcIndexes, sizeof(nfcIndexes)/4); 1238 iter.index=iter.length; 1239 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, FALSE, nfkc, sizeof(nfkc)/U_SIZEOF_UCHAR, nfkcIndexes, sizeof(nfkcIndexes)/4); 1240 iter.index=iter.length; 1241 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, FALSE, fcd, sizeof(fcd)/U_SIZEOF_UCHAR, fcdIndexes, sizeof(fcdIndexes)/4); 1242 1243 /* test iteration without doNormalize */ 1244 iter.index=0; 1245 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, TRUE, NULL, 0, nfdIndexes, sizeof(nfdIndexes)/4); 1246 iter.index=0; 1247 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, TRUE, NULL, 0, nfkdIndexes, sizeof(nfkdIndexes)/4); 1248 iter.index=0; 1249 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, TRUE, NULL, 0, nfcIndexes, sizeof(nfcIndexes)/4); 1250 iter.index=0; 1251 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, TRUE, NULL, 0, nfkcIndexes, sizeof(nfkcIndexes)/4); 1252 iter.index=0; 1253 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, TRUE, NULL, 0, fcdIndexes, sizeof(fcdIndexes)/4); 1254 1255 iter.index=iter.length; 1256 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, FALSE, NULL, 0, nfdIndexes, sizeof(nfdIndexes)/4); 1257 iter.index=iter.length; 1258 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, FALSE, NULL, 0, nfkdIndexes, sizeof(nfkdIndexes)/4); 1259 iter.index=iter.length; 1260 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, FALSE, NULL, 0, nfcIndexes, sizeof(nfcIndexes)/4); 1261 iter.index=iter.length; 1262 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, FALSE, NULL, 0, nfkcIndexes, sizeof(nfkcIndexes)/4); 1263 iter.index=iter.length; 1264 _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, FALSE, NULL, 0, fcdIndexes, sizeof(fcdIndexes)/4); 1265 1266 /* try without neededToNormalize */ 1267 errorCode=U_ZERO_ERROR; 1268 buffer[0]=5; 1269 iter.index=1; 1270 length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, 1271 UNORM_NFD, 0, TRUE, NULL, 1272 &errorCode); 1273 if(U_FAILURE(errorCode) || length!=2 || buffer[0]!=nfd[2] || buffer[1]!=nfd[3]) { 1274 log_err("error unorm_next(without needed) %s\n", u_errorName(errorCode)); 1275 return; 1276 } 1277 1278 /* preflight */ 1279 neededToNormalize=9; 1280 iter.index=1; 1281 length=unorm_next(&iter, NULL, 0, 1282 UNORM_NFD, 0, TRUE, &neededToNormalize, 1283 &errorCode); 1284 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || neededToNormalize!=FALSE || length!=2) { 1285 log_err("error unorm_next(pure preflighting) %s\n", u_errorName(errorCode)); 1286 return; 1287 } 1288 1289 errorCode=U_ZERO_ERROR; 1290 buffer[0]=buffer[1]=5; 1291 neededToNormalize=9; 1292 iter.index=1; 1293 length=unorm_next(&iter, buffer, 1, 1294 UNORM_NFD, 0, TRUE, &neededToNormalize, 1295 &errorCode); 1296 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || neededToNormalize!=FALSE || length!=2 || buffer[1]!=5) { 1297 log_err("error unorm_next(preflighting) %s\n", u_errorName(errorCode)); 1298 return; 1299 } 1300 1301 /* no iterator */ 1302 errorCode=U_ZERO_ERROR; 1303 buffer[0]=buffer[1]=5; 1304 neededToNormalize=9; 1305 iter.index=1; 1306 length=unorm_next(NULL, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, 1307 UNORM_NFD, 0, TRUE, &neededToNormalize, 1308 &errorCode); 1309 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 1310 log_err("error unorm_next(no iterator) %s\n", u_errorName(errorCode)); 1311 return; 1312 } 1313 1314 /* illegal mode */ 1315 buffer[0]=buffer[1]=5; 1316 neededToNormalize=9; 1317 iter.index=1; 1318 length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, 1319 (UNormalizationMode)0, 0, TRUE, &neededToNormalize, 1320 &errorCode); 1321 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 1322 log_err("error unorm_next(illegal mode) %s\n", u_errorName(errorCode)); 1323 return; 1324 } 1325 1326 /* error coming in */ 1327 errorCode=U_MISPLACED_QUANTIFIER; 1328 buffer[0]=5; 1329 iter.index=1; 1330 length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, 1331 UNORM_NFD, 0, TRUE, NULL, 1332 &errorCode); 1333 if(errorCode!=U_MISPLACED_QUANTIFIER) { 1334 log_err("error unorm_next(U_MISPLACED_QUANTIFIER) %s\n", u_errorName(errorCode)); 1335 return; 1336 } 1337 1338 /* missing pErrorCode */ 1339 buffer[0]=5; 1340 iter.index=1; 1341 length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, 1342 UNORM_NFD, 0, TRUE, NULL, 1343 NULL); 1344 if(iter.index!=1 || buffer[0]!=5) { 1345 log_err("error unorm_next(pErrorCode==NULL) %s\n", u_errorName(errorCode)); 1346 return; 1347 } 1348 } 1349 1350 static void 1351 TestFCNFKCClosure(void) { 1352 static const struct { 1353 UChar32 c; 1354 const UChar s[6]; 1355 } tests[]={ 1356 { 0x037A, { 0x0020, 0x03B9, 0 } }, 1357 { 0x03D2, { 0x03C5, 0 } }, 1358 { 0x20A8, { 0x0072, 0x0073, 0 } }, 1359 { 0x210B, { 0x0068, 0 } }, 1360 { 0x210C, { 0x0068, 0 } }, 1361 { 0x2121, { 0x0074, 0x0065, 0x006C, 0 } }, 1362 { 0x2122, { 0x0074, 0x006D, 0 } }, 1363 { 0x2128, { 0x007A, 0 } }, 1364 { 0x1D5DB, { 0x0068, 0 } }, 1365 { 0x1D5ED, { 0x007A, 0 } }, 1366 { 0x0061, { 0 } } 1367 }; 1368 1369 UChar buffer[8]; 1370 UErrorCode errorCode; 1371 int32_t i, length; 1372 1373 for(i=0; i<LENGTHOF(tests); ++i) { 1374 errorCode=U_ZERO_ERROR; 1375 length=u_getFC_NFKC_Closure(tests[i].c, buffer, LENGTHOF(buffer), &errorCode); 1376 if(U_FAILURE(errorCode) || length!=u_strlen(buffer) || 0!=u_strcmp(tests[i].s, buffer)) { 1377 log_err("u_getFC_NFKC_Closure(U+%04lx) is wrong (%s)\n", tests[i].c, u_errorName(errorCode)); 1378 } 1379 } 1380 1381 /* error handling */ 1382 errorCode=U_ZERO_ERROR; 1383 length=u_getFC_NFKC_Closure(0x5c, NULL, LENGTHOF(buffer), &errorCode); 1384 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 1385 log_err("u_getFC_NFKC_Closure(dest=NULL) is wrong (%s)\n", u_errorName(errorCode)); 1386 } 1387 1388 length=u_getFC_NFKC_Closure(0x5c, buffer, LENGTHOF(buffer), &errorCode); 1389 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 1390 log_err("u_getFC_NFKC_Closure(U_FAILURE) is wrong (%s)\n", u_errorName(errorCode)); 1391 } 1392 } 1393 1394 static void 1395 TestQuickCheckPerCP() { 1396 UErrorCode errorCode; 1397 UChar32 c, lead, trail; 1398 UChar s[U16_MAX_LENGTH], nfd[16]; 1399 int32_t length, lccc1, lccc2, tccc1, tccc2; 1400 int32_t qc1, qc2; 1401 1402 if( 1403 u_getIntPropertyMaxValue(UCHAR_NFD_QUICK_CHECK)!=(int32_t)UNORM_YES || 1404 u_getIntPropertyMaxValue(UCHAR_NFKD_QUICK_CHECK)!=(int32_t)UNORM_YES || 1405 u_getIntPropertyMaxValue(UCHAR_NFC_QUICK_CHECK)!=(int32_t)UNORM_MAYBE || 1406 u_getIntPropertyMaxValue(UCHAR_NFKC_QUICK_CHECK)!=(int32_t)UNORM_MAYBE || 1407 u_getIntPropertyMaxValue(UCHAR_LEAD_CANONICAL_COMBINING_CLASS)!=u_getIntPropertyMaxValue(UCHAR_CANONICAL_COMBINING_CLASS) || 1408 u_getIntPropertyMaxValue(UCHAR_TRAIL_CANONICAL_COMBINING_CLASS)!=u_getIntPropertyMaxValue(UCHAR_CANONICAL_COMBINING_CLASS) 1409 ) { 1410 log_err("wrong result from one of the u_getIntPropertyMaxValue(UCHAR_NF*_QUICK_CHECK) or UCHAR_*_CANONICAL_COMBINING_CLASS\n"); 1411 } 1412 1413 /* 1414 * compare the quick check property values for some code points 1415 * to the quick check results for checking same-code point strings 1416 */ 1417 errorCode=U_ZERO_ERROR; 1418 c=0; 1419 while(c<0x110000) { 1420 length=0; 1421 U16_APPEND_UNSAFE(s, length, c); 1422 1423 qc1=u_getIntPropertyValue(c, UCHAR_NFC_QUICK_CHECK); 1424 qc2=unorm_quickCheck(s, length, UNORM_NFC, &errorCode); 1425 if(qc1!=qc2) { 1426 log_err("u_getIntPropertyValue(NFC)=%d != %d=unorm_quickCheck(NFC) for U+%04x\n", qc1, qc2, c); 1427 } 1428 1429 qc1=u_getIntPropertyValue(c, UCHAR_NFD_QUICK_CHECK); 1430 qc2=unorm_quickCheck(s, length, UNORM_NFD, &errorCode); 1431 if(qc1!=qc2) { 1432 log_err("u_getIntPropertyValue(NFD)=%d != %d=unorm_quickCheck(NFD) for U+%04x\n", qc1, qc2, c); 1433 } 1434 1435 qc1=u_getIntPropertyValue(c, UCHAR_NFKC_QUICK_CHECK); 1436 qc2=unorm_quickCheck(s, length, UNORM_NFKC, &errorCode); 1437 if(qc1!=qc2) { 1438 log_err("u_getIntPropertyValue(NFKC)=%d != %d=unorm_quickCheck(NFKC) for U+%04x\n", qc1, qc2, c); 1439 } 1440 1441 qc1=u_getIntPropertyValue(c, UCHAR_NFKD_QUICK_CHECK); 1442 qc2=unorm_quickCheck(s, length, UNORM_NFKD, &errorCode); 1443 if(qc1!=qc2) { 1444 log_err("u_getIntPropertyValue(NFKD)=%d != %d=unorm_quickCheck(NFKD) for U+%04x\n", qc1, qc2, c); 1445 } 1446 1447 length=unorm_normalize(s, length, UNORM_NFD, 0, nfd, LENGTHOF(nfd), &errorCode); 1448 /* length-length == 0 is used to get around a compiler warning. */ 1449 U16_GET(nfd, 0, length-length, length, lead); 1450 U16_GET(nfd, 0, length-1, length, trail); 1451 1452 lccc1=u_getIntPropertyValue(c, UCHAR_LEAD_CANONICAL_COMBINING_CLASS); 1453 lccc2=u_getCombiningClass(lead); 1454 tccc1=u_getIntPropertyValue(c, UCHAR_TRAIL_CANONICAL_COMBINING_CLASS); 1455 tccc2=u_getCombiningClass(trail); 1456 1457 if(lccc1!=lccc2) { 1458 log_err("u_getIntPropertyValue(lccc)=%d != %d=u_getCombiningClass(lead) for U+%04x\n", 1459 lccc1, lccc2, c); 1460 } 1461 if(tccc1!=tccc2) { 1462 log_err("u_getIntPropertyValue(tccc)=%d != %d=u_getCombiningClass(trail) for U+%04x\n", 1463 tccc1, tccc2, c); 1464 } 1465 1466 /* skip some code points */ 1467 c=(20*c)/19+1; 1468 } 1469 } 1470 1471 static void 1472 TestComposition(void) { 1473 static const struct { 1474 UNormalizationMode mode; 1475 uint32_t options; 1476 UChar input[12]; 1477 UChar expect[12]; 1478 } cases[]={ 1479 /* 1480 * special cases for UAX #15 bug 1481 * see Unicode Public Review Issue #29 1482 * at http://www.unicode.org/review/resolved-pri.html#pri29 1483 */ 1484 { UNORM_NFC, 0, { 0x1100, 0x0300, 0x1161, 0x0327 }, { 0x1100, 0x0300, 0x1161, 0x0327 } }, 1485 { UNORM_NFC, 0, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 }, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 } }, 1486 { UNORM_NFC, 0, { 0xac00, 0x0300, 0x0327, 0x11a8 }, { 0xac00, 0x0327, 0x0300, 0x11a8 } }, 1487 { UNORM_NFC, 0, { 0x0b47, 0x0300, 0x0b3e }, { 0x0b47, 0x0300, 0x0b3e } }, 1488 1489 { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0x1100, 0x0300, 0x1161, 0x0327 }, { 0xac00, 0x0300, 0x0327 } }, 1490 { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 }, { 0xac01, 0x0300, 0x0327 } }, 1491 { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0xac00, 0x0300, 0x0327, 0x11a8 }, { 0xac01, 0x0327, 0x0300 } }, 1492 { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0x0b47, 0x0300, 0x0b3e }, { 0x0b4b, 0x0300 } } 1493 1494 /* TODO: add test cases for UNORM_FCC here (j2151) */ 1495 }; 1496 1497 UChar output[16]; 1498 UErrorCode errorCode; 1499 int32_t i, length; 1500 1501 for(i=0; i<LENGTHOF(cases); ++i) { 1502 errorCode=U_ZERO_ERROR; 1503 length=unorm_normalize( 1504 cases[i].input, -1, 1505 cases[i].mode, cases[i].options, 1506 output, LENGTHOF(output), 1507 &errorCode); 1508 if( U_FAILURE(errorCode) || 1509 length!=u_strlen(cases[i].expect) || 1510 0!=u_memcmp(output, cases[i].expect, length) 1511 ) { 1512 log_err("unexpected result for case %d\n", i); 1513 } 1514 } 1515 } 1516 1517 #endif /* #if !UCONFIG_NO_NORMALIZATION */ 1518