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