1 /********************************************************************
3 * Copyright (c) 1997-2013, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /* file name: cbiditst.c
8 * tab size: 8 (not used)
11 * created on: 1999sep27
12 * created by: Markus W. Scherer, updated by Matitiahu Allouche
16 #include "unicode/utypes.h"
17 #include "unicode/uchar.h"
18 #include "unicode/ustring.h"
19 #include "unicode/ubidi.h"
20 #include "unicode/ushape.h"
23 /* the following include is needed for sprintf */
26 #define MAXLEN MAX_STRING_LENGTH
27 #define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
29 /* prototypes ---------------------------------------------------------------*/
31 void addComplexTest(TestNode** root);
33 static void testCharFromDirProp(void);
35 static void testBidi(void);
37 static void doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst);
39 static void doMisc(void);
41 static void doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test,
42 int32_t lineStart, UBool countRunsFirst);
44 static void _testReordering(UBiDi *pBiDi, int testNumber);
46 static void testInverse(void);
48 static void _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction);
50 static void _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
51 UBiDiLevel direction, UErrorCode *pErrorCode);
53 static void _testWriteReverse(void);
55 static void _testManyAddedPoints(void);
57 static void _testMisc(void);
59 static void doArabicShapingTest(void);
61 static void doLamAlefSpecialVLTRArabicShapingTest(void);
63 static void doTashkeelSpecialVLTRArabicShapingTest(void);
65 static void doLOGICALArabicDeShapingTest(void);
67 static void doArabicShapingTestForBug5421(void);
69 static void doArabicShapingTestForBug8703(void);
71 static void doArabicShapingTestForBug9024(void);
73 static void testReorder(void);
75 static void testReorderArabicMathSymbols(void);
77 static void testFailureRecovery(void);
79 static void testMultipleParagraphs(void);
81 static void testGetBaseDirection(void);
83 static void testContext(void);
85 static void doTailTest(void);
87 static void testBracketOverflow(void);
90 static void testReorderingMode(void);
91 static void testReorderRunsOnly(void);
92 static void testStreaming(void);
93 static void testClassOverride(void);
94 static const char* inverseBasic(UBiDi *pBiDi, const char *src, int32_t srcLen,
95 uint32_t option, UBiDiLevel level, char *result);
96 static UBool assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex,
97 const char *srcChars, const char *destChars,
98 const UChar *dest, int32_t destLen, int mode,
99 int option, UBiDiLevel level);
100 static UBool checkResultLength(UBiDi *pBiDi, const char *srcChars,
101 const char *destChars,
102 int32_t destLen, const char *mode,
103 const char *option, UBiDiLevel level);
104 static UBool checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src,
105 const char *dest, const char *mode, const char* option,
106 UBiDiLevel level, UBool forward);
108 /* helpers ------------------------------------------------------------------ */
110 static const char *levelString="...............................................................";
112 static void initCharFromDirProps(void);
115 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer);
117 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels);
119 /* regression tests ---------------------------------------------------------*/
122 addComplexTest(TestNode** root) {
123 addTest(root, testCharFromDirProp, "complex/bidi/TestCharFromDirProp");
124 addTest(root, testBidi, "complex/bidi/TestBidi");
125 addTest(root, testInverse, "complex/bidi/TestInverse");
126 addTest(root, testReorder,"complex/bidi/TestReorder");
127 addTest(root, testFailureRecovery,"complex/bidi/TestFailureRecovery");
128 addTest(root, testMultipleParagraphs,"complex/bidi/TestMultipleParagraphs");
129 addTest(root, testReorderingMode, "complex/bidi/TestReorderingMode");
130 addTest(root, testReorderRunsOnly, "complex/bidi/TestReorderRunsOnly");
131 addTest(root, testStreaming, "complex/bidi/TestStreaming");
132 addTest(root, testClassOverride, "complex/bidi/TestClassOverride");
133 addTest(root, testGetBaseDirection, "complex/bidi/testGetBaseDirection");
134 addTest(root, testContext, "complex/bidi/testContext");
135 addTest(root, testBracketOverflow, "complex/bidi/TestBracketOverflow");
137 addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest");
138 addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef");
139 addTest(root, doTashkeelSpecialVLTRArabicShapingTest, "complex/arabic-shaping/tashkeel");
140 addTest(root, doLOGICALArabicDeShapingTest, "complex/arabic-shaping/unshaping");
141 addTest(root, doArabicShapingTestForBug5421, "complex/arabic-shaping/bug-5421");
142 addTest(root, doTailTest, "complex/arabic-shaping/tailtest");
143 addTest(root, doArabicShapingTestForBug8703, "complex/arabic-shaping/bug-8703");
144 addTest(root, testReorderArabicMathSymbols, "complex/bidi/bug-9024");
145 addTest(root, doArabicShapingTestForBug9024, "complex/arabic-shaping/bug-9024");
149 testCharFromDirProp(void) {
150 /* verify that the exemplar characters have the expected bidi classes */
153 log_verbose("\nEntering TestCharFromDirProp\n\n");
154 initCharFromDirProps();
156 for(i=0; i<U_CHAR_DIRECTION_COUNT; ++i) {
157 if(u_charDirection(charFromDirProp[i])!=(UCharDirection)i) {
158 log_err("\nu_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n",
159 i, charFromDirProp[i], u_charDirection(charFromDirProp[i]), i);
162 log_verbose("\nExiting TestCharFromDirProp\n\n");
167 UBiDi *pBiDi, *pLine=NULL;
168 UErrorCode errorCode=U_ZERO_ERROR;
170 log_verbose("\nEntering TestBidi\n\n");
172 pBiDi=ubidi_openSized(MAXLEN, 0, &errorCode);
176 doTests(pBiDi, pLine, FALSE);
177 doTests(pBiDi, pLine, TRUE);
179 log_err("ubidi_open() returned NULL, out of memory\n");
182 log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode));
193 log_verbose("\nExiting TestBidi\n\n");
197 doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst) {
199 UChar string[MAXLEN];
200 UErrorCode errorCode;
202 UBiDiLevel paraLevel;
204 for(testNumber=0; testNumber<bidiTestCount; ++testNumber) {
205 errorCode=U_ZERO_ERROR;
206 getStringFromDirProps(tests[testNumber].text, tests[testNumber].length, string);
207 paraLevel=tests[testNumber].paraLevel;
208 ubidi_setPara(pBiDi, string, -1, paraLevel, NULL, &errorCode);
209 if(U_SUCCESS(errorCode)) {
210 log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n",
211 testNumber, paraLevel, ubidi_getDirection(pBiDi), paraLevel);
212 lineStart=tests[testNumber].lineStart;
214 doTest(pBiDi, testNumber, tests+testNumber, 0, countRunsFirst);
216 ubidi_setLine(pBiDi, lineStart, tests[testNumber].lineLimit, pLine, &errorCode);
217 if(U_SUCCESS(errorCode)) {
218 log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n",
219 lineStart, tests[testNumber].lineLimit, ubidi_getDirection(pLine), ubidi_getParaLevel(pLine));
220 doTest(pLine, testNumber, tests+testNumber, lineStart, countRunsFirst);
222 log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n",
223 testNumber, lineStart, tests[testNumber].lineLimit, myErrorName(errorCode));
227 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
228 testNumber, paraLevel, myErrorName(errorCode));
233 static const char columns[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
235 #define TABLE_SIZE 256
236 static UBool tablesInitialized = FALSE;
237 static UChar pseudoToUChar[TABLE_SIZE];
238 static uint8_t UCharToPseudo[TABLE_SIZE]; /* used for Unicode chars < 0x0100 */
239 static uint8_t UCharToPseud2[TABLE_SIZE]; /* used for Unicode chars >=0x0100 */
241 static void buildPseudoTables(void)
243 The rules for pseudo-Bidi are as follows:
251 - A-F == Arabic Letters 0631-0636
252 - G-V == Hebrew letters 05d7-05e6
253 - W-Z == Unassigned RTL 08d0-08d3
254 - 0-5 == western digits 0030-0035
255 - 6-9 == Arabic-Indic digits 0666-0669
256 - ` == Combining Grave Accent 0300 (NSM)
257 - ~ == Delete 007f (BN)
258 - | == Paragraph Separator 2029 (B)
259 - _ == Info Separator 1 001f (S)
260 All other characters represent themselves as Latin-1, with the corresponding
267 /* initialize all tables to unknown */
268 for (i=0; i < TABLE_SIZE; i++) {
269 pseudoToUChar[i] = 0xFFFD;
270 UCharToPseudo[i] = '?';
271 UCharToPseud2[i] = '?';
273 /* initialize non letters or digits */
274 pseudoToUChar[(uint8_t) 0 ] = 0x0000; UCharToPseudo[0x00] = (uint8_t) 0 ;
275 pseudoToUChar[(uint8_t)' '] = 0x0020; UCharToPseudo[0x20] = (uint8_t)' ';
276 pseudoToUChar[(uint8_t)'!'] = 0x0021; UCharToPseudo[0x21] = (uint8_t)'!';
277 pseudoToUChar[(uint8_t)'"'] = 0x0022; UCharToPseudo[0x22] = (uint8_t)'"';
278 pseudoToUChar[(uint8_t)'#'] = 0x0023; UCharToPseudo[0x23] = (uint8_t)'#';
279 pseudoToUChar[(uint8_t)'$'] = 0x0024; UCharToPseudo[0x24] = (uint8_t)'$';
280 pseudoToUChar[(uint8_t)'%'] = 0x0025; UCharToPseudo[0x25] = (uint8_t)'%';
281 pseudoToUChar[(uint8_t)'\'']= 0x0027; UCharToPseudo[0x27] = (uint8_t)'\'';
282 pseudoToUChar[(uint8_t)'('] = 0x0028; UCharToPseudo[0x28] = (uint8_t)'(';
283 pseudoToUChar[(uint8_t)')'] = 0x0029; UCharToPseudo[0x29] = (uint8_t)')';
284 pseudoToUChar[(uint8_t)'*'] = 0x002A; UCharToPseudo[0x2A] = (uint8_t)'*';
285 pseudoToUChar[(uint8_t)'+'] = 0x002B; UCharToPseudo[0x2B] = (uint8_t)'+';
286 pseudoToUChar[(uint8_t)','] = 0x002C; UCharToPseudo[0x2C] = (uint8_t)',';
287 pseudoToUChar[(uint8_t)'-'] = 0x002D; UCharToPseudo[0x2D] = (uint8_t)'-';
288 pseudoToUChar[(uint8_t)'.'] = 0x002E; UCharToPseudo[0x2E] = (uint8_t)'.';
289 pseudoToUChar[(uint8_t)'/'] = 0x002F; UCharToPseudo[0x2F] = (uint8_t)'/';
290 pseudoToUChar[(uint8_t)':'] = 0x003A; UCharToPseudo[0x3A] = (uint8_t)':';
291 pseudoToUChar[(uint8_t)';'] = 0x003B; UCharToPseudo[0x3B] = (uint8_t)';';
292 pseudoToUChar[(uint8_t)'<'] = 0x003C; UCharToPseudo[0x3C] = (uint8_t)'<';
293 pseudoToUChar[(uint8_t)'='] = 0x003D; UCharToPseudo[0x3D] = (uint8_t)'=';
294 pseudoToUChar[(uint8_t)'>'] = 0x003E; UCharToPseudo[0x3E] = (uint8_t)'>';
295 pseudoToUChar[(uint8_t)'?'] = 0x003F; UCharToPseudo[0x3F] = (uint8_t)'?';
296 pseudoToUChar[(uint8_t)'\\']= 0x005C; UCharToPseudo[0x5C] = (uint8_t)'\\';
297 /* initialize specially used characters */
298 pseudoToUChar[(uint8_t)'`'] = 0x0300; UCharToPseud2[0x00] = (uint8_t)'`'; /* NSM */
299 pseudoToUChar[(uint8_t)'@'] = 0x200E; UCharToPseud2[0x0E] = (uint8_t)'@'; /* LRM */
300 pseudoToUChar[(uint8_t)'&'] = 0x200F; UCharToPseud2[0x0F] = (uint8_t)'&'; /* RLM */
301 pseudoToUChar[(uint8_t)'_'] = 0x001F; UCharToPseudo[0x1F] = (uint8_t)'_'; /* S */
302 pseudoToUChar[(uint8_t)'|'] = 0x2029; UCharToPseud2[0x29] = (uint8_t)'|'; /* B */
303 pseudoToUChar[(uint8_t)'['] = 0x202A; UCharToPseud2[0x2A] = (uint8_t)'['; /* LRE */
304 pseudoToUChar[(uint8_t)']'] = 0x202B; UCharToPseud2[0x2B] = (uint8_t)']'; /* RLE */
305 pseudoToUChar[(uint8_t)'^'] = 0x202C; UCharToPseud2[0x2C] = (uint8_t)'^'; /* PDF */
306 pseudoToUChar[(uint8_t)'{'] = 0x202D; UCharToPseud2[0x2D] = (uint8_t)'{'; /* LRO */
307 pseudoToUChar[(uint8_t)'}'] = 0x202E; UCharToPseud2[0x2E] = (uint8_t)'}'; /* RLO */
308 pseudoToUChar[(uint8_t)'~'] = 0x007F; UCharToPseudo[0x7F] = (uint8_t)'~'; /* BN */
309 /* initialize western digits */
310 for (i = 0, uchar = 0x0030; i < 6; i++, uchar++) {
311 c = (uint8_t)columns[i];
312 pseudoToUChar[c] = uchar;
313 UCharToPseudo[uchar & 0x00ff] = c;
315 /* initialize Hindi digits */
316 for (i = 6, uchar = 0x0666; i < 10; i++, uchar++) {
317 c = (uint8_t)columns[i];
318 pseudoToUChar[c] = uchar;
319 UCharToPseud2[uchar & 0x00ff] = c;
321 /* initialize Arabic letters */
322 for (i = 10, uchar = 0x0631; i < 16; i++, uchar++) {
323 c = (uint8_t)columns[i];
324 pseudoToUChar[c] = uchar;
325 UCharToPseud2[uchar & 0x00ff] = c;
327 /* initialize Hebrew letters */
328 for (i = 16, uchar = 0x05D7; i < 32; i++, uchar++) {
329 c = (uint8_t)columns[i];
330 pseudoToUChar[c] = uchar;
331 UCharToPseud2[uchar & 0x00ff] = c;
333 /* initialize Unassigned code points */
334 for (i = 32, uchar=0x08D0; i < 36; i++, uchar++) {
335 c = (uint8_t)columns[i];
336 pseudoToUChar[c] = uchar;
337 UCharToPseud2[uchar & 0x00ff] = c;
339 /* initialize Latin lower case letters */
340 for (i = 36, uchar = 0x0061; i < 62; i++, uchar++) {
341 c = (uint8_t)columns[i];
342 pseudoToUChar[c] = uchar;
343 UCharToPseudo[uchar & 0x00ff] = c;
345 tablesInitialized = TRUE;
348 /*----------------------------------------------------------------------*/
350 static int pseudoToU16(const int length, const char * input, UChar * output)
351 /* This function converts a pseudo-Bidi string into a UChar string.
352 It returns the length of the UChar string.
356 if (!tablesInitialized) {
359 for (i = 0; i < length; i++)
360 output[i] = pseudoToUChar[(uint8_t)input[i]];
365 /*----------------------------------------------------------------------*/
367 static int u16ToPseudo(const int length, const UChar * input, char * output)
368 /* This function converts a UChar string into a pseudo-Bidi string.
369 It returns the length of the pseudo-Bidi string.
374 if (!tablesInitialized) {
377 for (i = 0; i < length; i++)
380 output[i] = uchar < 0x0100 ? UCharToPseudo[uchar] :
381 UCharToPseud2[uchar & 0x00ff];
383 output[length] = '\0';
387 static char * formatLevels(UBiDi *bidi, char *buffer) {
388 UErrorCode ec = U_ZERO_ERROR;
389 const UBiDiLevel* gotLevels = ubidi_getLevels(bidi, &ec);
390 int len = ubidi_getLength(bidi);
395 strcpy(buffer, "BAD LEVELS");
398 for (i=0; i<len; i++) {
400 if (k >= sizeof(columns))
409 static const char *reorderingModeNames[] = {
410 "UBIDI_REORDER_DEFAULT",
411 "UBIDI_REORDER_NUMBERS_SPECIAL",
412 "UBIDI_REORDER_GROUP_NUMBERS_WITH_R",
413 "UBIDI_REORDER_RUNS_ONLY",
414 "UBIDI_REORDER_INVERSE_NUMBERS_AS_L",
415 "UBIDI_REORDER_INVERSE_LIKE_DIRECT",
416 "UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL"};
418 static char *reorderingOptionNames(char *buffer, int options) {
420 if (options & UBIDI_OPTION_INSERT_MARKS) {
421 strcat(buffer, " UBIDI_OPTION_INSERT_MARKS");
423 if (options & UBIDI_OPTION_REMOVE_CONTROLS) {
424 strcat(buffer, " UBIDI_OPTION_REMOVE_CONTROLS");
426 if (options & UBIDI_OPTION_STREAMING) {
427 strcat(buffer, " UBIDI_OPTION_STREAMING");
432 static void printCaseInfo(UBiDi *bidi, const char *src, const char *dst)
433 /* src and dst are char arrays encoded as pseudo Bidi */
435 /* Since calls to log_err with a \n within the pattern increment the
436 * error count, new lines are issued via fputs, except when we want the
437 * increment to happen.
439 UErrorCode errorCode=U_ZERO_ERROR;
440 int32_t i, length = ubidi_getProcessedLength(bidi);
441 const UBiDiLevel *levels;
442 char levelChars[MAXLEN];
446 log_err("========================================"); fputs("\n", stderr);
447 levels = ubidi_getLevels(bidi, &errorCode);
448 if (U_FAILURE(errorCode)) {
449 strcpy(levelChars, "BAD LEVELS");
451 log_err("Processed length: %d", length); fputs("\n", stderr);
452 for (i = 0; i < length; i++) {
454 if (lev < sizeof(columns)) {
455 levelChars[i] = columns[lev];
460 levelChars[length] = 0;
462 log_err("Levels: %s", levelChars); fputs("\n", stderr);
463 log_err("Source: %s", src); fputs("\n", stderr);
464 log_err("Result: %s", dst); fputs("\n", stderr);
465 log_err("Direction: %d", ubidi_getDirection(bidi)); fputs("\n", stderr);
466 log_err("paraLevel: %d", ubidi_getParaLevel(bidi)); fputs("\n", stderr);
467 i = ubidi_getReorderingMode(bidi);
468 log_err("reorderingMode: %d = %s", i, reorderingModeNames[i]);
470 i = ubidi_getReorderingOptions(bidi);
471 log_err("reorderingOptions: %d = %s", i, reorderingOptionNames(buffer, i));
473 runCount = ubidi_countRuns(bidi, &errorCode);
474 if (U_FAILURE(errorCode)) {
475 log_err( "BAD RUNS");
477 log_err("Runs: %d => logicalStart.length/level: ", runCount);
478 for (i = 0; i < runCount; i++) {
481 dir = ubidi_getVisualRun(bidi, i, &start, &len);
482 log_err(" %d.%d/%d", start, len, dir);
488 static UBool matchingPair(UBiDi *bidi, int32_t i, char c1, char c2)
490 /* No test for []{} since they have special meaning for pseudo Bidi */
491 static char mates1Chars[] = "<>()";
492 static char mates2Chars[] = "><)(";
499 /* For UBIDI_REORDER_RUNS_ONLY, it would not be correct to check levels[i],
500 so we use the appropriate run's level, which is good for all cases.
502 ubidi_getLogicalRun(bidi, i, NULL, &level);
503 if ((level & 1) == 0) {
506 len = strlen(mates1Chars);
507 for (k = 0; k < len; k++) {
508 if ((c1 == mates1Chars[k]) && (c2 == mates2Chars[k])) {
515 static UBool checkWhatYouCan(UBiDi *bidi, const char *srcChars, const char *dstChars)
516 /* srcChars and dstChars are char arrays encoded as pseudo Bidi */
518 int32_t i, idx, logLimit, visLimit;
519 UBool testOK, errMap, errDst;
520 UErrorCode errorCode=U_ZERO_ERROR;
521 int32_t visMap[MAXLEN];
522 int32_t logMap[MAXLEN];
523 char accumSrc[MAXLEN];
524 char accumDst[MAXLEN];
525 ubidi_getVisualMap(bidi, visMap, &errorCode);
526 ubidi_getLogicalMap(bidi, logMap, &errorCode);
527 if (U_FAILURE(errorCode)) {
528 log_err("Error #1 invoking ICU within checkWhatYouCan\n");
533 errMap = errDst = FALSE;
534 logLimit = ubidi_getProcessedLength(bidi);
535 visLimit = ubidi_getResultLength(bidi);
536 memset(accumSrc, '?', logLimit);
537 memset(accumDst, '?', visLimit);
539 for (i = 0; i < logLimit; i++) {
540 idx = ubidi_getVisualIndex(bidi, i, &errorCode);
541 if (idx != logMap[i]) {
544 if (idx == UBIDI_MAP_NOWHERE) {
547 if (idx >= visLimit) {
550 accumDst[idx] = srcChars[i];
551 if (!matchingPair(bidi, i, srcChars[i], dstChars[idx])) {
555 accumDst[visLimit] = 0;
556 if (U_FAILURE(errorCode)) {
557 log_err("Error #2 invoking ICU within checkWhatYouCan\n");
562 printCaseInfo(bidi, srcChars, dstChars);
565 log_err("Mismatch between getLogicalMap() and getVisualIndex()\n");
567 for (i = 0; i < logLimit; i++) {
568 log_err(" %d", logMap[i]);
572 for (i = 0; i < logLimit; i++) {
573 log_err(" %d", ubidi_getVisualIndex(bidi, i, &errorCode));
579 printCaseInfo(bidi, srcChars, dstChars);
582 log_err("Source does not map to Result\n");
583 log_err("We got: %s", accumDst); fputs("\n", stderr);
586 errMap = errDst = FALSE;
587 for (i = 0; i < visLimit; i++) {
588 idx = ubidi_getLogicalIndex(bidi, i, &errorCode);
589 if (idx != visMap[i]) {
592 if (idx == UBIDI_MAP_NOWHERE) {
595 if (idx >= logLimit) {
598 accumSrc[idx] = dstChars[i];
599 if (!matchingPair(bidi, idx, srcChars[idx], dstChars[i])) {
603 accumSrc[logLimit] = 0;
604 if (U_FAILURE(errorCode)) {
605 log_err("Error #3 invoking ICU within checkWhatYouCan\n");
610 printCaseInfo(bidi, srcChars, dstChars);
613 log_err("Mismatch between getVisualMap() and getLogicalIndex()\n");
615 for (i = 0; i < visLimit; i++) {
616 log_err(" %d", visMap[i]);
620 for (i = 0; i < visLimit; i++) {
621 log_err(" %d", ubidi_getLogicalIndex(bidi, i, &errorCode));
627 printCaseInfo(bidi, srcChars, dstChars);
630 log_err("Result does not map to Source\n");
631 log_err("We got: %s", accumSrc);
639 static const char* const logicalOrder[] ={
641 "del(QDVT) add(BVDL)",
642 "del(PQ)add(R.S.)T)U.&",
643 "del(LV)add(L.V.) L.V.&",
644 "day 0 R DPDHRVR dayabbr",
645 "day 1 H DPHPDHDA dayabbr",
646 "day 2 L DPBLENDA dayabbr",
647 "day 3 J DPJQVM dayabbr",
648 "day 4 I DPIQNF dayabbr",
649 "day 5 M DPMEG dayabbr",
653 static const char* const visualOrder[]={
655 "del(TVDQ) add(LDVB)",
656 "del(QP)add(S.R.)&.U(T", /* updated for Unicode 6.3 matching brackets */
657 "del(VL)add(V.L.) &.V.L", /* updated for Unicode 6.3 matching brackets */
658 "day 0 RVRHDPD R dayabbr",
659 "day 1 ADHDPHPD H dayabbr",
660 "day 2 ADNELBPD L dayabbr",
661 "day 3 MVQJPD J dayabbr",
662 "day 4 FNQIPD I dayabbr",
663 "day 5 GEMPD M dayabbr",
667 static const char* const visualOrder1[]={
669 ")BVDL(dda )QDVT(led",
670 "T(U.&).R.S(dda)PQ(led", /* updated for Unicode 6.3 matching brackets */
671 "L.V.& ).L.V(dda)LV(led", /* updated for Unicode 6.3 matching brackets */
672 "rbbayad R DPDHRVR 0 yad",
673 "rbbayad H DPHPDHDA 1 yad",
674 "rbbayad L DPBLENDA 2 yad",
675 "rbbayad J DPJQVM 3 yad",
676 "rbbayad I DPIQNF 4 yad",
677 "rbbayad M DPMEG 5 yad",
682 static const char* const visualOrder2[]={
683 "@)@K.C.&@(dda)@KC@(led",
684 "@)@BVDL@(dda )@QDVT@(led",
685 "R.S.)T)U.&@(dda)@PQ@(led",
686 "L.V.) L.V.&@(dda)@LV@(led",
687 "rbbayad @R DPDHRVR@ 0 yad",
688 "rbbayad @H DPHPDHDA@ 1 yad",
689 "rbbayad @L DPBLENDA@ 2 yad",
690 "rbbayad @J DPJQVM@ 3 yad",
691 "rbbayad @I DPIQNF@ 4 yad",
692 "rbbayad @M DPMEG@ 5 yad",
696 static const char* const visualOrder3[]={
698 ")BVDL(ddaQDVT) (led",
699 "R.S.)T)U.&(PQ)dda(led",
700 "L.V.) L.V.&(LV)dda(led",
701 "rbbayad DPDHRVR R 0 yad",
702 "rbbayad DPHPDHDA H 1 yad",
703 "rbbayad DPBLENDA L 2 yad",
704 "rbbayad DPJQVM J 3 yad",
705 "rbbayad DPIQNF I 4 yad",
706 "rbbayad DPMEG M 5 yad",
710 static const char* const visualOrder4[]={
712 "del( (TVDQadd(LDVB)",
713 "del(add(QP(.U(T(.S.R",
714 "del(add(VL(.V.L (.V.L",
715 "day 0 R RVRHDPD dayabbr",
716 "day 1 H ADHDPHPD dayabbr",
717 "day 2 L ADNELBPD dayabbr",
718 "day 3 J MVQJPD dayabbr",
719 "day 4 I FNQIPD dayabbr",
720 "day 5 M GEMPD dayabbr",
724 char formatChars[MAXLEN];
725 UErrorCode ec = U_ZERO_ERROR;
726 UBiDi* bidi = ubidi_open();
729 log_verbose("\nEntering TestReorder\n\n");
731 for(i=0;i<LENGTHOF(logicalOrder);i++){
732 int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
733 int32_t destSize = srcSize*2;
737 log_verbose("Testing L2V #1 for case %d\n", i);
738 pseudoToU16(srcSize,logicalOrder[i],src);
740 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
742 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
743 i, UBIDI_DEFAULT_LTR, u_errorName(ec));
745 /* try pre-flighting */
746 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
747 if(ec!=U_BUFFER_OVERFLOW_ERROR){
748 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
749 }else if(destSize!=srcSize){
750 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
754 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
755 u16ToPseudo(destSize,dest,chars);
756 if(destSize!=srcSize){
757 log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
758 }else if(strcmp(visualOrder[i],chars)!=0){
759 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
760 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
761 logicalOrder[i],visualOrder[i],chars,formatLevels(bidi, formatChars),i);
763 checkWhatYouCan(bidi, logicalOrder[i], chars);
766 for(i=0;i<LENGTHOF(logicalOrder);i++){
767 int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
768 int32_t destSize = srcSize*2;
772 log_verbose("Testing L2V #2 for case %d\n", i);
773 pseudoToU16(srcSize,logicalOrder[i],src);
775 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
777 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
778 i, UBIDI_DEFAULT_LTR, u_errorName(ec));
780 /* try pre-flighting */
781 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
782 if(ec!=U_BUFFER_OVERFLOW_ERROR){
783 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
784 }else if(destSize!=srcSize){
785 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
789 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
790 u16ToPseudo(destSize,dest,chars);
791 if(destSize!=srcSize){
792 log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
793 }else if(strcmp(visualOrder1[i],chars)!=0){
794 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE.\n"
795 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
796 logicalOrder[i],visualOrder1[i],chars,formatLevels(bidi, formatChars),i);
800 for(i=0;i<LENGTHOF(logicalOrder);i++){
801 int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
802 int32_t destSize = srcSize*2;
806 log_verbose("Testing V2L #3 for case %d\n", i);
807 pseudoToU16(srcSize,logicalOrder[i],src);
809 ubidi_setInverse(bidi,TRUE);
810 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
812 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
813 i, UBIDI_DEFAULT_LTR, u_errorName(ec));
815 /* try pre-flighting */
816 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
817 if(ec!=U_BUFFER_OVERFLOW_ERROR){
818 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
822 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
823 u16ToPseudo(destSize,dest,chars);
824 if(strcmp(visualOrder2[i],chars)!=0){
825 log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE.\n"
826 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
827 logicalOrder[i],visualOrder2[i],chars,formatLevels(bidi, formatChars),i);
830 /* Max Explicit level */
831 for(i=0;i<LENGTHOF(logicalOrder);i++){
832 int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
833 int32_t destSize = srcSize*2;
837 UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
838 log_verbose("Testing V2L #4 for case %d\n", i);
839 pseudoToU16(srcSize,logicalOrder[i],src);
841 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
843 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
844 i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
846 /* try pre-flighting */
847 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_OUTPUT_REVERSE,&ec);
848 if(ec!=U_BUFFER_OVERFLOW_ERROR){
849 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
850 }else if(destSize!=srcSize){
851 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
855 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_OUTPUT_REVERSE,&ec);
856 u16ToPseudo(destSize,dest,chars);
857 if(destSize!=srcSize){
858 log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize );
859 }else if(strcmp(visualOrder3[i],chars)!=0){
860 log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE.\n"
861 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
862 logicalOrder[i],visualOrder3[i],chars,formatLevels(bidi, formatChars),i);
865 for(i=0;i<LENGTHOF(logicalOrder);i++){
866 int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
867 int32_t destSize = srcSize*2;
871 UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
872 log_verbose("Testing V2L #5 for case %d\n", i);
873 pseudoToU16(srcSize,logicalOrder[i],src);
875 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
877 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
878 i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
880 /* try pre-flighting */
881 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
882 if(ec!=U_BUFFER_OVERFLOW_ERROR){
883 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
887 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
888 u16ToPseudo(destSize,dest,chars);
889 if(strcmp(visualOrder4[i],chars)!=0){
890 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS.\n"
891 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
892 logicalOrder[i],visualOrder4[i],chars,formatLevels(bidi, formatChars),i);
897 log_verbose("\nExiting TestReorder\n\n");
901 testReorderArabicMathSymbols(void) {
902 static const UChar logicalOrder[][MAXLEN]={
903 /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
904 {0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
905 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
906 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
907 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
908 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
909 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
910 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
911 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B},
912 /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
913 {0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
914 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
915 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
916 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
917 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
918 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
919 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
920 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B},
921 /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
922 {0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
923 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
924 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
925 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
926 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
927 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
928 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
929 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB},
930 /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
931 {0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
932 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
933 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
934 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
935 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
936 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
937 0xD83B, 0xDE39, 0xD83B, 0xDE3B},
938 /* Arabic mathematical Symbols - Tailed Symbols */
939 {0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
940 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
941 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
942 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F}
944 static const UChar visualOrder[][MAXLEN]={
945 /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
946 {0xD83B, 0xDE1B, 0xD83B, 0xDE1A, 0xD83B, 0xDE19, 0x20,
947 0xD83B, 0xDE18, 0xD83B, 0xDE17, 0xD83B, 0xDE16, 0x20,
948 0xD83B, 0xDE15, 0xD83B, 0xDE14, 0xD83B, 0xDE13, 0xD83B, 0xDE12, 0x20,
949 0xD83B, 0xDE11, 0xD83B, 0xDE10, 0xD83B, 0xDE0F, 0xD83B, 0xDE0E, 0x20,
950 0xD83B, 0xDE0D, 0xD83B, 0xDE0C, 0xD83B, 0xDE0B, 0xD83B, 0xDE0A, 0x20,
951 0xD83B, 0xDE09, 0xD83B, 0xDE08, 0xD83B, 0xDE07, 0x20,
952 0xD83B, 0xDE06, 0xD83B, 0xDE05, 0xD83B, 0xDE24, 0x20,
953 0xD83B, 0xDE03, 0xD83B, 0xDE02, 0xD83B, 0xDE01, 0xD83B, 0xDE00},
954 /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
955 {0xD83B, 0xDE9B, 0xD83B, 0xDE9A, 0xD83B, 0xDE99, 0x20,
956 0xD83B, 0xDE98, 0xD83B, 0xDE97, 0xD83B, 0xDE96, 0x20,
957 0xD83B, 0xDE95, 0xD83B, 0xDE94, 0xD83B, 0xDE93, 0xD83B, 0xDE92, 0x20,
958 0xD83B, 0xDE91, 0xD83B, 0xDE90, 0xD83B, 0xDE8F, 0xD83B, 0xDE8E, 0x20,
959 0xD83B, 0xDE8D, 0xD83B, 0xDE8C, 0xD83B, 0xDE8B, 0x20,
960 0xD83B, 0xDE89, 0xD83B, 0xDE88, 0xD83B, 0xDE87, 0x20,
961 0xD83B, 0xDE86, 0xD83B, 0xDE85, 0xD83B, 0xDE84, 0x20,
962 0xD83B, 0xDE83, 0xD83B, 0xDE82, 0xD83B, 0xDE81, 0xD83B, 0xDE80},
963 /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
964 {0xD83B, 0xDEBB, 0xD83B, 0xDEBA, 0xD83B, 0xDEB9, 0x20,
965 0xD83B, 0xDEB8, 0xD83B, 0xDEB7, 0xD83B, 0xDEB6, 0x20,
966 0xD83B, 0xDEB5, 0xD83B, 0xDEB4, 0xD83B, 0xDEB3, 0xD83B, 0xDEB2, 0x20,
967 0xD83B, 0xDEB1, 0xD83B, 0xDEB0, 0xD83B, 0xDEAF, 0xD83B, 0xDEAE, 0x20,
968 0xD83B, 0xDEAD, 0xD83B, 0xDEAC, 0xD83B, 0xDEAB, 0x20,
969 0xD83B, 0xDEA9, 0xD83B, 0xDEA8, 0xD83B, 0xDEA7, 0x20,
970 0xD83B, 0xDEA6, 0xD83B, 0xDEA5, 0x20,
971 0xD83B, 0xDEA3, 0xD83B, 0xDEA2, 0xD83B, 0xDEA1},
972 /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
973 {0xD83B, 0xDE3B, 0xD83B, 0xDE39, 0x20,
974 0xD83B, 0xDE37, 0xD83B, 0xDE36, 0x20,
975 0xD83B, 0xDE35, 0xD83B, 0xDE34, 0xD83B, 0xDE32, 0x20,
976 0xD83B, 0xDE31, 0xD83B, 0xDE30, 0xD83B, 0xDE2F, 0xD83B, 0xDE2E, 0x20,
977 0xD83B, 0xDE2D, 0xD83B, 0xDE2C, 0xD83B, 0xDE2B, 0xD83B, 0xDE2A, 0x20,
978 0xD83B, 0xDE29, 0xD83B, 0xDE27, 0x20,
979 0xD83B, 0xDE22, 0xD83B, 0xDE21},
980 /* Arabic mathematical Symbols - Tailed Symbols */
981 {0xD83B, 0xDE5F, 0xD83B, 0xDE5D, 0xD83B, 0xDE5B, 0xD83B, 0xDE59, 0x20,
982 0xD83B, 0xDE57, 0xD83B, 0xDE54, 0xD83B, 0xDE52, 0xD83B, 0xDE51, 0x20,
983 0xD83B, 0xDE4F, 0xD83B, 0xDE4E, 0xD83B, 0xDE4D, 0x20,
984 0xD83B, 0xDE4B, 0xD83B, 0xDE49, 0xD83B, 0xDE47, 0xD83B, 0xDE42}
986 char formatChars[MAXLEN];
987 UErrorCode ec = U_ZERO_ERROR;
988 UBiDi* bidi = ubidi_open();
991 log_verbose("\nEntering TestReorderArabicMathSymbols\n\n");
993 for(i=0;i<LENGTHOF(logicalOrder);i++){
994 int32_t srcSize = u_strlen(logicalOrder[i]);
995 int32_t destSize = srcSize*2;
997 log_verbose("Testing L2V #1 for case %d\n", i);
999 ubidi_setPara(bidi,logicalOrder[i],srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
1001 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
1002 i, UBIDI_DEFAULT_LTR, u_errorName(ec));
1004 /* try pre-flighting */
1005 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
1006 if(ec!=U_BUFFER_OVERFLOW_ERROR){
1007 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
1008 }else if(destSize!=srcSize){
1009 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
1013 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
1014 if(destSize!=srcSize){
1015 log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
1016 }else if(memcmp(dest, visualOrder[i], destSize*U_SIZEOF_UCHAR)!=0){
1017 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
1018 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
1019 logicalOrder[i],visualOrder[i],dest,formatLevels(bidi, formatChars),i);
1025 log_verbose("\nExiting TestReorderArabicMathSymbols\n\n");
1029 doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, int32_t lineStart, UBool countRunsFirst) {
1030 const uint8_t *dirProps=test->text+lineStart;
1031 const UBiDiLevel *levels=test->levels;
1032 const uint8_t *visualMap=test->visualMap;
1033 int32_t i, len=ubidi_getLength(pBiDi), logicalIndex, runCount = 0;
1034 UErrorCode errorCode=U_ZERO_ERROR;
1035 UBiDiLevel level, level2;
1037 if (countRunsFirst) {
1038 log_verbose("Calling ubidi_countRuns() first.\n");
1040 runCount = ubidi_countRuns(pBiDi, &errorCode);
1042 if(U_FAILURE(errorCode)) {
1043 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
1047 log_verbose("Calling ubidi_getLogicalMap() first.\n");
1050 _testReordering(pBiDi, testNumber);
1052 for(i=0; i<len; ++i) {
1053 log_verbose("%3d %3d %.*s%-3s @%d\n",
1054 i, ubidi_getLevelAt(pBiDi, i), ubidi_getLevelAt(pBiDi, i), levelString,
1055 dirPropNames[dirProps[i]],
1056 ubidi_getVisualIndex(pBiDi, i, &errorCode));
1059 log_verbose("\n-----levels:");
1060 for(i=0; i<len; ++i) {
1064 log_verbose(" %d", ubidi_getLevelAt(pBiDi, i));
1067 log_verbose("\n--reordered:");
1068 for(i=0; i<len; ++i) {
1072 log_verbose(" %d", ubidi_getVisualIndex(pBiDi, i, &errorCode));
1076 if(test->direction!=ubidi_getDirection(pBiDi)) {
1077 log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber, ubidi_getDirection(pBiDi));
1080 if(test->resultLevel!=ubidi_getParaLevel(pBiDi)) {
1081 log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber, ubidi_getParaLevel(pBiDi));
1084 for(i=0; i<len; ++i) {
1085 if(levels[i]!=ubidi_getLevelAt(pBiDi, i)) {
1086 log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d, expected %d\n", testNumber, i, ubidi_getLevelAt(pBiDi, i), levels[i]);
1091 for(i=0; i<len; ++i) {
1092 logicalIndex=ubidi_getVisualIndex(pBiDi, i, &errorCode);
1093 if(U_FAILURE(errorCode)) {
1094 log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
1097 if(visualMap[i]!=logicalIndex) {
1098 log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber, i, logicalIndex);
1103 if (! countRunsFirst) {
1104 runCount=ubidi_countRuns(pBiDi, &errorCode);
1105 if(U_FAILURE(errorCode)) {
1106 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
1111 for(logicalIndex=0; logicalIndex<len;) {
1112 level=ubidi_getLevelAt(pBiDi, logicalIndex);
1113 ubidi_getLogicalRun(pBiDi, logicalIndex, &logicalIndex, &level2);
1115 log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): "
1116 "wrong level %d instead of %d\n",
1117 testNumber, logicalIndex, level, level2);
1120 log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
1121 "compared to %d=ubidi_countRuns()\n",
1122 testNumber, ubidi_countRuns(pBiDi, &errorCode));
1127 log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
1128 "compared to %d=ubidi_getRunCount()\n",
1129 testNumber, ubidi_countRuns(pBiDi, &errorCode));
1133 log_verbose("\n\n");
1137 _testReordering(UBiDi *pBiDi, int testNumber) {
1139 logicalMap1[MAXLEN], logicalMap2[MAXLEN], logicalMap3[MAXLEN],
1140 visualMap1[MAXLEN], visualMap2[MAXLEN], visualMap3[MAXLEN], visualMap4[MAXLEN];
1141 UErrorCode errorCode=U_ZERO_ERROR;
1142 const UBiDiLevel *levels;
1143 int32_t i, length=ubidi_getLength(pBiDi),
1144 destLength=ubidi_getResultLength(pBiDi);
1145 int32_t runCount, visualIndex, logicalStart, runLength;
1152 /* get the logical and visual maps from the object */
1153 ubidi_getLogicalMap(pBiDi, logicalMap1, &errorCode);
1154 if(U_FAILURE(errorCode)) {
1155 log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
1159 ubidi_getVisualMap(pBiDi, visualMap1, &errorCode);
1160 if(U_FAILURE(errorCode)) {
1161 log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
1165 /* invert them both */
1166 ubidi_invertMap(logicalMap1, visualMap2, length);
1167 ubidi_invertMap(visualMap1, logicalMap2, destLength);
1169 /* get them from the levels array, too */
1170 levels=ubidi_getLevels(pBiDi, &errorCode);
1172 if(U_FAILURE(errorCode)) {
1173 log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
1177 ubidi_reorderLogical(levels, length, logicalMap3);
1178 ubidi_reorderVisual(levels, length, visualMap3);
1180 /* get the visual map from the runs, too */
1181 runCount=ubidi_countRuns(pBiDi, &errorCode);
1182 if(U_FAILURE(errorCode)) {
1183 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
1186 log_verbose("\n----%2d runs:", runCount);
1188 for(i=0; i<runCount; ++i) {
1189 odd=(UBool)ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength);
1190 log_verbose(" (%c @%d[%d])", odd ? 'R' : 'L', logicalStart, runLength);
1191 if(UBIDI_LTR==odd) {
1193 visualMap4[visualIndex++]=logicalStart++;
1194 } while(--runLength>0);
1196 logicalStart+=runLength; /* logicalLimit */
1198 visualMap4[visualIndex++]=--logicalStart;
1199 } while(--runLength>0);
1204 /* print all the maps */
1205 log_verbose("logical maps:\n");
1206 for(i=0; i<length; ++i) {
1207 log_verbose("%4d", logicalMap1[i]);
1210 for(i=0; i<length; ++i) {
1211 log_verbose("%4d", logicalMap2[i]);
1214 for(i=0; i<length; ++i) {
1215 log_verbose("%4d", logicalMap3[i]);
1218 log_verbose("\nvisual maps:\n");
1219 for(i=0; i<destLength; ++i) {
1220 log_verbose("%4d", visualMap1[i]);
1223 for(i=0; i<destLength; ++i) {
1224 log_verbose("%4d", visualMap2[i]);
1227 for(i=0; i<length; ++i) {
1228 log_verbose("%4d", visualMap3[i]);
1231 for(i=0; i<length; ++i) {
1232 log_verbose("%4d", visualMap4[i]);
1236 /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */
1237 for(i=0; i<length; ++i) {
1238 if(logicalMap1[i]!=logicalMap2[i]) {
1239 log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber, i);
1242 if(logicalMap1[i]!=logicalMap3[i]) {
1243 log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber, i);
1247 if(visualMap1[i]!=visualMap2[i]) {
1248 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber, i);
1251 if(visualMap1[i]!=visualMap3[i]) {
1252 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber, i);
1255 if(visualMap1[i]!=visualMap4[i]) {
1256 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber, i);
1260 if(logicalMap1[i]!=ubidi_getVisualIndex(pBiDi, i, &errorCode)) {
1261 log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber, i);
1264 if(U_FAILURE(errorCode)) {
1265 log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
1268 if(visualMap1[i]!=ubidi_getLogicalIndex(pBiDi, i, &errorCode)) {
1269 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber, i);
1272 if(U_FAILURE(errorCode)) {
1273 log_err("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
1279 #define RETURN_IF_BAD_ERRCODE(x) \
1280 if (U_FAILURE(errorCode)) { \
1281 log_err("\nbad errorCode %d at %s\n", errorCode, (x)); \
1285 #define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
1287 static void testGetBaseDirection(void) {
1293 /*Mixed Start with L*/
1294 stringMixedEnglishFirst[]={ 0x61, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 },
1295 /*Mixed Start with AL*/
1296 stringMixedArabicFirst[]={ 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
1297 /*Mixed Start with R*/
1298 stringMixedHebrewFirst[]={ 0x05EA, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
1299 /*All AL (Arabic. Persian)*/
1300 stringPersian[]={0x0698, 0x067E, 0x0686, 0x06AF, 0},
1301 /*All R (Hebrew etc.)*/
1302 stringHebrew[]={0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
1304 stringEnglish[]={0x71, 0x61, 0x66, 0},
1305 /*Mixed Start with weak AL an then L*/
1306 stringStartWeakAL[]={ 0x0663, 0x71, 0x61, 0x66, 0},
1307 /*Mixed Start with weak L and then AL*/
1308 stringStartWeakL[]={0x31, 0x0698, 0x067E, 0x0686, 0x06AF, 0},
1312 stringSurrogateChar[]={0xD800, 0xDC00, 0},
1314 stringInvalidUchar[]={-1},
1315 /*All weak L (English Digits)*/
1316 stringAllEnglishDigits[]={0x31, 0x32, 0x33, 0},
1317 /*All weak AL (Arabic Digits)*/
1318 stringAllArabicDigits[]={0x0663, 0x0664, 0x0665, 0},
1319 /*First L (English) others are R (Hebrew etc.) */
1320 stringFirstL[] = {0x71, 0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
1321 /*Last R (Hebrew etc.) others are weak L (English Digits)*/
1322 stringLastR[] = {0x31, 0x32, 0x33, 0x05F1, 0};
1324 static const struct {
1328 STRING_TEST_CASE(stringMixedEnglishFirst),
1329 STRING_TEST_CASE(stringMixedArabicFirst),
1330 STRING_TEST_CASE(stringMixedHebrewFirst),
1331 STRING_TEST_CASE(stringPersian),
1332 STRING_TEST_CASE(stringHebrew),
1333 STRING_TEST_CASE(stringEnglish),
1334 STRING_TEST_CASE(stringStartWeakAL),
1335 STRING_TEST_CASE(stringStartWeakL),
1336 STRING_TEST_CASE(stringEmpty),
1337 STRING_TEST_CASE(stringSurrogateChar),
1338 STRING_TEST_CASE(stringInvalidUchar),
1339 STRING_TEST_CASE(stringAllEnglishDigits),
1340 STRING_TEST_CASE(stringAllArabicDigits),
1341 STRING_TEST_CASE(stringFirstL),
1342 STRING_TEST_CASE(stringLastR),
1345 /* Expected results */
1346 static const UBiDiDirection expectedDir[] ={
1347 UBIDI_LTR, UBIDI_RTL, UBIDI_RTL,
1348 UBIDI_RTL, UBIDI_RTL, UBIDI_LTR,
1349 UBIDI_LTR, UBIDI_RTL, UBIDI_NEUTRAL,
1350 UBIDI_LTR, UBIDI_NEUTRAL, UBIDI_NEUTRAL,
1351 UBIDI_NEUTRAL, UBIDI_LTR, UBIDI_RTL
1354 log_verbose("testGetBaseDirection() with %u test cases ---\n",
1355 LENGTHOF(testCases));
1357 for(i=0; i<LENGTHOF(testCases); ++i) {
1358 dir = ubidi_getBaseDirection(testCases[i].s, testCases[i].length );
1359 log_verbose("Testing case %d\tReceived dir %d\n", i, dir);
1360 if (dir != expectedDir[i])
1361 log_err("\nFailed getBaseDirection case %d Expected %d \tReceived %d\n",
1362 i, expectedDir[i], dir);
1367 dir = ubidi_getBaseDirection(NULL, 3);
1368 if (dir != UBIDI_NEUTRAL )
1369 log_err("\nFailed getBaseDirection for NULL string " ,
1370 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
1371 /*All L- English string and length=-3 */
1372 dir = ubidi_getBaseDirection( stringEnglish, -3);
1373 if (dir != UBIDI_NEUTRAL )
1374 log_err("\nFailed getBaseDirection for string w length= -3 ",
1375 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
1376 /*All L- English string and length=-1 */
1377 dir = ubidi_getBaseDirection( stringEnglish, -1);
1378 if (dir != UBIDI_LTR )
1379 log_err("\nFailed getBaseDirection for English string w length= -1 ",
1380 "\nExpected %d \nReceived %d", UBIDI_LTR, dir);
1381 /*All AL- Persian string and length=-1 */
1382 dir = ubidi_getBaseDirection( stringPersian, -1);
1383 if (dir != UBIDI_RTL )
1384 log_err("\nFailed getBaseDirection for Persian string w length= -1 ",
1385 "\nExpected %d \nReceived %d", UBIDI_RTL, dir);
1386 /*All R- Hebrew string and length=-1 */
1387 dir = ubidi_getBaseDirection( stringHebrew, -1);
1388 if (dir != UBIDI_RTL )
1389 log_err("\nFailed getBaseDirection for Hebrew string w length= -1 ",
1390 "\nExpected %d \nReceived %d", UBIDI_RTL, dir);
1391 /*All weak L- English digits string and length=-1 */
1392 dir = ubidi_getBaseDirection(stringAllEnglishDigits, -1);
1393 if (dir != UBIDI_NEUTRAL )
1394 log_err("\nFailed getBaseDirection for English digits string w length= -1 ",
1395 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
1396 /*All weak AL- Arabic digits string and length=-1 */
1397 dir = ubidi_getBaseDirection(stringAllArabicDigits, -1);
1398 if (dir != UBIDI_NEUTRAL )
1399 log_err("\nFailed getBaseDirection for Arabic string w length= -1 ",
1400 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
1405 static void doMisc(void) {
1406 /* Miscellaneous tests to exercize less popular code paths */
1407 UBiDi *bidi, *bidiLine;
1408 UChar src[MAXLEN], dest[MAXLEN];
1409 int32_t srcLen, destLen, runCount, i;
1412 int32_t map[MAXLEN];
1413 UErrorCode errorCode=U_ZERO_ERROR;
1414 static const int32_t srcMap[6] = {0,1,-1,5,4};
1415 static const int32_t dstMap[6] = {0,1,-1,-1,4,3};
1417 bidi = ubidi_openSized(120, 66, &errorCode);
1419 log_err("Error with openSized(120, 66)\n");
1422 bidiLine = ubidi_open();
1424 log_err("Error with open()\n");
1428 destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode);
1430 log_err("\nwriteReverse should return zero length, ",
1431 "returned %d instead\n", destLen);
1433 RETURN_IF_BAD_ERRCODE("#1#");
1435 ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
1436 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1438 log_err("\nwriteReordered should return zero length, ",
1439 "returned %d instead\n", destLen);
1441 RETURN_IF_BAD_ERRCODE("#2#");
1443 srcLen = u_unescape("abc ", src, MAXLEN);
1444 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1445 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1446 for (i = 3; i < 6; i++) {
1447 level = ubidi_getLevelAt(bidiLine, i);
1448 if (level != UBIDI_RTL) {
1449 log_err("\nTrailing space at index %d should get paragraph level"
1450 "%d, got %d instead\n", i, UBIDI_RTL, level);
1453 RETURN_IF_BAD_ERRCODE("#3#");
1455 srcLen = u_unescape("abc def", src, MAXLEN);
1456 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1457 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1458 for (i = 3; i < 6; i++) {
1459 level = ubidi_getLevelAt(bidiLine, i);
1460 if (level != UBIDI_RTL) {
1461 log_err("\nTrailing space at index %d should get paragraph level"
1462 "%d, got %d instead\n", i, UBIDI_RTL, level);
1465 RETURN_IF_BAD_ERRCODE("#4#");
1467 srcLen = u_unescape("abcdefghi ", src, MAXLEN);
1468 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1469 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1470 for (i = 3; i < 6; i++) {
1471 level = ubidi_getLevelAt(bidiLine, i);
1473 log_err("\nTrailing char at index %d should get level 2, "
1474 "got %d instead\n", i, level);
1477 RETURN_IF_BAD_ERRCODE("#5#");
1479 ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS);
1480 srcLen = u_unescape("\\u200eabc def", src, MAXLEN);
1481 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1482 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1483 destLen = ubidi_getResultLength(bidiLine);
1485 log_err("\nWrong result length, should be 5, got %d\n", destLen);
1487 RETURN_IF_BAD_ERRCODE("#6#");
1489 srcLen = u_unescape("abcdefghi", src, MAXLEN);
1490 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1491 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1492 dir = ubidi_getDirection(bidiLine);
1493 if (dir != UBIDI_LTR) {
1494 log_err("\nWrong direction #1, should be %d, got %d\n",
1497 RETURN_IF_BAD_ERRCODE("#7#");
1499 ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
1500 runCount = ubidi_countRuns(bidi, &errorCode);
1501 if (runCount != 0) {
1502 log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount);
1504 RETURN_IF_BAD_ERRCODE("#8#");
1506 srcLen = u_unescape(" ", src, MAXLEN);
1507 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1508 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1509 runCount = ubidi_countRuns(bidiLine, &errorCode);
1510 if (runCount != 1) {
1511 log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount);
1513 RETURN_IF_BAD_ERRCODE("#9#");
1515 srcLen = u_unescape("a\\u05d0 bc", src, MAXLEN);
1516 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1517 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1518 dir = ubidi_getDirection(bidi);
1519 if (dir != UBIDI_MIXED) {
1520 log_err("\nWrong direction #2, should be %d, got %d\n",
1523 dir = ubidi_getDirection(bidiLine);
1524 if (dir != UBIDI_MIXED) {
1525 log_err("\nWrong direction #3, should be %d, got %d\n",
1528 runCount = ubidi_countRuns(bidiLine, &errorCode);
1529 if (runCount != 2) {
1530 log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount);
1532 RETURN_IF_BAD_ERRCODE("#10#");
1534 ubidi_invertMap(srcMap, map, 5);
1535 if (memcmp(dstMap, map, sizeof(dstMap))) {
1536 log_err("\nUnexpected inverted Map, got ");
1537 for (i = 0; i < 6; i++) {
1538 log_err("%d ", map[i]);
1543 /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
1544 srcLen = u_unescape("abc\\u200e", src, MAXLEN);
1545 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1546 destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
1547 UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode);
1548 if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) {
1549 log_err("\nWrong result #1, should be 'abc', got '%s'\n",
1550 aescstrdup(dest, destLen));
1552 RETURN_IF_BAD_ERRCODE("#11#");
1554 /* test inverse Bidi with marks and contextual orientation */
1555 ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
1556 ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
1557 ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1558 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1560 log_err("\nWrong result #2, length should be 0, got %d\n", destLen);
1562 RETURN_IF_BAD_ERRCODE("#12#");
1563 srcLen = u_unescape(" ", src, MAXLEN);
1564 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1565 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1566 if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
1567 log_err("\nWrong result #3, should be ' ', got '%s'\n",
1568 aescstrdup(dest, destLen));
1570 RETURN_IF_BAD_ERRCODE("#13#");
1571 srcLen = u_unescape("abc", src, MAXLEN);
1572 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1573 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1574 if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
1575 log_err("\nWrong result #4, should be 'abc', got '%s'\n",
1576 aescstrdup(dest, destLen));
1578 RETURN_IF_BAD_ERRCODE("#14#");
1579 srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN);
1580 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1581 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1582 srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN);
1583 if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) {
1584 log_err("\nWrong result #5, should be '%s', got '%s'\n",
1585 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1587 RETURN_IF_BAD_ERRCODE("#15#");
1588 srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN);
1589 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1590 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1591 srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN);
1592 if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) {
1593 log_err("\nWrong result #6, should be '%s', got '%s'\n",
1594 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1596 RETURN_IF_BAD_ERRCODE("#16#");
1597 srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN);
1598 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1599 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1600 srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN);
1601 if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) {
1602 log_err("\nWrong result #7, should be '%s', got '%s'\n",
1603 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1605 RETURN_IF_BAD_ERRCODE("#17#");
1606 srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN);
1607 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1608 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1609 srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN);
1610 if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) {
1611 log_err("\nWrong result #8, should be '%s', got '%s'\n",
1612 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1614 RETURN_IF_BAD_ERRCODE("#18#");
1615 ubidi_orderParagraphsLTR(bidi, TRUE);
1616 srcLen = u_unescape("\n\r \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r"
1617 "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n"
1618 "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN);
1619 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1620 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1621 srcLen = u_unescape("\n\r \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r"
1622 "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n"
1623 "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN);
1624 if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) {
1625 log_err("\nWrong result #9, should be '%s', got '%s'\n",
1626 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1628 RETURN_IF_BAD_ERRCODE("#19#");
1629 srcLen = u_unescape("\\u05d0 \t", src, MAXLEN);
1630 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1631 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1632 srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN);
1633 if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) {
1634 log_err("\nWrong result #10, should be '%s', got '%s'\n",
1635 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1637 RETURN_IF_BAD_ERRCODE("#20#");
1638 srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN);
1639 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1640 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1641 srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN);
1642 if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) {
1643 log_err("\nWrong result #11, should be '%s', got '%s'\n",
1644 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1646 RETURN_IF_BAD_ERRCODE("#21#");
1647 srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN);
1648 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1649 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1650 srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN);
1651 if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) {
1652 log_err("\nWrong result #12, should be '%s', got '%s'\n",
1653 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1655 RETURN_IF_BAD_ERRCODE("#22#");
1656 srcLen = u_unescape("ab \t", src, MAXLEN);
1657 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1658 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1659 srcLen = u_unescape("\\u200f\t ab", src, MAXLEN);
1660 if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) {
1661 log_err("\nWrong result #13, should be '%s', got '%s'\n",
1662 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1664 RETURN_IF_BAD_ERRCODE("#23#");
1666 /* check exceeding para level */
1668 bidi = ubidi_open();
1669 srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN);
1670 ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode);
1671 level = ubidi_getLevelAt(bidi, 2);
1672 if (level != UBIDI_MAX_EXPLICIT_LEVEL) {
1673 log_err("\nWrong level at index 2\n, should be %d, got %d\n", UBIDI_MAX_EXPLICIT_LEVEL, level);
1675 RETURN_IF_BAD_ERRCODE("#24#");
1677 /* check 1-char runs with RUNS_ONLY */
1678 ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY);
1679 srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN);
1680 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1681 runCount = ubidi_countRuns(bidi, &errorCode);
1682 if (runCount != 14) {
1683 log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount);
1685 RETURN_IF_BAD_ERRCODE("#25#");
1688 ubidi_close(bidiLine);
1692 testFailureRecovery(void) {
1693 UErrorCode errorCode;
1694 UBiDi *bidi, *bidiLine;
1698 UBiDiReorderingMode rm;
1699 static UBiDiLevel myLevels[3] = {6,5,4};
1701 log_verbose("\nEntering TestFailureRecovery\n\n");
1702 errorCode = U_FILE_ACCESS_ERROR;
1703 if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0) {
1704 log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n");
1706 if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0) {
1707 log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n");
1709 errorCode = U_ZERO_ERROR;
1710 if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1711 log_err("ubidi_writeReordered did not fail as expected\n");
1714 bidi = ubidi_open();
1715 srcLen = u_unescape("abc", src, MAXLEN);
1716 errorCode = U_ZERO_ERROR;
1717 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_LTR - 1, NULL, &errorCode);
1718 if (U_SUCCESS(errorCode)) {
1719 log_err("\nubidi_setPara did not fail when passed too big para level\n");
1721 errorCode = U_ZERO_ERROR;
1722 if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1723 log_err("ubidi_writeReverse did not fail as expected\n");
1725 bidiLine = ubidi_open();
1726 errorCode = U_ZERO_ERROR;
1727 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1728 if (U_SUCCESS(errorCode)) {
1729 log_err("\nubidi_setLine did not fail when called before valid setPara()\n");
1731 errorCode = U_ZERO_ERROR;
1732 srcLen = u_unescape("abc", src, MAXLEN);
1733 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR + 4, NULL, &errorCode);
1734 level = ubidi_getLevelAt(bidi, 3);
1736 log_err("\nubidi_getLevelAt did not fail when called with bad argument\n");
1738 errorCode = U_ZERO_ERROR;
1740 bidi = ubidi_openSized(-1, 0, &errorCode);
1741 if (U_SUCCESS(errorCode)) {
1742 log_err("\nubidi_openSized did not fail when called with bad argument\n");
1745 bidi = ubidi_openSized(2, 1, &errorCode);
1746 errorCode = U_ZERO_ERROR;
1747 srcLen = u_unescape("abc", src, MAXLEN);
1748 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1749 if (U_SUCCESS(errorCode)) {
1750 log_err("\nsetPara did not fail when called with text too long\n");
1752 errorCode = U_ZERO_ERROR;
1753 srcLen = u_unescape("=2", src, MAXLEN);
1754 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1755 ubidi_countRuns(bidi, &errorCode);
1756 if (U_SUCCESS(errorCode)) {
1757 log_err("\nsetPara did not fail when called for too many runs\n");
1760 bidi = ubidi_open();
1761 rm = ubidi_getReorderingMode(bidi);
1762 ubidi_setReorderingMode(bidi, UBIDI_REORDER_DEFAULT - 1);
1763 if (rm != ubidi_getReorderingMode(bidi)) {
1764 log_err("\nsetReorderingMode with bad argument #1 should have no effect\n");
1766 ubidi_setReorderingMode(bidi, 9999);
1767 if (rm != ubidi_getReorderingMode(bidi)) {
1768 log_err("\nsetReorderingMode with bad argument #2 should have no effect\n");
1771 /* Try a surrogate char */
1772 errorCode = U_ZERO_ERROR;
1773 srcLen = u_unescape("\\uD800\\uDC00", src, MAXLEN);
1774 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1775 if (ubidi_getDirection(bidi) != UBIDI_MIXED) {
1776 log_err("\ngetDirection for 1st surrogate char should be MIXED\n");
1778 errorCode = U_ZERO_ERROR;
1779 srcLen = u_unescape("abc", src, MAXLEN);
1780 ubidi_setPara(bidi, src, srcLen, 5, myLevels, &errorCode);
1781 if (U_SUCCESS(errorCode)) {
1782 log_err("\nsetPara did not fail when called with bad levels\n");
1785 ubidi_close(bidiLine);
1787 log_verbose("\nExiting TestFailureRecovery\n\n");
1791 testMultipleParagraphs(void) {
1792 static const char* const text = "__ABC\\u001c" /* Para #0 offset 0 */
1793 "__\\u05d0DE\\u001c" /* 1 6 */
1794 "__123\\u001c" /* 2 12 */
1795 "\\u000d\\u000a" /* 3 18 */
1796 "FG\\u000d" /* 4 20 */
1797 "\\u000d" /* 5 23 */
1798 "HI\\u000d\\u000a" /* 6 24 */
1799 "\\u000d\\u000a" /* 7 28 */
1800 "\\u000a" /* 8 30 */
1801 "\\u000a" /* 9 31 */
1802 "JK\\u001c"; /* 10 32 */
1803 static const int32_t paraCount=11;
1804 static const int32_t paraBounds[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35};
1805 static const UBiDiLevel paraLevels[]={UBIDI_LTR, UBIDI_RTL, UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL, 22, 23};
1806 static const UBiDiLevel multiLevels[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1807 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
1808 {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1809 {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0},
1810 {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
1811 {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}};
1812 static const char* const text2 = "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2";
1813 static const UBiDiLevel levels2[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2};
1814 static UBiDiLevel myLevels[10] = {0,0,0,0,0,0,0,0,0,0};
1815 static const UChar multiparaTestString[] = {
1816 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da,
1817 0x20, 0xa, 0xa, 0x41, 0x72, 0x74, 0x69, 0x73,
1818 0x74, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,
1819 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa, 0x41, 0x6c,
1820 0x62, 0x75, 0x6d, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1,
1821 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa,
1822 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x20, 0x32, 0x3a,
1823 0x32, 0x37, 0xa, 0xa
1825 static const UBiDiLevel multiparaTestLevels[] = {
1826 1, 1, 1, 1, 1, 1, 1, 1,
1827 1, 1, 0, 0, 0, 0, 0, 0,
1828 0, 0, 0, 1, 1, 1, 1, 1,
1829 1, 1, 1, 0, 0, 0, 0, 0,
1830 0, 0, 0, 0, 0, 1, 1, 1,
1831 1, 1, 1, 1, 1, 0, 0, 0,
1832 0, 0, 0, 0, 0, 0, 0, 0,
1835 UBiDiLevel gotLevel;
1836 const UBiDiLevel* gotLevels;
1837 UBool orderParagraphsLTR;
1838 UChar src[MAXLEN], dest[MAXLEN];
1839 UErrorCode errorCode=U_ZERO_ERROR;
1840 UBiDi* pBidi=ubidi_open();
1842 int32_t srcSize, count, paraStart, paraLimit, paraIndex, length;
1843 int32_t srcLen, destLen;
1846 log_verbose("\nEntering TestMultipleParagraphs\n\n");
1847 u_unescape(text, src, MAXLEN);
1848 srcSize=u_strlen(src);
1849 ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
1850 if(U_FAILURE(errorCode)){
1851 log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
1852 UBIDI_LTR, u_errorName(errorCode));
1856 /* check paragraph count and boundaries */
1857 if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
1858 log_err("ubidi_countParagraphs returned %d, should be %d\n",
1861 for (i=0; i<paraCount; i++) {
1862 ubidi_getParagraphByIndex(pBidi, i, ¶Start, ¶Limit, NULL, &errorCode);
1863 if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
1864 log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
1865 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
1868 errorCode=U_ZERO_ERROR;
1869 /* check with last paragraph not terminated by B */
1871 ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
1872 if(U_FAILURE(errorCode)){
1873 log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
1874 UBIDI_LTR, u_errorName(errorCode));
1878 if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
1879 log_err("2nd ubidi_countParagraphs returned %d, should be %d\n",
1883 ubidi_getParagraphByIndex(pBidi, i, ¶Start, ¶Limit, NULL, &errorCode);
1884 if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
1885 log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
1886 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
1888 errorCode=U_ZERO_ERROR;
1889 /* check paraLevel for all paragraphs under various paraLevel specs */
1890 for (k=0; k<6; k++) {
1891 ubidi_setPara(pBidi, src, srcSize, paraLevels[k], NULL, &errorCode);
1892 for (i=0; i<paraCount; i++) {
1893 paraIndex=ubidi_getParagraph(pBidi, paraBounds[i], NULL, NULL, &gotLevel, &errorCode);
1895 log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n",
1896 paraLevels[k], i, paraIndex, i);
1898 if (gotLevel!=multiLevels[k][i]) {
1899 log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n",
1900 paraLevels[k], i, gotLevel, multiLevels[k][i]);
1903 gotLevel=ubidi_getParaLevel(pBidi);
1904 if (gotLevel!=multiLevels[k][0]) {
1905 log_err("For paraLevel=%d getParaLevel=%d, expected %d\n",
1906 paraLevels[k], gotLevel, multiLevels[k][0]);
1909 errorCode=U_ZERO_ERROR;
1910 /* check that the result of ubidi_getParaLevel changes if the first
1911 * paragraph has a different level
1913 src[0]=0x05d2; /* Hebrew letter Gimel */
1914 ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_LTR, NULL, &errorCode);
1915 gotLevel=ubidi_getParaLevel(pBidi);
1916 if (gotLevel!=UBIDI_RTL) {
1917 log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n",
1918 gotLevel, UBIDI_RTL);
1920 errorCode=U_ZERO_ERROR;
1921 /* check that line cannot overlap paragraph boundaries */
1925 ubidi_setLine(pBidi, i, k, pLine, &errorCode);
1926 if (U_SUCCESS(errorCode)) {
1927 log_err("For line limits %d-%d got success %s\n",
1928 i, k, u_errorName(errorCode));
1930 errorCode=U_ZERO_ERROR;
1933 ubidi_setLine(pBidi, i, k, pLine, &errorCode);
1934 if (U_FAILURE(errorCode)) {
1935 log_err("For line limits %d-%d got error %s\n",
1936 i, k, u_errorName(errorCode));
1937 errorCode=U_ZERO_ERROR;
1939 /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */
1940 ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
1941 /* get levels through para Bidi block */
1942 gotLevels=ubidi_getLevels(pBidi, &errorCode);
1943 if (U_FAILURE(errorCode)) {
1944 log_err("Error on Para getLevels %s\n", u_errorName(errorCode));
1949 for (i=26; i<32; i++) {
1950 if (gotLevels[i]!=UBIDI_RTL) {
1951 log_err("For char %d(%04x), level=%d, expected=%d\n",
1952 i, src[i], gotLevels[i], UBIDI_RTL);
1955 /* get levels through para Line block */
1958 ubidi_setLine(pBidi, i, k, pLine, &errorCode);
1959 if (U_FAILURE(errorCode)) {
1960 log_err("For line limits %d-%d got error %s\n",
1961 i, k, u_errorName(errorCode));
1966 paraIndex=ubidi_getParagraph(pLine, i, ¶Start, ¶Limit, &gotLevel, &errorCode);
1967 gotLevels=ubidi_getLevels(pLine, &errorCode);
1968 if (U_FAILURE(errorCode)) {
1969 log_err("Error on Line getLevels %s\n", u_errorName(errorCode));
1974 length=ubidi_getLength(pLine);
1975 if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=UBIDI_RTL)) {
1976 log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
1977 "level of separator=%d expected=%d\n",
1978 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], UBIDI_RTL);
1980 orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
1981 if (orderParagraphsLTR) {
1982 log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, FALSE);
1984 ubidi_orderParagraphsLTR(pBidi, TRUE);
1985 orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
1986 if (!orderParagraphsLTR) {
1987 log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, TRUE);
1989 /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */
1990 ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
1991 /* get levels through para Bidi block */
1992 gotLevels=ubidi_getLevels(pBidi, &errorCode);
1993 for (i=26; i<32; i++) {
1994 if (gotLevels[i]!=0) {
1995 log_err("For char %d(%04x), level=%d, expected=%d\n",
1996 i, src[i], gotLevels[i], 0);
1999 errorCode=U_ZERO_ERROR;
2000 /* get levels through para Line block */
2003 ubidi_setLine(pBidi, paraStart, paraLimit, pLine, &errorCode);
2004 paraIndex=ubidi_getParagraph(pLine, i, ¶Start, ¶Limit, &gotLevel, &errorCode);
2005 gotLevels=ubidi_getLevels(pLine, &errorCode);
2006 length=ubidi_getLength(pLine);
2007 if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=0)) {
2008 log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
2009 "level of separator=%d expected=%d\n",
2010 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], 0);
2011 log_verbose("levels=");
2012 for (count=0; count<length; count++) {
2013 log_verbose(" %d", gotLevels[count]);
2018 /* test that the concatenation of separate invocations of the bidi code
2019 * on each individual paragraph in order matches the levels array that
2020 * results from invoking bidi once over the entire multiparagraph tests
2021 * (with orderParagraphsLTR false, of course)
2023 u_unescape(text, src, MAXLEN); /* restore original content */
2024 srcSize=u_strlen(src);
2025 ubidi_orderParagraphsLTR(pBidi, FALSE);
2026 ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_RTL, NULL, &errorCode);
2027 gotLevels=ubidi_getLevels(pBidi, &errorCode);
2028 for (i=0; i<paraCount; i++) {
2029 /* use pLine for individual paragraphs */
2030 paraStart = paraBounds[i];
2031 length = paraBounds[i+1] - paraStart;
2032 ubidi_setPara(pLine, src+paraStart, length, UBIDI_DEFAULT_RTL, NULL, &errorCode);
2033 for (j=0; j<length; j++) {
2034 if ((k=ubidi_getLevelAt(pLine, j)) != (gotLevel=gotLevels[paraStart+j])) {
2035 log_err("Checking paragraph concatenation: for paragraph=%d, "
2036 "char=%d(%04x), level=%d, expected=%d\n",
2037 i, j, src[paraStart+j], k, gotLevel);
2042 /* ensure that leading numerics in a paragraph are not treated as arabic
2043 numerals because of arabic text in a preceding paragraph
2045 u_unescape(text2, src, MAXLEN);
2046 srcSize=u_strlen(src);
2047 ubidi_orderParagraphsLTR(pBidi, TRUE);
2048 ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
2049 gotLevels=ubidi_getLevels(pBidi, &errorCode);
2050 if (U_FAILURE(errorCode)) {
2051 log_err("Can't get levels. %s\n", u_errorName(errorCode));
2054 for (i=0; i<srcSize; i++) {
2055 if (gotLevels[i]!=levels2[i]) {
2056 log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n",
2057 i, src[i], gotLevels[i], levels2[i]);
2061 /* check handling of whitespace before end of paragraph separator when
2062 * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B
2064 u_memset(src, 0x0020, MAXLEN);
2066 ubidi_orderParagraphsLTR(pBidi, TRUE);
2067 for (i=0x001c; i<=0x0020; i+=(0x0020-0x001c)) {
2068 src[4]=(UChar)i; /* with and without terminating B */
2069 for (j=0x0041; j<=0x05d0; j+=(0x05d0-0x0041)) {
2070 src[0]=(UChar)j; /* leading 'A' or Alef */
2071 for (gotLevel=4; gotLevel<=5; gotLevel++) {
2072 /* test even and odd paraLevel */
2073 ubidi_setPara(pBidi, src, srcSize, gotLevel, NULL, &errorCode);
2074 gotLevels=ubidi_getLevels(pBidi, &errorCode);
2075 for (k=1; k<=3; k++) {
2076 if (gotLevels[k]!=gotLevel) {
2077 log_err("Checking trailing spaces: for leading_char=%04x, "
2078 "last_char=%04x, index=%d, level=%d, expected=%d\n",
2079 src[0], src[4], k, gotLevels[k], gotLevel);
2086 /* check default orientation when inverse bidi and paragraph starts
2087 * with LTR strong char and ends with RTL strong char, with and without
2090 ubidi_setReorderingMode(pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
2091 srcLen = u_unescape("abc \\u05d2\\u05d1\n", src, MAXLEN);
2092 ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
2093 destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
2094 srcLen = u_unescape("\\u05d1\\u05d2 abc\n", src, MAXLEN);
2095 if (memcmp(src, dest, destLen * sizeof(UChar))) {
2096 log_err("\nInvalid output #0, should be '%s', got '%s'\n",
2097 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
2099 srcLen = u_unescape("abc \\u05d2\\u05d1", src, MAXLEN);
2100 ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
2101 destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
2102 srcLen = u_unescape("\\u05d1\\u05d2 abc", src, MAXLEN);
2103 if (memcmp(src, dest, destLen * sizeof(UChar))) {
2104 log_err("\nInvalid output #1, should be '%s', got '%s'\n",
2105 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
2108 /* check multiple paragraphs together with explicit levels
2110 ubidi_setReorderingMode(pBidi, UBIDI_REORDER_DEFAULT);
2111 srcLen = u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src, MAXLEN);
2112 ubidi_setPara(pBidi, src, srcLen, UBIDI_LTR, myLevels, &errorCode);
2113 destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
2114 srcLen = u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src, MAXLEN);
2115 if (memcmp(src, dest, destLen * sizeof(UChar))) {
2116 log_err("\nInvalid output #2, should be '%s', got '%s'\n",
2117 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
2119 count = ubidi_countParagraphs(pBidi);
2121 log_err("\nInvalid number of paras, should be 2, got %d\n", count);
2126 log_verbose("\nExiting TestMultipleParagraphs\n\n");
2128 /* check levels in multiple paragraphs with default para level
2130 pBidi = ubidi_open();
2131 errorCode = U_ZERO_ERROR;
2132 ubidi_setPara(pBidi, multiparaTestString, LENGTHOF(multiparaTestString),
2133 UBIDI_DEFAULT_LTR, NULL, &errorCode);
2134 if (U_FAILURE(errorCode)) {
2135 log_err("ubidi_setPara failed for multiparaTestString\n");
2139 gotLevels = ubidi_getLevels(pBidi, &errorCode);
2140 if (U_FAILURE(errorCode)) {
2141 log_err("ubidi_getLevels failed for multiparaTestString\n");
2145 for (i = 0; i < LENGTHOF(multiparaTestString); i++) {
2146 if (gotLevels[i] != multiparaTestLevels[i]) {
2147 log_err("Error on level for multiparaTestString at index %d, "
2148 "expected=%d, actual=%d\n",
2149 i, multiparaTestLevels[i], gotLevels[i]);
2157 /* inverse BiDi ------------------------------------------------------------- */
2159 static int countRoundtrips=0, countNonRoundtrips=0;
2161 #define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
2166 string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 },
2167 string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 },
2168 string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 },
2169 string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 },
2170 string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 };
2172 static const struct {
2176 STRING_TEST_CASE(string0),
2177 STRING_TEST_CASE(string1),
2178 STRING_TEST_CASE(string2),
2179 STRING_TEST_CASE(string3),
2180 STRING_TEST_CASE(string4)
2184 UErrorCode errorCode;
2187 log_verbose("\nEntering TestInverse\n\n");
2190 log_err("unable to open a UBiDi object (out of memory)\n");
2194 log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", LENGTHOF(testCases));
2195 for(i=0; i<LENGTHOF(testCases); ++i) {
2196 log_verbose("Testing case %d\n", i);
2197 errorCode=U_ZERO_ERROR;
2198 _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode);
2201 log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", LENGTHOF(testCases));
2202 for(i=0; i<LENGTHOF(testCases); ++i) {
2203 log_verbose("Testing case %d\n", i);
2204 errorCode=U_ZERO_ERROR;
2205 _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode);
2208 _testManyInverseBidi(pBiDi, 0);
2209 _testManyInverseBidi(pBiDi, 1);
2213 log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips);
2215 _testWriteReverse();
2217 _testManyAddedPoints();
2221 log_verbose("\nExiting TestInverse\n\n");
2224 #define COUNT_REPEAT_SEGMENTS 6
2226 static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={
2227 { 0x61, 0x62 }, /* L */
2228 { 0x5d0, 0x5d1 }, /* R */
2229 { 0x627, 0x628 }, /* AL */
2230 { 0x31, 0x32 }, /* EN */
2231 { 0x661, 0x662 }, /* AN */
2232 { 0x20, 0x20 } /* WS (N) */
2236 _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction) {
2237 UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
2239 UErrorCode errorCode;
2241 log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n",
2242 direction==0 ? 'L' : 'R');
2243 for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) {
2244 text[0]=repeatSegments[i][0];
2245 text[1]=repeatSegments[i][1];
2246 for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) {
2247 text[3]=repeatSegments[j][0];
2248 text[4]=repeatSegments[j][1];
2249 for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) {
2250 text[6]=repeatSegments[k][0];
2251 text[7]=repeatSegments[k][1];
2253 errorCode=U_ZERO_ERROR;
2254 log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i, j, k);
2255 _testInverseBidi(pBiDi, text, 8, direction, &errorCode);
2262 _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
2263 UBiDiLevel direction, UErrorCode *pErrorCode) {
2264 UChar visualLTR[MAXLEN], logicalDest[MAXLEN], visualDest[MAXLEN];
2265 int32_t ltrLength, logicalLength, visualLength;
2268 log_verbose("inverse Bidi: testInverse(L)\n");
2270 /* convert visual to logical */
2271 ubidi_setInverse(pBiDi, TRUE);
2272 if (!ubidi_isInverse(pBiDi)) {
2273 log_err("Error while doing ubidi_setInverse(TRUE)\n");
2275 ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode);
2276 if (src != ubidi_getText(pBiDi)) {
2277 log_err("Wrong value returned by ubidi_getText\n");
2279 logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
2280 UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
2282 printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode));
2285 /* convert back to visual LTR */
2286 ubidi_setInverse(pBiDi, FALSE);
2287 if (ubidi_isInverse(pBiDi)) {
2288 log_err("Error while doing ubidi_setInverse(FALSE)\n");
2290 ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
2291 visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
2292 UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode);
2294 log_verbose("inverse Bidi: testInverse(R)\n");
2296 /* reverse visual from RTL to LTR */
2297 ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, LENGTHOF(visualLTR), 0, pErrorCode);
2299 printUnicode(src, srcLength, NULL);
2302 /* convert visual RTL to logical */
2303 ubidi_setInverse(pBiDi, TRUE);
2304 ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode);
2305 logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
2306 UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
2308 printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode));
2311 /* convert back to visual RTL */
2312 ubidi_setInverse(pBiDi, FALSE);
2313 ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
2314 visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
2315 UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode);
2318 printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode));
2321 printUnicode(visualDest, visualLength, NULL);
2324 /* check and print results */
2325 if(U_FAILURE(*pErrorCode)) {
2326 log_err("inverse BiDi: *** error %s\n"
2327 " turn on verbose mode to see details\n", u_errorName(*pErrorCode));
2328 } else if(srcLength==visualLength && memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) {
2330 log_verbose(" + roundtripped\n");
2332 ++countNonRoundtrips;
2333 log_verbose(" * did not roundtrip\n");
2334 log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n"
2335 " turn on verbose mode to see details\n");
2340 _testWriteReverse(void) {
2341 /* U+064e and U+0650 are combining marks (Mn) */
2342 static const UChar forward[]={
2343 0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29
2344 }, reverseKeepCombining[]={
2345 0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f
2346 }, reverseRemoveControlsKeepCombiningDoMirror[]={
2347 0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650
2350 UErrorCode errorCode;
2353 /* test ubidi_writeReverse() with "interesting" options */
2354 errorCode=U_ZERO_ERROR;
2355 length=ubidi_writeReverse(forward, LENGTHOF(forward),
2356 reverse, LENGTHOF(reverse),
2357 UBIDI_KEEP_BASE_COMBINING,
2359 if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseKeepCombining) || memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) {
2360 log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n",
2361 length, LENGTHOF(reverseKeepCombining), u_errorName(errorCode));
2364 memset(reverse, 0xa5, LENGTHOF(reverse)*U_SIZEOF_UCHAR);
2365 errorCode=U_ZERO_ERROR;
2366 length=ubidi_writeReverse(forward, LENGTHOF(forward),
2367 reverse, LENGTHOF(reverse),
2368 UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING,
2370 if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) {
2371 log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n"
2372 " length=%d (should be %d), error code %s\n",
2373 length, LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode));
2377 static void _testManyAddedPoints(void) {
2378 UErrorCode errorCode = U_ZERO_ERROR;
2379 UBiDi *bidi = ubidi_open();
2380 UChar text[90], dest[MAXLEN], expected[120];
2382 for (i = 0; i < LENGTHOF(text); i+=3) {
2383 text[i] = 0x0061; /* 'a' */
2385 text[i+2] = 0x0033; /* '3' */
2387 ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
2388 ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
2389 ubidi_setPara(bidi, text, LENGTHOF(text), UBIDI_LTR, NULL, &errorCode);
2390 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
2391 for (i = 0; i < LENGTHOF(expected); i+=4) {
2392 expected[i] = 0x0061; /* 'a' */
2393 expected[i+1] = 0x05d0;
2394 expected[i+2] = 0x200e;
2395 expected[i+3] = 0x0033; /* '3' */
2397 if (memcmp(dest, expected, destLen * sizeof(UChar))) {
2398 log_err("\nInvalid output with many added points, "
2399 "expected '%s', got '%s'\n",
2400 aescstrdup(expected, LENGTHOF(expected)),
2401 aescstrdup(dest, destLen));
2406 static void _testMisc(void) {
2407 UErrorCode errorCode = U_ZERO_ERROR;
2408 UBiDi *bidi = ubidi_open();
2409 UChar src[3], dest[MAXLEN], expected[5];
2411 ubidi_setInverse(bidi, TRUE);
2412 src[0] = src[1] = src[2] = 0x0020;
2413 ubidi_setPara(bidi, src, LENGTHOF(src), UBIDI_RTL, NULL, &errorCode);
2414 destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
2415 UBIDI_OUTPUT_REVERSE | UBIDI_INSERT_LRM_FOR_NUMERIC,
2417 u_unescape("\\u200f \\u200f", expected, 5);
2418 if (memcmp(dest, expected, destLen * sizeof(UChar))) {
2419 log_err("\nInvalid output with RLM at both sides, "
2420 "expected '%s', got '%s'\n",
2421 aescstrdup(expected, LENGTHOF(expected)),
2422 aescstrdup(dest, destLen));
2427 /* arabic shaping ----------------------------------------------------------- */
2430 doArabicShapingTest(void) {
2434 0x627, /* arabic:alef */
2441 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0
2443 0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0
2444 }, logical_alen2an_init_lr[]={
2445 0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0
2446 }, logical_alen2an_init_al[]={
2447 0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0
2448 }, reverse_alen2an_init_lr[]={
2449 0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0
2450 }, reverse_alen2an_init_al[]={
2451 0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0
2456 UErrorCode errorCode;
2459 /* test number shaping */
2461 /* european->arabic */
2462 errorCode=U_ZERO_ERROR;
2463 length=u_shapeArabic(source, LENGTHOF(source),
2464 dest, LENGTHOF(dest),
2465 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2467 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) {
2468 log_err("failure in u_shapeArabic(en2an)\n");
2471 /* arabic->european */
2472 errorCode=U_ZERO_ERROR;
2473 length=u_shapeArabic(source, -1,
2474 dest, LENGTHOF(dest),
2475 U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
2477 if(U_FAILURE(errorCode) || length!=u_strlen(source) || memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) {
2478 log_err("failure in u_shapeArabic(an2en)\n");
2481 /* european->arabic with context, logical order, initial state not AL */
2482 errorCode=U_ZERO_ERROR;
2483 length=u_shapeArabic(source, LENGTHOF(source),
2484 dest, LENGTHOF(dest),
2485 U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN,
2487 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
2488 log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n");
2491 /* european->arabic with context, logical order, initial state AL */
2492 errorCode=U_ZERO_ERROR;
2493 length=u_shapeArabic(source, LENGTHOF(source),
2494 dest, LENGTHOF(dest),
2495 U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
2497 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
2498 log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n");
2501 /* european->arabic with context, reverse order, initial state not AL */
2502 errorCode=U_ZERO_ERROR;
2503 length=u_shapeArabic(source, LENGTHOF(source),
2504 dest, LENGTHOF(dest),
2505 U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2507 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
2508 log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n");
2511 /* european->arabic with context, reverse order, initial state AL */
2512 errorCode=U_ZERO_ERROR;
2513 length=u_shapeArabic(source, LENGTHOF(source),
2514 dest, LENGTHOF(dest),
2515 U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2517 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
2518 log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n");
2522 errorCode=U_ZERO_ERROR;
2523 length=u_shapeArabic(source, LENGTHOF(source),
2524 dest, LENGTHOF(dest),
2527 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) {
2528 log_err("failure in u_shapeArabic(noop)\n");
2531 errorCode=U_ZERO_ERROR;
2532 length=u_shapeArabic(source, 0,
2533 dest, LENGTHOF(dest),
2534 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2536 if(U_FAILURE(errorCode) || length!=0) {
2537 log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), LENGTHOF(source));
2540 /* preflight digit shaping */
2541 errorCode=U_ZERO_ERROR;
2542 length=u_shapeArabic(source, LENGTHOF(source),
2544 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2546 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=LENGTHOF(source)) {
2547 log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n",
2548 length, u_errorName(errorCode), LENGTHOF(source));
2551 /* test illegal arguments */
2552 errorCode=U_ZERO_ERROR;
2553 length=u_shapeArabic(NULL, LENGTHOF(source),
2554 dest, LENGTHOF(dest),
2555 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2557 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2558 log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2561 errorCode=U_ZERO_ERROR;
2562 length=u_shapeArabic(source, -2,
2563 dest, LENGTHOF(dest),
2564 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2566 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2567 log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2570 errorCode=U_ZERO_ERROR;
2571 length=u_shapeArabic(source, LENGTHOF(source),
2572 NULL, LENGTHOF(dest),
2573 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2575 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2576 log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2579 errorCode=U_ZERO_ERROR;
2580 length=u_shapeArabic(source, LENGTHOF(source),
2582 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2584 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2585 log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2588 errorCode=U_ZERO_ERROR;
2589 length=u_shapeArabic(source, LENGTHOF(source),
2590 dest, LENGTHOF(dest),
2591 U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN,
2593 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2594 log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2597 errorCode=U_ZERO_ERROR;
2598 length=u_shapeArabic(source, LENGTHOF(source),
2599 dest, LENGTHOF(dest),
2600 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED,
2602 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2603 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2606 errorCode=U_ZERO_ERROR;
2607 length=u_shapeArabic(source, LENGTHOF(source),
2608 (UChar *)(source+2), LENGTHOF(dest), /* overlap source and destination */
2609 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2611 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2612 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2615 errorCode=U_ZERO_ERROR;
2616 length=u_shapeArabic(lamalef, LENGTHOF(lamalef),
2617 dest, LENGTHOF(dest),
2618 U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2620 if(U_FAILURE(errorCode) || length == LENGTHOF(lamalef)) {
2621 log_err("failure in u_shapeArabic(U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR)\n");
2622 log_err("returned %s instead of U_ZERO_ERROR or returned length %d instead of 3\n", u_errorName(errorCode), length);
2627 doLamAlefSpecialVLTRArabicShapingTest(void) {
2630 /*a*/ 0x20 ,0x646,0x622,0x644,0x627,0x20,
2631 /*b*/ 0x646,0x623,0x64E,0x644,0x627,0x20,
2632 /*c*/ 0x646,0x627,0x670,0x644,0x627,0x20,
2633 /*d*/ 0x646,0x622,0x653,0x644,0x627,0x20,
2634 /*e*/ 0x646,0x625,0x655,0x644,0x627,0x20,
2635 /*f*/ 0x646,0x622,0x654,0x644,0x627,0x20,
2638 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
2639 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
2640 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
2643 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
2644 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
2645 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20
2646 }, shape_at_begin[]={
2647 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
2648 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
2649 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2650 }, shape_grow_shrink[]={
2651 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
2652 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
2653 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2654 }, shape_excepttashkeel_near[]={
2655 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
2656 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
2657 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
2659 }, shape_excepttashkeel_at_end[]={
2660 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
2661 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
2662 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,
2664 }, shape_excepttashkeel_at_begin[]={
2665 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
2666 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
2667 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2668 }, shape_excepttashkeel_grow_shrink[]={
2669 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
2670 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
2671 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2675 UErrorCode errorCode;
2678 errorCode=U_ZERO_ERROR;
2680 length=u_shapeArabic(source, LENGTHOF(source),
2681 dest, LENGTHOF(dest),
2682 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2683 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2686 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
2687 log_err("failure in u_shapeArabic(LAMALEF shape_near)\n");
2690 errorCode=U_ZERO_ERROR;
2692 length=u_shapeArabic(source, LENGTHOF(source),
2693 dest, LENGTHOF(dest),
2694 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
2695 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2698 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_end) || memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) {
2699 log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n");
2702 errorCode=U_ZERO_ERROR;
2704 length=u_shapeArabic(source, LENGTHOF(source),
2705 dest, LENGTHOF(dest),
2706 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
2707 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2710 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_begin) || memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
2711 log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n");
2714 errorCode=U_ZERO_ERROR;
2716 length=u_shapeArabic(source, LENGTHOF(source),
2717 dest, LENGTHOF(dest),
2718 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
2719 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2722 if(U_FAILURE(errorCode) || memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
2723 log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n");
2726 /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */
2728 errorCode=U_ZERO_ERROR;
2730 length=u_shapeArabic(source, LENGTHOF(source),
2731 dest, LENGTHOF(dest),
2732 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2733 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2736 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
2737 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n");
2740 errorCode=U_ZERO_ERROR;
2742 length=u_shapeArabic(source, LENGTHOF(source),
2743 dest, LENGTHOF(dest),
2744 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
2745 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2748 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_end) || memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) {
2749 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n");
2752 errorCode=U_ZERO_ERROR;
2754 length=u_shapeArabic(source, LENGTHOF(source),
2755 dest, LENGTHOF(dest),
2756 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
2757 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2760 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_begin) || memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) {
2761 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n");
2764 errorCode=U_ZERO_ERROR;
2766 length=u_shapeArabic(source, LENGTHOF(source),
2767 dest, LENGTHOF(dest),
2768 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK|
2769 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2772 if(U_FAILURE(errorCode) || memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
2773 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n");
2778 doTashkeelSpecialVLTRArabicShapingTest(void) {
2781 0x64A,0x628,0x631,0x639,0x20,
2782 0x64A,0x628,0x651,0x631,0x64E,0x639,0x20,
2783 0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20,
2784 0x628,0x670,0x631,0x670,0x639,0x20,
2785 0x628,0x653,0x631,0x653,0x639,0x20,
2786 0x628,0x654,0x631,0x654,0x639,0x20,
2787 0x628,0x655,0x631,0x655,0x639,0x20,
2789 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb,
2790 0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,
2791 0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,
2792 0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
2793 }, shape_excepttashkeel_near[]={
2794 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20,
2795 0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb,
2796 0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20,
2797 0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
2801 UErrorCode errorCode;
2804 errorCode=U_ZERO_ERROR;
2806 length=u_shapeArabic(source, LENGTHOF(source),
2807 dest, LENGTHOF(dest),
2808 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2809 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2812 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
2813 log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n");
2816 errorCode=U_ZERO_ERROR;
2818 length=u_shapeArabic(source, LENGTHOF(source),
2819 dest, LENGTHOF(dest),
2820 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2821 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2824 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
2825 log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n");
2830 doLOGICALArabicDeShapingTest(void) {
2833 0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020,
2834 0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4,
2835 0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020
2837 0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627,
2838 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
2839 0x629,0x20,0x20,0x20,0x20
2840 }, unshape_at_end[]={
2841 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
2842 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
2843 0x644,0x62d,0x631,0x629,0x20
2844 }, unshape_at_begin[]={
2845 0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20,
2846 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
2847 0x629,0x20,0x20,0x20,0x20
2848 }, unshape_grow_shrink[]={
2849 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
2850 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
2851 0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20
2855 UErrorCode errorCode;
2858 errorCode=U_ZERO_ERROR;
2860 length=u_shapeArabic(source, LENGTHOF(source),
2861 dest, LENGTHOF(dest),
2862 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2863 U_SHAPE_TEXT_DIRECTION_LOGICAL,
2866 if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_near) || memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) {
2867 log_err("failure in u_shapeArabic(unshape_near)\n");
2870 errorCode=U_ZERO_ERROR;
2872 length=u_shapeArabic(source, LENGTHOF(source),
2873 dest, LENGTHOF(dest),
2874 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
2875 U_SHAPE_TEXT_DIRECTION_LOGICAL,
2878 if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_end) || memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) {
2879 log_err("failure in u_shapeArabic(unshape_at_end)\n");
2882 errorCode=U_ZERO_ERROR;
2884 length=u_shapeArabic(source, LENGTHOF(source),
2885 dest, LENGTHOF(dest),
2886 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
2887 U_SHAPE_TEXT_DIRECTION_LOGICAL,
2890 if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_begin) || memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
2891 log_err("failure in u_shapeArabic(unshape_at_begin)\n");
2894 errorCode=U_ZERO_ERROR;
2896 length=u_shapeArabic(source, LENGTHOF(source),
2897 dest, LENGTHOF(dest),
2898 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
2899 U_SHAPE_TEXT_DIRECTION_LOGICAL,
2902 if(U_FAILURE(errorCode) || memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
2903 log_err("failure in u_shapeArabic(unshape_grow_shrink)\n");
2910 static const UChar src[] = { 0x0020, 0x0633, 0 };
2911 static const UChar dst_old[] = { 0xFEB1, 0x200B,0 };
2912 static const UChar dst_new[] = { 0xFEB1, 0xFE73,0 };
2913 UChar dst[3] = { 0x0000, 0x0000,0 };
2917 log_verbose("SRC: U+%04X U+%04X\n", src[0],src[1]);
2919 log_verbose("Trying old tail\n");
2920 status = U_ZERO_ERROR;
2921 length = u_shapeArabic(src, -1, dst, LENGTHOF(dst),
2922 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR, &status);
2923 if(U_FAILURE(status)) {
2924 log_err("Fail: status %s\n", u_errorName(status));
2925 } else if(length!=2) {
2926 log_err("Fail: len %d expected 3\n", length);
2927 } else if(u_strncmp(dst,dst_old,LENGTHOF(dst))) {
2928 log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
2929 dst[0],dst[1],dst_old[0],dst_old[1]);
2931 log_verbose("OK: U+%04X U+%04X len %d err %s\n",
2932 dst[0],dst[1],length,u_errorName(status));
2936 log_verbose("Trying new tail\n");
2937 status = U_ZERO_ERROR;
2938 length = u_shapeArabic(src, -1, dst, LENGTHOF(dst),
2939 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR|U_SHAPE_TAIL_NEW_UNICODE, &status);
2940 if(U_FAILURE(status)) {
2941 log_err("Fail: status %s\n", u_errorName(status));
2942 } else if(length!=2) {
2943 log_err("Fail: len %d expected 3\n", length);
2944 } else if(u_strncmp(dst,dst_new,LENGTHOF(dst))) {
2945 log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
2946 dst[0],dst[1],dst_new[0],dst_new[1]);
2948 log_verbose("OK: U+%04X U+%04X len %d err %s\n",
2949 dst[0],dst[1],length,u_errorName(status));
2954 doArabicShapingTestForBug5421(void) {
2956 persian_letters_source[]={
2957 0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020
2958 }, persian_letters[]={
2959 0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020
2960 }, tashkeel_aggregation_source[]={
2961 0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020,
2962 0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020
2963 }, tashkeel_aggregation[]={
2964 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3,
2965 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020
2966 }, untouched_presentation_source[]={
2967 0x0020 ,0x0627, 0xfe90,0x0020
2968 }, untouched_presentation[]={
2969 0x0020,0xfe8D, 0xfe90,0x0020
2970 }, untouched_presentation_r_source[]={
2971 0x0020 ,0xfe90, 0x0627, 0x0020
2972 }, untouched_presentation_r[]={
2973 0x0020, 0xfe90,0xfe8D,0x0020
2977 UErrorCode errorCode;
2980 errorCode=U_ZERO_ERROR;
2982 length=u_shapeArabic(persian_letters_source, LENGTHOF(persian_letters_source),
2983 dest, LENGTHOF(dest),
2984 U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2987 if(U_FAILURE(errorCode) || length!=LENGTHOF(persian_letters) || memcmp(dest, persian_letters, length*U_SIZEOF_UCHAR)!=0) {
2988 log_err("failure in u_shapeArabic(persian_letters)\n");
2991 errorCode=U_ZERO_ERROR;
2993 length=u_shapeArabic(tashkeel_aggregation_source, LENGTHOF(tashkeel_aggregation_source),
2994 dest, LENGTHOF(dest),
2995 U_SHAPE_AGGREGATE_TASHKEEL|U_SHAPE_PRESERVE_PRESENTATION|
2996 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2999 if(U_FAILURE(errorCode) || length!=LENGTHOF(tashkeel_aggregation) || memcmp(dest, tashkeel_aggregation, length*U_SIZEOF_UCHAR)!=0) {
3000 log_err("failure in u_shapeArabic(tashkeel_aggregation)\n");
3003 errorCode=U_ZERO_ERROR;
3005 length=u_shapeArabic(untouched_presentation_source, LENGTHOF(untouched_presentation_source),
3006 dest, LENGTHOF(dest),
3007 U_SHAPE_PRESERVE_PRESENTATION|
3008 U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
3011 if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation) || memcmp(dest, untouched_presentation, length*U_SIZEOF_UCHAR)!=0) {
3012 log_err("failure in u_shapeArabic(untouched_presentation)\n");
3015 errorCode=U_ZERO_ERROR;
3017 length=u_shapeArabic(untouched_presentation_r_source, LENGTHOF(untouched_presentation_r_source),
3018 dest, LENGTHOF(dest),
3019 U_SHAPE_PRESERVE_PRESENTATION|
3020 U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_LOGICAL,
3023 if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation_r) || memcmp(dest, untouched_presentation_r, length*U_SIZEOF_UCHAR)!=0) {
3024 log_err("failure in u_shapeArabic(untouched_presentation_r)\n");
3029 doArabicShapingTestForBug8703(void) {
3032 0x0634,0x0651,0x0645,0x0652,0x0633
3033 }, letters_source2[]={
3034 0x0634,0x0651,0x0645,0x0652,0x0633
3035 }, letters_source3[]={
3036 0x0634,0x0651,0x0645,0x0652,0x0633
3037 }, letters_source4[]={
3038 0x0634,0x0651,0x0645,0x0652,0x0633
3039 }, letters_source5[]={
3040 0x0633,0x0652,0x0645,0x0651,0x0634
3041 }, letters_source6[]={
3042 0x0633,0x0652,0x0645,0x0651,0x0634
3043 }, letters_source7[]={
3044 0x0633,0x0652,0x0645,0x0651,0x0634
3045 }, letters_source8[]={
3046 0x0633,0x0652,0x0645,0x0651,0x0634
3047 }, letters_dest1[]={
3048 0x0020,0xFEB7,0xFE7D,0xFEE4,0xFEB2
3049 }, letters_dest2[]={
3050 0xFEB7,0xFE7D,0xFEE4,0xFEB2,0x0020
3051 }, letters_dest3[]={
3052 0xFEB7,0xFE7D,0xFEE4,0xFEB2
3053 }, letters_dest4[]={
3054 0xFEB7,0xFE7D,0xFEE4,0x0640,0xFEB2
3055 }, letters_dest5[]={
3056 0x0020,0xFEB2,0xFEE4,0xFE7D,0xFEB7
3057 }, letters_dest6[]={
3058 0xFEB2,0xFEE4,0xFE7D,0xFEB7,0x0020
3059 }, letters_dest7[]={
3060 0xFEB2,0xFEE4,0xFE7D,0xFEB7
3061 }, letters_dest8[]={
3062 0xFEB2,0x0640,0xFEE4,0xFE7D,0xFEB7
3066 UErrorCode errorCode;
3069 errorCode=U_ZERO_ERROR;
3071 length=u_shapeArabic(letters_source1, LENGTHOF(letters_source1),
3072 dest, LENGTHOF(dest),
3073 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
3076 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) {
3077 log_err("failure in u_shapeArabic(letters_source1)\n");
3080 errorCode=U_ZERO_ERROR;
3082 length=u_shapeArabic(letters_source2, LENGTHOF(letters_source2),
3083 dest, LENGTHOF(dest),
3084 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
3087 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) {
3088 log_err("failure in u_shapeArabic(letters_source2)\n");
3091 errorCode=U_ZERO_ERROR;
3093 length=u_shapeArabic(letters_source3, LENGTHOF(letters_source3),
3094 dest, LENGTHOF(dest),
3095 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
3098 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) {
3099 log_err("failure in u_shapeArabic(letters_source3)\n");
3102 errorCode=U_ZERO_ERROR;
3104 length=u_shapeArabic(letters_source4, LENGTHOF(letters_source4),
3105 dest, LENGTHOF(dest),
3106 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
3109 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) {
3110 log_err("failure in u_shapeArabic(letters_source4)\n");
3113 errorCode=U_ZERO_ERROR;
3115 length=u_shapeArabic(letters_source5, LENGTHOF(letters_source5),
3116 dest, LENGTHOF(dest),
3117 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
3120 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) {
3121 log_err("failure in u_shapeArabic(letters_source5)\n");
3124 errorCode=U_ZERO_ERROR;
3126 length=u_shapeArabic(letters_source6, LENGTHOF(letters_source6),
3127 dest, LENGTHOF(dest),
3128 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
3131 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) {
3132 log_err("failure in u_shapeArabic(letters_source6)\n");
3135 errorCode=U_ZERO_ERROR;
3137 length=u_shapeArabic(letters_source7, LENGTHOF(letters_source7),
3138 dest, LENGTHOF(dest),
3139 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
3142 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest7) || memcmp(dest, letters_dest7, length*U_SIZEOF_UCHAR)!=0) {
3143 log_err("failure in u_shapeArabic(letters_source7)\n");
3146 errorCode=U_ZERO_ERROR;
3148 length=u_shapeArabic(letters_source8, LENGTHOF(letters_source8),
3149 dest, LENGTHOF(dest),
3150 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
3153 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest8) || memcmp(dest, letters_dest8, length*U_SIZEOF_UCHAR)!=0) {
3154 log_err("failure in u_shapeArabic(letters_source8)\n");
3159 doArabicShapingTestForBug9024(void) {
3161 letters_source1[]={ /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
3162 0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
3163 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
3164 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
3165 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
3166 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
3167 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
3168 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
3169 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
3170 }, letters_source2[]={/* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
3171 0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
3172 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
3173 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
3174 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
3175 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
3176 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
3177 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
3178 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
3179 }, letters_source3[]={/* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
3180 0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
3181 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
3182 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
3183 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
3184 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
3185 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
3186 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
3187 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
3188 }, letters_source4[]={/* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
3189 0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
3190 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
3191 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
3192 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
3193 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
3194 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
3195 0xD83B, 0xDE39, 0xD83B, 0xDE3B
3196 }, letters_source5[]={/* Arabic mathematical Symbols - Tailed Symbols */
3197 0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
3198 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
3199 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
3200 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
3201 }, letters_source6[]={/* Arabic mathematical Symbols - Stretched Symbols with 06 range */
3202 0xD83B, 0xDE21, 0x0633, 0xD83B, 0xDE62, 0x0647
3203 }, letters_dest1[]={
3204 0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
3205 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
3206 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
3207 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
3208 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
3209 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
3210 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
3211 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
3212 }, letters_dest2[]={
3213 0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
3214 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
3215 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
3216 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
3217 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
3218 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
3219 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
3220 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
3221 }, letters_dest3[]={
3222 0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
3223 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
3224 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
3225 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
3226 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
3227 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
3228 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
3229 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
3230 }, letters_dest4[]={
3231 0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
3232 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
3233 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
3234 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
3235 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
3236 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
3237 0xD83B, 0xDE39, 0xD83B, 0xDE3B
3238 }, letters_dest5[]={
3239 0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
3240 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
3241 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
3242 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
3243 }, letters_dest6[]={
3244 0xD83B, 0xDE21, 0xFEB1, 0xD83B, 0xDE62, 0xFEE9
3248 UErrorCode errorCode;
3251 errorCode=U_ZERO_ERROR;
3253 length=u_shapeArabic(letters_source1, LENGTHOF(letters_source1),
3254 dest, LENGTHOF(dest),
3255 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
3258 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) {
3259 log_err("failure in u_shapeArabic(letters_source1)\n");
3262 errorCode=U_ZERO_ERROR;
3264 length=u_shapeArabic(letters_source2, LENGTHOF(letters_source2),
3265 dest, LENGTHOF(dest),
3266 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
3269 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) {
3270 log_err("failure in u_shapeArabic(letters_source2)\n");
3273 errorCode=U_ZERO_ERROR;
3275 length=u_shapeArabic(letters_source3, LENGTHOF(letters_source3),
3276 dest, LENGTHOF(dest),
3277 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
3280 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) {
3281 log_err("failure in u_shapeArabic(letters_source3)\n");
3284 errorCode=U_ZERO_ERROR;
3286 length=u_shapeArabic(letters_source4, LENGTHOF(letters_source4),
3287 dest, LENGTHOF(dest),
3288 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
3291 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) {
3292 log_err("failure in u_shapeArabic(letters_source4)\n");
3295 errorCode=U_ZERO_ERROR;
3297 length=u_shapeArabic(letters_source5, LENGTHOF(letters_source5),
3298 dest, LENGTHOF(dest),
3299 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
3302 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) {
3303 log_err("failure in u_shapeArabic(letters_source5)\n");
3306 errorCode=U_ZERO_ERROR;
3308 length=u_shapeArabic(letters_source6, LENGTHOF(letters_source6),
3309 dest, LENGTHOF(dest),
3310 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
3313 if(U_FAILURE(errorCode) || length!=LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) {
3314 log_err("failure in u_shapeArabic(letters_source6)\n");
3319 /* helpers ------------------------------------------------------------------ */
3321 static void initCharFromDirProps(void) {
3322 static const UVersionInfo ucd401={ 4, 0, 1, 0 };
3323 static UVersionInfo ucdVersion={ 0, 0, 0, 0 };
3325 /* lazy initialization */
3326 if(ucdVersion[0]>0) {
3330 u_getUnicodeVersion(ucdVersion);
3331 if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) {
3332 /* Unicode 4.0.1 changes bidi classes for +-/ */
3333 charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */
3337 /* return a string with characters according to the desired directional properties */
3339 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer) {
3342 initCharFromDirProps();
3344 /* this part would have to be modified for UTF-x */
3345 for(i=0; i<length; ++i) {
3346 buffer[i]=charFromDirProp[dirProps[i]];
3352 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) {
3356 for(i=0; i<length; ++i) {
3358 log_verbose("%4x.%u ", s[i], levels[i]);
3360 log_verbose("%4x ", s[i]);
3368 /* Reordering Mode BiDi --------------------------------------------------------- */
3370 static const UBiDiLevel paraLevels[] = { UBIDI_LTR, UBIDI_RTL };
3373 assertSuccessful(const char* message, UErrorCode* rc) {
3374 if (rc != NULL && U_FAILURE(*rc)) {
3375 log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
3382 assertStringsEqual(const char* expected, const char* actual, const char* src,
3383 const char* mode, const char* option, UBiDi* pBiDi) {
3384 if (uprv_strcmp(expected, actual)) {
3385 char formatChars[MAXLEN];
3386 log_err("\nActual and expected output mismatch.\n"
3387 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n",
3389 "Actual output:", actual,
3390 "Expected output:", expected,
3391 "Levels:", formatLevels(pBiDi, formatChars),
3392 "Reordering mode:", ubidi_getReorderingMode(pBiDi), mode,
3393 "Paragraph level:", ubidi_getParaLevel(pBiDi),
3394 "Reordering option:", ubidi_getReorderingOptions(pBiDi), option);
3401 getBiDiObject(void) {
3402 UBiDi* pBiDi = ubidi_open();
3403 if (pBiDi == NULL) {
3404 log_err("Unable to allocate a UBiDi object. Tests are skipped.\n");
3409 #define MAKE_ITEMS(val) val, #val
3411 static const struct {
3412 UBiDiReorderingMode value;
3413 const char* description;
3416 { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) },
3417 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT) },
3418 { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL) },
3419 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) },
3420 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L) }
3422 static const struct {
3424 const char* description;
3427 { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS) },
3431 #define TC_COUNT LENGTHOF(textIn)
3432 #define MODES_COUNT LENGTHOF(modes)
3433 #define OPTIONS_COUNT LENGTHOF(options)
3434 #define LEVELS_COUNT LENGTHOF(paraLevels)
3436 static const char* const textIn[] = {
3445 /* (4) JIH1.2,3MLK */
3449 /* (6) JIH.>12->a */
3451 /* (7) CBA.>67->89=a */
3453 /* (8) CBA.123->xyz */
3457 /* (10) a.>67->xyz */
3465 static const char* const textOut[] = {
3468 /* TC 1: .123->4.5 */
3469 ".123->4.5", /* (1) */
3470 "4.5<-123.", /* (2) */
3473 /* TC 3: .678->8.9 */
3474 ".8.9<-678", /* (4) */
3475 "8.9<-678.", /* (5) */
3476 ".678->8.9", /* (6) */
3477 /* TC 4: MLK1.2,3JIH */
3478 "KLM1.2,3HIJ", /* (7) */
3479 /* TC 5: FE.>12-> */
3480 "12<.EF->", /* (8) */
3481 "<-12<.EF", /* (9) */
3482 "EF.>@12->", /* (10) */
3483 /* TC 6: JIH.>12->a */
3484 "12<.HIJ->a", /* (11) */
3485 "a<-12<.HIJ", /* (12) */
3486 "HIJ.>@12->a", /* (13) */
3487 "a&<-12<.HIJ", /* (14) */
3488 /* TC 7: CBA.>67->89=a */
3489 "ABC.>@67->89=a", /* (15) */
3490 "a=89<-67<.ABC", /* (16) */
3491 "a&=89<-67<.ABC", /* (17) */
3492 "89<-67<.ABC=a", /* (18) */
3493 /* TC 8: CBA.123->xyz */
3494 "123.ABC->xyz", /* (19) */
3495 "xyz<-123.ABC", /* (20) */
3496 "ABC.@123->xyz", /* (21) */
3497 "xyz&<-123.ABC", /* (22) */
3498 /* TC 9: .>12->xyz */
3499 ".>12->xyz", /* (23) */
3500 "xyz<-12<.", /* (24) */
3501 "xyz&<-12<.", /* (25) */
3502 /* TC 10: a.>67->xyz */
3503 "a.>67->xyz", /* (26) */
3504 "a.>@67@->xyz", /* (27) */
3505 "xyz<-67<.a", /* (28) */
3507 "123HIJ", /* (29) */
3508 "HIJ123", /* (30) */
3509 /* TC 12: 123 JIH */
3510 "123 HIJ", /* (31) */
3511 "HIJ 123", /* (32) */
3514 #define NO UBIDI_MAP_NOWHERE
3515 #define MAX_MAP_LENGTH 20
3517 static const int32_t forwardMap[][MAX_MAP_LENGTH] = {
3519 { 0, 1, 2 }, /* (0) */
3520 /* TC 1: .123->4.5 */
3521 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */
3522 { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (2) */
3524 { 0, 1, 2 }, /* (3) */
3525 /* TC 3: .678->8.9 */
3526 { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */
3527 { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (5) */
3528 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */
3529 /* TC 4: MLK1.2,3JIH */
3530 { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */
3531 /* TC 5: FE.>12-> */
3532 { 5, 4, 3, 2, 0, 1, 6, 7 }, /* (8) */
3533 { 7, 6, 5, 4, 2, 3, 1, 0 }, /* (9) */
3534 { 1, 0, 2, 3, 5, 6, 7, 8 }, /* (10) */
3535 /* TC 6: JIH.>12->a */
3536 { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 }, /* (11) */
3537 { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 }, /* (12) */
3538 { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 }, /* (13) */
3539 { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 }, /* (14) */
3540 /* TC 7: CBA.>67->89=a */
3541 { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 }, /* (15) */
3542 { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 }, /* (16) */
3543 { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 }, /* (17) */
3544 { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 }, /* (18) */
3545 /* TC 8: CBA.123->xyz */
3546 { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 }, /* (19) */
3547 { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (20) */
3548 { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (21) */
3549 { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 }, /* (22) */
3550 /* TC 9: .>12->xyz */
3551 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */
3552 { 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (24) */
3553 { 9, 8, 6, 7, 5, 4, 0, 1, 2 }, /* (25) */
3554 /* TC 10: a.>67->xyz */
3555 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */
3556 { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 }, /* (27) */
3557 { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (28) */
3559 { 0, 1, 2, 5, 4, 3 }, /* (29) */
3560 { 3, 4, 5, 2, 1, 0 }, /* (30) */
3561 /* TC 12: 123 JIH */
3562 { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */
3563 { 4, 5, 6, 3, 2, 1, 0 }, /* (32) */
3566 static const int32_t inverseMap[][MAX_MAP_LENGTH] = {
3568 { 0, 1, 2 }, /* (0) */
3569 /* TC 1: .123->4.5 */
3570 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */
3571 { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (2) */
3573 { 0, 1, 2 }, /* (3) */
3574 /* TC 3: .678->8.9 */
3575 { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */
3576 { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (5) */
3577 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */
3578 /* TC 4: MLK1.2,3JIH */
3579 { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */
3580 /* TC 5: FE.>12-> */
3581 { 4, 5, 3, 2, 1, 0, 6, 7 }, /* (8) */
3582 { 7, 6, 4, 5, 3, 2, 1, 0 }, /* (9) */
3583 { 1, 0, 2, 3, NO, 4, 5, 6, 7 }, /* (10) */
3584 /* TC 6: JIH.>12->a */
3585 { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 }, /* (11) */
3586 { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (12) */
3587 { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (13) */
3588 { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (14) */
3589 /* TC 7: CBA.>67->89=a */
3590 { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (15) */
3591 { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (16) */
3592 { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (17) */
3593 { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 }, /* (18) */
3594 /* TC 8: CBA.123->xyz */
3595 { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 }, /* (19) */
3596 { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (20) */
3597 { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 }, /* (21) */
3598 { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (22) */
3599 /* TC 9: .>12->xyz */
3600 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */
3601 { 6, 7, 8, 5, 4, 2, 3, 1, 0 }, /* (24) */
3602 { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 }, /* (25) */
3603 /* TC 10: a.>67->xyz */
3604 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */
3605 { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (27) */
3606 { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 }, /* (28) */
3608 { 0, 1, 2, 5, 4, 3 }, /* (29) */
3609 { 5, 4, 3, 0, 1, 2 }, /* (30) */
3610 /* TC 12: 123 JIH */
3611 { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */
3612 { 6, 5, 4, 3, 0, 1, 2 }, /* (32) */
3615 static const char outIndices[TC_COUNT][MODES_COUNT - 1][OPTIONS_COUNT]
3618 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3619 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3620 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3621 {{ 0, 0}, { 0, 0}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3623 { /* TC 1: .123->4.5 */
3624 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3625 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3626 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3627 {{ 1, 2}, { 1, 2}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3630 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3631 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3632 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3633 {{ 3, 3}, { 3, 3}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3635 { /* TC 3: .678->8.9 */
3636 {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3637 {{ 4, 5}, { 4, 5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3638 {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3639 {{ 6, 5}, { 6, 5}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3641 { /* TC 4: MLK1.2,3JIH */
3642 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3643 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3644 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3645 {{ 7, 7}, { 7, 7}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3647 { /* TC 5: FE.>12-> */
3648 {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3649 {{10, 9}, { 8, 9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3650 {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3651 {{10, 9}, { 8, 9}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3653 { /* TC 6: JIH.>12->a */
3654 {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3655 {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3656 {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3657 {{13, 14}, {11, 12}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3659 { /* TC 7: CBA.>67->89=a */
3660 {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3661 {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3662 {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3663 {{15, 17}, {18, 16}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3665 { /* TC 8: CBA.>124->xyz */
3666 {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3667 {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3668 {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3669 {{21, 22}, {19, 20}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3671 { /* TC 9: .>12->xyz */
3672 {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3673 {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3674 {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3675 {{23, 25}, {23, 24}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3677 { /* TC 10: a.>67->xyz */
3678 {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3679 {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3680 {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3681 {{26, 27}, {26, 28}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3683 { /* TC 11: 124JIH */
3684 {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3685 {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3686 {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3687 {{30, 30}, {30, 30}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3689 { /* TC 12: 124 JIH */
3690 {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3691 {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3692 {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3693 {{31, 32}, {31, 32}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3698 assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, const char *srcChars,
3699 const char *destChars, const UChar *dest, int32_t destLen,
3700 int mode, int option, UBiDiLevel level) {
3702 static const char roundtrip[TC_COUNT][MODES_COUNT][OPTIONS_COUNT]
3705 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3706 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3707 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3708 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3709 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3711 { /* TC 1: .123->4.5 */
3712 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3713 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3714 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3715 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3716 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3719 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3720 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3721 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3722 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3723 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3725 { /* TC 3: .678->8.9 */
3726 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3727 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3728 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3729 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3730 {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3732 { /* TC 4: MLK1.2,3JIH */
3733 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3734 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3735 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3736 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3737 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3739 { /* TC 5: FE.>12-> */
3740 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3741 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3742 {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3743 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3744 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3746 { /* TC 6: JIH.>12->a */
3747 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3748 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3749 {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3750 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3751 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3753 { /* TC 7: CBA.>67->89=a */
3754 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3755 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3756 {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3757 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3758 {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3760 { /* TC 8: CBA.>123->xyz */
3761 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3762 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3763 {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3764 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3765 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3767 { /* TC 9: .>12->xyz */
3768 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3769 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3770 {{ 1, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3771 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3772 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3774 { /* TC 10: a.>67->xyz */
3775 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3776 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3777 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3778 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3779 {{ 1, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3781 { /* TC 11: 123JIH */
3782 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3783 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3784 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3785 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3786 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3788 { /* TC 12: 123 JIH */
3789 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3790 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3791 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3792 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3793 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3797 #define SET_ROUND_TRIP_MODE(mode) \
3798 ubidi_setReorderingMode(pBiDi, mode); \
3802 UErrorCode rc = U_ZERO_ERROR;
3803 UChar dest2[MAXLEN];
3806 char destChars2[MAXLEN];
3807 char destChars3[MAXLEN];
3809 switch (modes[mode].value) {
3810 case UBIDI_REORDER_NUMBERS_SPECIAL:
3811 SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL)
3812 case UBIDI_REORDER_GROUP_NUMBERS_WITH_R:
3813 SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R)
3814 case UBIDI_REORDER_RUNS_ONLY:
3815 SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY)
3816 case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
3817 SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
3818 case UBIDI_REORDER_INVERSE_LIKE_DIRECT:
3819 SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
3820 case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL:
3821 SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL)
3823 SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT)
3825 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
3827 ubidi_setPara(pBiDi, dest, destLen, level, NULL, &rc);
3828 assertSuccessful("ubidi_setPara", &rc);
3830 destLen2 = ubidi_writeReordered(pBiDi, dest2, MAXLEN, UBIDI_DO_MIRRORING,
3832 assertSuccessful("ubidi_writeReordered", &rc);
3834 u16ToPseudo(destLen, dest, destChars3);
3835 u16ToPseudo(destLen2, dest2, destChars2);
3836 checkWhatYouCan(pBiDi, destChars3, destChars2);
3837 if (strcmp(srcChars, destChars2)) {
3838 if (roundtrip[tc][mode][option][level]) {
3839 log_err("\nRound trip failed for case=%d mode=%d option=%d.\n"
3840 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
3841 "\n%20s %u\n", tc, mode, option,
3842 "Original text:", srcChars,
3843 "Round-tripped text:", destChars2,
3844 "Intermediate text:", destChars3,
3845 "Reordering mode:", modes[mode].description,
3846 "Reordering option:", options[option].description,
3847 "Paragraph level:", level);
3850 log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n"
3851 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
3852 "\n%20s %u\n", tc, mode, option,
3853 "Original text:", srcChars,
3854 "Round-tripped text:", destChars2,
3855 "Intermediate text:", destChars3,
3856 "Reordering mode:", modes[mode].description,
3857 "Reordering option:", options[option].description,
3858 "Paragraph level:", level);
3862 if (!checkResultLength(pBiDi, destChars, destChars2, destLen2,
3863 desc, "UBIDI_OPTION_REMOVE_CONTROLS", level)) {
3866 if (outIndex > -1 && !checkMaps(pBiDi, outIndex, srcChars, destChars,
3867 desc, "UBIDI_OPTION_REMOVE_CONTROLS",
3875 checkResultLength(UBiDi *pBiDi, const char *srcChars, const char *destChars,
3876 int32_t destLen, const char* mode,
3877 const char* option, UBiDiLevel level) {
3879 if (strcmp(mode, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0)
3880 actualLen = strlen(destChars);
3882 actualLen = ubidi_getResultLength(pBiDi);
3883 if (actualLen != destLen) {
3884 log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n"
3885 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n",
3886 "Expected:", destLen, "Actual:", actualLen,
3887 "Input:", srcChars, "Output:", destChars,
3888 "Reordering mode:", mode, "Reordering option:", option,
3889 "Paragraph level:", level);
3896 testReorderRunsOnly(void) {
3897 static const struct {
3899 const char* textOut[2][2];
3900 const char noroundtrip[2];
3902 {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*0*/
3903 {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
3904 {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}}, /*1*/
3905 {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}}, /*2*/
3906 {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"}, /*3*/
3907 {"* /%$123=-", "* /%$123=-"}}, {0, 0}},
3908 {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"}, /*4*/
3909 {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}},
3910 {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"}, /*5*/
3911 {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}},
3912 {"123->abc", {{"abc<-123", "abc<-123"}, /*6*/
3913 {"abc&<-123", "abc<-123"}}, {1, 0}},
3914 {"123->JKL", {{"JKL<-123", "123->JKL"}, /*7*/
3915 {"JKL<-123", "JKL<-@123"}}, {0, 1}},
3916 {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"}, /*8*/
3917 {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}},
3918 {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"}, /*9*/
3919 {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}},
3920 {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"}, /*10*/
3921 {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}},
3922 {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"}, /*11*/
3923 {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}},
3924 {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"}, /*12*/
3925 {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}},
3926 {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"}, /*13*/
3927 {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}},
3928 {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"}, /*14*/
3929 {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}},
3930 {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*15*/
3931 {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
3932 {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}, /*16*/
3933 {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}},
3934 {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"}, /*17*/
3935 {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}},
3936 {"123", {{"123", "123"}, /* just one run */ /*18*/
3937 {"123", "123"}}, {0, 0}}
3939 UBiDi *pBiDi = getBiDiObject();
3940 UBiDi *pL2VBiDi = getBiDiObject();
3941 UChar src[MAXLEN], dest[MAXLEN], visual1[MAXLEN], visual2[MAXLEN];
3942 char destChars[MAXLEN], vis1Chars[MAXLEN], vis2Chars[MAXLEN];
3943 int32_t srcLen, destLen, vis1Len, vis2Len, option, i, j, nCases, paras;
3944 UErrorCode rc = U_ZERO_ERROR;
3947 log_verbose("\nEntering TestReorderRunsOnly\n\n");
3950 ubidi_close(pBiDi); /* in case this one was allocated */
3953 ubidi_setReorderingMode(pBiDi, UBIDI_REORDER_RUNS_ONLY);
3954 ubidi_setReorderingOptions(pL2VBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
3956 for (option = 0; option < 2; option++) {
3957 ubidi_setReorderingOptions(pBiDi, option==0 ? UBIDI_OPTION_REMOVE_CONTROLS
3958 : UBIDI_OPTION_INSERT_MARKS);
3959 for (i = 0, nCases = LENGTHOF(testCases); i < nCases; i++) {
3960 srcLen = strlen(testCases[i].textIn);
3961 pseudoToU16(srcLen, testCases[i].textIn, src);
3962 for(j = 0; j < 2; j++) {
3963 log_verbose("Now doing test for option %d, case %d, level %d\n",
3965 level = paraLevels[j];
3966 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
3967 assertSuccessful("ubidi_setPara", &rc);
3969 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
3970 assertSuccessful("ubidi_writeReordered", &rc);
3971 u16ToPseudo(destLen, dest, destChars);
3972 checkWhatYouCan(pBiDi, testCases[i].textIn, destChars);
3973 assertStringsEqual(testCases[i].textOut[option][level], destChars,
3974 testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY",
3975 option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
3978 if((option==0) && testCases[i].noroundtrip[level]) {
3981 ubidi_setPara(pL2VBiDi, src, srcLen, level, NULL, &rc);
3982 assertSuccessful("ubidi_setPara1", &rc);
3984 vis1Len = ubidi_writeReordered(pL2VBiDi, visual1, MAXLEN, UBIDI_DO_MIRRORING, &rc);
3985 assertSuccessful("ubidi_writeReordered1", &rc);
3986 u16ToPseudo(vis1Len, visual1, vis1Chars);
3987 checkWhatYouCan(pL2VBiDi, testCases[i].textIn, vis1Chars);
3988 ubidi_setPara(pL2VBiDi, dest, destLen, level^1, NULL, &rc);
3989 assertSuccessful("ubidi_setPara2", &rc);
3991 vis2Len = ubidi_writeReordered(pL2VBiDi, visual2, MAXLEN, UBIDI_DO_MIRRORING, &rc);
3992 assertSuccessful("ubidi_writeReordered2", &rc);
3993 u16ToPseudo(vis2Len, visual2, vis2Chars);
3994 checkWhatYouCan(pL2VBiDi, destChars, vis2Chars);
3995 assertStringsEqual(vis1Chars, vis2Chars,
3996 testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY (2)",
3997 option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
4003 /* test with null or empty text */
4004 ubidi_setPara(pBiDi, src, 0, UBIDI_LTR, NULL, &rc);
4005 assertSuccessful("ubidi_setPara3", &rc);
4006 paras = ubidi_countParagraphs(pBiDi);
4008 log_err("\nInvalid number of paras (should be 0): %d\n", paras);
4012 ubidi_close(pL2VBiDi);
4014 log_verbose("\nExiting TestReorderRunsOnly\n\n");
4018 testReorderingMode(void) {
4020 UChar src[MAXLEN], dest[MAXLEN];
4021 char destChars[MAXLEN];
4022 UBiDi *pBiDi = NULL, *pBiDi2 = NULL, *pBiDi3 = NULL;
4024 int tc, mode, option, level;
4025 uint32_t optionValue, optionBack;
4026 UBiDiReorderingMode modeValue, modeBack;
4027 int32_t srcLen, destLen, idx;
4028 const char *expectedChars;
4029 UBool testOK = TRUE;
4031 log_verbose("\nEntering TestReorderingMode\n\n");
4033 pBiDi = getBiDiObject();
4034 pBiDi2 = getBiDiObject();
4035 pBiDi3 = getBiDiObject();
4037 ubidi_close(pBiDi); /* in case this one was allocated */
4038 ubidi_close(pBiDi2); /* in case this one was allocated */
4042 ubidi_setInverse(pBiDi2, TRUE);
4044 for (tc = 0; tc < TC_COUNT; tc++) {
4045 const char *srcChars = textIn[tc];
4046 srcLen = strlen(srcChars);
4047 pseudoToU16(srcLen, srcChars, src);
4049 for (mode = 0; mode < MODES_COUNT; mode++) {
4050 modeValue = modes[mode].value;
4051 ubidi_setReorderingMode(pBiDi, modeValue);
4052 modeBack = ubidi_getReorderingMode(pBiDi);
4053 if (modeValue != modeBack) {
4054 log_err("Error while setting reordering mode to %d, returned %d\n",
4055 modeValue, modeBack);
4058 for (option = 0; option < OPTIONS_COUNT; option++) {
4059 optionValue = options[option].value;
4060 ubidi_setReorderingOptions(pBiDi, optionValue);
4061 optionBack = ubidi_getReorderingOptions(pBiDi);
4062 if (optionValue != optionBack) {
4063 log_err("Error while setting reordering option to %d, returned %d\n",
4064 optionValue, optionBack);
4067 for (level = 0; level < LEVELS_COUNT; level++) {
4068 log_verbose("starting test %d mode=%d option=%d level=%d\n",
4069 tc, modes[mode].value, options[option].value, level);
4071 ubidi_setPara(pBiDi, src, srcLen, paraLevels[level], NULL, &rc);
4072 assertSuccessful("ubidi_setPara", &rc);
4075 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
4076 UBIDI_DO_MIRRORING, &rc);
4077 assertSuccessful("ubidi_writeReordered", &rc);
4078 u16ToPseudo(destLen, dest, destChars);
4079 if (!((modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
4080 (options[option].value == UBIDI_OPTION_INSERT_MARKS))) {
4081 checkWhatYouCan(pBiDi, srcChars, destChars);
4084 if (modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) {
4086 expectedChars = inverseBasic(pBiDi2, srcChars, srcLen,
4087 options[option].value, paraLevels[level], destChars);
4090 idx = outIndices[tc][mode][option][level];
4091 expectedChars = textOut[idx];
4093 if (!assertStringsEqual(expectedChars, destChars, srcChars,
4094 modes[mode].description,
4095 options[option].description,
4099 if (options[option].value == UBIDI_OPTION_INSERT_MARKS &&
4100 !assertRoundTrip(pBiDi3, tc, idx, srcChars,
4101 destChars, dest, destLen,
4102 mode, option, paraLevels[level])) {
4105 else if (!checkResultLength(pBiDi, srcChars, destChars,
4106 destLen, modes[mode].description,
4107 options[option].description,
4108 paraLevels[level])) {
4111 else if (idx > -1 && !checkMaps(pBiDi, idx, srcChars,
4112 destChars, modes[mode].description,
4113 options[option].description, paraLevels[level],
4121 if (testOK == TRUE) {
4122 log_verbose("\nReordering mode test OK\n");
4124 ubidi_close(pBiDi3);
4125 ubidi_close(pBiDi2);
4128 log_verbose("\nExiting TestReorderingMode\n\n");
4131 static const char* inverseBasic(UBiDi *pBiDi, const char *srcChars, int32_t srcLen,
4132 uint32_t option, UBiDiLevel level, char *result) {
4133 UErrorCode rc = U_ZERO_ERROR;
4135 UChar src[MAXLEN], dest2[MAXLEN];
4137 if (pBiDi == NULL || src == NULL) {
4140 ubidi_setReorderingOptions(pBiDi, option);
4141 pseudoToU16(srcLen, srcChars, src);
4142 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
4143 assertSuccessful("ubidi_setPara", &rc);
4146 destLen = ubidi_writeReordered(pBiDi, dest2, MAXLEN,
4147 UBIDI_DO_MIRRORING, &rc);
4148 assertSuccessful("ubidi_writeReordered", &rc);
4149 u16ToPseudo(destLen, dest2, result);
4150 if (!(option == UBIDI_OPTION_INSERT_MARKS)) {
4151 checkWhatYouCan(pBiDi, srcChars, result);
4156 #define NULL_CHAR '\0'
4159 testStreaming(void) {
4160 #define MAXPORTIONS 10
4162 static const struct {
4165 short int nPortions[2];
4166 char portionLens[2][MAXPORTIONS];
4167 const char* message[2];
4175 6, { 6, 6 }, {{ 4, 6, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }},
4176 {"4, 6, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"}
4178 { "abcd\\u000Afgh\\u000D12345\\u000A456",
4179 6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
4180 {"5, 4, 6, 3", "5, 4, 6, 3"}
4182 { "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D",
4183 6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
4184 {"5, 4, 6, 3", "5, 4, 6, 3"}
4186 { "abcde\\u000Afghi",
4187 10, { 2, 2 }, {{ 6, 4 }, { 6, 4 }},
4192 UBiDi *pBiDi = NULL;
4194 UErrorCode rc = U_ZERO_ERROR;
4195 int32_t srcLen, processedLen, chunk, len, nPortions;
4196 int i, j, levelIndex;
4198 int nTests = LENGTHOF(testData), nLevels = LENGTHOF(paraLevels);
4199 UBool mismatch, testOK = TRUE;
4200 char processedLenStr[MAXPORTIONS * 5];
4202 log_verbose("\nEntering TestStreaming\n\n");
4204 pBiDi = getBiDiObject();
4206 ubidi_orderParagraphsLTR(pBiDi, TRUE);
4208 for (levelIndex = 0; levelIndex < nLevels; levelIndex++) {
4209 for (i = 0; i < nTests; i++) {
4210 srcLen = u_unescape(testData[i].textIn, src, MAXLEN);
4211 chunk = testData[i].chunk;
4212 nPortions = testData[i].nPortions[levelIndex];
4213 level = paraLevels[levelIndex];
4214 processedLenStr[0] = NULL_CHAR;
4215 log_verbose("Testing level %d, case %d\n", level, i);
4219 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
4220 for (j = 0, pSrc = src; j < MAXPORTIONS && srcLen > 0; j++) {
4222 len = chunk < srcLen ? chunk : srcLen;
4223 ubidi_setPara(pBiDi, pSrc, len, level, NULL, &rc);
4224 if (!assertSuccessful("ubidi_setPara", &rc)) {
4228 processedLen = ubidi_getProcessedLength(pBiDi);
4229 if (processedLen == 0) {
4230 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_DEFAULT);
4234 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
4236 mismatch |= (UBool)(j >= nPortions ||
4237 processedLen != testData[i].portionLens[levelIndex][j]);
4239 sprintf(processedLenStr + j * 4, "%4d", processedLen);
4240 srcLen -= processedLen, pSrc += processedLen;
4243 if (mismatch || j != nPortions) {
4245 log_err("\nProcessed lengths mismatch.\n"
4246 "\tParagraph level: %u\n"
4247 "\tInput string: %s\n"
4248 "\tActually processed portion lengths: { %s }\n"
4249 "\tExpected portion lengths : { %s }\n",
4250 paraLevels[levelIndex], testData[i].textIn,
4251 processedLenStr, testData[i].message[levelIndex]);
4256 if (testOK == TRUE) {
4257 log_verbose("\nBiDi streaming test OK\n");
4259 log_verbose("\nExiting TestStreaming\n\n");
4264 static UCharDirection U_CALLCONV
4265 overrideBidiClass(const void *context, UChar32 c) {
4267 #define DEF U_BIDI_CLASS_DEFAULT
4269 static const UCharDirection customClasses[] = {
4270 /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
4271 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 00-07 */
4272 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 08-0F */
4273 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 10-17 */
4274 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 18-1F */
4275 DEF, DEF, DEF, DEF, DEF, DEF, R, DEF, /* 20-27 */
4276 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 28-2F */
4277 EN, EN, EN, EN, EN, EN, AN, AN, /* 30-37 */
4278 AN, AN, DEF, DEF, DEF, DEF, DEF, DEF, /* 38-3F */
4279 L, AL, AL, AL, AL, AL, AL, R, /* 40-47 */
4280 R, R, R, R, R, R, R, R, /* 48-4F */
4281 R, R, R, R, R, R, R, R, /* 50-57 */
4282 R, R, R, LRE, DEF, RLE, PDF, S, /* 58-5F */
4283 NSM, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 60-67 */
4284 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 68-6F */
4285 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 70-77 */
4286 DEF, DEF, DEF, LRO, B, RLO, BN, DEF /* 78-7F */
4288 static const int nEntries = LENGTHOF(customClasses);
4289 const char *dummy = context; /* just to avoid a compiler warning */
4292 return c >= nEntries ? U_BIDI_CLASS_DEFAULT : customClasses[c];
4297 static void verifyCallbackParams(UBiDiClassCallback* fn, const void* context,
4298 UBiDiClassCallback* expectedFn,
4299 const void* expectedContext,
4300 int32_t sizeOfContext) {
4301 if (fn != expectedFn) {
4302 log_err("Class callback pointer is not set properly.\n");
4304 if (context != expectedContext) {
4305 log_err("Class callback context is not set properly.\n");
4307 else if (context != NULL &&
4308 memcmp(context, expectedContext, sizeOfContext)) {
4309 log_err("Callback context content doesn't match the expected one.\n");
4314 testClassOverride(void) {
4315 static const char* const textSrc = "JIH.>12->a \\u05D0\\u05D1 6 ABC78";
4316 static const char* const textResult = "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0";
4318 UChar src[MAXLEN], dest[MAXLEN];
4319 UErrorCode rc = U_ZERO_ERROR;
4320 UBiDi *pBiDi = NULL;
4321 UBiDiClassCallback* oldFn = NULL;
4322 UBiDiClassCallback* newFn = overrideBidiClass;
4323 const void* oldContext = NULL;
4324 int32_t srcLen, destLen, textSrcSize = (int32_t)uprv_strlen(textSrc);
4325 char* destChars = NULL;
4327 log_verbose("\nEntering TestClassOverride\n\n");
4329 pBiDi = getBiDiObject();
4334 ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
4335 verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
4337 ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
4338 if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
4342 verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
4344 ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
4345 verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
4347 ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
4348 if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
4352 verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
4354 srcLen = u_unescape(textSrc, src, MAXLEN);
4355 ubidi_setPara(pBiDi, src, srcLen, UBIDI_LTR, NULL, &rc);
4356 assertSuccessful("ubidi_setPara", &rc);
4358 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
4359 UBIDI_DO_MIRRORING, &rc);
4360 assertSuccessful("ubidi_writeReordered", &rc);
4362 destChars = aescstrdup(dest, destLen);
4363 if (uprv_strcmp(textResult, destChars)) {
4364 log_err("\nActual and expected output mismatch.\n"
4365 "%20s %s\n%20s %s\n%20s %s\n",
4366 "Input:", textSrc, "Actual output:", destChars,
4367 "Expected output:", textResult);
4370 log_verbose("\nClass override test OK\n");
4373 log_verbose("\nExiting TestClassOverride\n\n");
4376 static char * formatMap(const int32_t * map, int len, char * buffer)
4380 for (i = 0; i < len; i++) {
4384 else if (k >= sizeof(columns))
4395 checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, const char *dest,
4396 const char *mode, const char* option, UBiDiLevel level, UBool forward)
4398 int32_t actualLogicalMap[MAX_MAP_LENGTH];
4399 int32_t actualVisualMap[MAX_MAP_LENGTH];
4400 int32_t getIndexMap[MAX_MAP_LENGTH];
4401 int32_t i, srcLen, resLen, idx;
4402 const int32_t *expectedLogicalMap, *expectedVisualMap;
4403 UErrorCode rc = U_ZERO_ERROR;
4404 UBool testOK = TRUE;
4407 expectedLogicalMap = forwardMap[stringIndex];
4408 expectedVisualMap = inverseMap[stringIndex];
4411 expectedLogicalMap = inverseMap[stringIndex];
4412 expectedVisualMap = forwardMap[stringIndex];
4414 ubidi_getLogicalMap(pBiDi, actualLogicalMap, &rc);
4415 if (!assertSuccessful("ubidi_getLogicalMap", &rc)) {
4418 srcLen = ubidi_getProcessedLength(pBiDi);
4419 if (memcmp(expectedLogicalMap, actualLogicalMap, srcLen * sizeof(int32_t))) {
4420 char expChars[MAX_MAP_LENGTH];
4421 char actChars[MAX_MAP_LENGTH];
4422 log_err("\nubidi_getLogicalMap() returns unexpected map for output string "
4429 "Paragraph level : %d == %d\n"
4430 "Reordering mode : %s == %d\n"
4431 "Reordering option: %s == %d\n"
4432 "Forward flag : %d\n",
4433 stringIndex, src, dest, columns,
4434 formatMap(expectedLogicalMap, srcLen, expChars),
4435 formatMap(actualLogicalMap, srcLen, actChars),
4436 level, ubidi_getParaLevel(pBiDi),
4437 mode, ubidi_getReorderingMode(pBiDi),
4438 option, ubidi_getReorderingOptions(pBiDi),
4443 resLen = ubidi_getResultLength(pBiDi);
4444 ubidi_getVisualMap(pBiDi, actualVisualMap, &rc);
4445 assertSuccessful("ubidi_getVisualMap", &rc);
4446 if (memcmp(expectedVisualMap, actualVisualMap, resLen * sizeof(int32_t))) {
4447 char expChars[MAX_MAP_LENGTH];
4448 char actChars[MAX_MAP_LENGTH];
4449 log_err("\nubidi_getVisualMap() returns unexpected map for output string "
4456 "Paragraph level : %d == %d\n"
4457 "Reordering mode : %s == %d\n"
4458 "Reordering option: %s == %d\n"
4459 "Forward flag : %d\n",
4460 stringIndex, src, dest, columns,
4461 formatMap(expectedVisualMap, resLen, expChars),
4462 formatMap(actualVisualMap, resLen, actChars),
4463 level, ubidi_getParaLevel(pBiDi),
4464 mode, ubidi_getReorderingMode(pBiDi),
4465 option, ubidi_getReorderingOptions(pBiDi),
4470 for (i = 0; i < srcLen; i++) {
4471 idx = ubidi_getVisualIndex(pBiDi, i, &rc);
4472 assertSuccessful("ubidi_getVisualIndex", &rc);
4473 getIndexMap[i] = idx;
4475 if (memcmp(actualLogicalMap, getIndexMap, srcLen * sizeof(int32_t))) {
4476 char actChars[MAX_MAP_LENGTH];
4477 char gotChars[MAX_MAP_LENGTH];
4478 log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string "
4485 "Paragraph level : %d == %d\n"
4486 "Reordering mode : %s == %d\n"
4487 "Reordering option: %s == %d\n"
4488 "Forward flag : %d\n",
4489 stringIndex, src, dest, columns,
4490 formatMap(actualLogicalMap, srcLen, actChars),
4491 formatMap(getIndexMap, srcLen, gotChars),
4492 level, ubidi_getParaLevel(pBiDi),
4493 mode, ubidi_getReorderingMode(pBiDi),
4494 option, ubidi_getReorderingOptions(pBiDi),
4499 for (i = 0; i < resLen; i++) {
4500 idx = ubidi_getLogicalIndex(pBiDi, i, &rc);
4501 assertSuccessful("ubidi_getLogicalIndex", &rc);
4502 getIndexMap[i] = idx;
4504 if (memcmp(actualVisualMap, getIndexMap, resLen * sizeof(int32_t))) {
4505 char actChars[MAX_MAP_LENGTH];
4506 char gotChars[MAX_MAP_LENGTH];
4507 log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string "
4514 "Paragraph level : %d == %d\n"
4515 "Reordering mode : %s == %d\n"
4516 "Reordering option: %s == %d\n"
4517 "Forward flag : %d\n",
4518 stringIndex, src, dest, columns,
4519 formatMap(actualVisualMap, resLen, actChars),
4520 formatMap(getIndexMap, resLen, gotChars),
4521 level, ubidi_getParaLevel(pBiDi),
4522 mode, ubidi_getReorderingMode(pBiDi),
4523 option, ubidi_getReorderingOptions(pBiDi),
4532 assertIllegalArgument(const char* message, UErrorCode* rc) {
4533 if (*rc != U_ILLEGAL_ARGUMENT_ERROR) {
4534 log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
4541 const char* prologue;
4543 const char* epilogue;
4544 const char* expected;
4545 UBiDiLevel paraLevel;
4548 static const contextCase contextData[] = {
4549 /*00*/ {"", "", "", "", UBIDI_LTR},
4550 /*01*/ {"", ".-=JKL-+*", "", ".-=LKJ-+*", UBIDI_LTR},
4551 /*02*/ {" ", ".-=JKL-+*", " ", ".-=LKJ-+*", UBIDI_LTR},
4552 /*03*/ {"a", ".-=JKL-+*", "b", ".-=LKJ-+*", UBIDI_LTR},
4553 /*04*/ {"D", ".-=JKL-+*", "", "LKJ=-.-+*", UBIDI_LTR},
4554 /*05*/ {"", ".-=JKL-+*", " D", ".-=*+-LKJ", UBIDI_LTR},
4555 /*06*/ {"", ".-=JKL-+*", " 2", ".-=*+-LKJ", UBIDI_LTR},
4556 /*07*/ {"", ".-=JKL-+*", " 7", ".-=*+-LKJ", UBIDI_LTR},
4557 /*08*/ {" G 1", ".-=JKL-+*", " H", "*+-LKJ=-.", UBIDI_LTR},
4558 /*09*/ {"7", ".-=JKL-+*", " H", ".-=*+-LKJ", UBIDI_LTR},
4559 /*10*/ {"", ".-=abc-+*", "", "*+-abc=-.", UBIDI_RTL},
4560 /*11*/ {" ", ".-=abc-+*", " ", "*+-abc=-.", UBIDI_RTL},
4561 /*12*/ {"D", ".-=abc-+*", "G", "*+-abc=-.", UBIDI_RTL},
4562 /*13*/ {"x", ".-=abc-+*", "", "*+-.-=abc", UBIDI_RTL},
4563 /*14*/ {"", ".-=abc-+*", " y", "abc-+*=-.", UBIDI_RTL},
4564 /*15*/ {"", ".-=abc-+*", " 2", "abc-+*=-.", UBIDI_RTL},
4565 /*16*/ {" x 1", ".-=abc-+*", " 2", ".-=abc-+*", UBIDI_RTL},
4566 /*17*/ {" x 7", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL},
4567 /*18*/ {"x|", ".-=abc-+*", " 8", "*+-abc=-.", UBIDI_RTL},
4568 /*19*/ {"G|y", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL},
4569 /*20*/ {"", ".-=", "", ".-=", UBIDI_DEFAULT_LTR},
4570 /*21*/ {"D", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
4571 /*22*/ {"G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
4572 /*23*/ {"xG", ".-=", "", ".-=", UBIDI_DEFAULT_LTR},
4573 /*24*/ {"x|G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
4574 /*25*/ {"x|G", ".-=|-+*", "", "=-.|-+*", UBIDI_DEFAULT_LTR},
4576 #define CONTEXT_COUNT LENGTHOF(contextData)
4581 UChar prologue[MAXLEN], epilogue[MAXLEN], src[MAXLEN], dest[MAXLEN];
4582 char destChars[MAXLEN];
4583 UBiDi *pBiDi = NULL;
4585 int32_t proLength, epiLength, srcLen, destLen, tc;
4587 UBool testOK = TRUE;
4589 log_verbose("\nEntering TestContext \n\n");
4591 /* test null BiDi object */
4593 ubidi_setContext(pBiDi, NULL, 0, NULL, 0, &rc);
4594 testOK &= assertIllegalArgument("Error when BiDi object is null", &rc);
4596 pBiDi = getBiDiObject();
4597 ubidi_orderParagraphsLTR(pBiDi, TRUE);
4599 /* test proLength < -1 */
4601 ubidi_setContext(pBiDi, NULL, -2, NULL, 0, &rc);
4602 testOK &= assertIllegalArgument("Error when proLength < -1", &rc);
4603 /* test epiLength < -1 */
4605 ubidi_setContext(pBiDi, NULL, 0, NULL, -2, &rc);
4606 testOK &= assertIllegalArgument("Error when epiLength < -1", &rc);
4607 /* test prologue == NULL */
4609 ubidi_setContext(pBiDi, NULL, 3, NULL, 0, &rc);
4610 testOK &= assertIllegalArgument("Prologue is NULL", &rc);
4611 /* test epilogue == NULL */
4613 ubidi_setContext(pBiDi, NULL, 0, NULL, 4, &rc);
4614 testOK &= assertIllegalArgument("Epilogue is NULL", &rc);
4616 for (tc = 0; tc < CONTEXT_COUNT; tc++) {
4617 cc = contextData[tc];
4618 proLength = strlen(cc.prologue);
4619 pseudoToU16(proLength, cc.prologue, prologue);
4620 epiLength = strlen(cc.epilogue);
4621 pseudoToU16(epiLength, cc.epilogue, epilogue);
4622 /* in the call below, prologue and epilogue are swapped to show
4623 that the next call will override this call */
4625 ubidi_setContext(pBiDi, epilogue, epiLength, prologue, proLength, &rc);
4626 testOK &= assertSuccessful("swapped ubidi_setContext", &rc);
4627 ubidi_setContext(pBiDi, prologue, -1, epilogue, -1, &rc);
4628 testOK &= assertSuccessful("regular ubidi_setContext", &rc);
4629 srcLen = strlen(cc.source);
4630 pseudoToU16(srcLen, cc.source, src);
4631 ubidi_setPara(pBiDi, src, srcLen, cc.paraLevel, NULL, &rc);
4632 testOK &= assertSuccessful("ubidi_setPara", &rc);
4633 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
4634 assertSuccessful("ubidi_writeReordered", &rc);
4635 u16ToPseudo(destLen, dest, destChars);
4636 if (uprv_strcmp(cc.expected, destChars)) {
4637 char formatChars[MAXLEN];
4638 log_err("\nActual and expected output mismatch on case %d.\n"
4639 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d\n%20s %u\n%20s %d\n",
4641 "Prologue:", cc.prologue,
4642 "Input:", cc.source,
4643 "Epilogue:", cc.epilogue,
4644 "Expected output:", cc.expected,
4645 "Actual output:", destChars,
4646 "Levels:", formatLevels(pBiDi, formatChars),
4647 "Reordering mode:", ubidi_getReorderingMode(pBiDi),
4648 "Paragraph level:", ubidi_getParaLevel(pBiDi),
4649 "Reordering option:", ubidi_getReorderingOptions(pBiDi));
4653 if (testOK == TRUE) {
4654 log_verbose("\nContext test OK\n");
4658 log_verbose("\nExiting TestContext \n\n");
4661 /* Ticket#11054 ubidi_setPara crash with heavily nested brackets */
4663 testBracketOverflow(void) {
4664 static const char* TEXT = "(((((((((((((((((((((((((((((((((((((((((a)(A)))))))))))))))))))))))))))))))))))))))))";
4665 UErrorCode status = U_ZERO_ERROR;
4671 bidi = ubidi_open();
4672 len = uprv_strlen(TEXT);
4673 pseudoToU16(len, TEXT, src);
4674 ubidi_setPara(bidi, src, len, UBIDI_DEFAULT_LTR , NULL, &status);
4675 if (U_FAILURE(status)) {
4676 log_err("setPara failed with heavily nested brackets - %s", u_errorName(status));