1 /********************************************************************
3 * Copyright (c) 1997-2014, 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 _testPresentationForms(const UChar
*in
);
75 static void doArabicShapingTestForNewCharacters(void);
77 static void testReorder(void);
79 static void testReorderArabicMathSymbols(void);
81 static void testFailureRecovery(void);
83 static void testMultipleParagraphs(void);
85 static void testGetBaseDirection(void);
87 static void testContext(void);
89 static void doTailTest(void);
92 static void testReorderingMode(void);
93 static void testReorderRunsOnly(void);
94 static void testStreaming(void);
95 static void testClassOverride(void);
96 static const char* inverseBasic(UBiDi
*pBiDi
, const char *src
, int32_t srcLen
,
97 uint32_t option
, UBiDiLevel level
, char *result
);
98 static UBool
assertRoundTrip(UBiDi
*pBiDi
, int32_t tc
, int32_t outIndex
,
99 const char *srcChars
, const char *destChars
,
100 const UChar
*dest
, int32_t destLen
, int mode
,
101 int option
, UBiDiLevel level
);
102 static UBool
checkResultLength(UBiDi
*pBiDi
, const char *srcChars
,
103 const char *destChars
,
104 int32_t destLen
, const char *mode
,
105 const char *option
, UBiDiLevel level
);
106 static UBool
checkMaps(UBiDi
*pBiDi
, int32_t stringIndex
, const char *src
,
107 const char *dest
, const char *mode
, const char* option
,
108 UBiDiLevel level
, UBool forward
);
110 /* helpers ------------------------------------------------------------------ */
112 static const char *levelString
="...............................................................";
114 static void initCharFromDirProps(void);
117 getStringFromDirProps(const uint8_t *dirProps
, int32_t length
, UChar
*buffer
);
119 static void printUnicode(const UChar
*s
, int32_t length
, const UBiDiLevel
*levels
);
121 /* regression tests ---------------------------------------------------------*/
124 addComplexTest(TestNode
** root
) {
125 addTest(root
, testCharFromDirProp
, "complex/bidi/TestCharFromDirProp");
126 addTest(root
, testBidi
, "complex/bidi/TestBidi");
127 addTest(root
, testInverse
, "complex/bidi/TestInverse");
128 addTest(root
, testReorder
,"complex/bidi/TestReorder");
129 addTest(root
, testFailureRecovery
,"complex/bidi/TestFailureRecovery");
130 addTest(root
, testMultipleParagraphs
,"complex/bidi/TestMultipleParagraphs");
131 addTest(root
, testReorderingMode
, "complex/bidi/TestReorderingMode");
132 addTest(root
, testReorderRunsOnly
, "complex/bidi/TestReorderRunsOnly");
133 addTest(root
, testStreaming
, "complex/bidi/TestStreaming");
134 addTest(root
, testClassOverride
, "complex/bidi/TestClassOverride");
135 addTest(root
, testGetBaseDirection
, "complex/bidi/testGetBaseDirection");
136 addTest(root
, testContext
, "complex/bidi/testContext");
138 addTest(root
, doArabicShapingTest
, "complex/arabic-shaping/ArabicShapingTest");
139 addTest(root
, doLamAlefSpecialVLTRArabicShapingTest
, "complex/arabic-shaping/lamalef");
140 addTest(root
, doTashkeelSpecialVLTRArabicShapingTest
, "complex/arabic-shaping/tashkeel");
141 addTest(root
, doLOGICALArabicDeShapingTest
, "complex/arabic-shaping/unshaping");
142 addTest(root
, doArabicShapingTestForBug5421
, "complex/arabic-shaping/bug-5421");
143 addTest(root
, doTailTest
, "complex/arabic-shaping/tailtest");
144 addTest(root
, doArabicShapingTestForBug8703
, "complex/arabic-shaping/bug-8703");
145 addTest(root
, testReorderArabicMathSymbols
, "complex/bidi/bug-9024");
146 addTest(root
, doArabicShapingTestForBug9024
, "complex/arabic-shaping/bug-9024");
147 addTest(root
, doArabicShapingTestForNewCharacters
, "complex/arabic-shaping/shaping2");
151 testCharFromDirProp(void) {
152 /* verify that the exemplar characters have the expected bidi classes */
155 log_verbose("\nEntering TestCharFromDirProp\n\n");
156 initCharFromDirProps();
158 for(i
=0; i
<U_CHAR_DIRECTION_COUNT
; ++i
) {
159 if(u_charDirection(charFromDirProp
[i
])!=(UCharDirection
)i
) {
160 log_err("\nu_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n",
161 i
, charFromDirProp
[i
], u_charDirection(charFromDirProp
[i
]), i
);
164 log_verbose("\nExiting TestCharFromDirProp\n\n");
169 UBiDi
*pBiDi
, *pLine
=NULL
;
170 UErrorCode errorCode
=U_ZERO_ERROR
;
172 log_verbose("\nEntering TestBidi\n\n");
174 pBiDi
=ubidi_openSized(MAXLEN
, 0, &errorCode
);
178 doTests(pBiDi
, pLine
, FALSE
);
179 doTests(pBiDi
, pLine
, TRUE
);
181 log_err("ubidi_open() returned NULL, out of memory\n");
184 log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode
));
195 log_verbose("\nExiting TestBidi\n\n");
199 doTests(UBiDi
*pBiDi
, UBiDi
*pLine
, UBool countRunsFirst
) {
201 UChar string
[MAXLEN
];
202 UErrorCode errorCode
;
204 UBiDiLevel paraLevel
;
206 for(testNumber
=0; testNumber
<bidiTestCount
; ++testNumber
) {
207 errorCode
=U_ZERO_ERROR
;
208 getStringFromDirProps(tests
[testNumber
].text
, tests
[testNumber
].length
, string
);
209 paraLevel
=tests
[testNumber
].paraLevel
;
210 ubidi_setPara(pBiDi
, string
, -1, paraLevel
, NULL
, &errorCode
);
211 if(U_SUCCESS(errorCode
)) {
212 log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n",
213 testNumber
, paraLevel
, ubidi_getDirection(pBiDi
), paraLevel
);
214 lineStart
=tests
[testNumber
].lineStart
;
216 doTest(pBiDi
, testNumber
, tests
+testNumber
, 0, countRunsFirst
);
218 ubidi_setLine(pBiDi
, lineStart
, tests
[testNumber
].lineLimit
, pLine
, &errorCode
);
219 if(U_SUCCESS(errorCode
)) {
220 log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n",
221 lineStart
, tests
[testNumber
].lineLimit
, ubidi_getDirection(pLine
), ubidi_getParaLevel(pLine
));
222 doTest(pLine
, testNumber
, tests
+testNumber
, lineStart
, countRunsFirst
);
224 log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n",
225 testNumber
, lineStart
, tests
[testNumber
].lineLimit
, myErrorName(errorCode
));
229 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
230 testNumber
, paraLevel
, myErrorName(errorCode
));
235 static const char columns
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
237 #define TABLE_SIZE 256
238 static UBool tablesInitialized
= FALSE
;
239 static UChar pseudoToUChar
[TABLE_SIZE
];
240 static uint8_t UCharToPseudo
[TABLE_SIZE
]; /* used for Unicode chars < 0x0100 */
241 static uint8_t UCharToPseud2
[TABLE_SIZE
]; /* used for Unicode chars >=0x0100 */
243 static void buildPseudoTables(void)
245 The rules for pseudo-Bidi are as follows:
253 - A-F == Arabic Letters 0631-0636
254 - G-V == Hebrew letters 05d7-05e6
255 - W-Z == Unassigned RTL 08d0-08d3
256 - 0-5 == western digits 0030-0035
257 - 6-9 == Arabic-Indic digits 0666-0669
258 - ` == Combining Grave Accent 0300 (NSM)
259 - ~ == Delete 007f (BN)
260 - | == Paragraph Separator 2029 (B)
261 - _ == Info Separator 1 001f (S)
262 All other characters represent themselves as Latin-1, with the corresponding
269 /* initialize all tables to unknown */
270 for (i
=0; i
< TABLE_SIZE
; i
++) {
271 pseudoToUChar
[i
] = 0xFFFD;
272 UCharToPseudo
[i
] = '?';
273 UCharToPseud2
[i
] = '?';
275 /* initialize non letters or digits */
276 pseudoToUChar
[(uint8_t) 0 ] = 0x0000; UCharToPseudo
[0x00] = (uint8_t) 0 ;
277 pseudoToUChar
[(uint8_t)' '] = 0x0020; UCharToPseudo
[0x20] = (uint8_t)' ';
278 pseudoToUChar
[(uint8_t)'!'] = 0x0021; UCharToPseudo
[0x21] = (uint8_t)'!';
279 pseudoToUChar
[(uint8_t)'"'] = 0x0022; UCharToPseudo
[0x22] = (uint8_t)'"';
280 pseudoToUChar
[(uint8_t)'#'] = 0x0023; UCharToPseudo
[0x23] = (uint8_t)'#';
281 pseudoToUChar
[(uint8_t)'$'] = 0x0024; UCharToPseudo
[0x24] = (uint8_t)'$';
282 pseudoToUChar
[(uint8_t)'%'] = 0x0025; UCharToPseudo
[0x25] = (uint8_t)'%';
283 pseudoToUChar
[(uint8_t)'\'']= 0x0027; UCharToPseudo
[0x27] = (uint8_t)'\'';
284 pseudoToUChar
[(uint8_t)'('] = 0x0028; UCharToPseudo
[0x28] = (uint8_t)'(';
285 pseudoToUChar
[(uint8_t)')'] = 0x0029; UCharToPseudo
[0x29] = (uint8_t)')';
286 pseudoToUChar
[(uint8_t)'*'] = 0x002A; UCharToPseudo
[0x2A] = (uint8_t)'*';
287 pseudoToUChar
[(uint8_t)'+'] = 0x002B; UCharToPseudo
[0x2B] = (uint8_t)'+';
288 pseudoToUChar
[(uint8_t)','] = 0x002C; UCharToPseudo
[0x2C] = (uint8_t)',';
289 pseudoToUChar
[(uint8_t)'-'] = 0x002D; UCharToPseudo
[0x2D] = (uint8_t)'-';
290 pseudoToUChar
[(uint8_t)'.'] = 0x002E; UCharToPseudo
[0x2E] = (uint8_t)'.';
291 pseudoToUChar
[(uint8_t)'/'] = 0x002F; UCharToPseudo
[0x2F] = (uint8_t)'/';
292 pseudoToUChar
[(uint8_t)':'] = 0x003A; UCharToPseudo
[0x3A] = (uint8_t)':';
293 pseudoToUChar
[(uint8_t)';'] = 0x003B; UCharToPseudo
[0x3B] = (uint8_t)';';
294 pseudoToUChar
[(uint8_t)'<'] = 0x003C; UCharToPseudo
[0x3C] = (uint8_t)'<';
295 pseudoToUChar
[(uint8_t)'='] = 0x003D; UCharToPseudo
[0x3D] = (uint8_t)'=';
296 pseudoToUChar
[(uint8_t)'>'] = 0x003E; UCharToPseudo
[0x3E] = (uint8_t)'>';
297 pseudoToUChar
[(uint8_t)'?'] = 0x003F; UCharToPseudo
[0x3F] = (uint8_t)'?';
298 pseudoToUChar
[(uint8_t)'\\']= 0x005C; UCharToPseudo
[0x5C] = (uint8_t)'\\';
299 /* initialize specially used characters */
300 pseudoToUChar
[(uint8_t)'`'] = 0x0300; UCharToPseud2
[0x00] = (uint8_t)'`'; /* NSM */
301 pseudoToUChar
[(uint8_t)'@'] = 0x200E; UCharToPseud2
[0x0E] = (uint8_t)'@'; /* LRM */
302 pseudoToUChar
[(uint8_t)'&'] = 0x200F; UCharToPseud2
[0x0F] = (uint8_t)'&'; /* RLM */
303 pseudoToUChar
[(uint8_t)'_'] = 0x001F; UCharToPseudo
[0x1F] = (uint8_t)'_'; /* S */
304 pseudoToUChar
[(uint8_t)'|'] = 0x2029; UCharToPseud2
[0x29] = (uint8_t)'|'; /* B */
305 pseudoToUChar
[(uint8_t)'['] = 0x202A; UCharToPseud2
[0x2A] = (uint8_t)'['; /* LRE */
306 pseudoToUChar
[(uint8_t)']'] = 0x202B; UCharToPseud2
[0x2B] = (uint8_t)']'; /* RLE */
307 pseudoToUChar
[(uint8_t)'^'] = 0x202C; UCharToPseud2
[0x2C] = (uint8_t)'^'; /* PDF */
308 pseudoToUChar
[(uint8_t)'{'] = 0x202D; UCharToPseud2
[0x2D] = (uint8_t)'{'; /* LRO */
309 pseudoToUChar
[(uint8_t)'}'] = 0x202E; UCharToPseud2
[0x2E] = (uint8_t)'}'; /* RLO */
310 pseudoToUChar
[(uint8_t)'~'] = 0x007F; UCharToPseudo
[0x7F] = (uint8_t)'~'; /* BN */
311 /* initialize western digits */
312 for (i
= 0, uchar
= 0x0030; i
< 6; i
++, uchar
++) {
313 c
= (uint8_t)columns
[i
];
314 pseudoToUChar
[c
] = uchar
;
315 UCharToPseudo
[uchar
& 0x00ff] = c
;
317 /* initialize Hindi digits */
318 for (i
= 6, uchar
= 0x0666; i
< 10; i
++, uchar
++) {
319 c
= (uint8_t)columns
[i
];
320 pseudoToUChar
[c
] = uchar
;
321 UCharToPseud2
[uchar
& 0x00ff] = c
;
323 /* initialize Arabic letters */
324 for (i
= 10, uchar
= 0x0631; i
< 16; i
++, uchar
++) {
325 c
= (uint8_t)columns
[i
];
326 pseudoToUChar
[c
] = uchar
;
327 UCharToPseud2
[uchar
& 0x00ff] = c
;
329 /* initialize Hebrew letters */
330 for (i
= 16, uchar
= 0x05D7; i
< 32; i
++, uchar
++) {
331 c
= (uint8_t)columns
[i
];
332 pseudoToUChar
[c
] = uchar
;
333 UCharToPseud2
[uchar
& 0x00ff] = c
;
335 /* initialize Unassigned code points */
336 for (i
= 32, uchar
=0x08D0; i
< 36; i
++, uchar
++) {
337 c
= (uint8_t)columns
[i
];
338 pseudoToUChar
[c
] = uchar
;
339 UCharToPseud2
[uchar
& 0x00ff] = c
;
341 /* initialize Latin lower case letters */
342 for (i
= 36, uchar
= 0x0061; i
< 62; i
++, uchar
++) {
343 c
= (uint8_t)columns
[i
];
344 pseudoToUChar
[c
] = uchar
;
345 UCharToPseudo
[uchar
& 0x00ff] = c
;
347 tablesInitialized
= TRUE
;
350 /*----------------------------------------------------------------------*/
352 static int pseudoToU16(const int length
, const char * input
, UChar
* output
)
353 /* This function converts a pseudo-Bidi string into a UChar string.
354 It returns the length of the UChar string.
358 if (!tablesInitialized
) {
361 for (i
= 0; i
< length
; i
++)
362 output
[i
] = pseudoToUChar
[(uint8_t)input
[i
]];
367 /*----------------------------------------------------------------------*/
369 static int u16ToPseudo(const int length
, const UChar
* input
, char * output
)
370 /* This function converts a UChar string into a pseudo-Bidi string.
371 It returns the length of the pseudo-Bidi string.
376 if (!tablesInitialized
) {
379 for (i
= 0; i
< length
; i
++)
382 output
[i
] = uchar
< 0x0100 ? UCharToPseudo
[uchar
] :
383 UCharToPseud2
[uchar
& 0x00ff];
385 output
[length
] = '\0';
389 static char * formatLevels(UBiDi
*bidi
, char *buffer
) {
390 UErrorCode ec
= U_ZERO_ERROR
;
391 const UBiDiLevel
* gotLevels
= ubidi_getLevels(bidi
, &ec
);
392 int len
= ubidi_getLength(bidi
);
397 strcpy(buffer
, "BAD LEVELS");
400 for (i
=0; i
<len
; i
++) {
402 if (k
>= sizeof(columns
))
411 static const char *reorderingModeNames
[] = {
412 "UBIDI_REORDER_DEFAULT",
413 "UBIDI_REORDER_NUMBERS_SPECIAL",
414 "UBIDI_REORDER_GROUP_NUMBERS_WITH_R",
415 "UBIDI_REORDER_RUNS_ONLY",
416 "UBIDI_REORDER_INVERSE_NUMBERS_AS_L",
417 "UBIDI_REORDER_INVERSE_LIKE_DIRECT",
418 "UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL"};
420 static char *reorderingOptionNames(char *buffer
, int options
) {
422 if (options
& UBIDI_OPTION_INSERT_MARKS
) {
423 strcat(buffer
, " UBIDI_OPTION_INSERT_MARKS");
425 if (options
& UBIDI_OPTION_REMOVE_CONTROLS
) {
426 strcat(buffer
, " UBIDI_OPTION_REMOVE_CONTROLS");
428 if (options
& UBIDI_OPTION_STREAMING
) {
429 strcat(buffer
, " UBIDI_OPTION_STREAMING");
434 static void printCaseInfo(UBiDi
*bidi
, const char *src
, const char *dst
)
435 /* src and dst are char arrays encoded as pseudo Bidi */
437 /* Since calls to log_err with a \n within the pattern increment the
438 * error count, new lines are issued via fputs, except when we want the
439 * increment to happen.
441 UErrorCode errorCode
=U_ZERO_ERROR
;
442 int32_t i
, length
= ubidi_getProcessedLength(bidi
);
443 const UBiDiLevel
*levels
;
444 char levelChars
[MAXLEN
];
448 log_err("========================================"); fputs("\n", stderr
);
449 levels
= ubidi_getLevels(bidi
, &errorCode
);
450 if (U_FAILURE(errorCode
)) {
451 strcpy(levelChars
, "BAD LEVELS");
453 log_err("Processed length: %d", length
); fputs("\n", stderr
);
454 for (i
= 0; i
< length
; i
++) {
456 if (lev
< sizeof(columns
)) {
457 levelChars
[i
] = columns
[lev
];
462 levelChars
[length
] = 0;
464 log_err("Levels: %s", levelChars
); fputs("\n", stderr
);
465 log_err("Source: %s", src
); fputs("\n", stderr
);
466 log_err("Result: %s", dst
); fputs("\n", stderr
);
467 log_err("Direction: %d", ubidi_getDirection(bidi
)); fputs("\n", stderr
);
468 log_err("paraLevel: %d", ubidi_getParaLevel(bidi
)); fputs("\n", stderr
);
469 i
= ubidi_getReorderingMode(bidi
);
470 log_err("reorderingMode: %d = %s", i
, reorderingModeNames
[i
]);
472 i
= ubidi_getReorderingOptions(bidi
);
473 log_err("reorderingOptions: %d = %s", i
, reorderingOptionNames(buffer
, i
));
475 runCount
= ubidi_countRuns(bidi
, &errorCode
);
476 if (U_FAILURE(errorCode
)) {
477 log_err( "BAD RUNS");
479 log_err("Runs: %d => logicalStart.length/level: ", runCount
);
480 for (i
= 0; i
< runCount
; i
++) {
483 dir
= ubidi_getVisualRun(bidi
, i
, &start
, &len
);
484 log_err(" %d.%d/%d", start
, len
, dir
);
490 static UBool
matchingPair(UBiDi
*bidi
, int32_t i
, char c1
, char c2
)
492 /* No test for []{} since they have special meaning for pseudo Bidi */
493 static char mates1Chars
[] = "<>()";
494 static char mates2Chars
[] = "><)(";
501 /* For UBIDI_REORDER_RUNS_ONLY, it would not be correct to check levels[i],
502 so we use the appropriate run's level, which is good for all cases.
504 ubidi_getLogicalRun(bidi
, i
, NULL
, &level
);
505 if ((level
& 1) == 0) {
508 len
= strlen(mates1Chars
);
509 for (k
= 0; k
< len
; k
++) {
510 if ((c1
== mates1Chars
[k
]) && (c2
== mates2Chars
[k
])) {
517 static UBool
checkWhatYouCan(UBiDi
*bidi
, const char *srcChars
, const char *dstChars
)
518 /* srcChars and dstChars are char arrays encoded as pseudo Bidi */
520 int32_t i
, idx
, logLimit
, visLimit
;
521 UBool testOK
, errMap
, errDst
;
522 UErrorCode errorCode
=U_ZERO_ERROR
;
523 int32_t visMap
[MAXLEN
];
524 int32_t logMap
[MAXLEN
];
525 char accumSrc
[MAXLEN
];
526 char accumDst
[MAXLEN
];
527 ubidi_getVisualMap(bidi
, visMap
, &errorCode
);
528 ubidi_getLogicalMap(bidi
, logMap
, &errorCode
);
529 if (U_FAILURE(errorCode
)) {
530 log_err("Error #1 invoking ICU within checkWhatYouCan\n");
535 errMap
= errDst
= FALSE
;
536 logLimit
= ubidi_getProcessedLength(bidi
);
537 visLimit
= ubidi_getResultLength(bidi
);
538 memset(accumSrc
, '?', logLimit
);
539 memset(accumDst
, '?', visLimit
);
541 for (i
= 0; i
< logLimit
; i
++) {
542 idx
= ubidi_getVisualIndex(bidi
, i
, &errorCode
);
543 if (idx
!= logMap
[i
]) {
546 if (idx
== UBIDI_MAP_NOWHERE
) {
549 if (idx
>= visLimit
) {
552 accumDst
[idx
] = srcChars
[i
];
553 if (!matchingPair(bidi
, i
, srcChars
[i
], dstChars
[idx
])) {
557 accumDst
[visLimit
] = 0;
558 if (U_FAILURE(errorCode
)) {
559 log_err("Error #2 invoking ICU within checkWhatYouCan\n");
564 printCaseInfo(bidi
, srcChars
, dstChars
);
567 log_err("Mismatch between getLogicalMap() and getVisualIndex()\n");
569 for (i
= 0; i
< logLimit
; i
++) {
570 log_err(" %d", logMap
[i
]);
574 for (i
= 0; i
< logLimit
; i
++) {
575 log_err(" %d", ubidi_getVisualIndex(bidi
, i
, &errorCode
));
581 printCaseInfo(bidi
, srcChars
, dstChars
);
584 log_err("Source does not map to Result\n");
585 log_err("We got: %s", accumDst
); fputs("\n", stderr
);
588 errMap
= errDst
= FALSE
;
589 for (i
= 0; i
< visLimit
; i
++) {
590 idx
= ubidi_getLogicalIndex(bidi
, i
, &errorCode
);
591 if (idx
!= visMap
[i
]) {
594 if (idx
== UBIDI_MAP_NOWHERE
) {
597 if (idx
>= logLimit
) {
600 accumSrc
[idx
] = dstChars
[i
];
601 if (!matchingPair(bidi
, idx
, srcChars
[idx
], dstChars
[i
])) {
605 accumSrc
[logLimit
] = 0;
606 if (U_FAILURE(errorCode
)) {
607 log_err("Error #3 invoking ICU within checkWhatYouCan\n");
612 printCaseInfo(bidi
, srcChars
, dstChars
);
615 log_err("Mismatch between getVisualMap() and getLogicalIndex()\n");
617 for (i
= 0; i
< visLimit
; i
++) {
618 log_err(" %d", visMap
[i
]);
622 for (i
= 0; i
< visLimit
; i
++) {
623 log_err(" %d", ubidi_getLogicalIndex(bidi
, i
, &errorCode
));
629 printCaseInfo(bidi
, srcChars
, dstChars
);
632 log_err("Result does not map to Source\n");
633 log_err("We got: %s", accumSrc
);
641 static const char* const logicalOrder
[] ={
643 "del(QDVT) add(BVDL)",
644 "del(PQ)add(R.S.)T)U.&",
645 "del(LV)add(L.V.) L.V.&",
646 "day 0 R DPDHRVR dayabbr",
647 "day 1 H DPHPDHDA dayabbr",
648 "day 2 L DPBLENDA dayabbr",
649 "day 3 J DPJQVM dayabbr",
650 "day 4 I DPIQNF dayabbr",
651 "day 5 M DPMEG dayabbr",
655 static const char* const visualOrder
[]={
657 "del(TVDQ) add(LDVB)",
658 "del(QP)add(S.R.)&.U(T", /* updated for Unicode 6.3 matching brackets */
659 "del(VL)add(V.L.) &.V.L", /* updated for Unicode 6.3 matching brackets */
660 "day 0 RVRHDPD R dayabbr",
661 "day 1 ADHDPHPD H dayabbr",
662 "day 2 ADNELBPD L dayabbr",
663 "day 3 MVQJPD J dayabbr",
664 "day 4 FNQIPD I dayabbr",
665 "day 5 GEMPD M dayabbr",
669 static const char* const visualOrder1
[]={
671 ")BVDL(dda )QDVT(led",
672 "T(U.&).R.S(dda)PQ(led", /* updated for Unicode 6.3 matching brackets */
673 "L.V.& ).L.V(dda)LV(led", /* updated for Unicode 6.3 matching brackets */
674 "rbbayad R DPDHRVR 0 yad",
675 "rbbayad H DPHPDHDA 1 yad",
676 "rbbayad L DPBLENDA 2 yad",
677 "rbbayad J DPJQVM 3 yad",
678 "rbbayad I DPIQNF 4 yad",
679 "rbbayad M DPMEG 5 yad",
684 static const char* const visualOrder2
[]={
685 "@)@K.C.&@(dda)@KC@(led",
686 "@)@BVDL@(dda )@QDVT@(led",
687 "R.S.)T)U.&@(dda)@PQ@(led",
688 "L.V.) L.V.&@(dda)@LV@(led",
689 "rbbayad @R DPDHRVR@ 0 yad",
690 "rbbayad @H DPHPDHDA@ 1 yad",
691 "rbbayad @L DPBLENDA@ 2 yad",
692 "rbbayad @J DPJQVM@ 3 yad",
693 "rbbayad @I DPIQNF@ 4 yad",
694 "rbbayad @M DPMEG@ 5 yad",
698 static const char* const visualOrder3
[]={
700 ")BVDL(ddaQDVT) (led",
701 "R.S.)T)U.&(PQ)dda(led",
702 "L.V.) L.V.&(LV)dda(led",
703 "rbbayad DPDHRVR R 0 yad",
704 "rbbayad DPHPDHDA H 1 yad",
705 "rbbayad DPBLENDA L 2 yad",
706 "rbbayad DPJQVM J 3 yad",
707 "rbbayad DPIQNF I 4 yad",
708 "rbbayad DPMEG M 5 yad",
712 static const char* const visualOrder4
[]={
714 "del( (TVDQadd(LDVB)",
715 "del(add(QP(.U(T(.S.R",
716 "del(add(VL(.V.L (.V.L",
717 "day 0 R RVRHDPD dayabbr",
718 "day 1 H ADHDPHPD dayabbr",
719 "day 2 L ADNELBPD dayabbr",
720 "day 3 J MVQJPD dayabbr",
721 "day 4 I FNQIPD dayabbr",
722 "day 5 M GEMPD dayabbr",
726 char formatChars
[MAXLEN
];
727 UErrorCode ec
= U_ZERO_ERROR
;
728 UBiDi
* bidi
= ubidi_open();
731 log_verbose("\nEntering TestReorder\n\n");
733 for(i
=0;i
<LENGTHOF(logicalOrder
);i
++){
734 int32_t srcSize
= (int32_t)strlen(logicalOrder
[i
]);
735 int32_t destSize
= srcSize
*2;
739 log_verbose("Testing L2V #1 for case %d\n", i
);
740 pseudoToU16(srcSize
,logicalOrder
[i
],src
);
742 ubidi_setPara(bidi
,src
,srcSize
,UBIDI_DEFAULT_LTR
,NULL
,&ec
);
744 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
745 i
, UBIDI_DEFAULT_LTR
, u_errorName(ec
));
747 /* try pre-flighting */
748 destSize
= ubidi_writeReordered(bidi
,dest
,0,UBIDI_DO_MIRRORING
,&ec
);
749 if(ec
!=U_BUFFER_OVERFLOW_ERROR
){
750 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec
));
751 }else if(destSize
!=srcSize
){
752 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize
,destSize
);
756 destSize
=ubidi_writeReordered(bidi
,dest
,destSize
+1,UBIDI_DO_MIRRORING
,&ec
);
757 u16ToPseudo(destSize
,dest
,chars
);
758 if(destSize
!=srcSize
){
759 log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
760 }else if(strcmp(visualOrder
[i
],chars
)!=0){
761 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
762 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
763 logicalOrder
[i
],visualOrder
[i
],chars
,formatLevels(bidi
, formatChars
),i
);
765 checkWhatYouCan(bidi
, logicalOrder
[i
], chars
);
768 for(i
=0;i
<LENGTHOF(logicalOrder
);i
++){
769 int32_t srcSize
= (int32_t)strlen(logicalOrder
[i
]);
770 int32_t destSize
= srcSize
*2;
774 log_verbose("Testing L2V #2 for case %d\n", i
);
775 pseudoToU16(srcSize
,logicalOrder
[i
],src
);
777 ubidi_setPara(bidi
,src
,srcSize
,UBIDI_DEFAULT_LTR
,NULL
,&ec
);
779 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
780 i
, UBIDI_DEFAULT_LTR
, u_errorName(ec
));
782 /* try pre-flighting */
783 destSize
= ubidi_writeReordered(bidi
,dest
,0,UBIDI_DO_MIRRORING
+UBIDI_OUTPUT_REVERSE
,&ec
);
784 if(ec
!=U_BUFFER_OVERFLOW_ERROR
){
785 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec
));
786 }else if(destSize
!=srcSize
){
787 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize
,destSize
);
791 destSize
=ubidi_writeReordered(bidi
,dest
,destSize
+1,UBIDI_DO_MIRRORING
+UBIDI_OUTPUT_REVERSE
,&ec
);
792 u16ToPseudo(destSize
,dest
,chars
);
793 if(destSize
!=srcSize
){
794 log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
795 }else if(strcmp(visualOrder1
[i
],chars
)!=0){
796 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE.\n"
797 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
798 logicalOrder
[i
],visualOrder1
[i
],chars
,formatLevels(bidi
, formatChars
),i
);
802 for(i
=0;i
<LENGTHOF(logicalOrder
);i
++){
803 int32_t srcSize
= (int32_t)strlen(logicalOrder
[i
]);
804 int32_t destSize
= srcSize
*2;
808 log_verbose("Testing V2L #3 for case %d\n", i
);
809 pseudoToU16(srcSize
,logicalOrder
[i
],src
);
811 ubidi_setInverse(bidi
,TRUE
);
812 ubidi_setPara(bidi
,src
,srcSize
,UBIDI_DEFAULT_LTR
,NULL
,&ec
);
814 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
815 i
, UBIDI_DEFAULT_LTR
, u_errorName(ec
));
817 /* try pre-flighting */
818 destSize
= ubidi_writeReordered(bidi
,dest
,0,UBIDI_INSERT_LRM_FOR_NUMERIC
+UBIDI_OUTPUT_REVERSE
,&ec
);
819 if(ec
!=U_BUFFER_OVERFLOW_ERROR
){
820 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec
));
824 destSize
=ubidi_writeReordered(bidi
,dest
,destSize
+1,UBIDI_INSERT_LRM_FOR_NUMERIC
+UBIDI_OUTPUT_REVERSE
,&ec
);
825 u16ToPseudo(destSize
,dest
,chars
);
826 if(strcmp(visualOrder2
[i
],chars
)!=0){
827 log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE.\n"
828 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
829 logicalOrder
[i
],visualOrder2
[i
],chars
,formatLevels(bidi
, formatChars
),i
);
832 /* Max Explicit level */
833 for(i
=0;i
<LENGTHOF(logicalOrder
);i
++){
834 int32_t srcSize
= (int32_t)strlen(logicalOrder
[i
]);
835 int32_t destSize
= srcSize
*2;
839 UBiDiLevel levels
[UBIDI_MAX_EXPLICIT_LEVEL
]={1,2,3,4,5,6,7,8,9,10};
840 log_verbose("Testing V2L #4 for case %d\n", i
);
841 pseudoToU16(srcSize
,logicalOrder
[i
],src
);
843 ubidi_setPara(bidi
,src
,srcSize
,UBIDI_DEFAULT_LTR
,levels
,&ec
);
845 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
846 i
, UBIDI_MAX_EXPLICIT_LEVEL
, u_errorName(ec
));
848 /* try pre-flighting */
849 destSize
= ubidi_writeReordered(bidi
,dest
,0,UBIDI_OUTPUT_REVERSE
,&ec
);
850 if(ec
!=U_BUFFER_OVERFLOW_ERROR
){
851 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec
));
852 }else if(destSize
!=srcSize
){
853 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize
,destSize
);
857 destSize
=ubidi_writeReordered(bidi
,dest
,destSize
+1,UBIDI_OUTPUT_REVERSE
,&ec
);
858 u16ToPseudo(destSize
,dest
,chars
);
859 if(destSize
!=srcSize
){
860 log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize
,srcSize
);
861 }else if(strcmp(visualOrder3
[i
],chars
)!=0){
862 log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE.\n"
863 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
864 logicalOrder
[i
],visualOrder3
[i
],chars
,formatLevels(bidi
, formatChars
),i
);
867 for(i
=0;i
<LENGTHOF(logicalOrder
);i
++){
868 int32_t srcSize
= (int32_t)strlen(logicalOrder
[i
]);
869 int32_t destSize
= srcSize
*2;
873 UBiDiLevel levels
[UBIDI_MAX_EXPLICIT_LEVEL
]={1,2,3,4,5,6,7,8,9,10};
874 log_verbose("Testing V2L #5 for case %d\n", i
);
875 pseudoToU16(srcSize
,logicalOrder
[i
],src
);
877 ubidi_setPara(bidi
,src
,srcSize
,UBIDI_DEFAULT_LTR
,levels
,&ec
);
879 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
880 i
, UBIDI_MAX_EXPLICIT_LEVEL
, u_errorName(ec
));
882 /* try pre-flighting */
883 destSize
= ubidi_writeReordered(bidi
,dest
,0,UBIDI_DO_MIRRORING
+UBIDI_REMOVE_BIDI_CONTROLS
,&ec
);
884 if(ec
!=U_BUFFER_OVERFLOW_ERROR
){
885 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec
));
889 destSize
=ubidi_writeReordered(bidi
,dest
,destSize
+1,UBIDI_DO_MIRRORING
+UBIDI_REMOVE_BIDI_CONTROLS
,&ec
);
890 u16ToPseudo(destSize
,dest
,chars
);
891 if(strcmp(visualOrder4
[i
],chars
)!=0){
892 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS.\n"
893 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
894 logicalOrder
[i
],visualOrder4
[i
],chars
,formatLevels(bidi
, formatChars
),i
);
899 log_verbose("\nExiting TestReorder\n\n");
903 testReorderArabicMathSymbols(void) {
904 static const UChar logicalOrder
[][MAXLEN
]={
905 /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
906 {0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
907 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
908 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
909 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
910 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
911 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
912 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
913 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B},
914 /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
915 {0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
916 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
917 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
918 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
919 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
920 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
921 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
922 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B},
923 /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
924 {0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
925 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
926 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
927 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
928 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
929 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
930 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
931 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB},
932 /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
933 {0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
934 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
935 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
936 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
937 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
938 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
939 0xD83B, 0xDE39, 0xD83B, 0xDE3B},
940 /* Arabic mathematical Symbols - Tailed Symbols */
941 {0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
942 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
943 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
944 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F}
946 static const UChar visualOrder
[][MAXLEN
]={
947 /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
948 {0xD83B, 0xDE1B, 0xD83B, 0xDE1A, 0xD83B, 0xDE19, 0x20,
949 0xD83B, 0xDE18, 0xD83B, 0xDE17, 0xD83B, 0xDE16, 0x20,
950 0xD83B, 0xDE15, 0xD83B, 0xDE14, 0xD83B, 0xDE13, 0xD83B, 0xDE12, 0x20,
951 0xD83B, 0xDE11, 0xD83B, 0xDE10, 0xD83B, 0xDE0F, 0xD83B, 0xDE0E, 0x20,
952 0xD83B, 0xDE0D, 0xD83B, 0xDE0C, 0xD83B, 0xDE0B, 0xD83B, 0xDE0A, 0x20,
953 0xD83B, 0xDE09, 0xD83B, 0xDE08, 0xD83B, 0xDE07, 0x20,
954 0xD83B, 0xDE06, 0xD83B, 0xDE05, 0xD83B, 0xDE24, 0x20,
955 0xD83B, 0xDE03, 0xD83B, 0xDE02, 0xD83B, 0xDE01, 0xD83B, 0xDE00},
956 /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
957 {0xD83B, 0xDE9B, 0xD83B, 0xDE9A, 0xD83B, 0xDE99, 0x20,
958 0xD83B, 0xDE98, 0xD83B, 0xDE97, 0xD83B, 0xDE96, 0x20,
959 0xD83B, 0xDE95, 0xD83B, 0xDE94, 0xD83B, 0xDE93, 0xD83B, 0xDE92, 0x20,
960 0xD83B, 0xDE91, 0xD83B, 0xDE90, 0xD83B, 0xDE8F, 0xD83B, 0xDE8E, 0x20,
961 0xD83B, 0xDE8D, 0xD83B, 0xDE8C, 0xD83B, 0xDE8B, 0x20,
962 0xD83B, 0xDE89, 0xD83B, 0xDE88, 0xD83B, 0xDE87, 0x20,
963 0xD83B, 0xDE86, 0xD83B, 0xDE85, 0xD83B, 0xDE84, 0x20,
964 0xD83B, 0xDE83, 0xD83B, 0xDE82, 0xD83B, 0xDE81, 0xD83B, 0xDE80},
965 /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
966 {0xD83B, 0xDEBB, 0xD83B, 0xDEBA, 0xD83B, 0xDEB9, 0x20,
967 0xD83B, 0xDEB8, 0xD83B, 0xDEB7, 0xD83B, 0xDEB6, 0x20,
968 0xD83B, 0xDEB5, 0xD83B, 0xDEB4, 0xD83B, 0xDEB3, 0xD83B, 0xDEB2, 0x20,
969 0xD83B, 0xDEB1, 0xD83B, 0xDEB0, 0xD83B, 0xDEAF, 0xD83B, 0xDEAE, 0x20,
970 0xD83B, 0xDEAD, 0xD83B, 0xDEAC, 0xD83B, 0xDEAB, 0x20,
971 0xD83B, 0xDEA9, 0xD83B, 0xDEA8, 0xD83B, 0xDEA7, 0x20,
972 0xD83B, 0xDEA6, 0xD83B, 0xDEA5, 0x20,
973 0xD83B, 0xDEA3, 0xD83B, 0xDEA2, 0xD83B, 0xDEA1},
974 /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
975 {0xD83B, 0xDE3B, 0xD83B, 0xDE39, 0x20,
976 0xD83B, 0xDE37, 0xD83B, 0xDE36, 0x20,
977 0xD83B, 0xDE35, 0xD83B, 0xDE34, 0xD83B, 0xDE32, 0x20,
978 0xD83B, 0xDE31, 0xD83B, 0xDE30, 0xD83B, 0xDE2F, 0xD83B, 0xDE2E, 0x20,
979 0xD83B, 0xDE2D, 0xD83B, 0xDE2C, 0xD83B, 0xDE2B, 0xD83B, 0xDE2A, 0x20,
980 0xD83B, 0xDE29, 0xD83B, 0xDE27, 0x20,
981 0xD83B, 0xDE22, 0xD83B, 0xDE21},
982 /* Arabic mathematical Symbols - Tailed Symbols */
983 {0xD83B, 0xDE5F, 0xD83B, 0xDE5D, 0xD83B, 0xDE5B, 0xD83B, 0xDE59, 0x20,
984 0xD83B, 0xDE57, 0xD83B, 0xDE54, 0xD83B, 0xDE52, 0xD83B, 0xDE51, 0x20,
985 0xD83B, 0xDE4F, 0xD83B, 0xDE4E, 0xD83B, 0xDE4D, 0x20,
986 0xD83B, 0xDE4B, 0xD83B, 0xDE49, 0xD83B, 0xDE47, 0xD83B, 0xDE42}
988 char formatChars
[MAXLEN
];
989 UErrorCode ec
= U_ZERO_ERROR
;
990 UBiDi
* bidi
= ubidi_open();
993 log_verbose("\nEntering TestReorderArabicMathSymbols\n\n");
995 for(i
=0;i
<LENGTHOF(logicalOrder
);i
++){
996 int32_t srcSize
= u_strlen(logicalOrder
[i
]);
997 int32_t destSize
= srcSize
*2;
999 log_verbose("Testing L2V #1 for case %d\n", i
);
1001 ubidi_setPara(bidi
,logicalOrder
[i
],srcSize
,UBIDI_DEFAULT_LTR
,NULL
,&ec
);
1003 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
1004 i
, UBIDI_DEFAULT_LTR
, u_errorName(ec
));
1006 /* try pre-flighting */
1007 destSize
= ubidi_writeReordered(bidi
,dest
,0,UBIDI_DO_MIRRORING
,&ec
);
1008 if(ec
!=U_BUFFER_OVERFLOW_ERROR
){
1009 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec
));
1010 }else if(destSize
!=srcSize
){
1011 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize
,destSize
);
1015 destSize
=ubidi_writeReordered(bidi
,dest
,destSize
+1,UBIDI_DO_MIRRORING
,&ec
);
1016 if(destSize
!=srcSize
){
1017 log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
1018 }else if(memcmp(dest
, visualOrder
[i
], destSize
*U_SIZEOF_UCHAR
)!=0){
1019 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
1020 "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
1021 logicalOrder
[i
],visualOrder
[i
],dest
,formatLevels(bidi
, formatChars
),i
);
1027 log_verbose("\nExiting TestReorderArabicMathSymbols\n\n");
1031 doTest(UBiDi
*pBiDi
, int testNumber
, const BiDiTestData
*test
, int32_t lineStart
, UBool countRunsFirst
) {
1032 const uint8_t *dirProps
=test
->text
+lineStart
;
1033 const UBiDiLevel
*levels
=test
->levels
;
1034 const uint8_t *visualMap
=test
->visualMap
;
1035 int32_t i
, len
=ubidi_getLength(pBiDi
), logicalIndex
, runCount
= 0;
1036 UErrorCode errorCode
=U_ZERO_ERROR
;
1037 UBiDiLevel level
, level2
;
1039 if (countRunsFirst
) {
1040 log_verbose("Calling ubidi_countRuns() first.\n");
1042 runCount
= ubidi_countRuns(pBiDi
, &errorCode
);
1044 if(U_FAILURE(errorCode
)) {
1045 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber
, myErrorName(errorCode
));
1049 log_verbose("Calling ubidi_getLogicalMap() first.\n");
1052 _testReordering(pBiDi
, testNumber
);
1054 for(i
=0; i
<len
; ++i
) {
1055 log_verbose("%3d %3d %.*s%-3s @%d\n",
1056 i
, ubidi_getLevelAt(pBiDi
, i
), ubidi_getLevelAt(pBiDi
, i
), levelString
,
1057 dirPropNames
[dirProps
[i
]],
1058 ubidi_getVisualIndex(pBiDi
, i
, &errorCode
));
1061 log_verbose("\n-----levels:");
1062 for(i
=0; i
<len
; ++i
) {
1066 log_verbose(" %d", ubidi_getLevelAt(pBiDi
, i
));
1069 log_verbose("\n--reordered:");
1070 for(i
=0; i
<len
; ++i
) {
1074 log_verbose(" %d", ubidi_getVisualIndex(pBiDi
, i
, &errorCode
));
1078 if(test
->direction
!=ubidi_getDirection(pBiDi
)) {
1079 log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber
, ubidi_getDirection(pBiDi
));
1082 if(test
->resultLevel
!=ubidi_getParaLevel(pBiDi
)) {
1083 log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber
, ubidi_getParaLevel(pBiDi
));
1086 for(i
=0; i
<len
; ++i
) {
1087 if(levels
[i
]!=ubidi_getLevelAt(pBiDi
, i
)) {
1088 log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d, expected %d\n", testNumber
, i
, ubidi_getLevelAt(pBiDi
, i
), levels
[i
]);
1093 for(i
=0; i
<len
; ++i
) {
1094 logicalIndex
=ubidi_getVisualIndex(pBiDi
, i
, &errorCode
);
1095 if(U_FAILURE(errorCode
)) {
1096 log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber
, i
, myErrorName(errorCode
));
1099 if(visualMap
[i
]!=logicalIndex
) {
1100 log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber
, i
, logicalIndex
);
1105 if (! countRunsFirst
) {
1106 runCount
=ubidi_countRuns(pBiDi
, &errorCode
);
1107 if(U_FAILURE(errorCode
)) {
1108 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber
, myErrorName(errorCode
));
1113 for(logicalIndex
=0; logicalIndex
<len
;) {
1114 level
=ubidi_getLevelAt(pBiDi
, logicalIndex
);
1115 ubidi_getLogicalRun(pBiDi
, logicalIndex
, &logicalIndex
, &level2
);
1117 log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): "
1118 "wrong level %d instead of %d\n",
1119 testNumber
, logicalIndex
, level
, level2
);
1122 log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
1123 "compared to %d=ubidi_countRuns()\n",
1124 testNumber
, ubidi_countRuns(pBiDi
, &errorCode
));
1129 log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
1130 "compared to %d=ubidi_getRunCount()\n",
1131 testNumber
, ubidi_countRuns(pBiDi
, &errorCode
));
1135 log_verbose("\n\n");
1139 _testReordering(UBiDi
*pBiDi
, int testNumber
) {
1141 logicalMap1
[MAXLEN
], logicalMap2
[MAXLEN
], logicalMap3
[MAXLEN
],
1142 visualMap1
[MAXLEN
], visualMap2
[MAXLEN
], visualMap3
[MAXLEN
], visualMap4
[MAXLEN
];
1143 UErrorCode errorCode
=U_ZERO_ERROR
;
1144 const UBiDiLevel
*levels
;
1145 int32_t i
, length
=ubidi_getLength(pBiDi
),
1146 destLength
=ubidi_getResultLength(pBiDi
);
1147 int32_t runCount
, visualIndex
, logicalStart
, runLength
;
1154 /* get the logical and visual maps from the object */
1155 ubidi_getLogicalMap(pBiDi
, logicalMap1
, &errorCode
);
1156 if(U_FAILURE(errorCode
)) {
1157 log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber
, myErrorName(errorCode
));
1161 ubidi_getVisualMap(pBiDi
, visualMap1
, &errorCode
);
1162 if(U_FAILURE(errorCode
)) {
1163 log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber
, myErrorName(errorCode
));
1167 /* invert them both */
1168 ubidi_invertMap(logicalMap1
, visualMap2
, length
);
1169 ubidi_invertMap(visualMap1
, logicalMap2
, destLength
);
1171 /* get them from the levels array, too */
1172 levels
=ubidi_getLevels(pBiDi
, &errorCode
);
1174 if(U_FAILURE(errorCode
)) {
1175 log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber
, myErrorName(errorCode
));
1179 ubidi_reorderLogical(levels
, length
, logicalMap3
);
1180 ubidi_reorderVisual(levels
, length
, visualMap3
);
1182 /* get the visual map from the runs, too */
1183 runCount
=ubidi_countRuns(pBiDi
, &errorCode
);
1184 if(U_FAILURE(errorCode
)) {
1185 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber
, myErrorName(errorCode
));
1188 log_verbose("\n----%2d runs:", runCount
);
1190 for(i
=0; i
<runCount
; ++i
) {
1191 odd
=(UBool
)ubidi_getVisualRun(pBiDi
, i
, &logicalStart
, &runLength
);
1192 log_verbose(" (%c @%d[%d])", odd
? 'R' : 'L', logicalStart
, runLength
);
1193 if(UBIDI_LTR
==odd
) {
1195 visualMap4
[visualIndex
++]=logicalStart
++;
1196 } while(--runLength
>0);
1198 logicalStart
+=runLength
; /* logicalLimit */
1200 visualMap4
[visualIndex
++]=--logicalStart
;
1201 } while(--runLength
>0);
1206 /* print all the maps */
1207 log_verbose("logical maps:\n");
1208 for(i
=0; i
<length
; ++i
) {
1209 log_verbose("%4d", logicalMap1
[i
]);
1212 for(i
=0; i
<length
; ++i
) {
1213 log_verbose("%4d", logicalMap2
[i
]);
1216 for(i
=0; i
<length
; ++i
) {
1217 log_verbose("%4d", logicalMap3
[i
]);
1220 log_verbose("\nvisual maps:\n");
1221 for(i
=0; i
<destLength
; ++i
) {
1222 log_verbose("%4d", visualMap1
[i
]);
1225 for(i
=0; i
<destLength
; ++i
) {
1226 log_verbose("%4d", visualMap2
[i
]);
1229 for(i
=0; i
<length
; ++i
) {
1230 log_verbose("%4d", visualMap3
[i
]);
1233 for(i
=0; i
<length
; ++i
) {
1234 log_verbose("%4d", visualMap4
[i
]);
1238 /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */
1239 for(i
=0; i
<length
; ++i
) {
1240 if(logicalMap1
[i
]!=logicalMap2
[i
]) {
1241 log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber
, i
);
1244 if(logicalMap1
[i
]!=logicalMap3
[i
]) {
1245 log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber
, i
);
1249 if(visualMap1
[i
]!=visualMap2
[i
]) {
1250 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber
, i
);
1253 if(visualMap1
[i
]!=visualMap3
[i
]) {
1254 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber
, i
);
1257 if(visualMap1
[i
]!=visualMap4
[i
]) {
1258 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber
, i
);
1262 if(logicalMap1
[i
]!=ubidi_getVisualIndex(pBiDi
, i
, &errorCode
)) {
1263 log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber
, i
);
1266 if(U_FAILURE(errorCode
)) {
1267 log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber
, i
, myErrorName(errorCode
));
1270 if(visualMap1
[i
]!=ubidi_getLogicalIndex(pBiDi
, i
, &errorCode
)) {
1271 log_err("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber
, i
);
1274 if(U_FAILURE(errorCode
)) {
1275 log_err("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber
, i
, myErrorName(errorCode
));
1281 #define RETURN_IF_BAD_ERRCODE(x) \
1282 if (U_FAILURE(errorCode)) { \
1283 log_err("\nbad errorCode %d at %s\n", errorCode, (x)); \
1287 #define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
1289 static void testGetBaseDirection(void) {
1295 /*Mixed Start with L*/
1296 stringMixedEnglishFirst
[]={ 0x61, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 },
1297 /*Mixed Start with AL*/
1298 stringMixedArabicFirst
[]={ 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
1299 /*Mixed Start with R*/
1300 stringMixedHebrewFirst
[]={ 0x05EA, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
1301 /*All AL (Arabic. Persian)*/
1302 stringPersian
[]={0x0698, 0x067E, 0x0686, 0x06AF, 0},
1303 /*All R (Hebrew etc.)*/
1304 stringHebrew
[]={0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
1306 stringEnglish
[]={0x71, 0x61, 0x66, 0},
1307 /*Mixed Start with weak AL an then L*/
1308 stringStartWeakAL
[]={ 0x0663, 0x71, 0x61, 0x66, 0},
1309 /*Mixed Start with weak L and then AL*/
1310 stringStartWeakL
[]={0x31, 0x0698, 0x067E, 0x0686, 0x06AF, 0},
1314 stringSurrogateChar
[]={0xD800, 0xDC00, 0},
1316 stringInvalidUchar
[]={-1},
1317 /*All weak L (English Digits)*/
1318 stringAllEnglishDigits
[]={0x31, 0x32, 0x33, 0},
1319 /*All weak AL (Arabic Digits)*/
1320 stringAllArabicDigits
[]={0x0663, 0x0664, 0x0665, 0},
1321 /*First L (English) others are R (Hebrew etc.) */
1322 stringFirstL
[] = {0x71, 0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
1323 /*Last R (Hebrew etc.) others are weak L (English Digits)*/
1324 stringLastR
[] = {0x31, 0x32, 0x33, 0x05F1, 0};
1326 static const struct {
1330 STRING_TEST_CASE(stringMixedEnglishFirst
),
1331 STRING_TEST_CASE(stringMixedArabicFirst
),
1332 STRING_TEST_CASE(stringMixedHebrewFirst
),
1333 STRING_TEST_CASE(stringPersian
),
1334 STRING_TEST_CASE(stringHebrew
),
1335 STRING_TEST_CASE(stringEnglish
),
1336 STRING_TEST_CASE(stringStartWeakAL
),
1337 STRING_TEST_CASE(stringStartWeakL
),
1338 STRING_TEST_CASE(stringEmpty
),
1339 STRING_TEST_CASE(stringSurrogateChar
),
1340 STRING_TEST_CASE(stringInvalidUchar
),
1341 STRING_TEST_CASE(stringAllEnglishDigits
),
1342 STRING_TEST_CASE(stringAllArabicDigits
),
1343 STRING_TEST_CASE(stringFirstL
),
1344 STRING_TEST_CASE(stringLastR
),
1347 /* Expected results */
1348 static const UBiDiDirection expectedDir
[] ={
1349 UBIDI_LTR
, UBIDI_RTL
, UBIDI_RTL
,
1350 UBIDI_RTL
, UBIDI_RTL
, UBIDI_LTR
,
1351 UBIDI_LTR
, UBIDI_RTL
, UBIDI_NEUTRAL
,
1352 UBIDI_LTR
, UBIDI_NEUTRAL
, UBIDI_NEUTRAL
,
1353 UBIDI_NEUTRAL
, UBIDI_LTR
, UBIDI_RTL
1356 log_verbose("testGetBaseDirection() with %u test cases ---\n",
1357 LENGTHOF(testCases
));
1359 for(i
=0; i
<LENGTHOF(testCases
); ++i
) {
1360 dir
= ubidi_getBaseDirection(testCases
[i
].s
, testCases
[i
].length
);
1361 log_verbose("Testing case %d\tReceived dir %d\n", i
, dir
);
1362 if (dir
!= expectedDir
[i
])
1363 log_err("\nFailed getBaseDirection case %d Expected %d \tReceived %d\n",
1364 i
, expectedDir
[i
], dir
);
1369 dir
= ubidi_getBaseDirection(NULL
, 3);
1370 if (dir
!= UBIDI_NEUTRAL
)
1371 log_err("\nFailed getBaseDirection for NULL string " ,
1372 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL
, dir
);
1373 /*All L- English string and length=-3 */
1374 dir
= ubidi_getBaseDirection( stringEnglish
, -3);
1375 if (dir
!= UBIDI_NEUTRAL
)
1376 log_err("\nFailed getBaseDirection for string w length= -3 ",
1377 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL
, dir
);
1378 /*All L- English string and length=-1 */
1379 dir
= ubidi_getBaseDirection( stringEnglish
, -1);
1380 if (dir
!= UBIDI_LTR
)
1381 log_err("\nFailed getBaseDirection for English string w length= -1 ",
1382 "\nExpected %d \nReceived %d", UBIDI_LTR
, dir
);
1383 /*All AL- Persian string and length=-1 */
1384 dir
= ubidi_getBaseDirection( stringPersian
, -1);
1385 if (dir
!= UBIDI_RTL
)
1386 log_err("\nFailed getBaseDirection for Persian string w length= -1 ",
1387 "\nExpected %d \nReceived %d", UBIDI_RTL
, dir
);
1388 /*All R- Hebrew string and length=-1 */
1389 dir
= ubidi_getBaseDirection( stringHebrew
, -1);
1390 if (dir
!= UBIDI_RTL
)
1391 log_err("\nFailed getBaseDirection for Hebrew string w length= -1 ",
1392 "\nExpected %d \nReceived %d", UBIDI_RTL
, dir
);
1393 /*All weak L- English digits string and length=-1 */
1394 dir
= ubidi_getBaseDirection(stringAllEnglishDigits
, -1);
1395 if (dir
!= UBIDI_NEUTRAL
)
1396 log_err("\nFailed getBaseDirection for English digits string w length= -1 ",
1397 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL
, dir
);
1398 /*All weak AL- Arabic digits string and length=-1 */
1399 dir
= ubidi_getBaseDirection(stringAllArabicDigits
, -1);
1400 if (dir
!= UBIDI_NEUTRAL
)
1401 log_err("\nFailed getBaseDirection for Arabic string w length= -1 ",
1402 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL
, dir
);
1407 static void doMisc(void) {
1408 /* Miscellaneous tests to exercize less popular code paths */
1409 UBiDi
*bidi
, *bidiLine
;
1410 UChar src
[MAXLEN
], dest
[MAXLEN
];
1411 int32_t srcLen
, destLen
, runCount
, i
;
1414 int32_t map
[MAXLEN
];
1415 UErrorCode errorCode
=U_ZERO_ERROR
;
1416 static const int32_t srcMap
[6] = {0,1,-1,5,4};
1417 static const int32_t dstMap
[6] = {0,1,-1,-1,4,3};
1419 bidi
= ubidi_openSized(120, 66, &errorCode
);
1421 log_err("Error with openSized(120, 66)\n");
1424 bidiLine
= ubidi_open();
1426 log_err("Error with open()\n");
1430 destLen
= ubidi_writeReverse(src
, 0, dest
, MAXLEN
, 0, &errorCode
);
1432 log_err("\nwriteReverse should return zero length, ",
1433 "returned %d instead\n", destLen
);
1435 RETURN_IF_BAD_ERRCODE("#1#");
1437 ubidi_setPara(bidi
, src
, 0, UBIDI_LTR
, NULL
, &errorCode
);
1438 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1440 log_err("\nwriteReordered should return zero length, ",
1441 "returned %d instead\n", destLen
);
1443 RETURN_IF_BAD_ERRCODE("#2#");
1445 srcLen
= u_unescape("abc ", src
, MAXLEN
);
1446 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_RTL
, NULL
, &errorCode
);
1447 ubidi_setLine(bidi
, 0, 6, bidiLine
, &errorCode
);
1448 for (i
= 3; i
< 6; i
++) {
1449 level
= ubidi_getLevelAt(bidiLine
, i
);
1450 if (level
!= UBIDI_RTL
) {
1451 log_err("\nTrailing space at index %d should get paragraph level"
1452 "%d, got %d instead\n", i
, UBIDI_RTL
, level
);
1455 RETURN_IF_BAD_ERRCODE("#3#");
1457 srcLen
= u_unescape("abc def", src
, MAXLEN
);
1458 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_RTL
, NULL
, &errorCode
);
1459 ubidi_setLine(bidi
, 0, 6, bidiLine
, &errorCode
);
1460 for (i
= 3; i
< 6; i
++) {
1461 level
= ubidi_getLevelAt(bidiLine
, i
);
1462 if (level
!= UBIDI_RTL
) {
1463 log_err("\nTrailing space at index %d should get paragraph level"
1464 "%d, got %d instead\n", i
, UBIDI_RTL
, level
);
1467 RETURN_IF_BAD_ERRCODE("#4#");
1469 srcLen
= u_unescape("abcdefghi ", src
, MAXLEN
);
1470 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_RTL
, NULL
, &errorCode
);
1471 ubidi_setLine(bidi
, 0, 6, bidiLine
, &errorCode
);
1472 for (i
= 3; i
< 6; i
++) {
1473 level
= ubidi_getLevelAt(bidiLine
, i
);
1475 log_err("\nTrailing char at index %d should get level 2, "
1476 "got %d instead\n", i
, level
);
1479 RETURN_IF_BAD_ERRCODE("#5#");
1481 ubidi_setReorderingOptions(bidi
, UBIDI_OPTION_REMOVE_CONTROLS
);
1482 srcLen
= u_unescape("\\u200eabc def", src
, MAXLEN
);
1483 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_RTL
, NULL
, &errorCode
);
1484 ubidi_setLine(bidi
, 0, 6, bidiLine
, &errorCode
);
1485 destLen
= ubidi_getResultLength(bidiLine
);
1487 log_err("\nWrong result length, should be 5, got %d\n", destLen
);
1489 RETURN_IF_BAD_ERRCODE("#6#");
1491 srcLen
= u_unescape("abcdefghi", src
, MAXLEN
);
1492 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_LTR
, NULL
, &errorCode
);
1493 ubidi_setLine(bidi
, 0, 6, bidiLine
, &errorCode
);
1494 dir
= ubidi_getDirection(bidiLine
);
1495 if (dir
!= UBIDI_LTR
) {
1496 log_err("\nWrong direction #1, should be %d, got %d\n",
1499 RETURN_IF_BAD_ERRCODE("#7#");
1501 ubidi_setPara(bidi
, src
, 0, UBIDI_LTR
, NULL
, &errorCode
);
1502 runCount
= ubidi_countRuns(bidi
, &errorCode
);
1503 if (runCount
!= 0) {
1504 log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount
);
1506 RETURN_IF_BAD_ERRCODE("#8#");
1508 srcLen
= u_unescape(" ", src
, MAXLEN
);
1509 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_RTL
, NULL
, &errorCode
);
1510 ubidi_setLine(bidi
, 0, 6, bidiLine
, &errorCode
);
1511 runCount
= ubidi_countRuns(bidiLine
, &errorCode
);
1512 if (runCount
!= 1) {
1513 log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount
);
1515 RETURN_IF_BAD_ERRCODE("#9#");
1517 srcLen
= u_unescape("a\\u05d0 bc", src
, MAXLEN
);
1518 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_RTL
, NULL
, &errorCode
);
1519 ubidi_setLine(bidi
, 0, 6, bidiLine
, &errorCode
);
1520 dir
= ubidi_getDirection(bidi
);
1521 if (dir
!= UBIDI_MIXED
) {
1522 log_err("\nWrong direction #2, should be %d, got %d\n",
1525 dir
= ubidi_getDirection(bidiLine
);
1526 if (dir
!= UBIDI_MIXED
) {
1527 log_err("\nWrong direction #3, should be %d, got %d\n",
1530 runCount
= ubidi_countRuns(bidiLine
, &errorCode
);
1531 if (runCount
!= 2) {
1532 log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount
);
1534 RETURN_IF_BAD_ERRCODE("#10#");
1536 ubidi_invertMap(srcMap
, map
, 5);
1537 if (memcmp(dstMap
, map
, sizeof(dstMap
))) {
1538 log_err("\nUnexpected inverted Map, got ");
1539 for (i
= 0; i
< 6; i
++) {
1540 log_err("%d ", map
[i
]);
1545 /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
1546 srcLen
= u_unescape("abc\\u200e", src
, MAXLEN
);
1547 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_LTR
, NULL
, &errorCode
);
1548 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
,
1549 UBIDI_REMOVE_BIDI_CONTROLS
| UBIDI_DO_MIRRORING
, &errorCode
);
1550 if (destLen
!= 3 || memcmp(dest
, src
, 3 * sizeof(UChar
))) {
1551 log_err("\nWrong result #1, should be 'abc', got '%s'\n",
1552 aescstrdup(dest
, destLen
));
1554 RETURN_IF_BAD_ERRCODE("#11#");
1556 /* test inverse Bidi with marks and contextual orientation */
1557 ubidi_setReorderingMode(bidi
, UBIDI_REORDER_INVERSE_LIKE_DIRECT
);
1558 ubidi_setReorderingOptions(bidi
, UBIDI_OPTION_INSERT_MARKS
);
1559 ubidi_setPara(bidi
, src
, 0, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
1560 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1562 log_err("\nWrong result #2, length should be 0, got %d\n", destLen
);
1564 RETURN_IF_BAD_ERRCODE("#12#");
1565 srcLen
= u_unescape(" ", src
, MAXLEN
);
1566 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
1567 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1568 if (destLen
!= 3 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1569 log_err("\nWrong result #3, should be ' ', got '%s'\n",
1570 aescstrdup(dest
, destLen
));
1572 RETURN_IF_BAD_ERRCODE("#13#");
1573 srcLen
= u_unescape("abc", src
, MAXLEN
);
1574 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
1575 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1576 if (destLen
!= 3 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1577 log_err("\nWrong result #4, should be 'abc', got '%s'\n",
1578 aescstrdup(dest
, destLen
));
1580 RETURN_IF_BAD_ERRCODE("#14#");
1581 srcLen
= u_unescape("\\u05d0\\u05d1", src
, MAXLEN
);
1582 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
1583 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1584 srcLen
= u_unescape("\\u05d1\\u05d0", src
, MAXLEN
);
1585 if (destLen
!= 2 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1586 log_err("\nWrong result #5, should be '%s', got '%s'\n",
1587 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
1589 RETURN_IF_BAD_ERRCODE("#15#");
1590 srcLen
= u_unescape("abc \\u05d0\\u05d1", src
, MAXLEN
);
1591 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
1592 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1593 srcLen
= u_unescape("\\u05d1\\u05d0 abc", src
, MAXLEN
);
1594 if (destLen
!= 6 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1595 log_err("\nWrong result #6, should be '%s', got '%s'\n",
1596 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
1598 RETURN_IF_BAD_ERRCODE("#16#");
1599 srcLen
= u_unescape("\\u05d0\\u05d1 abc", src
, MAXLEN
);
1600 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
1601 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1602 srcLen
= u_unescape("\\u200fabc \\u05d1\\u05d0", src
, MAXLEN
);
1603 if (destLen
!= 7 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1604 log_err("\nWrong result #7, should be '%s', got '%s'\n",
1605 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
1607 RETURN_IF_BAD_ERRCODE("#17#");
1608 srcLen
= u_unescape("\\u05d0\\u05d1 abc .-=", src
, MAXLEN
);
1609 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
1610 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1611 srcLen
= u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src
, MAXLEN
);
1612 if (destLen
!= 11 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1613 log_err("\nWrong result #8, should be '%s', got '%s'\n",
1614 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
1616 RETURN_IF_BAD_ERRCODE("#18#");
1617 ubidi_orderParagraphsLTR(bidi
, TRUE
);
1618 srcLen
= u_unescape("\n\r \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r"
1619 "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n"
1620 "-* \\u05d8\\u05d9 abc .-=", src
, MAXLEN
);
1621 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
1622 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1623 srcLen
= u_unescape("\n\r \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r"
1624 "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n"
1625 "\\u200f=-. abc \\u05d9\\u05d8 *-", src
, MAXLEN
);
1626 if (destLen
!= 57 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1627 log_err("\nWrong result #9, should be '%s', got '%s'\n",
1628 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
1630 RETURN_IF_BAD_ERRCODE("#19#");
1631 srcLen
= u_unescape("\\u05d0 \t", src
, MAXLEN
);
1632 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_LTR
, NULL
, &errorCode
);
1633 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1634 srcLen
= u_unescape("\\u05D0\\u200e \t", src
, MAXLEN
);
1635 if (destLen
!= 4 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1636 log_err("\nWrong result #10, should be '%s', got '%s'\n",
1637 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
1639 RETURN_IF_BAD_ERRCODE("#20#");
1640 srcLen
= u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src
, MAXLEN
);
1641 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_LTR
, NULL
, &errorCode
);
1642 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1643 srcLen
= u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src
, MAXLEN
);
1644 if (destLen
!= 16 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1645 log_err("\nWrong result #11, should be '%s', got '%s'\n",
1646 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
1648 RETURN_IF_BAD_ERRCODE("#21#");
1649 srcLen
= u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src
, MAXLEN
);
1650 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_LTR
, NULL
, &errorCode
);
1651 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1652 srcLen
= u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src
, MAXLEN
);
1653 if (destLen
!= 13 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1654 log_err("\nWrong result #12, should be '%s', got '%s'\n",
1655 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
1657 RETURN_IF_BAD_ERRCODE("#22#");
1658 srcLen
= u_unescape("ab \t", src
, MAXLEN
);
1659 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_RTL
, NULL
, &errorCode
);
1660 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
1661 srcLen
= u_unescape("\\u200f\t ab", src
, MAXLEN
);
1662 if (destLen
!= 5 || memcmp(dest
, src
, destLen
* sizeof(UChar
))) {
1663 log_err("\nWrong result #13, should be '%s', got '%s'\n",
1664 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
1666 RETURN_IF_BAD_ERRCODE("#23#");
1668 /* check exceeding para level */
1670 bidi
= ubidi_open();
1671 srcLen
= u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src
, MAXLEN
);
1672 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_MAX_EXPLICIT_LEVEL
- 1, NULL
, &errorCode
);
1673 level
= ubidi_getLevelAt(bidi
, 2);
1674 if (level
!= UBIDI_MAX_EXPLICIT_LEVEL
) {
1675 log_err("\nWrong level at index 2\n, should be %d, got %d\n", UBIDI_MAX_EXPLICIT_LEVEL
, level
);
1677 RETURN_IF_BAD_ERRCODE("#24#");
1679 /* check 1-char runs with RUNS_ONLY */
1680 ubidi_setReorderingMode(bidi
, UBIDI_REORDER_RUNS_ONLY
);
1681 srcLen
= u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src
, MAXLEN
);
1682 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_LTR
, NULL
, &errorCode
);
1683 runCount
= ubidi_countRuns(bidi
, &errorCode
);
1684 if (runCount
!= 14) {
1685 log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount
);
1687 RETURN_IF_BAD_ERRCODE("#25#");
1690 ubidi_close(bidiLine
);
1694 testFailureRecovery(void) {
1695 UErrorCode errorCode
;
1696 UBiDi
*bidi
, *bidiLine
;
1700 UBiDiReorderingMode rm
;
1701 static UBiDiLevel myLevels
[3] = {6,5,4};
1703 log_verbose("\nEntering TestFailureRecovery\n\n");
1704 errorCode
= U_FILE_ACCESS_ERROR
;
1705 if (ubidi_writeReordered(NULL
, NULL
, 0, 0, &errorCode
) != 0) {
1706 log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n");
1708 if (ubidi_writeReverse(NULL
, 0, NULL
, 0, 0, &errorCode
) != 0) {
1709 log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n");
1711 errorCode
= U_ZERO_ERROR
;
1712 if (ubidi_writeReordered(NULL
, NULL
, 0, 0, &errorCode
) != 0 || errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1713 log_err("ubidi_writeReordered did not fail as expected\n");
1716 bidi
= ubidi_open();
1717 srcLen
= u_unescape("abc", src
, MAXLEN
);
1718 errorCode
= U_ZERO_ERROR
;
1719 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_DEFAULT_LTR
- 1, NULL
, &errorCode
);
1720 if (U_SUCCESS(errorCode
)) {
1721 log_err("\nubidi_setPara did not fail when passed too big para level\n");
1723 errorCode
= U_ZERO_ERROR
;
1724 if (ubidi_writeReverse(NULL
, 0, NULL
, 0, 0, &errorCode
) != 0 || errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1725 log_err("ubidi_writeReverse did not fail as expected\n");
1727 bidiLine
= ubidi_open();
1728 errorCode
= U_ZERO_ERROR
;
1729 ubidi_setLine(bidi
, 0, 6, bidiLine
, &errorCode
);
1730 if (U_SUCCESS(errorCode
)) {
1731 log_err("\nubidi_setLine did not fail when called before valid setPara()\n");
1733 errorCode
= U_ZERO_ERROR
;
1734 srcLen
= u_unescape("abc", src
, MAXLEN
);
1735 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_LTR
+ 4, NULL
, &errorCode
);
1736 level
= ubidi_getLevelAt(bidi
, 3);
1738 log_err("\nubidi_getLevelAt did not fail when called with bad argument\n");
1740 errorCode
= U_ZERO_ERROR
;
1742 bidi
= ubidi_openSized(-1, 0, &errorCode
);
1743 if (U_SUCCESS(errorCode
)) {
1744 log_err("\nubidi_openSized did not fail when called with bad argument\n");
1747 bidi
= ubidi_openSized(2, 1, &errorCode
);
1748 errorCode
= U_ZERO_ERROR
;
1749 srcLen
= u_unescape("abc", src
, MAXLEN
);
1750 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_LTR
, NULL
, &errorCode
);
1751 if (U_SUCCESS(errorCode
)) {
1752 log_err("\nsetPara did not fail when called with text too long\n");
1754 errorCode
= U_ZERO_ERROR
;
1755 srcLen
= u_unescape("=2", src
, MAXLEN
);
1756 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_RTL
, NULL
, &errorCode
);
1757 ubidi_countRuns(bidi
, &errorCode
);
1758 if (U_SUCCESS(errorCode
)) {
1759 log_err("\nsetPara did not fail when called for too many runs\n");
1762 bidi
= ubidi_open();
1763 rm
= ubidi_getReorderingMode(bidi
);
1764 ubidi_setReorderingMode(bidi
, UBIDI_REORDER_DEFAULT
- 1);
1765 if (rm
!= ubidi_getReorderingMode(bidi
)) {
1766 log_err("\nsetReorderingMode with bad argument #1 should have no effect\n");
1768 ubidi_setReorderingMode(bidi
, 9999);
1769 if (rm
!= ubidi_getReorderingMode(bidi
)) {
1770 log_err("\nsetReorderingMode with bad argument #2 should have no effect\n");
1773 /* Try a surrogate char */
1774 errorCode
= U_ZERO_ERROR
;
1775 srcLen
= u_unescape("\\uD800\\uDC00", src
, MAXLEN
);
1776 ubidi_setPara(bidi
, src
, srcLen
, UBIDI_RTL
, NULL
, &errorCode
);
1777 if (ubidi_getDirection(bidi
) != UBIDI_MIXED
) {
1778 log_err("\ngetDirection for 1st surrogate char should be MIXED\n");
1780 errorCode
= U_ZERO_ERROR
;
1781 srcLen
= u_unescape("abc", src
, MAXLEN
);
1782 ubidi_setPara(bidi
, src
, srcLen
, 5, myLevels
, &errorCode
);
1783 if (U_SUCCESS(errorCode
)) {
1784 log_err("\nsetPara did not fail when called with bad levels\n");
1787 ubidi_close(bidiLine
);
1789 log_verbose("\nExiting TestFailureRecovery\n\n");
1793 testMultipleParagraphs(void) {
1794 static const char* const text
= "__ABC\\u001c" /* Para #0 offset 0 */
1795 "__\\u05d0DE\\u001c" /* 1 6 */
1796 "__123\\u001c" /* 2 12 */
1797 "\\u000d\\u000a" /* 3 18 */
1798 "FG\\u000d" /* 4 20 */
1799 "\\u000d" /* 5 23 */
1800 "HI\\u000d\\u000a" /* 6 24 */
1801 "\\u000d\\u000a" /* 7 28 */
1802 "\\u000a" /* 8 30 */
1803 "\\u000a" /* 9 31 */
1804 "JK\\u001c"; /* 10 32 */
1805 static const int32_t paraCount
=11;
1806 static const int32_t paraBounds
[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35};
1807 static const UBiDiLevel paraLevels
[]={UBIDI_LTR
, UBIDI_RTL
, UBIDI_DEFAULT_LTR
, UBIDI_DEFAULT_RTL
, 22, 23};
1808 static const UBiDiLevel multiLevels
[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1809 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
1810 {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1811 {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0},
1812 {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
1813 {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}};
1814 static const char* const text2
= "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2";
1815 static const UBiDiLevel levels2
[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2};
1816 static UBiDiLevel myLevels
[10] = {0,0,0,0,0,0,0,0,0,0};
1817 static const UChar multiparaTestString
[] = {
1818 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da,
1819 0x20, 0xa, 0xa, 0x41, 0x72, 0x74, 0x69, 0x73,
1820 0x74, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,
1821 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa, 0x41, 0x6c,
1822 0x62, 0x75, 0x6d, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1,
1823 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa,
1824 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x20, 0x32, 0x3a,
1825 0x32, 0x37, 0xa, 0xa
1827 static const UBiDiLevel multiparaTestLevels
[] = {
1828 1, 1, 1, 1, 1, 1, 1, 1,
1829 1, 1, 0, 0, 0, 0, 0, 0,
1830 0, 0, 0, 1, 1, 1, 1, 1,
1831 1, 1, 1, 0, 0, 0, 0, 0,
1832 0, 0, 0, 0, 0, 1, 1, 1,
1833 1, 1, 1, 1, 1, 0, 0, 0,
1834 0, 0, 0, 0, 0, 0, 0, 0,
1837 UBiDiLevel gotLevel
;
1838 const UBiDiLevel
* gotLevels
;
1839 UBool orderParagraphsLTR
;
1840 UChar src
[MAXLEN
], dest
[MAXLEN
];
1841 UErrorCode errorCode
=U_ZERO_ERROR
;
1842 UBiDi
* pBidi
=ubidi_open();
1844 int32_t srcSize
, count
, paraStart
, paraLimit
, paraIndex
, length
;
1845 int32_t srcLen
, destLen
;
1848 log_verbose("\nEntering TestMultipleParagraphs\n\n");
1849 u_unescape(text
, src
, MAXLEN
);
1850 srcSize
=u_strlen(src
);
1851 ubidi_setPara(pBidi
, src
, srcSize
, UBIDI_LTR
, NULL
, &errorCode
);
1852 if(U_FAILURE(errorCode
)){
1853 log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
1854 UBIDI_LTR
, u_errorName(errorCode
));
1858 /* check paragraph count and boundaries */
1859 if (paraCount
!=(count
=ubidi_countParagraphs(pBidi
))) {
1860 log_err("ubidi_countParagraphs returned %d, should be %d\n",
1863 for (i
=0; i
<paraCount
; i
++) {
1864 ubidi_getParagraphByIndex(pBidi
, i
, ¶Start
, ¶Limit
, NULL
, &errorCode
);
1865 if ((paraStart
!=paraBounds
[i
]) || (paraLimit
!=paraBounds
[i
+1])) {
1866 log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
1867 i
, paraStart
, paraLimit
, paraBounds
[i
], paraBounds
[i
+1]);
1870 errorCode
=U_ZERO_ERROR
;
1871 /* check with last paragraph not terminated by B */
1873 ubidi_setPara(pBidi
, src
, srcSize
, UBIDI_LTR
, NULL
, &errorCode
);
1874 if(U_FAILURE(errorCode
)){
1875 log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
1876 UBIDI_LTR
, u_errorName(errorCode
));
1880 if (paraCount
!=(count
=ubidi_countParagraphs(pBidi
))) {
1881 log_err("2nd ubidi_countParagraphs returned %d, should be %d\n",
1885 ubidi_getParagraphByIndex(pBidi
, i
, ¶Start
, ¶Limit
, NULL
, &errorCode
);
1886 if ((paraStart
!=paraBounds
[i
]) || (paraLimit
!=paraBounds
[i
+1])) {
1887 log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
1888 i
, paraStart
, paraLimit
, paraBounds
[i
], paraBounds
[i
+1]);
1890 errorCode
=U_ZERO_ERROR
;
1891 /* check paraLevel for all paragraphs under various paraLevel specs */
1892 for (k
=0; k
<6; k
++) {
1893 ubidi_setPara(pBidi
, src
, srcSize
, paraLevels
[k
], NULL
, &errorCode
);
1894 for (i
=0; i
<paraCount
; i
++) {
1895 paraIndex
=ubidi_getParagraph(pBidi
, paraBounds
[i
], NULL
, NULL
, &gotLevel
, &errorCode
);
1897 log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n",
1898 paraLevels
[k
], i
, paraIndex
, i
);
1900 if (gotLevel
!=multiLevels
[k
][i
]) {
1901 log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n",
1902 paraLevels
[k
], i
, gotLevel
, multiLevels
[k
][i
]);
1905 gotLevel
=ubidi_getParaLevel(pBidi
);
1906 if (gotLevel
!=multiLevels
[k
][0]) {
1907 log_err("For paraLevel=%d getParaLevel=%d, expected %d\n",
1908 paraLevels
[k
], gotLevel
, multiLevels
[k
][0]);
1911 errorCode
=U_ZERO_ERROR
;
1912 /* check that the result of ubidi_getParaLevel changes if the first
1913 * paragraph has a different level
1915 src
[0]=0x05d2; /* Hebrew letter Gimel */
1916 ubidi_setPara(pBidi
, src
, srcSize
, UBIDI_DEFAULT_LTR
, NULL
, &errorCode
);
1917 gotLevel
=ubidi_getParaLevel(pBidi
);
1918 if (gotLevel
!=UBIDI_RTL
) {
1919 log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n",
1920 gotLevel
, UBIDI_RTL
);
1922 errorCode
=U_ZERO_ERROR
;
1923 /* check that line cannot overlap paragraph boundaries */
1927 ubidi_setLine(pBidi
, i
, k
, pLine
, &errorCode
);
1928 if (U_SUCCESS(errorCode
)) {
1929 log_err("For line limits %d-%d got success %s\n",
1930 i
, k
, u_errorName(errorCode
));
1932 errorCode
=U_ZERO_ERROR
;
1935 ubidi_setLine(pBidi
, i
, k
, pLine
, &errorCode
);
1936 if (U_FAILURE(errorCode
)) {
1937 log_err("For line limits %d-%d got error %s\n",
1938 i
, k
, u_errorName(errorCode
));
1939 errorCode
=U_ZERO_ERROR
;
1941 /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */
1942 ubidi_setPara(pBidi
, src
, srcSize
, UBIDI_RTL
, NULL
, &errorCode
);
1943 /* get levels through para Bidi block */
1944 gotLevels
=ubidi_getLevels(pBidi
, &errorCode
);
1945 if (U_FAILURE(errorCode
)) {
1946 log_err("Error on Para getLevels %s\n", u_errorName(errorCode
));
1951 for (i
=26; i
<32; i
++) {
1952 if (gotLevels
[i
]!=UBIDI_RTL
) {
1953 log_err("For char %d(%04x), level=%d, expected=%d\n",
1954 i
, src
[i
], gotLevels
[i
], UBIDI_RTL
);
1957 /* get levels through para Line block */
1960 ubidi_setLine(pBidi
, i
, k
, pLine
, &errorCode
);
1961 if (U_FAILURE(errorCode
)) {
1962 log_err("For line limits %d-%d got error %s\n",
1963 i
, k
, u_errorName(errorCode
));
1968 paraIndex
=ubidi_getParagraph(pLine
, i
, ¶Start
, ¶Limit
, &gotLevel
, &errorCode
);
1969 gotLevels
=ubidi_getLevels(pLine
, &errorCode
);
1970 if (U_FAILURE(errorCode
)) {
1971 log_err("Error on Line getLevels %s\n", u_errorName(errorCode
));
1976 length
=ubidi_getLength(pLine
);
1977 if ((gotLevel
!=UBIDI_RTL
) || (gotLevels
[length
-1]!=UBIDI_RTL
)) {
1978 log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
1979 "level of separator=%d expected=%d\n",
1980 paraIndex
, paraStart
, paraLimit
, gotLevel
, UBIDI_RTL
, gotLevels
[length
-1], UBIDI_RTL
);
1982 orderParagraphsLTR
=ubidi_isOrderParagraphsLTR(pBidi
);
1983 if (orderParagraphsLTR
) {
1984 log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR
, FALSE
);
1986 ubidi_orderParagraphsLTR(pBidi
, TRUE
);
1987 orderParagraphsLTR
=ubidi_isOrderParagraphsLTR(pBidi
);
1988 if (!orderParagraphsLTR
) {
1989 log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR
, TRUE
);
1991 /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */
1992 ubidi_setPara(pBidi
, src
, srcSize
, UBIDI_RTL
, NULL
, &errorCode
);
1993 /* get levels through para Bidi block */
1994 gotLevels
=ubidi_getLevels(pBidi
, &errorCode
);
1995 for (i
=26; i
<32; i
++) {
1996 if (gotLevels
[i
]!=0) {
1997 log_err("For char %d(%04x), level=%d, expected=%d\n",
1998 i
, src
[i
], gotLevels
[i
], 0);
2001 errorCode
=U_ZERO_ERROR
;
2002 /* get levels through para Line block */
2005 ubidi_setLine(pBidi
, paraStart
, paraLimit
, pLine
, &errorCode
);
2006 paraIndex
=ubidi_getParagraph(pLine
, i
, ¶Start
, ¶Limit
, &gotLevel
, &errorCode
);
2007 gotLevels
=ubidi_getLevels(pLine
, &errorCode
);
2008 length
=ubidi_getLength(pLine
);
2009 if ((gotLevel
!=UBIDI_RTL
) || (gotLevels
[length
-1]!=0)) {
2010 log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
2011 "level of separator=%d expected=%d\n",
2012 paraIndex
, paraStart
, paraLimit
, gotLevel
, UBIDI_RTL
, gotLevels
[length
-1], 0);
2013 log_verbose("levels=");
2014 for (count
=0; count
<length
; count
++) {
2015 log_verbose(" %d", gotLevels
[count
]);
2020 /* test that the concatenation of separate invocations of the bidi code
2021 * on each individual paragraph in order matches the levels array that
2022 * results from invoking bidi once over the entire multiparagraph tests
2023 * (with orderParagraphsLTR false, of course)
2025 u_unescape(text
, src
, MAXLEN
); /* restore original content */
2026 srcSize
=u_strlen(src
);
2027 ubidi_orderParagraphsLTR(pBidi
, FALSE
);
2028 ubidi_setPara(pBidi
, src
, srcSize
, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
2029 gotLevels
=ubidi_getLevels(pBidi
, &errorCode
);
2030 for (i
=0; i
<paraCount
; i
++) {
2031 /* use pLine for individual paragraphs */
2032 paraStart
= paraBounds
[i
];
2033 length
= paraBounds
[i
+1] - paraStart
;
2034 ubidi_setPara(pLine
, src
+paraStart
, length
, UBIDI_DEFAULT_RTL
, NULL
, &errorCode
);
2035 for (j
=0; j
<length
; j
++) {
2036 if ((k
=ubidi_getLevelAt(pLine
, j
)) != (gotLevel
=gotLevels
[paraStart
+j
])) {
2037 log_err("Checking paragraph concatenation: for paragraph=%d, "
2038 "char=%d(%04x), level=%d, expected=%d\n",
2039 i
, j
, src
[paraStart
+j
], k
, gotLevel
);
2044 /* ensure that leading numerics in a paragraph are not treated as arabic
2045 numerals because of arabic text in a preceding paragraph
2047 u_unescape(text2
, src
, MAXLEN
);
2048 srcSize
=u_strlen(src
);
2049 ubidi_orderParagraphsLTR(pBidi
, TRUE
);
2050 ubidi_setPara(pBidi
, src
, srcSize
, UBIDI_RTL
, NULL
, &errorCode
);
2051 gotLevels
=ubidi_getLevels(pBidi
, &errorCode
);
2052 if (U_FAILURE(errorCode
)) {
2053 log_err("Can't get levels. %s\n", u_errorName(errorCode
));
2056 for (i
=0; i
<srcSize
; i
++) {
2057 if (gotLevels
[i
]!=levels2
[i
]) {
2058 log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n",
2059 i
, src
[i
], gotLevels
[i
], levels2
[i
]);
2063 /* check handling of whitespace before end of paragraph separator when
2064 * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B
2066 u_memset(src
, 0x0020, MAXLEN
);
2068 ubidi_orderParagraphsLTR(pBidi
, TRUE
);
2069 for (i
=0x001c; i
<=0x0020; i
+=(0x0020-0x001c)) {
2070 src
[4]=(UChar
)i
; /* with and without terminating B */
2071 for (j
=0x0041; j
<=0x05d0; j
+=(0x05d0-0x0041)) {
2072 src
[0]=(UChar
)j
; /* leading 'A' or Alef */
2073 for (gotLevel
=4; gotLevel
<=5; gotLevel
++) {
2074 /* test even and odd paraLevel */
2075 ubidi_setPara(pBidi
, src
, srcSize
, gotLevel
, NULL
, &errorCode
);
2076 gotLevels
=ubidi_getLevels(pBidi
, &errorCode
);
2077 for (k
=1; k
<=3; k
++) {
2078 if (gotLevels
[k
]!=gotLevel
) {
2079 log_err("Checking trailing spaces: for leading_char=%04x, "
2080 "last_char=%04x, index=%d, level=%d, expected=%d\n",
2081 src
[0], src
[4], k
, gotLevels
[k
], gotLevel
);
2088 /* check default orientation when inverse bidi and paragraph starts
2089 * with LTR strong char and ends with RTL strong char, with and without
2092 ubidi_setReorderingMode(pBidi
, UBIDI_REORDER_INVERSE_LIKE_DIRECT
);
2093 srcLen
= u_unescape("abc \\u05d2\\u05d1\n", src
, MAXLEN
);
2094 ubidi_setPara(pBidi
, src
, srcLen
, UBIDI_DEFAULT_LTR
, NULL
, &errorCode
);
2095 destLen
= ubidi_writeReordered(pBidi
, dest
, MAXLEN
, 0, &errorCode
);
2096 srcLen
= u_unescape("\\u05d1\\u05d2 abc\n", src
, MAXLEN
);
2097 if (memcmp(src
, dest
, destLen
* sizeof(UChar
))) {
2098 log_err("\nInvalid output #0, should be '%s', got '%s'\n",
2099 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
2101 srcLen
= u_unescape("abc \\u05d2\\u05d1", src
, MAXLEN
);
2102 ubidi_setPara(pBidi
, src
, srcLen
, UBIDI_DEFAULT_LTR
, NULL
, &errorCode
);
2103 destLen
= ubidi_writeReordered(pBidi
, dest
, MAXLEN
, 0, &errorCode
);
2104 srcLen
= u_unescape("\\u05d1\\u05d2 abc", src
, MAXLEN
);
2105 if (memcmp(src
, dest
, destLen
* sizeof(UChar
))) {
2106 log_err("\nInvalid output #1, should be '%s', got '%s'\n",
2107 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
2110 /* check multiple paragraphs together with explicit levels
2112 ubidi_setReorderingMode(pBidi
, UBIDI_REORDER_DEFAULT
);
2113 srcLen
= u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src
, MAXLEN
);
2114 ubidi_setPara(pBidi
, src
, srcLen
, UBIDI_LTR
, myLevels
, &errorCode
);
2115 destLen
= ubidi_writeReordered(pBidi
, dest
, MAXLEN
, 0, &errorCode
);
2116 srcLen
= u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src
, MAXLEN
);
2117 if (memcmp(src
, dest
, destLen
* sizeof(UChar
))) {
2118 log_err("\nInvalid output #2, should be '%s', got '%s'\n",
2119 aescstrdup(src
, srcLen
), aescstrdup(dest
, destLen
));
2121 count
= ubidi_countParagraphs(pBidi
);
2123 log_err("\nInvalid number of paras, should be 2, got %d\n", count
);
2128 log_verbose("\nExiting TestMultipleParagraphs\n\n");
2130 /* check levels in multiple paragraphs with default para level
2132 pBidi
= ubidi_open();
2133 errorCode
= U_ZERO_ERROR
;
2134 ubidi_setPara(pBidi
, multiparaTestString
, LENGTHOF(multiparaTestString
),
2135 UBIDI_DEFAULT_LTR
, NULL
, &errorCode
);
2136 if (U_FAILURE(errorCode
)) {
2137 log_err("ubidi_setPara failed for multiparaTestString\n");
2141 gotLevels
= ubidi_getLevels(pBidi
, &errorCode
);
2142 if (U_FAILURE(errorCode
)) {
2143 log_err("ubidi_getLevels failed for multiparaTestString\n");
2147 for (i
= 0; i
< LENGTHOF(multiparaTestString
); i
++) {
2148 if (gotLevels
[i
] != multiparaTestLevels
[i
]) {
2149 log_err("Error on level for multiparaTestString at index %d, "
2150 "expected=%d, actual=%d\n",
2151 i
, multiparaTestLevels
[i
], gotLevels
[i
]);
2159 /* inverse BiDi ------------------------------------------------------------- */
2161 static int countRoundtrips
=0, countNonRoundtrips
=0;
2163 #define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
2168 string0
[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 },
2169 string1
[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 },
2170 string2
[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 },
2171 string3
[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 },
2172 string4
[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 };
2174 static const struct {
2178 STRING_TEST_CASE(string0
),
2179 STRING_TEST_CASE(string1
),
2180 STRING_TEST_CASE(string2
),
2181 STRING_TEST_CASE(string3
),
2182 STRING_TEST_CASE(string4
)
2186 UErrorCode errorCode
;
2189 log_verbose("\nEntering TestInverse\n\n");
2192 log_err("unable to open a UBiDi object (out of memory)\n");
2196 log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", LENGTHOF(testCases
));
2197 for(i
=0; i
<LENGTHOF(testCases
); ++i
) {
2198 log_verbose("Testing case %d\n", i
);
2199 errorCode
=U_ZERO_ERROR
;
2200 _testInverseBidi(pBiDi
, testCases
[i
].s
, testCases
[i
].length
, 0, &errorCode
);
2203 log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", LENGTHOF(testCases
));
2204 for(i
=0; i
<LENGTHOF(testCases
); ++i
) {
2205 log_verbose("Testing case %d\n", i
);
2206 errorCode
=U_ZERO_ERROR
;
2207 _testInverseBidi(pBiDi
, testCases
[i
].s
, testCases
[i
].length
, 1, &errorCode
);
2210 _testManyInverseBidi(pBiDi
, 0);
2211 _testManyInverseBidi(pBiDi
, 1);
2215 log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips
, countNonRoundtrips
);
2217 _testWriteReverse();
2219 _testManyAddedPoints();
2223 log_verbose("\nExiting TestInverse\n\n");
2226 #define COUNT_REPEAT_SEGMENTS 6
2228 static const UChar repeatSegments
[COUNT_REPEAT_SEGMENTS
][2]={
2229 { 0x61, 0x62 }, /* L */
2230 { 0x5d0, 0x5d1 }, /* R */
2231 { 0x627, 0x628 }, /* AL */
2232 { 0x31, 0x32 }, /* EN */
2233 { 0x661, 0x662 }, /* AN */
2234 { 0x20, 0x20 } /* WS (N) */
2238 _testManyInverseBidi(UBiDi
*pBiDi
, UBiDiLevel direction
) {
2239 UChar text
[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
2241 UErrorCode errorCode
;
2243 log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n",
2244 direction
==0 ? 'L' : 'R');
2245 for(i
=0; i
<COUNT_REPEAT_SEGMENTS
; ++i
) {
2246 text
[0]=repeatSegments
[i
][0];
2247 text
[1]=repeatSegments
[i
][1];
2248 for(j
=0; j
<COUNT_REPEAT_SEGMENTS
; ++j
) {
2249 text
[3]=repeatSegments
[j
][0];
2250 text
[4]=repeatSegments
[j
][1];
2251 for(k
=0; k
<COUNT_REPEAT_SEGMENTS
; ++k
) {
2252 text
[6]=repeatSegments
[k
][0];
2253 text
[7]=repeatSegments
[k
][1];
2255 errorCode
=U_ZERO_ERROR
;
2256 log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i
, j
, k
);
2257 _testInverseBidi(pBiDi
, text
, 8, direction
, &errorCode
);
2264 _testInverseBidi(UBiDi
*pBiDi
, const UChar
*src
, int32_t srcLength
,
2265 UBiDiLevel direction
, UErrorCode
*pErrorCode
) {
2266 UChar visualLTR
[MAXLEN
], logicalDest
[MAXLEN
], visualDest
[MAXLEN
];
2267 int32_t ltrLength
, logicalLength
, visualLength
;
2270 log_verbose("inverse Bidi: testInverse(L)\n");
2272 /* convert visual to logical */
2273 ubidi_setInverse(pBiDi
, TRUE
);
2274 if (!ubidi_isInverse(pBiDi
)) {
2275 log_err("Error while doing ubidi_setInverse(TRUE)\n");
2277 ubidi_setPara(pBiDi
, src
, srcLength
, 0, NULL
, pErrorCode
);
2278 if (src
!= ubidi_getText(pBiDi
)) {
2279 log_err("Wrong value returned by ubidi_getText\n");
2281 logicalLength
=ubidi_writeReordered(pBiDi
, logicalDest
, LENGTHOF(logicalDest
),
2282 UBIDI_DO_MIRRORING
|UBIDI_INSERT_LRM_FOR_NUMERIC
, pErrorCode
);
2284 printUnicode(src
, srcLength
, ubidi_getLevels(pBiDi
, pErrorCode
));
2287 /* convert back to visual LTR */
2288 ubidi_setInverse(pBiDi
, FALSE
);
2289 if (ubidi_isInverse(pBiDi
)) {
2290 log_err("Error while doing ubidi_setInverse(FALSE)\n");
2292 ubidi_setPara(pBiDi
, logicalDest
, logicalLength
, 0, NULL
, pErrorCode
);
2293 visualLength
=ubidi_writeReordered(pBiDi
, visualDest
, LENGTHOF(visualDest
),
2294 UBIDI_DO_MIRRORING
|UBIDI_REMOVE_BIDI_CONTROLS
, pErrorCode
);
2296 log_verbose("inverse Bidi: testInverse(R)\n");
2298 /* reverse visual from RTL to LTR */
2299 ltrLength
=ubidi_writeReverse(src
, srcLength
, visualLTR
, LENGTHOF(visualLTR
), 0, pErrorCode
);
2301 printUnicode(src
, srcLength
, NULL
);
2304 /* convert visual RTL to logical */
2305 ubidi_setInverse(pBiDi
, TRUE
);
2306 ubidi_setPara(pBiDi
, visualLTR
, ltrLength
, 0, NULL
, pErrorCode
);
2307 logicalLength
=ubidi_writeReordered(pBiDi
, logicalDest
, LENGTHOF(logicalDest
),
2308 UBIDI_DO_MIRRORING
|UBIDI_INSERT_LRM_FOR_NUMERIC
, pErrorCode
);
2310 printUnicode(visualLTR
, ltrLength
, ubidi_getLevels(pBiDi
, pErrorCode
));
2313 /* convert back to visual RTL */
2314 ubidi_setInverse(pBiDi
, FALSE
);
2315 ubidi_setPara(pBiDi
, logicalDest
, logicalLength
, 0, NULL
, pErrorCode
);
2316 visualLength
=ubidi_writeReordered(pBiDi
, visualDest
, LENGTHOF(visualDest
),
2317 UBIDI_DO_MIRRORING
|UBIDI_REMOVE_BIDI_CONTROLS
|UBIDI_OUTPUT_REVERSE
, pErrorCode
);
2320 printUnicode(logicalDest
, logicalLength
, ubidi_getLevels(pBiDi
, pErrorCode
));
2323 printUnicode(visualDest
, visualLength
, NULL
);
2326 /* check and print results */
2327 if(U_FAILURE(*pErrorCode
)) {
2328 log_err("inverse BiDi: *** error %s\n"
2329 " turn on verbose mode to see details\n", u_errorName(*pErrorCode
));
2330 } else if(srcLength
==visualLength
&& memcmp(src
, visualDest
, srcLength
*U_SIZEOF_UCHAR
)==0) {
2332 log_verbose(" + roundtripped\n");
2334 ++countNonRoundtrips
;
2335 log_verbose(" * did not roundtrip\n");
2336 log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n"
2337 " turn on verbose mode to see details\n");
2342 _testWriteReverse(void) {
2343 /* U+064e and U+0650 are combining marks (Mn) */
2344 static const UChar forward
[]={
2345 0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29
2346 }, reverseKeepCombining
[]={
2347 0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f
2348 }, reverseRemoveControlsKeepCombiningDoMirror
[]={
2349 0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650
2352 UErrorCode errorCode
;
2355 /* test ubidi_writeReverse() with "interesting" options */
2356 errorCode
=U_ZERO_ERROR
;
2357 length
=ubidi_writeReverse(forward
, LENGTHOF(forward
),
2358 reverse
, LENGTHOF(reverse
),
2359 UBIDI_KEEP_BASE_COMBINING
,
2361 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(reverseKeepCombining
) || memcmp(reverse
, reverseKeepCombining
, length
*U_SIZEOF_UCHAR
)!=0) {
2362 log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n",
2363 length
, LENGTHOF(reverseKeepCombining
), u_errorName(errorCode
));
2366 memset(reverse
, 0xa5, LENGTHOF(reverse
)*U_SIZEOF_UCHAR
);
2367 errorCode
=U_ZERO_ERROR
;
2368 length
=ubidi_writeReverse(forward
, LENGTHOF(forward
),
2369 reverse
, LENGTHOF(reverse
),
2370 UBIDI_REMOVE_BIDI_CONTROLS
|UBIDI_DO_MIRRORING
|UBIDI_KEEP_BASE_COMBINING
,
2372 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror
) || memcmp(reverse
, reverseRemoveControlsKeepCombiningDoMirror
, length
*U_SIZEOF_UCHAR
)!=0) {
2373 log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n"
2374 " length=%d (should be %d), error code %s\n",
2375 length
, LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror
), u_errorName(errorCode
));
2379 static void _testManyAddedPoints(void) {
2380 UErrorCode errorCode
= U_ZERO_ERROR
;
2381 UBiDi
*bidi
= ubidi_open();
2382 UChar text
[90], dest
[MAXLEN
], expected
[120];
2384 for (i
= 0; i
< LENGTHOF(text
); i
+=3) {
2385 text
[i
] = 0x0061; /* 'a' */
2387 text
[i
+2] = 0x0033; /* '3' */
2389 ubidi_setReorderingMode(bidi
, UBIDI_REORDER_INVERSE_LIKE_DIRECT
);
2390 ubidi_setReorderingOptions(bidi
, UBIDI_OPTION_INSERT_MARKS
);
2391 ubidi_setPara(bidi
, text
, LENGTHOF(text
), UBIDI_LTR
, NULL
, &errorCode
);
2392 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
, 0, &errorCode
);
2393 for (i
= 0; i
< LENGTHOF(expected
); i
+=4) {
2394 expected
[i
] = 0x0061; /* 'a' */
2395 expected
[i
+1] = 0x05d0;
2396 expected
[i
+2] = 0x200e;
2397 expected
[i
+3] = 0x0033; /* '3' */
2399 if (memcmp(dest
, expected
, destLen
* sizeof(UChar
))) {
2400 log_err("\nInvalid output with many added points, "
2401 "expected '%s', got '%s'\n",
2402 aescstrdup(expected
, LENGTHOF(expected
)),
2403 aescstrdup(dest
, destLen
));
2408 static void _testMisc(void) {
2409 UErrorCode errorCode
= U_ZERO_ERROR
;
2410 UBiDi
*bidi
= ubidi_open();
2411 UChar src
[3], dest
[MAXLEN
], expected
[5];
2413 ubidi_setInverse(bidi
, TRUE
);
2414 src
[0] = src
[1] = src
[2] = 0x0020;
2415 ubidi_setPara(bidi
, src
, LENGTHOF(src
), UBIDI_RTL
, NULL
, &errorCode
);
2416 destLen
= ubidi_writeReordered(bidi
, dest
, MAXLEN
,
2417 UBIDI_OUTPUT_REVERSE
| UBIDI_INSERT_LRM_FOR_NUMERIC
,
2419 u_unescape("\\u200f \\u200f", expected
, 5);
2420 if (memcmp(dest
, expected
, destLen
* sizeof(UChar
))) {
2421 log_err("\nInvalid output with RLM at both sides, "
2422 "expected '%s', got '%s'\n",
2423 aescstrdup(expected
, LENGTHOF(expected
)),
2424 aescstrdup(dest
, destLen
));
2429 /* arabic shaping ----------------------------------------------------------- */
2432 doArabicShapingTest(void) {
2436 0x627, /* arabic:alef */
2443 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0
2445 0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0
2446 }, logical_alen2an_init_lr
[]={
2447 0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0
2448 }, logical_alen2an_init_al
[]={
2449 0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0
2450 }, reverse_alen2an_init_lr
[]={
2451 0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0
2452 }, reverse_alen2an_init_al
[]={
2453 0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0
2458 UErrorCode errorCode
;
2461 /* test number shaping */
2463 /* european->arabic */
2464 errorCode
=U_ZERO_ERROR
;
2465 length
=u_shapeArabic(source
, LENGTHOF(source
),
2466 dest
, LENGTHOF(dest
),
2467 U_SHAPE_DIGITS_EN2AN
|U_SHAPE_DIGIT_TYPE_AN
,
2469 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(source
) || memcmp(dest
, en2an
, length
*U_SIZEOF_UCHAR
)!=0) {
2470 log_err("failure in u_shapeArabic(en2an)\n");
2473 /* arabic->european */
2474 errorCode
=U_ZERO_ERROR
;
2475 length
=u_shapeArabic(source
, -1,
2476 dest
, LENGTHOF(dest
),
2477 U_SHAPE_DIGITS_AN2EN
|U_SHAPE_DIGIT_TYPE_AN_EXTENDED
,
2479 if(U_FAILURE(errorCode
) || length
!=u_strlen(source
) || memcmp(dest
, an2en
, length
*U_SIZEOF_UCHAR
)!=0) {
2480 log_err("failure in u_shapeArabic(an2en)\n");
2483 /* european->arabic with context, logical order, initial state not AL */
2484 errorCode
=U_ZERO_ERROR
;
2485 length
=u_shapeArabic(source
, LENGTHOF(source
),
2486 dest
, LENGTHOF(dest
),
2487 U_SHAPE_DIGITS_ALEN2AN_INIT_LR
|U_SHAPE_DIGIT_TYPE_AN
,
2489 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(source
) || memcmp(dest
, logical_alen2an_init_lr
, length
*U_SIZEOF_UCHAR
)!=0) {
2490 log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n");
2493 /* european->arabic with context, logical order, initial state AL */
2494 errorCode
=U_ZERO_ERROR
;
2495 length
=u_shapeArabic(source
, LENGTHOF(source
),
2496 dest
, LENGTHOF(dest
),
2497 U_SHAPE_DIGITS_ALEN2AN_INIT_AL
|U_SHAPE_DIGIT_TYPE_AN_EXTENDED
,
2499 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(source
) || memcmp(dest
, logical_alen2an_init_al
, length
*U_SIZEOF_UCHAR
)!=0) {
2500 log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n");
2503 /* european->arabic with context, reverse order, initial state not AL */
2504 errorCode
=U_ZERO_ERROR
;
2505 length
=u_shapeArabic(source
, LENGTHOF(source
),
2506 dest
, LENGTHOF(dest
),
2507 U_SHAPE_DIGITS_ALEN2AN_INIT_LR
|U_SHAPE_DIGIT_TYPE_AN
|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2509 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(source
) || memcmp(dest
, reverse_alen2an_init_lr
, length
*U_SIZEOF_UCHAR
)!=0) {
2510 log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n");
2513 /* european->arabic with context, reverse order, initial state AL */
2514 errorCode
=U_ZERO_ERROR
;
2515 length
=u_shapeArabic(source
, LENGTHOF(source
),
2516 dest
, LENGTHOF(dest
),
2517 U_SHAPE_DIGITS_ALEN2AN_INIT_AL
|U_SHAPE_DIGIT_TYPE_AN_EXTENDED
|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2519 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(source
) || memcmp(dest
, reverse_alen2an_init_al
, length
*U_SIZEOF_UCHAR
)!=0) {
2520 log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n");
2524 errorCode
=U_ZERO_ERROR
;
2525 length
=u_shapeArabic(source
, LENGTHOF(source
),
2526 dest
, LENGTHOF(dest
),
2529 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(source
) || memcmp(dest
, source
, length
*U_SIZEOF_UCHAR
)!=0) {
2530 log_err("failure in u_shapeArabic(noop)\n");
2533 errorCode
=U_ZERO_ERROR
;
2534 length
=u_shapeArabic(source
, 0,
2535 dest
, LENGTHOF(dest
),
2536 U_SHAPE_DIGITS_EN2AN
|U_SHAPE_DIGIT_TYPE_AN
,
2538 if(U_FAILURE(errorCode
) || length
!=0) {
2539 log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode
), LENGTHOF(source
));
2542 /* preflight digit shaping */
2543 errorCode
=U_ZERO_ERROR
;
2544 length
=u_shapeArabic(source
, LENGTHOF(source
),
2546 U_SHAPE_DIGITS_EN2AN
|U_SHAPE_DIGIT_TYPE_AN
,
2548 if(errorCode
!=U_BUFFER_OVERFLOW_ERROR
|| length
!=LENGTHOF(source
)) {
2549 log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n",
2550 length
, u_errorName(errorCode
), LENGTHOF(source
));
2553 /* test illegal arguments */
2554 errorCode
=U_ZERO_ERROR
;
2555 length
=u_shapeArabic(NULL
, LENGTHOF(source
),
2556 dest
, LENGTHOF(dest
),
2557 U_SHAPE_DIGITS_EN2AN
|U_SHAPE_DIGIT_TYPE_AN
,
2559 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2560 log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode
));
2563 errorCode
=U_ZERO_ERROR
;
2564 length
=u_shapeArabic(source
, -2,
2565 dest
, LENGTHOF(dest
),
2566 U_SHAPE_DIGITS_EN2AN
|U_SHAPE_DIGIT_TYPE_AN
,
2568 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2569 log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode
));
2572 errorCode
=U_ZERO_ERROR
;
2573 length
=u_shapeArabic(source
, LENGTHOF(source
),
2574 NULL
, LENGTHOF(dest
),
2575 U_SHAPE_DIGITS_EN2AN
|U_SHAPE_DIGIT_TYPE_AN
,
2577 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2578 log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode
));
2581 errorCode
=U_ZERO_ERROR
;
2582 length
=u_shapeArabic(source
, LENGTHOF(source
),
2584 U_SHAPE_DIGITS_EN2AN
|U_SHAPE_DIGIT_TYPE_AN
,
2586 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2587 log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode
));
2590 errorCode
=U_ZERO_ERROR
;
2591 length
=u_shapeArabic(source
, LENGTHOF(source
),
2592 dest
, LENGTHOF(dest
),
2593 U_SHAPE_DIGITS_RESERVED
|U_SHAPE_DIGIT_TYPE_AN
,
2595 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2596 log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode
));
2599 errorCode
=U_ZERO_ERROR
;
2600 length
=u_shapeArabic(source
, LENGTHOF(source
),
2601 dest
, LENGTHOF(dest
),
2602 U_SHAPE_DIGITS_EN2AN
|U_SHAPE_DIGIT_TYPE_RESERVED
,
2604 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2605 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode
));
2608 errorCode
=U_ZERO_ERROR
;
2609 length
=u_shapeArabic(source
, LENGTHOF(source
),
2610 (UChar
*)(source
+2), LENGTHOF(dest
), /* overlap source and destination */
2611 U_SHAPE_DIGITS_EN2AN
|U_SHAPE_DIGIT_TYPE_AN
,
2613 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2614 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode
));
2617 errorCode
=U_ZERO_ERROR
;
2618 length
=u_shapeArabic(lamalef
, LENGTHOF(lamalef
),
2619 dest
, LENGTHOF(dest
),
2620 U_SHAPE_LETTERS_UNSHAPE
| U_SHAPE_LENGTH_GROW_SHRINK
| U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2622 if(U_FAILURE(errorCode
) || length
== LENGTHOF(lamalef
)) {
2623 log_err("failure in u_shapeArabic(U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR)\n");
2624 log_err("returned %s instead of U_ZERO_ERROR or returned length %d instead of 3\n", u_errorName(errorCode
), length
);
2629 doLamAlefSpecialVLTRArabicShapingTest(void) {
2632 /*a*/ 0x20 ,0x646,0x622,0x644,0x627,0x20,
2633 /*b*/ 0x646,0x623,0x64E,0x644,0x627,0x20,
2634 /*c*/ 0x646,0x627,0x670,0x644,0x627,0x20,
2635 /*d*/ 0x646,0x622,0x653,0x644,0x627,0x20,
2636 /*e*/ 0x646,0x625,0x655,0x644,0x627,0x20,
2637 /*f*/ 0x646,0x622,0x654,0x644,0x627,0x20,
2640 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
2641 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
2642 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
2645 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
2646 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
2647 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20
2648 }, shape_at_begin
[]={
2649 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
2650 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
2651 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2652 }, shape_grow_shrink
[]={
2653 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
2654 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
2655 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2656 }, shape_excepttashkeel_near
[]={
2657 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
2658 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
2659 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
2661 }, shape_excepttashkeel_at_end
[]={
2662 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
2663 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
2664 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,
2666 }, shape_excepttashkeel_at_begin
[]={
2667 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
2668 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
2669 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2670 }, shape_excepttashkeel_grow_shrink
[]={
2671 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
2672 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
2673 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2677 UErrorCode errorCode
;
2680 errorCode
=U_ZERO_ERROR
;
2682 length
=u_shapeArabic(source
, LENGTHOF(source
),
2683 dest
, LENGTHOF(dest
),
2684 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_LENGTH_FIXED_SPACES_NEAR
|
2685 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2688 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(shape_near
) || memcmp(dest
, shape_near
, length
*U_SIZEOF_UCHAR
)!=0) {
2689 log_err("failure in u_shapeArabic(LAMALEF shape_near)\n");
2692 errorCode
=U_ZERO_ERROR
;
2694 length
=u_shapeArabic(source
, LENGTHOF(source
),
2695 dest
, LENGTHOF(dest
),
2696 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_LENGTH_FIXED_SPACES_AT_END
|
2697 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2700 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(shape_at_end
) || memcmp(dest
, shape_at_end
, length
*U_SIZEOF_UCHAR
)!=0) {
2701 log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n");
2704 errorCode
=U_ZERO_ERROR
;
2706 length
=u_shapeArabic(source
, LENGTHOF(source
),
2707 dest
, LENGTHOF(dest
),
2708 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING
|
2709 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2712 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(shape_at_begin
) || memcmp(dest
, shape_at_begin
, length
*U_SIZEOF_UCHAR
)!=0) {
2713 log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n");
2716 errorCode
=U_ZERO_ERROR
;
2718 length
=u_shapeArabic(source
, LENGTHOF(source
),
2719 dest
, LENGTHOF(dest
),
2720 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_LENGTH_GROW_SHRINK
|
2721 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2724 if(U_FAILURE(errorCode
) || memcmp(dest
, shape_grow_shrink
, length
*U_SIZEOF_UCHAR
)!=0) {
2725 log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n");
2728 /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */
2730 errorCode
=U_ZERO_ERROR
;
2732 length
=u_shapeArabic(source
, LENGTHOF(source
),
2733 dest
, LENGTHOF(dest
),
2734 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED
|U_SHAPE_LENGTH_FIXED_SPACES_NEAR
|
2735 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2738 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(shape_excepttashkeel_near
) || memcmp(dest
, shape_excepttashkeel_near
, length
*U_SIZEOF_UCHAR
)!=0) {
2739 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n");
2742 errorCode
=U_ZERO_ERROR
;
2744 length
=u_shapeArabic(source
, LENGTHOF(source
),
2745 dest
, LENGTHOF(dest
),
2746 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED
|U_SHAPE_LENGTH_FIXED_SPACES_AT_END
|
2747 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2750 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(shape_excepttashkeel_at_end
) || memcmp(dest
,shape_excepttashkeel_at_end
, length
*U_SIZEOF_UCHAR
)!=0) {
2751 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n");
2754 errorCode
=U_ZERO_ERROR
;
2756 length
=u_shapeArabic(source
, LENGTHOF(source
),
2757 dest
, LENGTHOF(dest
),
2758 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED
|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING
|
2759 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2762 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(shape_excepttashkeel_at_begin
) || memcmp(dest
, shape_excepttashkeel_at_begin
, length
*U_SIZEOF_UCHAR
)!=0) {
2763 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n");
2766 errorCode
=U_ZERO_ERROR
;
2768 length
=u_shapeArabic(source
, LENGTHOF(source
),
2769 dest
, LENGTHOF(dest
),
2770 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED
|U_SHAPE_LENGTH_GROW_SHRINK
|
2771 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2774 if(U_FAILURE(errorCode
) || memcmp(dest
, shape_excepttashkeel_grow_shrink
, length
*U_SIZEOF_UCHAR
)!=0) {
2775 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n");
2780 doTashkeelSpecialVLTRArabicShapingTest(void) {
2783 0x64A,0x628,0x631,0x639,0x20,
2784 0x64A,0x628,0x651,0x631,0x64E,0x639,0x20,
2785 0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20,
2786 0x628,0x670,0x631,0x670,0x639,0x20,
2787 0x628,0x653,0x631,0x653,0x639,0x20,
2788 0x628,0x654,0x631,0x654,0x639,0x20,
2789 0x628,0x655,0x631,0x655,0x639,0x20,
2791 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb,
2792 0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,
2793 0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,
2794 0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
2795 }, shape_excepttashkeel_near
[]={
2796 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20,
2797 0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb,
2798 0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20,
2799 0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
2803 UErrorCode errorCode
;
2806 errorCode
=U_ZERO_ERROR
;
2808 length
=u_shapeArabic(source
, LENGTHOF(source
),
2809 dest
, LENGTHOF(dest
),
2810 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_LENGTH_FIXED_SPACES_NEAR
|
2811 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2814 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(shape_near
) || memcmp(dest
, shape_near
, length
*U_SIZEOF_UCHAR
)!=0) {
2815 log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n");
2818 errorCode
=U_ZERO_ERROR
;
2820 length
=u_shapeArabic(source
, LENGTHOF(source
),
2821 dest
, LENGTHOF(dest
),
2822 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED
|U_SHAPE_LENGTH_FIXED_SPACES_NEAR
|
2823 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2826 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(shape_excepttashkeel_near
) || memcmp(dest
, shape_excepttashkeel_near
, length
*U_SIZEOF_UCHAR
)!=0) {
2827 log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n");
2832 doLOGICALArabicDeShapingTest(void) {
2835 0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020,
2836 0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4,
2837 0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020
2839 0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627,
2840 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
2841 0x629,0x20,0x20,0x20,0x20
2842 }, unshape_at_end
[]={
2843 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
2844 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
2845 0x644,0x62d,0x631,0x629,0x20
2846 }, unshape_at_begin
[]={
2847 0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20,
2848 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
2849 0x629,0x20,0x20,0x20,0x20
2850 }, unshape_grow_shrink
[]={
2851 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
2852 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
2853 0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20
2857 UErrorCode errorCode
;
2860 errorCode
=U_ZERO_ERROR
;
2862 length
=u_shapeArabic(source
, LENGTHOF(source
),
2863 dest
, LENGTHOF(dest
),
2864 U_SHAPE_LETTERS_UNSHAPE
|U_SHAPE_LENGTH_FIXED_SPACES_NEAR
|
2865 U_SHAPE_TEXT_DIRECTION_LOGICAL
,
2868 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(unshape_near
) || memcmp(dest
, unshape_near
, length
*U_SIZEOF_UCHAR
)!=0) {
2869 log_err("failure in u_shapeArabic(unshape_near)\n");
2872 errorCode
=U_ZERO_ERROR
;
2874 length
=u_shapeArabic(source
, LENGTHOF(source
),
2875 dest
, LENGTHOF(dest
),
2876 U_SHAPE_LETTERS_UNSHAPE
|U_SHAPE_LENGTH_FIXED_SPACES_AT_END
|
2877 U_SHAPE_TEXT_DIRECTION_LOGICAL
,
2880 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(unshape_at_end
) || memcmp(dest
, unshape_at_end
, length
*U_SIZEOF_UCHAR
)!=0) {
2881 log_err("failure in u_shapeArabic(unshape_at_end)\n");
2884 errorCode
=U_ZERO_ERROR
;
2886 length
=u_shapeArabic(source
, LENGTHOF(source
),
2887 dest
, LENGTHOF(dest
),
2888 U_SHAPE_LETTERS_UNSHAPE
|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING
|
2889 U_SHAPE_TEXT_DIRECTION_LOGICAL
,
2892 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(unshape_at_begin
) || memcmp(dest
, unshape_at_begin
, length
*U_SIZEOF_UCHAR
)!=0) {
2893 log_err("failure in u_shapeArabic(unshape_at_begin)\n");
2896 errorCode
=U_ZERO_ERROR
;
2898 length
=u_shapeArabic(source
, LENGTHOF(source
),
2899 dest
, LENGTHOF(dest
),
2900 U_SHAPE_LETTERS_UNSHAPE
|U_SHAPE_LENGTH_GROW_SHRINK
|
2901 U_SHAPE_TEXT_DIRECTION_LOGICAL
,
2904 if(U_FAILURE(errorCode
) || memcmp(dest
, unshape_grow_shrink
, length
*U_SIZEOF_UCHAR
)!=0) {
2905 log_err("failure in u_shapeArabic(unshape_grow_shrink)\n");
2912 static const UChar src
[] = { 0x0020, 0x0633, 0 };
2913 static const UChar dst_old
[] = { 0xFEB1, 0x200B,0 };
2914 static const UChar dst_new
[] = { 0xFEB1, 0xFE73,0 };
2915 UChar dst
[3] = { 0x0000, 0x0000,0 };
2919 log_verbose("SRC: U+%04X U+%04X\n", src
[0],src
[1]);
2921 log_verbose("Trying old tail\n");
2922 status
= U_ZERO_ERROR
;
2923 length
= u_shapeArabic(src
, -1, dst
, LENGTHOF(dst
),
2924 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_SEEN_TWOCELL_NEAR
, &status
);
2925 if(U_FAILURE(status
)) {
2926 log_err("Fail: status %s\n", u_errorName(status
));
2927 } else if(length
!=2) {
2928 log_err("Fail: len %d expected 3\n", length
);
2929 } else if(u_strncmp(dst
,dst_old
,LENGTHOF(dst
))) {
2930 log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
2931 dst
[0],dst
[1],dst_old
[0],dst_old
[1]);
2933 log_verbose("OK: U+%04X U+%04X len %d err %s\n",
2934 dst
[0],dst
[1],length
,u_errorName(status
));
2938 log_verbose("Trying new tail\n");
2939 status
= U_ZERO_ERROR
;
2940 length
= u_shapeArabic(src
, -1, dst
, LENGTHOF(dst
),
2941 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_SEEN_TWOCELL_NEAR
|U_SHAPE_TAIL_NEW_UNICODE
, &status
);
2942 if(U_FAILURE(status
)) {
2943 log_err("Fail: status %s\n", u_errorName(status
));
2944 } else if(length
!=2) {
2945 log_err("Fail: len %d expected 3\n", length
);
2946 } else if(u_strncmp(dst
,dst_new
,LENGTHOF(dst
))) {
2947 log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
2948 dst
[0],dst
[1],dst_new
[0],dst_new
[1]);
2950 log_verbose("OK: U+%04X U+%04X len %d err %s\n",
2951 dst
[0],dst
[1],length
,u_errorName(status
));
2956 doArabicShapingTestForBug5421(void) {
2958 persian_letters_source
[]={
2959 0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020
2960 }, persian_letters
[]={
2961 0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020
2962 }, tashkeel_aggregation_source
[]={
2963 0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020,
2964 0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020
2965 }, tashkeel_aggregation
[]={
2966 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3,
2967 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020
2968 }, untouched_presentation_source
[]={
2969 0x0020 ,0x0627, 0xfe90,0x0020
2970 }, untouched_presentation
[]={
2971 0x0020,0xfe8D, 0xfe90,0x0020
2972 }, untouched_presentation_r_source
[]={
2973 0x0020 ,0xfe90, 0x0627, 0x0020
2974 }, untouched_presentation_r
[]={
2975 0x0020, 0xfe90,0xfe8D,0x0020
2979 UErrorCode errorCode
;
2982 errorCode
=U_ZERO_ERROR
;
2984 length
=u_shapeArabic(persian_letters_source
, LENGTHOF(persian_letters_source
),
2985 dest
, LENGTHOF(dest
),
2986 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
2989 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(persian_letters
) || memcmp(dest
, persian_letters
, length
*U_SIZEOF_UCHAR
)!=0) {
2990 log_err("failure in u_shapeArabic(persian_letters)\n");
2993 errorCode
=U_ZERO_ERROR
;
2995 length
=u_shapeArabic(tashkeel_aggregation_source
, LENGTHOF(tashkeel_aggregation_source
),
2996 dest
, LENGTHOF(dest
),
2997 U_SHAPE_AGGREGATE_TASHKEEL
|U_SHAPE_PRESERVE_PRESENTATION
|
2998 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED
|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
3001 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(tashkeel_aggregation
) || memcmp(dest
, tashkeel_aggregation
, length
*U_SIZEOF_UCHAR
)!=0) {
3002 log_err("failure in u_shapeArabic(tashkeel_aggregation)\n");
3005 errorCode
=U_ZERO_ERROR
;
3007 length
=u_shapeArabic(untouched_presentation_source
, LENGTHOF(untouched_presentation_source
),
3008 dest
, LENGTHOF(dest
),
3009 U_SHAPE_PRESERVE_PRESENTATION
|
3010 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
,
3013 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(untouched_presentation
) || memcmp(dest
, untouched_presentation
, length
*U_SIZEOF_UCHAR
)!=0) {
3014 log_err("failure in u_shapeArabic(untouched_presentation)\n");
3017 errorCode
=U_ZERO_ERROR
;
3019 length
=u_shapeArabic(untouched_presentation_r_source
, LENGTHOF(untouched_presentation_r_source
),
3020 dest
, LENGTHOF(dest
),
3021 U_SHAPE_PRESERVE_PRESENTATION
|
3022 U_SHAPE_LETTERS_SHAPE
|U_SHAPE_TEXT_DIRECTION_LOGICAL
,
3025 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(untouched_presentation_r
) || memcmp(dest
, untouched_presentation_r
, length
*U_SIZEOF_UCHAR
)!=0) {
3026 log_err("failure in u_shapeArabic(untouched_presentation_r)\n");
3031 doArabicShapingTestForBug8703(void) {
3034 0x0634,0x0651,0x0645,0x0652,0x0633
3035 }, letters_source2
[]={
3036 0x0634,0x0651,0x0645,0x0652,0x0633
3037 }, letters_source3
[]={
3038 0x0634,0x0651,0x0645,0x0652,0x0633
3039 }, letters_source4
[]={
3040 0x0634,0x0651,0x0645,0x0652,0x0633
3041 }, letters_source5
[]={
3042 0x0633,0x0652,0x0645,0x0651,0x0634
3043 }, letters_source6
[]={
3044 0x0633,0x0652,0x0645,0x0651,0x0634
3045 }, letters_source7
[]={
3046 0x0633,0x0652,0x0645,0x0651,0x0634
3047 }, letters_source8
[]={
3048 0x0633,0x0652,0x0645,0x0651,0x0634
3049 }, letters_dest1
[]={
3050 0x0020,0xFEB7,0xFE7D,0xFEE4,0xFEB2
3051 }, letters_dest2
[]={
3052 0xFEB7,0xFE7D,0xFEE4,0xFEB2,0x0020
3053 }, letters_dest3
[]={
3054 0xFEB7,0xFE7D,0xFEE4,0xFEB2
3055 }, letters_dest4
[]={
3056 0xFEB7,0xFE7D,0xFEE4,0x0640,0xFEB2
3057 }, letters_dest5
[]={
3058 0x0020,0xFEB2,0xFEE4,0xFE7D,0xFEB7
3059 }, letters_dest6
[]={
3060 0xFEB2,0xFEE4,0xFE7D,0xFEB7,0x0020
3061 }, letters_dest7
[]={
3062 0xFEB2,0xFEE4,0xFE7D,0xFEB7
3063 }, letters_dest8
[]={
3064 0xFEB2,0x0640,0xFEE4,0xFE7D,0xFEB7
3068 UErrorCode errorCode
;
3071 errorCode
=U_ZERO_ERROR
;
3073 length
=u_shapeArabic(letters_source1
, LENGTHOF(letters_source1
),
3074 dest
, LENGTHOF(dest
),
3075 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL
| U_SHAPE_TASHKEEL_BEGIN
| U_SHAPE_LETTERS_SHAPE
,
3078 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest1
) || memcmp(dest
, letters_dest1
, length
*U_SIZEOF_UCHAR
)!=0) {
3079 log_err("failure in u_shapeArabic(letters_source1)\n");
3082 errorCode
=U_ZERO_ERROR
;
3084 length
=u_shapeArabic(letters_source2
, LENGTHOF(letters_source2
),
3085 dest
, LENGTHOF(dest
),
3086 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL
| U_SHAPE_TASHKEEL_END
| U_SHAPE_LETTERS_SHAPE
,
3089 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest2
) || memcmp(dest
, letters_dest2
, length
*U_SIZEOF_UCHAR
)!=0) {
3090 log_err("failure in u_shapeArabic(letters_source2)\n");
3093 errorCode
=U_ZERO_ERROR
;
3095 length
=u_shapeArabic(letters_source3
, LENGTHOF(letters_source3
),
3096 dest
, LENGTHOF(dest
),
3097 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL
| U_SHAPE_TASHKEEL_RESIZE
| U_SHAPE_LETTERS_SHAPE
,
3100 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest3
) || memcmp(dest
, letters_dest3
, length
*U_SIZEOF_UCHAR
)!=0) {
3101 log_err("failure in u_shapeArabic(letters_source3)\n");
3104 errorCode
=U_ZERO_ERROR
;
3106 length
=u_shapeArabic(letters_source4
, LENGTHOF(letters_source4
),
3107 dest
, LENGTHOF(dest
),
3108 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL
| U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL
| U_SHAPE_LETTERS_SHAPE
,
3111 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest4
) || memcmp(dest
, letters_dest4
, length
*U_SIZEOF_UCHAR
)!=0) {
3112 log_err("failure in u_shapeArabic(letters_source4)\n");
3115 errorCode
=U_ZERO_ERROR
;
3117 length
=u_shapeArabic(letters_source5
, LENGTHOF(letters_source5
),
3118 dest
, LENGTHOF(dest
),
3119 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
| U_SHAPE_TASHKEEL_BEGIN
| U_SHAPE_LETTERS_SHAPE
,
3122 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest5
) || memcmp(dest
, letters_dest5
, length
*U_SIZEOF_UCHAR
)!=0) {
3123 log_err("failure in u_shapeArabic(letters_source5)\n");
3126 errorCode
=U_ZERO_ERROR
;
3128 length
=u_shapeArabic(letters_source6
, LENGTHOF(letters_source6
),
3129 dest
, LENGTHOF(dest
),
3130 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
| U_SHAPE_TASHKEEL_END
| U_SHAPE_LETTERS_SHAPE
,
3133 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest6
) || memcmp(dest
, letters_dest6
, length
*U_SIZEOF_UCHAR
)!=0) {
3134 log_err("failure in u_shapeArabic(letters_source6)\n");
3137 errorCode
=U_ZERO_ERROR
;
3139 length
=u_shapeArabic(letters_source7
, LENGTHOF(letters_source7
),
3140 dest
, LENGTHOF(dest
),
3141 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
| U_SHAPE_TASHKEEL_RESIZE
| U_SHAPE_LETTERS_SHAPE
,
3144 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest7
) || memcmp(dest
, letters_dest7
, length
*U_SIZEOF_UCHAR
)!=0) {
3145 log_err("failure in u_shapeArabic(letters_source7)\n");
3148 errorCode
=U_ZERO_ERROR
;
3150 length
=u_shapeArabic(letters_source8
, LENGTHOF(letters_source8
),
3151 dest
, LENGTHOF(dest
),
3152 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
| U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL
| U_SHAPE_LETTERS_SHAPE
,
3155 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest8
) || memcmp(dest
, letters_dest8
, length
*U_SIZEOF_UCHAR
)!=0) {
3156 log_err("failure in u_shapeArabic(letters_source8)\n");
3161 doArabicShapingTestForBug9024(void) {
3163 letters_source1
[]={ /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
3164 0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
3165 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
3166 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
3167 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
3168 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
3169 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
3170 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
3171 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
3172 }, letters_source2
[]={/* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
3173 0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
3174 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
3175 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
3176 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
3177 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
3178 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
3179 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
3180 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
3181 }, letters_source3
[]={/* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
3182 0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
3183 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
3184 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
3185 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
3186 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
3187 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
3188 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
3189 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
3190 }, letters_source4
[]={/* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
3191 0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
3192 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
3193 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
3194 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
3195 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
3196 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
3197 0xD83B, 0xDE39, 0xD83B, 0xDE3B
3198 }, letters_source5
[]={/* Arabic mathematical Symbols - Tailed Symbols */
3199 0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
3200 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
3201 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
3202 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
3203 }, letters_source6
[]={/* Arabic mathematical Symbols - Stretched Symbols with 06 range */
3204 0xD83B, 0xDE21, 0x0633, 0xD83B, 0xDE62, 0x0647
3205 }, letters_dest1
[]={
3206 0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
3207 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
3208 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
3209 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
3210 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
3211 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
3212 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
3213 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
3214 }, letters_dest2
[]={
3215 0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
3216 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
3217 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
3218 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
3219 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
3220 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
3221 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
3222 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
3223 }, letters_dest3
[]={
3224 0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
3225 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
3226 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
3227 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
3228 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
3229 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
3230 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
3231 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
3232 }, letters_dest4
[]={
3233 0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
3234 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
3235 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
3236 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
3237 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
3238 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
3239 0xD83B, 0xDE39, 0xD83B, 0xDE3B
3240 }, letters_dest5
[]={
3241 0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
3242 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
3243 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
3244 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
3245 }, letters_dest6
[]={
3246 0xD83B, 0xDE21, 0xFEB1, 0xD83B, 0xDE62, 0xFEE9
3250 UErrorCode errorCode
;
3253 errorCode
=U_ZERO_ERROR
;
3255 length
=u_shapeArabic(letters_source1
, LENGTHOF(letters_source1
),
3256 dest
, LENGTHOF(dest
),
3257 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL
| U_SHAPE_TASHKEEL_BEGIN
| U_SHAPE_LETTERS_SHAPE
,
3260 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest1
) || memcmp(dest
, letters_dest1
, length
*U_SIZEOF_UCHAR
)!=0) {
3261 log_err("failure in u_shapeArabic(letters_source1)\n");
3264 errorCode
=U_ZERO_ERROR
;
3266 length
=u_shapeArabic(letters_source2
, LENGTHOF(letters_source2
),
3267 dest
, LENGTHOF(dest
),
3268 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL
| U_SHAPE_TASHKEEL_END
| U_SHAPE_LETTERS_SHAPE
,
3271 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest2
) || memcmp(dest
, letters_dest2
, length
*U_SIZEOF_UCHAR
)!=0) {
3272 log_err("failure in u_shapeArabic(letters_source2)\n");
3275 errorCode
=U_ZERO_ERROR
;
3277 length
=u_shapeArabic(letters_source3
, LENGTHOF(letters_source3
),
3278 dest
, LENGTHOF(dest
),
3279 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL
| U_SHAPE_TASHKEEL_RESIZE
| U_SHAPE_LETTERS_SHAPE
,
3282 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest3
) || memcmp(dest
, letters_dest3
, length
*U_SIZEOF_UCHAR
)!=0) {
3283 log_err("failure in u_shapeArabic(letters_source3)\n");
3286 errorCode
=U_ZERO_ERROR
;
3288 length
=u_shapeArabic(letters_source4
, LENGTHOF(letters_source4
),
3289 dest
, LENGTHOF(dest
),
3290 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL
| U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL
| U_SHAPE_LETTERS_SHAPE
,
3293 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest4
) || memcmp(dest
, letters_dest4
, length
*U_SIZEOF_UCHAR
)!=0) {
3294 log_err("failure in u_shapeArabic(letters_source4)\n");
3297 errorCode
=U_ZERO_ERROR
;
3299 length
=u_shapeArabic(letters_source5
, LENGTHOF(letters_source5
),
3300 dest
, LENGTHOF(dest
),
3301 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
| U_SHAPE_TASHKEEL_BEGIN
| U_SHAPE_LETTERS_SHAPE
,
3304 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest5
) || memcmp(dest
, letters_dest5
, length
*U_SIZEOF_UCHAR
)!=0) {
3305 log_err("failure in u_shapeArabic(letters_source5)\n");
3308 errorCode
=U_ZERO_ERROR
;
3310 length
=u_shapeArabic(letters_source6
, LENGTHOF(letters_source6
),
3311 dest
, LENGTHOF(dest
),
3312 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
| U_SHAPE_TASHKEEL_END
| U_SHAPE_LETTERS_SHAPE
,
3315 if(U_FAILURE(errorCode
) || length
!=LENGTHOF(letters_dest6
) || memcmp(dest
, letters_dest6
, length
*U_SIZEOF_UCHAR
)!=0) {
3316 log_err("failure in u_shapeArabic(letters_source6)\n");
3321 static void _testPresentationForms(const UChar
* in
) {
3322 enum Forms
{ GENERIC
, ISOLATED
, FINAL
, INITIAL
, MEDIAL
};
3323 /* This character is used to check whether the in-character is rewritten correctly
3324 and whether the surrounding characters are shaped correctly as well. */
3325 UChar otherChar
[] = {0x0628, 0xfe8f, 0xfe90, 0xfe91, 0xfe92};
3328 UErrorCode errorCode
;
3331 /* Testing isolated shaping */
3332 src
[0] = in
[GENERIC
];
3333 errorCode
=U_ZERO_ERROR
;
3334 length
=u_shapeArabic(src
, 1,
3336 U_SHAPE_LETTERS_SHAPE
,
3338 if(U_FAILURE(errorCode
) || length
!=1 || dst
[0] != in
[ISOLATED
]) {
3339 log_err("failure in u_shapeArabic(_testAllForms: shaping isolated): %x\n", in
[GENERIC
]);
3341 errorCode
=U_ZERO_ERROR
;
3342 length
=u_shapeArabic(dst
, 1,
3344 U_SHAPE_LETTERS_UNSHAPE
,
3346 if(U_FAILURE(errorCode
) || length
!=1 || src
[0] != in
[GENERIC
]) {
3347 log_err("failure in u_shapeArabic(_testAllForms: unshaping isolated): %x\n", in
[GENERIC
]);
3350 /* Testing final shaping */
3351 src
[0] = otherChar
[GENERIC
];
3352 src
[1] = in
[GENERIC
];
3353 if (in
[FINAL
] != 0) {
3354 errorCode
=U_ZERO_ERROR
;
3355 length
=u_shapeArabic(src
, 2,
3357 U_SHAPE_LETTERS_SHAPE
,
3359 if(U_FAILURE(errorCode
) || length
!=2 || dst
[0] != otherChar
[INITIAL
] || dst
[1] != in
[FINAL
]) {
3360 log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in
[GENERIC
]);
3362 errorCode
=U_ZERO_ERROR
;
3363 length
=u_shapeArabic(dst
, 2,
3365 U_SHAPE_LETTERS_UNSHAPE
,
3367 if(U_FAILURE(errorCode
) || length
!=2 || src
[0] != otherChar
[GENERIC
] || src
[1] != in
[GENERIC
]) {
3368 log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in
[GENERIC
]);
3371 errorCode
=U_ZERO_ERROR
;
3372 length
=u_shapeArabic(src
, 2,
3374 U_SHAPE_LETTERS_SHAPE
,
3376 if(U_FAILURE(errorCode
) || length
!=2 || dst
[0] != otherChar
[ISOLATED
] || dst
[1] != in
[ISOLATED
]) {
3377 log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in
[GENERIC
]);
3379 errorCode
=U_ZERO_ERROR
;
3380 length
=u_shapeArabic(dst
, 2,
3382 U_SHAPE_LETTERS_UNSHAPE
,
3384 if(U_FAILURE(errorCode
) || length
!=2 || src
[0] != otherChar
[GENERIC
] || src
[1] != in
[GENERIC
]) {
3385 log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in
[GENERIC
]);
3389 /* Testing initial shaping */
3390 src
[0] = in
[GENERIC
];
3391 src
[1] = otherChar
[GENERIC
];
3392 if (in
[INITIAL
] != 0) {
3393 /* Testing characters that have an initial form */
3394 errorCode
=U_ZERO_ERROR
;
3395 length
=u_shapeArabic(src
, 2,
3397 U_SHAPE_LETTERS_SHAPE
,
3399 if(U_FAILURE(errorCode
) || length
!=2 || dst
[0] != in
[INITIAL
] || dst
[1] != otherChar
[FINAL
]) {
3400 log_err("failure in u_shapeArabic(_testAllForms: shaping initial): %x\n", in
[GENERIC
]);
3402 errorCode
=U_ZERO_ERROR
;
3403 length
=u_shapeArabic(dst
, 2,
3405 U_SHAPE_LETTERS_UNSHAPE
,
3407 if(U_FAILURE(errorCode
) || length
!=2 || src
[0] != in
[GENERIC
] || src
[1] != otherChar
[GENERIC
]) {
3408 log_err("failure in u_shapeArabic(_testAllForms: unshaping initial): %x\n", in
[GENERIC
]);
3411 /* Testing characters that do not have an initial form */
3412 errorCode
=U_ZERO_ERROR
;
3413 length
=u_shapeArabic(src
, 2,
3415 U_SHAPE_LETTERS_SHAPE
,
3417 if(U_FAILURE(errorCode
) || length
!=2 || dst
[0] != in
[ISOLATED
] || dst
[1] != otherChar
[ISOLATED
]) {
3418 log_err("failure in u_shapeArabic(_testTwoForms: shaping initial): %x\n", in
[GENERIC
]);
3420 errorCode
=U_ZERO_ERROR
;
3421 length
=u_shapeArabic(dst
, 2,
3423 U_SHAPE_LETTERS_UNSHAPE
,
3425 if(U_FAILURE(errorCode
) || length
!=2 || src
[0] != in
[GENERIC
] || src
[1] != otherChar
[GENERIC
]) {
3426 log_err("failure in u_shapeArabic(_testTwoForms: unshaping initial): %x\n", in
[GENERIC
]);
3430 /* Testing medial shaping */
3431 src
[0] = otherChar
[0];
3432 src
[1] = in
[GENERIC
];
3433 src
[2] = otherChar
[0];
3434 errorCode
=U_ZERO_ERROR
;
3435 if (in
[MEDIAL
] != 0) {
3436 /* Testing characters that have an medial form */
3437 length
=u_shapeArabic(src
, 3,
3439 U_SHAPE_LETTERS_SHAPE
,
3441 if(U_FAILURE(errorCode
) || length
!=3 || dst
[0] != otherChar
[INITIAL
] || dst
[1] != in
[MEDIAL
] || dst
[2] != otherChar
[FINAL
]) {
3442 log_err("failure in u_shapeArabic(_testAllForms: shaping medial): %x\n", in
[GENERIC
]);
3444 errorCode
=U_ZERO_ERROR
;
3445 length
=u_shapeArabic(dst
, 3,
3447 U_SHAPE_LETTERS_UNSHAPE
,
3449 if(U_FAILURE(errorCode
) || length
!=3 || src
[0] != otherChar
[GENERIC
] || src
[1] != in
[GENERIC
] || src
[2] != otherChar
[GENERIC
]) {
3450 log_err("failure in u_shapeArabic(_testAllForms: unshaping medial): %x\n", in
[GENERIC
]);
3453 /* Testing characters that do not have an medial form */
3454 errorCode
=U_ZERO_ERROR
;
3455 length
=u_shapeArabic(src
, 3,
3457 U_SHAPE_LETTERS_SHAPE
,
3459 if(U_FAILURE(errorCode
) || length
!=3 || dst
[0] != otherChar
[INITIAL
] || dst
[1] != in
[FINAL
] || dst
[2] != otherChar
[ISOLATED
]) {
3460 log_err("failure in u_shapeArabic(_testTwoForms: shaping medial): %x\n", in
[GENERIC
]);
3462 errorCode
=U_ZERO_ERROR
;
3463 length
=u_shapeArabic(dst
, 3,
3465 U_SHAPE_LETTERS_UNSHAPE
,
3467 if(U_FAILURE(errorCode
) || length
!=3 || src
[0] != otherChar
[GENERIC
] || src
[1] != in
[GENERIC
] || src
[2] != otherChar
[GENERIC
]) {
3468 log_err("failure in u_shapeArabic(_testTwoForms: unshaping medial): %x\n", in
[GENERIC
]);
3474 doArabicShapingTestForNewCharacters(void) {
3475 static const UChar letterForms
[][5]={
3476 { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69 }, /* TTEH */
3477 { 0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61 }, /* TTEHEH */
3478 { 0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55 }, /* BEEH */
3479 { 0x0688, 0xFB88, 0xFB89, 0, 0 }, /* DDAL */
3480 { 0x068C, 0xFB84, 0xFB85, 0, 0 }, /* DAHAL */
3481 { 0x068D, 0xFB82, 0xFB83, 0, 0 }, /* DDAHAL */
3482 { 0x068E, 0xFB86, 0xFB87, 0, 0 }, /* DUL */
3483 { 0x0691, 0xFB8C, 0xFB8D, 0, 0 }, /* RREH */
3484 { 0x06BA, 0xFB9E, 0xFB9F, 0, 0 }, /* NOON GHUNNA */
3485 { 0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3 }, /* RNOON */
3486 { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD }, /* HEH DOACHASHMEE */
3487 { 0x06C0, 0xFBA4, 0xFBA5, 0, 0 }, /* HEH WITH YEH ABOVE */
3488 { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9 }, /* HEH GOAL */
3489 { 0x06C5, 0xFBE0, 0xFBE1, 0, 0 }, /* KIRGIHIZ OE */
3490 { 0x06C6, 0xFBD9, 0xFBDA, 0, 0 }, /* OE */
3491 { 0x06C7, 0xFBD7, 0xFBD8, 0, 0 }, /* U */
3492 { 0x06C8, 0xFBDB, 0xFBDC, 0, 0 }, /* YU */
3493 { 0x06C9, 0xFBE2, 0xFBE3, 0, 0 }, /* KIRGIZ YU */
3494 { 0x06CB, 0xFBDE, 0xFBDF, 0, 0}, /* VE */
3495 { 0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7 }, /* E */
3496 { 0x06D2, 0xFBAE, 0xFBAF, 0, 0 }, /* YEH BARREE */
3497 { 0x06D3, 0xFBB0, 0xFBB1, 0, 0 }, /* YEH BARREE WITH HAMZA ABOVE */
3498 { 0x0622, 0xFE81, 0xFE82, 0, 0, }, /* ALEF WITH MADDA ABOVE */
3499 { 0x0623, 0xFE83, 0xFE84, 0, 0, }, /* ALEF WITH HAMZA ABOVE */
3500 { 0x0624, 0xFE85, 0xFE86, 0, 0, }, /* WAW WITH HAMZA ABOVE */
3501 { 0x0625, 0xFE87, 0xFE88, 0, 0, }, /* ALEF WITH HAMZA BELOW */
3502 { 0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, }, /* YEH WITH HAMZA ABOVE */
3503 { 0x0627, 0xFE8D, 0xFE8E, 0, 0, }, /* ALEF */
3504 { 0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, }, /* BEH */
3505 { 0x0629, 0xFE93, 0xFE94, 0, 0, }, /* TEH MARBUTA */
3506 { 0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98, }, /* TEH */
3507 { 0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, }, /* THEH */
3508 { 0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0, }, /* JEEM */
3509 { 0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, }, /* HAH */
3510 { 0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8, }, /* KHAH */
3511 { 0x062F, 0xFEA9, 0xFEAA, 0, 0, }, /* DAL */
3512 { 0x0630, 0xFEAB, 0xFEAC, 0, 0, }, /* THAL */
3513 { 0x0631, 0xFEAD, 0xFEAE, 0, 0, }, /* REH */
3514 { 0x0632, 0xFEAF, 0xFEB0, 0, 0, }, /* ZAIN */
3515 { 0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, }, /* SEEN */
3516 { 0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, }, /* SHEEN */
3517 { 0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, }, /* SAD */
3518 { 0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, }, /* DAD */
3519 { 0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, }, /* TAH */
3520 { 0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, }, /* ZAH */
3521 { 0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, }, /* AIN */
3522 { 0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0, }, /* GHAIN */
3523 { 0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4, }, /* FEH */
3524 { 0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8, }, /* QAF */
3525 { 0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, }, /* KAF */
3526 { 0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0, }, /* LAM */
3527 { 0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, }, /* MEEM */
3528 { 0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8, }, /* NOON */
3529 { 0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, }, /* HEH */
3530 { 0x0648, 0xFEED, 0xFEEE, 0, 0, }, /* WAW */
3531 { 0x0649, 0xFEEF, 0xFEF0, 0, 0, }, /* ALEF MAKSURA */
3532 { 0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, }, /* YEH */
3533 { 0x064E, 0xFE76, 0, 0, 0xFE77, }, /* FATHA */
3534 { 0x064F, 0xFE78, 0, 0, 0xFE79, }, /* DAMMA */
3535 { 0x0650, 0xFE7A, 0, 0, 0xFE7B, }, /* KASRA */
3536 { 0x0651, 0xFE7C, 0, 0, 0xFE7D, }, /* SHADDA */
3537 { 0x0652, 0xFE7E, 0, 0, 0xFE7F, }, /* SUKUN */
3538 { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69, }, /* TTEH */
3539 { 0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59, }, /* PEH */
3540 { 0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, }, /* TCHEH */
3541 { 0x0688, 0xFB88, 0xFB89, 0, 0, }, /* DDAL */
3542 { 0x0691, 0xFB8C, 0xFB8D, 0, 0, }, /* RREH */
3543 { 0x0698, 0xFB8A, 0xFB8B, 0, 0, }, /* JEH */
3544 { 0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, }, /* KEHEH */
3545 { 0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95, }, /* GAF */
3546 { 0x06BA, 0xFB9E, 0xFB9F, 0, 0, }, /* NOON GHUNNA */
3547 { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, }, /* HEH DOACHASHMEE */
3548 { 0x06C0, 0xFBA4, 0xFBA5, 0, 0, }, /* HEH WITH YEH ABOVE */
3549 { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, }, /* HEH GOAL */
3550 { 0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, }, /* FARSI YEH */
3551 { 0x06D2, 0xFBAE, 0xFBAF, 0, 0, }, /* YEH BARREE */
3552 { 0x06D3, 0xFBB0, 0xFBB1, 0, 0, }}; /* YEH BARREE WITH HAMZA ABOVE */
3554 for (i
= 0; i
< LENGTHOF(letterForms
); ++i
) {
3555 _testPresentationForms(letterForms
[i
]);
3559 /* helpers ------------------------------------------------------------------ */
3561 static void initCharFromDirProps(void) {
3562 static const UVersionInfo ucd401
={ 4, 0, 1, 0 };
3563 static UVersionInfo ucdVersion
={ 0, 0, 0, 0 };
3565 /* lazy initialization */
3566 if(ucdVersion
[0]>0) {
3570 u_getUnicodeVersion(ucdVersion
);
3571 if(memcmp(ucdVersion
, ucd401
, sizeof(UVersionInfo
))>=0) {
3572 /* Unicode 4.0.1 changes bidi classes for +-/ */
3573 charFromDirProp
[U_EUROPEAN_NUMBER_SEPARATOR
]=0x2b; /* change ES character from / to + */
3577 /* return a string with characters according to the desired directional properties */
3579 getStringFromDirProps(const uint8_t *dirProps
, int32_t length
, UChar
*buffer
) {
3582 initCharFromDirProps();
3584 /* this part would have to be modified for UTF-x */
3585 for(i
=0; i
<length
; ++i
) {
3586 buffer
[i
]=charFromDirProp
[dirProps
[i
]];
3592 static void printUnicode(const UChar
*s
, int32_t length
, const UBiDiLevel
*levels
) {
3596 for(i
=0; i
<length
; ++i
) {
3598 log_verbose("%4x.%u ", s
[i
], levels
[i
]);
3600 log_verbose("%4x ", s
[i
]);
3608 /* Reordering Mode BiDi --------------------------------------------------------- */
3610 static const UBiDiLevel paraLevels
[] = { UBIDI_LTR
, UBIDI_RTL
};
3613 assertSuccessful(const char* message
, UErrorCode
* rc
) {
3614 if (rc
!= NULL
&& U_FAILURE(*rc
)) {
3615 log_err("%s() failed with error %s.\n", message
, myErrorName(*rc
));
3622 assertStringsEqual(const char* expected
, const char* actual
, const char* src
,
3623 const char* mode
, const char* option
, UBiDi
* pBiDi
) {
3624 if (uprv_strcmp(expected
, actual
)) {
3625 char formatChars
[MAXLEN
];
3626 log_err("\nActual and expected output mismatch.\n"
3627 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n",
3629 "Actual output:", actual
,
3630 "Expected output:", expected
,
3631 "Levels:", formatLevels(pBiDi
, formatChars
),
3632 "Reordering mode:", ubidi_getReorderingMode(pBiDi
), mode
,
3633 "Paragraph level:", ubidi_getParaLevel(pBiDi
),
3634 "Reordering option:", ubidi_getReorderingOptions(pBiDi
), option
);
3641 getBiDiObject(void) {
3642 UBiDi
* pBiDi
= ubidi_open();
3643 if (pBiDi
== NULL
) {
3644 log_err("Unable to allocate a UBiDi object. Tests are skipped.\n");
3649 #define MAKE_ITEMS(val) val, #val
3651 static const struct {
3652 UBiDiReorderingMode value
;
3653 const char* description
;
3656 { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R
) },
3657 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT
) },
3658 { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL
) },
3659 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL
) },
3660 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L
) }
3662 static const struct {
3664 const char* description
;
3667 { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS
) },
3671 #define TC_COUNT LENGTHOF(textIn)
3672 #define MODES_COUNT LENGTHOF(modes)
3673 #define OPTIONS_COUNT LENGTHOF(options)
3674 #define LEVELS_COUNT LENGTHOF(paraLevels)
3676 static const char* const textIn
[] = {
3685 /* (4) JIH1.2,3MLK */
3689 /* (6) JIH.>12->a */
3691 /* (7) CBA.>67->89=a */
3693 /* (8) CBA.123->xyz */
3697 /* (10) a.>67->xyz */
3705 static const char* const textOut
[] = {
3708 /* TC 1: .123->4.5 */
3709 ".123->4.5", /* (1) */
3710 "4.5<-123.", /* (2) */
3713 /* TC 3: .678->8.9 */
3714 ".8.9<-678", /* (4) */
3715 "8.9<-678.", /* (5) */
3716 ".678->8.9", /* (6) */
3717 /* TC 4: MLK1.2,3JIH */
3718 "KLM1.2,3HIJ", /* (7) */
3719 /* TC 5: FE.>12-> */
3720 "12<.EF->", /* (8) */
3721 "<-12<.EF", /* (9) */
3722 "EF.>@12->", /* (10) */
3723 /* TC 6: JIH.>12->a */
3724 "12<.HIJ->a", /* (11) */
3725 "a<-12<.HIJ", /* (12) */
3726 "HIJ.>@12->a", /* (13) */
3727 "a&<-12<.HIJ", /* (14) */
3728 /* TC 7: CBA.>67->89=a */
3729 "ABC.>@67->89=a", /* (15) */
3730 "a=89<-67<.ABC", /* (16) */
3731 "a&=89<-67<.ABC", /* (17) */
3732 "89<-67<.ABC=a", /* (18) */
3733 /* TC 8: CBA.123->xyz */
3734 "123.ABC->xyz", /* (19) */
3735 "xyz<-123.ABC", /* (20) */
3736 "ABC.@123->xyz", /* (21) */
3737 "xyz&<-123.ABC", /* (22) */
3738 /* TC 9: .>12->xyz */
3739 ".>12->xyz", /* (23) */
3740 "xyz<-12<.", /* (24) */
3741 "xyz&<-12<.", /* (25) */
3742 /* TC 10: a.>67->xyz */
3743 "a.>67->xyz", /* (26) */
3744 "a.>@67@->xyz", /* (27) */
3745 "xyz<-67<.a", /* (28) */
3747 "123HIJ", /* (29) */
3748 "HIJ123", /* (30) */
3749 /* TC 12: 123 JIH */
3750 "123 HIJ", /* (31) */
3751 "HIJ 123", /* (32) */
3754 #define NO UBIDI_MAP_NOWHERE
3755 #define MAX_MAP_LENGTH 20
3757 static const int32_t forwardMap
[][MAX_MAP_LENGTH
] = {
3759 { 0, 1, 2 }, /* (0) */
3760 /* TC 1: .123->4.5 */
3761 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */
3762 { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (2) */
3764 { 0, 1, 2 }, /* (3) */
3765 /* TC 3: .678->8.9 */
3766 { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */
3767 { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (5) */
3768 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */
3769 /* TC 4: MLK1.2,3JIH */
3770 { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */
3771 /* TC 5: FE.>12-> */
3772 { 5, 4, 3, 2, 0, 1, 6, 7 }, /* (8) */
3773 { 7, 6, 5, 4, 2, 3, 1, 0 }, /* (9) */
3774 { 1, 0, 2, 3, 5, 6, 7, 8 }, /* (10) */
3775 /* TC 6: JIH.>12->a */
3776 { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 }, /* (11) */
3777 { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 }, /* (12) */
3778 { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 }, /* (13) */
3779 { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 }, /* (14) */
3780 /* TC 7: CBA.>67->89=a */
3781 { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 }, /* (15) */
3782 { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 }, /* (16) */
3783 { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 }, /* (17) */
3784 { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 }, /* (18) */
3785 /* TC 8: CBA.123->xyz */
3786 { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 }, /* (19) */
3787 { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (20) */
3788 { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (21) */
3789 { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 }, /* (22) */
3790 /* TC 9: .>12->xyz */
3791 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */
3792 { 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (24) */
3793 { 9, 8, 6, 7, 5, 4, 0, 1, 2 }, /* (25) */
3794 /* TC 10: a.>67->xyz */
3795 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */
3796 { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 }, /* (27) */
3797 { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (28) */
3799 { 0, 1, 2, 5, 4, 3 }, /* (29) */
3800 { 3, 4, 5, 2, 1, 0 }, /* (30) */
3801 /* TC 12: 123 JIH */
3802 { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */
3803 { 4, 5, 6, 3, 2, 1, 0 }, /* (32) */
3806 static const int32_t inverseMap
[][MAX_MAP_LENGTH
] = {
3808 { 0, 1, 2 }, /* (0) */
3809 /* TC 1: .123->4.5 */
3810 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */
3811 { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (2) */
3813 { 0, 1, 2 }, /* (3) */
3814 /* TC 3: .678->8.9 */
3815 { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */
3816 { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (5) */
3817 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */
3818 /* TC 4: MLK1.2,3JIH */
3819 { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */
3820 /* TC 5: FE.>12-> */
3821 { 4, 5, 3, 2, 1, 0, 6, 7 }, /* (8) */
3822 { 7, 6, 4, 5, 3, 2, 1, 0 }, /* (9) */
3823 { 1, 0, 2, 3, NO
, 4, 5, 6, 7 }, /* (10) */
3824 /* TC 6: JIH.>12->a */
3825 { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 }, /* (11) */
3826 { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (12) */
3827 { 2, 1, 0, 3, 4, NO
, 5, 6, 7, 8, 9 }, /* (13) */
3828 { 9, NO
, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (14) */
3829 /* TC 7: CBA.>67->89=a */
3830 { 2, 1, 0, 3, 4, NO
, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (15) */
3831 { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (16) */
3832 { 12, NO
, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (17) */
3833 { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 }, /* (18) */
3834 /* TC 8: CBA.123->xyz */
3835 { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 }, /* (19) */
3836 { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (20) */
3837 { 2, 1, 0, 3, NO
, 4, 5, 6, 7, 8, 9, 10, 11 }, /* (21) */
3838 { 9, 10, 11, NO
, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (22) */
3839 /* TC 9: .>12->xyz */
3840 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */
3841 { 6, 7, 8, 5, 4, 2, 3, 1, 0 }, /* (24) */
3842 { 6, 7, 8, NO
, 5, 4, 2, 3, 1, 0 }, /* (25) */
3843 /* TC 10: a.>67->xyz */
3844 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */
3845 { 0, 1, 2, NO
, 3, 4, NO
, 5, 6, 7, 8, 9 }, /* (27) */
3846 { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 }, /* (28) */
3848 { 0, 1, 2, 5, 4, 3 }, /* (29) */
3849 { 5, 4, 3, 0, 1, 2 }, /* (30) */
3850 /* TC 12: 123 JIH */
3851 { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */
3852 { 6, 5, 4, 3, 0, 1, 2 }, /* (32) */
3855 static const char outIndices
[TC_COUNT
][MODES_COUNT
- 1][OPTIONS_COUNT
]
3858 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3859 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3860 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3861 {{ 0, 0}, { 0, 0}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3863 { /* TC 1: .123->4.5 */
3864 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3865 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3866 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3867 {{ 1, 2}, { 1, 2}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3870 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3871 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3872 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3873 {{ 3, 3}, { 3, 3}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3875 { /* TC 3: .678->8.9 */
3876 {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3877 {{ 4, 5}, { 4, 5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3878 {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3879 {{ 6, 5}, { 6, 5}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3881 { /* TC 4: MLK1.2,3JIH */
3882 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3883 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3884 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3885 {{ 7, 7}, { 7, 7}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3887 { /* TC 5: FE.>12-> */
3888 {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3889 {{10, 9}, { 8, 9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3890 {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3891 {{10, 9}, { 8, 9}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3893 { /* TC 6: JIH.>12->a */
3894 {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3895 {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3896 {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3897 {{13, 14}, {11, 12}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3899 { /* TC 7: CBA.>67->89=a */
3900 {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3901 {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3902 {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3903 {{15, 17}, {18, 16}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3905 { /* TC 8: CBA.>124->xyz */
3906 {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3907 {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3908 {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3909 {{21, 22}, {19, 20}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3911 { /* TC 9: .>12->xyz */
3912 {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3913 {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3914 {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3915 {{23, 25}, {23, 24}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3917 { /* TC 10: a.>67->xyz */
3918 {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3919 {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3920 {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3921 {{26, 27}, {26, 28}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3923 { /* TC 11: 124JIH */
3924 {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3925 {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3926 {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3927 {{30, 30}, {30, 30}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3929 { /* TC 12: 124 JIH */
3930 {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3931 {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3932 {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3933 {{31, 32}, {31, 32}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3938 assertRoundTrip(UBiDi
*pBiDi
, int32_t tc
, int32_t outIndex
, const char *srcChars
,
3939 const char *destChars
, const UChar
*dest
, int32_t destLen
,
3940 int mode
, int option
, UBiDiLevel level
) {
3942 static const char roundtrip
[TC_COUNT
][MODES_COUNT
][OPTIONS_COUNT
]
3945 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3946 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3947 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3948 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3949 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3951 { /* TC 1: .123->4.5 */
3952 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3953 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3954 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3955 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3956 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3959 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3960 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3961 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3962 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3963 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3965 { /* TC 3: .678->8.9 */
3966 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3967 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3968 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3969 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3970 {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3972 { /* TC 4: MLK1.2,3JIH */
3973 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3974 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3975 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3976 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3977 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3979 { /* TC 5: FE.>12-> */
3980 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3981 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3982 {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3983 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3984 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3986 { /* TC 6: JIH.>12->a */
3987 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3988 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3989 {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3990 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3991 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3993 { /* TC 7: CBA.>67->89=a */
3994 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3995 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3996 {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3997 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3998 {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4000 { /* TC 8: CBA.>123->xyz */
4001 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4002 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4003 {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4004 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4005 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4007 { /* TC 9: .>12->xyz */
4008 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4009 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4010 {{ 1, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4011 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4012 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4014 { /* TC 10: a.>67->xyz */
4015 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4016 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4017 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4018 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4019 {{ 1, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4021 { /* TC 11: 123JIH */
4022 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4023 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4024 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4025 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4026 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4028 { /* TC 12: 123 JIH */
4029 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4030 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4031 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4032 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4033 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4037 #define SET_ROUND_TRIP_MODE(mode) \
4038 ubidi_setReorderingMode(pBiDi, mode); \
4042 UErrorCode rc
= U_ZERO_ERROR
;
4043 UChar dest2
[MAXLEN
];
4046 char destChars2
[MAXLEN
];
4047 char destChars3
[MAXLEN
];
4049 switch (modes
[mode
].value
) {
4050 case UBIDI_REORDER_NUMBERS_SPECIAL
:
4051 SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL
)
4052 case UBIDI_REORDER_GROUP_NUMBERS_WITH_R
:
4053 SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R
)
4054 case UBIDI_REORDER_RUNS_ONLY
:
4055 SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY
)
4056 case UBIDI_REORDER_INVERSE_NUMBERS_AS_L
:
4057 SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT
)
4058 case UBIDI_REORDER_INVERSE_LIKE_DIRECT
:
4059 SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT
)
4060 case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL
:
4061 SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL
)
4063 SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT
)
4065 ubidi_setReorderingOptions(pBiDi
, UBIDI_OPTION_REMOVE_CONTROLS
);
4067 ubidi_setPara(pBiDi
, dest
, destLen
, level
, NULL
, &rc
);
4068 assertSuccessful("ubidi_setPara", &rc
);
4070 destLen2
= ubidi_writeReordered(pBiDi
, dest2
, MAXLEN
, UBIDI_DO_MIRRORING
,
4072 assertSuccessful("ubidi_writeReordered", &rc
);
4074 u16ToPseudo(destLen
, dest
, destChars3
);
4075 u16ToPseudo(destLen2
, dest2
, destChars2
);
4076 checkWhatYouCan(pBiDi
, destChars3
, destChars2
);
4077 if (strcmp(srcChars
, destChars2
)) {
4078 if (roundtrip
[tc
][mode
][option
][level
]) {
4079 log_err("\nRound trip failed for case=%d mode=%d option=%d.\n"
4080 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
4081 "\n%20s %u\n", tc
, mode
, option
,
4082 "Original text:", srcChars
,
4083 "Round-tripped text:", destChars2
,
4084 "Intermediate text:", destChars3
,
4085 "Reordering mode:", modes
[mode
].description
,
4086 "Reordering option:", options
[option
].description
,
4087 "Paragraph level:", level
);
4090 log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n"
4091 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
4092 "\n%20s %u\n", tc
, mode
, option
,
4093 "Original text:", srcChars
,
4094 "Round-tripped text:", destChars2
,
4095 "Intermediate text:", destChars3
,
4096 "Reordering mode:", modes
[mode
].description
,
4097 "Reordering option:", options
[option
].description
,
4098 "Paragraph level:", level
);
4102 if (!checkResultLength(pBiDi
, destChars
, destChars2
, destLen2
,
4103 desc
, "UBIDI_OPTION_REMOVE_CONTROLS", level
)) {
4106 if (outIndex
> -1 && !checkMaps(pBiDi
, outIndex
, srcChars
, destChars
,
4107 desc
, "UBIDI_OPTION_REMOVE_CONTROLS",
4115 checkResultLength(UBiDi
*pBiDi
, const char *srcChars
, const char *destChars
,
4116 int32_t destLen
, const char* mode
,
4117 const char* option
, UBiDiLevel level
) {
4119 if (strcmp(mode
, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0)
4120 actualLen
= strlen(destChars
);
4122 actualLen
= ubidi_getResultLength(pBiDi
);
4123 if (actualLen
!= destLen
) {
4124 log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n"
4125 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n",
4126 "Expected:", destLen
, "Actual:", actualLen
,
4127 "Input:", srcChars
, "Output:", destChars
,
4128 "Reordering mode:", mode
, "Reordering option:", option
,
4129 "Paragraph level:", level
);
4136 testReorderRunsOnly(void) {
4137 static const struct {
4139 const char* textOut
[2][2];
4140 const char noroundtrip
[2];
4142 {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*0*/
4143 {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
4144 {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}}, /*1*/
4145 {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}}, /*2*/
4146 {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"}, /*3*/
4147 {"* /%$123=-", "* /%$123=-"}}, {0, 0}},
4148 {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"}, /*4*/
4149 {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}},
4150 {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"}, /*5*/
4151 {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}},
4152 {"123->abc", {{"abc<-123", "abc<-123"}, /*6*/
4153 {"abc&<-123", "abc<-123"}}, {1, 0}},
4154 {"123->JKL", {{"JKL<-123", "123->JKL"}, /*7*/
4155 {"JKL<-123", "JKL<-@123"}}, {0, 1}},
4156 {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"}, /*8*/
4157 {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}},
4158 {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"}, /*9*/
4159 {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}},
4160 {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"}, /*10*/
4161 {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}},
4162 {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"}, /*11*/
4163 {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}},
4164 {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"}, /*12*/
4165 {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}},
4166 {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"}, /*13*/
4167 {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}},
4168 {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"}, /*14*/
4169 {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}},
4170 {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*15*/
4171 {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
4172 {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}, /*16*/
4173 {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}},
4174 {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"}, /*17*/
4175 {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}},
4176 {"123", {{"123", "123"}, /* just one run */ /*18*/
4177 {"123", "123"}}, {0, 0}}
4179 UBiDi
*pBiDi
= getBiDiObject();
4180 UBiDi
*pL2VBiDi
= getBiDiObject();
4181 UChar src
[MAXLEN
], dest
[MAXLEN
], visual1
[MAXLEN
], visual2
[MAXLEN
];
4182 char destChars
[MAXLEN
], vis1Chars
[MAXLEN
], vis2Chars
[MAXLEN
];
4183 int32_t srcLen
, destLen
, vis1Len
, vis2Len
, option
, i
, j
, nCases
, paras
;
4184 UErrorCode rc
= U_ZERO_ERROR
;
4187 log_verbose("\nEntering TestReorderRunsOnly\n\n");
4190 ubidi_close(pBiDi
); /* in case this one was allocated */
4193 ubidi_setReorderingMode(pBiDi
, UBIDI_REORDER_RUNS_ONLY
);
4194 ubidi_setReorderingOptions(pL2VBiDi
, UBIDI_OPTION_REMOVE_CONTROLS
);
4196 for (option
= 0; option
< 2; option
++) {
4197 ubidi_setReorderingOptions(pBiDi
, option
==0 ? UBIDI_OPTION_REMOVE_CONTROLS
4198 : UBIDI_OPTION_INSERT_MARKS
);
4199 for (i
= 0, nCases
= LENGTHOF(testCases
); i
< nCases
; i
++) {
4200 srcLen
= strlen(testCases
[i
].textIn
);
4201 pseudoToU16(srcLen
, testCases
[i
].textIn
, src
);
4202 for(j
= 0; j
< 2; j
++) {
4203 log_verbose("Now doing test for option %d, case %d, level %d\n",
4205 level
= paraLevels
[j
];
4206 ubidi_setPara(pBiDi
, src
, srcLen
, level
, NULL
, &rc
);
4207 assertSuccessful("ubidi_setPara", &rc
);
4209 destLen
= ubidi_writeReordered(pBiDi
, dest
, MAXLEN
, UBIDI_DO_MIRRORING
, &rc
);
4210 assertSuccessful("ubidi_writeReordered", &rc
);
4211 u16ToPseudo(destLen
, dest
, destChars
);
4212 checkWhatYouCan(pBiDi
, testCases
[i
].textIn
, destChars
);
4213 assertStringsEqual(testCases
[i
].textOut
[option
][level
], destChars
,
4214 testCases
[i
].textIn
, "UBIDI_REORDER_RUNS_ONLY",
4215 option
==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
4218 if((option
==0) && testCases
[i
].noroundtrip
[level
]) {
4221 ubidi_setPara(pL2VBiDi
, src
, srcLen
, level
, NULL
, &rc
);
4222 assertSuccessful("ubidi_setPara1", &rc
);
4224 vis1Len
= ubidi_writeReordered(pL2VBiDi
, visual1
, MAXLEN
, UBIDI_DO_MIRRORING
, &rc
);
4225 assertSuccessful("ubidi_writeReordered1", &rc
);
4226 u16ToPseudo(vis1Len
, visual1
, vis1Chars
);
4227 checkWhatYouCan(pL2VBiDi
, testCases
[i
].textIn
, vis1Chars
);
4228 ubidi_setPara(pL2VBiDi
, dest
, destLen
, level
^1, NULL
, &rc
);
4229 assertSuccessful("ubidi_setPara2", &rc
);
4231 vis2Len
= ubidi_writeReordered(pL2VBiDi
, visual2
, MAXLEN
, UBIDI_DO_MIRRORING
, &rc
);
4232 assertSuccessful("ubidi_writeReordered2", &rc
);
4233 u16ToPseudo(vis2Len
, visual2
, vis2Chars
);
4234 checkWhatYouCan(pL2VBiDi
, destChars
, vis2Chars
);
4235 assertStringsEqual(vis1Chars
, vis2Chars
,
4236 testCases
[i
].textIn
, "UBIDI_REORDER_RUNS_ONLY (2)",
4237 option
==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
4243 /* test with null or empty text */
4244 ubidi_setPara(pBiDi
, src
, 0, UBIDI_LTR
, NULL
, &rc
);
4245 assertSuccessful("ubidi_setPara3", &rc
);
4246 paras
= ubidi_countParagraphs(pBiDi
);
4248 log_err("\nInvalid number of paras (should be 0): %d\n", paras
);
4252 ubidi_close(pL2VBiDi
);
4254 log_verbose("\nExiting TestReorderRunsOnly\n\n");
4258 testReorderingMode(void) {
4260 UChar src
[MAXLEN
], dest
[MAXLEN
];
4261 char destChars
[MAXLEN
];
4262 UBiDi
*pBiDi
= NULL
, *pBiDi2
= NULL
, *pBiDi3
= NULL
;
4264 int tc
, mode
, option
, level
;
4265 uint32_t optionValue
, optionBack
;
4266 UBiDiReorderingMode modeValue
, modeBack
;
4267 int32_t srcLen
, destLen
, idx
;
4268 const char *expectedChars
;
4269 UBool testOK
= TRUE
;
4271 log_verbose("\nEntering TestReorderingMode\n\n");
4273 pBiDi
= getBiDiObject();
4274 pBiDi2
= getBiDiObject();
4275 pBiDi3
= getBiDiObject();
4277 ubidi_close(pBiDi
); /* in case this one was allocated */
4278 ubidi_close(pBiDi2
); /* in case this one was allocated */
4282 ubidi_setInverse(pBiDi2
, TRUE
);
4284 for (tc
= 0; tc
< TC_COUNT
; tc
++) {
4285 const char *srcChars
= textIn
[tc
];
4286 srcLen
= strlen(srcChars
);
4287 pseudoToU16(srcLen
, srcChars
, src
);
4289 for (mode
= 0; mode
< MODES_COUNT
; mode
++) {
4290 modeValue
= modes
[mode
].value
;
4291 ubidi_setReorderingMode(pBiDi
, modeValue
);
4292 modeBack
= ubidi_getReorderingMode(pBiDi
);
4293 if (modeValue
!= modeBack
) {
4294 log_err("Error while setting reordering mode to %d, returned %d\n",
4295 modeValue
, modeBack
);
4298 for (option
= 0; option
< OPTIONS_COUNT
; option
++) {
4299 optionValue
= options
[option
].value
;
4300 ubidi_setReorderingOptions(pBiDi
, optionValue
);
4301 optionBack
= ubidi_getReorderingOptions(pBiDi
);
4302 if (optionValue
!= optionBack
) {
4303 log_err("Error while setting reordering option to %d, returned %d\n",
4304 optionValue
, optionBack
);
4307 for (level
= 0; level
< LEVELS_COUNT
; level
++) {
4308 log_verbose("starting test %d mode=%d option=%d level=%d\n",
4309 tc
, modes
[mode
].value
, options
[option
].value
, level
);
4311 ubidi_setPara(pBiDi
, src
, srcLen
, paraLevels
[level
], NULL
, &rc
);
4312 assertSuccessful("ubidi_setPara", &rc
);
4315 destLen
= ubidi_writeReordered(pBiDi
, dest
, MAXLEN
,
4316 UBIDI_DO_MIRRORING
, &rc
);
4317 assertSuccessful("ubidi_writeReordered", &rc
);
4318 u16ToPseudo(destLen
, dest
, destChars
);
4319 if (!((modes
[mode
].value
== UBIDI_REORDER_INVERSE_NUMBERS_AS_L
) &&
4320 (options
[option
].value
== UBIDI_OPTION_INSERT_MARKS
))) {
4321 checkWhatYouCan(pBiDi
, srcChars
, destChars
);
4324 if (modes
[mode
].value
== UBIDI_REORDER_INVERSE_NUMBERS_AS_L
) {
4326 expectedChars
= inverseBasic(pBiDi2
, srcChars
, srcLen
,
4327 options
[option
].value
, paraLevels
[level
], destChars
);
4330 idx
= outIndices
[tc
][mode
][option
][level
];
4331 expectedChars
= textOut
[idx
];
4333 if (!assertStringsEqual(expectedChars
, destChars
, srcChars
,
4334 modes
[mode
].description
,
4335 options
[option
].description
,
4339 if (options
[option
].value
== UBIDI_OPTION_INSERT_MARKS
&&
4340 !assertRoundTrip(pBiDi3
, tc
, idx
, srcChars
,
4341 destChars
, dest
, destLen
,
4342 mode
, option
, paraLevels
[level
])) {
4345 else if (!checkResultLength(pBiDi
, srcChars
, destChars
,
4346 destLen
, modes
[mode
].description
,
4347 options
[option
].description
,
4348 paraLevels
[level
])) {
4351 else if (idx
> -1 && !checkMaps(pBiDi
, idx
, srcChars
,
4352 destChars
, modes
[mode
].description
,
4353 options
[option
].description
, paraLevels
[level
],
4361 if (testOK
== TRUE
) {
4362 log_verbose("\nReordering mode test OK\n");
4364 ubidi_close(pBiDi3
);
4365 ubidi_close(pBiDi2
);
4368 log_verbose("\nExiting TestReorderingMode\n\n");
4371 static const char* inverseBasic(UBiDi
*pBiDi
, const char *srcChars
, int32_t srcLen
,
4372 uint32_t option
, UBiDiLevel level
, char *result
) {
4373 UErrorCode rc
= U_ZERO_ERROR
;
4375 UChar src
[MAXLEN
], dest2
[MAXLEN
];
4377 if (pBiDi
== NULL
|| src
== NULL
) {
4380 ubidi_setReorderingOptions(pBiDi
, option
);
4381 pseudoToU16(srcLen
, srcChars
, src
);
4382 ubidi_setPara(pBiDi
, src
, srcLen
, level
, NULL
, &rc
);
4383 assertSuccessful("ubidi_setPara", &rc
);
4386 destLen
= ubidi_writeReordered(pBiDi
, dest2
, MAXLEN
,
4387 UBIDI_DO_MIRRORING
, &rc
);
4388 assertSuccessful("ubidi_writeReordered", &rc
);
4389 u16ToPseudo(destLen
, dest2
, result
);
4390 if (!(option
== UBIDI_OPTION_INSERT_MARKS
)) {
4391 checkWhatYouCan(pBiDi
, srcChars
, result
);
4396 #define NULL_CHAR '\0'
4399 testStreaming(void) {
4400 #define MAXPORTIONS 10
4402 static const struct {
4405 short int nPortions
[2];
4406 char portionLens
[2][MAXPORTIONS
];
4407 const char* message
[2];
4415 6, { 6, 6 }, {{ 4, 6, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }},
4416 {"4, 6, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"}
4418 { "abcd\\u000Afgh\\u000D12345\\u000A456",
4419 6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
4420 {"5, 4, 6, 3", "5, 4, 6, 3"}
4422 { "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D",
4423 6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
4424 {"5, 4, 6, 3", "5, 4, 6, 3"}
4426 { "abcde\\u000Afghi",
4427 10, { 2, 2 }, {{ 6, 4 }, { 6, 4 }},
4432 UBiDi
*pBiDi
= NULL
;
4434 UErrorCode rc
= U_ZERO_ERROR
;
4435 int32_t srcLen
, processedLen
, chunk
, len
, nPortions
;
4436 int i
, j
, levelIndex
;
4438 int nTests
= LENGTHOF(testData
), nLevels
= LENGTHOF(paraLevels
);
4439 UBool mismatch
, testOK
= TRUE
;
4440 char processedLenStr
[MAXPORTIONS
* 5];
4442 log_verbose("\nEntering TestStreaming\n\n");
4444 pBiDi
= getBiDiObject();
4446 ubidi_orderParagraphsLTR(pBiDi
, TRUE
);
4448 for (levelIndex
= 0; levelIndex
< nLevels
; levelIndex
++) {
4449 for (i
= 0; i
< nTests
; i
++) {
4450 srcLen
= u_unescape(testData
[i
].textIn
, src
, MAXLEN
);
4451 chunk
= testData
[i
].chunk
;
4452 nPortions
= testData
[i
].nPortions
[levelIndex
];
4453 level
= paraLevels
[levelIndex
];
4454 processedLenStr
[0] = NULL_CHAR
;
4455 log_verbose("Testing level %d, case %d\n", level
, i
);
4459 ubidi_setReorderingOptions(pBiDi
, UBIDI_OPTION_STREAMING
);
4460 for (j
= 0, pSrc
= src
; j
< MAXPORTIONS
&& srcLen
> 0; j
++) {
4462 len
= chunk
< srcLen
? chunk
: srcLen
;
4463 ubidi_setPara(pBiDi
, pSrc
, len
, level
, NULL
, &rc
);
4464 if (!assertSuccessful("ubidi_setPara", &rc
)) {
4468 processedLen
= ubidi_getProcessedLength(pBiDi
);
4469 if (processedLen
== 0) {
4470 ubidi_setReorderingOptions(pBiDi
, UBIDI_OPTION_DEFAULT
);
4474 ubidi_setReorderingOptions(pBiDi
, UBIDI_OPTION_STREAMING
);
4476 mismatch
|= (UBool
)(j
>= nPortions
||
4477 processedLen
!= testData
[i
].portionLens
[levelIndex
][j
]);
4479 sprintf(processedLenStr
+ j
* 4, "%4d", processedLen
);
4480 srcLen
-= processedLen
, pSrc
+= processedLen
;
4483 if (mismatch
|| j
!= nPortions
) {
4485 log_err("\nProcessed lengths mismatch.\n"
4486 "\tParagraph level: %u\n"
4487 "\tInput string: %s\n"
4488 "\tActually processed portion lengths: { %s }\n"
4489 "\tExpected portion lengths : { %s }\n",
4490 paraLevels
[levelIndex
], testData
[i
].textIn
,
4491 processedLenStr
, testData
[i
].message
[levelIndex
]);
4496 if (testOK
== TRUE
) {
4497 log_verbose("\nBiDi streaming test OK\n");
4499 log_verbose("\nExiting TestStreaming\n\n");
4504 static UCharDirection U_CALLCONV
4505 overrideBidiClass(const void *context
, UChar32 c
) {
4507 #define DEF U_BIDI_CLASS_DEFAULT
4509 static const UCharDirection customClasses
[] = {
4510 /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
4511 DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, /* 00-07 */
4512 DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, /* 08-0F */
4513 DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, /* 10-17 */
4514 DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, /* 18-1F */
4515 DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, R
, DEF
, /* 20-27 */
4516 DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, /* 28-2F */
4517 EN
, EN
, EN
, EN
, EN
, EN
, AN
, AN
, /* 30-37 */
4518 AN
, AN
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, /* 38-3F */
4519 L
, AL
, AL
, AL
, AL
, AL
, AL
, R
, /* 40-47 */
4520 R
, R
, R
, R
, R
, R
, R
, R
, /* 48-4F */
4521 R
, R
, R
, R
, R
, R
, R
, R
, /* 50-57 */
4522 R
, R
, R
, LRE
, DEF
, RLE
, PDF
, S
, /* 58-5F */
4523 NSM
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, /* 60-67 */
4524 DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, /* 68-6F */
4525 DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, DEF
, /* 70-77 */
4526 DEF
, DEF
, DEF
, LRO
, B
, RLO
, BN
, DEF
/* 78-7F */
4528 static const int nEntries
= LENGTHOF(customClasses
);
4529 const char *dummy
= context
; /* just to avoid a compiler warning */
4532 return c
>= nEntries
? U_BIDI_CLASS_DEFAULT
: customClasses
[c
];
4537 static void verifyCallbackParams(UBiDiClassCallback
* fn
, const void* context
,
4538 UBiDiClassCallback
* expectedFn
,
4539 const void* expectedContext
,
4540 int32_t sizeOfContext
) {
4541 if (fn
!= expectedFn
) {
4542 log_err("Class callback pointer is not set properly.\n");
4544 if (context
!= expectedContext
) {
4545 log_err("Class callback context is not set properly.\n");
4547 else if (context
!= NULL
&&
4548 memcmp(context
, expectedContext
, sizeOfContext
)) {
4549 log_err("Callback context content doesn't match the expected one.\n");
4554 testClassOverride(void) {
4555 static const char* const textSrc
= "JIH.>12->a \\u05D0\\u05D1 6 ABC78";
4556 static const char* const textResult
= "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0";
4558 UChar src
[MAXLEN
], dest
[MAXLEN
];
4559 UErrorCode rc
= U_ZERO_ERROR
;
4560 UBiDi
*pBiDi
= NULL
;
4561 UBiDiClassCallback
* oldFn
= NULL
;
4562 UBiDiClassCallback
* newFn
= overrideBidiClass
;
4563 const void* oldContext
= NULL
;
4564 int32_t srcLen
, destLen
, textSrcSize
= (int32_t)uprv_strlen(textSrc
);
4565 char* destChars
= NULL
;
4567 log_verbose("\nEntering TestClassOverride\n\n");
4569 pBiDi
= getBiDiObject();
4574 ubidi_getClassCallback(pBiDi
, &oldFn
, &oldContext
);
4575 verifyCallbackParams(oldFn
, oldContext
, NULL
, NULL
, 0);
4577 ubidi_setClassCallback(pBiDi
, newFn
, textSrc
, &oldFn
, &oldContext
, &rc
);
4578 if (!assertSuccessful("ubidi_setClassCallback", &rc
)) {
4582 verifyCallbackParams(oldFn
, oldContext
, NULL
, NULL
, 0);
4584 ubidi_getClassCallback(pBiDi
, &oldFn
, &oldContext
);
4585 verifyCallbackParams(oldFn
, oldContext
, newFn
, textSrc
, textSrcSize
);
4587 ubidi_setClassCallback(pBiDi
, newFn
, textSrc
, &oldFn
, &oldContext
, &rc
);
4588 if (!assertSuccessful("ubidi_setClassCallback", &rc
)) {
4592 verifyCallbackParams(oldFn
, oldContext
, newFn
, textSrc
, textSrcSize
);
4594 srcLen
= u_unescape(textSrc
, src
, MAXLEN
);
4595 ubidi_setPara(pBiDi
, src
, srcLen
, UBIDI_LTR
, NULL
, &rc
);
4596 assertSuccessful("ubidi_setPara", &rc
);
4598 destLen
= ubidi_writeReordered(pBiDi
, dest
, MAXLEN
,
4599 UBIDI_DO_MIRRORING
, &rc
);
4600 assertSuccessful("ubidi_writeReordered", &rc
);
4602 destChars
= aescstrdup(dest
, destLen
);
4603 if (uprv_strcmp(textResult
, destChars
)) {
4604 log_err("\nActual and expected output mismatch.\n"
4605 "%20s %s\n%20s %s\n%20s %s\n",
4606 "Input:", textSrc
, "Actual output:", destChars
,
4607 "Expected output:", textResult
);
4610 log_verbose("\nClass override test OK\n");
4613 log_verbose("\nExiting TestClassOverride\n\n");
4616 static char * formatMap(const int32_t * map
, int len
, char * buffer
)
4620 for (i
= 0; i
< len
; i
++) {
4624 else if (k
>= sizeof(columns
))
4635 checkMaps(UBiDi
*pBiDi
, int32_t stringIndex
, const char *src
, const char *dest
,
4636 const char *mode
, const char* option
, UBiDiLevel level
, UBool forward
)
4638 int32_t actualLogicalMap
[MAX_MAP_LENGTH
];
4639 int32_t actualVisualMap
[MAX_MAP_LENGTH
];
4640 int32_t getIndexMap
[MAX_MAP_LENGTH
];
4641 int32_t i
, srcLen
, resLen
, idx
;
4642 const int32_t *expectedLogicalMap
, *expectedVisualMap
;
4643 UErrorCode rc
= U_ZERO_ERROR
;
4644 UBool testOK
= TRUE
;
4647 expectedLogicalMap
= forwardMap
[stringIndex
];
4648 expectedVisualMap
= inverseMap
[stringIndex
];
4651 expectedLogicalMap
= inverseMap
[stringIndex
];
4652 expectedVisualMap
= forwardMap
[stringIndex
];
4654 ubidi_getLogicalMap(pBiDi
, actualLogicalMap
, &rc
);
4655 if (!assertSuccessful("ubidi_getLogicalMap", &rc
)) {
4658 srcLen
= ubidi_getProcessedLength(pBiDi
);
4659 if (memcmp(expectedLogicalMap
, actualLogicalMap
, srcLen
* sizeof(int32_t))) {
4660 char expChars
[MAX_MAP_LENGTH
];
4661 char actChars
[MAX_MAP_LENGTH
];
4662 log_err("\nubidi_getLogicalMap() returns unexpected map for output string "
4669 "Paragraph level : %d == %d\n"
4670 "Reordering mode : %s == %d\n"
4671 "Reordering option: %s == %d\n"
4672 "Forward flag : %d\n",
4673 stringIndex
, src
, dest
, columns
,
4674 formatMap(expectedLogicalMap
, srcLen
, expChars
),
4675 formatMap(actualLogicalMap
, srcLen
, actChars
),
4676 level
, ubidi_getParaLevel(pBiDi
),
4677 mode
, ubidi_getReorderingMode(pBiDi
),
4678 option
, ubidi_getReorderingOptions(pBiDi
),
4683 resLen
= ubidi_getResultLength(pBiDi
);
4684 ubidi_getVisualMap(pBiDi
, actualVisualMap
, &rc
);
4685 assertSuccessful("ubidi_getVisualMap", &rc
);
4686 if (memcmp(expectedVisualMap
, actualVisualMap
, resLen
* sizeof(int32_t))) {
4687 char expChars
[MAX_MAP_LENGTH
];
4688 char actChars
[MAX_MAP_LENGTH
];
4689 log_err("\nubidi_getVisualMap() returns unexpected map for output string "
4696 "Paragraph level : %d == %d\n"
4697 "Reordering mode : %s == %d\n"
4698 "Reordering option: %s == %d\n"
4699 "Forward flag : %d\n",
4700 stringIndex
, src
, dest
, columns
,
4701 formatMap(expectedVisualMap
, resLen
, expChars
),
4702 formatMap(actualVisualMap
, resLen
, actChars
),
4703 level
, ubidi_getParaLevel(pBiDi
),
4704 mode
, ubidi_getReorderingMode(pBiDi
),
4705 option
, ubidi_getReorderingOptions(pBiDi
),
4710 for (i
= 0; i
< srcLen
; i
++) {
4711 idx
= ubidi_getVisualIndex(pBiDi
, i
, &rc
);
4712 assertSuccessful("ubidi_getVisualIndex", &rc
);
4713 getIndexMap
[i
] = idx
;
4715 if (memcmp(actualLogicalMap
, getIndexMap
, srcLen
* sizeof(int32_t))) {
4716 char actChars
[MAX_MAP_LENGTH
];
4717 char gotChars
[MAX_MAP_LENGTH
];
4718 log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string "
4725 "Paragraph level : %d == %d\n"
4726 "Reordering mode : %s == %d\n"
4727 "Reordering option: %s == %d\n"
4728 "Forward flag : %d\n",
4729 stringIndex
, src
, dest
, columns
,
4730 formatMap(actualLogicalMap
, srcLen
, actChars
),
4731 formatMap(getIndexMap
, srcLen
, gotChars
),
4732 level
, ubidi_getParaLevel(pBiDi
),
4733 mode
, ubidi_getReorderingMode(pBiDi
),
4734 option
, ubidi_getReorderingOptions(pBiDi
),
4739 for (i
= 0; i
< resLen
; i
++) {
4740 idx
= ubidi_getLogicalIndex(pBiDi
, i
, &rc
);
4741 assertSuccessful("ubidi_getLogicalIndex", &rc
);
4742 getIndexMap
[i
] = idx
;
4744 if (memcmp(actualVisualMap
, getIndexMap
, resLen
* sizeof(int32_t))) {
4745 char actChars
[MAX_MAP_LENGTH
];
4746 char gotChars
[MAX_MAP_LENGTH
];
4747 log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string "
4754 "Paragraph level : %d == %d\n"
4755 "Reordering mode : %s == %d\n"
4756 "Reordering option: %s == %d\n"
4757 "Forward flag : %d\n",
4758 stringIndex
, src
, dest
, columns
,
4759 formatMap(actualVisualMap
, resLen
, actChars
),
4760 formatMap(getIndexMap
, resLen
, gotChars
),
4761 level
, ubidi_getParaLevel(pBiDi
),
4762 mode
, ubidi_getReorderingMode(pBiDi
),
4763 option
, ubidi_getReorderingOptions(pBiDi
),
4772 assertIllegalArgument(const char* message
, UErrorCode
* rc
) {
4773 if (*rc
!= U_ILLEGAL_ARGUMENT_ERROR
) {
4774 log_err("%s() failed with error %s.\n", message
, myErrorName(*rc
));
4781 const char* prologue
;
4783 const char* epilogue
;
4784 const char* expected
;
4785 UBiDiLevel paraLevel
;
4788 static const contextCase contextData
[] = {
4789 /*00*/ {"", "", "", "", UBIDI_LTR
},
4790 /*01*/ {"", ".-=JKL-+*", "", ".-=LKJ-+*", UBIDI_LTR
},
4791 /*02*/ {" ", ".-=JKL-+*", " ", ".-=LKJ-+*", UBIDI_LTR
},
4792 /*03*/ {"a", ".-=JKL-+*", "b", ".-=LKJ-+*", UBIDI_LTR
},
4793 /*04*/ {"D", ".-=JKL-+*", "", "LKJ=-.-+*", UBIDI_LTR
},
4794 /*05*/ {"", ".-=JKL-+*", " D", ".-=*+-LKJ", UBIDI_LTR
},
4795 /*06*/ {"", ".-=JKL-+*", " 2", ".-=*+-LKJ", UBIDI_LTR
},
4796 /*07*/ {"", ".-=JKL-+*", " 7", ".-=*+-LKJ", UBIDI_LTR
},
4797 /*08*/ {" G 1", ".-=JKL-+*", " H", "*+-LKJ=-.", UBIDI_LTR
},
4798 /*09*/ {"7", ".-=JKL-+*", " H", ".-=*+-LKJ", UBIDI_LTR
},
4799 /*10*/ {"", ".-=abc-+*", "", "*+-abc=-.", UBIDI_RTL
},
4800 /*11*/ {" ", ".-=abc-+*", " ", "*+-abc=-.", UBIDI_RTL
},
4801 /*12*/ {"D", ".-=abc-+*", "G", "*+-abc=-.", UBIDI_RTL
},
4802 /*13*/ {"x", ".-=abc-+*", "", "*+-.-=abc", UBIDI_RTL
},
4803 /*14*/ {"", ".-=abc-+*", " y", "abc-+*=-.", UBIDI_RTL
},
4804 /*15*/ {"", ".-=abc-+*", " 2", "abc-+*=-.", UBIDI_RTL
},
4805 /*16*/ {" x 1", ".-=abc-+*", " 2", ".-=abc-+*", UBIDI_RTL
},
4806 /*17*/ {" x 7", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL
},
4807 /*18*/ {"x|", ".-=abc-+*", " 8", "*+-abc=-.", UBIDI_RTL
},
4808 /*19*/ {"G|y", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL
},
4809 /*20*/ {"", ".-=", "", ".-=", UBIDI_DEFAULT_LTR
},
4810 /*21*/ {"D", ".-=", "", "=-.", UBIDI_DEFAULT_LTR
},
4811 /*22*/ {"G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR
},
4812 /*23*/ {"xG", ".-=", "", ".-=", UBIDI_DEFAULT_LTR
},
4813 /*24*/ {"x|G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR
},
4814 /*25*/ {"x|G", ".-=|-+*", "", "=-.|-+*", UBIDI_DEFAULT_LTR
},
4816 #define CONTEXT_COUNT LENGTHOF(contextData)
4821 UChar prologue
[MAXLEN
], epilogue
[MAXLEN
], src
[MAXLEN
], dest
[MAXLEN
];
4822 char destChars
[MAXLEN
];
4823 UBiDi
*pBiDi
= NULL
;
4825 int32_t proLength
, epiLength
, srcLen
, destLen
, tc
;
4827 UBool testOK
= TRUE
;
4829 log_verbose("\nEntering TestContext \n\n");
4831 /* test null BiDi object */
4833 ubidi_setContext(pBiDi
, NULL
, 0, NULL
, 0, &rc
);
4834 testOK
&= assertIllegalArgument("Error when BiDi object is null", &rc
);
4836 pBiDi
= getBiDiObject();
4837 ubidi_orderParagraphsLTR(pBiDi
, TRUE
);
4839 /* test proLength < -1 */
4841 ubidi_setContext(pBiDi
, NULL
, -2, NULL
, 0, &rc
);
4842 testOK
&= assertIllegalArgument("Error when proLength < -1", &rc
);
4843 /* test epiLength < -1 */
4845 ubidi_setContext(pBiDi
, NULL
, 0, NULL
, -2, &rc
);
4846 testOK
&= assertIllegalArgument("Error when epiLength < -1", &rc
);
4847 /* test prologue == NULL */
4849 ubidi_setContext(pBiDi
, NULL
, 3, NULL
, 0, &rc
);
4850 testOK
&= assertIllegalArgument("Prologue is NULL", &rc
);
4851 /* test epilogue == NULL */
4853 ubidi_setContext(pBiDi
, NULL
, 0, NULL
, 4, &rc
);
4854 testOK
&= assertIllegalArgument("Epilogue is NULL", &rc
);
4856 for (tc
= 0; tc
< CONTEXT_COUNT
; tc
++) {
4857 cc
= contextData
[tc
];
4858 proLength
= strlen(cc
.prologue
);
4859 pseudoToU16(proLength
, cc
.prologue
, prologue
);
4860 epiLength
= strlen(cc
.epilogue
);
4861 pseudoToU16(epiLength
, cc
.epilogue
, epilogue
);
4862 /* in the call below, prologue and epilogue are swapped to show
4863 that the next call will override this call */
4865 ubidi_setContext(pBiDi
, epilogue
, epiLength
, prologue
, proLength
, &rc
);
4866 testOK
&= assertSuccessful("swapped ubidi_setContext", &rc
);
4867 ubidi_setContext(pBiDi
, prologue
, -1, epilogue
, -1, &rc
);
4868 testOK
&= assertSuccessful("regular ubidi_setContext", &rc
);
4869 srcLen
= strlen(cc
.source
);
4870 pseudoToU16(srcLen
, cc
.source
, src
);
4871 ubidi_setPara(pBiDi
, src
, srcLen
, cc
.paraLevel
, NULL
, &rc
);
4872 testOK
&= assertSuccessful("ubidi_setPara", &rc
);
4873 destLen
= ubidi_writeReordered(pBiDi
, dest
, MAXLEN
, UBIDI_DO_MIRRORING
, &rc
);
4874 assertSuccessful("ubidi_writeReordered", &rc
);
4875 u16ToPseudo(destLen
, dest
, destChars
);
4876 if (uprv_strcmp(cc
.expected
, destChars
)) {
4877 char formatChars
[MAXLEN
];
4878 log_err("\nActual and expected output mismatch on case %d.\n"
4879 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d\n%20s %u\n%20s %d\n",
4881 "Prologue:", cc
.prologue
,
4882 "Input:", cc
.source
,
4883 "Epilogue:", cc
.epilogue
,
4884 "Expected output:", cc
.expected
,
4885 "Actual output:", destChars
,
4886 "Levels:", formatLevels(pBiDi
, formatChars
),
4887 "Reordering mode:", ubidi_getReorderingMode(pBiDi
),
4888 "Paragraph level:", ubidi_getParaLevel(pBiDi
),
4889 "Reordering option:", ubidi_getReorderingOptions(pBiDi
));
4893 if (testOK
== TRUE
) {
4894 log_verbose("\nContext test OK\n");
4898 log_verbose("\nExiting TestContext \n\n");