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