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