1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2014, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 /* file name: cbiditst.c 7 * encoding: US-ASCII 8 * tab size: 8 (not used) 9 * indentation:4 10 * 11 * created on: 1999sep27 12 * created by: Markus W. Scherer, updated by Matitiahu Allouche 13 */ 14 15 #include "cintltst.h" 16 #include "unicode/utypes.h" 17 #include "unicode/uchar.h" 18 #include "unicode/ustring.h" 19 #include "unicode/ubidi.h" 20 #include "unicode/ushape.h" 21 #include "cbiditst.h" 22 #include "cstring.h" 23 /* the following include is needed for sprintf */ 24 #include <stdio.h> 25 26 #define MAXLEN MAX_STRING_LENGTH 27 28 /* prototypes ---------------------------------------------------------------*/ 29 30 void addComplexTest(TestNode** root); 31 32 static void testCharFromDirProp(void); 33 34 static void testBidi(void); 35 36 static void doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst); 37 38 static void doMisc(void); 39 40 static void doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, 41 int32_t lineStart, UBool countRunsFirst); 42 43 static void _testReordering(UBiDi *pBiDi, int testNumber); 44 45 static void testInverse(void); 46 47 static void _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction); 48 49 static void _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength, 50 UBiDiLevel direction, UErrorCode *pErrorCode); 51 52 static void _testWriteReverse(void); 53 54 static void _testManyAddedPoints(void); 55 56 static void _testMisc(void); 57 58 static void doArabicShapingTest(void); 59 60 static void doLamAlefSpecialVLTRArabicShapingTest(void); 61 62 static void doTashkeelSpecialVLTRArabicShapingTest(void); 63 64 static void doLOGICALArabicDeShapingTest(void); 65 66 static void doArabicShapingTestForBug5421(void); 67 68 static void doArabicShapingTestForBug8703(void); 69 70 static void doArabicShapingTestForBug9024(void); 71 72 static void _testPresentationForms(const UChar *in); 73 74 static void doArabicShapingTestForNewCharacters(void); 75 76 static void testReorder(void); 77 78 static void testReorderArabicMathSymbols(void); 79 80 static void testFailureRecovery(void); 81 82 static void testMultipleParagraphs(void); 83 84 static void testGetBaseDirection(void); 85 86 static void testContext(void); 87 88 static void doTailTest(void); 89 90 static void testBracketOverflow(void); 91 92 /* new BIDI API */ 93 static void testReorderingMode(void); 94 static void testReorderRunsOnly(void); 95 static void testStreaming(void); 96 static void testClassOverride(void); 97 static const char* inverseBasic(UBiDi *pBiDi, const char *src, int32_t srcLen, 98 uint32_t option, UBiDiLevel level, char *result); 99 static UBool assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, 100 const char *srcChars, const char *destChars, 101 const UChar *dest, int32_t destLen, int mode, 102 int option, UBiDiLevel level); 103 static UBool checkResultLength(UBiDi *pBiDi, const char *srcChars, 104 const char *destChars, 105 int32_t destLen, const char *mode, 106 const char *option, UBiDiLevel level); 107 static UBool checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, 108 const char *dest, const char *mode, const char* option, 109 UBiDiLevel level, UBool forward); 110 111 /* helpers ------------------------------------------------------------------ */ 112 113 static const char *levelString="..............................................................."; 114 115 static void initCharFromDirProps(void); 116 117 static UChar * 118 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer); 119 120 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels); 121 122 /* regression tests ---------------------------------------------------------*/ 123 124 void 125 addComplexTest(TestNode** root) { 126 addTest(root, testCharFromDirProp, "complex/bidi/TestCharFromDirProp"); 127 addTest(root, testBidi, "complex/bidi/TestBidi"); 128 addTest(root, testInverse, "complex/bidi/TestInverse"); 129 addTest(root, testReorder,"complex/bidi/TestReorder"); 130 addTest(root, testFailureRecovery,"complex/bidi/TestFailureRecovery"); 131 addTest(root, testMultipleParagraphs,"complex/bidi/TestMultipleParagraphs"); 132 addTest(root, testReorderingMode, "complex/bidi/TestReorderingMode"); 133 addTest(root, testReorderRunsOnly, "complex/bidi/TestReorderRunsOnly"); 134 addTest(root, testStreaming, "complex/bidi/TestStreaming"); 135 addTest(root, testClassOverride, "complex/bidi/TestClassOverride"); 136 addTest(root, testGetBaseDirection, "complex/bidi/testGetBaseDirection"); 137 addTest(root, testContext, "complex/bidi/testContext"); 138 addTest(root, testBracketOverflow, "complex/bidi/TestBracketOverflow"); 139 140 addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest"); 141 addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef"); 142 addTest(root, doTashkeelSpecialVLTRArabicShapingTest, "complex/arabic-shaping/tashkeel"); 143 addTest(root, doLOGICALArabicDeShapingTest, "complex/arabic-shaping/unshaping"); 144 addTest(root, doArabicShapingTestForBug5421, "complex/arabic-shaping/bug-5421"); 145 addTest(root, doTailTest, "complex/arabic-shaping/tailtest"); 146 addTest(root, doArabicShapingTestForBug8703, "complex/arabic-shaping/bug-8703"); 147 addTest(root, testReorderArabicMathSymbols, "complex/bidi/bug-9024"); 148 addTest(root, doArabicShapingTestForBug9024, "complex/arabic-shaping/bug-9024"); 149 addTest(root, doArabicShapingTestForNewCharacters, "complex/arabic-shaping/shaping2"); 150 } 151 152 static void 153 testCharFromDirProp(void) { 154 /* verify that the exemplar characters have the expected bidi classes */ 155 int32_t i; 156 157 log_verbose("\nEntering TestCharFromDirProp\n\n"); 158 initCharFromDirProps(); 159 160 for(i=0; i<U_CHAR_DIRECTION_COUNT; ++i) { 161 if(u_charDirection(charFromDirProp[i])!=(UCharDirection)i) { 162 log_err("\nu_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n", 163 i, charFromDirProp[i], u_charDirection(charFromDirProp[i]), i); 164 } 165 } 166 log_verbose("\nExiting TestCharFromDirProp\n\n"); 167 } 168 169 static void 170 testBidi(void) { 171 UBiDi *pBiDi, *pLine=NULL; 172 UErrorCode errorCode=U_ZERO_ERROR; 173 174 log_verbose("\nEntering TestBidi\n\n"); 175 176 pBiDi=ubidi_openSized(MAXLEN, 0, &errorCode); 177 if(pBiDi!=NULL) { 178 pLine=ubidi_open(); 179 if(pLine!=NULL) { 180 doTests(pBiDi, pLine, FALSE); 181 doTests(pBiDi, pLine, TRUE); 182 } else { 183 log_err("ubidi_open() returned NULL, out of memory\n"); 184 } 185 } else { 186 log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode)); 187 } 188 doMisc(); 189 190 if(pLine!=NULL) { 191 ubidi_close(pLine); 192 } 193 if(pBiDi!=NULL) { 194 ubidi_close(pBiDi); 195 } 196 197 log_verbose("\nExiting TestBidi\n\n"); 198 } 199 200 static void 201 doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst) { 202 int testNumber; 203 UChar string[MAXLEN]; 204 UErrorCode errorCode; 205 int32_t lineStart; 206 UBiDiLevel paraLevel; 207 208 for(testNumber=0; testNumber<bidiTestCount; ++testNumber) { 209 errorCode=U_ZERO_ERROR; 210 getStringFromDirProps(tests[testNumber].text, tests[testNumber].length, string); 211 paraLevel=tests[testNumber].paraLevel; 212 ubidi_setPara(pBiDi, string, -1, paraLevel, NULL, &errorCode); 213 if(U_SUCCESS(errorCode)) { 214 log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n", 215 testNumber, paraLevel, ubidi_getDirection(pBiDi), paraLevel); 216 lineStart=tests[testNumber].lineStart; 217 if(lineStart==-1) { 218 doTest(pBiDi, testNumber, tests+testNumber, 0, countRunsFirst); 219 } else { 220 ubidi_setLine(pBiDi, lineStart, tests[testNumber].lineLimit, pLine, &errorCode); 221 if(U_SUCCESS(errorCode)) { 222 log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n", 223 lineStart, tests[testNumber].lineLimit, ubidi_getDirection(pLine), ubidi_getParaLevel(pLine)); 224 doTest(pLine, testNumber, tests+testNumber, lineStart, countRunsFirst); 225 } else { 226 log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n", 227 testNumber, lineStart, tests[testNumber].lineLimit, myErrorName(errorCode)); 228 } 229 } 230 } else { 231 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", 232 testNumber, paraLevel, myErrorName(errorCode)); 233 } 234 } 235 } 236 237 static const char columns[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 238 239 #define TABLE_SIZE 256 240 static UBool tablesInitialized = FALSE; 241 static UChar pseudoToUChar[TABLE_SIZE]; 242 static uint8_t UCharToPseudo[TABLE_SIZE]; /* used for Unicode chars < 0x0100 */ 243 static uint8_t UCharToPseud2[TABLE_SIZE]; /* used for Unicode chars >=0x0100 */ 244 245 static void buildPseudoTables(void) 246 /* 247 The rules for pseudo-Bidi are as follows: 248 - [ == LRE 249 - ] == RLE 250 - { == LRO 251 - } == RLO 252 - ^ == PDF 253 - @ == LRM 254 - & == RLM 255 - A-F == Arabic Letters 0631-0636 256 - G-V == Hebrew letters 05d7-05e6 257 - W-Z == Unassigned RTL 08d0-08d3 258 - 0-5 == western digits 0030-0035 259 - 6-9 == Arabic-Indic digits 0666-0669 260 - ` == Combining Grave Accent 0300 (NSM) 261 - ~ == Delete 007f (BN) 262 - | == Paragraph Separator 2029 (B) 263 - _ == Info Separator 1 001f (S) 264 All other characters represent themselves as Latin-1, with the corresponding 265 Bidi properties. 266 */ 267 { 268 int i; 269 UChar uchar; 270 uint8_t c; 271 /* initialize all tables to unknown */ 272 for (i=0; i < TABLE_SIZE; i++) { 273 pseudoToUChar[i] = 0xFFFD; 274 UCharToPseudo[i] = '?'; 275 UCharToPseud2[i] = '?'; 276 } 277 /* initialize non letters or digits */ 278 pseudoToUChar[(uint8_t) 0 ] = 0x0000; UCharToPseudo[0x00] = (uint8_t) 0 ; 279 pseudoToUChar[(uint8_t)' '] = 0x0020; UCharToPseudo[0x20] = (uint8_t)' '; 280 pseudoToUChar[(uint8_t)'!'] = 0x0021; UCharToPseudo[0x21] = (uint8_t)'!'; 281 pseudoToUChar[(uint8_t)'"'] = 0x0022; UCharToPseudo[0x22] = (uint8_t)'"'; 282 pseudoToUChar[(uint8_t)'#'] = 0x0023; UCharToPseudo[0x23] = (uint8_t)'#'; 283 pseudoToUChar[(uint8_t)'$'] = 0x0024; UCharToPseudo[0x24] = (uint8_t)'$'; 284 pseudoToUChar[(uint8_t)'%'] = 0x0025; UCharToPseudo[0x25] = (uint8_t)'%'; 285 pseudoToUChar[(uint8_t)'\'']= 0x0027; UCharToPseudo[0x27] = (uint8_t)'\''; 286 pseudoToUChar[(uint8_t)'('] = 0x0028; UCharToPseudo[0x28] = (uint8_t)'('; 287 pseudoToUChar[(uint8_t)')'] = 0x0029; UCharToPseudo[0x29] = (uint8_t)')'; 288 pseudoToUChar[(uint8_t)'*'] = 0x002A; UCharToPseudo[0x2A] = (uint8_t)'*'; 289 pseudoToUChar[(uint8_t)'+'] = 0x002B; UCharToPseudo[0x2B] = (uint8_t)'+'; 290 pseudoToUChar[(uint8_t)','] = 0x002C; UCharToPseudo[0x2C] = (uint8_t)','; 291 pseudoToUChar[(uint8_t)'-'] = 0x002D; UCharToPseudo[0x2D] = (uint8_t)'-'; 292 pseudoToUChar[(uint8_t)'.'] = 0x002E; UCharToPseudo[0x2E] = (uint8_t)'.'; 293 pseudoToUChar[(uint8_t)'/'] = 0x002F; UCharToPseudo[0x2F] = (uint8_t)'/'; 294 pseudoToUChar[(uint8_t)':'] = 0x003A; UCharToPseudo[0x3A] = (uint8_t)':'; 295 pseudoToUChar[(uint8_t)';'] = 0x003B; UCharToPseudo[0x3B] = (uint8_t)';'; 296 pseudoToUChar[(uint8_t)'<'] = 0x003C; UCharToPseudo[0x3C] = (uint8_t)'<'; 297 pseudoToUChar[(uint8_t)'='] = 0x003D; UCharToPseudo[0x3D] = (uint8_t)'='; 298 pseudoToUChar[(uint8_t)'>'] = 0x003E; UCharToPseudo[0x3E] = (uint8_t)'>'; 299 pseudoToUChar[(uint8_t)'?'] = 0x003F; UCharToPseudo[0x3F] = (uint8_t)'?'; 300 pseudoToUChar[(uint8_t)'\\']= 0x005C; UCharToPseudo[0x5C] = (uint8_t)'\\'; 301 /* initialize specially used characters */ 302 pseudoToUChar[(uint8_t)'`'] = 0x0300; UCharToPseud2[0x00] = (uint8_t)'`'; /* NSM */ 303 pseudoToUChar[(uint8_t)'@'] = 0x200E; UCharToPseud2[0x0E] = (uint8_t)'@'; /* LRM */ 304 pseudoToUChar[(uint8_t)'&'] = 0x200F; UCharToPseud2[0x0F] = (uint8_t)'&'; /* RLM */ 305 pseudoToUChar[(uint8_t)'_'] = 0x001F; UCharToPseudo[0x1F] = (uint8_t)'_'; /* S */ 306 pseudoToUChar[(uint8_t)'|'] = 0x2029; UCharToPseud2[0x29] = (uint8_t)'|'; /* B */ 307 pseudoToUChar[(uint8_t)'['] = 0x202A; UCharToPseud2[0x2A] = (uint8_t)'['; /* LRE */ 308 pseudoToUChar[(uint8_t)']'] = 0x202B; UCharToPseud2[0x2B] = (uint8_t)']'; /* RLE */ 309 pseudoToUChar[(uint8_t)'^'] = 0x202C; UCharToPseud2[0x2C] = (uint8_t)'^'; /* PDF */ 310 pseudoToUChar[(uint8_t)'{'] = 0x202D; UCharToPseud2[0x2D] = (uint8_t)'{'; /* LRO */ 311 pseudoToUChar[(uint8_t)'}'] = 0x202E; UCharToPseud2[0x2E] = (uint8_t)'}'; /* RLO */ 312 pseudoToUChar[(uint8_t)'~'] = 0x007F; UCharToPseudo[0x7F] = (uint8_t)'~'; /* BN */ 313 /* initialize western digits */ 314 for (i = 0, uchar = 0x0030; i < 6; i++, uchar++) { 315 c = (uint8_t)columns[i]; 316 pseudoToUChar[c] = uchar; 317 UCharToPseudo[uchar & 0x00ff] = c; 318 } 319 /* initialize Hindi digits */ 320 for (i = 6, uchar = 0x0666; i < 10; i++, uchar++) { 321 c = (uint8_t)columns[i]; 322 pseudoToUChar[c] = uchar; 323 UCharToPseud2[uchar & 0x00ff] = c; 324 } 325 /* initialize Arabic letters */ 326 for (i = 10, uchar = 0x0631; i < 16; i++, uchar++) { 327 c = (uint8_t)columns[i]; 328 pseudoToUChar[c] = uchar; 329 UCharToPseud2[uchar & 0x00ff] = c; 330 } 331 /* initialize Hebrew letters */ 332 for (i = 16, uchar = 0x05D7; i < 32; i++, uchar++) { 333 c = (uint8_t)columns[i]; 334 pseudoToUChar[c] = uchar; 335 UCharToPseud2[uchar & 0x00ff] = c; 336 } 337 /* initialize Unassigned code points */ 338 for (i = 32, uchar=0x08D0; i < 36; i++, uchar++) { 339 c = (uint8_t)columns[i]; 340 pseudoToUChar[c] = uchar; 341 UCharToPseud2[uchar & 0x00ff] = c; 342 } 343 /* initialize Latin lower case letters */ 344 for (i = 36, uchar = 0x0061; i < 62; i++, uchar++) { 345 c = (uint8_t)columns[i]; 346 pseudoToUChar[c] = uchar; 347 UCharToPseudo[uchar & 0x00ff] = c; 348 } 349 tablesInitialized = TRUE; 350 } 351 352 /*----------------------------------------------------------------------*/ 353 354 static int pseudoToU16(const int length, const char * input, UChar * output) 355 /* This function converts a pseudo-Bidi string into a UChar string. 356 It returns the length of the UChar string. 357 */ 358 { 359 int i; 360 if (!tablesInitialized) { 361 buildPseudoTables(); 362 } 363 for (i = 0; i < length; i++) 364 output[i] = pseudoToUChar[(uint8_t)input[i]]; 365 output[length] = 0; 366 return length; 367 } 368 369 /*----------------------------------------------------------------------*/ 370 371 static int u16ToPseudo(const int length, const UChar * input, char * output) 372 /* This function converts a UChar string into a pseudo-Bidi string. 373 It returns the length of the pseudo-Bidi string. 374 */ 375 { 376 int i; 377 UChar uchar; 378 if (!tablesInitialized) { 379 buildPseudoTables(); 380 } 381 for (i = 0; i < length; i++) 382 { 383 uchar = input[i]; 384 output[i] = uchar < 0x0100 ? UCharToPseudo[uchar] : 385 UCharToPseud2[uchar & 0x00ff]; 386 } 387 output[length] = '\0'; 388 return length; 389 } 390 391 static char * formatLevels(UBiDi *bidi, char *buffer) { 392 UErrorCode ec = U_ZERO_ERROR; 393 const UBiDiLevel* gotLevels = ubidi_getLevels(bidi, &ec); 394 int len = ubidi_getLength(bidi); 395 char c; 396 int i, k; 397 398 if(U_FAILURE(ec)) { 399 strcpy(buffer, "BAD LEVELS"); 400 return buffer; 401 } 402 for (i=0; i<len; i++) { 403 k = gotLevels[i]; 404 if (k >= sizeof(columns)) 405 c = '+'; 406 else 407 c = columns[k]; 408 buffer[i] = c; 409 } 410 buffer[len] = '\0'; 411 return buffer; 412 } 413 static const char *reorderingModeNames[] = { 414 "UBIDI_REORDER_DEFAULT", 415 "UBIDI_REORDER_NUMBERS_SPECIAL", 416 "UBIDI_REORDER_GROUP_NUMBERS_WITH_R", 417 "UBIDI_REORDER_RUNS_ONLY", 418 "UBIDI_REORDER_INVERSE_NUMBERS_AS_L", 419 "UBIDI_REORDER_INVERSE_LIKE_DIRECT", 420 "UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL"}; 421 422 static char *reorderingOptionNames(char *buffer, int options) { 423 buffer[0] = 0; 424 if (options & UBIDI_OPTION_INSERT_MARKS) { 425 strcat(buffer, " UBIDI_OPTION_INSERT_MARKS"); 426 } 427 if (options & UBIDI_OPTION_REMOVE_CONTROLS) { 428 strcat(buffer, " UBIDI_OPTION_REMOVE_CONTROLS"); 429 } 430 if (options & UBIDI_OPTION_STREAMING) { 431 strcat(buffer, " UBIDI_OPTION_STREAMING"); 432 } 433 return buffer; 434 } 435 436 static void printCaseInfo(UBiDi *bidi, const char *src, const char *dst) 437 /* src and dst are char arrays encoded as pseudo Bidi */ 438 { 439 /* Since calls to log_err with a \n within the pattern increment the 440 * error count, new lines are issued via fputs, except when we want the 441 * increment to happen. 442 */ 443 UErrorCode errorCode=U_ZERO_ERROR; 444 int32_t i, length = ubidi_getProcessedLength(bidi); 445 const UBiDiLevel *levels; 446 char levelChars[MAXLEN]; 447 UBiDiLevel lev; 448 int32_t runCount; 449 char buffer[100]; 450 log_err("========================================"); fputs("\n", stderr); 451 levels = ubidi_getLevels(bidi, &errorCode); 452 if (U_FAILURE(errorCode)) { 453 strcpy(levelChars, "BAD LEVELS"); 454 } else { 455 log_err("Processed length: %d", length); fputs("\n", stderr); 456 for (i = 0; i < length; i++) { 457 lev = levels[i]; 458 if (lev < sizeof(columns)) { 459 levelChars[i] = columns[lev]; 460 } else { 461 levelChars[i] = '+'; 462 } 463 } 464 levelChars[length] = 0; 465 } 466 log_err("Levels: %s", levelChars); fputs("\n", stderr); 467 log_err("Source: %s", src); fputs("\n", stderr); 468 log_err("Result: %s", dst); fputs("\n", stderr); 469 log_err("Direction: %d", ubidi_getDirection(bidi)); fputs("\n", stderr); 470 log_err("paraLevel: %d", ubidi_getParaLevel(bidi)); fputs("\n", stderr); 471 i = ubidi_getReorderingMode(bidi); 472 log_err("reorderingMode: %d = %s", i, reorderingModeNames[i]); 473 fputs("\n", stderr); 474 i = ubidi_getReorderingOptions(bidi); 475 log_err("reorderingOptions: %d = %s", i, reorderingOptionNames(buffer, i)); 476 fputs("\n", stderr); 477 runCount = ubidi_countRuns(bidi, &errorCode); 478 if (U_FAILURE(errorCode)) { 479 log_err( "BAD RUNS"); 480 } else { 481 log_err("Runs: %d => logicalStart.length/level: ", runCount); 482 for (i = 0; i < runCount; i++) { 483 UBiDiDirection dir; 484 int32_t start, len; 485 dir = ubidi_getVisualRun(bidi, i, &start, &len); 486 log_err(" %d.%d/%d", start, len, dir); 487 } 488 } 489 fputs("\n", stderr); 490 } 491 492 static UBool matchingPair(UBiDi *bidi, int32_t i, char c1, char c2) 493 { 494 /* No test for []{} since they have special meaning for pseudo Bidi */ 495 static char mates1Chars[] = "<>()"; 496 static char mates2Chars[] = "><)("; 497 UBiDiLevel level; 498 int k, len; 499 500 if (c1 == c2) { 501 return TRUE; 502 } 503 /* For UBIDI_REORDER_RUNS_ONLY, it would not be correct to check levels[i], 504 so we use the appropriate run's level, which is good for all cases. 505 */ 506 ubidi_getLogicalRun(bidi, i, NULL, &level); 507 if ((level & 1) == 0) { 508 return FALSE; 509 } 510 len = strlen(mates1Chars); 511 for (k = 0; k < len; k++) { 512 if ((c1 == mates1Chars[k]) && (c2 == mates2Chars[k])) { 513 return TRUE; 514 } 515 } 516 return FALSE; 517 } 518 519 static UBool checkWhatYouCan(UBiDi *bidi, const char *srcChars, const char *dstChars) 520 /* srcChars and dstChars are char arrays encoded as pseudo Bidi */ 521 { 522 int32_t i, idx, logLimit, visLimit; 523 UBool testOK, errMap, errDst; 524 UErrorCode errorCode=U_ZERO_ERROR; 525 int32_t visMap[MAXLEN]; 526 int32_t logMap[MAXLEN]; 527 char accumSrc[MAXLEN]; 528 char accumDst[MAXLEN]; 529 ubidi_getVisualMap(bidi, visMap, &errorCode); 530 ubidi_getLogicalMap(bidi, logMap, &errorCode); 531 if (U_FAILURE(errorCode)) { 532 log_err("Error #1 invoking ICU within checkWhatYouCan\n"); 533 return FALSE; 534 } 535 536 testOK = TRUE; 537 errMap = errDst = FALSE; 538 logLimit = ubidi_getProcessedLength(bidi); 539 visLimit = ubidi_getResultLength(bidi); 540 memset(accumSrc, '?', logLimit); 541 memset(accumDst, '?', visLimit); 542 543 for (i = 0; i < logLimit; i++) { 544 idx = ubidi_getVisualIndex(bidi, i, &errorCode); 545 if (idx != logMap[i]) { 546 errMap = TRUE; 547 } 548 if (idx == UBIDI_MAP_NOWHERE) { 549 continue; 550 } 551 if (idx >= visLimit) { 552 continue; 553 } 554 accumDst[idx] = srcChars[i]; 555 if (!matchingPair(bidi, i, srcChars[i], dstChars[idx])) { 556 errDst = TRUE; 557 } 558 } 559 accumDst[visLimit] = 0; 560 if (U_FAILURE(errorCode)) { 561 log_err("Error #2 invoking ICU within checkWhatYouCan\n"); 562 return FALSE; 563 } 564 if (errMap) { 565 if (testOK) { 566 printCaseInfo(bidi, srcChars, dstChars); 567 testOK = FALSE; 568 } 569 log_err("Mismatch between getLogicalMap() and getVisualIndex()\n"); 570 log_err("Map :"); 571 for (i = 0; i < logLimit; i++) { 572 log_err(" %d", logMap[i]); 573 } 574 fputs("\n", stderr); 575 log_err("Indexes:"); 576 for (i = 0; i < logLimit; i++) { 577 log_err(" %d", ubidi_getVisualIndex(bidi, i, &errorCode)); 578 } 579 fputs("\n", stderr); 580 } 581 if (errDst) { 582 if (testOK) { 583 printCaseInfo(bidi, srcChars, dstChars); 584 testOK = FALSE; 585 } 586 log_err("Source does not map to Result\n"); 587 log_err("We got: %s", accumDst); fputs("\n", stderr); 588 } 589 590 errMap = errDst = FALSE; 591 for (i = 0; i < visLimit; i++) { 592 idx = ubidi_getLogicalIndex(bidi, i, &errorCode); 593 if (idx != visMap[i]) { 594 errMap = TRUE; 595 } 596 if (idx == UBIDI_MAP_NOWHERE) { 597 continue; 598 } 599 if (idx >= logLimit) { 600 continue; 601 } 602 accumSrc[idx] = dstChars[i]; 603 if (!matchingPair(bidi, idx, srcChars[idx], dstChars[i])) { 604 errDst = TRUE; 605 } 606 } 607 accumSrc[logLimit] = 0; 608 if (U_FAILURE(errorCode)) { 609 log_err("Error #3 invoking ICU within checkWhatYouCan\n"); 610 return FALSE; 611 } 612 if (errMap) { 613 if (testOK) { 614 printCaseInfo(bidi, srcChars, dstChars); 615 testOK = FALSE; 616 } 617 log_err("Mismatch between getVisualMap() and getLogicalIndex()\n"); 618 log_err("Map :"); 619 for (i = 0; i < visLimit; i++) { 620 log_err(" %d", visMap[i]); 621 } 622 fputs("\n", stderr); 623 log_err("Indexes:"); 624 for (i = 0; i < visLimit; i++) { 625 log_err(" %d", ubidi_getLogicalIndex(bidi, i, &errorCode)); 626 } 627 fputs("\n", stderr); 628 } 629 if (errDst) { 630 if (testOK) { 631 printCaseInfo(bidi, srcChars, dstChars); 632 testOK = FALSE; 633 } 634 log_err("Result does not map to Source\n"); 635 log_err("We got: %s", accumSrc); 636 fputs("\n", stderr); 637 } 638 return testOK; 639 } 640 641 static void 642 testReorder(void) { 643 static const char* const logicalOrder[] ={ 644 "del(KC)add(K.C.&)", 645 "del(QDVT) add(BVDL)", 646 "del(PQ)add(R.S.)T)U.&", 647 "del(LV)add(L.V.) L.V.&", 648 "day 0 R DPDHRVR dayabbr", 649 "day 1 H DPHPDHDA dayabbr", 650 "day 2 L DPBLENDA dayabbr", 651 "day 3 J DPJQVM dayabbr", 652 "day 4 I DPIQNF dayabbr", 653 "day 5 M DPMEG dayabbr", 654 "helloDPMEG", 655 "hello WXYZ" 656 }; 657 static const char* const visualOrder[]={ 658 "del(CK)add(&.C.K)", 659 "del(TVDQ) add(LDVB)", 660 "del(QP)add(S.R.)&.U(T", /* updated for Unicode 6.3 matching brackets */ 661 "del(VL)add(V.L.) &.V.L", /* updated for Unicode 6.3 matching brackets */ 662 "day 0 RVRHDPD R dayabbr", 663 "day 1 ADHDPHPD H dayabbr", 664 "day 2 ADNELBPD L dayabbr", 665 "day 3 MVQJPD J dayabbr", 666 "day 4 FNQIPD I dayabbr", 667 "day 5 GEMPD M dayabbr", 668 "helloGEMPD", 669 "hello ZYXW" 670 }; 671 static const char* const visualOrder1[]={ 672 ")K.C.&(dda)KC(led", 673 ")BVDL(dda )QDVT(led", 674 "T(U.&).R.S(dda)PQ(led", /* updated for Unicode 6.3 matching brackets */ 675 "L.V.& ).L.V(dda)LV(led", /* updated for Unicode 6.3 matching brackets */ 676 "rbbayad R DPDHRVR 0 yad", 677 "rbbayad H DPHPDHDA 1 yad", 678 "rbbayad L DPBLENDA 2 yad", 679 "rbbayad J DPJQVM 3 yad", 680 "rbbayad I DPIQNF 4 yad", 681 "rbbayad M DPMEG 5 yad", 682 "DPMEGolleh", 683 "WXYZ olleh" 684 }; 685 686 static const char* const visualOrder2[]={ 687 "@)@K.C.&@(dda)@KC@(led", 688 "@)@BVDL@(dda )@QDVT@(led", 689 "R.S.)T)U.&@(dda)@PQ@(led", 690 "L.V.) L.V.&@(dda)@LV@(led", 691 "rbbayad @R DPDHRVR@ 0 yad", 692 "rbbayad @H DPHPDHDA@ 1 yad", 693 "rbbayad @L DPBLENDA@ 2 yad", 694 "rbbayad @J DPJQVM@ 3 yad", 695 "rbbayad @I DPIQNF@ 4 yad", 696 "rbbayad @M DPMEG@ 5 yad", 697 "DPMEGolleh", 698 "WXYZ@ olleh" 699 }; 700 static const char* const visualOrder3[]={ 701 ")K.C.&(KC)dda(led", 702 ")BVDL(ddaQDVT) (led", 703 "R.S.)T)U.&(PQ)dda(led", 704 "L.V.) L.V.&(LV)dda(led", 705 "rbbayad DPDHRVR R 0 yad", 706 "rbbayad DPHPDHDA H 1 yad", 707 "rbbayad DPBLENDA L 2 yad", 708 "rbbayad DPJQVM J 3 yad", 709 "rbbayad DPIQNF I 4 yad", 710 "rbbayad DPMEG M 5 yad", 711 "DPMEGolleh", 712 "WXYZ olleh" 713 }; 714 static const char* const visualOrder4[]={ 715 "del(add(CK(.C.K)", 716 "del( (TVDQadd(LDVB)", 717 "del(add(QP(.U(T(.S.R", 718 "del(add(VL(.V.L (.V.L", 719 "day 0 R RVRHDPD dayabbr", 720 "day 1 H ADHDPHPD dayabbr", 721 "day 2 L ADNELBPD dayabbr", 722 "day 3 J MVQJPD dayabbr", 723 "day 4 I FNQIPD dayabbr", 724 "day 5 M GEMPD dayabbr", 725 "helloGEMPD", 726 "hello ZYXW" 727 }; 728 char formatChars[MAXLEN]; 729 UErrorCode ec = U_ZERO_ERROR; 730 UBiDi* bidi = ubidi_open(); 731 int i; 732 733 log_verbose("\nEntering TestReorder\n\n"); 734 735 for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){ 736 int32_t srcSize = (int32_t)strlen(logicalOrder[i]); 737 int32_t destSize = srcSize*2; 738 UChar src[MAXLEN]; 739 UChar dest[MAXLEN]; 740 char chars[MAXLEN]; 741 log_verbose("Testing L2V #1 for case %d\n", i); 742 pseudoToU16(srcSize,logicalOrder[i],src); 743 ec = U_ZERO_ERROR; 744 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec); 745 if(U_FAILURE(ec)){ 746 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", 747 i, UBIDI_DEFAULT_LTR, u_errorName(ec)); 748 } 749 /* try pre-flighting */ 750 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec); 751 if(ec!=U_BUFFER_OVERFLOW_ERROR){ 752 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); 753 }else if(destSize!=srcSize){ 754 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize); 755 }else{ 756 ec= U_ZERO_ERROR; 757 } 758 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec); 759 u16ToPseudo(destSize,dest,chars); 760 if(destSize!=srcSize){ 761 log_err("ubidi_writeReordered() destSize and srcSize do not match\n"); 762 }else if(strcmp(visualOrder[i],chars)!=0){ 763 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n" 764 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", 765 logicalOrder[i],visualOrder[i],chars,formatLevels(bidi, formatChars),i); 766 } 767 checkWhatYouCan(bidi, logicalOrder[i], chars); 768 } 769 770 for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){ 771 int32_t srcSize = (int32_t)strlen(logicalOrder[i]); 772 int32_t destSize = srcSize*2; 773 UChar src[MAXLEN]; 774 UChar dest[MAXLEN]; 775 char chars[MAXLEN]; 776 log_verbose("Testing L2V #2 for case %d\n", i); 777 pseudoToU16(srcSize,logicalOrder[i],src); 778 ec = U_ZERO_ERROR; 779 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec); 780 if(U_FAILURE(ec)){ 781 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", 782 i, UBIDI_DEFAULT_LTR, u_errorName(ec)); 783 } 784 /* try pre-flighting */ 785 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec); 786 if(ec!=U_BUFFER_OVERFLOW_ERROR){ 787 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); 788 }else if(destSize!=srcSize){ 789 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize); 790 }else{ 791 ec= U_ZERO_ERROR; 792 } 793 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec); 794 u16ToPseudo(destSize,dest,chars); 795 if(destSize!=srcSize){ 796 log_err("ubidi_writeReordered() destSize and srcSize do not match\n"); 797 }else if(strcmp(visualOrder1[i],chars)!=0){ 798 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE.\n" 799 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", 800 logicalOrder[i],visualOrder1[i],chars,formatLevels(bidi, formatChars),i); 801 } 802 } 803 804 for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){ 805 int32_t srcSize = (int32_t)strlen(logicalOrder[i]); 806 int32_t destSize = srcSize*2; 807 UChar src[MAXLEN]; 808 UChar dest[MAXLEN]; 809 char chars[MAXLEN]; 810 log_verbose("Testing V2L #3 for case %d\n", i); 811 pseudoToU16(srcSize,logicalOrder[i],src); 812 ec = U_ZERO_ERROR; 813 ubidi_setInverse(bidi,TRUE); 814 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec); 815 if(U_FAILURE(ec)){ 816 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", 817 i, UBIDI_DEFAULT_LTR, u_errorName(ec)); 818 } 819 /* try pre-flighting */ 820 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec); 821 if(ec!=U_BUFFER_OVERFLOW_ERROR){ 822 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); 823 }else{ 824 ec= U_ZERO_ERROR; 825 } 826 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec); 827 u16ToPseudo(destSize,dest,chars); 828 if(strcmp(visualOrder2[i],chars)!=0){ 829 log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE.\n" 830 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", 831 logicalOrder[i],visualOrder2[i],chars,formatLevels(bidi, formatChars),i); 832 } 833 } 834 /* Max Explicit level */ 835 for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){ 836 int32_t srcSize = (int32_t)strlen(logicalOrder[i]); 837 int32_t destSize = srcSize*2; 838 UChar src[MAXLEN]; 839 UChar dest[MAXLEN]; 840 char chars[MAXLEN]; 841 UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10}; 842 log_verbose("Testing V2L #4 for case %d\n", i); 843 pseudoToU16(srcSize,logicalOrder[i],src); 844 ec = U_ZERO_ERROR; 845 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec); 846 if(U_FAILURE(ec)){ 847 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", 848 i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec)); 849 } 850 /* try pre-flighting */ 851 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_OUTPUT_REVERSE,&ec); 852 if(ec!=U_BUFFER_OVERFLOW_ERROR){ 853 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); 854 }else if(destSize!=srcSize){ 855 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize); 856 }else{ 857 ec = U_ZERO_ERROR; 858 } 859 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_OUTPUT_REVERSE,&ec); 860 u16ToPseudo(destSize,dest,chars); 861 if(destSize!=srcSize){ 862 log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize ); 863 }else if(strcmp(visualOrder3[i],chars)!=0){ 864 log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE.\n" 865 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", 866 logicalOrder[i],visualOrder3[i],chars,formatLevels(bidi, formatChars),i); 867 } 868 } 869 for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){ 870 int32_t srcSize = (int32_t)strlen(logicalOrder[i]); 871 int32_t destSize = srcSize*2; 872 UChar src[MAXLEN]; 873 UChar dest[MAXLEN]; 874 char chars[MAXLEN]; 875 UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10}; 876 log_verbose("Testing V2L #5 for case %d\n", i); 877 pseudoToU16(srcSize,logicalOrder[i],src); 878 ec = U_ZERO_ERROR; 879 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec); 880 if(U_FAILURE(ec)){ 881 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", 882 i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec)); 883 } 884 /* try pre-flighting */ 885 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec); 886 if(ec!=U_BUFFER_OVERFLOW_ERROR){ 887 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); 888 }else{ 889 ec= U_ZERO_ERROR; 890 } 891 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec); 892 u16ToPseudo(destSize,dest,chars); 893 if(strcmp(visualOrder4[i],chars)!=0){ 894 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS.\n" 895 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", 896 logicalOrder[i],visualOrder4[i],chars,formatLevels(bidi, formatChars),i); 897 } 898 } 899 ubidi_close(bidi); 900 901 log_verbose("\nExiting TestReorder\n\n"); 902 } 903 904 static void 905 testReorderArabicMathSymbols(void) { 906 static const UChar logicalOrder[][MAXLEN]={ 907 /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */ 908 {0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20, 909 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20, 910 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20, 911 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20, 912 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20, 913 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20, 914 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20, 915 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B}, 916 /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */ 917 {0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20, 918 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20, 919 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20, 920 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20, 921 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20, 922 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20, 923 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20, 924 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B}, 925 /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */ 926 {0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20, 927 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20, 928 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20, 929 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20, 930 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20, 931 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20, 932 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20, 933 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB}, 934 /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */ 935 {0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20, 936 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20, 937 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20, 938 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20, 939 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20, 940 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20, 941 0xD83B, 0xDE39, 0xD83B, 0xDE3B}, 942 /* Arabic mathematical Symbols - Tailed Symbols */ 943 {0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20, 944 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20, 945 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20, 946 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F} 947 }; 948 static const UChar visualOrder[][MAXLEN]={ 949 /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */ 950 {0xD83B, 0xDE1B, 0xD83B, 0xDE1A, 0xD83B, 0xDE19, 0x20, 951 0xD83B, 0xDE18, 0xD83B, 0xDE17, 0xD83B, 0xDE16, 0x20, 952 0xD83B, 0xDE15, 0xD83B, 0xDE14, 0xD83B, 0xDE13, 0xD83B, 0xDE12, 0x20, 953 0xD83B, 0xDE11, 0xD83B, 0xDE10, 0xD83B, 0xDE0F, 0xD83B, 0xDE0E, 0x20, 954 0xD83B, 0xDE0D, 0xD83B, 0xDE0C, 0xD83B, 0xDE0B, 0xD83B, 0xDE0A, 0x20, 955 0xD83B, 0xDE09, 0xD83B, 0xDE08, 0xD83B, 0xDE07, 0x20, 956 0xD83B, 0xDE06, 0xD83B, 0xDE05, 0xD83B, 0xDE24, 0x20, 957 0xD83B, 0xDE03, 0xD83B, 0xDE02, 0xD83B, 0xDE01, 0xD83B, 0xDE00}, 958 /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */ 959 {0xD83B, 0xDE9B, 0xD83B, 0xDE9A, 0xD83B, 0xDE99, 0x20, 960 0xD83B, 0xDE98, 0xD83B, 0xDE97, 0xD83B, 0xDE96, 0x20, 961 0xD83B, 0xDE95, 0xD83B, 0xDE94, 0xD83B, 0xDE93, 0xD83B, 0xDE92, 0x20, 962 0xD83B, 0xDE91, 0xD83B, 0xDE90, 0xD83B, 0xDE8F, 0xD83B, 0xDE8E, 0x20, 963 0xD83B, 0xDE8D, 0xD83B, 0xDE8C, 0xD83B, 0xDE8B, 0x20, 964 0xD83B, 0xDE89, 0xD83B, 0xDE88, 0xD83B, 0xDE87, 0x20, 965 0xD83B, 0xDE86, 0xD83B, 0xDE85, 0xD83B, 0xDE84, 0x20, 966 0xD83B, 0xDE83, 0xD83B, 0xDE82, 0xD83B, 0xDE81, 0xD83B, 0xDE80}, 967 /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */ 968 {0xD83B, 0xDEBB, 0xD83B, 0xDEBA, 0xD83B, 0xDEB9, 0x20, 969 0xD83B, 0xDEB8, 0xD83B, 0xDEB7, 0xD83B, 0xDEB6, 0x20, 970 0xD83B, 0xDEB5, 0xD83B, 0xDEB4, 0xD83B, 0xDEB3, 0xD83B, 0xDEB2, 0x20, 971 0xD83B, 0xDEB1, 0xD83B, 0xDEB0, 0xD83B, 0xDEAF, 0xD83B, 0xDEAE, 0x20, 972 0xD83B, 0xDEAD, 0xD83B, 0xDEAC, 0xD83B, 0xDEAB, 0x20, 973 0xD83B, 0xDEA9, 0xD83B, 0xDEA8, 0xD83B, 0xDEA7, 0x20, 974 0xD83B, 0xDEA6, 0xD83B, 0xDEA5, 0x20, 975 0xD83B, 0xDEA3, 0xD83B, 0xDEA2, 0xD83B, 0xDEA1}, 976 /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */ 977 {0xD83B, 0xDE3B, 0xD83B, 0xDE39, 0x20, 978 0xD83B, 0xDE37, 0xD83B, 0xDE36, 0x20, 979 0xD83B, 0xDE35, 0xD83B, 0xDE34, 0xD83B, 0xDE32, 0x20, 980 0xD83B, 0xDE31, 0xD83B, 0xDE30, 0xD83B, 0xDE2F, 0xD83B, 0xDE2E, 0x20, 981 0xD83B, 0xDE2D, 0xD83B, 0xDE2C, 0xD83B, 0xDE2B, 0xD83B, 0xDE2A, 0x20, 982 0xD83B, 0xDE29, 0xD83B, 0xDE27, 0x20, 983 0xD83B, 0xDE22, 0xD83B, 0xDE21}, 984 /* Arabic mathematical Symbols - Tailed Symbols */ 985 {0xD83B, 0xDE5F, 0xD83B, 0xDE5D, 0xD83B, 0xDE5B, 0xD83B, 0xDE59, 0x20, 986 0xD83B, 0xDE57, 0xD83B, 0xDE54, 0xD83B, 0xDE52, 0xD83B, 0xDE51, 0x20, 987 0xD83B, 0xDE4F, 0xD83B, 0xDE4E, 0xD83B, 0xDE4D, 0x20, 988 0xD83B, 0xDE4B, 0xD83B, 0xDE49, 0xD83B, 0xDE47, 0xD83B, 0xDE42} 989 }; 990 char formatChars[MAXLEN]; 991 UErrorCode ec = U_ZERO_ERROR; 992 UBiDi* bidi = ubidi_open(); 993 int i; 994 995 log_verbose("\nEntering TestReorderArabicMathSymbols\n\n"); 996 997 for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){ 998 int32_t srcSize = u_strlen(logicalOrder[i]); 999 int32_t destSize = srcSize*2; 1000 UChar dest[MAXLEN]; 1001 log_verbose("Testing L2V #1 for case %d\n", i); 1002 ec = U_ZERO_ERROR; 1003 ubidi_setPara(bidi,logicalOrder[i],srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec); 1004 if(U_FAILURE(ec)){ 1005 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", 1006 i, UBIDI_DEFAULT_LTR, u_errorName(ec)); 1007 } 1008 /* try pre-flighting */ 1009 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec); 1010 if(ec!=U_BUFFER_OVERFLOW_ERROR){ 1011 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); 1012 }else if(destSize!=srcSize){ 1013 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize); 1014 }else{ 1015 ec= U_ZERO_ERROR; 1016 } 1017 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec); 1018 if(destSize!=srcSize){ 1019 log_err("ubidi_writeReordered() destSize and srcSize do not match\n"); 1020 }else if(memcmp(dest, visualOrder[i], destSize*U_SIZEOF_UCHAR)!=0){ 1021 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n" 1022 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", 1023 logicalOrder[i],visualOrder[i],dest,formatLevels(bidi, formatChars),i); 1024 } 1025 } 1026 1027 ubidi_close(bidi); 1028 1029 log_verbose("\nExiting TestReorderArabicMathSymbols\n\n"); 1030 } 1031 1032 static void 1033 doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, int32_t lineStart, UBool countRunsFirst) { 1034 const uint8_t *dirProps=test->text+lineStart; 1035 const UBiDiLevel *levels=test->levels; 1036 const uint8_t *visualMap=test->visualMap; 1037 int32_t i, len=ubidi_getLength(pBiDi), logicalIndex, runCount = 0; 1038 UErrorCode errorCode=U_ZERO_ERROR; 1039 UBiDiLevel level, level2; 1040 1041 if (countRunsFirst) { 1042 log_verbose("Calling ubidi_countRuns() first.\n"); 1043 1044 runCount = ubidi_countRuns(pBiDi, &errorCode); 1045 1046 if(U_FAILURE(errorCode)) { 1047 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); 1048 return; 1049 } 1050 } else { 1051 log_verbose("Calling ubidi_getLogicalMap() first.\n"); 1052 } 1053 1054 _testReordering(pBiDi, testNumber); 1055 1056 for(i=0; i<len; ++i) { 1057 log_verbose("%3d %3d %.*s%-3s @%d\n", 1058 i, ubidi_getLevelAt(pBiDi, i), ubidi_getLevelAt(pBiDi, i), levelString, 1059 dirPropNames[dirProps[i]], 1060 ubidi_getVisualIndex(pBiDi, i, &errorCode)); 1061 } 1062 1063 log_verbose("\n-----levels:"); 1064 for(i=0; i<len; ++i) { 1065 if(i>0) { 1066 log_verbose(","); 1067 } 1068 log_verbose(" %d", ubidi_getLevelAt(pBiDi, i)); 1069 } 1070 1071 log_verbose("\n--reordered:"); 1072 for(i=0; i<len; ++i) { 1073 if(i>0) { 1074 log_verbose(","); 1075 } 1076 log_verbose(" %d", ubidi_getVisualIndex(pBiDi, i, &errorCode)); 1077 } 1078 log_verbose("\n"); 1079 1080 if(test->direction!=ubidi_getDirection(pBiDi)) { 1081 log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber, ubidi_getDirection(pBiDi)); 1082 } 1083 1084 if(test->resultLevel!=ubidi_getParaLevel(pBiDi)) { 1085 log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber, ubidi_getParaLevel(pBiDi)); 1086 } 1087 1088 for(i=0; i<len; ++i) { 1089 if(levels[i]!=ubidi_getLevelAt(pBiDi, i)) { 1090 log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d, expected %d\n", testNumber, i, ubidi_getLevelAt(pBiDi, i), levels[i]); 1091 return; 1092 } 1093 } 1094 1095 for(i=0; i<len; ++i) { 1096 logicalIndex=ubidi_getVisualIndex(pBiDi, i, &errorCode); 1097 if(U_FAILURE(errorCode)) { 1098 log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode)); 1099 return; 1100 } 1101 if(visualMap[i]!=logicalIndex) { 1102 log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber, i, logicalIndex); 1103 return; 1104 } 1105 } 1106 1107 if (! countRunsFirst) { 1108 runCount=ubidi_countRuns(pBiDi, &errorCode); 1109 if(U_FAILURE(errorCode)) { 1110 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); 1111 return; 1112 } 1113 } 1114 1115 for(logicalIndex=0; logicalIndex<len;) { 1116 level=ubidi_getLevelAt(pBiDi, logicalIndex); 1117 ubidi_getLogicalRun(pBiDi, logicalIndex, &logicalIndex, &level2); 1118 if(level!=level2) { 1119 log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): " 1120 "wrong level %d instead of %d\n", 1121 testNumber, logicalIndex, level, level2); 1122 } 1123 if(--runCount<0) { 1124 log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs " 1125 "compared to %d=ubidi_countRuns()\n", 1126 testNumber, ubidi_countRuns(pBiDi, &errorCode)); 1127 return; 1128 } 1129 } 1130 if(runCount!=0) { 1131 log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs " 1132 "compared to %d=ubidi_getRunCount()\n", 1133 testNumber, ubidi_countRuns(pBiDi, &errorCode)); 1134 return; 1135 } 1136 1137 log_verbose("\n\n"); 1138 } 1139 1140 static void 1141 _testReordering(UBiDi *pBiDi, int testNumber) { 1142 int32_t 1143 logicalMap1[MAXLEN], logicalMap2[MAXLEN], logicalMap3[MAXLEN], 1144 visualMap1[MAXLEN], visualMap2[MAXLEN], visualMap3[MAXLEN], visualMap4[MAXLEN]; 1145 UErrorCode errorCode=U_ZERO_ERROR; 1146 const UBiDiLevel *levels; 1147 int32_t i, length=ubidi_getLength(pBiDi), 1148 destLength=ubidi_getResultLength(pBiDi); 1149 int32_t runCount, visualIndex, logicalStart, runLength; 1150 UBool odd; 1151 1152 if(length<=0) { 1153 return; 1154 } 1155 1156 /* get the logical and visual maps from the object */ 1157 ubidi_getLogicalMap(pBiDi, logicalMap1, &errorCode); 1158 if(U_FAILURE(errorCode)) { 1159 log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); 1160 return; 1161 } 1162 1163 ubidi_getVisualMap(pBiDi, visualMap1, &errorCode); 1164 if(U_FAILURE(errorCode)) { 1165 log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); 1166 return; 1167 } 1168 1169 /* invert them both */ 1170 ubidi_invertMap(logicalMap1, visualMap2, length); 1171 ubidi_invertMap(visualMap1, logicalMap2, destLength); 1172 1173 /* get them from the levels array, too */ 1174 levels=ubidi_getLevels(pBiDi, &errorCode); 1175 1176 if(U_FAILURE(errorCode)) { 1177 log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); 1178 return; 1179 } 1180 1181 ubidi_reorderLogical(levels, length, logicalMap3); 1182 ubidi_reorderVisual(levels, length, visualMap3); 1183 1184 /* get the visual map from the runs, too */ 1185 runCount=ubidi_countRuns(pBiDi, &errorCode); 1186 if(U_FAILURE(errorCode)) { 1187 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); 1188 return; 1189 } 1190 log_verbose("\n----%2d runs:", runCount); 1191 visualIndex=0; 1192 for(i=0; i<runCount; ++i) { 1193 odd=(UBool)ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength); 1194 log_verbose(" (%c @%d[%d])", odd ? 'R' : 'L', logicalStart, runLength); 1195 if(UBIDI_LTR==odd) { 1196 do { /* LTR */ 1197 visualMap4[visualIndex++]=logicalStart++; 1198 } while(--runLength>0); 1199 } else { 1200 logicalStart+=runLength; /* logicalLimit */ 1201 do { /* RTL */ 1202 visualMap4[visualIndex++]=--logicalStart; 1203 } while(--runLength>0); 1204 } 1205 } 1206 log_verbose("\n"); 1207 1208 /* print all the maps */ 1209 log_verbose("logical maps:\n"); 1210 for(i=0; i<length; ++i) { 1211 log_verbose("%4d", logicalMap1[i]); 1212 } 1213 log_verbose("\n"); 1214 for(i=0; i<length; ++i) { 1215 log_verbose("%4d", logicalMap2[i]); 1216 } 1217 log_verbose("\n"); 1218 for(i=0; i<length; ++i) { 1219 log_verbose("%4d", logicalMap3[i]); 1220 } 1221 1222 log_verbose("\nvisual maps:\n"); 1223 for(i=0; i<destLength; ++i) { 1224 log_verbose("%4d", visualMap1[i]); 1225 } 1226 log_verbose("\n"); 1227 for(i=0; i<destLength; ++i) { 1228 log_verbose("%4d", visualMap2[i]); 1229 } 1230 log_verbose("\n"); 1231 for(i=0; i<length; ++i) { 1232 log_verbose("%4d", visualMap3[i]); 1233 } 1234 log_verbose("\n"); 1235 for(i=0; i<length; ++i) { 1236 log_verbose("%4d", visualMap4[i]); 1237 } 1238 log_verbose("\n"); 1239 1240 /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */ 1241 for(i=0; i<length; ++i) { 1242 if(logicalMap1[i]!=logicalMap2[i]) { 1243 log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber, i); 1244 break; 1245 } 1246 if(logicalMap1[i]!=logicalMap3[i]) { 1247 log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber, i); 1248 break; 1249 } 1250 1251 if(visualMap1[i]!=visualMap2[i]) { 1252 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber, i); 1253 break; 1254 } 1255 if(visualMap1[i]!=visualMap3[i]) { 1256 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber, i); 1257 break; 1258 } 1259 if(visualMap1[i]!=visualMap4[i]) { 1260 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber, i); 1261 break; 1262 } 1263 1264 if(logicalMap1[i]!=ubidi_getVisualIndex(pBiDi, i, &errorCode)) { 1265 log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber, i); 1266 break; 1267 } 1268 if(U_FAILURE(errorCode)) { 1269 log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode)); 1270 break; 1271 } 1272 if(visualMap1[i]!=ubidi_getLogicalIndex(pBiDi, i, &errorCode)) { 1273 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber, i); 1274 break; 1275 } 1276 if(U_FAILURE(errorCode)) { 1277 log_err("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode)); 1278 break; 1279 } 1280 } 1281 } 1282 1283 #define RETURN_IF_BAD_ERRCODE(x) \ 1284 if (U_FAILURE(errorCode)) { \ 1285 log_err("\nbad errorCode %d at %s\n", errorCode, (x)); \ 1286 return; \ 1287 } \ 1288 1289 #define STRING_TEST_CASE(s) { (s), UPRV_LENGTHOF(s) } 1290 1291 static void testGetBaseDirection(void) { 1292 UBiDiDirection dir; 1293 int i; 1294 1295 /* Test Data */ 1296 static const UChar 1297 /*Mixed Start with L*/ 1298 stringMixedEnglishFirst[]={ 0x61, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 }, 1299 /*Mixed Start with AL*/ 1300 stringMixedArabicFirst[]={ 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 }, 1301 /*Mixed Start with R*/ 1302 stringMixedHebrewFirst[]={ 0x05EA, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 }, 1303 /*All AL (Arabic. Persian)*/ 1304 stringPersian[]={0x0698, 0x067E, 0x0686, 0x06AF, 0}, 1305 /*All R (Hebrew etc.)*/ 1306 stringHebrew[]={0x0590, 0x05D5, 0x05EA, 0x05F1, 0}, 1307 /*All L (English)*/ 1308 stringEnglish[]={0x71, 0x61, 0x66, 0}, 1309 /*Mixed Start with weak AL an then L*/ 1310 stringStartWeakAL[]={ 0x0663, 0x71, 0x61, 0x66, 0}, 1311 /*Mixed Start with weak L and then AL*/ 1312 stringStartWeakL[]={0x31, 0x0698, 0x067E, 0x0686, 0x06AF, 0}, 1313 /*Empty*/ 1314 stringEmpty[]={0}, 1315 /*Surrogate Char.*/ 1316 stringSurrogateChar[]={0xD800, 0xDC00, 0}, 1317 /*Invalid UChar*/ 1318 stringInvalidUchar[]={-1}, 1319 /*All weak L (English Digits)*/ 1320 stringAllEnglishDigits[]={0x31, 0x32, 0x33, 0}, 1321 /*All weak AL (Arabic Digits)*/ 1322 stringAllArabicDigits[]={0x0663, 0x0664, 0x0665, 0}, 1323 /*First L (English) others are R (Hebrew etc.) */ 1324 stringFirstL[] = {0x71, 0x0590, 0x05D5, 0x05EA, 0x05F1, 0}, 1325 /*Last R (Hebrew etc.) others are weak L (English Digits)*/ 1326 stringLastR[] = {0x31, 0x32, 0x33, 0x05F1, 0}; 1327 1328 static const struct { 1329 const UChar *s; 1330 int32_t length; 1331 } testCases[]={ 1332 STRING_TEST_CASE(stringMixedEnglishFirst), 1333 STRING_TEST_CASE(stringMixedArabicFirst), 1334 STRING_TEST_CASE(stringMixedHebrewFirst), 1335 STRING_TEST_CASE(stringPersian), 1336 STRING_TEST_CASE(stringHebrew), 1337 STRING_TEST_CASE(stringEnglish), 1338 STRING_TEST_CASE(stringStartWeakAL), 1339 STRING_TEST_CASE(stringStartWeakL), 1340 STRING_TEST_CASE(stringEmpty), 1341 STRING_TEST_CASE(stringSurrogateChar), 1342 STRING_TEST_CASE(stringInvalidUchar), 1343 STRING_TEST_CASE(stringAllEnglishDigits), 1344 STRING_TEST_CASE(stringAllArabicDigits), 1345 STRING_TEST_CASE(stringFirstL), 1346 STRING_TEST_CASE(stringLastR), 1347 }; 1348 1349 /* Expected results */ 1350 static const UBiDiDirection expectedDir[] ={ 1351 UBIDI_LTR, UBIDI_RTL, UBIDI_RTL, 1352 UBIDI_RTL, UBIDI_RTL, UBIDI_LTR, 1353 UBIDI_LTR, UBIDI_RTL, UBIDI_NEUTRAL, 1354 UBIDI_LTR, UBIDI_NEUTRAL, UBIDI_NEUTRAL, 1355 UBIDI_NEUTRAL, UBIDI_LTR, UBIDI_RTL 1356 }; 1357 1358 log_verbose("testGetBaseDirection() with %u test cases ---\n", 1359 UPRV_LENGTHOF(testCases)); 1360 /* Run Tests */ 1361 for(i=0; i<UPRV_LENGTHOF(testCases); ++i) { 1362 dir = ubidi_getBaseDirection(testCases[i].s, testCases[i].length ); 1363 log_verbose("Testing case %d\tReceived dir %d\n", i, dir); 1364 if (dir != expectedDir[i]) 1365 log_err("\nFailed getBaseDirection case %d Expected %d \tReceived %d\n", 1366 i, expectedDir[i], dir); 1367 } 1368 1369 /* Misc. tests */ 1370 /* NULL string */ 1371 dir = ubidi_getBaseDirection(NULL, 3); 1372 if (dir != UBIDI_NEUTRAL ) 1373 log_err("\nFailed getBaseDirection for NULL string " , 1374 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir); 1375 /*All L- English string and length=-3 */ 1376 dir = ubidi_getBaseDirection( stringEnglish, -3); 1377 if (dir != UBIDI_NEUTRAL ) 1378 log_err("\nFailed getBaseDirection for string w length= -3 ", 1379 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir); 1380 /*All L- English string and length=-1 */ 1381 dir = ubidi_getBaseDirection( stringEnglish, -1); 1382 if (dir != UBIDI_LTR ) 1383 log_err("\nFailed getBaseDirection for English string w length= -1 ", 1384 "\nExpected %d \nReceived %d", UBIDI_LTR, dir); 1385 /*All AL- Persian string and length=-1 */ 1386 dir = ubidi_getBaseDirection( stringPersian, -1); 1387 if (dir != UBIDI_RTL ) 1388 log_err("\nFailed getBaseDirection for Persian string w length= -1 ", 1389 "\nExpected %d \nReceived %d", UBIDI_RTL, dir); 1390 /*All R- Hebrew string and length=-1 */ 1391 dir = ubidi_getBaseDirection( stringHebrew, -1); 1392 if (dir != UBIDI_RTL ) 1393 log_err("\nFailed getBaseDirection for Hebrew string w length= -1 ", 1394 "\nExpected %d \nReceived %d", UBIDI_RTL, dir); 1395 /*All weak L- English digits string and length=-1 */ 1396 dir = ubidi_getBaseDirection(stringAllEnglishDigits, -1); 1397 if (dir != UBIDI_NEUTRAL ) 1398 log_err("\nFailed getBaseDirection for English digits string w length= -1 ", 1399 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir); 1400 /*All weak AL- Arabic digits string and length=-1 */ 1401 dir = ubidi_getBaseDirection(stringAllArabicDigits, -1); 1402 if (dir != UBIDI_NEUTRAL ) 1403 log_err("\nFailed getBaseDirection for Arabic string w length= -1 ", 1404 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir); 1405 1406 } 1407 1408 1409 static void doMisc(void) { 1410 /* Miscellaneous tests to exercize less popular code paths */ 1411 UBiDi *bidi, *bidiLine; 1412 UChar src[MAXLEN], dest[MAXLEN]; 1413 int32_t srcLen, destLen, runCount, i; 1414 UBiDiLevel level; 1415 UBiDiDirection dir; 1416 int32_t map[MAXLEN]; 1417 UErrorCode errorCode=U_ZERO_ERROR; 1418 static const int32_t srcMap[6] = {0,1,-1,5,4}; 1419 static const int32_t dstMap[6] = {0,1,-1,-1,4,3}; 1420 1421 bidi = ubidi_openSized(120, 66, &errorCode); 1422 if (bidi == NULL) { 1423 log_err("Error with openSized(120, 66)\n"); 1424 return; 1425 } 1426 bidiLine = ubidi_open(); 1427 if (bidi == NULL) { 1428 log_err("Error with open()\n"); 1429 return; 1430 } 1431 1432 destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode); 1433 if (destLen != 0) { 1434 log_err("\nwriteReverse should return zero length, ", 1435 "returned %d instead\n", destLen); 1436 } 1437 RETURN_IF_BAD_ERRCODE("#1#"); 1438 1439 ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode); 1440 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1441 if (destLen != 0) { 1442 log_err("\nwriteReordered should return zero length, ", 1443 "returned %d instead\n", destLen); 1444 } 1445 RETURN_IF_BAD_ERRCODE("#2#"); 1446 1447 srcLen = u_unescape("abc ", src, MAXLEN); 1448 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); 1449 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); 1450 for (i = 3; i < 6; i++) { 1451 level = ubidi_getLevelAt(bidiLine, i); 1452 if (level != UBIDI_RTL) { 1453 log_err("\nTrailing space at index %d should get paragraph level" 1454 "%d, got %d instead\n", i, UBIDI_RTL, level); 1455 } 1456 } 1457 RETURN_IF_BAD_ERRCODE("#3#"); 1458 1459 srcLen = u_unescape("abc def", src, MAXLEN); 1460 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); 1461 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); 1462 for (i = 3; i < 6; i++) { 1463 level = ubidi_getLevelAt(bidiLine, i); 1464 if (level != UBIDI_RTL) { 1465 log_err("\nTrailing space at index %d should get paragraph level" 1466 "%d, got %d instead\n", i, UBIDI_RTL, level); 1467 } 1468 } 1469 RETURN_IF_BAD_ERRCODE("#4#"); 1470 1471 srcLen = u_unescape("abcdefghi ", src, MAXLEN); 1472 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); 1473 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); 1474 for (i = 3; i < 6; i++) { 1475 level = ubidi_getLevelAt(bidiLine, i); 1476 if (level != 2) { 1477 log_err("\nTrailing char at index %d should get level 2, " 1478 "got %d instead\n", i, level); 1479 } 1480 } 1481 RETURN_IF_BAD_ERRCODE("#5#"); 1482 1483 ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS); 1484 srcLen = u_unescape("\\u200eabc def", src, MAXLEN); 1485 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); 1486 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); 1487 destLen = ubidi_getResultLength(bidiLine); 1488 if (destLen != 5) { 1489 log_err("\nWrong result length, should be 5, got %d\n", destLen); 1490 } 1491 RETURN_IF_BAD_ERRCODE("#6#"); 1492 1493 srcLen = u_unescape("abcdefghi", src, MAXLEN); 1494 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); 1495 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); 1496 dir = ubidi_getDirection(bidiLine); 1497 if (dir != UBIDI_LTR) { 1498 log_err("\nWrong direction #1, should be %d, got %d\n", 1499 UBIDI_LTR, dir); 1500 } 1501 RETURN_IF_BAD_ERRCODE("#7#"); 1502 1503 ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode); 1504 runCount = ubidi_countRuns(bidi, &errorCode); 1505 if (runCount != 0) { 1506 log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount); 1507 } 1508 RETURN_IF_BAD_ERRCODE("#8#"); 1509 1510 srcLen = u_unescape(" ", src, MAXLEN); 1511 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); 1512 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); 1513 runCount = ubidi_countRuns(bidiLine, &errorCode); 1514 if (runCount != 1) { 1515 log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount); 1516 } 1517 RETURN_IF_BAD_ERRCODE("#9#"); 1518 1519 srcLen = u_unescape("a\\u05d0 bc", src, MAXLEN); 1520 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); 1521 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); 1522 dir = ubidi_getDirection(bidi); 1523 if (dir != UBIDI_MIXED) { 1524 log_err("\nWrong direction #2, should be %d, got %d\n", 1525 UBIDI_MIXED, dir); 1526 } 1527 dir = ubidi_getDirection(bidiLine); 1528 if (dir != UBIDI_MIXED) { 1529 log_err("\nWrong direction #3, should be %d, got %d\n", 1530 UBIDI_MIXED, dir); 1531 } 1532 runCount = ubidi_countRuns(bidiLine, &errorCode); 1533 if (runCount != 2) { 1534 log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount); 1535 } 1536 RETURN_IF_BAD_ERRCODE("#10#"); 1537 1538 ubidi_invertMap(srcMap, map, 5); 1539 if (memcmp(dstMap, map, sizeof(dstMap))) { 1540 log_err("\nUnexpected inverted Map, got "); 1541 for (i = 0; i < 6; i++) { 1542 log_err("%d ", map[i]); 1543 } 1544 log_err("\n"); 1545 } 1546 1547 /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */ 1548 srcLen = u_unescape("abc\\u200e", src, MAXLEN); 1549 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); 1550 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 1551 UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode); 1552 if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) { 1553 log_err("\nWrong result #1, should be 'abc', got '%s'\n", 1554 aescstrdup(dest, destLen)); 1555 } 1556 RETURN_IF_BAD_ERRCODE("#11#"); 1557 1558 /* test inverse Bidi with marks and contextual orientation */ 1559 ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT); 1560 ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS); 1561 ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode); 1562 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1563 if (destLen != 0) { 1564 log_err("\nWrong result #2, length should be 0, got %d\n", destLen); 1565 } 1566 RETURN_IF_BAD_ERRCODE("#12#"); 1567 srcLen = u_unescape(" ", src, MAXLEN); 1568 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); 1569 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1570 if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) { 1571 log_err("\nWrong result #3, should be ' ', got '%s'\n", 1572 aescstrdup(dest, destLen)); 1573 } 1574 RETURN_IF_BAD_ERRCODE("#13#"); 1575 srcLen = u_unescape("abc", src, MAXLEN); 1576 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); 1577 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1578 if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) { 1579 log_err("\nWrong result #4, should be 'abc', got '%s'\n", 1580 aescstrdup(dest, destLen)); 1581 } 1582 RETURN_IF_BAD_ERRCODE("#14#"); 1583 srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN); 1584 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); 1585 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1586 srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN); 1587 if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) { 1588 log_err("\nWrong result #5, should be '%s', got '%s'\n", 1589 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 1590 } 1591 RETURN_IF_BAD_ERRCODE("#15#"); 1592 srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN); 1593 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); 1594 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1595 srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN); 1596 if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) { 1597 log_err("\nWrong result #6, should be '%s', got '%s'\n", 1598 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 1599 } 1600 RETURN_IF_BAD_ERRCODE("#16#"); 1601 srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN); 1602 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); 1603 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1604 srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN); 1605 if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) { 1606 log_err("\nWrong result #7, should be '%s', got '%s'\n", 1607 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 1608 } 1609 RETURN_IF_BAD_ERRCODE("#17#"); 1610 srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN); 1611 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); 1612 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1613 srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN); 1614 if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) { 1615 log_err("\nWrong result #8, should be '%s', got '%s'\n", 1616 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 1617 } 1618 RETURN_IF_BAD_ERRCODE("#18#"); 1619 ubidi_orderParagraphsLTR(bidi, TRUE); 1620 srcLen = u_unescape("\n\r \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r" 1621 "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n" 1622 "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN); 1623 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); 1624 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1625 srcLen = u_unescape("\n\r \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r" 1626 "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n" 1627 "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN); 1628 if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) { 1629 log_err("\nWrong result #9, should be '%s', got '%s'\n", 1630 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 1631 } 1632 RETURN_IF_BAD_ERRCODE("#19#"); 1633 srcLen = u_unescape("\\u05d0 \t", src, MAXLEN); 1634 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); 1635 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1636 srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN); 1637 if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) { 1638 log_err("\nWrong result #10, should be '%s', got '%s'\n", 1639 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 1640 } 1641 RETURN_IF_BAD_ERRCODE("#20#"); 1642 srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN); 1643 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); 1644 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1645 srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN); 1646 if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) { 1647 log_err("\nWrong result #11, should be '%s', got '%s'\n", 1648 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 1649 } 1650 RETURN_IF_BAD_ERRCODE("#21#"); 1651 srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN); 1652 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); 1653 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1654 srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN); 1655 if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) { 1656 log_err("\nWrong result #12, should be '%s', got '%s'\n", 1657 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 1658 } 1659 RETURN_IF_BAD_ERRCODE("#22#"); 1660 srcLen = u_unescape("ab \t", src, MAXLEN); 1661 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); 1662 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 1663 srcLen = u_unescape("\\u200f\t ab", src, MAXLEN); 1664 if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) { 1665 log_err("\nWrong result #13, should be '%s', got '%s'\n", 1666 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 1667 } 1668 RETURN_IF_BAD_ERRCODE("#23#"); 1669 1670 /* check exceeding para level */ 1671 ubidi_close(bidi); 1672 bidi = ubidi_open(); 1673 srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN); 1674 ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode); 1675 level = ubidi_getLevelAt(bidi, 2); 1676 if (level != UBIDI_MAX_EXPLICIT_LEVEL) { 1677 log_err("\nWrong level at index 2\n, should be %d, got %d\n", UBIDI_MAX_EXPLICIT_LEVEL, level); 1678 } 1679 RETURN_IF_BAD_ERRCODE("#24#"); 1680 1681 /* check 1-char runs with RUNS_ONLY */ 1682 ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY); 1683 srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN); 1684 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); 1685 runCount = ubidi_countRuns(bidi, &errorCode); 1686 if (runCount != 14) { 1687 log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount); 1688 } 1689 RETURN_IF_BAD_ERRCODE("#25#"); 1690 1691 ubidi_close(bidi); 1692 ubidi_close(bidiLine); 1693 } 1694 1695 static void 1696 testFailureRecovery(void) { 1697 UErrorCode errorCode; 1698 UBiDi *bidi, *bidiLine; 1699 UChar src[MAXLEN]; 1700 int32_t srcLen; 1701 UBiDiLevel level; 1702 UBiDiReorderingMode rm; 1703 static UBiDiLevel myLevels[3] = {6,5,4}; 1704 1705 log_verbose("\nEntering TestFailureRecovery\n\n"); 1706 errorCode = U_FILE_ACCESS_ERROR; 1707 if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0) { 1708 log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n"); 1709 } 1710 if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0) { 1711 log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n"); 1712 } 1713 errorCode = U_ZERO_ERROR; 1714 if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) { 1715 log_err("ubidi_writeReordered did not fail as expected\n"); 1716 } 1717 1718 bidi = ubidi_open(); 1719 srcLen = u_unescape("abc", src, MAXLEN); 1720 errorCode = U_ZERO_ERROR; 1721 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_LTR - 1, NULL, &errorCode); 1722 if (U_SUCCESS(errorCode)) { 1723 log_err("\nubidi_setPara did not fail when passed too big para level\n"); 1724 } 1725 errorCode = U_ZERO_ERROR; 1726 if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) { 1727 log_err("ubidi_writeReverse did not fail as expected\n"); 1728 } 1729 bidiLine = ubidi_open(); 1730 errorCode = U_ZERO_ERROR; 1731 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); 1732 if (U_SUCCESS(errorCode)) { 1733 log_err("\nubidi_setLine did not fail when called before valid setPara()\n"); 1734 } 1735 errorCode = U_ZERO_ERROR; 1736 srcLen = u_unescape("abc", src, MAXLEN); 1737 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR + 4, NULL, &errorCode); 1738 level = ubidi_getLevelAt(bidi, 3); 1739 if (level != 0) { 1740 log_err("\nubidi_getLevelAt did not fail when called with bad argument\n"); 1741 } 1742 errorCode = U_ZERO_ERROR; 1743 ubidi_close(bidi); 1744 bidi = ubidi_openSized(-1, 0, &errorCode); 1745 if (U_SUCCESS(errorCode)) { 1746 log_err("\nubidi_openSized did not fail when called with bad argument\n"); 1747 } 1748 ubidi_close(bidi); 1749 bidi = ubidi_openSized(2, 1, &errorCode); 1750 errorCode = U_ZERO_ERROR; 1751 srcLen = u_unescape("abc", src, MAXLEN); 1752 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); 1753 if (U_SUCCESS(errorCode)) { 1754 log_err("\nsetPara did not fail when called with text too long\n"); 1755 } 1756 errorCode = U_ZERO_ERROR; 1757 srcLen = u_unescape("=2", src, MAXLEN); 1758 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); 1759 ubidi_countRuns(bidi, &errorCode); 1760 if (U_SUCCESS(errorCode)) { 1761 log_err("\nsetPara did not fail when called for too many runs\n"); 1762 } 1763 ubidi_close(bidi); 1764 bidi = ubidi_open(); 1765 rm = ubidi_getReorderingMode(bidi); 1766 ubidi_setReorderingMode(bidi, UBIDI_REORDER_DEFAULT - 1); 1767 if (rm != ubidi_getReorderingMode(bidi)) { 1768 log_err("\nsetReorderingMode with bad argument #1 should have no effect\n"); 1769 } 1770 ubidi_setReorderingMode(bidi, 9999); 1771 if (rm != ubidi_getReorderingMode(bidi)) { 1772 log_err("\nsetReorderingMode with bad argument #2 should have no effect\n"); 1773 } 1774 1775 /* Try a surrogate char */ 1776 errorCode = U_ZERO_ERROR; 1777 srcLen = u_unescape("\\uD800\\uDC00", src, MAXLEN); 1778 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); 1779 if (ubidi_getDirection(bidi) != UBIDI_MIXED) { 1780 log_err("\ngetDirection for 1st surrogate char should be MIXED\n"); 1781 } 1782 errorCode = U_ZERO_ERROR; 1783 srcLen = u_unescape("abc", src, MAXLEN); 1784 ubidi_setPara(bidi, src, srcLen, 5, myLevels, &errorCode); 1785 if (U_SUCCESS(errorCode)) { 1786 log_err("\nsetPara did not fail when called with bad levels\n"); 1787 } 1788 ubidi_close(bidi); 1789 ubidi_close(bidiLine); 1790 1791 log_verbose("\nExiting TestFailureRecovery\n\n"); 1792 } 1793 1794 static void 1795 testMultipleParagraphs(void) { 1796 static const char* const text = "__ABC\\u001c" /* Para #0 offset 0 */ 1797 "__\\u05d0DE\\u001c" /* 1 6 */ 1798 "__123\\u001c" /* 2 12 */ 1799 "\\u000d\\u000a" /* 3 18 */ 1800 "FG\\u000d" /* 4 20 */ 1801 "\\u000d" /* 5 23 */ 1802 "HI\\u000d\\u000a" /* 6 24 */ 1803 "\\u000d\\u000a" /* 7 28 */ 1804 "\\u000a" /* 8 30 */ 1805 "\\u000a" /* 9 31 */ 1806 "JK\\u001c"; /* 10 32 */ 1807 static const int32_t paraCount=11; 1808 static const int32_t paraBounds[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35}; 1809 static const UBiDiLevel paraLevels[]={UBIDI_LTR, UBIDI_RTL, UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL, 22, 23}; 1810 static const UBiDiLevel multiLevels[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1811 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1812 {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1813 {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0}, 1814 {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}, 1815 {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}}; 1816 static const char* const text2 = "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2"; 1817 static const UBiDiLevel levels2[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2}; 1818 static UBiDiLevel myLevels[10] = {0,0,0,0,0,0,0,0,0,0}; 1819 static const UChar multiparaTestString[] = { 1820 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da, 1821 0x20, 0xa, 0xa, 0x41, 0x72, 0x74, 0x69, 0x73, 1822 0x74, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20, 1823 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa, 0x41, 0x6c, 1824 0x62, 0x75, 0x6d, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1, 1825 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa, 1826 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x20, 0x32, 0x3a, 1827 0x32, 0x37, 0xa, 0xa 1828 }; 1829 static const UBiDiLevel multiparaTestLevels[] = { 1830 1, 1, 1, 1, 1, 1, 1, 1, 1831 1, 1, 0, 0, 0, 0, 0, 0, 1832 0, 0, 0, 1, 1, 1, 1, 1, 1833 1, 1, 1, 0, 0, 0, 0, 0, 1834 0, 0, 0, 0, 0, 1, 1, 1, 1835 1, 1, 1, 1, 1, 0, 0, 0, 1836 0, 0, 0, 0, 0, 0, 0, 0, 1837 0, 0, 0, 0 1838 }; 1839 UBiDiLevel gotLevel; 1840 const UBiDiLevel* gotLevels; 1841 UBool orderParagraphsLTR; 1842 UChar src[MAXLEN], dest[MAXLEN]; 1843 UErrorCode errorCode=U_ZERO_ERROR; 1844 UBiDi* pBidi=ubidi_open(); 1845 UBiDi* pLine; 1846 int32_t srcSize, count, paraStart, paraLimit, paraIndex, length; 1847 int32_t srcLen, destLen; 1848 int i, j, k; 1849 1850 log_verbose("\nEntering TestMultipleParagraphs\n\n"); 1851 u_unescape(text, src, MAXLEN); 1852 srcSize=u_strlen(src); 1853 ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode); 1854 if(U_FAILURE(errorCode)){ 1855 log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n", 1856 UBIDI_LTR, u_errorName(errorCode)); 1857 ubidi_close(pBidi); 1858 return; 1859 } 1860 /* check paragraph count and boundaries */ 1861 if (paraCount!=(count=ubidi_countParagraphs(pBidi))) { 1862 log_err("ubidi_countParagraphs returned %d, should be %d\n", 1863 count, paraCount); 1864 } 1865 for (i=0; i<paraCount; i++) { 1866 ubidi_getParagraphByIndex(pBidi, i, ¶Start, ¶Limit, NULL, &errorCode); 1867 if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) { 1868 log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n", 1869 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]); 1870 } 1871 } 1872 errorCode=U_ZERO_ERROR; 1873 /* check with last paragraph not terminated by B */ 1874 src[srcSize-1]='L'; 1875 ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode); 1876 if(U_FAILURE(errorCode)){ 1877 log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n", 1878 UBIDI_LTR, u_errorName(errorCode)); 1879 ubidi_close(pBidi); 1880 return; 1881 } 1882 if (paraCount!=(count=ubidi_countParagraphs(pBidi))) { 1883 log_err("2nd ubidi_countParagraphs returned %d, should be %d\n", 1884 count, paraCount); 1885 } 1886 i=paraCount-1; 1887 ubidi_getParagraphByIndex(pBidi, i, ¶Start, ¶Limit, NULL, &errorCode); 1888 if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) { 1889 log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n", 1890 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]); 1891 } 1892 errorCode=U_ZERO_ERROR; 1893 /* check paraLevel for all paragraphs under various paraLevel specs */ 1894 for (k=0; k<6; k++) { 1895 ubidi_setPara(pBidi, src, srcSize, paraLevels[k], NULL, &errorCode); 1896 for (i=0; i<paraCount; i++) { 1897 paraIndex=ubidi_getParagraph(pBidi, paraBounds[i], NULL, NULL, &gotLevel, &errorCode); 1898 if (paraIndex!=i) { 1899 log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n", 1900 paraLevels[k], i, paraIndex, i); 1901 } 1902 if (gotLevel!=multiLevels[k][i]) { 1903 log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n", 1904 paraLevels[k], i, gotLevel, multiLevels[k][i]); 1905 } 1906 } 1907 gotLevel=ubidi_getParaLevel(pBidi); 1908 if (gotLevel!=multiLevels[k][0]) { 1909 log_err("For paraLevel=%d getParaLevel=%d, expected %d\n", 1910 paraLevels[k], gotLevel, multiLevels[k][0]); 1911 } 1912 } 1913 errorCode=U_ZERO_ERROR; 1914 /* check that the result of ubidi_getParaLevel changes if the first 1915 * paragraph has a different level 1916 */ 1917 src[0]=0x05d2; /* Hebrew letter Gimel */ 1918 ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_LTR, NULL, &errorCode); 1919 gotLevel=ubidi_getParaLevel(pBidi); 1920 if (gotLevel!=UBIDI_RTL) { 1921 log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n", 1922 gotLevel, UBIDI_RTL); 1923 } 1924 errorCode=U_ZERO_ERROR; 1925 /* check that line cannot overlap paragraph boundaries */ 1926 pLine=ubidi_open(); 1927 i=paraBounds[1]; 1928 k=paraBounds[2]+1; 1929 ubidi_setLine(pBidi, i, k, pLine, &errorCode); 1930 if (U_SUCCESS(errorCode)) { 1931 log_err("For line limits %d-%d got success %s\n", 1932 i, k, u_errorName(errorCode)); 1933 } 1934 errorCode=U_ZERO_ERROR; 1935 i=paraBounds[1]; 1936 k=paraBounds[2]; 1937 ubidi_setLine(pBidi, i, k, pLine, &errorCode); 1938 if (U_FAILURE(errorCode)) { 1939 log_err("For line limits %d-%d got error %s\n", 1940 i, k, u_errorName(errorCode)); 1941 errorCode=U_ZERO_ERROR; 1942 } 1943 /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */ 1944 ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode); 1945 /* get levels through para Bidi block */ 1946 gotLevels=ubidi_getLevels(pBidi, &errorCode); 1947 if (U_FAILURE(errorCode)) { 1948 log_err("Error on Para getLevels %s\n", u_errorName(errorCode)); 1949 ubidi_close(pLine); 1950 ubidi_close(pBidi); 1951 return; 1952 } 1953 for (i=26; i<32; i++) { 1954 if (gotLevels[i]!=UBIDI_RTL) { 1955 log_err("For char %d(%04x), level=%d, expected=%d\n", 1956 i, src[i], gotLevels[i], UBIDI_RTL); 1957 } 1958 } 1959 /* get levels through para Line block */ 1960 i=paraBounds[1]; 1961 k=paraBounds[2]; 1962 ubidi_setLine(pBidi, i, k, pLine, &errorCode); 1963 if (U_FAILURE(errorCode)) { 1964 log_err("For line limits %d-%d got error %s\n", 1965 i, k, u_errorName(errorCode)); 1966 ubidi_close(pLine); 1967 ubidi_close(pBidi); 1968 return; 1969 } 1970 paraIndex=ubidi_getParagraph(pLine, i, ¶Start, ¶Limit, &gotLevel, &errorCode); 1971 gotLevels=ubidi_getLevels(pLine, &errorCode); 1972 if (U_FAILURE(errorCode)) { 1973 log_err("Error on Line getLevels %s\n", u_errorName(errorCode)); 1974 ubidi_close(pLine); 1975 ubidi_close(pBidi); 1976 return; 1977 } 1978 length=ubidi_getLength(pLine); 1979 if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=UBIDI_RTL)) { 1980 log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, " 1981 "level of separator=%d expected=%d\n", 1982 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], UBIDI_RTL); 1983 } 1984 orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi); 1985 if (orderParagraphsLTR) { 1986 log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, FALSE); 1987 } 1988 ubidi_orderParagraphsLTR(pBidi, TRUE); 1989 orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi); 1990 if (!orderParagraphsLTR) { 1991 log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, TRUE); 1992 } 1993 /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */ 1994 ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode); 1995 /* get levels through para Bidi block */ 1996 gotLevels=ubidi_getLevels(pBidi, &errorCode); 1997 for (i=26; i<32; i++) { 1998 if (gotLevels[i]!=0) { 1999 log_err("For char %d(%04x), level=%d, expected=%d\n", 2000 i, src[i], gotLevels[i], 0); 2001 } 2002 } 2003 errorCode=U_ZERO_ERROR; 2004 /* get levels through para Line block */ 2005 i=paraBounds[1]; 2006 k=paraBounds[2]; 2007 ubidi_setLine(pBidi, paraStart, paraLimit, pLine, &errorCode); 2008 paraIndex=ubidi_getParagraph(pLine, i, ¶Start, ¶Limit, &gotLevel, &errorCode); 2009 gotLevels=ubidi_getLevels(pLine, &errorCode); 2010 length=ubidi_getLength(pLine); 2011 if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=0)) { 2012 log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, " 2013 "level of separator=%d expected=%d\n", 2014 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], 0); 2015 log_verbose("levels="); 2016 for (count=0; count<length; count++) { 2017 log_verbose(" %d", gotLevels[count]); 2018 } 2019 log_verbose("\n"); 2020 } 2021 2022 /* test that the concatenation of separate invocations of the bidi code 2023 * on each individual paragraph in order matches the levels array that 2024 * results from invoking bidi once over the entire multiparagraph tests 2025 * (with orderParagraphsLTR false, of course) 2026 */ 2027 u_unescape(text, src, MAXLEN); /* restore original content */ 2028 srcSize=u_strlen(src); 2029 ubidi_orderParagraphsLTR(pBidi, FALSE); 2030 ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_RTL, NULL, &errorCode); 2031 gotLevels=ubidi_getLevels(pBidi, &errorCode); 2032 for (i=0; i<paraCount; i++) { 2033 /* use pLine for individual paragraphs */ 2034 paraStart = paraBounds[i]; 2035 length = paraBounds[i+1] - paraStart; 2036 ubidi_setPara(pLine, src+paraStart, length, UBIDI_DEFAULT_RTL, NULL, &errorCode); 2037 for (j=0; j<length; j++) { 2038 if ((k=ubidi_getLevelAt(pLine, j)) != (gotLevel=gotLevels[paraStart+j])) { 2039 log_err("Checking paragraph concatenation: for paragraph=%d, " 2040 "char=%d(%04x), level=%d, expected=%d\n", 2041 i, j, src[paraStart+j], k, gotLevel); 2042 } 2043 } 2044 } 2045 2046 /* ensure that leading numerics in a paragraph are not treated as arabic 2047 numerals because of arabic text in a preceding paragraph 2048 */ 2049 u_unescape(text2, src, MAXLEN); 2050 srcSize=u_strlen(src); 2051 ubidi_orderParagraphsLTR(pBidi, TRUE); 2052 ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode); 2053 gotLevels=ubidi_getLevels(pBidi, &errorCode); 2054 if (U_FAILURE(errorCode)) { 2055 log_err("Can't get levels. %s\n", u_errorName(errorCode)); 2056 return; 2057 } 2058 for (i=0; i<srcSize; i++) { 2059 if (gotLevels[i]!=levels2[i]) { 2060 log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n", 2061 i, src[i], gotLevels[i], levels2[i]); 2062 } 2063 } 2064 2065 /* check handling of whitespace before end of paragraph separator when 2066 * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B 2067 */ 2068 u_memset(src, 0x0020, MAXLEN); 2069 srcSize = 5; 2070 ubidi_orderParagraphsLTR(pBidi, TRUE); 2071 for (i=0x001c; i<=0x0020; i+=(0x0020-0x001c)) { 2072 src[4]=(UChar)i; /* with and without terminating B */ 2073 for (j=0x0041; j<=0x05d0; j+=(0x05d0-0x0041)) { 2074 src[0]=(UChar)j; /* leading 'A' or Alef */ 2075 for (gotLevel=4; gotLevel<=5; gotLevel++) { 2076 /* test even and odd paraLevel */ 2077 ubidi_setPara(pBidi, src, srcSize, gotLevel, NULL, &errorCode); 2078 gotLevels=ubidi_getLevels(pBidi, &errorCode); 2079 for (k=1; k<=3; k++) { 2080 if (gotLevels[k]!=gotLevel) { 2081 log_err("Checking trailing spaces: for leading_char=%04x, " 2082 "last_char=%04x, index=%d, level=%d, expected=%d\n", 2083 src[0], src[4], k, gotLevels[k], gotLevel); 2084 } 2085 } 2086 } 2087 } 2088 } 2089 2090 /* check default orientation when inverse bidi and paragraph starts 2091 * with LTR strong char and ends with RTL strong char, with and without 2092 * a terminating B 2093 */ 2094 ubidi_setReorderingMode(pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT); 2095 srcLen = u_unescape("abc \\u05d2\\u05d1\n", src, MAXLEN); 2096 ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode); 2097 destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode); 2098 srcLen = u_unescape("\\u05d1\\u05d2 abc\n", src, MAXLEN); 2099 if (memcmp(src, dest, destLen * sizeof(UChar))) { 2100 log_err("\nInvalid output #0, should be '%s', got '%s'\n", 2101 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 2102 } 2103 srcLen = u_unescape("abc \\u05d2\\u05d1", src, MAXLEN); 2104 ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode); 2105 destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode); 2106 srcLen = u_unescape("\\u05d1\\u05d2 abc", src, MAXLEN); 2107 if (memcmp(src, dest, destLen * sizeof(UChar))) { 2108 log_err("\nInvalid output #1, should be '%s', got '%s'\n", 2109 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 2110 } 2111 2112 /* check multiple paragraphs together with explicit levels 2113 */ 2114 ubidi_setReorderingMode(pBidi, UBIDI_REORDER_DEFAULT); 2115 srcLen = u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src, MAXLEN); 2116 ubidi_setPara(pBidi, src, srcLen, UBIDI_LTR, myLevels, &errorCode); 2117 destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode); 2118 srcLen = u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src, MAXLEN); 2119 if (memcmp(src, dest, destLen * sizeof(UChar))) { 2120 log_err("\nInvalid output #2, should be '%s', got '%s'\n", 2121 aescstrdup(src, srcLen), aescstrdup(dest, destLen)); 2122 } 2123 count = ubidi_countParagraphs(pBidi); 2124 if (count != 2) { 2125 log_err("\nInvalid number of paras, should be 2, got %d\n", count); 2126 } 2127 2128 ubidi_close(pLine); 2129 ubidi_close(pBidi); 2130 log_verbose("\nExiting TestMultipleParagraphs\n\n"); 2131 2132 /* check levels in multiple paragraphs with default para level 2133 */ 2134 pBidi = ubidi_open(); 2135 errorCode = U_ZERO_ERROR; 2136 ubidi_setPara(pBidi, multiparaTestString, UPRV_LENGTHOF(multiparaTestString), 2137 UBIDI_DEFAULT_LTR, NULL, &errorCode); 2138 if (U_FAILURE(errorCode)) { 2139 log_err("ubidi_setPara failed for multiparaTestString\n"); 2140 ubidi_close(pBidi); 2141 return; 2142 } 2143 gotLevels = ubidi_getLevels(pBidi, &errorCode); 2144 if (U_FAILURE(errorCode)) { 2145 log_err("ubidi_getLevels failed for multiparaTestString\n"); 2146 ubidi_close(pBidi); 2147 return; 2148 } 2149 for (i = 0; i < UPRV_LENGTHOF(multiparaTestString); i++) { 2150 if (gotLevels[i] != multiparaTestLevels[i]) { 2151 log_err("Error on level for multiparaTestString at index %d, " 2152 "expected=%d, actual=%d\n", 2153 i, multiparaTestLevels[i], gotLevels[i]); 2154 } 2155 } 2156 ubidi_close(pBidi); 2157 2158 } 2159 2160 2161 /* inverse BiDi ------------------------------------------------------------- */ 2162 2163 static int countRoundtrips=0, countNonRoundtrips=0; 2164 2165 #define STRING_TEST_CASE(s) { (s), UPRV_LENGTHOF(s) } 2166 2167 static void 2168 testInverse(void) { 2169 static const UChar 2170 string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 }, 2171 string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 }, 2172 string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 }, 2173 string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 }, 2174 string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 }; 2175 2176 static const struct { 2177 const UChar *s; 2178 int32_t length; 2179 } testCases[]={ 2180 STRING_TEST_CASE(string0), 2181 STRING_TEST_CASE(string1), 2182 STRING_TEST_CASE(string2), 2183 STRING_TEST_CASE(string3), 2184 STRING_TEST_CASE(string4) 2185 }; 2186 2187 UBiDi *pBiDi; 2188 UErrorCode errorCode; 2189 int i; 2190 2191 log_verbose("\nEntering TestInverse\n\n"); 2192 pBiDi=ubidi_open(); 2193 if(pBiDi==NULL) { 2194 log_err("unable to open a UBiDi object (out of memory)\n"); 2195 return; 2196 } 2197 2198 log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", UPRV_LENGTHOF(testCases)); 2199 for(i=0; i<UPRV_LENGTHOF(testCases); ++i) { 2200 log_verbose("Testing case %d\n", i); 2201 errorCode=U_ZERO_ERROR; 2202 _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode); 2203 } 2204 2205 log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", UPRV_LENGTHOF(testCases)); 2206 for(i=0; i<UPRV_LENGTHOF(testCases); ++i) { 2207 log_verbose("Testing case %d\n", i); 2208 errorCode=U_ZERO_ERROR; 2209 _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode); 2210 } 2211 2212 _testManyInverseBidi(pBiDi, 0); 2213 _testManyInverseBidi(pBiDi, 1); 2214 2215 ubidi_close(pBiDi); 2216 2217 log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips); 2218 2219 _testWriteReverse(); 2220 2221 _testManyAddedPoints(); 2222 2223 _testMisc(); 2224 2225 log_verbose("\nExiting TestInverse\n\n"); 2226 } 2227 2228 #define COUNT_REPEAT_SEGMENTS 6 2229 2230 static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={ 2231 { 0x61, 0x62 }, /* L */ 2232 { 0x5d0, 0x5d1 }, /* R */ 2233 { 0x627, 0x628 }, /* AL */ 2234 { 0x31, 0x32 }, /* EN */ 2235 { 0x661, 0x662 }, /* AN */ 2236 { 0x20, 0x20 } /* WS (N) */ 2237 }; 2238 2239 static void 2240 _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction) { 2241 UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 }; 2242 int i, j, k; 2243 UErrorCode errorCode; 2244 2245 log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n", 2246 direction==0 ? 'L' : 'R'); 2247 for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) { 2248 text[0]=repeatSegments[i][0]; 2249 text[1]=repeatSegments[i][1]; 2250 for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) { 2251 text[3]=repeatSegments[j][0]; 2252 text[4]=repeatSegments[j][1]; 2253 for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) { 2254 text[6]=repeatSegments[k][0]; 2255 text[7]=repeatSegments[k][1]; 2256 2257 errorCode=U_ZERO_ERROR; 2258 log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i, j, k); 2259 _testInverseBidi(pBiDi, text, 8, direction, &errorCode); 2260 } 2261 } 2262 } 2263 } 2264 2265 static void 2266 _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength, 2267 UBiDiLevel direction, UErrorCode *pErrorCode) { 2268 UChar visualLTR[MAXLEN], logicalDest[MAXLEN], visualDest[MAXLEN]; 2269 int32_t ltrLength, logicalLength, visualLength; 2270 2271 if(direction==0) { 2272 log_verbose("inverse Bidi: testInverse(L)\n"); 2273 2274 /* convert visual to logical */ 2275 ubidi_setInverse(pBiDi, TRUE); 2276 if (!ubidi_isInverse(pBiDi)) { 2277 log_err("Error while doing ubidi_setInverse(TRUE)\n"); 2278 } 2279 ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode); 2280 if (src != ubidi_getText(pBiDi)) { 2281 log_err("Wrong value returned by ubidi_getText\n"); 2282 } 2283 logicalLength=ubidi_writeReordered(pBiDi, logicalDest, UPRV_LENGTHOF(logicalDest), 2284 UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode); 2285 log_verbose(" v "); 2286 printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode)); 2287 log_verbose("\n"); 2288 2289 /* convert back to visual LTR */ 2290 ubidi_setInverse(pBiDi, FALSE); 2291 if (ubidi_isInverse(pBiDi)) { 2292 log_err("Error while doing ubidi_setInverse(FALSE)\n"); 2293 } 2294 ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode); 2295 visualLength=ubidi_writeReordered(pBiDi, visualDest, UPRV_LENGTHOF(visualDest), 2296 UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode); 2297 } else { 2298 log_verbose("inverse Bidi: testInverse(R)\n"); 2299 2300 /* reverse visual from RTL to LTR */ 2301 ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, UPRV_LENGTHOF(visualLTR), 0, pErrorCode); 2302 log_verbose(" vr"); 2303 printUnicode(src, srcLength, NULL); 2304 log_verbose("\n"); 2305 2306 /* convert visual RTL to logical */ 2307 ubidi_setInverse(pBiDi, TRUE); 2308 ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode); 2309 logicalLength=ubidi_writeReordered(pBiDi, logicalDest, UPRV_LENGTHOF(logicalDest), 2310 UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode); 2311 log_verbose(" vl"); 2312 printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode)); 2313 log_verbose("\n"); 2314 2315 /* convert back to visual RTL */ 2316 ubidi_setInverse(pBiDi, FALSE); 2317 ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode); 2318 visualLength=ubidi_writeReordered(pBiDi, visualDest, UPRV_LENGTHOF(visualDest), 2319 UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode); 2320 } 2321 log_verbose(" l "); 2322 printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode)); 2323 log_verbose("\n"); 2324 log_verbose(" v "); 2325 printUnicode(visualDest, visualLength, NULL); 2326 log_verbose("\n"); 2327 2328 /* check and print results */ 2329 if(U_FAILURE(*pErrorCode)) { 2330 log_err("inverse BiDi: *** error %s\n" 2331 " turn on verbose mode to see details\n", u_errorName(*pErrorCode)); 2332 } else if(srcLength==visualLength && memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) { 2333 ++countRoundtrips; 2334 log_verbose(" + roundtripped\n"); 2335 } else { 2336 ++countNonRoundtrips; 2337 log_verbose(" * did not roundtrip\n"); 2338 log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n" 2339 " turn on verbose mode to see details\n"); 2340 } 2341 } 2342 2343 static void 2344 _testWriteReverse(void) { 2345 /* U+064e and U+0650 are combining marks (Mn) */ 2346 static const UChar forward[]={ 2347 0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29 2348 }, reverseKeepCombining[]={ 2349 0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f 2350 }, reverseRemoveControlsKeepCombiningDoMirror[]={ 2351 0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650 2352 }; 2353 UChar reverse[10]; 2354 UErrorCode errorCode; 2355 int32_t length; 2356 2357 /* test ubidi_writeReverse() with "interesting" options */ 2358 errorCode=U_ZERO_ERROR; 2359 length=ubidi_writeReverse(forward, UPRV_LENGTHOF(forward), 2360 reverse, UPRV_LENGTHOF(reverse), 2361 UBIDI_KEEP_BASE_COMBINING, 2362 &errorCode); 2363 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(reverseKeepCombining) || memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) { 2364 log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n", 2365 length, UPRV_LENGTHOF(reverseKeepCombining), u_errorName(errorCode)); 2366 } 2367 2368 memset(reverse, 0xa5, UPRV_LENGTHOF(reverse)*U_SIZEOF_UCHAR); 2369 errorCode=U_ZERO_ERROR; 2370 length=ubidi_writeReverse(forward, UPRV_LENGTHOF(forward), 2371 reverse, UPRV_LENGTHOF(reverse), 2372 UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING, 2373 &errorCode); 2374 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) { 2375 log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n" 2376 " length=%d (should be %d), error code %s\n", 2377 length, UPRV_LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode)); 2378 } 2379 } 2380 2381 static void _testManyAddedPoints(void) { 2382 UErrorCode errorCode = U_ZERO_ERROR; 2383 UBiDi *bidi = ubidi_open(); 2384 UChar text[90], dest[MAXLEN], expected[120]; 2385 int destLen, i; 2386 for (i = 0; i < UPRV_LENGTHOF(text); i+=3) { 2387 text[i] = 0x0061; /* 'a' */ 2388 text[i+1] = 0x05d0; 2389 text[i+2] = 0x0033; /* '3' */ 2390 } 2391 ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT); 2392 ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS); 2393 ubidi_setPara(bidi, text, UPRV_LENGTHOF(text), UBIDI_LTR, NULL, &errorCode); 2394 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); 2395 for (i = 0; i < UPRV_LENGTHOF(expected); i+=4) { 2396 expected[i] = 0x0061; /* 'a' */ 2397 expected[i+1] = 0x05d0; 2398 expected[i+2] = 0x200e; 2399 expected[i+3] = 0x0033; /* '3' */ 2400 } 2401 if (memcmp(dest, expected, destLen * sizeof(UChar))) { 2402 log_err("\nInvalid output with many added points, " 2403 "expected '%s', got '%s'\n", 2404 aescstrdup(expected, UPRV_LENGTHOF(expected)), 2405 aescstrdup(dest, destLen)); 2406 } 2407 ubidi_close(bidi); 2408 } 2409 2410 static void _testMisc(void) { 2411 UErrorCode errorCode = U_ZERO_ERROR; 2412 UBiDi *bidi = ubidi_open(); 2413 UChar src[3], dest[MAXLEN], expected[5]; 2414 int destLen; 2415 ubidi_setInverse(bidi, TRUE); 2416 src[0] = src[1] = src[2] = 0x0020; 2417 ubidi_setPara(bidi, src, UPRV_LENGTHOF(src), UBIDI_RTL, NULL, &errorCode); 2418 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 2419 UBIDI_OUTPUT_REVERSE | UBIDI_INSERT_LRM_FOR_NUMERIC, 2420 &errorCode); 2421 u_unescape("\\u200f \\u200f", expected, 5); 2422 if (memcmp(dest, expected, destLen * sizeof(UChar))) { 2423 log_err("\nInvalid output with RLM at both sides, " 2424 "expected '%s', got '%s'\n", 2425 aescstrdup(expected, UPRV_LENGTHOF(expected)), 2426 aescstrdup(dest, destLen)); 2427 } 2428 ubidi_close(bidi); 2429 } 2430 2431 /* arabic shaping ----------------------------------------------------------- */ 2432 2433 static void 2434 doArabicShapingTest(void) { 2435 static const UChar 2436 source[]={ 2437 0x31, /* en:1 */ 2438 0x627, /* arabic:alef */ 2439 0x32, /* en:2 */ 2440 0x6f3, /* an:3 */ 2441 0x61, /* latin:a */ 2442 0x34, /* en:4 */ 2443 0 2444 }, en2an[]={ 2445 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 2446 }, an2en[]={ 2447 0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0 2448 }, logical_alen2an_init_lr[]={ 2449 0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0 2450 }, logical_alen2an_init_al[]={ 2451 0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0 2452 }, reverse_alen2an_init_lr[]={ 2453 0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 2454 }, reverse_alen2an_init_al[]={ 2455 0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0 2456 }, lamalef[]={ 2457 0xfefb, 0 2458 }; 2459 UChar dest[8]; 2460 UErrorCode errorCode; 2461 int32_t length; 2462 2463 /* test number shaping */ 2464 2465 /* european->arabic */ 2466 errorCode=U_ZERO_ERROR; 2467 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2468 dest, UPRV_LENGTHOF(dest), 2469 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, 2470 &errorCode); 2471 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) { 2472 log_err("failure in u_shapeArabic(en2an)\n"); 2473 } 2474 2475 /* arabic->european */ 2476 errorCode=U_ZERO_ERROR; 2477 length=u_shapeArabic(source, -1, 2478 dest, UPRV_LENGTHOF(dest), 2479 U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED, 2480 &errorCode); 2481 if(U_FAILURE(errorCode) || length!=u_strlen(source) || memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) { 2482 log_err("failure in u_shapeArabic(an2en)\n"); 2483 } 2484 2485 /* european->arabic with context, logical order, initial state not AL */ 2486 errorCode=U_ZERO_ERROR; 2487 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2488 dest, UPRV_LENGTHOF(dest), 2489 U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN, 2490 &errorCode); 2491 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) { 2492 log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n"); 2493 } 2494 2495 /* european->arabic with context, logical order, initial state AL */ 2496 errorCode=U_ZERO_ERROR; 2497 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2498 dest, UPRV_LENGTHOF(dest), 2499 U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED, 2500 &errorCode); 2501 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) { 2502 log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n"); 2503 } 2504 2505 /* european->arabic with context, reverse order, initial state not AL */ 2506 errorCode=U_ZERO_ERROR; 2507 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2508 dest, UPRV_LENGTHOF(dest), 2509 U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2510 &errorCode); 2511 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) { 2512 log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n"); 2513 } 2514 2515 /* european->arabic with context, reverse order, initial state AL */ 2516 errorCode=U_ZERO_ERROR; 2517 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2518 dest, UPRV_LENGTHOF(dest), 2519 U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2520 &errorCode); 2521 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) { 2522 log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n"); 2523 } 2524 2525 /* test noop */ 2526 errorCode=U_ZERO_ERROR; 2527 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2528 dest, UPRV_LENGTHOF(dest), 2529 0, 2530 &errorCode); 2531 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) { 2532 log_err("failure in u_shapeArabic(noop)\n"); 2533 } 2534 2535 errorCode=U_ZERO_ERROR; 2536 length=u_shapeArabic(source, 0, 2537 dest, UPRV_LENGTHOF(dest), 2538 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, 2539 &errorCode); 2540 if(U_FAILURE(errorCode) || length!=0) { 2541 log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), UPRV_LENGTHOF(source)); 2542 } 2543 2544 /* preflight digit shaping */ 2545 errorCode=U_ZERO_ERROR; 2546 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2547 NULL, 0, 2548 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, 2549 &errorCode); 2550 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=UPRV_LENGTHOF(source)) { 2551 log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n", 2552 length, u_errorName(errorCode), UPRV_LENGTHOF(source)); 2553 } 2554 2555 /* test illegal arguments */ 2556 errorCode=U_ZERO_ERROR; 2557 length=u_shapeArabic(NULL, UPRV_LENGTHOF(source), 2558 dest, UPRV_LENGTHOF(dest), 2559 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, 2560 &errorCode); 2561 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 2562 log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); 2563 } 2564 2565 errorCode=U_ZERO_ERROR; 2566 length=u_shapeArabic(source, -2, 2567 dest, UPRV_LENGTHOF(dest), 2568 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, 2569 &errorCode); 2570 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 2571 log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); 2572 } 2573 2574 errorCode=U_ZERO_ERROR; 2575 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2576 NULL, UPRV_LENGTHOF(dest), 2577 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, 2578 &errorCode); 2579 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 2580 log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); 2581 } 2582 2583 errorCode=U_ZERO_ERROR; 2584 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2585 dest, -1, 2586 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, 2587 &errorCode); 2588 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 2589 log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); 2590 } 2591 2592 errorCode=U_ZERO_ERROR; 2593 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2594 dest, UPRV_LENGTHOF(dest), 2595 U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN, 2596 &errorCode); 2597 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 2598 log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); 2599 } 2600 2601 errorCode=U_ZERO_ERROR; 2602 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2603 dest, UPRV_LENGTHOF(dest), 2604 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED, 2605 &errorCode); 2606 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 2607 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); 2608 } 2609 2610 errorCode=U_ZERO_ERROR; 2611 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2612 (UChar *)(source+2), UPRV_LENGTHOF(dest), /* overlap source and destination */ 2613 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, 2614 &errorCode); 2615 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { 2616 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); 2617 } 2618 2619 errorCode=U_ZERO_ERROR; 2620 length=u_shapeArabic(lamalef, UPRV_LENGTHOF(lamalef), 2621 dest, UPRV_LENGTHOF(dest), 2622 U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2623 &errorCode); 2624 if(U_FAILURE(errorCode) || length == UPRV_LENGTHOF(lamalef)) { 2625 log_err("failure in u_shapeArabic(U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR)\n"); 2626 log_err("returned %s instead of U_ZERO_ERROR or returned length %d instead of 3\n", u_errorName(errorCode), length); 2627 } 2628 } 2629 2630 static void 2631 doLamAlefSpecialVLTRArabicShapingTest(void) { 2632 static const UChar 2633 source[]={ 2634 /*a*/ 0x20 ,0x646,0x622,0x644,0x627,0x20, 2635 /*b*/ 0x646,0x623,0x64E,0x644,0x627,0x20, 2636 /*c*/ 0x646,0x627,0x670,0x644,0x627,0x20, 2637 /*d*/ 0x646,0x622,0x653,0x644,0x627,0x20, 2638 /*e*/ 0x646,0x625,0x655,0x644,0x627,0x20, 2639 /*f*/ 0x646,0x622,0x654,0x644,0x627,0x20, 2640 /*g*/ 0xFEFC,0x639 2641 }, shape_near[]={ 2642 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20, 2643 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20, 2644 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20, 2645 0xfefc,0xfecb 2646 }, shape_at_end[]={ 2647 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670, 2648 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d, 2649 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20 2650 }, shape_at_begin[]={ 2651 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76, 2652 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d, 2653 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb 2654 }, shape_grow_shrink[]={ 2655 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5, 2656 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9, 2657 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb 2658 }, shape_excepttashkeel_near[]={ 2659 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20, 2660 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20, 2661 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20, 2662 0xfefc,0xfecb 2663 }, shape_excepttashkeel_at_end[]={ 2664 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5, 2665 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9, 2666 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20, 2667 0x20,0x20,0x20 2668 }, shape_excepttashkeel_at_begin[]={ 2669 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76, 2670 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d, 2671 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb 2672 }, shape_excepttashkeel_grow_shrink[]={ 2673 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670, 2674 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d, 2675 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb 2676 }; 2677 2678 UChar dest[38]; 2679 UErrorCode errorCode; 2680 int32_t length; 2681 2682 errorCode=U_ZERO_ERROR; 2683 2684 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2685 dest, UPRV_LENGTHOF(dest), 2686 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| 2687 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2688 &errorCode); 2689 2690 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) { 2691 log_err("failure in u_shapeArabic(LAMALEF shape_near)\n"); 2692 } 2693 2694 errorCode=U_ZERO_ERROR; 2695 2696 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2697 dest, UPRV_LENGTHOF(dest), 2698 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END| 2699 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2700 &errorCode); 2701 2702 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_at_end) || memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) { 2703 log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n"); 2704 } 2705 2706 errorCode=U_ZERO_ERROR; 2707 2708 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2709 dest, UPRV_LENGTHOF(dest), 2710 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING| 2711 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2712 &errorCode); 2713 2714 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_at_begin) || memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) { 2715 log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n"); 2716 } 2717 2718 errorCode=U_ZERO_ERROR; 2719 2720 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2721 dest, UPRV_LENGTHOF(dest), 2722 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK| 2723 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2724 &errorCode); 2725 2726 if(U_FAILURE(errorCode) || memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) { 2727 log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n"); 2728 } 2729 2730 /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */ 2731 2732 errorCode=U_ZERO_ERROR; 2733 2734 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2735 dest, UPRV_LENGTHOF(dest), 2736 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| 2737 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2738 &errorCode); 2739 2740 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) { 2741 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n"); 2742 } 2743 2744 errorCode=U_ZERO_ERROR; 2745 2746 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2747 dest, UPRV_LENGTHOF(dest), 2748 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END| 2749 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2750 &errorCode); 2751 2752 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_at_end) || memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) { 2753 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n"); 2754 } 2755 2756 errorCode=U_ZERO_ERROR; 2757 2758 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2759 dest, UPRV_LENGTHOF(dest), 2760 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING| 2761 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2762 &errorCode); 2763 2764 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_at_begin) || memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) { 2765 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n"); 2766 } 2767 2768 errorCode=U_ZERO_ERROR; 2769 2770 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2771 dest, UPRV_LENGTHOF(dest), 2772 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK| 2773 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2774 &errorCode); 2775 2776 if(U_FAILURE(errorCode) || memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) { 2777 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n"); 2778 } 2779 } 2780 2781 static void 2782 doTashkeelSpecialVLTRArabicShapingTest(void) { 2783 static const UChar 2784 source[]={ 2785 0x64A,0x628,0x631,0x639,0x20, 2786 0x64A,0x628,0x651,0x631,0x64E,0x639,0x20, 2787 0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20, 2788 0x628,0x670,0x631,0x670,0x639,0x20, 2789 0x628,0x653,0x631,0x653,0x639,0x20, 2790 0x628,0x654,0x631,0x654,0x639,0x20, 2791 0x628,0x655,0x631,0x655,0x639,0x20, 2792 }, shape_near[]={ 2793 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb, 2794 0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670, 2795 0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654, 2796 0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20 2797 }, shape_excepttashkeel_near[]={ 2798 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20, 2799 0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb, 2800 0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20, 2801 0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20 2802 }; 2803 2804 UChar dest[43]; 2805 UErrorCode errorCode; 2806 int32_t length; 2807 2808 errorCode=U_ZERO_ERROR; 2809 2810 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2811 dest, UPRV_LENGTHOF(dest), 2812 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| 2813 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2814 &errorCode); 2815 2816 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) { 2817 log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n"); 2818 } 2819 2820 errorCode=U_ZERO_ERROR; 2821 2822 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2823 dest, UPRV_LENGTHOF(dest), 2824 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| 2825 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2826 &errorCode); 2827 2828 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) { 2829 log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n"); 2830 } 2831 } 2832 2833 static void 2834 doLOGICALArabicDeShapingTest(void) { 2835 static const UChar 2836 source[]={ 2837 0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020, 2838 0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4, 2839 0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020 2840 }, unshape_near[]={ 2841 0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627, 2842 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631, 2843 0x629,0x20,0x20,0x20,0x20 2844 }, unshape_at_end[]={ 2845 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642, 2846 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627, 2847 0x644,0x62d,0x631,0x629,0x20 2848 }, unshape_at_begin[]={ 2849 0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20, 2850 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631, 2851 0x629,0x20,0x20,0x20,0x20 2852 }, unshape_grow_shrink[]={ 2853 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642, 2854 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627, 2855 0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20 2856 }; 2857 2858 UChar dest[36]; 2859 UErrorCode errorCode; 2860 int32_t length; 2861 2862 errorCode=U_ZERO_ERROR; 2863 2864 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2865 dest, UPRV_LENGTHOF(dest), 2866 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| 2867 U_SHAPE_TEXT_DIRECTION_LOGICAL, 2868 &errorCode); 2869 2870 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_near) || memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) { 2871 log_err("failure in u_shapeArabic(unshape_near)\n"); 2872 } 2873 2874 errorCode=U_ZERO_ERROR; 2875 2876 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2877 dest, UPRV_LENGTHOF(dest), 2878 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END| 2879 U_SHAPE_TEXT_DIRECTION_LOGICAL, 2880 &errorCode); 2881 2882 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_at_end) || memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) { 2883 log_err("failure in u_shapeArabic(unshape_at_end)\n"); 2884 } 2885 2886 errorCode=U_ZERO_ERROR; 2887 2888 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2889 dest, UPRV_LENGTHOF(dest), 2890 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING| 2891 U_SHAPE_TEXT_DIRECTION_LOGICAL, 2892 &errorCode); 2893 2894 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_at_begin) || memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) { 2895 log_err("failure in u_shapeArabic(unshape_at_begin)\n"); 2896 } 2897 2898 errorCode=U_ZERO_ERROR; 2899 2900 length=u_shapeArabic(source, UPRV_LENGTHOF(source), 2901 dest, UPRV_LENGTHOF(dest), 2902 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK| 2903 U_SHAPE_TEXT_DIRECTION_LOGICAL, 2904 &errorCode); 2905 2906 if(U_FAILURE(errorCode) || memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) { 2907 log_err("failure in u_shapeArabic(unshape_grow_shrink)\n"); 2908 } 2909 2910 } 2911 2912 static void 2913 doTailTest(void) { 2914 static const UChar src[] = { 0x0020, 0x0633, 0 }; 2915 static const UChar dst_old[] = { 0xFEB1, 0x200B,0 }; 2916 static const UChar dst_new[] = { 0xFEB1, 0xFE73,0 }; 2917 UChar dst[3] = { 0x0000, 0x0000,0 }; 2918 int32_t length; 2919 UErrorCode status; 2920 2921 log_verbose("SRC: U+%04X U+%04X\n", src[0],src[1]); 2922 2923 log_verbose("Trying old tail\n"); 2924 status = U_ZERO_ERROR; 2925 length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst), 2926 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR, &status); 2927 if(U_FAILURE(status)) { 2928 log_err("Fail: status %s\n", u_errorName(status)); 2929 } else if(length!=2) { 2930 log_err("Fail: len %d expected 3\n", length); 2931 } else if(u_strncmp(dst,dst_old,UPRV_LENGTHOF(dst))) { 2932 log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n", 2933 dst[0],dst[1],dst_old[0],dst_old[1]); 2934 } else { 2935 log_verbose("OK: U+%04X U+%04X len %d err %s\n", 2936 dst[0],dst[1],length,u_errorName(status)); 2937 } 2938 2939 2940 log_verbose("Trying new tail\n"); 2941 status = U_ZERO_ERROR; 2942 length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst), 2943 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR|U_SHAPE_TAIL_NEW_UNICODE, &status); 2944 if(U_FAILURE(status)) { 2945 log_err("Fail: status %s\n", u_errorName(status)); 2946 } else if(length!=2) { 2947 log_err("Fail: len %d expected 3\n", length); 2948 } else if(u_strncmp(dst,dst_new,UPRV_LENGTHOF(dst))) { 2949 log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n", 2950 dst[0],dst[1],dst_new[0],dst_new[1]); 2951 } else { 2952 log_verbose("OK: U+%04X U+%04X len %d err %s\n", 2953 dst[0],dst[1],length,u_errorName(status)); 2954 } 2955 } 2956 2957 static void 2958 doArabicShapingTestForBug5421(void) { 2959 static const UChar 2960 persian_letters_source[]={ 2961 0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020 2962 }, persian_letters[]={ 2963 0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020 2964 }, tashkeel_aggregation_source[]={ 2965 0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020, 2966 0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020 2967 }, tashkeel_aggregation[]={ 2968 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 2969 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020 2970 }, untouched_presentation_source[]={ 2971 0x0020 ,0x0627, 0xfe90,0x0020 2972 }, untouched_presentation[]={ 2973 0x0020,0xfe8D, 0xfe90,0x0020 2974 }, untouched_presentation_r_source[]={ 2975 0x0020 ,0xfe90, 0x0627, 0x0020 2976 }, untouched_presentation_r[]={ 2977 0x0020, 0xfe90,0xfe8D,0x0020 2978 }; 2979 2980 UChar dest[38]; 2981 UErrorCode errorCode; 2982 int32_t length; 2983 2984 errorCode=U_ZERO_ERROR; 2985 2986 length=u_shapeArabic(persian_letters_source, UPRV_LENGTHOF(persian_letters_source), 2987 dest, UPRV_LENGTHOF(dest), 2988 U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 2989 &errorCode); 2990 2991 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(persian_letters) || memcmp(dest, persian_letters, length*U_SIZEOF_UCHAR)!=0) { 2992 log_err("failure in u_shapeArabic(persian_letters)\n"); 2993 } 2994 2995 errorCode=U_ZERO_ERROR; 2996 2997 length=u_shapeArabic(tashkeel_aggregation_source, UPRV_LENGTHOF(tashkeel_aggregation_source), 2998 dest, UPRV_LENGTHOF(dest), 2999 U_SHAPE_AGGREGATE_TASHKEEL|U_SHAPE_PRESERVE_PRESENTATION| 3000 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 3001 &errorCode); 3002 3003 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(tashkeel_aggregation) || memcmp(dest, tashkeel_aggregation, length*U_SIZEOF_UCHAR)!=0) { 3004 log_err("failure in u_shapeArabic(tashkeel_aggregation)\n"); 3005 } 3006 3007 errorCode=U_ZERO_ERROR; 3008 3009 length=u_shapeArabic(untouched_presentation_source, UPRV_LENGTHOF(untouched_presentation_source), 3010 dest, UPRV_LENGTHOF(dest), 3011 U_SHAPE_PRESERVE_PRESENTATION| 3012 U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, 3013 &errorCode); 3014 3015 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(untouched_presentation) || memcmp(dest, untouched_presentation, length*U_SIZEOF_UCHAR)!=0) { 3016 log_err("failure in u_shapeArabic(untouched_presentation)\n"); 3017 } 3018 3019 errorCode=U_ZERO_ERROR; 3020 3021 length=u_shapeArabic(untouched_presentation_r_source, UPRV_LENGTHOF(untouched_presentation_r_source), 3022 dest, UPRV_LENGTHOF(dest), 3023 U_SHAPE_PRESERVE_PRESENTATION| 3024 U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_LOGICAL, 3025 &errorCode); 3026 3027 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(untouched_presentation_r) || memcmp(dest, untouched_presentation_r, length*U_SIZEOF_UCHAR)!=0) { 3028 log_err("failure in u_shapeArabic(untouched_presentation_r)\n"); 3029 } 3030 } 3031 3032 static void 3033 doArabicShapingTestForBug8703(void) { 3034 static const UChar 3035 letters_source1[]={ 3036 0x0634,0x0651,0x0645,0x0652,0x0633 3037 }, letters_source2[]={ 3038 0x0634,0x0651,0x0645,0x0652,0x0633 3039 }, letters_source3[]={ 3040 0x0634,0x0651,0x0645,0x0652,0x0633 3041 }, letters_source4[]={ 3042 0x0634,0x0651,0x0645,0x0652,0x0633 3043 }, letters_source5[]={ 3044 0x0633,0x0652,0x0645,0x0651,0x0634 3045 }, letters_source6[]={ 3046 0x0633,0x0652,0x0645,0x0651,0x0634 3047 }, letters_source7[]={ 3048 0x0633,0x0652,0x0645,0x0651,0x0634 3049 }, letters_source8[]={ 3050 0x0633,0x0652,0x0645,0x0651,0x0634 3051 }, letters_dest1[]={ 3052 0x0020,0xFEB7,0xFE7D,0xFEE4,0xFEB2 3053 }, letters_dest2[]={ 3054 0xFEB7,0xFE7D,0xFEE4,0xFEB2,0x0020 3055 }, letters_dest3[]={ 3056 0xFEB7,0xFE7D,0xFEE4,0xFEB2 3057 }, letters_dest4[]={ 3058 0xFEB7,0xFE7D,0xFEE4,0x0640,0xFEB2 3059 }, letters_dest5[]={ 3060 0x0020,0xFEB2,0xFEE4,0xFE7D,0xFEB7 3061 }, letters_dest6[]={ 3062 0xFEB2,0xFEE4,0xFE7D,0xFEB7,0x0020 3063 }, letters_dest7[]={ 3064 0xFEB2,0xFEE4,0xFE7D,0xFEB7 3065 }, letters_dest8[]={ 3066 0xFEB2,0x0640,0xFEE4,0xFE7D,0xFEB7 3067 }; 3068 3069 UChar dest[20]; 3070 UErrorCode errorCode; 3071 int32_t length; 3072 3073 errorCode=U_ZERO_ERROR; 3074 3075 length=u_shapeArabic(letters_source1, UPRV_LENGTHOF(letters_source1), 3076 dest, UPRV_LENGTHOF(dest), 3077 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE, 3078 &errorCode); 3079 3080 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) { 3081 log_err("failure in u_shapeArabic(letters_source1)\n"); 3082 } 3083 3084 errorCode=U_ZERO_ERROR; 3085 3086 length=u_shapeArabic(letters_source2, UPRV_LENGTHOF(letters_source2), 3087 dest, UPRV_LENGTHOF(dest), 3088 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE, 3089 &errorCode); 3090 3091 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) { 3092 log_err("failure in u_shapeArabic(letters_source2)\n"); 3093 } 3094 3095 errorCode=U_ZERO_ERROR; 3096 3097 length=u_shapeArabic(letters_source3, UPRV_LENGTHOF(letters_source3), 3098 dest, UPRV_LENGTHOF(dest), 3099 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE, 3100 &errorCode); 3101 3102 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) { 3103 log_err("failure in u_shapeArabic(letters_source3)\n"); 3104 } 3105 3106 errorCode=U_ZERO_ERROR; 3107 3108 length=u_shapeArabic(letters_source4, UPRV_LENGTHOF(letters_source4), 3109 dest, UPRV_LENGTHOF(dest), 3110 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE, 3111 &errorCode); 3112 3113 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) { 3114 log_err("failure in u_shapeArabic(letters_source4)\n"); 3115 } 3116 3117 errorCode=U_ZERO_ERROR; 3118 3119 length=u_shapeArabic(letters_source5, UPRV_LENGTHOF(letters_source5), 3120 dest, UPRV_LENGTHOF(dest), 3121 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE, 3122 &errorCode); 3123 3124 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) { 3125 log_err("failure in u_shapeArabic(letters_source5)\n"); 3126 } 3127 3128 errorCode=U_ZERO_ERROR; 3129 3130 length=u_shapeArabic(letters_source6, UPRV_LENGTHOF(letters_source6), 3131 dest, UPRV_LENGTHOF(dest), 3132 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE, 3133 &errorCode); 3134 3135 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) { 3136 log_err("failure in u_shapeArabic(letters_source6)\n"); 3137 } 3138 3139 errorCode=U_ZERO_ERROR; 3140 3141 length=u_shapeArabic(letters_source7, UPRV_LENGTHOF(letters_source7), 3142 dest, UPRV_LENGTHOF(dest), 3143 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE, 3144 &errorCode); 3145 3146 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest7) || memcmp(dest, letters_dest7, length*U_SIZEOF_UCHAR)!=0) { 3147 log_err("failure in u_shapeArabic(letters_source7)\n"); 3148 } 3149 3150 errorCode=U_ZERO_ERROR; 3151 3152 length=u_shapeArabic(letters_source8, UPRV_LENGTHOF(letters_source8), 3153 dest, UPRV_LENGTHOF(dest), 3154 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE, 3155 &errorCode); 3156 3157 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest8) || memcmp(dest, letters_dest8, length*U_SIZEOF_UCHAR)!=0) { 3158 log_err("failure in u_shapeArabic(letters_source8)\n"); 3159 } 3160 } 3161 3162 static void 3163 doArabicShapingTestForBug9024(void) { 3164 static const UChar 3165 letters_source1[]={ /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */ 3166 0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20, 3167 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20, 3168 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20, 3169 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20, 3170 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20, 3171 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20, 3172 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20, 3173 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B 3174 }, letters_source2[]={/* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */ 3175 0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20, 3176 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20, 3177 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20, 3178 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20, 3179 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20, 3180 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20, 3181 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20, 3182 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B 3183 }, letters_source3[]={/* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */ 3184 0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20, 3185 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20, 3186 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20, 3187 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20, 3188 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20, 3189 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20, 3190 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20, 3191 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB 3192 }, letters_source4[]={/* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */ 3193 0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20, 3194 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20, 3195 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20, 3196 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20, 3197 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20, 3198 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20, 3199 0xD83B, 0xDE39, 0xD83B, 0xDE3B 3200 }, letters_source5[]={/* Arabic mathematical Symbols - Tailed Symbols */ 3201 0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20, 3202 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20, 3203 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20, 3204 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F 3205 }, letters_source6[]={/* Arabic mathematical Symbols - Stretched Symbols with 06 range */ 3206 0xD83B, 0xDE21, 0x0633, 0xD83B, 0xDE62, 0x0647 3207 }, letters_dest1[]={ 3208 0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20, 3209 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20, 3210 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20, 3211 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20, 3212 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20, 3213 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20, 3214 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20, 3215 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B 3216 }, letters_dest2[]={ 3217 0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20, 3218 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20, 3219 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20, 3220 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20, 3221 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20, 3222 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20, 3223 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20, 3224 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B 3225 }, letters_dest3[]={ 3226 0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20, 3227 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20, 3228 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20, 3229 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20, 3230 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20, 3231 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20, 3232 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20, 3233 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB 3234 }, letters_dest4[]={ 3235 0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20, 3236 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20, 3237 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20, 3238 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20, 3239 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20, 3240 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20, 3241 0xD83B, 0xDE39, 0xD83B, 0xDE3B 3242 }, letters_dest5[]={ 3243 0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20, 3244 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20, 3245 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20, 3246 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F 3247 }, letters_dest6[]={ 3248 0xD83B, 0xDE21, 0xFEB1, 0xD83B, 0xDE62, 0xFEE9 3249 }; 3250 3251 UChar dest[MAXLEN]; 3252 UErrorCode errorCode; 3253 int32_t length; 3254 3255 errorCode=U_ZERO_ERROR; 3256 3257 length=u_shapeArabic(letters_source1, UPRV_LENGTHOF(letters_source1), 3258 dest, UPRV_LENGTHOF(dest), 3259 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE, 3260 &errorCode); 3261 3262 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) { 3263 log_err("failure in u_shapeArabic(letters_source1)\n"); 3264 } 3265 3266 errorCode=U_ZERO_ERROR; 3267 3268 length=u_shapeArabic(letters_source2, UPRV_LENGTHOF(letters_source2), 3269 dest, UPRV_LENGTHOF(dest), 3270 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE, 3271 &errorCode); 3272 3273 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) { 3274 log_err("failure in u_shapeArabic(letters_source2)\n"); 3275 } 3276 3277 errorCode=U_ZERO_ERROR; 3278 3279 length=u_shapeArabic(letters_source3, UPRV_LENGTHOF(letters_source3), 3280 dest, UPRV_LENGTHOF(dest), 3281 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE, 3282 &errorCode); 3283 3284 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) { 3285 log_err("failure in u_shapeArabic(letters_source3)\n"); 3286 } 3287 3288 errorCode=U_ZERO_ERROR; 3289 3290 length=u_shapeArabic(letters_source4, UPRV_LENGTHOF(letters_source4), 3291 dest, UPRV_LENGTHOF(dest), 3292 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE, 3293 &errorCode); 3294 3295 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) { 3296 log_err("failure in u_shapeArabic(letters_source4)\n"); 3297 } 3298 3299 errorCode=U_ZERO_ERROR; 3300 3301 length=u_shapeArabic(letters_source5, UPRV_LENGTHOF(letters_source5), 3302 dest, UPRV_LENGTHOF(dest), 3303 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE, 3304 &errorCode); 3305 3306 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) { 3307 log_err("failure in u_shapeArabic(letters_source5)\n"); 3308 } 3309 3310 errorCode=U_ZERO_ERROR; 3311 3312 length=u_shapeArabic(letters_source6, UPRV_LENGTHOF(letters_source6), 3313 dest, UPRV_LENGTHOF(dest), 3314 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE, 3315 &errorCode); 3316 3317 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) { 3318 log_err("failure in u_shapeArabic(letters_source6)\n"); 3319 } 3320 3321 } 3322 3323 static void _testPresentationForms(const UChar* in) { 3324 enum Forms { GENERIC, ISOLATED, FINAL, INITIAL, MEDIAL }; 3325 /* This character is used to check whether the in-character is rewritten correctly 3326 and whether the surrounding characters are shaped correctly as well. */ 3327 UChar otherChar[] = {0x0628, 0xfe8f, 0xfe90, 0xfe91, 0xfe92}; 3328 UChar src[3]; 3329 UChar dst[3]; 3330 UErrorCode errorCode; 3331 int32_t length; 3332 3333 /* Testing isolated shaping */ 3334 src[0] = in[GENERIC]; 3335 errorCode=U_ZERO_ERROR; 3336 length=u_shapeArabic(src, 1, 3337 dst, 1, 3338 U_SHAPE_LETTERS_SHAPE, 3339 &errorCode); 3340 if(U_FAILURE(errorCode) || length!=1 || dst[0] != in[ISOLATED]) { 3341 log_err("failure in u_shapeArabic(_testAllForms: shaping isolated): %x\n", in[GENERIC]); 3342 } 3343 errorCode=U_ZERO_ERROR; 3344 length=u_shapeArabic(dst, 1, 3345 src, 1, 3346 U_SHAPE_LETTERS_UNSHAPE, 3347 &errorCode); 3348 if(U_FAILURE(errorCode) || length!=1 || src[0] != in[GENERIC]) { 3349 log_err("failure in u_shapeArabic(_testAllForms: unshaping isolated): %x\n", in[GENERIC]); 3350 } 3351 3352 /* Testing final shaping */ 3353 src[0] = otherChar[GENERIC]; 3354 src[1] = in[GENERIC]; 3355 if (in[FINAL] != 0) { 3356 errorCode=U_ZERO_ERROR; 3357 length=u_shapeArabic(src, 2, 3358 dst, 2, 3359 U_SHAPE_LETTERS_SHAPE, 3360 &errorCode); 3361 if(U_FAILURE(errorCode) || length!=2 || dst[0] != otherChar[INITIAL] || dst[1] != in[FINAL]) { 3362 log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in[GENERIC]); 3363 } 3364 errorCode=U_ZERO_ERROR; 3365 length=u_shapeArabic(dst, 2, 3366 src, 2, 3367 U_SHAPE_LETTERS_UNSHAPE, 3368 &errorCode); 3369 if(U_FAILURE(errorCode) || length!=2 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC]) { 3370 log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in[GENERIC]); 3371 } 3372 } else { 3373 errorCode=U_ZERO_ERROR; 3374 length=u_shapeArabic(src, 2, 3375 dst, 2, 3376 U_SHAPE_LETTERS_SHAPE, 3377 &errorCode); 3378 if(U_FAILURE(errorCode) || length!=2 || dst[0] != otherChar[ISOLATED] || dst[1] != in[ISOLATED]) { 3379 log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in[GENERIC]); 3380 } 3381 errorCode=U_ZERO_ERROR; 3382 length=u_shapeArabic(dst, 2, 3383 src, 2, 3384 U_SHAPE_LETTERS_UNSHAPE, 3385 &errorCode); 3386 if(U_FAILURE(errorCode) || length!=2 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC]) { 3387 log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in[GENERIC]); 3388 } 3389 } 3390 3391 /* Testing initial shaping */ 3392 src[0] = in[GENERIC]; 3393 src[1] = otherChar[GENERIC]; 3394 if (in[INITIAL] != 0) { 3395 /* Testing characters that have an initial form */ 3396 errorCode=U_ZERO_ERROR; 3397 length=u_shapeArabic(src, 2, 3398 dst, 2, 3399 U_SHAPE_LETTERS_SHAPE, 3400 &errorCode); 3401 if(U_FAILURE(errorCode) || length!=2 || dst[0] != in[INITIAL] || dst[1] != otherChar[FINAL]) { 3402 log_err("failure in u_shapeArabic(_testAllForms: shaping initial): %x\n", in[GENERIC]); 3403 } 3404 errorCode=U_ZERO_ERROR; 3405 length=u_shapeArabic(dst, 2, 3406 src, 2, 3407 U_SHAPE_LETTERS_UNSHAPE, 3408 &errorCode); 3409 if(U_FAILURE(errorCode) || length!=2 || src[0] != in[GENERIC] || src[1] != otherChar[GENERIC]) { 3410 log_err("failure in u_shapeArabic(_testAllForms: unshaping initial): %x\n", in[GENERIC]); 3411 } 3412 } else { 3413 /* Testing characters that do not have an initial form */ 3414 errorCode=U_ZERO_ERROR; 3415 length=u_shapeArabic(src, 2, 3416 dst, 2, 3417 U_SHAPE_LETTERS_SHAPE, 3418 &errorCode); 3419 if(U_FAILURE(errorCode) || length!=2 || dst[0] != in[ISOLATED] || dst[1] != otherChar[ISOLATED]) { 3420 log_err("failure in u_shapeArabic(_testTwoForms: shaping initial): %x\n", in[GENERIC]); 3421 } 3422 errorCode=U_ZERO_ERROR; 3423 length=u_shapeArabic(dst, 2, 3424 src, 2, 3425 U_SHAPE_LETTERS_UNSHAPE, 3426 &errorCode); 3427 if(U_FAILURE(errorCode) || length!=2 || src[0] != in[GENERIC] || src[1] != otherChar[GENERIC]) { 3428 log_err("failure in u_shapeArabic(_testTwoForms: unshaping initial): %x\n", in[GENERIC]); 3429 } 3430 } 3431 3432 /* Testing medial shaping */ 3433 src[0] = otherChar[0]; 3434 src[1] = in[GENERIC]; 3435 src[2] = otherChar[0]; 3436 errorCode=U_ZERO_ERROR; 3437 if (in[MEDIAL] != 0) { 3438 /* Testing characters that have an medial form */ 3439 length=u_shapeArabic(src, 3, 3440 dst, 3, 3441 U_SHAPE_LETTERS_SHAPE, 3442 &errorCode); 3443 if(U_FAILURE(errorCode) || length!=3 || dst[0] != otherChar[INITIAL] || dst[1] != in[MEDIAL] || dst[2] != otherChar[FINAL]) { 3444 log_err("failure in u_shapeArabic(_testAllForms: shaping medial): %x\n", in[GENERIC]); 3445 } 3446 errorCode=U_ZERO_ERROR; 3447 length=u_shapeArabic(dst, 3, 3448 src, 3, 3449 U_SHAPE_LETTERS_UNSHAPE, 3450 &errorCode); 3451 if(U_FAILURE(errorCode) || length!=3 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC] || src[2] != otherChar[GENERIC]) { 3452 log_err("failure in u_shapeArabic(_testAllForms: unshaping medial): %x\n", in[GENERIC]); 3453 } 3454 } else { 3455 /* Testing characters that do not have an medial form */ 3456 errorCode=U_ZERO_ERROR; 3457 length=u_shapeArabic(src, 3, 3458 dst, 3, 3459 U_SHAPE_LETTERS_SHAPE, 3460 &errorCode); 3461 if(U_FAILURE(errorCode) || length!=3 || dst[0] != otherChar[INITIAL] || dst[1] != in[FINAL] || dst[2] != otherChar[ISOLATED]) { 3462 log_err("failure in u_shapeArabic(_testTwoForms: shaping medial): %x\n", in[GENERIC]); 3463 } 3464 errorCode=U_ZERO_ERROR; 3465 length=u_shapeArabic(dst, 3, 3466 src, 3, 3467 U_SHAPE_LETTERS_UNSHAPE, 3468 &errorCode); 3469 if(U_FAILURE(errorCode) || length!=3 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC] || src[2] != otherChar[GENERIC]) { 3470 log_err("failure in u_shapeArabic(_testTwoForms: unshaping medial): %x\n", in[GENERIC]); 3471 } 3472 } 3473 } 3474 3475 static void 3476 doArabicShapingTestForNewCharacters(void) { 3477 static const UChar letterForms[][5]={ 3478 { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69 }, /* TTEH */ 3479 { 0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61 }, /* TTEHEH */ 3480 { 0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55 }, /* BEEH */ 3481 { 0x0688, 0xFB88, 0xFB89, 0, 0 }, /* DDAL */ 3482 { 0x068C, 0xFB84, 0xFB85, 0, 0 }, /* DAHAL */ 3483 { 0x068D, 0xFB82, 0xFB83, 0, 0 }, /* DDAHAL */ 3484 { 0x068E, 0xFB86, 0xFB87, 0, 0 }, /* DUL */ 3485 { 0x0691, 0xFB8C, 0xFB8D, 0, 0 }, /* RREH */ 3486 { 0x06BA, 0xFB9E, 0xFB9F, 0, 0 }, /* NOON GHUNNA */ 3487 { 0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3 }, /* RNOON */ 3488 { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD }, /* HEH DOACHASHMEE */ 3489 { 0x06C0, 0xFBA4, 0xFBA5, 0, 0 }, /* HEH WITH YEH ABOVE */ 3490 { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9 }, /* HEH GOAL */ 3491 { 0x06C5, 0xFBE0, 0xFBE1, 0, 0 }, /* KIRGIHIZ OE */ 3492 { 0x06C6, 0xFBD9, 0xFBDA, 0, 0 }, /* OE */ 3493 { 0x06C7, 0xFBD7, 0xFBD8, 0, 0 }, /* U */ 3494 { 0x06C8, 0xFBDB, 0xFBDC, 0, 0 }, /* YU */ 3495 { 0x06C9, 0xFBE2, 0xFBE3, 0, 0 }, /* KIRGIZ YU */ 3496 { 0x06CB, 0xFBDE, 0xFBDF, 0, 0}, /* VE */ 3497 { 0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7 }, /* E */ 3498 { 0x06D2, 0xFBAE, 0xFBAF, 0, 0 }, /* YEH BARREE */ 3499 { 0x06D3, 0xFBB0, 0xFBB1, 0, 0 }, /* YEH BARREE WITH HAMZA ABOVE */ 3500 { 0x0622, 0xFE81, 0xFE82, 0, 0, }, /* ALEF WITH MADDA ABOVE */ 3501 { 0x0623, 0xFE83, 0xFE84, 0, 0, }, /* ALEF WITH HAMZA ABOVE */ 3502 { 0x0624, 0xFE85, 0xFE86, 0, 0, }, /* WAW WITH HAMZA ABOVE */ 3503 { 0x0625, 0xFE87, 0xFE88, 0, 0, }, /* ALEF WITH HAMZA BELOW */ 3504 { 0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, }, /* YEH WITH HAMZA ABOVE */ 3505 { 0x0627, 0xFE8D, 0xFE8E, 0, 0, }, /* ALEF */ 3506 { 0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, }, /* BEH */ 3507 { 0x0629, 0xFE93, 0xFE94, 0, 0, }, /* TEH MARBUTA */ 3508 { 0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98, }, /* TEH */ 3509 { 0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, }, /* THEH */ 3510 { 0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0, }, /* JEEM */ 3511 { 0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, }, /* HAH */ 3512 { 0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8, }, /* KHAH */ 3513 { 0x062F, 0xFEA9, 0xFEAA, 0, 0, }, /* DAL */ 3514 { 0x0630, 0xFEAB, 0xFEAC, 0, 0, }, /* THAL */ 3515 { 0x0631, 0xFEAD, 0xFEAE, 0, 0, }, /* REH */ 3516 { 0x0632, 0xFEAF, 0xFEB0, 0, 0, }, /* ZAIN */ 3517 { 0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, }, /* SEEN */ 3518 { 0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, }, /* SHEEN */ 3519 { 0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, }, /* SAD */ 3520 { 0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, }, /* DAD */ 3521 { 0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, }, /* TAH */ 3522 { 0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, }, /* ZAH */ 3523 { 0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, }, /* AIN */ 3524 { 0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0, }, /* GHAIN */ 3525 { 0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4, }, /* FEH */ 3526 { 0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8, }, /* QAF */ 3527 { 0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, }, /* KAF */ 3528 { 0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0, }, /* LAM */ 3529 { 0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, }, /* MEEM */ 3530 { 0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8, }, /* NOON */ 3531 { 0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, }, /* HEH */ 3532 { 0x0648, 0xFEED, 0xFEEE, 0, 0, }, /* WAW */ 3533 { 0x0649, 0xFEEF, 0xFEF0, 0, 0, }, /* ALEF MAKSURA */ 3534 { 0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, }, /* YEH */ 3535 { 0x064E, 0xFE76, 0, 0, 0xFE77, }, /* FATHA */ 3536 { 0x064F, 0xFE78, 0, 0, 0xFE79, }, /* DAMMA */ 3537 { 0x0650, 0xFE7A, 0, 0, 0xFE7B, }, /* KASRA */ 3538 { 0x0651, 0xFE7C, 0, 0, 0xFE7D, }, /* SHADDA */ 3539 { 0x0652, 0xFE7E, 0, 0, 0xFE7F, }, /* SUKUN */ 3540 { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69, }, /* TTEH */ 3541 { 0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59, }, /* PEH */ 3542 { 0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, }, /* TCHEH */ 3543 { 0x0688, 0xFB88, 0xFB89, 0, 0, }, /* DDAL */ 3544 { 0x0691, 0xFB8C, 0xFB8D, 0, 0, }, /* RREH */ 3545 { 0x0698, 0xFB8A, 0xFB8B, 0, 0, }, /* JEH */ 3546 { 0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, }, /* KEHEH */ 3547 { 0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95, }, /* GAF */ 3548 { 0x06BA, 0xFB9E, 0xFB9F, 0, 0, }, /* NOON GHUNNA */ 3549 { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, }, /* HEH DOACHASHMEE */ 3550 { 0x06C0, 0xFBA4, 0xFBA5, 0, 0, }, /* HEH WITH YEH ABOVE */ 3551 { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, }, /* HEH GOAL */ 3552 { 0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, }, /* FARSI YEH */ 3553 { 0x06D2, 0xFBAE, 0xFBAF, 0, 0, }, /* YEH BARREE */ 3554 { 0x06D3, 0xFBB0, 0xFBB1, 0, 0, }}; /* YEH BARREE WITH HAMZA ABOVE */ 3555 int32_t i; 3556 for (i = 0; i < UPRV_LENGTHOF(letterForms); ++i) { 3557 _testPresentationForms(letterForms[i]); 3558 } 3559 } 3560 3561 /* helpers ------------------------------------------------------------------ */ 3562 3563 static void initCharFromDirProps(void) { 3564 static const UVersionInfo ucd401={ 4, 0, 1, 0 }; 3565 static UVersionInfo ucdVersion={ 0, 0, 0, 0 }; 3566 3567 /* lazy initialization */ 3568 if(ucdVersion[0]>0) { 3569 return; 3570 } 3571 3572 u_getUnicodeVersion(ucdVersion); 3573 if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) { 3574 /* Unicode 4.0.1 changes bidi classes for +-/ */ 3575 charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */ 3576 } 3577 } 3578 3579 /* return a string with characters according to the desired directional properties */ 3580 static UChar * 3581 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer) { 3582 int32_t i; 3583 3584 initCharFromDirProps(); 3585 3586 /* this part would have to be modified for UTF-x */ 3587 for(i=0; i<length; ++i) { 3588 buffer[i]=charFromDirProp[dirProps[i]]; 3589 } 3590 buffer[length]=0; 3591 return buffer; 3592 } 3593 3594 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) { 3595 int32_t i; 3596 3597 log_verbose("{ "); 3598 for(i=0; i<length; ++i) { 3599 if(levels!=NULL) { 3600 log_verbose("%4x.%u ", s[i], levels[i]); 3601 } else { 3602 log_verbose("%4x ", s[i]); 3603 } 3604 } 3605 log_verbose(" }"); 3606 } 3607 3608 /* new BIDI API */ 3609 3610 /* Reordering Mode BiDi --------------------------------------------------------- */ 3611 3612 static const UBiDiLevel paraLevels[] = { UBIDI_LTR, UBIDI_RTL }; 3613 3614 static UBool 3615 assertSuccessful(const char* message, UErrorCode* rc) { 3616 if (rc != NULL && U_FAILURE(*rc)) { 3617 log_err("%s() failed with error %s.\n", message, myErrorName(*rc)); 3618 return FALSE; 3619 } 3620 return TRUE; 3621 } 3622 3623 static UBool 3624 assertStringsEqual(const char* expected, const char* actual, const char* src, 3625 const char* mode, const char* option, UBiDi* pBiDi) { 3626 if (uprv_strcmp(expected, actual)) { 3627 char formatChars[MAXLEN]; 3628 log_err("\nActual and expected output mismatch.\n" 3629 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n", 3630 "Input:", src, 3631 "Actual output:", actual, 3632 "Expected output:", expected, 3633 "Levels:", formatLevels(pBiDi, formatChars), 3634 "Reordering mode:", ubidi_getReorderingMode(pBiDi), mode, 3635 "Paragraph level:", ubidi_getParaLevel(pBiDi), 3636 "Reordering option:", ubidi_getReorderingOptions(pBiDi), option); 3637 return FALSE; 3638 } 3639 return TRUE; 3640 } 3641 3642 static UBiDi* 3643 getBiDiObject(void) { 3644 UBiDi* pBiDi = ubidi_open(); 3645 if (pBiDi == NULL) { 3646 log_err("Unable to allocate a UBiDi object. Tests are skipped.\n"); 3647 } 3648 return pBiDi; 3649 } 3650 3651 #define MAKE_ITEMS(val) val, #val 3652 3653 static const struct { 3654 UBiDiReorderingMode value; 3655 const char* description; 3656 } 3657 modes[] = { 3658 { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) }, 3659 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT) }, 3660 { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL) }, 3661 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) }, 3662 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L) } 3663 }; 3664 static const struct { 3665 uint32_t value; 3666 const char* description; 3667 } 3668 options[] = { 3669 { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS) }, 3670 { MAKE_ITEMS(0) } 3671 }; 3672 3673 #define TC_COUNT UPRV_LENGTHOF(textIn) 3674 #define MODES_COUNT UPRV_LENGTHOF(modes) 3675 #define OPTIONS_COUNT UPRV_LENGTHOF(options) 3676 #define LEVELS_COUNT UPRV_LENGTHOF(paraLevels) 3677 3678 static const char* const textIn[] = { 3679 /* (0) 123 */ 3680 "123", 3681 /* (1) .123->4.5 */ 3682 ".123->4.5", 3683 /* (2) 678 */ 3684 "678", 3685 /* (3) .678->8.9 */ 3686 ".678->8.9", 3687 /* (4) JIH1.2,3MLK */ 3688 "JIH1.2,3MLK", 3689 /* (5) FE.>12-> */ 3690 "FE.>12->", 3691 /* (6) JIH.>12->a */ 3692 "JIH.>12->a", 3693 /* (7) CBA.>67->89=a */ 3694 "CBA.>67->89=a", 3695 /* (8) CBA.123->xyz */ 3696 "CBA.123->xyz", 3697 /* (9) .>12->xyz */ 3698 ".>12->xyz", 3699 /* (10) a.>67->xyz */ 3700 "a.>67->xyz", 3701 /* (11) 123JIH */ 3702 "123JIH", 3703 /* (12) 123 JIH */ 3704 "123 JIH" 3705 }; 3706 3707 static const char* const textOut[] = { 3708 /* TC 0: 123 */ 3709 "123", /* (0) */ 3710 /* TC 1: .123->4.5 */ 3711 ".123->4.5", /* (1) */ 3712 "4.5<-123.", /* (2) */ 3713 /* TC 2: 678 */ 3714 "678", /* (3) */ 3715 /* TC 3: .678->8.9 */ 3716 ".8.9<-678", /* (4) */ 3717 "8.9<-678.", /* (5) */ 3718 ".678->8.9", /* (6) */ 3719 /* TC 4: MLK1.2,3JIH */ 3720 "KLM1.2,3HIJ", /* (7) */ 3721 /* TC 5: FE.>12-> */ 3722 "12<.EF->", /* (8) */ 3723 "<-12<.EF", /* (9) */ 3724 "EF.>@12->", /* (10) */ 3725 /* TC 6: JIH.>12->a */ 3726 "12<.HIJ->a", /* (11) */ 3727 "a<-12<.HIJ", /* (12) */ 3728 "HIJ.>@12->a", /* (13) */ 3729 "a&<-12<.HIJ", /* (14) */ 3730 /* TC 7: CBA.>67->89=a */ 3731 "ABC.>@67->89=a", /* (15) */ 3732 "a=89<-67<.ABC", /* (16) */ 3733 "a&=89<-67<.ABC", /* (17) */ 3734 "89<-67<.ABC=a", /* (18) */ 3735 /* TC 8: CBA.123->xyz */ 3736 "123.ABC->xyz", /* (19) */ 3737 "xyz<-123.ABC", /* (20) */ 3738 "ABC.@123->xyz", /* (21) */ 3739 "xyz&<-123.ABC", /* (22) */ 3740 /* TC 9: .>12->xyz */ 3741 ".>12->xyz", /* (23) */ 3742 "xyz<-12<.", /* (24) */ 3743 "xyz&<-12<.", /* (25) */ 3744 /* TC 10: a.>67->xyz */ 3745 "a.>67->xyz", /* (26) */ 3746 "a.>@67@->xyz", /* (27) */ 3747 "xyz<-67<.a", /* (28) */ 3748 /* TC 11: 123JIH */ 3749 "123HIJ", /* (29) */ 3750 "HIJ123", /* (30) */ 3751 /* TC 12: 123 JIH */ 3752 "123 HIJ", /* (31) */ 3753 "HIJ 123", /* (32) */ 3754 }; 3755 3756 #define NO UBIDI_MAP_NOWHERE 3757 #define MAX_MAP_LENGTH 20 3758 3759 static const int32_t forwardMap[][MAX_MAP_LENGTH] = { 3760 /* TC 0: 123 */ 3761 { 0, 1, 2 }, /* (0) */ 3762 /* TC 1: .123->4.5 */ 3763 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */ 3764 { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (2) */ 3765 /* TC 2: 678 */ 3766 { 0, 1, 2 }, /* (3) */ 3767 /* TC 3: .678->8.9 */ 3768 { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */ 3769 { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (5) */ 3770 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */ 3771 /* TC 4: MLK1.2,3JIH */ 3772 { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */ 3773 /* TC 5: FE.>12-> */ 3774 { 5, 4, 3, 2, 0, 1, 6, 7 }, /* (8) */ 3775 { 7, 6, 5, 4, 2, 3, 1, 0 }, /* (9) */ 3776 { 1, 0, 2, 3, 5, 6, 7, 8 }, /* (10) */ 3777 /* TC 6: JIH.>12->a */ 3778 { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 }, /* (11) */ 3779 { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 }, /* (12) */ 3780 { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 }, /* (13) */ 3781 { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 }, /* (14) */ 3782 /* TC 7: CBA.>67->89=a */ 3783 { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 }, /* (15) */ 3784 { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 }, /* (16) */ 3785 { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 }, /* (17) */ 3786 { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 }, /* (18) */ 3787 /* TC 8: CBA.123->xyz */ 3788 { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 }, /* (19) */ 3789 { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (20) */ 3790 { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (21) */ 3791 { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 }, /* (22) */ 3792 /* TC 9: .>12->xyz */ 3793 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */ 3794 { 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (24) */ 3795 { 9, 8, 6, 7, 5, 4, 0, 1, 2 }, /* (25) */ 3796 /* TC 10: a.>67->xyz */ 3797 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */ 3798 { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 }, /* (27) */ 3799 { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (28) */ 3800 /* TC 11: 123JIH */ 3801 { 0, 1, 2, 5, 4, 3 }, /* (29) */ 3802 { 3, 4, 5, 2, 1, 0 }, /* (30) */ 3803 /* TC 12: 123 JIH */ 3804 { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */ 3805 { 4, 5, 6, 3, 2, 1, 0 }, /* (32) */ 3806 }; 3807 3808 static const int32_t inverseMap[][MAX_MAP_LENGTH] = { 3809 /* TC 0: 123 */ 3810 { 0, 1, 2 }, /* (0) */ 3811 /* TC 1: .123->4.5 */ 3812 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */ 3813 { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (2) */ 3814 /* TC 2: 678 */ 3815 { 0, 1, 2 }, /* (3) */ 3816 /* TC 3: .678->8.9 */ 3817 { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */ 3818 { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (5) */ 3819 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */ 3820 /* TC 4: MLK1.2,3JIH */ 3821 { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */ 3822 /* TC 5: FE.>12-> */ 3823 { 4, 5, 3, 2, 1, 0, 6, 7 }, /* (8) */ 3824 { 7, 6, 4, 5, 3, 2, 1, 0 }, /* (9) */ 3825 { 1, 0, 2, 3, NO, 4, 5, 6, 7 }, /* (10) */ 3826 /* TC 6: JIH.>12->a */ 3827 { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 }, /* (11) */ 3828 { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (12) */ 3829 { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (13) */ 3830 { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (14) */ 3831 /* TC 7: CBA.>67->89=a */ 3832 { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (15) */ 3833 { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (16) */ 3834 { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (17) */ 3835 { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 }, /* (18) */ 3836 /* TC 8: CBA.123->xyz */ 3837 { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 }, /* (19) */ 3838 { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (20) */ 3839 { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 }, /* (21) */ 3840 { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (22) */ 3841 /* TC 9: .>12->xyz */ 3842 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */ 3843 { 6, 7, 8, 5, 4, 2, 3, 1, 0 }, /* (24) */ 3844 { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 }, /* (25) */ 3845 /* TC 10: a.>67->xyz */ 3846 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */ 3847 { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (27) */ 3848 { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 }, /* (28) */ 3849 /* TC 11: 123JIH */ 3850 { 0, 1, 2, 5, 4, 3 }, /* (29) */ 3851 { 5, 4, 3, 0, 1, 2 }, /* (30) */ 3852 /* TC 12: 123 JIH */ 3853 { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */ 3854 { 6, 5, 4, 3, 0, 1, 2 }, /* (32) */ 3855 }; 3856 3857 static const char outIndices[TC_COUNT][MODES_COUNT - 1][OPTIONS_COUNT] 3858 [LEVELS_COUNT] = { 3859 { /* TC 0: 123 */ 3860 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3861 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3862 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3863 {{ 0, 0}, { 0, 0}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3864 }, 3865 { /* TC 1: .123->4.5 */ 3866 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3867 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3868 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3869 {{ 1, 2}, { 1, 2}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3870 }, 3871 { /* TC 2: 678 */ 3872 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3873 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3874 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3875 {{ 3, 3}, { 3, 3}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3876 }, 3877 { /* TC 3: .678->8.9 */ 3878 {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3879 {{ 4, 5}, { 4, 5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3880 {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3881 {{ 6, 5}, { 6, 5}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3882 }, 3883 { /* TC 4: MLK1.2,3JIH */ 3884 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3885 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3886 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3887 {{ 7, 7}, { 7, 7}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3888 }, 3889 { /* TC 5: FE.>12-> */ 3890 {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3891 {{10, 9}, { 8, 9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3892 {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3893 {{10, 9}, { 8, 9}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3894 }, 3895 { /* TC 6: JIH.>12->a */ 3896 {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3897 {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3898 {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3899 {{13, 14}, {11, 12}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3900 }, 3901 { /* TC 7: CBA.>67->89=a */ 3902 {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3903 {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3904 {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3905 {{15, 17}, {18, 16}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3906 }, 3907 { /* TC 8: CBA.>124->xyz */ 3908 {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3909 {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3910 {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3911 {{21, 22}, {19, 20}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3912 }, 3913 { /* TC 9: .>12->xyz */ 3914 {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3915 {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3916 {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3917 {{23, 25}, {23, 24}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3918 }, 3919 { /* TC 10: a.>67->xyz */ 3920 {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3921 {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3922 {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3923 {{26, 27}, {26, 28}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3924 }, 3925 { /* TC 11: 124JIH */ 3926 {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3927 {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3928 {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3929 {{30, 30}, {30, 30}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3930 }, 3931 { /* TC 12: 124 JIH */ 3932 {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3933 {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3934 {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3935 {{31, 32}, {31, 32}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3936 } 3937 }; 3938 3939 static UBool 3940 assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, const char *srcChars, 3941 const char *destChars, const UChar *dest, int32_t destLen, 3942 int mode, int option, UBiDiLevel level) { 3943 3944 static const char roundtrip[TC_COUNT][MODES_COUNT][OPTIONS_COUNT] 3945 [LEVELS_COUNT] = { 3946 { /* TC 0: 123 */ 3947 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3948 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3949 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3950 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3951 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 3952 }, 3953 { /* TC 1: .123->4.5 */ 3954 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3955 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3956 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3957 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3958 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 3959 }, 3960 { /* TC 2: 678 */ 3961 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3962 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3963 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3964 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3965 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 3966 }, 3967 { /* TC 3: .678->8.9 */ 3968 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3969 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3970 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3971 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3972 {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 3973 }, 3974 { /* TC 4: MLK1.2,3JIH */ 3975 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3976 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3977 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3978 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3979 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 3980 }, 3981 { /* TC 5: FE.>12-> */ 3982 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3983 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3984 {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3985 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3986 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 3987 }, 3988 { /* TC 6: JIH.>12->a */ 3989 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3990 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3991 {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3992 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 3993 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 3994 }, 3995 { /* TC 7: CBA.>67->89=a */ 3996 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 3997 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 3998 {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 3999 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 4000 {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 4001 }, 4002 { /* TC 8: CBA.>123->xyz */ 4003 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 4004 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 4005 {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 4006 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 4007 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 4008 }, 4009 { /* TC 9: .>12->xyz */ 4010 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 4011 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 4012 {{ 1, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 4013 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 4014 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 4015 }, 4016 { /* TC 10: a.>67->xyz */ 4017 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 4018 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 4019 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 4020 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 4021 {{ 1, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 4022 }, 4023 { /* TC 11: 123JIH */ 4024 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 4025 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 4026 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 4027 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 4028 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 4029 }, 4030 { /* TC 12: 123 JIH */ 4031 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ 4032 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ 4033 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ 4034 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ 4035 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ 4036 } 4037 }; 4038 4039 #define SET_ROUND_TRIP_MODE(mode) \ 4040 ubidi_setReorderingMode(pBiDi, mode); \ 4041 desc = #mode; \ 4042 break; 4043 4044 UErrorCode rc = U_ZERO_ERROR; 4045 UChar dest2[MAXLEN]; 4046 int32_t destLen2; 4047 const char* desc; 4048 char destChars2[MAXLEN]; 4049 char destChars3[MAXLEN]; 4050 4051 switch (modes[mode].value) { 4052 case UBIDI_REORDER_NUMBERS_SPECIAL: 4053 SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) 4054 case UBIDI_REORDER_GROUP_NUMBERS_WITH_R: 4055 SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) 4056 case UBIDI_REORDER_RUNS_ONLY: 4057 SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY) 4058 case UBIDI_REORDER_INVERSE_NUMBERS_AS_L: 4059 SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT) 4060 case UBIDI_REORDER_INVERSE_LIKE_DIRECT: 4061 SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT) 4062 case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL: 4063 SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL) 4064 default: 4065 SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT) 4066 } 4067 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_REMOVE_CONTROLS); 4068 4069 ubidi_setPara(pBiDi, dest, destLen, level, NULL, &rc); 4070 assertSuccessful("ubidi_setPara", &rc); 4071 *dest2 = 0; 4072 destLen2 = ubidi_writeReordered(pBiDi, dest2, MAXLEN, UBIDI_DO_MIRRORING, 4073 &rc); 4074 assertSuccessful("ubidi_writeReordered", &rc); 4075 4076 u16ToPseudo(destLen, dest, destChars3); 4077 u16ToPseudo(destLen2, dest2, destChars2); 4078 checkWhatYouCan(pBiDi, destChars3, destChars2); 4079 if (strcmp(srcChars, destChars2)) { 4080 if (roundtrip[tc][mode][option][level]) { 4081 log_err("\nRound trip failed for case=%d mode=%d option=%d.\n" 4082 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s" 4083 "\n%20s %u\n", tc, mode, option, 4084 "Original text:", srcChars, 4085 "Round-tripped text:", destChars2, 4086 "Intermediate text:", destChars3, 4087 "Reordering mode:", modes[mode].description, 4088 "Reordering option:", options[option].description, 4089 "Paragraph level:", level); 4090 } 4091 else { 4092 log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n" 4093 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s" 4094 "\n%20s %u\n", tc, mode, option, 4095 "Original text:", srcChars, 4096 "Round-tripped text:", destChars2, 4097 "Intermediate text:", destChars3, 4098 "Reordering mode:", modes[mode].description, 4099 "Reordering option:", options[option].description, 4100 "Paragraph level:", level); 4101 } 4102 return FALSE; 4103 } 4104 if (!checkResultLength(pBiDi, destChars, destChars2, destLen2, 4105 desc, "UBIDI_OPTION_REMOVE_CONTROLS", level)) { 4106 return FALSE; 4107 } 4108 if (outIndex > -1 && !checkMaps(pBiDi, outIndex, srcChars, destChars, 4109 desc, "UBIDI_OPTION_REMOVE_CONTROLS", 4110 level, FALSE)) { 4111 return FALSE; 4112 } 4113 return TRUE; 4114 } 4115 4116 static UBool 4117 checkResultLength(UBiDi *pBiDi, const char *srcChars, const char *destChars, 4118 int32_t destLen, const char* mode, 4119 const char* option, UBiDiLevel level) { 4120 int32_t actualLen; 4121 if (strcmp(mode, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0) 4122 actualLen = strlen(destChars); 4123 else 4124 actualLen = ubidi_getResultLength(pBiDi); 4125 if (actualLen != destLen) { 4126 log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n" 4127 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n", 4128 "Expected:", destLen, "Actual:", actualLen, 4129 "Input:", srcChars, "Output:", destChars, 4130 "Reordering mode:", mode, "Reordering option:", option, 4131 "Paragraph level:", level); 4132 return FALSE; 4133 } 4134 return TRUE; 4135 } 4136 4137 static void 4138 testReorderRunsOnly(void) { 4139 static const struct { 4140 const char* textIn; 4141 const char* textOut[2][2]; 4142 const char noroundtrip[2]; 4143 } testCases[] = { 4144 {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*0*/ 4145 {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}}, 4146 {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}}, /*1*/ 4147 {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}}, /*2*/ 4148 {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"}, /*3*/ 4149 {"* /%$123=-", "* /%$123=-"}}, {0, 0}}, 4150 {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"}, /*4*/ 4151 {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}}, 4152 {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"}, /*5*/ 4153 {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}}, 4154 {"123->abc", {{"abc<-123", "abc<-123"}, /*6*/ 4155 {"abc&<-123", "abc<-123"}}, {1, 0}}, 4156 {"123->JKL", {{"JKL<-123", "123->JKL"}, /*7*/ 4157 {"JKL<-123", "JKL<-@123"}}, {0, 1}}, 4158 {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"}, /*8*/ 4159 {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}}, 4160 {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"}, /*9*/ 4161 {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}}, 4162 {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"}, /*10*/ 4163 {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}}, 4164 {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"}, /*11*/ 4165 {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}}, 4166 {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"}, /*12*/ 4167 {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}}, 4168 {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"}, /*13*/ 4169 {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}}, 4170 {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"}, /*14*/ 4171 {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}}, 4172 {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*15*/ 4173 {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}}, 4174 {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}, /*16*/ 4175 {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}}, 4176 {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"}, /*17*/ 4177 {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}}, 4178 {"123", {{"123", "123"}, /* just one run */ /*18*/ 4179 {"123", "123"}}, {0, 0}} 4180 }; 4181 UBiDi *pBiDi = getBiDiObject(); 4182 UBiDi *pL2VBiDi = getBiDiObject(); 4183 UChar src[MAXLEN], dest[MAXLEN], visual1[MAXLEN], visual2[MAXLEN]; 4184 char destChars[MAXLEN], vis1Chars[MAXLEN], vis2Chars[MAXLEN]; 4185 int32_t srcLen, destLen, vis1Len, vis2Len, option, i, j, nCases, paras; 4186 UErrorCode rc = U_ZERO_ERROR; 4187 UBiDiLevel level; 4188 4189 log_verbose("\nEntering TestReorderRunsOnly\n\n"); 4190 4191 if(!pL2VBiDi) { 4192 ubidi_close(pBiDi); /* in case this one was allocated */ 4193 return; 4194 } 4195 ubidi_setReorderingMode(pBiDi, UBIDI_REORDER_RUNS_ONLY); 4196 ubidi_setReorderingOptions(pL2VBiDi, UBIDI_OPTION_REMOVE_CONTROLS); 4197 4198 for (option = 0; option < 2; option++) { 4199 ubidi_setReorderingOptions(pBiDi, option==0 ? UBIDI_OPTION_REMOVE_CONTROLS 4200 : UBIDI_OPTION_INSERT_MARKS); 4201 for (i = 0, nCases = UPRV_LENGTHOF(testCases); i < nCases; i++) { 4202 srcLen = strlen(testCases[i].textIn); 4203 pseudoToU16(srcLen, testCases[i].textIn, src); 4204 for(j = 0; j < 2; j++) { 4205 log_verbose("Now doing test for option %d, case %d, level %d\n", 4206 i, option, j); 4207 level = paraLevels[j]; 4208 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc); 4209 assertSuccessful("ubidi_setPara", &rc); 4210 *dest = 0; 4211 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc); 4212 assertSuccessful("ubidi_writeReordered", &rc); 4213 u16ToPseudo(destLen, dest, destChars); 4214 checkWhatYouCan(pBiDi, testCases[i].textIn, destChars); 4215 assertStringsEqual(testCases[i].textOut[option][level], destChars, 4216 testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY", 4217 option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS", 4218 pBiDi); 4219 4220 if((option==0) && testCases[i].noroundtrip[level]) { 4221 continue; 4222 } 4223 ubidi_setPara(pL2VBiDi, src, srcLen, level, NULL, &rc); 4224 assertSuccessful("ubidi_setPara1", &rc); 4225 *visual1 = 0; 4226 vis1Len = ubidi_writeReordered(pL2VBiDi, visual1, MAXLEN, UBIDI_DO_MIRRORING, &rc); 4227 assertSuccessful("ubidi_writeReordered1", &rc); 4228 u16ToPseudo(vis1Len, visual1, vis1Chars); 4229 checkWhatYouCan(pL2VBiDi, testCases[i].textIn, vis1Chars); 4230 ubidi_setPara(pL2VBiDi, dest, destLen, level^1, NULL, &rc); 4231 assertSuccessful("ubidi_setPara2", &rc); 4232 *visual2 = 0; 4233 vis2Len = ubidi_writeReordered(pL2VBiDi, visual2, MAXLEN, UBIDI_DO_MIRRORING, &rc); 4234 assertSuccessful("ubidi_writeReordered2", &rc); 4235 u16ToPseudo(vis2Len, visual2, vis2Chars); 4236 checkWhatYouCan(pL2VBiDi, destChars, vis2Chars); 4237 assertStringsEqual(vis1Chars, vis2Chars, 4238 testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY (2)", 4239 option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS", 4240 pBiDi); 4241 } 4242 } 4243 } 4244 4245 /* test with null or empty text */ 4246 ubidi_setPara(pBiDi, src, 0, UBIDI_LTR, NULL, &rc); 4247 assertSuccessful("ubidi_setPara3", &rc); 4248 paras = ubidi_countParagraphs(pBiDi); 4249 if (paras != 0) { 4250 log_err("\nInvalid number of paras (should be 0): %d\n", paras); 4251 } 4252 4253 ubidi_close(pBiDi); 4254 ubidi_close(pL2VBiDi); 4255 4256 log_verbose("\nExiting TestReorderRunsOnly\n\n"); 4257 } 4258 4259 static void 4260 testReorderingMode(void) { 4261 4262 UChar src[MAXLEN], dest[MAXLEN]; 4263 char destChars[MAXLEN]; 4264 UBiDi *pBiDi = NULL, *pBiDi2 = NULL, *pBiDi3 = NULL; 4265 UErrorCode rc; 4266 int tc, mode, option, level; 4267 uint32_t optionValue, optionBack; 4268 UBiDiReorderingMode modeValue, modeBack; 4269 int32_t srcLen, destLen, idx; 4270 const char *expectedChars; 4271 UBool testOK = TRUE; 4272 4273 log_verbose("\nEntering TestReorderingMode\n\n"); 4274 4275 pBiDi = getBiDiObject(); 4276 pBiDi2 = getBiDiObject(); 4277 pBiDi3 = getBiDiObject(); 4278 if(!pBiDi3) { 4279 ubidi_close(pBiDi); /* in case this one was allocated */ 4280 ubidi_close(pBiDi2); /* in case this one was allocated */ 4281 return; 4282 } 4283 4284 ubidi_setInverse(pBiDi2, TRUE); 4285 4286 for (tc = 0; tc < TC_COUNT; tc++) { 4287 const char *srcChars = textIn[tc]; 4288 srcLen = strlen(srcChars); 4289 pseudoToU16(srcLen, srcChars, src); 4290 4291 for (mode = 0; mode < MODES_COUNT; mode++) { 4292 modeValue = modes[mode].value; 4293 ubidi_setReorderingMode(pBiDi, modeValue); 4294 modeBack = ubidi_getReorderingMode(pBiDi); 4295 if (modeValue != modeBack) { 4296 log_err("Error while setting reordering mode to %d, returned %d\n", 4297 modeValue, modeBack); 4298 } 4299 4300 for (option = 0; option < OPTIONS_COUNT; option++) { 4301 optionValue = options[option].value; 4302 ubidi_setReorderingOptions(pBiDi, optionValue); 4303 optionBack = ubidi_getReorderingOptions(pBiDi); 4304 if (optionValue != optionBack) { 4305 log_err("Error while setting reordering option to %d, returned %d\n", 4306 optionValue, optionBack); 4307 } 4308 4309 for (level = 0; level < LEVELS_COUNT; level++) { 4310 log_verbose("starting test %d mode=%d option=%d level=%d\n", 4311 tc, modes[mode].value, options[option].value, level); 4312 rc = U_ZERO_ERROR; 4313 ubidi_setPara(pBiDi, src, srcLen, paraLevels[level], NULL, &rc); 4314 assertSuccessful("ubidi_setPara", &rc); 4315 4316 *dest = 0; 4317 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, 4318 UBIDI_DO_MIRRORING, &rc); 4319 assertSuccessful("ubidi_writeReordered", &rc); 4320 u16ToPseudo(destLen, dest, destChars); 4321 if (!((modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) && 4322 (options[option].value == UBIDI_OPTION_INSERT_MARKS))) { 4323 checkWhatYouCan(pBiDi, srcChars, destChars); 4324 } 4325 4326 if (modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) { 4327 idx = -1; 4328 expectedChars = inverseBasic(pBiDi2, srcChars, srcLen, 4329 options[option].value, paraLevels[level], destChars); 4330 } 4331 else { 4332 idx = outIndices[tc][mode][option][level]; 4333 expectedChars = textOut[idx]; 4334 } 4335 if (!assertStringsEqual(expectedChars, destChars, srcChars, 4336 modes[mode].description, 4337 options[option].description, 4338 pBiDi)) { 4339 testOK = FALSE; 4340 } 4341 if (options[option].value == UBIDI_OPTION_INSERT_MARKS && 4342 !assertRoundTrip(pBiDi3, tc, idx, srcChars, 4343 destChars, dest, destLen, 4344 mode, option, paraLevels[level])) { 4345 testOK = FALSE; 4346 } 4347 else if (!checkResultLength(pBiDi, srcChars, destChars, 4348 destLen, modes[mode].description, 4349 options[option].description, 4350 paraLevels[level])) { 4351 testOK = FALSE; 4352 } 4353 else if (idx > -1 && !checkMaps(pBiDi, idx, srcChars, 4354 destChars, modes[mode].description, 4355 options[option].description, paraLevels[level], 4356 TRUE)) { 4357 testOK = FALSE; 4358 } 4359 } 4360 } 4361 } 4362 } 4363 if (testOK == TRUE) { 4364 log_verbose("\nReordering mode test OK\n"); 4365 } 4366 ubidi_close(pBiDi3); 4367 ubidi_close(pBiDi2); 4368 ubidi_close(pBiDi); 4369 4370 log_verbose("\nExiting TestReorderingMode\n\n"); 4371 } 4372 4373 static const char* inverseBasic(UBiDi *pBiDi, const char *srcChars, int32_t srcLen, 4374 uint32_t option, UBiDiLevel level, char *result) { 4375 UErrorCode rc = U_ZERO_ERROR; 4376 int32_t destLen; 4377 UChar src[MAXLEN], dest2[MAXLEN]; 4378 4379 if (pBiDi == NULL || srcChars == NULL) { 4380 return NULL; 4381 } 4382 ubidi_setReorderingOptions(pBiDi, option); 4383 pseudoToU16(srcLen, srcChars, src); 4384 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc); 4385 assertSuccessful("ubidi_setPara", &rc); 4386 4387 *dest2 = 0; 4388 destLen = ubidi_writeReordered(pBiDi, dest2, MAXLEN, 4389 UBIDI_DO_MIRRORING, &rc); 4390 assertSuccessful("ubidi_writeReordered", &rc); 4391 u16ToPseudo(destLen, dest2, result); 4392 if (!(option == UBIDI_OPTION_INSERT_MARKS)) { 4393 checkWhatYouCan(pBiDi, srcChars, result); 4394 } 4395 return result; 4396 } 4397 4398 #define NULL_CHAR '\0' 4399 4400 static void 4401 testStreaming(void) { 4402 #define MAXPORTIONS 10 4403 4404 static const struct { 4405 const char* textIn; 4406 short int chunk; 4407 short int nPortions[2]; 4408 char portionLens[2][MAXPORTIONS]; 4409 const char* message[2]; 4410 } testData[] = { 4411 { "123\\u000A" 4412 "abc45\\u000D" 4413 "67890\\u000A" 4414 "\\u000D" 4415 "02468\\u000D" 4416 "ghi", 4417 6, { 6, 6 }, {{ 4, 6, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }}, 4418 {"4, 6, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"} 4419 }, 4420 { "abcd\\u000Afgh\\u000D12345\\u000A456", 4421 6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }}, 4422 {"5, 4, 6, 3", "5, 4, 6, 3"} 4423 }, 4424 { "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D", 4425 6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }}, 4426 {"5, 4, 6, 3", "5, 4, 6, 3"} 4427 }, 4428 { "abcde\\u000Afghi", 4429 10, { 2, 2 }, {{ 6, 4 }, { 6, 4 }}, 4430 {"6, 4", "6, 4"} 4431 } 4432 }; 4433 UChar src[MAXLEN]; 4434 UBiDi *pBiDi = NULL; 4435 UChar *pSrc; 4436 UErrorCode rc = U_ZERO_ERROR; 4437 int32_t srcLen, processedLen, chunk, len, nPortions; 4438 int i, j, levelIndex; 4439 UBiDiLevel level; 4440 int nTests = UPRV_LENGTHOF(testData), nLevels = UPRV_LENGTHOF(paraLevels); 4441 UBool mismatch, testOK = TRUE; 4442 char processedLenStr[MAXPORTIONS * 5]; 4443 4444 log_verbose("\nEntering TestStreaming\n\n"); 4445 4446 pBiDi = getBiDiObject(); 4447 4448 ubidi_orderParagraphsLTR(pBiDi, TRUE); 4449 4450 for (levelIndex = 0; levelIndex < nLevels; levelIndex++) { 4451 for (i = 0; i < nTests; i++) { 4452 srcLen = u_unescape(testData[i].textIn, src, MAXLEN); 4453 chunk = testData[i].chunk; 4454 nPortions = testData[i].nPortions[levelIndex]; 4455 level = paraLevels[levelIndex]; 4456 processedLenStr[0] = NULL_CHAR; 4457 log_verbose("Testing level %d, case %d\n", level, i); 4458 4459 mismatch = FALSE; 4460 4461 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING); 4462 for (j = 0, pSrc = src; j < MAXPORTIONS && srcLen > 0; j++) { 4463 4464 len = chunk < srcLen ? chunk : srcLen; 4465 ubidi_setPara(pBiDi, pSrc, len, level, NULL, &rc); 4466 if (!assertSuccessful("ubidi_setPara", &rc)) { 4467 break; 4468 } 4469 4470 processedLen = ubidi_getProcessedLength(pBiDi); 4471 if (processedLen == 0) { 4472 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_DEFAULT); 4473 j--; 4474 continue; 4475 } 4476 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING); 4477 4478 mismatch |= (UBool)(j >= nPortions || 4479 processedLen != testData[i].portionLens[levelIndex][j]); 4480 4481 sprintf(processedLenStr + j * 4, "%4d", processedLen); 4482 srcLen -= processedLen, pSrc += processedLen; 4483 } 4484 4485 if (mismatch || j != nPortions) { 4486 testOK = FALSE; 4487 log_err("\nProcessed lengths mismatch.\n" 4488 "\tParagraph level: %u\n" 4489 "\tInput string: %s\n" 4490 "\tActually processed portion lengths: { %s }\n" 4491 "\tExpected portion lengths : { %s }\n", 4492 paraLevels[levelIndex], testData[i].textIn, 4493 processedLenStr, testData[i].message[levelIndex]); 4494 } 4495 } 4496 } 4497 ubidi_close(pBiDi); 4498 if (testOK == TRUE) { 4499 log_verbose("\nBiDi streaming test OK\n"); 4500 } 4501 log_verbose("\nExiting TestStreaming\n\n"); 4502 } 4503 4504 U_CDECL_BEGIN 4505 4506 static UCharDirection U_CALLCONV 4507 overrideBidiClass(const void *context, UChar32 c) { 4508 4509 #define DEF U_BIDI_CLASS_DEFAULT 4510 4511 static const UCharDirection customClasses[] = { 4512 /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ 4513 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 00-07 */ 4514 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 08-0F */ 4515 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 10-17 */ 4516 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 18-1F */ 4517 DEF, DEF, DEF, DEF, DEF, DEF, R, DEF, /* 20-27 */ 4518 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 28-2F */ 4519 EN, EN, EN, EN, EN, EN, AN, AN, /* 30-37 */ 4520 AN, AN, DEF, DEF, DEF, DEF, DEF, DEF, /* 38-3F */ 4521 L, AL, AL, AL, AL, AL, AL, R, /* 40-47 */ 4522 R, R, R, R, R, R, R, R, /* 48-4F */ 4523 R, R, R, R, R, R, R, R, /* 50-57 */ 4524 R, R, R, LRE, DEF, RLE, PDF, S, /* 58-5F */ 4525 NSM, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 60-67 */ 4526 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 68-6F */ 4527 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 70-77 */ 4528 DEF, DEF, DEF, LRO, B, RLO, BN, DEF /* 78-7F */ 4529 }; 4530 static const int nEntries = UPRV_LENGTHOF(customClasses); 4531 const char *dummy = context; /* just to avoid a compiler warning */ 4532 dummy++; 4533 4534 return c >= nEntries ? U_BIDI_CLASS_DEFAULT : customClasses[c]; 4535 } 4536 4537 U_CDECL_END 4538 4539 static void verifyCallbackParams(UBiDiClassCallback* fn, const void* context, 4540 UBiDiClassCallback* expectedFn, 4541 const void* expectedContext, 4542 int32_t sizeOfContext) { 4543 if (fn != expectedFn) { 4544 log_err("Class callback pointer is not set properly.\n"); 4545 } 4546 if (context != expectedContext) { 4547 log_err("Class callback context is not set properly.\n"); 4548 } 4549 else if (context != NULL && 4550 memcmp(context, expectedContext, sizeOfContext)) { 4551 log_err("Callback context content doesn't match the expected one.\n"); 4552 } 4553 } 4554 4555 static void 4556 testClassOverride(void) { 4557 static const char* const textSrc = "JIH.>12->a \\u05D0\\u05D1 6 ABC78"; 4558 static const char* const textResult = "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0"; 4559 4560 UChar src[MAXLEN], dest[MAXLEN]; 4561 UErrorCode rc = U_ZERO_ERROR; 4562 UBiDi *pBiDi = NULL; 4563 UBiDiClassCallback* oldFn = NULL; 4564 UBiDiClassCallback* newFn = overrideBidiClass; 4565 const void* oldContext = NULL; 4566 int32_t srcLen, destLen, textSrcSize = (int32_t)uprv_strlen(textSrc); 4567 char* destChars = NULL; 4568 4569 log_verbose("\nEntering TestClassOverride\n\n"); 4570 4571 pBiDi = getBiDiObject(); 4572 if(!pBiDi) { 4573 return; 4574 } 4575 4576 ubidi_getClassCallback(pBiDi, &oldFn, &oldContext); 4577 verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0); 4578 4579 ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc); 4580 if (!assertSuccessful("ubidi_setClassCallback", &rc)) { 4581 ubidi_close(pBiDi); 4582 return; 4583 } 4584 verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0); 4585 4586 ubidi_getClassCallback(pBiDi, &oldFn, &oldContext); 4587 verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize); 4588 4589 ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc); 4590 if (!assertSuccessful("ubidi_setClassCallback", &rc)) { 4591 ubidi_close(pBiDi); 4592 return; 4593 } 4594 verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize); 4595 4596 srcLen = u_unescape(textSrc, src, MAXLEN); 4597 ubidi_setPara(pBiDi, src, srcLen, UBIDI_LTR, NULL, &rc); 4598 assertSuccessful("ubidi_setPara", &rc); 4599 4600 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, 4601 UBIDI_DO_MIRRORING, &rc); 4602 assertSuccessful("ubidi_writeReordered", &rc); 4603 4604 destChars = aescstrdup(dest, destLen); 4605 if (uprv_strcmp(textResult, destChars)) { 4606 log_err("\nActual and expected output mismatch.\n" 4607 "%20s %s\n%20s %s\n%20s %s\n", 4608 "Input:", textSrc, "Actual output:", destChars, 4609 "Expected output:", textResult); 4610 } 4611 else { 4612 log_verbose("\nClass override test OK\n"); 4613 } 4614 ubidi_close(pBiDi); 4615 log_verbose("\nExiting TestClassOverride\n\n"); 4616 } 4617 4618 static char * formatMap(const int32_t * map, int len, char * buffer) 4619 { 4620 int32_t i, k; 4621 char c; 4622 for (i = 0; i < len; i++) { 4623 k = map[i]; 4624 if (k < 0) 4625 c = '-'; 4626 else if (k >= sizeof(columns)) 4627 c = '+'; 4628 else 4629 c = columns[k]; 4630 buffer[i] = c; 4631 } 4632 buffer[len] = '\0'; 4633 return buffer; 4634 } 4635 4636 static UBool 4637 checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, const char *dest, 4638 const char *mode, const char* option, UBiDiLevel level, UBool forward) 4639 { 4640 int32_t actualLogicalMap[MAX_MAP_LENGTH]; 4641 int32_t actualVisualMap[MAX_MAP_LENGTH]; 4642 int32_t getIndexMap[MAX_MAP_LENGTH]; 4643 int32_t i, srcLen, resLen, idx; 4644 const int32_t *expectedLogicalMap, *expectedVisualMap; 4645 UErrorCode rc = U_ZERO_ERROR; 4646 UBool testOK = TRUE; 4647 4648 if (forward) { 4649 expectedLogicalMap = forwardMap[stringIndex]; 4650 expectedVisualMap = inverseMap[stringIndex]; 4651 } 4652 else { 4653 expectedLogicalMap = inverseMap[stringIndex]; 4654 expectedVisualMap = forwardMap[stringIndex]; 4655 } 4656 ubidi_getLogicalMap(pBiDi, actualLogicalMap, &rc); 4657 if (!assertSuccessful("ubidi_getLogicalMap", &rc)) { 4658 testOK = FALSE; 4659 } 4660 srcLen = ubidi_getProcessedLength(pBiDi); 4661 if (memcmp(expectedLogicalMap, actualLogicalMap, srcLen * sizeof(int32_t))) { 4662 char expChars[MAX_MAP_LENGTH]; 4663 char actChars[MAX_MAP_LENGTH]; 4664 log_err("\nubidi_getLogicalMap() returns unexpected map for output string " 4665 "index %d\n" 4666 "source: %s\n" 4667 "dest : %s\n" 4668 "Scale : %s\n" 4669 "ExpMap: %s\n" 4670 "Actual: %s\n" 4671 "Paragraph level : %d == %d\n" 4672 "Reordering mode : %s == %d\n" 4673 "Reordering option: %s == %d\n" 4674 "Forward flag : %d\n", 4675 stringIndex, src, dest, columns, 4676 formatMap(expectedLogicalMap, srcLen, expChars), 4677 formatMap(actualLogicalMap, srcLen, actChars), 4678 level, ubidi_getParaLevel(pBiDi), 4679 mode, ubidi_getReorderingMode(pBiDi), 4680 option, ubidi_getReorderingOptions(pBiDi), 4681 forward 4682 ); 4683 testOK = FALSE; 4684 } 4685 resLen = ubidi_getResultLength(pBiDi); 4686 ubidi_getVisualMap(pBiDi, actualVisualMap, &rc); 4687 assertSuccessful("ubidi_getVisualMap", &rc); 4688 if (memcmp(expectedVisualMap, actualVisualMap, resLen * sizeof(int32_t))) { 4689 char expChars[MAX_MAP_LENGTH]; 4690 char actChars[MAX_MAP_LENGTH]; 4691 log_err("\nubidi_getVisualMap() returns unexpected map for output string " 4692 "index %d\n" 4693 "source: %s\n" 4694 "dest : %s\n" 4695 "Scale : %s\n" 4696 "ExpMap: %s\n" 4697 "Actual: %s\n" 4698 "Paragraph level : %d == %d\n" 4699 "Reordering mode : %s == %d\n" 4700 "Reordering option: %s == %d\n" 4701 "Forward flag : %d\n", 4702 stringIndex, src, dest, columns, 4703 formatMap(expectedVisualMap, resLen, expChars), 4704 formatMap(actualVisualMap, resLen, actChars), 4705 level, ubidi_getParaLevel(pBiDi), 4706 mode, ubidi_getReorderingMode(pBiDi), 4707 option, ubidi_getReorderingOptions(pBiDi), 4708 forward 4709 ); 4710 testOK = FALSE; 4711 } 4712 for (i = 0; i < srcLen; i++) { 4713 idx = ubidi_getVisualIndex(pBiDi, i, &rc); 4714 assertSuccessful("ubidi_getVisualIndex", &rc); 4715 getIndexMap[i] = idx; 4716 } 4717 if (memcmp(actualLogicalMap, getIndexMap, srcLen * sizeof(int32_t))) { 4718 char actChars[MAX_MAP_LENGTH]; 4719 char gotChars[MAX_MAP_LENGTH]; 4720 log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string " 4721 "index %d\n" 4722 "source: %s\n" 4723 "dest : %s\n" 4724 "Scale : %s\n" 4725 "ActMap: %s\n" 4726 "IdxMap: %s\n" 4727 "Paragraph level : %d == %d\n" 4728 "Reordering mode : %s == %d\n" 4729 "Reordering option: %s == %d\n" 4730 "Forward flag : %d\n", 4731 stringIndex, src, dest, columns, 4732 formatMap(actualLogicalMap, srcLen, actChars), 4733 formatMap(getIndexMap, srcLen, gotChars), 4734 level, ubidi_getParaLevel(pBiDi), 4735 mode, ubidi_getReorderingMode(pBiDi), 4736 option, ubidi_getReorderingOptions(pBiDi), 4737 forward 4738 ); 4739 testOK = FALSE; 4740 } 4741 for (i = 0; i < resLen; i++) { 4742 idx = ubidi_getLogicalIndex(pBiDi, i, &rc); 4743 assertSuccessful("ubidi_getLogicalIndex", &rc); 4744 getIndexMap[i] = idx; 4745 } 4746 if (memcmp(actualVisualMap, getIndexMap, resLen * sizeof(int32_t))) { 4747 char actChars[MAX_MAP_LENGTH]; 4748 char gotChars[MAX_MAP_LENGTH]; 4749 log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string " 4750 "index %d\n" 4751 "source: %s\n" 4752 "dest : %s\n" 4753 "Scale : %s\n" 4754 "ActMap: %s\n" 4755 "IdxMap: %s\n" 4756 "Paragraph level : %d == %d\n" 4757 "Reordering mode : %s == %d\n" 4758 "Reordering option: %s == %d\n" 4759 "Forward flag : %d\n", 4760 stringIndex, src, dest, columns, 4761 formatMap(actualVisualMap, resLen, actChars), 4762 formatMap(getIndexMap, resLen, gotChars), 4763 level, ubidi_getParaLevel(pBiDi), 4764 mode, ubidi_getReorderingMode(pBiDi), 4765 option, ubidi_getReorderingOptions(pBiDi), 4766 forward 4767 ); 4768 testOK = FALSE; 4769 } 4770 return testOK; 4771 } 4772 4773 static UBool 4774 assertIllegalArgument(const char* message, UErrorCode* rc) { 4775 if (*rc != U_ILLEGAL_ARGUMENT_ERROR) { 4776 log_err("%s() failed with error %s.\n", message, myErrorName(*rc)); 4777 return FALSE; 4778 } 4779 return TRUE; 4780 } 4781 4782 typedef struct { 4783 const char* prologue; 4784 const char* source; 4785 const char* epilogue; 4786 const char* expected; 4787 UBiDiLevel paraLevel; 4788 } contextCase; 4789 4790 static const contextCase contextData[] = { 4791 /*00*/ {"", "", "", "", UBIDI_LTR}, 4792 /*01*/ {"", ".-=JKL-+*", "", ".-=LKJ-+*", UBIDI_LTR}, 4793 /*02*/ {" ", ".-=JKL-+*", " ", ".-=LKJ-+*", UBIDI_LTR}, 4794 /*03*/ {"a", ".-=JKL-+*", "b", ".-=LKJ-+*", UBIDI_LTR}, 4795 /*04*/ {"D", ".-=JKL-+*", "", "LKJ=-.-+*", UBIDI_LTR}, 4796 /*05*/ {"", ".-=JKL-+*", " D", ".-=*+-LKJ", UBIDI_LTR}, 4797 /*06*/ {"", ".-=JKL-+*", " 2", ".-=*+-LKJ", UBIDI_LTR}, 4798 /*07*/ {"", ".-=JKL-+*", " 7", ".-=*+-LKJ", UBIDI_LTR}, 4799 /*08*/ {" G 1", ".-=JKL-+*", " H", "*+-LKJ=-.", UBIDI_LTR}, 4800 /*09*/ {"7", ".-=JKL-+*", " H", ".-=*+-LKJ", UBIDI_LTR}, 4801 /*10*/ {"", ".-=abc-+*", "", "*+-abc=-.", UBIDI_RTL}, 4802 /*11*/ {" ", ".-=abc-+*", " ", "*+-abc=-.", UBIDI_RTL}, 4803 /*12*/ {"D", ".-=abc-+*", "G", "*+-abc=-.", UBIDI_RTL}, 4804 /*13*/ {"x", ".-=abc-+*", "", "*+-.-=abc", UBIDI_RTL}, 4805 /*14*/ {"", ".-=abc-+*", " y", "abc-+*=-.", UBIDI_RTL}, 4806 /*15*/ {"", ".-=abc-+*", " 2", "abc-+*=-.", UBIDI_RTL}, 4807 /*16*/ {" x 1", ".-=abc-+*", " 2", ".-=abc-+*", UBIDI_RTL}, 4808 /*17*/ {" x 7", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL}, 4809 /*18*/ {"x|", ".-=abc-+*", " 8", "*+-abc=-.", UBIDI_RTL}, 4810 /*19*/ {"G|y", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL}, 4811 /*20*/ {"", ".-=", "", ".-=", UBIDI_DEFAULT_LTR}, 4812 /*21*/ {"D", ".-=", "", "=-.", UBIDI_DEFAULT_LTR}, 4813 /*22*/ {"G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR}, 4814 /*23*/ {"xG", ".-=", "", ".-=", UBIDI_DEFAULT_LTR}, 4815 /*24*/ {"x|G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR}, 4816 /*25*/ {"x|G", ".-=|-+*", "", "=-.|-+*", UBIDI_DEFAULT_LTR}, 4817 }; 4818 #define CONTEXT_COUNT UPRV_LENGTHOF(contextData) 4819 4820 static void 4821 testContext(void) { 4822 4823 UChar prologue[MAXLEN], epilogue[MAXLEN], src[MAXLEN], dest[MAXLEN]; 4824 char destChars[MAXLEN]; 4825 UBiDi *pBiDi = NULL; 4826 UErrorCode rc; 4827 int32_t proLength, epiLength, srcLen, destLen, tc; 4828 contextCase cc; 4829 UBool testOK = TRUE; 4830 4831 log_verbose("\nEntering TestContext \n\n"); 4832 4833 /* test null BiDi object */ 4834 rc = U_ZERO_ERROR; 4835 ubidi_setContext(pBiDi, NULL, 0, NULL, 0, &rc); 4836 testOK &= assertIllegalArgument("Error when BiDi object is null", &rc); 4837 4838 pBiDi = getBiDiObject(); 4839 ubidi_orderParagraphsLTR(pBiDi, TRUE); 4840 4841 /* test proLength < -1 */ 4842 rc = U_ZERO_ERROR; 4843 ubidi_setContext(pBiDi, NULL, -2, NULL, 0, &rc); 4844 testOK &= assertIllegalArgument("Error when proLength < -1", &rc); 4845 /* test epiLength < -1 */ 4846 rc = U_ZERO_ERROR; 4847 ubidi_setContext(pBiDi, NULL, 0, NULL, -2, &rc); 4848 testOK &= assertIllegalArgument("Error when epiLength < -1", &rc); 4849 /* test prologue == NULL */ 4850 rc = U_ZERO_ERROR; 4851 ubidi_setContext(pBiDi, NULL, 3, NULL, 0, &rc); 4852 testOK &= assertIllegalArgument("Prologue is NULL", &rc); 4853 /* test epilogue == NULL */ 4854 rc = U_ZERO_ERROR; 4855 ubidi_setContext(pBiDi, NULL, 0, NULL, 4, &rc); 4856 testOK &= assertIllegalArgument("Epilogue is NULL", &rc); 4857 4858 for (tc = 0; tc < CONTEXT_COUNT; tc++) { 4859 cc = contextData[tc]; 4860 proLength = strlen(cc.prologue); 4861 pseudoToU16(proLength, cc.prologue, prologue); 4862 epiLength = strlen(cc.epilogue); 4863 pseudoToU16(epiLength, cc.epilogue, epilogue); 4864 /* in the call below, prologue and epilogue are swapped to show 4865 that the next call will override this call */ 4866 rc = U_ZERO_ERROR; 4867 ubidi_setContext(pBiDi, epilogue, epiLength, prologue, proLength, &rc); 4868 testOK &= assertSuccessful("swapped ubidi_setContext", &rc); 4869 ubidi_setContext(pBiDi, prologue, -1, epilogue, -1, &rc); 4870 testOK &= assertSuccessful("regular ubidi_setContext", &rc); 4871 srcLen = strlen(cc.source); 4872 pseudoToU16(srcLen, cc.source, src); 4873 ubidi_setPara(pBiDi, src, srcLen, cc.paraLevel, NULL, &rc); 4874 testOK &= assertSuccessful("ubidi_setPara", &rc); 4875 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc); 4876 assertSuccessful("ubidi_writeReordered", &rc); 4877 u16ToPseudo(destLen, dest, destChars); 4878 if (uprv_strcmp(cc.expected, destChars)) { 4879 char formatChars[MAXLEN]; 4880 log_err("\nActual and expected output mismatch on case %d.\n" 4881 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d\n%20s %u\n%20s %d\n", 4882 tc, 4883 "Prologue:", cc.prologue, 4884 "Input:", cc.source, 4885 "Epilogue:", cc.epilogue, 4886 "Expected output:", cc.expected, 4887 "Actual output:", destChars, 4888 "Levels:", formatLevels(pBiDi, formatChars), 4889 "Reordering mode:", ubidi_getReorderingMode(pBiDi), 4890 "Paragraph level:", ubidi_getParaLevel(pBiDi), 4891 "Reordering option:", ubidi_getReorderingOptions(pBiDi)); 4892 testOK = FALSE; 4893 } 4894 } 4895 if (testOK == TRUE) { 4896 log_verbose("\nContext test OK\n"); 4897 } 4898 ubidi_close(pBiDi); 4899 4900 log_verbose("\nExiting TestContext \n\n"); 4901 } 4902 4903 /* Ticket#11054 ubidi_setPara crash with heavily nested brackets */ 4904 static void 4905 testBracketOverflow(void) { 4906 static const char* TEXT = "(((((((((((((((((((((((((((((((((((((((((a)(A)))))))))))))))))))))))))))))))))))))))))"; 4907 UErrorCode status = U_ZERO_ERROR; 4908 UBiDi* bidi; 4909 UChar src[100]; 4910 int32_t len; 4911 4912 bidi = ubidi_open(); 4913 len = uprv_strlen(TEXT); 4914 pseudoToU16(len, TEXT, src); 4915 ubidi_setPara(bidi, src, len, UBIDI_DEFAULT_LTR , NULL, &status); 4916 if (U_FAILURE(status)) { 4917 log_err("setPara failed with heavily nested brackets - %s", u_errorName(status)); 4918 } 4919 4920 ubidi_close(bidi); 4921 } 4922 4923