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