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