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