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