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