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