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