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