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