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