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