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(void);
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 int32_t len = ubidi_getLength(bidi);
402 char c;
403 int32_t 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 >= (int32_t)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 = (int)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) UPRV_BLOCK_MACRO_BEGIN { \
1291 if (U_FAILURE(errorCode)) { \
1292 log_err("\nbad errorCode %d at %s\n", errorCode, (x)); \
1293 return; \
1294 } \
1295 } UPRV_BLOCK_MACRO_END
1296
1297 #define STRING_TEST_CASE(s) { (s), UPRV_LENGTHOF(s) }
1298
testGetBaseDirection(void)1299 static void testGetBaseDirection(void) {
1300 UBiDiDirection dir;
1301 int i;
1302
1303 /* Test Data */
1304 static const UChar
1305 /*Mixed Start with L*/
1306 stringMixedEnglishFirst[]={ 0x61, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 },
1307 /*Mixed Start with AL*/
1308 stringMixedArabicFirst[]={ 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
1309 /*Mixed Start with R*/
1310 stringMixedHebrewFirst[]={ 0x05EA, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
1311 /*All AL (Arabic. Persian)*/
1312 stringPersian[]={0x0698, 0x067E, 0x0686, 0x06AF, 0},
1313 /*All R (Hebrew etc.)*/
1314 stringHebrew[]={0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
1315 /*All L (English)*/
1316 stringEnglish[]={0x71, 0x61, 0x66, 0},
1317 /*Mixed Start with weak AL an then L*/
1318 stringStartWeakAL[]={ 0x0663, 0x71, 0x61, 0x66, 0},
1319 /*Mixed Start with weak L and then AL*/
1320 stringStartWeakL[]={0x31, 0x0698, 0x067E, 0x0686, 0x06AF, 0},
1321 /*Empty*/
1322 stringEmpty[]={0},
1323 /*Surrogate Char.*/
1324 stringSurrogateChar[]={0xD800, 0xDC00, 0},
1325 /*Invalid UChar*/
1326 stringInvalidUchar[]={-1},
1327 /*All weak L (English Digits)*/
1328 stringAllEnglishDigits[]={0x31, 0x32, 0x33, 0},
1329 /*All weak AL (Arabic Digits)*/
1330 stringAllArabicDigits[]={0x0663, 0x0664, 0x0665, 0},
1331 /*First L (English) others are R (Hebrew etc.) */
1332 stringFirstL[] = {0x71, 0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
1333 /*Last R (Hebrew etc.) others are weak L (English Digits)*/
1334 stringLastR[] = {0x31, 0x32, 0x33, 0x05F1, 0};
1335
1336 static const struct {
1337 const UChar *s;
1338 int32_t length;
1339 } testCases[]={
1340 STRING_TEST_CASE(stringMixedEnglishFirst),
1341 STRING_TEST_CASE(stringMixedArabicFirst),
1342 STRING_TEST_CASE(stringMixedHebrewFirst),
1343 STRING_TEST_CASE(stringPersian),
1344 STRING_TEST_CASE(stringHebrew),
1345 STRING_TEST_CASE(stringEnglish),
1346 STRING_TEST_CASE(stringStartWeakAL),
1347 STRING_TEST_CASE(stringStartWeakL),
1348 STRING_TEST_CASE(stringEmpty),
1349 STRING_TEST_CASE(stringSurrogateChar),
1350 STRING_TEST_CASE(stringInvalidUchar),
1351 STRING_TEST_CASE(stringAllEnglishDigits),
1352 STRING_TEST_CASE(stringAllArabicDigits),
1353 STRING_TEST_CASE(stringFirstL),
1354 STRING_TEST_CASE(stringLastR),
1355 };
1356
1357 /* Expected results */
1358 static const UBiDiDirection expectedDir[] ={
1359 UBIDI_LTR, UBIDI_RTL, UBIDI_RTL,
1360 UBIDI_RTL, UBIDI_RTL, UBIDI_LTR,
1361 UBIDI_LTR, UBIDI_RTL, UBIDI_NEUTRAL,
1362 UBIDI_LTR, UBIDI_NEUTRAL, UBIDI_NEUTRAL,
1363 UBIDI_NEUTRAL, UBIDI_LTR, UBIDI_RTL
1364 };
1365
1366 log_verbose("testGetBaseDirection() with %u test cases ---\n",
1367 UPRV_LENGTHOF(testCases));
1368 /* Run Tests */
1369 for(i=0; i<UPRV_LENGTHOF(testCases); ++i) {
1370 dir = ubidi_getBaseDirection(testCases[i].s, testCases[i].length );
1371 log_verbose("Testing case %d\tReceived dir %d\n", i, dir);
1372 if (dir != expectedDir[i])
1373 log_err("\nFailed getBaseDirection case %d Expected %d \tReceived %d\n",
1374 i, expectedDir[i], dir);
1375 }
1376
1377 /* Misc. tests */
1378 /* NULL string */
1379 dir = ubidi_getBaseDirection(NULL, 3);
1380 if (dir != UBIDI_NEUTRAL )
1381 log_err("\nFailed getBaseDirection for NULL string " ,
1382 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
1383 /*All L- English string and length=-3 */
1384 dir = ubidi_getBaseDirection( stringEnglish, -3);
1385 if (dir != UBIDI_NEUTRAL )
1386 log_err("\nFailed getBaseDirection for string w length= -3 ",
1387 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
1388 /*All L- English string and length=-1 */
1389 dir = ubidi_getBaseDirection( stringEnglish, -1);
1390 if (dir != UBIDI_LTR )
1391 log_err("\nFailed getBaseDirection for English string w length= -1 ",
1392 "\nExpected %d \nReceived %d", UBIDI_LTR, dir);
1393 /*All AL- Persian string and length=-1 */
1394 dir = ubidi_getBaseDirection( stringPersian, -1);
1395 if (dir != UBIDI_RTL )
1396 log_err("\nFailed getBaseDirection for Persian string w length= -1 ",
1397 "\nExpected %d \nReceived %d", UBIDI_RTL, dir);
1398 /*All R- Hebrew string and length=-1 */
1399 dir = ubidi_getBaseDirection( stringHebrew, -1);
1400 if (dir != UBIDI_RTL )
1401 log_err("\nFailed getBaseDirection for Hebrew string w length= -1 ",
1402 "\nExpected %d \nReceived %d", UBIDI_RTL, dir);
1403 /*All weak L- English digits string and length=-1 */
1404 dir = ubidi_getBaseDirection(stringAllEnglishDigits, -1);
1405 if (dir != UBIDI_NEUTRAL )
1406 log_err("\nFailed getBaseDirection for English digits string w length= -1 ",
1407 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
1408 /*All weak AL- Arabic digits string and length=-1 */
1409 dir = ubidi_getBaseDirection(stringAllArabicDigits, -1);
1410 if (dir != UBIDI_NEUTRAL )
1411 log_err("\nFailed getBaseDirection for Arabic string w length= -1 ",
1412 "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
1413
1414 }
1415
1416
doMisc(void)1417 static void doMisc(void) {
1418 /* Miscellaneous tests to exercize less popular code paths */
1419 UBiDi *bidi, *bidiLine;
1420 UChar src[MAXLEN], dest[MAXLEN];
1421 int32_t srcLen, destLen, runCount, i;
1422 UBiDiLevel level;
1423 UBiDiDirection dir;
1424 int32_t map[MAXLEN];
1425 UErrorCode errorCode=U_ZERO_ERROR;
1426 static const int32_t srcMap[6] = {0,1,-1,5,4};
1427 static const int32_t dstMap[6] = {0,1,-1,-1,4,3};
1428
1429 bidi = ubidi_openSized(120, 66, &errorCode);
1430 if (bidi == NULL) {
1431 log_err("Error with openSized(120, 66)\n");
1432 return;
1433 }
1434 bidiLine = ubidi_open();
1435 if (bidi == NULL) {
1436 log_err("Error with open()\n");
1437 return;
1438 }
1439
1440 destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode);
1441 if (destLen != 0) {
1442 log_err("\nwriteReverse should return zero length, ",
1443 "returned %d instead\n", destLen);
1444 }
1445 RETURN_IF_BAD_ERRCODE("#1#");
1446
1447 ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
1448 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1449 if (destLen != 0) {
1450 log_err("\nwriteReordered should return zero length, ",
1451 "returned %d instead\n", destLen);
1452 }
1453 RETURN_IF_BAD_ERRCODE("#2#");
1454
1455 srcLen = u_unescape("abc ", src, MAXLEN);
1456 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1457 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1458 for (i = 3; i < 6; i++) {
1459 level = ubidi_getLevelAt(bidiLine, i);
1460 if (level != UBIDI_RTL) {
1461 log_err("\nTrailing space at index %d should get paragraph level"
1462 "%d, got %d instead\n", i, UBIDI_RTL, level);
1463 }
1464 }
1465 RETURN_IF_BAD_ERRCODE("#3#");
1466
1467 srcLen = u_unescape("abc def", src, MAXLEN);
1468 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1469 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1470 for (i = 3; i < 6; i++) {
1471 level = ubidi_getLevelAt(bidiLine, i);
1472 if (level != UBIDI_RTL) {
1473 log_err("\nTrailing space at index %d should get paragraph level"
1474 "%d, got %d instead\n", i, UBIDI_RTL, level);
1475 }
1476 }
1477 RETURN_IF_BAD_ERRCODE("#4#");
1478
1479 srcLen = u_unescape("abcdefghi ", src, MAXLEN);
1480 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1481 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1482 for (i = 3; i < 6; i++) {
1483 level = ubidi_getLevelAt(bidiLine, i);
1484 if (level != 2) {
1485 log_err("\nTrailing char at index %d should get level 2, "
1486 "got %d instead\n", i, level);
1487 }
1488 }
1489 RETURN_IF_BAD_ERRCODE("#5#");
1490
1491 ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS);
1492 srcLen = u_unescape("\\u200eabc def", src, MAXLEN);
1493 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1494 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1495 destLen = ubidi_getResultLength(bidiLine);
1496 if (destLen != 5) {
1497 log_err("\nWrong result length, should be 5, got %d\n", destLen);
1498 }
1499 RETURN_IF_BAD_ERRCODE("#6#");
1500
1501 srcLen = u_unescape("abcdefghi", src, MAXLEN);
1502 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1503 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1504 dir = ubidi_getDirection(bidiLine);
1505 if (dir != UBIDI_LTR) {
1506 log_err("\nWrong direction #1, should be %d, got %d\n",
1507 UBIDI_LTR, dir);
1508 }
1509 RETURN_IF_BAD_ERRCODE("#7#");
1510
1511 ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
1512 runCount = ubidi_countRuns(bidi, &errorCode);
1513 if (runCount != 0) {
1514 log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount);
1515 }
1516 RETURN_IF_BAD_ERRCODE("#8#");
1517
1518 srcLen = u_unescape(" ", src, MAXLEN);
1519 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1520 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1521 runCount = ubidi_countRuns(bidiLine, &errorCode);
1522 if (runCount != 1) {
1523 log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount);
1524 }
1525 RETURN_IF_BAD_ERRCODE("#9#");
1526
1527 srcLen = u_unescape("a\\u05d0 bc", src, MAXLEN);
1528 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1529 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1530 dir = ubidi_getDirection(bidi);
1531 if (dir != UBIDI_MIXED) {
1532 log_err("\nWrong direction #2, should be %d, got %d\n",
1533 UBIDI_MIXED, dir);
1534 }
1535 dir = ubidi_getDirection(bidiLine);
1536 if (dir != UBIDI_MIXED) {
1537 log_err("\nWrong direction #3, should be %d, got %d\n",
1538 UBIDI_MIXED, dir);
1539 }
1540 runCount = ubidi_countRuns(bidiLine, &errorCode);
1541 if (runCount != 2) {
1542 log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount);
1543 }
1544 RETURN_IF_BAD_ERRCODE("#10#");
1545
1546 ubidi_invertMap(srcMap, map, 5);
1547 if (memcmp(dstMap, map, sizeof(dstMap))) {
1548 log_err("\nUnexpected inverted Map, got ");
1549 for (i = 0; i < 6; i++) {
1550 log_err("%d ", map[i]);
1551 }
1552 log_err("\n");
1553 }
1554
1555 /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
1556 srcLen = u_unescape("abc\\u200e", src, MAXLEN);
1557 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1558 destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
1559 UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode);
1560 if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) {
1561 log_err("\nWrong result #1, should be 'abc', got '%s'\n",
1562 aescstrdup(dest, destLen));
1563 }
1564 RETURN_IF_BAD_ERRCODE("#11#");
1565
1566 /* test inverse Bidi with marks and contextual orientation */
1567 ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
1568 ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
1569 ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1570 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1571 if (destLen != 0) {
1572 log_err("\nWrong result #2, length should be 0, got %d\n", destLen);
1573 }
1574 RETURN_IF_BAD_ERRCODE("#12#");
1575 srcLen = u_unescape(" ", src, MAXLEN);
1576 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1577 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1578 if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
1579 log_err("\nWrong result #3, should be ' ', got '%s'\n",
1580 aescstrdup(dest, destLen));
1581 }
1582 RETURN_IF_BAD_ERRCODE("#13#");
1583 srcLen = u_unescape("abc", src, MAXLEN);
1584 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1585 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1586 if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
1587 log_err("\nWrong result #4, should be 'abc', got '%s'\n",
1588 aescstrdup(dest, destLen));
1589 }
1590 RETURN_IF_BAD_ERRCODE("#14#");
1591 srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN);
1592 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1593 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1594 srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN);
1595 if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) {
1596 log_err("\nWrong result #5, should be '%s', got '%s'\n",
1597 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1598 }
1599 RETURN_IF_BAD_ERRCODE("#15#");
1600 srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN);
1601 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1602 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1603 srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN);
1604 if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) {
1605 log_err("\nWrong result #6, should be '%s', got '%s'\n",
1606 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1607 }
1608 RETURN_IF_BAD_ERRCODE("#16#");
1609 srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN);
1610 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1611 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1612 srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN);
1613 if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) {
1614 log_err("\nWrong result #7, should be '%s', got '%s'\n",
1615 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1616 }
1617 RETURN_IF_BAD_ERRCODE("#17#");
1618 srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN);
1619 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1620 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1621 srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN);
1622 if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) {
1623 log_err("\nWrong result #8, should be '%s', got '%s'\n",
1624 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1625 }
1626 RETURN_IF_BAD_ERRCODE("#18#");
1627 ubidi_orderParagraphsLTR(bidi, TRUE);
1628 srcLen = u_unescape("\n\r \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r"
1629 "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n"
1630 "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN);
1631 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
1632 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1633 srcLen = u_unescape("\n\r \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r"
1634 "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n"
1635 "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN);
1636 if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) {
1637 log_err("\nWrong result #9, should be '%s', got '%s'\n",
1638 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1639 }
1640 RETURN_IF_BAD_ERRCODE("#19#");
1641 srcLen = u_unescape("\\u05d0 \t", src, MAXLEN);
1642 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1643 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1644 srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN);
1645 if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) {
1646 log_err("\nWrong result #10, should be '%s', got '%s'\n",
1647 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1648 }
1649 RETURN_IF_BAD_ERRCODE("#20#");
1650 srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN);
1651 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1652 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1653 srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN);
1654 if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) {
1655 log_err("\nWrong result #11, should be '%s', got '%s'\n",
1656 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1657 }
1658 RETURN_IF_BAD_ERRCODE("#21#");
1659 srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN);
1660 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1661 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1662 srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN);
1663 if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) {
1664 log_err("\nWrong result #12, should be '%s', got '%s'\n",
1665 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1666 }
1667 RETURN_IF_BAD_ERRCODE("#22#");
1668 srcLen = u_unescape("ab \t", src, MAXLEN);
1669 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1670 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
1671 srcLen = u_unescape("\\u200f\t ab", src, MAXLEN);
1672 if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) {
1673 log_err("\nWrong result #13, should be '%s', got '%s'\n",
1674 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
1675 }
1676 RETURN_IF_BAD_ERRCODE("#23#");
1677
1678 /* check exceeding para level */
1679 ubidi_close(bidi);
1680 bidi = ubidi_open();
1681 srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN);
1682 ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode);
1683 level = ubidi_getLevelAt(bidi, 2);
1684 if (level != UBIDI_MAX_EXPLICIT_LEVEL) {
1685 log_err("\nWrong level at index 2\n, should be %d, got %d\n", UBIDI_MAX_EXPLICIT_LEVEL, level);
1686 }
1687 RETURN_IF_BAD_ERRCODE("#24#");
1688
1689 /* check 1-char runs with RUNS_ONLY */
1690 ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY);
1691 srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN);
1692 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1693 runCount = ubidi_countRuns(bidi, &errorCode);
1694 if (runCount != 14) {
1695 log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount);
1696 }
1697 RETURN_IF_BAD_ERRCODE("#25#");
1698
1699 ubidi_close(bidi);
1700 ubidi_close(bidiLine);
1701 }
1702
1703 static void
testFailureRecovery(void)1704 testFailureRecovery(void) {
1705 UErrorCode errorCode;
1706 UBiDi *bidi, *bidiLine;
1707 UChar src[MAXLEN];
1708 int32_t srcLen;
1709 UBiDiLevel level;
1710 UBiDiReorderingMode rm;
1711 static UBiDiLevel myLevels[3] = {6,5,4};
1712
1713 log_verbose("\nEntering TestFailureRecovery\n\n");
1714 errorCode = U_FILE_ACCESS_ERROR;
1715 if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0) {
1716 log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n");
1717 }
1718 if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0) {
1719 log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n");
1720 }
1721 errorCode = U_ZERO_ERROR;
1722 if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1723 log_err("ubidi_writeReordered did not fail as expected\n");
1724 }
1725
1726 bidi = ubidi_open();
1727 srcLen = u_unescape("abc", src, MAXLEN);
1728 errorCode = U_ZERO_ERROR;
1729 ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_LTR - 1, NULL, &errorCode);
1730 if (U_SUCCESS(errorCode)) {
1731 log_err("\nubidi_setPara did not fail when passed too big para level\n");
1732 }
1733 errorCode = U_ZERO_ERROR;
1734 if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1735 log_err("ubidi_writeReverse did not fail as expected\n");
1736 }
1737 bidiLine = ubidi_open();
1738 errorCode = U_ZERO_ERROR;
1739 ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
1740 if (U_SUCCESS(errorCode)) {
1741 log_err("\nubidi_setLine did not fail when called before valid setPara()\n");
1742 }
1743 errorCode = U_ZERO_ERROR;
1744 srcLen = u_unescape("abc", src, MAXLEN);
1745 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR + 4, NULL, &errorCode);
1746 level = ubidi_getLevelAt(bidi, 3);
1747 if (level != 0) {
1748 log_err("\nubidi_getLevelAt did not fail when called with bad argument\n");
1749 }
1750 errorCode = U_ZERO_ERROR;
1751 ubidi_close(bidi);
1752 bidi = ubidi_openSized(-1, 0, &errorCode);
1753 if (U_SUCCESS(errorCode)) {
1754 log_err("\nubidi_openSized did not fail when called with bad argument\n");
1755 }
1756 ubidi_close(bidi);
1757 bidi = ubidi_openSized(2, 1, &errorCode);
1758 errorCode = U_ZERO_ERROR;
1759 srcLen = u_unescape("abc", src, MAXLEN);
1760 ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
1761 if (U_SUCCESS(errorCode)) {
1762 log_err("\nsetPara did not fail when called with text too long\n");
1763 }
1764 errorCode = U_ZERO_ERROR;
1765 srcLen = u_unescape("=2", src, MAXLEN);
1766 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1767 ubidi_countRuns(bidi, &errorCode);
1768 if (U_SUCCESS(errorCode)) {
1769 log_err("\nsetPara did not fail when called for too many runs\n");
1770 }
1771 ubidi_close(bidi);
1772 bidi = ubidi_open();
1773 rm = ubidi_getReorderingMode(bidi);
1774 ubidi_setReorderingMode(bidi, UBIDI_REORDER_DEFAULT - 1);
1775 if (rm != ubidi_getReorderingMode(bidi)) {
1776 log_err("\nsetReorderingMode with bad argument #1 should have no effect\n");
1777 }
1778 ubidi_setReorderingMode(bidi, 9999);
1779 if (rm != ubidi_getReorderingMode(bidi)) {
1780 log_err("\nsetReorderingMode with bad argument #2 should have no effect\n");
1781 }
1782
1783 /* Try a surrogate char */
1784 errorCode = U_ZERO_ERROR;
1785 srcLen = u_unescape("\\uD800\\uDC00", src, MAXLEN);
1786 ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
1787 if (ubidi_getDirection(bidi) != UBIDI_MIXED) {
1788 log_err("\ngetDirection for 1st surrogate char should be MIXED\n");
1789 }
1790 errorCode = U_ZERO_ERROR;
1791 srcLen = u_unescape("abc", src, MAXLEN);
1792 ubidi_setPara(bidi, src, srcLen, 5, myLevels, &errorCode);
1793 if (U_SUCCESS(errorCode)) {
1794 log_err("\nsetPara did not fail when called with bad levels\n");
1795 }
1796 ubidi_close(bidi);
1797 ubidi_close(bidiLine);
1798
1799 log_verbose("\nExiting TestFailureRecovery\n\n");
1800 }
1801
1802 static void
testMultipleParagraphs(void)1803 testMultipleParagraphs(void) {
1804 static const char* const text = "__ABC\\u001c" /* Para #0 offset 0 */
1805 "__\\u05d0DE\\u001c" /* 1 6 */
1806 "__123\\u001c" /* 2 12 */
1807 "\\u000d\\u000a" /* 3 18 */
1808 "FG\\u000d" /* 4 20 */
1809 "\\u000d" /* 5 23 */
1810 "HI\\u000d\\u000a" /* 6 24 */
1811 "\\u000d\\u000a" /* 7 28 */
1812 "\\u000a" /* 8 30 */
1813 "\\u000a" /* 9 31 */
1814 "JK\\u001c"; /* 10 32 */
1815 static const int32_t paraCount=11;
1816 static const int32_t paraBounds[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35};
1817 static const UBiDiLevel paraLevels[]={UBIDI_LTR, UBIDI_RTL, UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL, 22, 23};
1818 static const UBiDiLevel multiLevels[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1819 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
1820 {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1821 {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0},
1822 {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
1823 {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}};
1824 static const char* const text2 = "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2";
1825 static const UBiDiLevel levels2[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2};
1826 static UBiDiLevel myLevels[10] = {0,0,0,0,0,0,0,0,0,0};
1827 static const UChar multiparaTestString[] = {
1828 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da,
1829 0x20, 0xa, 0xa, 0x41, 0x72, 0x74, 0x69, 0x73,
1830 0x74, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,
1831 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa, 0x41, 0x6c,
1832 0x62, 0x75, 0x6d, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1,
1833 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa,
1834 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x20, 0x32, 0x3a,
1835 0x32, 0x37, 0xa, 0xa
1836 };
1837 static const UBiDiLevel multiparaTestLevels[] = {
1838 1, 1, 1, 1, 1, 1, 1, 1,
1839 1, 1, 0, 0, 0, 0, 0, 0,
1840 0, 0, 0, 1, 1, 1, 1, 1,
1841 1, 1, 1, 0, 0, 0, 0, 0,
1842 0, 0, 0, 0, 0, 1, 1, 1,
1843 1, 1, 1, 1, 1, 0, 0, 0,
1844 0, 0, 0, 0, 0, 0, 0, 0,
1845 0, 0, 0, 0
1846 };
1847 UBiDiLevel gotLevel;
1848 const UBiDiLevel* gotLevels;
1849 UBool orderParagraphsLTR;
1850 UChar src[MAXLEN], dest[MAXLEN];
1851 UErrorCode errorCode=U_ZERO_ERROR;
1852 UBiDi* pBidi=ubidi_open();
1853 UBiDi* pLine;
1854 int32_t srcSize, count, paraStart, paraLimit, paraIndex, length;
1855 int32_t srcLen, destLen;
1856 int i, j, k;
1857
1858 log_verbose("\nEntering TestMultipleParagraphs\n\n");
1859 u_unescape(text, src, MAXLEN);
1860 srcSize=u_strlen(src);
1861 ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
1862 if(U_FAILURE(errorCode)){
1863 log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
1864 UBIDI_LTR, u_errorName(errorCode));
1865 ubidi_close(pBidi);
1866 return;
1867 }
1868 /* check paragraph count and boundaries */
1869 if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
1870 log_err("ubidi_countParagraphs returned %d, should be %d\n",
1871 count, paraCount);
1872 }
1873 for (i=0; i<paraCount; i++) {
1874 ubidi_getParagraphByIndex(pBidi, i, ¶Start, ¶Limit, NULL, &errorCode);
1875 if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
1876 log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
1877 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
1878 }
1879 }
1880 errorCode=U_ZERO_ERROR;
1881 /* check with last paragraph not terminated by B */
1882 src[srcSize-1]='L';
1883 ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
1884 if(U_FAILURE(errorCode)){
1885 log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
1886 UBIDI_LTR, u_errorName(errorCode));
1887 ubidi_close(pBidi);
1888 return;
1889 }
1890 if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
1891 log_err("2nd ubidi_countParagraphs returned %d, should be %d\n",
1892 count, paraCount);
1893 }
1894 i=paraCount-1;
1895 ubidi_getParagraphByIndex(pBidi, i, ¶Start, ¶Limit, NULL, &errorCode);
1896 if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
1897 log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
1898 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
1899 }
1900 errorCode=U_ZERO_ERROR;
1901 /* check paraLevel for all paragraphs under various paraLevel specs */
1902 for (k=0; k<6; k++) {
1903 ubidi_setPara(pBidi, src, srcSize, paraLevels[k], NULL, &errorCode);
1904 for (i=0; i<paraCount; i++) {
1905 paraIndex=ubidi_getParagraph(pBidi, paraBounds[i], NULL, NULL, &gotLevel, &errorCode);
1906 if (paraIndex!=i) {
1907 log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n",
1908 paraLevels[k], i, paraIndex, i);
1909 }
1910 if (gotLevel!=multiLevels[k][i]) {
1911 log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n",
1912 paraLevels[k], i, gotLevel, multiLevels[k][i]);
1913 }
1914 }
1915 gotLevel=ubidi_getParaLevel(pBidi);
1916 if (gotLevel!=multiLevels[k][0]) {
1917 log_err("For paraLevel=%d getParaLevel=%d, expected %d\n",
1918 paraLevels[k], gotLevel, multiLevels[k][0]);
1919 }
1920 }
1921 errorCode=U_ZERO_ERROR;
1922 /* check that the result of ubidi_getParaLevel changes if the first
1923 * paragraph has a different level
1924 */
1925 src[0]=0x05d2; /* Hebrew letter Gimel */
1926 ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_LTR, NULL, &errorCode);
1927 gotLevel=ubidi_getParaLevel(pBidi);
1928 if (gotLevel!=UBIDI_RTL) {
1929 log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n",
1930 gotLevel, UBIDI_RTL);
1931 }
1932 errorCode=U_ZERO_ERROR;
1933 /* check that line cannot overlap paragraph boundaries */
1934 pLine=ubidi_open();
1935 i=paraBounds[1];
1936 k=paraBounds[2]+1;
1937 ubidi_setLine(pBidi, i, k, pLine, &errorCode);
1938 if (U_SUCCESS(errorCode)) {
1939 log_err("For line limits %d-%d got success %s\n",
1940 i, k, u_errorName(errorCode));
1941 }
1942 errorCode=U_ZERO_ERROR;
1943 i=paraBounds[1];
1944 k=paraBounds[2];
1945 ubidi_setLine(pBidi, i, k, pLine, &errorCode);
1946 if (U_FAILURE(errorCode)) {
1947 log_err("For line limits %d-%d got error %s\n",
1948 i, k, u_errorName(errorCode));
1949 errorCode=U_ZERO_ERROR;
1950 }
1951 /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */
1952 ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
1953 /* get levels through para Bidi block */
1954 gotLevels=ubidi_getLevels(pBidi, &errorCode);
1955 if (U_FAILURE(errorCode)) {
1956 log_err("Error on Para getLevels %s\n", u_errorName(errorCode));
1957 ubidi_close(pLine);
1958 ubidi_close(pBidi);
1959 return;
1960 }
1961 for (i=26; i<32; i++) {
1962 if (gotLevels[i]!=UBIDI_RTL) {
1963 log_err("For char %d(%04x), level=%d, expected=%d\n",
1964 i, src[i], gotLevels[i], UBIDI_RTL);
1965 }
1966 }
1967 /* get levels through para Line block */
1968 i=paraBounds[1];
1969 k=paraBounds[2];
1970 ubidi_setLine(pBidi, i, k, pLine, &errorCode);
1971 if (U_FAILURE(errorCode)) {
1972 log_err("For line limits %d-%d got error %s\n",
1973 i, k, u_errorName(errorCode));
1974 ubidi_close(pLine);
1975 ubidi_close(pBidi);
1976 return;
1977 }
1978 paraIndex=ubidi_getParagraph(pLine, i, ¶Start, ¶Limit, &gotLevel, &errorCode);
1979 gotLevels=ubidi_getLevels(pLine, &errorCode);
1980 if (U_FAILURE(errorCode)) {
1981 log_err("Error on Line getLevels %s\n", u_errorName(errorCode));
1982 ubidi_close(pLine);
1983 ubidi_close(pBidi);
1984 return;
1985 }
1986 length=ubidi_getLength(pLine);
1987 if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=UBIDI_RTL)) {
1988 log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
1989 "level of separator=%d expected=%d\n",
1990 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], UBIDI_RTL);
1991 }
1992 orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
1993 if (orderParagraphsLTR) {
1994 log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, FALSE);
1995 }
1996 ubidi_orderParagraphsLTR(pBidi, TRUE);
1997 orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
1998 if (!orderParagraphsLTR) {
1999 log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, TRUE);
2000 }
2001 /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */
2002 ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
2003 /* get levels through para Bidi block */
2004 gotLevels=ubidi_getLevels(pBidi, &errorCode);
2005 for (i=26; i<32; i++) {
2006 if (gotLevels[i]!=0) {
2007 log_err("For char %d(%04x), level=%d, expected=%d\n",
2008 i, src[i], gotLevels[i], 0);
2009 }
2010 }
2011 errorCode=U_ZERO_ERROR;
2012 /* get levels through para Line block */
2013 i=paraBounds[1];
2014 k=paraBounds[2];
2015 ubidi_setLine(pBidi, paraStart, paraLimit, pLine, &errorCode);
2016 paraIndex=ubidi_getParagraph(pLine, i, ¶Start, ¶Limit, &gotLevel, &errorCode);
2017 gotLevels=ubidi_getLevels(pLine, &errorCode);
2018 length=ubidi_getLength(pLine);
2019 if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=0)) {
2020 log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
2021 "level of separator=%d expected=%d\n",
2022 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], 0);
2023 log_verbose("levels=");
2024 for (count=0; count<length; count++) {
2025 log_verbose(" %d", gotLevels[count]);
2026 }
2027 log_verbose("\n");
2028 }
2029
2030 /* test that the concatenation of separate invocations of the bidi code
2031 * on each individual paragraph in order matches the levels array that
2032 * results from invoking bidi once over the entire multiparagraph tests
2033 * (with orderParagraphsLTR false, of course)
2034 */
2035 u_unescape(text, src, MAXLEN); /* restore original content */
2036 srcSize=u_strlen(src);
2037 ubidi_orderParagraphsLTR(pBidi, FALSE);
2038 ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_RTL, NULL, &errorCode);
2039 gotLevels=ubidi_getLevels(pBidi, &errorCode);
2040 for (i=0; i<paraCount; i++) {
2041 /* use pLine for individual paragraphs */
2042 paraStart = paraBounds[i];
2043 length = paraBounds[i+1] - paraStart;
2044 ubidi_setPara(pLine, src+paraStart, length, UBIDI_DEFAULT_RTL, NULL, &errorCode);
2045 for (j=0; j<length; j++) {
2046 if ((k=ubidi_getLevelAt(pLine, j)) != (gotLevel=gotLevels[paraStart+j])) {
2047 log_err("Checking paragraph concatenation: for paragraph=%d, "
2048 "char=%d(%04x), level=%d, expected=%d\n",
2049 i, j, src[paraStart+j], k, gotLevel);
2050 }
2051 }
2052 }
2053
2054 /* ensure that leading numerics in a paragraph are not treated as arabic
2055 numerals because of arabic text in a preceding paragraph
2056 */
2057 u_unescape(text2, src, MAXLEN);
2058 srcSize=u_strlen(src);
2059 ubidi_orderParagraphsLTR(pBidi, TRUE);
2060 ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
2061 gotLevels=ubidi_getLevels(pBidi, &errorCode);
2062 if (U_FAILURE(errorCode)) {
2063 log_err("Can't get levels. %s\n", u_errorName(errorCode));
2064 return;
2065 }
2066 for (i=0; i<srcSize; i++) {
2067 if (gotLevels[i]!=levels2[i]) {
2068 log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n",
2069 i, src[i], gotLevels[i], levels2[i]);
2070 }
2071 }
2072
2073 /* check handling of whitespace before end of paragraph separator when
2074 * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B
2075 */
2076 u_memset(src, 0x0020, MAXLEN);
2077 srcSize = 5;
2078 ubidi_orderParagraphsLTR(pBidi, TRUE);
2079 for (i=0x001c; i<=0x0020; i+=(0x0020-0x001c)) {
2080 src[4]=(UChar)i; /* with and without terminating B */
2081 for (j=0x0041; j<=0x05d0; j+=(0x05d0-0x0041)) {
2082 src[0]=(UChar)j; /* leading 'A' or Alef */
2083 for (gotLevel=4; gotLevel<=5; gotLevel++) {
2084 /* test even and odd paraLevel */
2085 ubidi_setPara(pBidi, src, srcSize, gotLevel, NULL, &errorCode);
2086 gotLevels=ubidi_getLevels(pBidi, &errorCode);
2087 for (k=1; k<=3; k++) {
2088 if (gotLevels[k]!=gotLevel) {
2089 log_err("Checking trailing spaces: for leading_char=%04x, "
2090 "last_char=%04x, index=%d, level=%d, expected=%d\n",
2091 src[0], src[4], k, gotLevels[k], gotLevel);
2092 }
2093 }
2094 }
2095 }
2096 }
2097
2098 /* check default orientation when inverse bidi and paragraph starts
2099 * with LTR strong char and ends with RTL strong char, with and without
2100 * a terminating B
2101 */
2102 ubidi_setReorderingMode(pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
2103 srcLen = u_unescape("abc \\u05d2\\u05d1\n", src, MAXLEN);
2104 ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
2105 destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
2106 srcLen = u_unescape("\\u05d1\\u05d2 abc\n", src, MAXLEN);
2107 if (memcmp(src, dest, destLen * sizeof(UChar))) {
2108 log_err("\nInvalid output #0, should be '%s', got '%s'\n",
2109 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
2110 }
2111 srcLen = u_unescape("abc \\u05d2\\u05d1", src, MAXLEN);
2112 ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
2113 destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
2114 srcLen = u_unescape("\\u05d1\\u05d2 abc", src, MAXLEN);
2115 if (memcmp(src, dest, destLen * sizeof(UChar))) {
2116 log_err("\nInvalid output #1, should be '%s', got '%s'\n",
2117 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
2118 }
2119
2120 /* check multiple paragraphs together with explicit levels
2121 */
2122 ubidi_setReorderingMode(pBidi, UBIDI_REORDER_DEFAULT);
2123 srcLen = u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src, MAXLEN);
2124 ubidi_setPara(pBidi, src, srcLen, UBIDI_LTR, myLevels, &errorCode);
2125 destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
2126 srcLen = u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src, MAXLEN);
2127 if (memcmp(src, dest, destLen * sizeof(UChar))) {
2128 log_err("\nInvalid output #2, should be '%s', got '%s'\n",
2129 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
2130 }
2131 count = ubidi_countParagraphs(pBidi);
2132 if (count != 2) {
2133 log_err("\nInvalid number of paras, should be 2, got %d\n", count);
2134 }
2135
2136 ubidi_close(pLine);
2137 ubidi_close(pBidi);
2138 log_verbose("\nExiting TestMultipleParagraphs\n\n");
2139
2140 /* check levels in multiple paragraphs with default para level
2141 */
2142 pBidi = ubidi_open();
2143 errorCode = U_ZERO_ERROR;
2144 ubidi_setPara(pBidi, multiparaTestString, UPRV_LENGTHOF(multiparaTestString),
2145 UBIDI_DEFAULT_LTR, NULL, &errorCode);
2146 if (U_FAILURE(errorCode)) {
2147 log_err("ubidi_setPara failed for multiparaTestString\n");
2148 ubidi_close(pBidi);
2149 return;
2150 }
2151 gotLevels = ubidi_getLevels(pBidi, &errorCode);
2152 if (U_FAILURE(errorCode)) {
2153 log_err("ubidi_getLevels failed for multiparaTestString\n");
2154 ubidi_close(pBidi);
2155 return;
2156 }
2157 for (i = 0; i < UPRV_LENGTHOF(multiparaTestString); i++) {
2158 if (gotLevels[i] != multiparaTestLevels[i]) {
2159 log_err("Error on level for multiparaTestString at index %d, "
2160 "expected=%d, actual=%d\n",
2161 i, multiparaTestLevels[i], gotLevels[i]);
2162 }
2163 }
2164 ubidi_close(pBidi);
2165
2166 }
2167
2168
2169 /* inverse BiDi ------------------------------------------------------------- */
2170
2171 static int countRoundtrips=0, countNonRoundtrips=0;
2172
2173 #define STRING_TEST_CASE(s) { (s), UPRV_LENGTHOF(s) }
2174
2175 static void
testInverse(void)2176 testInverse(void) {
2177 static const UChar
2178 string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 },
2179 string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 },
2180 string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 },
2181 string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 },
2182 string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 };
2183
2184 static const struct {
2185 const UChar *s;
2186 int32_t length;
2187 } testCases[]={
2188 STRING_TEST_CASE(string0),
2189 STRING_TEST_CASE(string1),
2190 STRING_TEST_CASE(string2),
2191 STRING_TEST_CASE(string3),
2192 STRING_TEST_CASE(string4)
2193 };
2194
2195 UBiDi *pBiDi;
2196 UErrorCode errorCode;
2197 int i;
2198
2199 log_verbose("\nEntering TestInverse\n\n");
2200 pBiDi=ubidi_open();
2201 if(pBiDi==NULL) {
2202 log_err("unable to open a UBiDi object (out of memory)\n");
2203 return;
2204 }
2205
2206 log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", UPRV_LENGTHOF(testCases));
2207 for(i=0; i<UPRV_LENGTHOF(testCases); ++i) {
2208 log_verbose("Testing case %d\n", i);
2209 errorCode=U_ZERO_ERROR;
2210 _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode);
2211 }
2212
2213 log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", UPRV_LENGTHOF(testCases));
2214 for(i=0; i<UPRV_LENGTHOF(testCases); ++i) {
2215 log_verbose("Testing case %d\n", i);
2216 errorCode=U_ZERO_ERROR;
2217 _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode);
2218 }
2219
2220 _testManyInverseBidi(pBiDi, 0);
2221 _testManyInverseBidi(pBiDi, 1);
2222
2223 ubidi_close(pBiDi);
2224
2225 log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips);
2226
2227 _testWriteReverse();
2228
2229 _testManyAddedPoints();
2230
2231 _testMisc();
2232
2233 log_verbose("\nExiting TestInverse\n\n");
2234 }
2235
2236 #define COUNT_REPEAT_SEGMENTS 6
2237
2238 static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={
2239 { 0x61, 0x62 }, /* L */
2240 { 0x5d0, 0x5d1 }, /* R */
2241 { 0x627, 0x628 }, /* AL */
2242 { 0x31, 0x32 }, /* EN */
2243 { 0x661, 0x662 }, /* AN */
2244 { 0x20, 0x20 } /* WS (N) */
2245 };
2246
2247 static void
_testManyInverseBidi(UBiDi * pBiDi,UBiDiLevel direction)2248 _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction) {
2249 UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
2250 int i, j, k;
2251 UErrorCode errorCode;
2252
2253 log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n",
2254 direction==0 ? 'L' : 'R');
2255 for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) {
2256 text[0]=repeatSegments[i][0];
2257 text[1]=repeatSegments[i][1];
2258 for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) {
2259 text[3]=repeatSegments[j][0];
2260 text[4]=repeatSegments[j][1];
2261 for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) {
2262 text[6]=repeatSegments[k][0];
2263 text[7]=repeatSegments[k][1];
2264
2265 errorCode=U_ZERO_ERROR;
2266 log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i, j, k);
2267 _testInverseBidi(pBiDi, text, 8, direction, &errorCode);
2268 }
2269 }
2270 }
2271 }
2272
2273 static void
_testInverseBidi(UBiDi * pBiDi,const UChar * src,int32_t srcLength,UBiDiLevel direction,UErrorCode * pErrorCode)2274 _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
2275 UBiDiLevel direction, UErrorCode *pErrorCode) {
2276 UChar visualLTR[MAXLEN], logicalDest[MAXLEN], visualDest[MAXLEN];
2277 int32_t ltrLength, logicalLength, visualLength;
2278
2279 if(direction==0) {
2280 log_verbose("inverse Bidi: testInverse(L)\n");
2281
2282 /* convert visual to logical */
2283 ubidi_setInverse(pBiDi, TRUE);
2284 if (!ubidi_isInverse(pBiDi)) {
2285 log_err("Error while doing ubidi_setInverse(TRUE)\n");
2286 }
2287 ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode);
2288 if (src != ubidi_getText(pBiDi)) {
2289 log_err("Wrong value returned by ubidi_getText\n");
2290 }
2291 logicalLength=ubidi_writeReordered(pBiDi, logicalDest, UPRV_LENGTHOF(logicalDest),
2292 UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
2293 log_verbose(" v ");
2294 printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode));
2295 log_verbose("\n");
2296
2297 /* convert back to visual LTR */
2298 ubidi_setInverse(pBiDi, FALSE);
2299 if (ubidi_isInverse(pBiDi)) {
2300 log_err("Error while doing ubidi_setInverse(FALSE)\n");
2301 }
2302 ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
2303 visualLength=ubidi_writeReordered(pBiDi, visualDest, UPRV_LENGTHOF(visualDest),
2304 UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode);
2305 } else {
2306 log_verbose("inverse Bidi: testInverse(R)\n");
2307
2308 /* reverse visual from RTL to LTR */
2309 ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, UPRV_LENGTHOF(visualLTR), 0, pErrorCode);
2310 log_verbose(" vr");
2311 printUnicode(src, srcLength, NULL);
2312 log_verbose("\n");
2313
2314 /* convert visual RTL to logical */
2315 ubidi_setInverse(pBiDi, TRUE);
2316 ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode);
2317 logicalLength=ubidi_writeReordered(pBiDi, logicalDest, UPRV_LENGTHOF(logicalDest),
2318 UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
2319 log_verbose(" vl");
2320 printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode));
2321 log_verbose("\n");
2322
2323 /* convert back to visual RTL */
2324 ubidi_setInverse(pBiDi, FALSE);
2325 ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
2326 visualLength=ubidi_writeReordered(pBiDi, visualDest, UPRV_LENGTHOF(visualDest),
2327 UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode);
2328 }
2329 log_verbose(" l ");
2330 printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode));
2331 log_verbose("\n");
2332 log_verbose(" v ");
2333 printUnicode(visualDest, visualLength, NULL);
2334 log_verbose("\n");
2335
2336 /* check and print results */
2337 if(U_FAILURE(*pErrorCode)) {
2338 log_err("inverse BiDi: *** error %s\n"
2339 " turn on verbose mode to see details\n", u_errorName(*pErrorCode));
2340 } else if(srcLength==visualLength && memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) {
2341 ++countRoundtrips;
2342 log_verbose(" + roundtripped\n");
2343 } else {
2344 ++countNonRoundtrips;
2345 log_verbose(" * did not roundtrip\n");
2346 log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n"
2347 " turn on verbose mode to see details\n");
2348 }
2349 }
2350
2351 static void
_testWriteReverse(void)2352 _testWriteReverse(void) {
2353 /* U+064e and U+0650 are combining marks (Mn) */
2354 static const UChar forward[]={
2355 0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29
2356 }, reverseKeepCombining[]={
2357 0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f
2358 }, reverseRemoveControlsKeepCombiningDoMirror[]={
2359 0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650
2360 };
2361 UChar reverse[10];
2362 UErrorCode errorCode;
2363 int32_t length;
2364
2365 /* test ubidi_writeReverse() with "interesting" options */
2366 errorCode=U_ZERO_ERROR;
2367 length=ubidi_writeReverse(forward, UPRV_LENGTHOF(forward),
2368 reverse, UPRV_LENGTHOF(reverse),
2369 UBIDI_KEEP_BASE_COMBINING,
2370 &errorCode);
2371 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(reverseKeepCombining) || memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) {
2372 log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n",
2373 length, UPRV_LENGTHOF(reverseKeepCombining), u_errorName(errorCode));
2374 }
2375
2376 memset(reverse, 0xa5, UPRV_LENGTHOF(reverse)*U_SIZEOF_UCHAR);
2377 errorCode=U_ZERO_ERROR;
2378 length=ubidi_writeReverse(forward, UPRV_LENGTHOF(forward),
2379 reverse, UPRV_LENGTHOF(reverse),
2380 UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING,
2381 &errorCode);
2382 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) {
2383 log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n"
2384 " length=%d (should be %d), error code %s\n",
2385 length, UPRV_LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode));
2386 }
2387 }
2388
_testManyAddedPoints(void)2389 static void _testManyAddedPoints(void) {
2390 UErrorCode errorCode = U_ZERO_ERROR;
2391 UBiDi *bidi = ubidi_open();
2392 UChar text[90], dest[MAXLEN], expected[120];
2393 int destLen, i;
2394 for (i = 0; i < UPRV_LENGTHOF(text); i+=3) {
2395 text[i] = 0x0061; /* 'a' */
2396 text[i+1] = 0x05d0;
2397 text[i+2] = 0x0033; /* '3' */
2398 }
2399 ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
2400 ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
2401 ubidi_setPara(bidi, text, UPRV_LENGTHOF(text), UBIDI_LTR, NULL, &errorCode);
2402 destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
2403 for (i = 0; i < UPRV_LENGTHOF(expected); i+=4) {
2404 expected[i] = 0x0061; /* 'a' */
2405 expected[i+1] = 0x05d0;
2406 expected[i+2] = 0x200e;
2407 expected[i+3] = 0x0033; /* '3' */
2408 }
2409 if (memcmp(dest, expected, destLen * sizeof(UChar))) {
2410 log_err("\nInvalid output with many added points, "
2411 "expected '%s', got '%s'\n",
2412 aescstrdup(expected, UPRV_LENGTHOF(expected)),
2413 aescstrdup(dest, destLen));
2414 }
2415 ubidi_close(bidi);
2416 }
2417
_testMisc(void)2418 static void _testMisc(void) {
2419 UErrorCode errorCode = U_ZERO_ERROR;
2420 UBiDi *bidi = ubidi_open();
2421 UChar src[3], dest[MAXLEN], expected[5];
2422 int destLen;
2423 ubidi_setInverse(bidi, TRUE);
2424 src[0] = src[1] = src[2] = 0x0020;
2425 ubidi_setPara(bidi, src, UPRV_LENGTHOF(src), UBIDI_RTL, NULL, &errorCode);
2426 destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
2427 UBIDI_OUTPUT_REVERSE | UBIDI_INSERT_LRM_FOR_NUMERIC,
2428 &errorCode);
2429 u_unescape("\\u200f \\u200f", expected, 5);
2430 if (memcmp(dest, expected, destLen * sizeof(UChar))) {
2431 log_err("\nInvalid output with RLM at both sides, "
2432 "expected '%s', got '%s'\n",
2433 aescstrdup(expected, UPRV_LENGTHOF(expected)),
2434 aescstrdup(dest, destLen));
2435 }
2436 ubidi_close(bidi);
2437 }
2438
2439 /* arabic shaping ----------------------------------------------------------- */
2440
2441 static void
doArabicShapingTest(void)2442 doArabicShapingTest(void) {
2443 static const UChar
2444 source[]={
2445 0x31, /* en:1 */
2446 0x627, /* arabic:alef */
2447 0x32, /* en:2 */
2448 0x6f3, /* an:3 */
2449 0x61, /* latin:a */
2450 0x34, /* en:4 */
2451 0
2452 }, en2an[]={
2453 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0
2454 }, an2en[]={
2455 0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0
2456 }, logical_alen2an_init_lr[]={
2457 0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0
2458 }, logical_alen2an_init_al[]={
2459 0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0
2460 }, reverse_alen2an_init_lr[]={
2461 0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0
2462 }, reverse_alen2an_init_al[]={
2463 0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0
2464 }, lamalef[]={
2465 0xfefb, 0
2466 };
2467 UChar dest[8];
2468 UErrorCode errorCode;
2469 int32_t length;
2470
2471 /* test number shaping */
2472
2473 /* european->arabic */
2474 errorCode=U_ZERO_ERROR;
2475 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2476 dest, UPRV_LENGTHOF(dest),
2477 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2478 &errorCode);
2479 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) {
2480 log_err("failure in u_shapeArabic(en2an)\n");
2481 }
2482
2483 /* arabic->european */
2484 errorCode=U_ZERO_ERROR;
2485 length=u_shapeArabic(source, -1,
2486 dest, UPRV_LENGTHOF(dest),
2487 U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
2488 &errorCode);
2489 if(U_FAILURE(errorCode) || length!=u_strlen(source) || memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) {
2490 log_err("failure in u_shapeArabic(an2en)\n");
2491 }
2492
2493 /* european->arabic with context, logical order, initial state not AL */
2494 errorCode=U_ZERO_ERROR;
2495 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2496 dest, UPRV_LENGTHOF(dest),
2497 U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN,
2498 &errorCode);
2499 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
2500 log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n");
2501 }
2502
2503 /* european->arabic with context, logical order, initial state AL */
2504 errorCode=U_ZERO_ERROR;
2505 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2506 dest, UPRV_LENGTHOF(dest),
2507 U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
2508 &errorCode);
2509 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
2510 log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n");
2511 }
2512
2513 /* european->arabic with context, reverse order, initial state not AL */
2514 errorCode=U_ZERO_ERROR;
2515 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2516 dest, UPRV_LENGTHOF(dest),
2517 U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2518 &errorCode);
2519 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
2520 log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n");
2521 }
2522
2523 /* european->arabic with context, reverse order, initial state AL */
2524 errorCode=U_ZERO_ERROR;
2525 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2526 dest, UPRV_LENGTHOF(dest),
2527 U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2528 &errorCode);
2529 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
2530 log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n");
2531 }
2532
2533 /* test noop */
2534 errorCode=U_ZERO_ERROR;
2535 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2536 dest, UPRV_LENGTHOF(dest),
2537 0,
2538 &errorCode);
2539 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) {
2540 log_err("failure in u_shapeArabic(noop)\n");
2541 }
2542
2543 errorCode=U_ZERO_ERROR;
2544 length=u_shapeArabic(source, 0,
2545 dest, UPRV_LENGTHOF(dest),
2546 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2547 &errorCode);
2548 if(U_FAILURE(errorCode) || length!=0) {
2549 log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), UPRV_LENGTHOF(source));
2550 }
2551
2552 /* preflight digit shaping */
2553 errorCode=U_ZERO_ERROR;
2554 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2555 NULL, 0,
2556 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2557 &errorCode);
2558 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=UPRV_LENGTHOF(source)) {
2559 log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n",
2560 length, u_errorName(errorCode), UPRV_LENGTHOF(source));
2561 }
2562
2563 /* test illegal arguments */
2564 errorCode=U_ZERO_ERROR;
2565 length=u_shapeArabic(NULL, UPRV_LENGTHOF(source),
2566 dest, UPRV_LENGTHOF(dest),
2567 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2568 &errorCode);
2569 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2570 log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2571 }
2572
2573 errorCode=U_ZERO_ERROR;
2574 length=u_shapeArabic(source, -2,
2575 dest, UPRV_LENGTHOF(dest),
2576 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2577 &errorCode);
2578 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2579 log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2580 }
2581
2582 errorCode=U_ZERO_ERROR;
2583 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2584 NULL, UPRV_LENGTHOF(dest),
2585 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2586 &errorCode);
2587 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2588 log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2589 }
2590
2591 errorCode=U_ZERO_ERROR;
2592 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2593 dest, -1,
2594 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2595 &errorCode);
2596 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2597 log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2598 }
2599
2600 errorCode=U_ZERO_ERROR;
2601 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2602 dest, UPRV_LENGTHOF(dest),
2603 U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN,
2604 &errorCode);
2605 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2606 log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2607 }
2608
2609 errorCode=U_ZERO_ERROR;
2610 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2611 dest, UPRV_LENGTHOF(dest),
2612 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED,
2613 &errorCode);
2614 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2615 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2616 }
2617
2618 errorCode=U_ZERO_ERROR;
2619 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2620 (UChar *)(source+2), UPRV_LENGTHOF(dest), /* overlap source and destination */
2621 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
2622 &errorCode);
2623 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2624 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
2625 }
2626
2627 errorCode=U_ZERO_ERROR;
2628 length=u_shapeArabic(lamalef, UPRV_LENGTHOF(lamalef),
2629 dest, UPRV_LENGTHOF(dest),
2630 U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2631 &errorCode);
2632 if(U_FAILURE(errorCode) || length == UPRV_LENGTHOF(lamalef)) {
2633 log_err("failure in u_shapeArabic(U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR)\n");
2634 log_err("returned %s instead of U_ZERO_ERROR or returned length %d instead of 3\n", u_errorName(errorCode), length);
2635 }
2636 }
2637
2638 static void
doLamAlefSpecialVLTRArabicShapingTest(void)2639 doLamAlefSpecialVLTRArabicShapingTest(void) {
2640 static const UChar
2641 source[]={
2642 /*a*/ 0x20 ,0x646,0x622,0x644,0x627,0x20,
2643 /*b*/ 0x646,0x623,0x64E,0x644,0x627,0x20,
2644 /*c*/ 0x646,0x627,0x670,0x644,0x627,0x20,
2645 /*d*/ 0x646,0x622,0x653,0x644,0x627,0x20,
2646 /*e*/ 0x646,0x625,0x655,0x644,0x627,0x20,
2647 /*f*/ 0x646,0x622,0x654,0x644,0x627,0x20,
2648 /*g*/ 0xFEFC,0x639
2649 }, shape_near[]={
2650 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
2651 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
2652 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
2653 0xfefc,0xfecb
2654 }, shape_at_end[]={
2655 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
2656 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
2657 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20
2658 }, shape_at_begin[]={
2659 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
2660 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
2661 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2662 }, shape_grow_shrink[]={
2663 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
2664 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
2665 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2666 }, shape_excepttashkeel_near[]={
2667 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
2668 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
2669 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
2670 0xfefc,0xfecb
2671 }, shape_excepttashkeel_at_end[]={
2672 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
2673 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
2674 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,
2675 0x20,0x20,0x20
2676 }, shape_excepttashkeel_at_begin[]={
2677 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
2678 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
2679 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2680 }, shape_excepttashkeel_grow_shrink[]={
2681 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
2682 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
2683 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
2684 };
2685
2686 UChar dest[38];
2687 UErrorCode errorCode;
2688 int32_t length;
2689
2690 errorCode=U_ZERO_ERROR;
2691
2692 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2693 dest, UPRV_LENGTHOF(dest),
2694 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2695 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2696 &errorCode);
2697
2698 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
2699 log_err("failure in u_shapeArabic(LAMALEF shape_near)\n");
2700 }
2701
2702 errorCode=U_ZERO_ERROR;
2703
2704 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2705 dest, UPRV_LENGTHOF(dest),
2706 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
2707 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2708 &errorCode);
2709
2710 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_at_end) || memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) {
2711 log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n");
2712 }
2713
2714 errorCode=U_ZERO_ERROR;
2715
2716 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2717 dest, UPRV_LENGTHOF(dest),
2718 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
2719 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2720 &errorCode);
2721
2722 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_at_begin) || memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
2723 log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n");
2724 }
2725
2726 errorCode=U_ZERO_ERROR;
2727
2728 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2729 dest, UPRV_LENGTHOF(dest),
2730 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
2731 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2732 &errorCode);
2733
2734 if(U_FAILURE(errorCode) || memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
2735 log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n");
2736 }
2737
2738 /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */
2739
2740 errorCode=U_ZERO_ERROR;
2741
2742 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2743 dest, UPRV_LENGTHOF(dest),
2744 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2745 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2746 &errorCode);
2747
2748 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
2749 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n");
2750 }
2751
2752 errorCode=U_ZERO_ERROR;
2753
2754 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2755 dest, UPRV_LENGTHOF(dest),
2756 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
2757 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2758 &errorCode);
2759
2760 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_at_end) || memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) {
2761 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n");
2762 }
2763
2764 errorCode=U_ZERO_ERROR;
2765
2766 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2767 dest, UPRV_LENGTHOF(dest),
2768 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
2769 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2770 &errorCode);
2771
2772 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_at_begin) || memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) {
2773 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n");
2774 }
2775
2776 errorCode=U_ZERO_ERROR;
2777
2778 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2779 dest, UPRV_LENGTHOF(dest),
2780 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK|
2781 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2782 &errorCode);
2783
2784 if(U_FAILURE(errorCode) || memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
2785 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n");
2786 }
2787 }
2788
2789 static void
doTashkeelSpecialVLTRArabicShapingTest(void)2790 doTashkeelSpecialVLTRArabicShapingTest(void) {
2791 static const UChar
2792 source[]={
2793 0x64A,0x628,0x631,0x639,0x20,
2794 0x64A,0x628,0x651,0x631,0x64E,0x639,0x20,
2795 0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20,
2796 0x628,0x670,0x631,0x670,0x639,0x20,
2797 0x628,0x653,0x631,0x653,0x639,0x20,
2798 0x628,0x654,0x631,0x654,0x639,0x20,
2799 0x628,0x655,0x631,0x655,0x639,0x20,
2800 }, shape_near[]={
2801 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb,
2802 0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,
2803 0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,
2804 0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
2805 }, shape_excepttashkeel_near[]={
2806 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20,
2807 0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb,
2808 0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20,
2809 0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
2810 };
2811
2812 UChar dest[43];
2813 UErrorCode errorCode;
2814 int32_t length;
2815
2816 errorCode=U_ZERO_ERROR;
2817
2818 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2819 dest, UPRV_LENGTHOF(dest),
2820 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2821 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2822 &errorCode);
2823
2824 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
2825 log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n");
2826 }
2827
2828 errorCode=U_ZERO_ERROR;
2829
2830 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2831 dest, UPRV_LENGTHOF(dest),
2832 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2833 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2834 &errorCode);
2835
2836 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
2837 log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n");
2838 }
2839 }
2840
2841 static void
doLOGICALArabicDeShapingTest(void)2842 doLOGICALArabicDeShapingTest(void) {
2843 static const UChar
2844 source[]={
2845 0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020,
2846 0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4,
2847 0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020
2848 }, unshape_near[]={
2849 0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627,
2850 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
2851 0x629,0x20,0x20,0x20,0x20
2852 }, unshape_at_end[]={
2853 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
2854 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
2855 0x644,0x62d,0x631,0x629,0x20
2856 }, unshape_at_begin[]={
2857 0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20,
2858 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
2859 0x629,0x20,0x20,0x20,0x20
2860 }, unshape_grow_shrink[]={
2861 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
2862 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
2863 0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20
2864 };
2865
2866 UChar dest[36];
2867 UErrorCode errorCode;
2868 int32_t length;
2869
2870 errorCode=U_ZERO_ERROR;
2871
2872 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2873 dest, UPRV_LENGTHOF(dest),
2874 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
2875 U_SHAPE_TEXT_DIRECTION_LOGICAL,
2876 &errorCode);
2877
2878 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_near) || memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) {
2879 log_err("failure in u_shapeArabic(unshape_near)\n");
2880 }
2881
2882 errorCode=U_ZERO_ERROR;
2883
2884 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2885 dest, UPRV_LENGTHOF(dest),
2886 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
2887 U_SHAPE_TEXT_DIRECTION_LOGICAL,
2888 &errorCode);
2889
2890 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_at_end) || memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) {
2891 log_err("failure in u_shapeArabic(unshape_at_end)\n");
2892 }
2893
2894 errorCode=U_ZERO_ERROR;
2895
2896 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2897 dest, UPRV_LENGTHOF(dest),
2898 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
2899 U_SHAPE_TEXT_DIRECTION_LOGICAL,
2900 &errorCode);
2901
2902 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_at_begin) || memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
2903 log_err("failure in u_shapeArabic(unshape_at_begin)\n");
2904 }
2905
2906 errorCode=U_ZERO_ERROR;
2907
2908 length=u_shapeArabic(source, UPRV_LENGTHOF(source),
2909 dest, UPRV_LENGTHOF(dest),
2910 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
2911 U_SHAPE_TEXT_DIRECTION_LOGICAL,
2912 &errorCode);
2913
2914 if(U_FAILURE(errorCode) || memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
2915 log_err("failure in u_shapeArabic(unshape_grow_shrink)\n");
2916 }
2917
2918 }
2919
2920 static void
doTailTest(void)2921 doTailTest(void) {
2922 static const UChar src[] = { 0x0020, 0x0633, 0 };
2923 static const UChar dst_old[] = { 0xFEB1, 0x200B,0 };
2924 static const UChar dst_new[] = { 0xFEB1, 0xFE73,0 };
2925 UChar dst[3] = { 0x0000, 0x0000,0 };
2926 int32_t length;
2927 UErrorCode status;
2928
2929 log_verbose("SRC: U+%04X U+%04X\n", src[0],src[1]);
2930
2931 log_verbose("Trying old tail\n");
2932 status = U_ZERO_ERROR;
2933 length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
2934 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR, &status);
2935 if(U_FAILURE(status)) {
2936 log_err("Fail: status %s\n", u_errorName(status));
2937 } else if(length!=2) {
2938 log_err("Fail: len %d expected 3\n", length);
2939 } else if(u_strncmp(dst,dst_old,UPRV_LENGTHOF(dst))) {
2940 log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
2941 dst[0],dst[1],dst_old[0],dst_old[1]);
2942 } else {
2943 log_verbose("OK: U+%04X U+%04X len %d err %s\n",
2944 dst[0],dst[1],length,u_errorName(status));
2945 }
2946
2947
2948 log_verbose("Trying new tail\n");
2949 status = U_ZERO_ERROR;
2950 length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
2951 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR|U_SHAPE_TAIL_NEW_UNICODE, &status);
2952 if(U_FAILURE(status)) {
2953 log_err("Fail: status %s\n", u_errorName(status));
2954 } else if(length!=2) {
2955 log_err("Fail: len %d expected 3\n", length);
2956 } else if(u_strncmp(dst,dst_new,UPRV_LENGTHOF(dst))) {
2957 log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
2958 dst[0],dst[1],dst_new[0],dst_new[1]);
2959 } else {
2960 log_verbose("OK: U+%04X U+%04X len %d err %s\n",
2961 dst[0],dst[1],length,u_errorName(status));
2962 }
2963 }
2964
2965 static void
doArabicShapingTestForBug5421(void)2966 doArabicShapingTestForBug5421(void) {
2967 static const UChar
2968 persian_letters_source[]={
2969 0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020
2970 }, persian_letters[]={
2971 0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020
2972 }, tashkeel_aggregation_source[]={
2973 0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020,
2974 0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020
2975 }, tashkeel_aggregation[]={
2976 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3,
2977 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020
2978 }, untouched_presentation_source[]={
2979 0x0020 ,0x0627, 0xfe90,0x0020
2980 }, untouched_presentation[]={
2981 0x0020,0xfe8D, 0xfe90,0x0020
2982 }, untouched_presentation_r_source[]={
2983 0x0020 ,0xfe90, 0x0627, 0x0020
2984 }, untouched_presentation_r[]={
2985 0x0020, 0xfe90,0xfe8D,0x0020
2986 };
2987
2988 UChar dest[38];
2989 UErrorCode errorCode;
2990 int32_t length;
2991
2992 errorCode=U_ZERO_ERROR;
2993
2994 length=u_shapeArabic(persian_letters_source, UPRV_LENGTHOF(persian_letters_source),
2995 dest, UPRV_LENGTHOF(dest),
2996 U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
2997 &errorCode);
2998
2999 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(persian_letters) || memcmp(dest, persian_letters, length*U_SIZEOF_UCHAR)!=0) {
3000 log_err("failure in u_shapeArabic(persian_letters)\n");
3001 }
3002
3003 errorCode=U_ZERO_ERROR;
3004
3005 length=u_shapeArabic(tashkeel_aggregation_source, UPRV_LENGTHOF(tashkeel_aggregation_source),
3006 dest, UPRV_LENGTHOF(dest),
3007 U_SHAPE_AGGREGATE_TASHKEEL|U_SHAPE_PRESERVE_PRESENTATION|
3008 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
3009 &errorCode);
3010
3011 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(tashkeel_aggregation) || memcmp(dest, tashkeel_aggregation, length*U_SIZEOF_UCHAR)!=0) {
3012 log_err("failure in u_shapeArabic(tashkeel_aggregation)\n");
3013 }
3014
3015 errorCode=U_ZERO_ERROR;
3016
3017 length=u_shapeArabic(untouched_presentation_source, UPRV_LENGTHOF(untouched_presentation_source),
3018 dest, UPRV_LENGTHOF(dest),
3019 U_SHAPE_PRESERVE_PRESENTATION|
3020 U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
3021 &errorCode);
3022
3023 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(untouched_presentation) || memcmp(dest, untouched_presentation, length*U_SIZEOF_UCHAR)!=0) {
3024 log_err("failure in u_shapeArabic(untouched_presentation)\n");
3025 }
3026
3027 errorCode=U_ZERO_ERROR;
3028
3029 length=u_shapeArabic(untouched_presentation_r_source, UPRV_LENGTHOF(untouched_presentation_r_source),
3030 dest, UPRV_LENGTHOF(dest),
3031 U_SHAPE_PRESERVE_PRESENTATION|
3032 U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_LOGICAL,
3033 &errorCode);
3034
3035 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(untouched_presentation_r) || memcmp(dest, untouched_presentation_r, length*U_SIZEOF_UCHAR)!=0) {
3036 log_err("failure in u_shapeArabic(untouched_presentation_r)\n");
3037 }
3038 }
3039
3040 static void
doArabicShapingTestForBug8703(void)3041 doArabicShapingTestForBug8703(void) {
3042 static const UChar
3043 letters_source1[]={
3044 0x0634,0x0651,0x0645,0x0652,0x0633
3045 }, letters_source2[]={
3046 0x0634,0x0651,0x0645,0x0652,0x0633
3047 }, letters_source3[]={
3048 0x0634,0x0651,0x0645,0x0652,0x0633
3049 }, letters_source4[]={
3050 0x0634,0x0651,0x0645,0x0652,0x0633
3051 }, letters_source5[]={
3052 0x0633,0x0652,0x0645,0x0651,0x0634
3053 }, letters_source6[]={
3054 0x0633,0x0652,0x0645,0x0651,0x0634
3055 }, letters_source7[]={
3056 0x0633,0x0652,0x0645,0x0651,0x0634
3057 }, letters_source8[]={
3058 0x0633,0x0652,0x0645,0x0651,0x0634
3059 }, letters_dest1[]={
3060 0x0020,0xFEB7,0xFE7D,0xFEE4,0xFEB2
3061 }, letters_dest2[]={
3062 0xFEB7,0xFE7D,0xFEE4,0xFEB2,0x0020
3063 }, letters_dest3[]={
3064 0xFEB7,0xFE7D,0xFEE4,0xFEB2
3065 }, letters_dest4[]={
3066 0xFEB7,0xFE7D,0xFEE4,0x0640,0xFEB2
3067 }, letters_dest5[]={
3068 0x0020,0xFEB2,0xFEE4,0xFE7D,0xFEB7
3069 }, letters_dest6[]={
3070 0xFEB2,0xFEE4,0xFE7D,0xFEB7,0x0020
3071 }, letters_dest7[]={
3072 0xFEB2,0xFEE4,0xFE7D,0xFEB7
3073 }, letters_dest8[]={
3074 0xFEB2,0x0640,0xFEE4,0xFE7D,0xFEB7
3075 };
3076
3077 UChar dest[20];
3078 UErrorCode errorCode;
3079 int32_t length;
3080
3081 errorCode=U_ZERO_ERROR;
3082
3083 length=u_shapeArabic(letters_source1, UPRV_LENGTHOF(letters_source1),
3084 dest, UPRV_LENGTHOF(dest),
3085 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
3086 &errorCode);
3087
3088 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) {
3089 log_err("failure in u_shapeArabic(letters_source1)\n");
3090 }
3091
3092 errorCode=U_ZERO_ERROR;
3093
3094 length=u_shapeArabic(letters_source2, UPRV_LENGTHOF(letters_source2),
3095 dest, UPRV_LENGTHOF(dest),
3096 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
3097 &errorCode);
3098
3099 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) {
3100 log_err("failure in u_shapeArabic(letters_source2)\n");
3101 }
3102
3103 errorCode=U_ZERO_ERROR;
3104
3105 length=u_shapeArabic(letters_source3, UPRV_LENGTHOF(letters_source3),
3106 dest, UPRV_LENGTHOF(dest),
3107 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
3108 &errorCode);
3109
3110 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) {
3111 log_err("failure in u_shapeArabic(letters_source3)\n");
3112 }
3113
3114 errorCode=U_ZERO_ERROR;
3115
3116 length=u_shapeArabic(letters_source4, UPRV_LENGTHOF(letters_source4),
3117 dest, UPRV_LENGTHOF(dest),
3118 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
3119 &errorCode);
3120
3121 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) {
3122 log_err("failure in u_shapeArabic(letters_source4)\n");
3123 }
3124
3125 errorCode=U_ZERO_ERROR;
3126
3127 length=u_shapeArabic(letters_source5, UPRV_LENGTHOF(letters_source5),
3128 dest, UPRV_LENGTHOF(dest),
3129 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
3130 &errorCode);
3131
3132 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) {
3133 log_err("failure in u_shapeArabic(letters_source5)\n");
3134 }
3135
3136 errorCode=U_ZERO_ERROR;
3137
3138 length=u_shapeArabic(letters_source6, UPRV_LENGTHOF(letters_source6),
3139 dest, UPRV_LENGTHOF(dest),
3140 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
3141 &errorCode);
3142
3143 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) {
3144 log_err("failure in u_shapeArabic(letters_source6)\n");
3145 }
3146
3147 errorCode=U_ZERO_ERROR;
3148
3149 length=u_shapeArabic(letters_source7, UPRV_LENGTHOF(letters_source7),
3150 dest, UPRV_LENGTHOF(dest),
3151 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
3152 &errorCode);
3153
3154 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest7) || memcmp(dest, letters_dest7, length*U_SIZEOF_UCHAR)!=0) {
3155 log_err("failure in u_shapeArabic(letters_source7)\n");
3156 }
3157
3158 errorCode=U_ZERO_ERROR;
3159
3160 length=u_shapeArabic(letters_source8, UPRV_LENGTHOF(letters_source8),
3161 dest, UPRV_LENGTHOF(dest),
3162 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
3163 &errorCode);
3164
3165 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest8) || memcmp(dest, letters_dest8, length*U_SIZEOF_UCHAR)!=0) {
3166 log_err("failure in u_shapeArabic(letters_source8)\n");
3167 }
3168 }
3169
3170 static void
doArabicShapingTestForBug9024(void)3171 doArabicShapingTestForBug9024(void) {
3172 static const UChar
3173 letters_source1[]={ /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
3174 0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
3175 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
3176 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
3177 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
3178 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
3179 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
3180 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
3181 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
3182 }, letters_source2[]={/* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
3183 0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
3184 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
3185 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
3186 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
3187 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
3188 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
3189 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
3190 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
3191 }, letters_source3[]={/* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
3192 0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
3193 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
3194 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
3195 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
3196 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
3197 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
3198 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
3199 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
3200 }, letters_source4[]={/* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
3201 0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
3202 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
3203 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
3204 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
3205 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
3206 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
3207 0xD83B, 0xDE39, 0xD83B, 0xDE3B
3208 }, letters_source5[]={/* Arabic mathematical Symbols - Tailed Symbols */
3209 0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
3210 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
3211 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
3212 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
3213 }, letters_source6[]={/* Arabic mathematical Symbols - Stretched Symbols with 06 range */
3214 0xD83B, 0xDE21, 0x0633, 0xD83B, 0xDE62, 0x0647
3215 }, letters_dest1[]={
3216 0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
3217 0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
3218 0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
3219 0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
3220 0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
3221 0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
3222 0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
3223 0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
3224 }, letters_dest2[]={
3225 0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
3226 0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
3227 0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
3228 0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
3229 0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
3230 0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
3231 0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
3232 0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
3233 }, letters_dest3[]={
3234 0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
3235 0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
3236 0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
3237 0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
3238 0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
3239 0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
3240 0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
3241 0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
3242 }, letters_dest4[]={
3243 0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
3244 0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
3245 0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
3246 0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
3247 0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
3248 0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
3249 0xD83B, 0xDE39, 0xD83B, 0xDE3B
3250 }, letters_dest5[]={
3251 0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
3252 0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
3253 0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
3254 0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
3255 }, letters_dest6[]={
3256 0xD83B, 0xDE21, 0xFEB1, 0xD83B, 0xDE62, 0xFEE9
3257 };
3258
3259 UChar dest[MAXLEN];
3260 UErrorCode errorCode;
3261 int32_t length;
3262
3263 errorCode=U_ZERO_ERROR;
3264
3265 length=u_shapeArabic(letters_source1, UPRV_LENGTHOF(letters_source1),
3266 dest, UPRV_LENGTHOF(dest),
3267 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
3268 &errorCode);
3269
3270 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) {
3271 log_err("failure in u_shapeArabic(letters_source1)\n");
3272 }
3273
3274 errorCode=U_ZERO_ERROR;
3275
3276 length=u_shapeArabic(letters_source2, UPRV_LENGTHOF(letters_source2),
3277 dest, UPRV_LENGTHOF(dest),
3278 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
3279 &errorCode);
3280
3281 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) {
3282 log_err("failure in u_shapeArabic(letters_source2)\n");
3283 }
3284
3285 errorCode=U_ZERO_ERROR;
3286
3287 length=u_shapeArabic(letters_source3, UPRV_LENGTHOF(letters_source3),
3288 dest, UPRV_LENGTHOF(dest),
3289 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
3290 &errorCode);
3291
3292 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) {
3293 log_err("failure in u_shapeArabic(letters_source3)\n");
3294 }
3295
3296 errorCode=U_ZERO_ERROR;
3297
3298 length=u_shapeArabic(letters_source4, UPRV_LENGTHOF(letters_source4),
3299 dest, UPRV_LENGTHOF(dest),
3300 U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
3301 &errorCode);
3302
3303 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) {
3304 log_err("failure in u_shapeArabic(letters_source4)\n");
3305 }
3306
3307 errorCode=U_ZERO_ERROR;
3308
3309 length=u_shapeArabic(letters_source5, UPRV_LENGTHOF(letters_source5),
3310 dest, UPRV_LENGTHOF(dest),
3311 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
3312 &errorCode);
3313
3314 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) {
3315 log_err("failure in u_shapeArabic(letters_source5)\n");
3316 }
3317
3318 errorCode=U_ZERO_ERROR;
3319
3320 length=u_shapeArabic(letters_source6, UPRV_LENGTHOF(letters_source6),
3321 dest, UPRV_LENGTHOF(dest),
3322 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
3323 &errorCode);
3324
3325 if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) {
3326 log_err("failure in u_shapeArabic(letters_source6)\n");
3327 }
3328
3329 }
3330
_testPresentationForms(const UChar * in)3331 static void _testPresentationForms(const UChar* in) {
3332 enum Forms { GENERIC, ISOLATED, FINAL, INITIAL, MEDIAL };
3333 /* This character is used to check whether the in-character is rewritten correctly
3334 and whether the surrounding characters are shaped correctly as well. */
3335 UChar otherChar[] = {0x0628, 0xfe8f, 0xfe90, 0xfe91, 0xfe92};
3336 UChar src[3];
3337 UChar dst[3];
3338 UErrorCode errorCode;
3339 int32_t length;
3340
3341 /* Testing isolated shaping */
3342 src[0] = in[GENERIC];
3343 errorCode=U_ZERO_ERROR;
3344 length=u_shapeArabic(src, 1,
3345 dst, 1,
3346 U_SHAPE_LETTERS_SHAPE,
3347 &errorCode);
3348 if(U_FAILURE(errorCode) || length!=1 || dst[0] != in[ISOLATED]) {
3349 log_err("failure in u_shapeArabic(_testAllForms: shaping isolated): %x\n", in[GENERIC]);
3350 }
3351 errorCode=U_ZERO_ERROR;
3352 length=u_shapeArabic(dst, 1,
3353 src, 1,
3354 U_SHAPE_LETTERS_UNSHAPE,
3355 &errorCode);
3356 if(U_FAILURE(errorCode) || length!=1 || src[0] != in[GENERIC]) {
3357 log_err("failure in u_shapeArabic(_testAllForms: unshaping isolated): %x\n", in[GENERIC]);
3358 }
3359
3360 /* Testing final shaping */
3361 src[0] = otherChar[GENERIC];
3362 src[1] = in[GENERIC];
3363 if (in[FINAL] != 0) {
3364 errorCode=U_ZERO_ERROR;
3365 length=u_shapeArabic(src, 2,
3366 dst, 2,
3367 U_SHAPE_LETTERS_SHAPE,
3368 &errorCode);
3369 if(U_FAILURE(errorCode) || length!=2 || dst[0] != otherChar[INITIAL] || dst[1] != in[FINAL]) {
3370 log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in[GENERIC]);
3371 }
3372 errorCode=U_ZERO_ERROR;
3373 length=u_shapeArabic(dst, 2,
3374 src, 2,
3375 U_SHAPE_LETTERS_UNSHAPE,
3376 &errorCode);
3377 if(U_FAILURE(errorCode) || length!=2 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC]) {
3378 log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in[GENERIC]);
3379 }
3380 } else {
3381 errorCode=U_ZERO_ERROR;
3382 length=u_shapeArabic(src, 2,
3383 dst, 2,
3384 U_SHAPE_LETTERS_SHAPE,
3385 &errorCode);
3386 if(U_FAILURE(errorCode) || length!=2 || dst[0] != otherChar[ISOLATED] || dst[1] != in[ISOLATED]) {
3387 log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in[GENERIC]);
3388 }
3389 errorCode=U_ZERO_ERROR;
3390 length=u_shapeArabic(dst, 2,
3391 src, 2,
3392 U_SHAPE_LETTERS_UNSHAPE,
3393 &errorCode);
3394 if(U_FAILURE(errorCode) || length!=2 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC]) {
3395 log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in[GENERIC]);
3396 }
3397 }
3398
3399 /* Testing initial shaping */
3400 src[0] = in[GENERIC];
3401 src[1] = otherChar[GENERIC];
3402 if (in[INITIAL] != 0) {
3403 /* Testing characters that have an initial form */
3404 errorCode=U_ZERO_ERROR;
3405 length=u_shapeArabic(src, 2,
3406 dst, 2,
3407 U_SHAPE_LETTERS_SHAPE,
3408 &errorCode);
3409 if(U_FAILURE(errorCode) || length!=2 || dst[0] != in[INITIAL] || dst[1] != otherChar[FINAL]) {
3410 log_err("failure in u_shapeArabic(_testAllForms: shaping initial): %x\n", in[GENERIC]);
3411 }
3412 errorCode=U_ZERO_ERROR;
3413 length=u_shapeArabic(dst, 2,
3414 src, 2,
3415 U_SHAPE_LETTERS_UNSHAPE,
3416 &errorCode);
3417 if(U_FAILURE(errorCode) || length!=2 || src[0] != in[GENERIC] || src[1] != otherChar[GENERIC]) {
3418 log_err("failure in u_shapeArabic(_testAllForms: unshaping initial): %x\n", in[GENERIC]);
3419 }
3420 } else {
3421 /* Testing characters that do not have an initial form */
3422 errorCode=U_ZERO_ERROR;
3423 length=u_shapeArabic(src, 2,
3424 dst, 2,
3425 U_SHAPE_LETTERS_SHAPE,
3426 &errorCode);
3427 if(U_FAILURE(errorCode) || length!=2 || dst[0] != in[ISOLATED] || dst[1] != otherChar[ISOLATED]) {
3428 log_err("failure in u_shapeArabic(_testTwoForms: shaping initial): %x\n", in[GENERIC]);
3429 }
3430 errorCode=U_ZERO_ERROR;
3431 length=u_shapeArabic(dst, 2,
3432 src, 2,
3433 U_SHAPE_LETTERS_UNSHAPE,
3434 &errorCode);
3435 if(U_FAILURE(errorCode) || length!=2 || src[0] != in[GENERIC] || src[1] != otherChar[GENERIC]) {
3436 log_err("failure in u_shapeArabic(_testTwoForms: unshaping initial): %x\n", in[GENERIC]);
3437 }
3438 }
3439
3440 /* Testing medial shaping */
3441 src[0] = otherChar[0];
3442 src[1] = in[GENERIC];
3443 src[2] = otherChar[0];
3444 errorCode=U_ZERO_ERROR;
3445 if (in[MEDIAL] != 0) {
3446 /* Testing characters that have an medial form */
3447 length=u_shapeArabic(src, 3,
3448 dst, 3,
3449 U_SHAPE_LETTERS_SHAPE,
3450 &errorCode);
3451 if(U_FAILURE(errorCode) || length!=3 || dst[0] != otherChar[INITIAL] || dst[1] != in[MEDIAL] || dst[2] != otherChar[FINAL]) {
3452 log_err("failure in u_shapeArabic(_testAllForms: shaping medial): %x\n", in[GENERIC]);
3453 }
3454 errorCode=U_ZERO_ERROR;
3455 length=u_shapeArabic(dst, 3,
3456 src, 3,
3457 U_SHAPE_LETTERS_UNSHAPE,
3458 &errorCode);
3459 if(U_FAILURE(errorCode) || length!=3 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC] || src[2] != otherChar[GENERIC]) {
3460 log_err("failure in u_shapeArabic(_testAllForms: unshaping medial): %x\n", in[GENERIC]);
3461 }
3462 } else {
3463 /* Testing characters that do not have an medial form */
3464 errorCode=U_ZERO_ERROR;
3465 length=u_shapeArabic(src, 3,
3466 dst, 3,
3467 U_SHAPE_LETTERS_SHAPE,
3468 &errorCode);
3469 if(U_FAILURE(errorCode) || length!=3 || dst[0] != otherChar[INITIAL] || dst[1] != in[FINAL] || dst[2] != otherChar[ISOLATED]) {
3470 log_err("failure in u_shapeArabic(_testTwoForms: shaping medial): %x\n", in[GENERIC]);
3471 }
3472 errorCode=U_ZERO_ERROR;
3473 length=u_shapeArabic(dst, 3,
3474 src, 3,
3475 U_SHAPE_LETTERS_UNSHAPE,
3476 &errorCode);
3477 if(U_FAILURE(errorCode) || length!=3 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC] || src[2] != otherChar[GENERIC]) {
3478 log_err("failure in u_shapeArabic(_testTwoForms: unshaping medial): %x\n", in[GENERIC]);
3479 }
3480 }
3481 }
3482
3483 static void
doArabicShapingTestForNewCharacters(void)3484 doArabicShapingTestForNewCharacters(void) {
3485 static const UChar letterForms[][5]={
3486 { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69 }, /* TTEH */
3487 { 0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61 }, /* TTEHEH */
3488 { 0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55 }, /* BEEH */
3489 { 0x0688, 0xFB88, 0xFB89, 0, 0 }, /* DDAL */
3490 { 0x068C, 0xFB84, 0xFB85, 0, 0 }, /* DAHAL */
3491 { 0x068D, 0xFB82, 0xFB83, 0, 0 }, /* DDAHAL */
3492 { 0x068E, 0xFB86, 0xFB87, 0, 0 }, /* DUL */
3493 { 0x0691, 0xFB8C, 0xFB8D, 0, 0 }, /* RREH */
3494 { 0x06BA, 0xFB9E, 0xFB9F, 0, 0 }, /* NOON GHUNNA */
3495 { 0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3 }, /* RNOON */
3496 { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD }, /* HEH DOACHASHMEE */
3497 { 0x06C0, 0xFBA4, 0xFBA5, 0, 0 }, /* HEH WITH YEH ABOVE */
3498 { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9 }, /* HEH GOAL */
3499 { 0x06C5, 0xFBE0, 0xFBE1, 0, 0 }, /* KIRGIHIZ OE */
3500 { 0x06C6, 0xFBD9, 0xFBDA, 0, 0 }, /* OE */
3501 { 0x06C7, 0xFBD7, 0xFBD8, 0, 0 }, /* U */
3502 { 0x06C8, 0xFBDB, 0xFBDC, 0, 0 }, /* YU */
3503 { 0x06C9, 0xFBE2, 0xFBE3, 0, 0 }, /* KIRGIZ YU */
3504 { 0x06CB, 0xFBDE, 0xFBDF, 0, 0}, /* VE */
3505 { 0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7 }, /* E */
3506 { 0x06D2, 0xFBAE, 0xFBAF, 0, 0 }, /* YEH BARREE */
3507 { 0x06D3, 0xFBB0, 0xFBB1, 0, 0 }, /* YEH BARREE WITH HAMZA ABOVE */
3508 { 0x0622, 0xFE81, 0xFE82, 0, 0, }, /* ALEF WITH MADDA ABOVE */
3509 { 0x0623, 0xFE83, 0xFE84, 0, 0, }, /* ALEF WITH HAMZA ABOVE */
3510 { 0x0624, 0xFE85, 0xFE86, 0, 0, }, /* WAW WITH HAMZA ABOVE */
3511 { 0x0625, 0xFE87, 0xFE88, 0, 0, }, /* ALEF WITH HAMZA BELOW */
3512 { 0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, }, /* YEH WITH HAMZA ABOVE */
3513 { 0x0627, 0xFE8D, 0xFE8E, 0, 0, }, /* ALEF */
3514 { 0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, }, /* BEH */
3515 { 0x0629, 0xFE93, 0xFE94, 0, 0, }, /* TEH MARBUTA */
3516 { 0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98, }, /* TEH */
3517 { 0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, }, /* THEH */
3518 { 0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0, }, /* JEEM */
3519 { 0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, }, /* HAH */
3520 { 0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8, }, /* KHAH */
3521 { 0x062F, 0xFEA9, 0xFEAA, 0, 0, }, /* DAL */
3522 { 0x0630, 0xFEAB, 0xFEAC, 0, 0, }, /* THAL */
3523 { 0x0631, 0xFEAD, 0xFEAE, 0, 0, }, /* REH */
3524 { 0x0632, 0xFEAF, 0xFEB0, 0, 0, }, /* ZAIN */
3525 { 0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, }, /* SEEN */
3526 { 0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, }, /* SHEEN */
3527 { 0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, }, /* SAD */
3528 { 0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, }, /* DAD */
3529 { 0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, }, /* TAH */
3530 { 0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, }, /* ZAH */
3531 { 0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, }, /* AIN */
3532 { 0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0, }, /* GHAIN */
3533 { 0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4, }, /* FEH */
3534 { 0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8, }, /* QAF */
3535 { 0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, }, /* KAF */
3536 { 0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0, }, /* LAM */
3537 { 0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, }, /* MEEM */
3538 { 0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8, }, /* NOON */
3539 { 0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, }, /* HEH */
3540 { 0x0648, 0xFEED, 0xFEEE, 0, 0, }, /* WAW */
3541 { 0x0649, 0xFEEF, 0xFEF0, 0, 0, }, /* ALEF MAKSURA */
3542 { 0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, }, /* YEH */
3543 { 0x064E, 0xFE76, 0, 0, 0xFE77, }, /* FATHA */
3544 { 0x064F, 0xFE78, 0, 0, 0xFE79, }, /* DAMMA */
3545 { 0x0650, 0xFE7A, 0, 0, 0xFE7B, }, /* KASRA */
3546 { 0x0651, 0xFE7C, 0, 0, 0xFE7D, }, /* SHADDA */
3547 { 0x0652, 0xFE7E, 0, 0, 0xFE7F, }, /* SUKUN */
3548 { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69, }, /* TTEH */
3549 { 0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59, }, /* PEH */
3550 { 0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, }, /* TCHEH */
3551 { 0x0688, 0xFB88, 0xFB89, 0, 0, }, /* DDAL */
3552 { 0x0691, 0xFB8C, 0xFB8D, 0, 0, }, /* RREH */
3553 { 0x0698, 0xFB8A, 0xFB8B, 0, 0, }, /* JEH */
3554 { 0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, }, /* KEHEH */
3555 { 0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95, }, /* GAF */
3556 { 0x06BA, 0xFB9E, 0xFB9F, 0, 0, }, /* NOON GHUNNA */
3557 { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, }, /* HEH DOACHASHMEE */
3558 { 0x06C0, 0xFBA4, 0xFBA5, 0, 0, }, /* HEH WITH YEH ABOVE */
3559 { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, }, /* HEH GOAL */
3560 { 0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, }, /* FARSI YEH */
3561 { 0x06D2, 0xFBAE, 0xFBAF, 0, 0, }, /* YEH BARREE */
3562 { 0x06D3, 0xFBB0, 0xFBB1, 0, 0, }}; /* YEH BARREE WITH HAMZA ABOVE */
3563 int32_t i;
3564 for (i = 0; i < UPRV_LENGTHOF(letterForms); ++i) {
3565 _testPresentationForms(letterForms[i]);
3566 }
3567 }
3568
3569 /* helpers ------------------------------------------------------------------ */
3570
initCharFromDirProps(void)3571 static void initCharFromDirProps(void) {
3572 static const UVersionInfo ucd401={ 4, 0, 1, 0 };
3573 static UVersionInfo ucdVersion={ 0, 0, 0, 0 };
3574
3575 /* lazy initialization */
3576 if(ucdVersion[0]>0) {
3577 return;
3578 }
3579
3580 u_getUnicodeVersion(ucdVersion);
3581 if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) {
3582 /* Unicode 4.0.1 changes bidi classes for +-/ */
3583 charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */
3584 }
3585 }
3586
3587 /* return a string with characters according to the desired directional properties */
3588 static UChar *
getStringFromDirProps(const uint8_t * dirProps,int32_t length,UChar * buffer)3589 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer) {
3590 int32_t i;
3591
3592 initCharFromDirProps();
3593
3594 /* this part would have to be modified for UTF-x */
3595 for(i=0; i<length; ++i) {
3596 buffer[i]=charFromDirProp[dirProps[i]];
3597 }
3598 buffer[length]=0;
3599 return buffer;
3600 }
3601
printUnicode(const UChar * s,int32_t length,const UBiDiLevel * levels)3602 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) {
3603 int32_t i;
3604
3605 log_verbose("{ ");
3606 for(i=0; i<length; ++i) {
3607 if(levels!=NULL) {
3608 log_verbose("%4x.%u ", s[i], levels[i]);
3609 } else {
3610 log_verbose("%4x ", s[i]);
3611 }
3612 }
3613 log_verbose(" }");
3614 }
3615
3616 /* new BIDI API */
3617
3618 /* Reordering Mode BiDi --------------------------------------------------------- */
3619
3620 static const UBiDiLevel paraLevels[] = { UBIDI_LTR, UBIDI_RTL };
3621
3622 static UBool
assertSuccessful(const char * message,UErrorCode * rc)3623 assertSuccessful(const char* message, UErrorCode* rc) {
3624 if (rc != NULL && U_FAILURE(*rc)) {
3625 log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
3626 return FALSE;
3627 }
3628 return TRUE;
3629 }
3630
3631 static UBool
assertStringsEqual(const char * expected,const char * actual,const char * src,const char * mode,const char * option,UBiDi * pBiDi)3632 assertStringsEqual(const char* expected, const char* actual, const char* src,
3633 const char* mode, const char* option, UBiDi* pBiDi) {
3634 if (uprv_strcmp(expected, actual)) {
3635 char formatChars[MAXLEN];
3636 log_err("\nActual and expected output mismatch.\n"
3637 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n",
3638 "Input:", src,
3639 "Actual output:", actual,
3640 "Expected output:", expected,
3641 "Levels:", formatLevels(pBiDi, formatChars),
3642 "Reordering mode:", ubidi_getReorderingMode(pBiDi), mode,
3643 "Paragraph level:", ubidi_getParaLevel(pBiDi),
3644 "Reordering option:", ubidi_getReorderingOptions(pBiDi), option);
3645 return FALSE;
3646 }
3647 return TRUE;
3648 }
3649
3650 static UBiDi*
getBiDiObject(void)3651 getBiDiObject(void) {
3652 UBiDi* pBiDi = ubidi_open();
3653 if (pBiDi == NULL) {
3654 log_err("Unable to allocate a UBiDi object. Tests are skipped.\n");
3655 }
3656 return pBiDi;
3657 }
3658
3659 #define MAKE_ITEMS(val) val, #val
3660
3661 static const struct {
3662 UBiDiReorderingMode value;
3663 const char* description;
3664 }
3665 modes[] = {
3666 { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) },
3667 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT) },
3668 { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL) },
3669 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) },
3670 { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L) }
3671 };
3672 static const struct {
3673 uint32_t value;
3674 const char* description;
3675 }
3676 options[] = {
3677 { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS) },
3678 { MAKE_ITEMS(0) }
3679 };
3680
3681 #define TC_COUNT UPRV_LENGTHOF(textIn)
3682 #define MODES_COUNT UPRV_LENGTHOF(modes)
3683 #define OPTIONS_COUNT UPRV_LENGTHOF(options)
3684 #define LEVELS_COUNT UPRV_LENGTHOF(paraLevels)
3685
3686 static const char* const textIn[] = {
3687 /* (0) 123 */
3688 "123",
3689 /* (1) .123->4.5 */
3690 ".123->4.5",
3691 /* (2) 678 */
3692 "678",
3693 /* (3) .678->8.9 */
3694 ".678->8.9",
3695 /* (4) JIH1.2,3MLK */
3696 "JIH1.2,3MLK",
3697 /* (5) FE.>12-> */
3698 "FE.>12->",
3699 /* (6) JIH.>12->a */
3700 "JIH.>12->a",
3701 /* (7) CBA.>67->89=a */
3702 "CBA.>67->89=a",
3703 /* (8) CBA.123->xyz */
3704 "CBA.123->xyz",
3705 /* (9) .>12->xyz */
3706 ".>12->xyz",
3707 /* (10) a.>67->xyz */
3708 "a.>67->xyz",
3709 /* (11) 123JIH */
3710 "123JIH",
3711 /* (12) 123 JIH */
3712 "123 JIH"
3713 };
3714
3715 static const char* const textOut[] = {
3716 /* TC 0: 123 */
3717 "123", /* (0) */
3718 /* TC 1: .123->4.5 */
3719 ".123->4.5", /* (1) */
3720 "4.5<-123.", /* (2) */
3721 /* TC 2: 678 */
3722 "678", /* (3) */
3723 /* TC 3: .678->8.9 */
3724 ".8.9<-678", /* (4) */
3725 "8.9<-678.", /* (5) */
3726 ".678->8.9", /* (6) */
3727 /* TC 4: MLK1.2,3JIH */
3728 "KLM1.2,3HIJ", /* (7) */
3729 /* TC 5: FE.>12-> */
3730 "12<.EF->", /* (8) */
3731 "<-12<.EF", /* (9) */
3732 "EF.>@12->", /* (10) */
3733 /* TC 6: JIH.>12->a */
3734 "12<.HIJ->a", /* (11) */
3735 "a<-12<.HIJ", /* (12) */
3736 "HIJ.>@12->a", /* (13) */
3737 "a&<-12<.HIJ", /* (14) */
3738 /* TC 7: CBA.>67->89=a */
3739 "ABC.>@67->89=a", /* (15) */
3740 "a=89<-67<.ABC", /* (16) */
3741 "a&=89<-67<.ABC", /* (17) */
3742 "89<-67<.ABC=a", /* (18) */
3743 /* TC 8: CBA.123->xyz */
3744 "123.ABC->xyz", /* (19) */
3745 "xyz<-123.ABC", /* (20) */
3746 "ABC.@123->xyz", /* (21) */
3747 "xyz&<-123.ABC", /* (22) */
3748 /* TC 9: .>12->xyz */
3749 ".>12->xyz", /* (23) */
3750 "xyz<-12<.", /* (24) */
3751 "xyz&<-12<.", /* (25) */
3752 /* TC 10: a.>67->xyz */
3753 "a.>67->xyz", /* (26) */
3754 "a.>@67@->xyz", /* (27) */
3755 "xyz<-67<.a", /* (28) */
3756 /* TC 11: 123JIH */
3757 "123HIJ", /* (29) */
3758 "HIJ123", /* (30) */
3759 /* TC 12: 123 JIH */
3760 "123 HIJ", /* (31) */
3761 "HIJ 123", /* (32) */
3762 };
3763
3764 #define NO UBIDI_MAP_NOWHERE
3765 #define MAX_MAP_LENGTH 20
3766
3767 static const int32_t forwardMap[][MAX_MAP_LENGTH] = {
3768 /* TC 0: 123 */
3769 { 0, 1, 2 }, /* (0) */
3770 /* TC 1: .123->4.5 */
3771 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */
3772 { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (2) */
3773 /* TC 2: 678 */
3774 { 0, 1, 2 }, /* (3) */
3775 /* TC 3: .678->8.9 */
3776 { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */
3777 { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (5) */
3778 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */
3779 /* TC 4: MLK1.2,3JIH */
3780 { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */
3781 /* TC 5: FE.>12-> */
3782 { 5, 4, 3, 2, 0, 1, 6, 7 }, /* (8) */
3783 { 7, 6, 5, 4, 2, 3, 1, 0 }, /* (9) */
3784 { 1, 0, 2, 3, 5, 6, 7, 8 }, /* (10) */
3785 /* TC 6: JIH.>12->a */
3786 { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 }, /* (11) */
3787 { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 }, /* (12) */
3788 { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 }, /* (13) */
3789 { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 }, /* (14) */
3790 /* TC 7: CBA.>67->89=a */
3791 { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 }, /* (15) */
3792 { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 }, /* (16) */
3793 { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 }, /* (17) */
3794 { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 }, /* (18) */
3795 /* TC 8: CBA.123->xyz */
3796 { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 }, /* (19) */
3797 { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (20) */
3798 { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (21) */
3799 { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 }, /* (22) */
3800 /* TC 9: .>12->xyz */
3801 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */
3802 { 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (24) */
3803 { 9, 8, 6, 7, 5, 4, 0, 1, 2 }, /* (25) */
3804 /* TC 10: a.>67->xyz */
3805 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */
3806 { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 }, /* (27) */
3807 { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (28) */
3808 /* TC 11: 123JIH */
3809 { 0, 1, 2, 5, 4, 3 }, /* (29) */
3810 { 3, 4, 5, 2, 1, 0 }, /* (30) */
3811 /* TC 12: 123 JIH */
3812 { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */
3813 { 4, 5, 6, 3, 2, 1, 0 }, /* (32) */
3814 };
3815
3816 static const int32_t inverseMap[][MAX_MAP_LENGTH] = {
3817 /* TC 0: 123 */
3818 { 0, 1, 2 }, /* (0) */
3819 /* TC 1: .123->4.5 */
3820 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */
3821 { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (2) */
3822 /* TC 2: 678 */
3823 { 0, 1, 2 }, /* (3) */
3824 /* TC 3: .678->8.9 */
3825 { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */
3826 { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (5) */
3827 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */
3828 /* TC 4: MLK1.2,3JIH */
3829 { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */
3830 /* TC 5: FE.>12-> */
3831 { 4, 5, 3, 2, 1, 0, 6, 7 }, /* (8) */
3832 { 7, 6, 4, 5, 3, 2, 1, 0 }, /* (9) */
3833 { 1, 0, 2, 3, NO, 4, 5, 6, 7 }, /* (10) */
3834 /* TC 6: JIH.>12->a */
3835 { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 }, /* (11) */
3836 { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (12) */
3837 { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (13) */
3838 { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (14) */
3839 /* TC 7: CBA.>67->89=a */
3840 { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (15) */
3841 { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (16) */
3842 { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (17) */
3843 { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 }, /* (18) */
3844 /* TC 8: CBA.123->xyz */
3845 { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 }, /* (19) */
3846 { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (20) */
3847 { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 }, /* (21) */
3848 { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (22) */
3849 /* TC 9: .>12->xyz */
3850 { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */
3851 { 6, 7, 8, 5, 4, 2, 3, 1, 0 }, /* (24) */
3852 { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 }, /* (25) */
3853 /* TC 10: a.>67->xyz */
3854 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */
3855 { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (27) */
3856 { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 }, /* (28) */
3857 /* TC 11: 123JIH */
3858 { 0, 1, 2, 5, 4, 3 }, /* (29) */
3859 { 5, 4, 3, 0, 1, 2 }, /* (30) */
3860 /* TC 12: 123 JIH */
3861 { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */
3862 { 6, 5, 4, 3, 0, 1, 2 }, /* (32) */
3863 };
3864
3865 static const char outIndices[TC_COUNT][MODES_COUNT - 1][OPTIONS_COUNT]
3866 [LEVELS_COUNT] = {
3867 { /* TC 0: 123 */
3868 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3869 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3870 {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3871 {{ 0, 0}, { 0, 0}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3872 },
3873 { /* TC 1: .123->4.5 */
3874 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3875 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3876 {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3877 {{ 1, 2}, { 1, 2}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3878 },
3879 { /* TC 2: 678 */
3880 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3881 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3882 {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3883 {{ 3, 3}, { 3, 3}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3884 },
3885 { /* TC 3: .678->8.9 */
3886 {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3887 {{ 4, 5}, { 4, 5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3888 {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3889 {{ 6, 5}, { 6, 5}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3890 },
3891 { /* TC 4: MLK1.2,3JIH */
3892 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3893 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3894 {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3895 {{ 7, 7}, { 7, 7}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3896 },
3897 { /* TC 5: FE.>12-> */
3898 {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3899 {{10, 9}, { 8, 9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3900 {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3901 {{10, 9}, { 8, 9}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3902 },
3903 { /* TC 6: JIH.>12->a */
3904 {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3905 {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3906 {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3907 {{13, 14}, {11, 12}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3908 },
3909 { /* TC 7: CBA.>67->89=a */
3910 {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3911 {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3912 {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3913 {{15, 17}, {18, 16}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3914 },
3915 { /* TC 8: CBA.>124->xyz */
3916 {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3917 {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3918 {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3919 {{21, 22}, {19, 20}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3920 },
3921 { /* TC 9: .>12->xyz */
3922 {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3923 {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3924 {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3925 {{23, 25}, {23, 24}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3926 },
3927 { /* TC 10: a.>67->xyz */
3928 {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3929 {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3930 {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3931 {{26, 27}, {26, 28}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3932 },
3933 { /* TC 11: 124JIH */
3934 {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3935 {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3936 {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3937 {{30, 30}, {30, 30}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3938 },
3939 { /* TC 12: 124 JIH */
3940 {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3941 {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3942 {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3943 {{31, 32}, {31, 32}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3944 }
3945 };
3946
3947 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)3948 assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, const char *srcChars,
3949 const char *destChars, const UChar *dest, int32_t destLen,
3950 int mode, int option, UBiDiLevel level) {
3951
3952 static const char roundtrip[TC_COUNT][MODES_COUNT][OPTIONS_COUNT]
3953 [LEVELS_COUNT] = {
3954 { /* TC 0: 123 */
3955 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3956 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3957 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3958 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3959 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3960 },
3961 { /* TC 1: .123->4.5 */
3962 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3963 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3964 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3965 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3966 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3967 },
3968 { /* TC 2: 678 */
3969 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3970 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3971 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3972 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3973 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3974 },
3975 { /* TC 3: .678->8.9 */
3976 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3977 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3978 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3979 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3980 {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3981 },
3982 { /* TC 4: MLK1.2,3JIH */
3983 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3984 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3985 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3986 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3987 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3988 },
3989 { /* TC 5: FE.>12-> */
3990 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3991 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3992 {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
3993 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
3994 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
3995 },
3996 { /* TC 6: JIH.>12->a */
3997 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
3998 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
3999 {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4000 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4001 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4002 },
4003 { /* TC 7: CBA.>67->89=a */
4004 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4005 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4006 {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4007 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4008 {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4009 },
4010 { /* TC 8: CBA.>123->xyz */
4011 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4012 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4013 {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4014 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4015 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4016 },
4017 { /* TC 9: .>12->xyz */
4018 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4019 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4020 {{ 1, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4021 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4022 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4023 },
4024 { /* TC 10: a.>67->xyz */
4025 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4026 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4027 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4028 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4029 {{ 1, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4030 },
4031 { /* TC 11: 123JIH */
4032 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4033 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4034 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4035 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4036 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4037 },
4038 { /* TC 12: 123 JIH */
4039 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
4040 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
4041 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
4042 {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
4043 {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
4044 }
4045 };
4046
4047 #define SET_ROUND_TRIP_MODE(mode) \
4048 ubidi_setReorderingMode(pBiDi, mode); \
4049 desc = #mode; \
4050 break;
4051
4052 UErrorCode rc = U_ZERO_ERROR;
4053 UChar dest2[MAXLEN];
4054 int32_t destLen2;
4055 const char* desc;
4056 char destChars2[MAXLEN];
4057 char destChars3[MAXLEN];
4058
4059 switch (modes[mode].value) {
4060 case UBIDI_REORDER_NUMBERS_SPECIAL:
4061 SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL)
4062 case UBIDI_REORDER_GROUP_NUMBERS_WITH_R:
4063 SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R)
4064 case UBIDI_REORDER_RUNS_ONLY:
4065 SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY)
4066 case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
4067 SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
4068 case UBIDI_REORDER_INVERSE_LIKE_DIRECT:
4069 SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
4070 case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL:
4071 SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL)
4072 default:
4073 SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT)
4074 }
4075 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
4076
4077 ubidi_setPara(pBiDi, dest, destLen, level, NULL, &rc);
4078 assertSuccessful("ubidi_setPara", &rc);
4079 *dest2 = 0;
4080 destLen2 = ubidi_writeReordered(pBiDi, dest2, MAXLEN, UBIDI_DO_MIRRORING,
4081 &rc);
4082 assertSuccessful("ubidi_writeReordered", &rc);
4083
4084 u16ToPseudo(destLen, dest, destChars3);
4085 u16ToPseudo(destLen2, dest2, destChars2);
4086 checkWhatYouCan(pBiDi, destChars3, destChars2);
4087 if (strcmp(srcChars, destChars2)) {
4088 if (roundtrip[tc][mode][option][level]) {
4089 log_err("\nRound trip failed for case=%d mode=%d option=%d.\n"
4090 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
4091 "\n%20s %u\n", tc, mode, option,
4092 "Original text:", srcChars,
4093 "Round-tripped text:", destChars2,
4094 "Intermediate text:", destChars3,
4095 "Reordering mode:", modes[mode].description,
4096 "Reordering option:", options[option].description,
4097 "Paragraph level:", level);
4098 }
4099 else {
4100 log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n"
4101 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
4102 "\n%20s %u\n", tc, mode, option,
4103 "Original text:", srcChars,
4104 "Round-tripped text:", destChars2,
4105 "Intermediate text:", destChars3,
4106 "Reordering mode:", modes[mode].description,
4107 "Reordering option:", options[option].description,
4108 "Paragraph level:", level);
4109 }
4110 return FALSE;
4111 }
4112 if (!checkResultLength(pBiDi, destChars, destChars2, destLen2,
4113 desc, "UBIDI_OPTION_REMOVE_CONTROLS", level)) {
4114 return FALSE;
4115 }
4116 if (outIndex > -1 && !checkMaps(pBiDi, outIndex, srcChars, destChars,
4117 desc, "UBIDI_OPTION_REMOVE_CONTROLS",
4118 level, FALSE)) {
4119 return FALSE;
4120 }
4121 return TRUE;
4122 }
4123
4124 static UBool
checkResultLength(UBiDi * pBiDi,const char * srcChars,const char * destChars,int32_t destLen,const char * mode,const char * option,UBiDiLevel level)4125 checkResultLength(UBiDi *pBiDi, const char *srcChars, const char *destChars,
4126 int32_t destLen, const char* mode,
4127 const char* option, UBiDiLevel level) {
4128 int32_t actualLen;
4129 if (strcmp(mode, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0)
4130 actualLen = (int32_t)strlen(destChars);
4131 else
4132 actualLen = ubidi_getResultLength(pBiDi);
4133 if (actualLen != destLen) {
4134 log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n"
4135 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n",
4136 "Expected:", destLen, "Actual:", actualLen,
4137 "Input:", srcChars, "Output:", destChars,
4138 "Reordering mode:", mode, "Reordering option:", option,
4139 "Paragraph level:", level);
4140 return FALSE;
4141 }
4142 return TRUE;
4143 }
4144
4145 static void
testReorderRunsOnly(void)4146 testReorderRunsOnly(void) {
4147 static const struct {
4148 const char* textIn;
4149 const char* textOut[2][2];
4150 const char noroundtrip[2];
4151 } testCases[] = {
4152 {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*0*/
4153 {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
4154 {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}}, /*1*/
4155 {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}}, /*2*/
4156 {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"}, /*3*/
4157 {"* /%$123=-", "* /%$123=-"}}, {0, 0}},
4158 {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"}, /*4*/
4159 {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}},
4160 {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"}, /*5*/
4161 {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}},
4162 {"123->abc", {{"abc<-123", "abc<-123"}, /*6*/
4163 {"abc&<-123", "abc<-123"}}, {1, 0}},
4164 {"123->JKL", {{"JKL<-123", "123->JKL"}, /*7*/
4165 {"JKL<-123", "JKL<-@123"}}, {0, 1}},
4166 {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"}, /*8*/
4167 {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}},
4168 {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"}, /*9*/
4169 {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}},
4170 {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"}, /*10*/
4171 {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}},
4172 {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"}, /*11*/
4173 {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}},
4174 {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"}, /*12*/
4175 {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}},
4176 {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"}, /*13*/
4177 {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}},
4178 {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"}, /*14*/
4179 {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}},
4180 {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*15*/
4181 {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
4182 {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}, /*16*/
4183 {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}},
4184 {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"}, /*17*/
4185 {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}},
4186 {"123", {{"123", "123"}, /* just one run */ /*18*/
4187 {"123", "123"}}, {0, 0}}
4188 };
4189 UBiDi *pBiDi = getBiDiObject();
4190 UBiDi *pL2VBiDi = getBiDiObject();
4191 UChar src[MAXLEN], dest[MAXLEN], visual1[MAXLEN], visual2[MAXLEN];
4192 char destChars[MAXLEN], vis1Chars[MAXLEN], vis2Chars[MAXLEN];
4193 int32_t srcLen, destLen, vis1Len, vis2Len, option, i, j, nCases, paras;
4194 UErrorCode rc = U_ZERO_ERROR;
4195 UBiDiLevel level;
4196
4197 log_verbose("\nEntering TestReorderRunsOnly\n\n");
4198
4199 if(!pL2VBiDi) {
4200 ubidi_close(pBiDi); /* in case this one was allocated */
4201 return;
4202 }
4203 ubidi_setReorderingMode(pBiDi, UBIDI_REORDER_RUNS_ONLY);
4204 ubidi_setReorderingOptions(pL2VBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
4205
4206 for (option = 0; option < 2; option++) {
4207 ubidi_setReorderingOptions(pBiDi, option==0 ? UBIDI_OPTION_REMOVE_CONTROLS
4208 : UBIDI_OPTION_INSERT_MARKS);
4209 for (i = 0, nCases = UPRV_LENGTHOF(testCases); i < nCases; i++) {
4210 srcLen = (int32_t)strlen(testCases[i].textIn);
4211 pseudoToU16(srcLen, testCases[i].textIn, src);
4212 for(j = 0; j < 2; j++) {
4213 log_verbose("Now doing test for option %d, case %d, level %d\n",
4214 i, option, j);
4215 level = paraLevels[j];
4216 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
4217 assertSuccessful("ubidi_setPara", &rc);
4218 *dest = 0;
4219 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
4220 assertSuccessful("ubidi_writeReordered", &rc);
4221 u16ToPseudo(destLen, dest, destChars);
4222 checkWhatYouCan(pBiDi, testCases[i].textIn, destChars);
4223 assertStringsEqual(testCases[i].textOut[option][level], destChars,
4224 testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY",
4225 option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
4226 pBiDi);
4227
4228 if((option==0) && testCases[i].noroundtrip[level]) {
4229 continue;
4230 }
4231 ubidi_setPara(pL2VBiDi, src, srcLen, level, NULL, &rc);
4232 assertSuccessful("ubidi_setPara1", &rc);
4233 *visual1 = 0;
4234 vis1Len = ubidi_writeReordered(pL2VBiDi, visual1, MAXLEN, UBIDI_DO_MIRRORING, &rc);
4235 assertSuccessful("ubidi_writeReordered1", &rc);
4236 u16ToPseudo(vis1Len, visual1, vis1Chars);
4237 checkWhatYouCan(pL2VBiDi, testCases[i].textIn, vis1Chars);
4238 ubidi_setPara(pL2VBiDi, dest, destLen, level^1, NULL, &rc);
4239 assertSuccessful("ubidi_setPara2", &rc);
4240 *visual2 = 0;
4241 vis2Len = ubidi_writeReordered(pL2VBiDi, visual2, MAXLEN, UBIDI_DO_MIRRORING, &rc);
4242 assertSuccessful("ubidi_writeReordered2", &rc);
4243 u16ToPseudo(vis2Len, visual2, vis2Chars);
4244 checkWhatYouCan(pL2VBiDi, destChars, vis2Chars);
4245 assertStringsEqual(vis1Chars, vis2Chars,
4246 testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY (2)",
4247 option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
4248 pBiDi);
4249 }
4250 }
4251 }
4252
4253 /* test with null or empty text */
4254 ubidi_setPara(pBiDi, src, 0, UBIDI_LTR, NULL, &rc);
4255 assertSuccessful("ubidi_setPara3", &rc);
4256 paras = ubidi_countParagraphs(pBiDi);
4257 if (paras != 0) {
4258 log_err("\nInvalid number of paras (should be 0): %d\n", paras);
4259 }
4260
4261 ubidi_close(pBiDi);
4262 ubidi_close(pL2VBiDi);
4263
4264 log_verbose("\nExiting TestReorderRunsOnly\n\n");
4265 }
4266
4267 static void
testReorderingMode(void)4268 testReorderingMode(void) {
4269
4270 UChar src[MAXLEN], dest[MAXLEN];
4271 char destChars[MAXLEN];
4272 UBiDi *pBiDi = NULL, *pBiDi2 = NULL, *pBiDi3 = NULL;
4273 UErrorCode rc;
4274 int tc, mode, option, level;
4275 uint32_t optionValue, optionBack;
4276 UBiDiReorderingMode modeValue, modeBack;
4277 int32_t srcLen, destLen, idx;
4278 const char *expectedChars;
4279 UBool testOK = TRUE;
4280
4281 log_verbose("\nEntering TestReorderingMode\n\n");
4282
4283 pBiDi = getBiDiObject();
4284 pBiDi2 = getBiDiObject();
4285 pBiDi3 = getBiDiObject();
4286 if(!pBiDi3) {
4287 ubidi_close(pBiDi); /* in case this one was allocated */
4288 ubidi_close(pBiDi2); /* in case this one was allocated */
4289 return;
4290 }
4291
4292 ubidi_setInverse(pBiDi2, TRUE);
4293
4294 for (tc = 0; tc < TC_COUNT; tc++) {
4295 const char *srcChars = textIn[tc];
4296 srcLen = (int32_t)strlen(srcChars);
4297 pseudoToU16(srcLen, srcChars, src);
4298
4299 for (mode = 0; mode < MODES_COUNT; mode++) {
4300 modeValue = modes[mode].value;
4301 ubidi_setReorderingMode(pBiDi, modeValue);
4302 modeBack = ubidi_getReorderingMode(pBiDi);
4303 if (modeValue != modeBack) {
4304 log_err("Error while setting reordering mode to %d, returned %d\n",
4305 modeValue, modeBack);
4306 }
4307
4308 for (option = 0; option < OPTIONS_COUNT; option++) {
4309 optionValue = options[option].value;
4310 ubidi_setReorderingOptions(pBiDi, optionValue);
4311 optionBack = ubidi_getReorderingOptions(pBiDi);
4312 if (optionValue != optionBack) {
4313 log_err("Error while setting reordering option to %d, returned %d\n",
4314 optionValue, optionBack);
4315 }
4316
4317 for (level = 0; level < LEVELS_COUNT; level++) {
4318 log_verbose("starting test %d mode=%d option=%d level=%d\n",
4319 tc, modes[mode].value, options[option].value, level);
4320 rc = U_ZERO_ERROR;
4321 ubidi_setPara(pBiDi, src, srcLen, paraLevels[level], NULL, &rc);
4322 assertSuccessful("ubidi_setPara", &rc);
4323
4324 *dest = 0;
4325 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
4326 UBIDI_DO_MIRRORING, &rc);
4327 assertSuccessful("ubidi_writeReordered", &rc);
4328 u16ToPseudo(destLen, dest, destChars);
4329 if (!((modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
4330 (options[option].value == UBIDI_OPTION_INSERT_MARKS))) {
4331 checkWhatYouCan(pBiDi, srcChars, destChars);
4332 }
4333
4334 if (modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) {
4335 idx = -1;
4336 expectedChars = inverseBasic(pBiDi2, srcChars, srcLen,
4337 options[option].value, paraLevels[level], destChars);
4338 }
4339 else {
4340 idx = outIndices[tc][mode][option][level];
4341 expectedChars = textOut[idx];
4342 }
4343 if (!assertStringsEqual(expectedChars, destChars, srcChars,
4344 modes[mode].description,
4345 options[option].description,
4346 pBiDi)) {
4347 testOK = FALSE;
4348 }
4349 if (options[option].value == UBIDI_OPTION_INSERT_MARKS &&
4350 !assertRoundTrip(pBiDi3, tc, idx, srcChars,
4351 destChars, dest, destLen,
4352 mode, option, paraLevels[level])) {
4353 testOK = FALSE;
4354 }
4355 else if (!checkResultLength(pBiDi, srcChars, destChars,
4356 destLen, modes[mode].description,
4357 options[option].description,
4358 paraLevels[level])) {
4359 testOK = FALSE;
4360 }
4361 else if (idx > -1 && !checkMaps(pBiDi, idx, srcChars,
4362 destChars, modes[mode].description,
4363 options[option].description, paraLevels[level],
4364 TRUE)) {
4365 testOK = FALSE;
4366 }
4367 }
4368 }
4369 }
4370 }
4371 if (testOK == TRUE) {
4372 log_verbose("\nReordering mode test OK\n");
4373 }
4374 ubidi_close(pBiDi3);
4375 ubidi_close(pBiDi2);
4376 ubidi_close(pBiDi);
4377
4378 log_verbose("\nExiting TestReorderingMode\n\n");
4379 }
4380
inverseBasic(UBiDi * pBiDi,const char * srcChars,int32_t srcLen,uint32_t option,UBiDiLevel level,char * result)4381 static const char* inverseBasic(UBiDi *pBiDi, const char *srcChars, int32_t srcLen,
4382 uint32_t option, UBiDiLevel level, char *result) {
4383 UErrorCode rc = U_ZERO_ERROR;
4384 int32_t destLen;
4385 UChar src[MAXLEN], dest2[MAXLEN];
4386
4387 if (pBiDi == NULL || srcChars == NULL) {
4388 return NULL;
4389 }
4390 ubidi_setReorderingOptions(pBiDi, option);
4391 pseudoToU16(srcLen, srcChars, src);
4392 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
4393 assertSuccessful("ubidi_setPara", &rc);
4394
4395 *dest2 = 0;
4396 destLen = ubidi_writeReordered(pBiDi, dest2, MAXLEN,
4397 UBIDI_DO_MIRRORING, &rc);
4398 assertSuccessful("ubidi_writeReordered", &rc);
4399 u16ToPseudo(destLen, dest2, result);
4400 if (!(option == UBIDI_OPTION_INSERT_MARKS)) {
4401 checkWhatYouCan(pBiDi, srcChars, result);
4402 }
4403 return result;
4404 }
4405
4406 #define NULL_CHAR '\0'
4407
4408 static void
testStreaming(void)4409 testStreaming(void) {
4410 #define MAXPORTIONS 10
4411
4412 static const struct {
4413 const char* textIn;
4414 short int chunk;
4415 short int nPortions[2];
4416 char portionLens[2][MAXPORTIONS];
4417 const char* message[2];
4418 } testData[] = {
4419 { "123\\u000A"
4420 "abc45\\u000D"
4421 "67890\\u000A"
4422 "\\u000D"
4423 "02468\\u000D"
4424 "ghi",
4425 6, { 6, 6 }, {{ 4, 6, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }},
4426 {"4, 6, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"}
4427 },
4428 { "abcd\\u000Afgh\\u000D12345\\u000A456",
4429 6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
4430 {"5, 4, 6, 3", "5, 4, 6, 3"}
4431 },
4432 { "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D",
4433 6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
4434 {"5, 4, 6, 3", "5, 4, 6, 3"}
4435 },
4436 { "abcde\\u000Afghi",
4437 10, { 2, 2 }, {{ 6, 4 }, { 6, 4 }},
4438 {"6, 4", "6, 4"}
4439 }
4440 };
4441 UChar src[MAXLEN];
4442 UBiDi *pBiDi = NULL;
4443 UChar *pSrc;
4444 UErrorCode rc = U_ZERO_ERROR;
4445 int32_t srcLen, processedLen, chunk, len, nPortions;
4446 int i, j, levelIndex;
4447 UBiDiLevel level;
4448 int nTests = UPRV_LENGTHOF(testData), nLevels = UPRV_LENGTHOF(paraLevels);
4449 UBool mismatch, testOK = TRUE;
4450 char processedLenStr[MAXPORTIONS * 5];
4451
4452 log_verbose("\nEntering TestStreaming\n\n");
4453
4454 pBiDi = getBiDiObject();
4455
4456 ubidi_orderParagraphsLTR(pBiDi, TRUE);
4457
4458 for (levelIndex = 0; levelIndex < nLevels; levelIndex++) {
4459 for (i = 0; i < nTests; i++) {
4460 srcLen = u_unescape(testData[i].textIn, src, MAXLEN);
4461 chunk = testData[i].chunk;
4462 nPortions = testData[i].nPortions[levelIndex];
4463 level = paraLevels[levelIndex];
4464 processedLenStr[0] = NULL_CHAR;
4465 log_verbose("Testing level %d, case %d\n", level, i);
4466
4467 mismatch = FALSE;
4468
4469 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
4470 for (j = 0, pSrc = src; j < MAXPORTIONS && srcLen > 0; j++) {
4471
4472 len = chunk < srcLen ? chunk : srcLen;
4473 ubidi_setPara(pBiDi, pSrc, len, level, NULL, &rc);
4474 if (!assertSuccessful("ubidi_setPara", &rc)) {
4475 break;
4476 }
4477
4478 processedLen = ubidi_getProcessedLength(pBiDi);
4479 if (processedLen == 0) {
4480 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_DEFAULT);
4481 j--;
4482 continue;
4483 }
4484 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
4485
4486 mismatch |= (UBool)(j >= nPortions ||
4487 processedLen != testData[i].portionLens[levelIndex][j]);
4488
4489 sprintf(processedLenStr + j * 4, "%4d", processedLen);
4490 srcLen -= processedLen, pSrc += processedLen;
4491 }
4492
4493 if (mismatch || j != nPortions) {
4494 testOK = FALSE;
4495 log_err("\nProcessed lengths mismatch.\n"
4496 "\tParagraph level: %u\n"
4497 "\tInput string: %s\n"
4498 "\tActually processed portion lengths: { %s }\n"
4499 "\tExpected portion lengths : { %s }\n",
4500 paraLevels[levelIndex], testData[i].textIn,
4501 processedLenStr, testData[i].message[levelIndex]);
4502 }
4503 }
4504 }
4505 ubidi_close(pBiDi);
4506 if (testOK == TRUE) {
4507 log_verbose("\nBiDi streaming test OK\n");
4508 }
4509 log_verbose("\nExiting TestStreaming\n\n");
4510 }
4511
4512 U_CDECL_BEGIN
4513
4514 static UCharDirection U_CALLCONV
overrideBidiClass(const void * context,UChar32 c)4515 overrideBidiClass(const void *context, UChar32 c) {
4516
4517 #define DEF U_BIDI_CLASS_DEFAULT
4518
4519 static const UCharDirection customClasses[] = {
4520 /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
4521 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 00-07 */
4522 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 08-0F */
4523 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 10-17 */
4524 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 18-1F */
4525 DEF, DEF, DEF, DEF, DEF, DEF, R, DEF, /* 20-27 */
4526 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 28-2F */
4527 EN, EN, EN, EN, EN, EN, AN, AN, /* 30-37 */
4528 AN, AN, DEF, DEF, DEF, DEF, DEF, DEF, /* 38-3F */
4529 L, AL, AL, AL, AL, AL, AL, R, /* 40-47 */
4530 R, R, R, R, R, R, R, R, /* 48-4F */
4531 R, R, R, R, R, R, R, R, /* 50-57 */
4532 R, R, R, LRE, DEF, RLE, PDF, S, /* 58-5F */
4533 NSM, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 60-67 */
4534 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 68-6F */
4535 DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 70-77 */
4536 DEF, DEF, DEF, LRO, B, RLO, BN, DEF /* 78-7F */
4537 };
4538 static const int nEntries = UPRV_LENGTHOF(customClasses);
4539 const char *dummy = context; /* just to avoid a compiler warning */
4540 dummy++;
4541
4542 return c >= nEntries ? U_BIDI_CLASS_DEFAULT : customClasses[c];
4543 }
4544
4545 U_CDECL_END
4546
verifyCallbackParams(UBiDiClassCallback * fn,const void * context,UBiDiClassCallback * expectedFn,const void * expectedContext,int32_t sizeOfContext)4547 static void verifyCallbackParams(UBiDiClassCallback* fn, const void* context,
4548 UBiDiClassCallback* expectedFn,
4549 const void* expectedContext,
4550 int32_t sizeOfContext) {
4551 if (fn != expectedFn) {
4552 log_err("Class callback pointer is not set properly.\n");
4553 }
4554 if (context != expectedContext) {
4555 log_err("Class callback context is not set properly.\n");
4556 }
4557 else if (context != NULL &&
4558 memcmp(context, expectedContext, sizeOfContext)) {
4559 log_err("Callback context content doesn't match the expected one.\n");
4560 }
4561 }
4562
4563 static void
testClassOverride(void)4564 testClassOverride(void) {
4565 static const char* const textSrc = "JIH.>12->a \\u05D0\\u05D1 6 ABC78";
4566 static const char* const textResult = "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0";
4567
4568 UChar src[MAXLEN], dest[MAXLEN];
4569 UErrorCode rc = U_ZERO_ERROR;
4570 UBiDi *pBiDi = NULL;
4571 UBiDiClassCallback* oldFn = NULL;
4572 UBiDiClassCallback* newFn = overrideBidiClass;
4573 const void* oldContext = NULL;
4574 int32_t srcLen, destLen, textSrcSize = (int32_t)uprv_strlen(textSrc);
4575 char* destChars = NULL;
4576
4577 log_verbose("\nEntering TestClassOverride\n\n");
4578
4579 pBiDi = getBiDiObject();
4580 if(!pBiDi) {
4581 return;
4582 }
4583
4584 ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
4585 verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
4586
4587 ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
4588 if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
4589 ubidi_close(pBiDi);
4590 return;
4591 }
4592 verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
4593
4594 ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
4595 verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
4596
4597 ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
4598 if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
4599 ubidi_close(pBiDi);
4600 return;
4601 }
4602 verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
4603
4604 srcLen = u_unescape(textSrc, src, MAXLEN);
4605 ubidi_setPara(pBiDi, src, srcLen, UBIDI_LTR, NULL, &rc);
4606 assertSuccessful("ubidi_setPara", &rc);
4607
4608 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
4609 UBIDI_DO_MIRRORING, &rc);
4610 assertSuccessful("ubidi_writeReordered", &rc);
4611
4612 destChars = aescstrdup(dest, destLen);
4613 if (uprv_strcmp(textResult, destChars)) {
4614 log_err("\nActual and expected output mismatch.\n"
4615 "%20s %s\n%20s %s\n%20s %s\n",
4616 "Input:", textSrc, "Actual output:", destChars,
4617 "Expected output:", textResult);
4618 }
4619 else {
4620 log_verbose("\nClass override test OK\n");
4621 }
4622 ubidi_close(pBiDi);
4623 log_verbose("\nExiting TestClassOverride\n\n");
4624 }
4625
formatMap(const int32_t * map,int len,char * buffer)4626 static char * formatMap(const int32_t * map, int len, char * buffer)
4627 {
4628 int32_t i, k;
4629 char c;
4630 for (i = 0; i < len; i++) {
4631 k = map[i];
4632 if (k < 0)
4633 c = '-';
4634 else if (k >= (int32_t)sizeof(columns))
4635 c = '+';
4636 else
4637 c = columns[k];
4638 buffer[i] = c;
4639 }
4640 buffer[len] = '\0';
4641 return buffer;
4642 }
4643
4644 static UBool
checkMaps(UBiDi * pBiDi,int32_t stringIndex,const char * src,const char * dest,const char * mode,const char * option,UBiDiLevel level,UBool forward)4645 checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, const char *dest,
4646 const char *mode, const char* option, UBiDiLevel level, UBool forward)
4647 {
4648 int32_t actualLogicalMap[MAX_MAP_LENGTH];
4649 int32_t actualVisualMap[MAX_MAP_LENGTH];
4650 int32_t getIndexMap[MAX_MAP_LENGTH];
4651 int32_t i, srcLen, resLen, idx;
4652 const int32_t *expectedLogicalMap, *expectedVisualMap;
4653 UErrorCode rc = U_ZERO_ERROR;
4654 UBool testOK = TRUE;
4655
4656 if (forward) {
4657 expectedLogicalMap = forwardMap[stringIndex];
4658 expectedVisualMap = inverseMap[stringIndex];
4659 }
4660 else {
4661 expectedLogicalMap = inverseMap[stringIndex];
4662 expectedVisualMap = forwardMap[stringIndex];
4663 }
4664 ubidi_getLogicalMap(pBiDi, actualLogicalMap, &rc);
4665 if (!assertSuccessful("ubidi_getLogicalMap", &rc)) {
4666 testOK = FALSE;
4667 }
4668 srcLen = ubidi_getProcessedLength(pBiDi);
4669 if (memcmp(expectedLogicalMap, actualLogicalMap, srcLen * sizeof(int32_t))) {
4670 char expChars[MAX_MAP_LENGTH];
4671 char actChars[MAX_MAP_LENGTH];
4672 log_err("\nubidi_getLogicalMap() returns unexpected map for output string "
4673 "index %d\n"
4674 "source: %s\n"
4675 "dest : %s\n"
4676 "Scale : %s\n"
4677 "ExpMap: %s\n"
4678 "Actual: %s\n"
4679 "Paragraph level : %d == %d\n"
4680 "Reordering mode : %s == %d\n"
4681 "Reordering option: %s == %d\n"
4682 "Forward flag : %d\n",
4683 stringIndex, src, dest, columns,
4684 formatMap(expectedLogicalMap, srcLen, expChars),
4685 formatMap(actualLogicalMap, srcLen, actChars),
4686 level, ubidi_getParaLevel(pBiDi),
4687 mode, ubidi_getReorderingMode(pBiDi),
4688 option, ubidi_getReorderingOptions(pBiDi),
4689 forward
4690 );
4691 testOK = FALSE;
4692 }
4693 resLen = ubidi_getResultLength(pBiDi);
4694 ubidi_getVisualMap(pBiDi, actualVisualMap, &rc);
4695 assertSuccessful("ubidi_getVisualMap", &rc);
4696 if (memcmp(expectedVisualMap, actualVisualMap, resLen * sizeof(int32_t))) {
4697 char expChars[MAX_MAP_LENGTH];
4698 char actChars[MAX_MAP_LENGTH];
4699 log_err("\nubidi_getVisualMap() returns unexpected map for output string "
4700 "index %d\n"
4701 "source: %s\n"
4702 "dest : %s\n"
4703 "Scale : %s\n"
4704 "ExpMap: %s\n"
4705 "Actual: %s\n"
4706 "Paragraph level : %d == %d\n"
4707 "Reordering mode : %s == %d\n"
4708 "Reordering option: %s == %d\n"
4709 "Forward flag : %d\n",
4710 stringIndex, src, dest, columns,
4711 formatMap(expectedVisualMap, resLen, expChars),
4712 formatMap(actualVisualMap, resLen, actChars),
4713 level, ubidi_getParaLevel(pBiDi),
4714 mode, ubidi_getReorderingMode(pBiDi),
4715 option, ubidi_getReorderingOptions(pBiDi),
4716 forward
4717 );
4718 testOK = FALSE;
4719 }
4720 for (i = 0; i < srcLen; i++) {
4721 idx = ubidi_getVisualIndex(pBiDi, i, &rc);
4722 assertSuccessful("ubidi_getVisualIndex", &rc);
4723 getIndexMap[i] = idx;
4724 }
4725 if (memcmp(actualLogicalMap, getIndexMap, srcLen * sizeof(int32_t))) {
4726 char actChars[MAX_MAP_LENGTH];
4727 char gotChars[MAX_MAP_LENGTH];
4728 log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string "
4729 "index %d\n"
4730 "source: %s\n"
4731 "dest : %s\n"
4732 "Scale : %s\n"
4733 "ActMap: %s\n"
4734 "IdxMap: %s\n"
4735 "Paragraph level : %d == %d\n"
4736 "Reordering mode : %s == %d\n"
4737 "Reordering option: %s == %d\n"
4738 "Forward flag : %d\n",
4739 stringIndex, src, dest, columns,
4740 formatMap(actualLogicalMap, srcLen, actChars),
4741 formatMap(getIndexMap, srcLen, gotChars),
4742 level, ubidi_getParaLevel(pBiDi),
4743 mode, ubidi_getReorderingMode(pBiDi),
4744 option, ubidi_getReorderingOptions(pBiDi),
4745 forward
4746 );
4747 testOK = FALSE;
4748 }
4749 for (i = 0; i < resLen; i++) {
4750 idx = ubidi_getLogicalIndex(pBiDi, i, &rc);
4751 assertSuccessful("ubidi_getLogicalIndex", &rc);
4752 getIndexMap[i] = idx;
4753 }
4754 if (memcmp(actualVisualMap, getIndexMap, resLen * sizeof(int32_t))) {
4755 char actChars[MAX_MAP_LENGTH];
4756 char gotChars[MAX_MAP_LENGTH];
4757 log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string "
4758 "index %d\n"
4759 "source: %s\n"
4760 "dest : %s\n"
4761 "Scale : %s\n"
4762 "ActMap: %s\n"
4763 "IdxMap: %s\n"
4764 "Paragraph level : %d == %d\n"
4765 "Reordering mode : %s == %d\n"
4766 "Reordering option: %s == %d\n"
4767 "Forward flag : %d\n",
4768 stringIndex, src, dest, columns,
4769 formatMap(actualVisualMap, resLen, actChars),
4770 formatMap(getIndexMap, resLen, gotChars),
4771 level, ubidi_getParaLevel(pBiDi),
4772 mode, ubidi_getReorderingMode(pBiDi),
4773 option, ubidi_getReorderingOptions(pBiDi),
4774 forward
4775 );
4776 testOK = FALSE;
4777 }
4778 return testOK;
4779 }
4780
4781 static UBool
assertIllegalArgument(const char * message,UErrorCode * rc)4782 assertIllegalArgument(const char* message, UErrorCode* rc) {
4783 if (*rc != U_ILLEGAL_ARGUMENT_ERROR) {
4784 log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
4785 return FALSE;
4786 }
4787 return TRUE;
4788 }
4789
4790 typedef struct {
4791 const char* prologue;
4792 const char* source;
4793 const char* epilogue;
4794 const char* expected;
4795 UBiDiLevel paraLevel;
4796 } contextCase;
4797
4798 static const contextCase contextData[] = {
4799 /*00*/ {"", "", "", "", UBIDI_LTR},
4800 /*01*/ {"", ".-=JKL-+*", "", ".-=LKJ-+*", UBIDI_LTR},
4801 /*02*/ {" ", ".-=JKL-+*", " ", ".-=LKJ-+*", UBIDI_LTR},
4802 /*03*/ {"a", ".-=JKL-+*", "b", ".-=LKJ-+*", UBIDI_LTR},
4803 /*04*/ {"D", ".-=JKL-+*", "", "LKJ=-.-+*", UBIDI_LTR},
4804 /*05*/ {"", ".-=JKL-+*", " D", ".-=*+-LKJ", UBIDI_LTR},
4805 /*06*/ {"", ".-=JKL-+*", " 2", ".-=*+-LKJ", UBIDI_LTR},
4806 /*07*/ {"", ".-=JKL-+*", " 7", ".-=*+-LKJ", UBIDI_LTR},
4807 /*08*/ {" G 1", ".-=JKL-+*", " H", "*+-LKJ=-.", UBIDI_LTR},
4808 /*09*/ {"7", ".-=JKL-+*", " H", ".-=*+-LKJ", UBIDI_LTR},
4809 /*10*/ {"", ".-=abc-+*", "", "*+-abc=-.", UBIDI_RTL},
4810 /*11*/ {" ", ".-=abc-+*", " ", "*+-abc=-.", UBIDI_RTL},
4811 /*12*/ {"D", ".-=abc-+*", "G", "*+-abc=-.", UBIDI_RTL},
4812 /*13*/ {"x", ".-=abc-+*", "", "*+-.-=abc", UBIDI_RTL},
4813 /*14*/ {"", ".-=abc-+*", " y", "abc-+*=-.", UBIDI_RTL},
4814 /*15*/ {"", ".-=abc-+*", " 2", "abc-+*=-.", UBIDI_RTL},
4815 /*16*/ {" x 1", ".-=abc-+*", " 2", ".-=abc-+*", UBIDI_RTL},
4816 /*17*/ {" x 7", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL},
4817 /*18*/ {"x|", ".-=abc-+*", " 8", "*+-abc=-.", UBIDI_RTL},
4818 /*19*/ {"G|y", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL},
4819 /*20*/ {"", ".-=", "", ".-=", UBIDI_DEFAULT_LTR},
4820 /*21*/ {"D", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
4821 /*22*/ {"G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
4822 /*23*/ {"xG", ".-=", "", ".-=", UBIDI_DEFAULT_LTR},
4823 /*24*/ {"x|G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
4824 /*25*/ {"x|G", ".-=|-+*", "", "=-.|-+*", UBIDI_DEFAULT_LTR},
4825 };
4826 #define CONTEXT_COUNT UPRV_LENGTHOF(contextData)
4827
4828 static void
testContext(void)4829 testContext(void) {
4830
4831 UChar prologue[MAXLEN], epilogue[MAXLEN], src[MAXLEN], dest[MAXLEN];
4832 char destChars[MAXLEN];
4833 UBiDi *pBiDi = NULL;
4834 UErrorCode rc;
4835 int32_t proLength, epiLength, srcLen, destLen, tc;
4836 contextCase cc;
4837 UBool testOK = TRUE;
4838
4839 log_verbose("\nEntering TestContext \n\n");
4840
4841 /* test null BiDi object */
4842 rc = U_ZERO_ERROR;
4843 ubidi_setContext(pBiDi, NULL, 0, NULL, 0, &rc);
4844 testOK &= assertIllegalArgument("Error when BiDi object is null", &rc);
4845
4846 pBiDi = getBiDiObject();
4847 ubidi_orderParagraphsLTR(pBiDi, TRUE);
4848
4849 /* test proLength < -1 */
4850 rc = U_ZERO_ERROR;
4851 ubidi_setContext(pBiDi, NULL, -2, NULL, 0, &rc);
4852 testOK &= assertIllegalArgument("Error when proLength < -1", &rc);
4853 /* test epiLength < -1 */
4854 rc = U_ZERO_ERROR;
4855 ubidi_setContext(pBiDi, NULL, 0, NULL, -2, &rc);
4856 testOK &= assertIllegalArgument("Error when epiLength < -1", &rc);
4857 /* test prologue == NULL */
4858 rc = U_ZERO_ERROR;
4859 ubidi_setContext(pBiDi, NULL, 3, NULL, 0, &rc);
4860 testOK &= assertIllegalArgument("Prologue is NULL", &rc);
4861 /* test epilogue == NULL */
4862 rc = U_ZERO_ERROR;
4863 ubidi_setContext(pBiDi, NULL, 0, NULL, 4, &rc);
4864 testOK &= assertIllegalArgument("Epilogue is NULL", &rc);
4865
4866 for (tc = 0; tc < CONTEXT_COUNT; tc++) {
4867 cc = contextData[tc];
4868 proLength = (int32_t)strlen(cc.prologue);
4869 pseudoToU16(proLength, cc.prologue, prologue);
4870 epiLength = (int32_t)strlen(cc.epilogue);
4871 pseudoToU16(epiLength, cc.epilogue, epilogue);
4872 /* in the call below, prologue and epilogue are swapped to show
4873 that the next call will override this call */
4874 rc = U_ZERO_ERROR;
4875 ubidi_setContext(pBiDi, epilogue, epiLength, prologue, proLength, &rc);
4876 testOK &= assertSuccessful("swapped ubidi_setContext", &rc);
4877 ubidi_setContext(pBiDi, prologue, -1, epilogue, -1, &rc);
4878 testOK &= assertSuccessful("regular ubidi_setContext", &rc);
4879 srcLen = (int32_t)strlen(cc.source);
4880 pseudoToU16(srcLen, cc.source, src);
4881 ubidi_setPara(pBiDi, src, srcLen, cc.paraLevel, NULL, &rc);
4882 testOK &= assertSuccessful("ubidi_setPara", &rc);
4883 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
4884 assertSuccessful("ubidi_writeReordered", &rc);
4885 u16ToPseudo(destLen, dest, destChars);
4886 if (uprv_strcmp(cc.expected, destChars)) {
4887 char formatChars[MAXLEN];
4888 log_err("\nActual and expected output mismatch on case %d.\n"
4889 "%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",
4890 tc,
4891 "Prologue:", cc.prologue,
4892 "Input:", cc.source,
4893 "Epilogue:", cc.epilogue,
4894 "Expected output:", cc.expected,
4895 "Actual output:", destChars,
4896 "Levels:", formatLevels(pBiDi, formatChars),
4897 "Reordering mode:", ubidi_getReorderingMode(pBiDi),
4898 "Paragraph level:", ubidi_getParaLevel(pBiDi),
4899 "Reordering option:", ubidi_getReorderingOptions(pBiDi));
4900 testOK = FALSE;
4901 }
4902 }
4903 if (testOK == TRUE) {
4904 log_verbose("\nContext test OK\n");
4905 }
4906 ubidi_close(pBiDi);
4907
4908 log_verbose("\nExiting TestContext \n\n");
4909 }
4910
4911 /* Ticket#11054 ubidi_setPara crash with heavily nested brackets */
4912 static void
testBracketOverflow(void)4913 testBracketOverflow(void) {
4914 static const char* TEXT = "(((((((((((((((((((((((((((((((((((((((((a)(A)))))))))))))))))))))))))))))))))))))))))";
4915 UErrorCode status = U_ZERO_ERROR;
4916 UBiDi* bidi;
4917 UChar src[100];
4918 int32_t len;
4919
4920 bidi = ubidi_open();
4921 len = (int32_t)uprv_strlen(TEXT);
4922 pseudoToU16(len, TEXT, src);
4923 ubidi_setPara(bidi, src, len, UBIDI_DEFAULT_LTR , NULL, &status);
4924 if (U_FAILURE(status)) {
4925 log_err("setPara failed with heavily nested brackets - %s", u_errorName(status));
4926 }
4927
4928 ubidi_close(bidi);
4929 }
4930
TestExplicitLevel0(void)4931 static void TestExplicitLevel0(void) {
4932 // The following used to fail with an error, see ICU ticket #12922.
4933 static const UChar text[2] = { 0x202d, 0x05d0 };
4934 static UBiDiLevel embeddings[2] = { 0, 0 };
4935 UErrorCode errorCode = U_ZERO_ERROR;
4936 UBiDi *bidi = ubidi_open();
4937 ubidi_setPara(bidi, text, 2, UBIDI_DEFAULT_LTR , embeddings, &errorCode);
4938 if (U_FAILURE(errorCode)) {
4939 log_err("ubidi_setPara() - %s", u_errorName(errorCode));
4940 } else {
4941 UBiDiLevel level0 = ubidi_getLevelAt(bidi, 0);
4942 UBiDiLevel level1 = ubidi_getLevelAt(bidi, 1);
4943 if (level0 != 1 || level1 != 1) {
4944 log_err("resolved levels != 1: { %d, %d }\n", level0, level1);
4945 }
4946 if (embeddings[0] != 1 || embeddings[1] != 1) {
4947 log_err("modified embeddings[] levels != 1: { %d, %d }\n", embeddings[0], embeddings[1]);
4948 }
4949 }
4950 ubidi_close(bidi);
4951 }
4952