]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/cintltst/cbiditst.c
ICU-6.2.22.tar.gz
[apple/icu.git] / icuSources / test / cintltst / cbiditst.c
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2004, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /* file name: cbiditst.cpp
7 * encoding: US-ASCII
8 * tab size: 8 (not used)
9 * indentation:4
10 *
11 * created on: 1999sep27
12 * created by: Markus W. Scherer
13 */
14
15 #include "cintltst.h"
16 #include "unicode/utypes.h"
17 #include "unicode/uchar.h"
18 #include "unicode/ustring.h"
19 #include "unicode/ubidi.h"
20 #include "unicode/ushape.h"
21 #include "cmemory.h"
22 #include "cbiditst.h"
23 #include "cstring.h"
24
25 #define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
26
27 /* prototypes ---------------------------------------------------------------*/
28
29 static void
30 charFromDirPropTest(void);
31
32 static void
33 doBiDiTest(void);
34
35 static void
36 doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst);
37
38 static void
39 doTest(UBiDi *pBiDi, int testNumber, BiDiTestData *test, int32_t lineStart, UBool countRunsFirst);
40
41 static void
42 testReordering(UBiDi *pBiDi, int testNumber);
43
44 static void
45 doInverseBiDiTest(void);
46
47 static void
48 testManyInverseBiDi(UBiDi *pBiDi, UBiDiLevel direction);
49
50 static void
51 testInverseBiDi(UBiDi *pBiDi, const UChar *src, int32_t srcLength, UBiDiLevel direction, UErrorCode *pErrorCode);
52
53 static void
54 testWriteReverse(void);
55
56 static void
57 doArabicShapingTest(void);
58
59 static void
60 doLamAlefSpecialVLTRArabicShapingTest(void);
61
62 static void
63 doTashkeelSpecialVLTRArabicShapingTest(void);
64
65 static void
66 doLOGICALArabicDeShapingTest(void);
67
68 static void TestReorder(void);
69
70 /* helpers ------------------------------------------------------------------ */
71
72 static const char *levelString="...............................................................";
73
74 static void
75 initCharFromDirProps(void);
76
77 static UChar *
78 getStringFromDirProps(const uint8_t *dirProps, int32_t length);
79
80 static void
81 printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels);
82
83 /* regression tests ---------------------------------------------------------*/
84
85 void addComplexTest(TestNode** root);
86
87 void
88 addComplexTest(TestNode** root) {
89 addTest(root, charFromDirPropTest, "complex/bidi/charFromDirPropTest");
90 addTest(root, doBiDiTest, "complex/bidi/BiDiTest");
91 addTest(root, doInverseBiDiTest, "complex/bidi/inverse");
92 addTest(root, TestReorder,"complex/bidi/TestReorder");
93 addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest");
94 addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef");
95 addTest(root, doTashkeelSpecialVLTRArabicShapingTest, "complex/arabic-shaping/tashkeel");
96 addTest(root, doLOGICALArabicDeShapingTest, "complex/arabic-shaping/unshaping");
97 }
98
99 /* verify that the exemplar characters have the expected bidi classes */
100 static void
101 charFromDirPropTest(void) {
102 int32_t i;
103
104 initCharFromDirProps();
105
106 for(i=0; i<U_CHAR_DIRECTION_COUNT; ++i) {
107 if(u_charDirection(charFromDirProp[i])!=(UCharDirection)i) {
108 log_err("u_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n",
109 i, charFromDirProp[i], u_charDirection(charFromDirProp[i]), i);
110 }
111 }
112 }
113
114 static void
115 doBiDiTest() {
116 UBiDi *pBiDi, *pLine=NULL;
117 UErrorCode errorCode=U_ZERO_ERROR;
118
119 log_verbose("*** bidi regression test ***\n");
120
121 pBiDi=ubidi_openSized(MAX_STRING_LENGTH, 0, &errorCode);
122 if(pBiDi!=NULL) {
123 pLine=ubidi_open();
124 if(pLine!=NULL) {
125 doTests(pBiDi, pLine, FALSE);
126 doTests(pBiDi, pLine, TRUE);
127 } else {
128 log_err("ubidi_open() returned NULL, out of memory\n");
129 }
130 } else {
131 log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode));
132 }
133
134 if(pLine!=NULL) {
135 ubidi_close(pLine);
136 }
137 if(pBiDi!=NULL) {
138 ubidi_close(pBiDi);
139 }
140
141 log_verbose("*** bidi regression test finished ***\n");
142 }
143
144 static void
145 doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst) {
146 int i;
147 UChar *s;
148 UErrorCode errorCode;
149 int32_t lineStart;
150 UBiDiLevel paraLevel;
151
152 for(i=0; i<bidiTestCount; ++i) {
153 errorCode=U_ZERO_ERROR;
154 s=getStringFromDirProps(tests[i].text, tests[i].length);
155 paraLevel=tests[i].paraLevel;
156 ubidi_setPara(pBiDi, s, -1, paraLevel, NULL, &errorCode);
157 if(U_SUCCESS(errorCode)) {
158 log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n",
159 i, paraLevel, ubidi_getDirection(pBiDi), ubidi_getParaLevel(pBiDi));
160 lineStart=tests[i].lineStart;
161 if(lineStart==-1) {
162 doTest(pBiDi, i, tests+i, 0, countRunsFirst);
163 } else {
164 ubidi_setLine(pBiDi, lineStart, tests[i].lineLimit, pLine, &errorCode);
165 if(U_SUCCESS(errorCode)) {
166 log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n",
167 lineStart, tests[i].lineLimit, ubidi_getDirection(pLine), ubidi_getParaLevel(pLine));
168 doTest(pLine, i, tests+i, lineStart, countRunsFirst);
169 } else {
170 log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n",
171 i, lineStart, tests[i].lineLimit, myErrorName(errorCode));
172 }
173 }
174 } else {
175 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
176 i, paraLevel, myErrorName(errorCode));
177 }
178 }
179 }
180 static void TestReorder(){
181 static const char* const logicalOrder[] ={
182 "DEL(\\u062F\\u0625)ADD(\\u062F.\\u0625.\\u200F)",
183 "DEL(\\u0645\\u0627\\u064A\\u0648) ADD(\\u0623\\u064A\\u0627\\u0631)",
184 "DEL(\\u0644\\u0644)ADD(\\u0644.\\u0644.\\u0029\\u0644)\\u0644.\\u200F",
185 "DEL(\\u0631\\u064A)ADD(\\u0631.\\u064A.) \\u0631.\\u064A.\\u200F",
186 "DAY 2 \\u0646 \\u0627\\u0644\\u0627\\u062B\\u0646\\u064A\\u0646 DAYABBR",
187 "DAY 3 \\u062B \\u0627\\u0644\\u062B\\u0644\\u0627\\u062B\\u0627\\u0621 DAYABBR",
188 "DAY 4 \\u0631 \\u0627\\u0644\\u0623\\u0631\\u0628\\u0639\\u0627\\u0621 DAYABBR",
189 "DAY 5 \\u062E \\u0627\\u0644\\u062E\\u0645\\u064A\\u0633 DAYABBR",
190 "DAY 6 \\u062C \\u0627\\u0644\\u062C\\u0645\\u0639\\u0629 DAYABBR",
191 "DAY 7 \\u0633 \\u0627\\u0644\\u0633\\u0628\\u062A DAYABBR",
192 "HELLO\\u0627\\u0644\\u0633\\u0628\\u062A",
193 };
194 static const char* const visualOrder[]={
195 "DEL(\\u0625\\u062F)ADD(\\u200F.\\u0625.\\u062F)",
196 "DEL(\\u0648\\u064A\\u0627\\u0645) ADD(\\u0631\\u0627\\u064A\\u0623)",
197 "DEL(\\u0644\\u0644)ADD(\\u0644\\u0029.\\u0644.\\u0644)\\u200F.\\u0644",
198 /* I am doutful about this...
199 * what I would expect is :
200 * DEL(\\u064A\\u0631)ADD(.\\u064A.\\u0631) \\u200F.\\u064A.\\u0631
201 */
202 "DEL(\\u064A\\u0631)ADD(\\u200F.\\u064A.\\u0631 (.\\u064A.\\u0631",
203 "DAY 2 \\u0646\\u064A\\u0646\\u062B\\u0627\\u0644\\u0627 \\u0646 DAYABBR",
204 "DAY 3 \\u0621\\u0627\\u062B\\u0627\\u0644\\u062B\\u0644\\u0627 \\u062B DAYABBR",
205 "DAY 4 \\u0621\\u0627\\u0639\\u0628\\u0631\\u0623\\u0644\\u0627 \\u0631 DAYABBR",
206 "DAY 5 \\u0633\\u064A\\u0645\\u062E\\u0644\\u0627 \\u062E DAYABBR",
207 "DAY 6 \\u0629\\u0639\\u0645\\u062C\\u0644\\u0627 \\u062C DAYABBR",
208 "DAY 7 \\u062A\\u0628\\u0633\\u0644\\u0627 \\u0633 DAYABBR",
209 "HELLO\\u062A\\u0628\\u0633\\u0644\\u0627",
210 };
211 static const char* const visualOrder1[]={
212 ")\\u062F.\\u0625.\\u200F(DDA)\\u062F\\u0625(LED",
213 ")\\u0623\\u064A\\u0627\\u0631(DDA )\\u0645\\u0627\\u064A\\u0648(LED",
214 "\\u0644.\\u0644.(\\u0644(\\u0644.\\u200F(DDA)\\u0644\\u0644(LED",
215 "\\u0631.\\u064A.( \\u0631.\\u064A.\\u200F(DDA)\\u0631\\u064A(LED",
216 "RBBAYAD \\u0646 \\u0627\\u0644\\u0627\\u062B\\u0646\\u064A\\u0646 2 YAD",
217 "RBBAYAD \\u062B \\u0627\\u0644\\u062B\\u0644\\u0627\\u062B\\u0627\\u0621 3 YAD",
218 "RBBAYAD \\u0631 \\u0627\\u0644\\u0623\\u0631\\u0628\\u0639\\u0627\\u0621 4 YAD",
219 "RBBAYAD \\u062E \\u0627\\u0644\\u062E\\u0645\\u064A\\u0633 5 YAD",
220 "RBBAYAD \\u062C \\u0627\\u0644\\u062C\\u0645\\u0639\\u0629 6 YAD",
221 "RBBAYAD \\u0633 \\u0627\\u0644\\u0633\\u0628\\u062A 7 YAD",
222 "\\u0627\\u0644\\u0633\\u0628\\u062AOLLEH",
223 };
224
225 static const char* const visualOrder2[]={
226 "\\u200E)\\u200E\\u062F.\\u0625.\\u200F\\u200E(DDA)\\u200E\\u062F\\u0625\\u200E(LED",
227 "\\u200E)\\u200E\\u0623\\u064A\\u0627\\u0631\\u200E(DDA )\\u200E\\u0645\\u0627\\u064A\\u0648\\u200E(LED",
228 "\\u0644.\\u0644.)\\u0644)\\u0644.\\u200F\\u200E(DDA)\\u200E\\u0644\\u0644\\u200E(LED",
229 "\\u0631.\\u064A.) \\u0631.\\u064A.\\u200F\\u200E(DDA)\\u200E\\u0631\\u064A\\u200E(LED",
230 "RBBAYAD \\u200E\\u0646 \\u0627\\u0644\\u0627\\u062B\\u0646\\u064A\\u0646\\u200E 2 YAD",
231 "RBBAYAD \\u200E\\u062B \\u0627\\u0644\\u062B\\u0644\\u0627\\u062B\\u0627\\u0621\\u200E 3 YAD",
232 "RBBAYAD \\u200E\\u0631 \\u0627\\u0644\\u0623\\u0631\\u0628\\u0639\\u0627\\u0621\\u200E 4 YAD",
233 "RBBAYAD \\u200E\\u062E \\u0627\\u0644\\u062E\\u0645\\u064A\\u0633\\u200E 5 YAD",
234 "RBBAYAD \\u200E\\u062C \\u0627\\u0644\\u062C\\u0645\\u0639\\u0629\\u200E 6 YAD",
235 "RBBAYAD \\u200E\\u0633 \\u0627\\u0644\\u0633\\u0628\\u062A\\u200E 7 YAD",
236 "\\u0627\\u0644\\u0633\\u0628\\u062AOLLEH",
237 };
238 static const char* const visualOrder3[]={
239 ")\\u062F.\\u0625.\\u200F(DDA)\\u062F\\u0625(LED",
240 ")\\u0623\\u064A\\u0627\\u0631(DDA )\\u0645\\u0627\\u064A\\u0648(LED",
241 "\\u0644.\\u0644.)\\u0644)\\u0644.\\u200F(\\u0644\\u0644)DDA(LED",
242 "\\u0631.\\u064A.) \\u0631.\\u064A.\\u200F(\\u0631\\u064A)DDA(LED",
243 "RBBAYAD \\u0627\\u0644\\u0627\\u062B\\u0646\\u064A\\u0646 \\u0646 2 YAD",
244 "RBBAYAD \\u0627\\u0644\\u062B\\u0644\\u0627\\u062B\\u0627\\u0621 \\u062B 3 YAD",
245 "RBBAYAD \\u0627\\u0644\\u0623\\u0631\\u0628\\u0639\\u0627\\u0621 \\u0631 4 YAD",
246 "RBBAYAD \\u0627\\u0644\\u062E\\u0645\\u064A\\u0633 \\u062E 5 YAD",
247 "RBBAYAD \\u0627\\u0644\\u062C\\u0645\\u0639\\u0629 \\u062C",
248 "RBBAYAD \\u0627\\u0644\\u0633\\u0628\\u062A \\u0633 7 YAD",
249 "\\u0627\\u0644\\u0633\\u0628\\u062AOLLEH"
250 };
251 static const char* const visualOrder4[]={
252 "DEL(ADD(\\u0625\\u062F(.\\u0625.\\u062F)",
253 "DEL( (\\u0648\\u064A\\u0627\\u0645ADD(\\u0631\\u0627\\u064A\\u0623)",
254 "DEL(ADD(\\u0644\\u0644(.\\u0644(\\u0644(.\\u0644.\\u0644",
255 "DEL(ADD(\\u064A\\u0631(.\\u064A.\\u0631 (.\\u064A.\\u0631",
256 "DAY 2 \\u0646 \\u0646\\u064A\\u0646\\u062B\\u0627\\u0644\\u0627 DAYABBR",
257 "DAY 3 \\u062B \\u0621\\u0627\\u062B\\u0627\\u0644\\u062B\\u0644\\u0627 DAYABBR",
258 "DAY 4 \\u0631 \\u0621\\u0627\\u0639\\u0628\\u0631\\u0623\\u0644\\u0627 DAYABBR",
259 "DAY 5 \\u062E \\u0633\\u064A\\u0645\\u062E\\u0644\\u0627 DAYABBR",
260 "DAY 6 \\u062C \\u0629\\u0639\\u0645\\u062C\\u0644\\u0627 DAYABBR",
261 "DAY 7 \\u0633 \\u062A\\u0628\\u0633\\u0644\\u0627 DAYABBR ",
262 "HELLO\\u062A\\u0628\\u0633\\u0644\\u0627"
263 };
264 UErrorCode ec = U_ZERO_ERROR;
265 UBiDi* bidi = ubidi_open();
266 int i=0;
267 for(;i<(sizeof(logicalOrder)/sizeof(logicalOrder[0]));i++){
268 int32_t srcSize = (int32_t)uprv_strlen(logicalOrder[i]);
269 int32_t destSize = srcSize*2;
270 UChar* src = (UChar*) malloc(sizeof(UChar)*srcSize );
271 UChar* dest = (UChar*) malloc(sizeof(UChar)*destSize);
272 char* chars=NULL;
273 ec = U_ZERO_ERROR;
274 u_unescape(logicalOrder[i],src,srcSize);
275 srcSize= u_strlen(src);
276 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
277 if(U_FAILURE(ec)){
278 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
279 i, UBIDI_DEFAULT_LTR, u_errorName(ec));
280 }
281 /* try pre-flighting */
282 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
283 if(ec!=U_BUFFER_OVERFLOW_ERROR){
284 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
285 }else if(destSize!=srcSize){
286 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
287 }else{
288 ec= U_ZERO_ERROR;
289 }
290 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
291 chars = aescstrdup(dest,-1);
292 if(destSize!=srcSize){
293 log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
294 }else if(uprv_strncmp(visualOrder[i],chars,destSize)!=0){
295 log_err("ubidi_writeReordered() did not give expected results. Expected: %s Got: %s At Index: %d\n",visualOrder[i],chars,i);
296
297
298 }
299 free(src);
300 free(dest);
301 }
302
303 for(i=0;i<(sizeof(logicalOrder)/sizeof(logicalOrder[0]));i++){
304 int32_t srcSize = (int32_t)uprv_strlen(logicalOrder[i]);
305 int32_t destSize = srcSize*2;
306 UChar* src = (UChar*) malloc(sizeof(UChar)*srcSize );
307 UChar* dest = (UChar*) malloc(sizeof(UChar)*destSize);
308 char* chars=NULL;
309 ec = U_ZERO_ERROR;
310 u_unescape(logicalOrder[i],src,srcSize);
311 srcSize=u_strlen(src);
312 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
313 if(U_FAILURE(ec)){
314 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
315 i, UBIDI_DEFAULT_LTR, u_errorName(ec));
316 }
317 /* try pre-flighting */
318 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
319 if(ec!=U_BUFFER_OVERFLOW_ERROR){
320 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
321 }else if(destSize!=srcSize){
322 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
323 }else{
324 ec= U_ZERO_ERROR;
325 }
326 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
327 chars = aescstrdup(dest,destSize);
328 if(destSize!=srcSize){
329 log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
330 }else if(uprv_strncmp(visualOrder1[i],chars,destSize)!=0){
331 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE. Expected: %s Got: %s At Index: %d\n",visualOrder[i],chars,i);
332
333
334 }
335
336 free(src);
337 free(dest);
338 }
339
340 for(i=0;i<(sizeof(logicalOrder)/sizeof(logicalOrder[0]));i++){
341 int32_t srcSize = (int32_t)uprv_strlen(logicalOrder[i]);
342 int32_t destSize = srcSize*2;
343 UChar* src = (UChar*) malloc(sizeof(UChar)*srcSize );
344 UChar* dest = (UChar*) malloc(sizeof(UChar)*destSize);
345 char* chars=NULL;
346 ec = U_ZERO_ERROR;
347 u_unescape(logicalOrder[i],src,srcSize);
348 srcSize=u_strlen(src);
349 ubidi_setInverse(bidi,TRUE);
350 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
351
352 if(U_FAILURE(ec)){
353 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
354 i, UBIDI_DEFAULT_LTR, u_errorName(ec));
355 }
356 /* try pre-flighting */
357 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
358 if(ec!=U_BUFFER_OVERFLOW_ERROR){
359 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
360 }else{
361 ec= U_ZERO_ERROR;
362 }
363 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
364 chars = aescstrdup(dest,destSize);
365
366 /*if(destSize!=srcSize){
367 log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize );
368 }else*/
369 if(uprv_strncmp(visualOrder2[i],chars,destSize)!=0){
370 log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE. Expected: %s Got: %s At Index: %d\n",visualOrder[i],chars,i);
371
372
373 }
374
375 free(src);
376 free(dest);
377 }
378 /* Max Explicit level */
379 for(i=0;i<(sizeof(logicalOrder)/sizeof(logicalOrder[0]));i++){
380 int32_t srcSize = (int32_t)uprv_strlen(logicalOrder[i]);
381 int32_t destSize = srcSize*2;
382 UChar* src = (UChar*) malloc(sizeof(UChar)*srcSize );
383 UChar* dest = (UChar*) malloc(sizeof(UChar)*destSize);
384 char* chars=NULL;
385 UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
386 ec = U_ZERO_ERROR;
387 u_unescape(logicalOrder[i],src,srcSize);
388 srcSize=u_strlen(src);
389 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
390 if(U_FAILURE(ec)){
391 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
392 i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
393 }
394 /* try pre-flighting */
395 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_OUTPUT_REVERSE,&ec);
396 if(ec!=U_BUFFER_OVERFLOW_ERROR){
397 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
398 }else if(destSize!=srcSize){
399 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
400 }else{
401 ec= U_ZERO_ERROR;
402 }
403 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_OUTPUT_REVERSE,&ec);
404 chars = aescstrdup(dest,destSize);
405
406 if(destSize!=srcSize){
407 log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize );
408 }else if(uprv_strncmp(visualOrder3[i],chars,destSize)!=0){
409 log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE. Expected: %s Got: %s At Index: %d\n",visualOrder[i],chars,i);
410
411
412 }
413
414 free(src);
415 free(dest);
416 }
417 for(i=0;i<(sizeof(logicalOrder)/sizeof(logicalOrder[0]));i++){
418 int32_t srcSize = (int32_t)uprv_strlen(logicalOrder[i]);
419 int32_t destSize = srcSize*2;
420 UChar* src = (UChar*) malloc(sizeof(UChar)*srcSize );
421 UChar* dest = (UChar*) malloc(sizeof(UChar)*destSize);
422 char* chars=NULL;
423 UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
424 ec = U_ZERO_ERROR;
425 u_unescape(logicalOrder[i],src,srcSize);
426 srcSize=u_strlen(src);
427 ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
428 if(U_FAILURE(ec)){
429 log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
430 i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
431 }
432
433 /* try pre-flighting */
434 destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
435 if(ec!=U_BUFFER_OVERFLOW_ERROR){
436 log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
437 /*}else if(destSize!=srcSize){
438 log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);*/
439 }else{
440 ec= U_ZERO_ERROR;
441 }
442 destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
443 chars = aescstrdup(dest,destSize);
444
445 /*if(destSize!=srcSize){
446 log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize );
447 }else*/ if(uprv_strncmp(visualOrder4[i],chars,destSize)!=0){
448 log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS. Expected: %s Got: %s At Index: %d\n",visualOrder[i],chars,i);
449 }
450
451 free(src);
452 free(dest);
453 }
454 ubidi_close(bidi);
455 }
456
457 static void
458 doTest(UBiDi *pBiDi, int testNumber, BiDiTestData *test, int32_t lineStart, UBool countRunsFirst) {
459 const uint8_t *dirProps=test->text+lineStart;
460 const UBiDiLevel *levels=test->levels;
461 const uint8_t *visualMap=test->visualMap;
462 int32_t i, len=ubidi_getLength(pBiDi), logicalIndex, runCount = 0;
463 UErrorCode errorCode=U_ZERO_ERROR;
464 UBiDiLevel level, level2;
465
466 if (countRunsFirst) {
467 log_verbose("Calling ubidi_countRuns() first.\n");
468
469 runCount = ubidi_countRuns(pBiDi, &errorCode);
470
471 if(U_FAILURE(errorCode)) {
472 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
473 return;
474 }
475 } else {
476 log_verbose("Calling ubidi_getLogicalMap() first.\n");
477 }
478
479 testReordering(pBiDi, testNumber);
480
481 for(i=0; i<len; ++i) {
482 log_verbose("%3d %3d %.*s%-3s @%d\n",
483 i, ubidi_getLevelAt(pBiDi, i), ubidi_getLevelAt(pBiDi, i), levelString,
484 dirPropNames[dirProps[i]],
485 ubidi_getVisualIndex(pBiDi, i, &errorCode));
486 }
487
488 log_verbose("\n-----levels:");
489 for(i=0; i<len; ++i) {
490 if(i>0) {
491 log_verbose(",");
492 }
493 log_verbose(" %d", ubidi_getLevelAt(pBiDi, i));
494 }
495
496 log_verbose("\n--reordered:");
497 for(i=0; i<len; ++i) {
498 if(i>0) {
499 log_verbose(",");
500 }
501 log_verbose(" %d", ubidi_getVisualIndex(pBiDi, i, &errorCode));
502 }
503 log_verbose("\n");
504
505 if(test->direction!=ubidi_getDirection(pBiDi)) {
506 log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber, ubidi_getDirection(pBiDi));
507 }
508
509 if(test->resultLevel!=ubidi_getParaLevel(pBiDi)) {
510 log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber, ubidi_getParaLevel(pBiDi));
511 }
512
513 for(i=0; i<len; ++i) {
514 if(levels[i]!=ubidi_getLevelAt(pBiDi, i)) {
515 log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d\n", testNumber, i, ubidi_getLevelAt(pBiDi, i));
516 return;
517 }
518 }
519
520 for(i=0; i<len; ++i) {
521 logicalIndex=ubidi_getVisualIndex(pBiDi, i, &errorCode);
522 if(U_FAILURE(errorCode)) {
523 log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
524 return;
525 }
526 if(visualMap[i]!=logicalIndex) {
527 log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber, i, logicalIndex);
528 return;
529 }
530 }
531
532 if (! countRunsFirst) {
533 runCount=ubidi_countRuns(pBiDi, &errorCode);
534 if(U_FAILURE(errorCode)) {
535 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
536 return;
537 }
538 }
539
540 for(logicalIndex=0; logicalIndex<len;) {
541 level=ubidi_getLevelAt(pBiDi, logicalIndex);
542 ubidi_getLogicalRun(pBiDi, logicalIndex, &logicalIndex, &level2);
543 if(level!=level2) {
544 log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): wrong level %d\n", testNumber, logicalIndex, level2);
545 }
546 if(--runCount<0) {
547 log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs compared to %d=ubidi_getRunCount()\n", testNumber, ubidi_countRuns(pBiDi, &errorCode));
548 return;
549 }
550 }
551 if(runCount!=0) {
552 log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs compared to %d=ubidi_getRunCount()\n", testNumber, ubidi_countRuns(pBiDi, &errorCode));
553 return;
554 }
555
556 log_verbose("\n\n");
557 }
558
559 static void
560 testReordering(UBiDi *pBiDi, int testNumber) {
561 int32_t
562 logicalMap1[200], logicalMap2[200], logicalMap3[200],
563 visualMap1[200], visualMap2[200], visualMap3[200], visualMap4[200];
564 UErrorCode errorCode=U_ZERO_ERROR;
565 UBiDiLevel levels[200];
566 int32_t i, length=ubidi_getLength(pBiDi);
567 int32_t runCount, visualIndex, logicalStart, runLength;
568 UBool odd;
569
570 if(length<=0) {
571 return;
572 }
573
574 /* get the logical and visual maps from the object */
575 ubidi_getLogicalMap(pBiDi, logicalMap1, &errorCode);
576 if(U_FAILURE(errorCode)) {
577 log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
578 return;
579 }
580
581 ubidi_getVisualMap(pBiDi, visualMap1, &errorCode);
582
583 if(U_FAILURE(errorCode)) {
584 log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
585 return;
586 }
587
588 /* invert them both */
589 ubidi_invertMap(logicalMap1, visualMap2, length);
590 ubidi_invertMap(visualMap1, logicalMap2, length);
591
592 /* get them from the levels array, too */
593 uprv_memcpy(levels, ubidi_getLevels(pBiDi, &errorCode), length);
594
595 if(U_FAILURE(errorCode)) {
596 log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
597 return;
598 }
599
600 ubidi_reorderLogical(levels, length, logicalMap3);
601 ubidi_reorderVisual(levels, length, visualMap3);
602
603 /* get the visual map from the runs, too */
604 runCount=ubidi_countRuns(pBiDi, &errorCode);
605 if(U_FAILURE(errorCode)) {
606 log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
607 return;
608 }
609
610 log_verbose("\n----%2d runs:", runCount);
611 for(i=0; i<runCount; ++i) {
612 odd=(UBool)(ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength));
613 log_verbose(" (%c @%d[%d])", odd ? 'R' : 'L', logicalStart, runLength);
614 }
615 log_verbose("\n");
616
617 visualIndex=0;
618 for(i=0; i<runCount; ++i) {
619 if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength)) {
620 do { /* LTR */
621 visualMap4[visualIndex++]=logicalStart++;
622 } while(--runLength>0);
623 } else {
624 logicalStart+=runLength; /* logicalLimit */
625 do { /* RTL */
626 visualMap4[visualIndex++]=--logicalStart;
627 } while(--runLength>0);
628 }
629 }
630
631 /* print all the maps */
632 log_verbose("logical maps:\n");
633 for(i=0; i<length; ++i) {
634 log_verbose("%4d", logicalMap1[i]);
635 }
636 log_verbose("\n");
637 for(i=0; i<length; ++i) {
638 log_verbose("%4d", logicalMap2[i]);
639 }
640 log_verbose("\n");
641 for(i=0; i<length; ++i) {
642 log_verbose("%4d", logicalMap3[i]);
643 }
644
645 log_verbose("\nvisual maps:\n");
646 for(i=0; i<length; ++i) {
647 log_verbose("%4d", visualMap1[i]);
648 }
649 log_verbose("\n");
650 for(i=0; i<length; ++i) {
651 log_verbose("%4d", visualMap2[i]);
652 }
653 log_verbose("\n");
654 for(i=0; i<length; ++i) {
655 log_verbose("%4d", visualMap3[i]);
656 }
657 log_verbose("\n");
658 for(i=0; i<length; ++i) {
659 log_verbose("%4d", visualMap4[i]);
660 }
661 log_verbose("\n");
662
663 /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */
664 for(i=0; i<length; ++i) {
665 if(logicalMap1[i]!=logicalMap2[i]) {
666 log_verbose("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber, i);
667 break;
668 }
669 if(logicalMap1[i]!=logicalMap3[i]) {
670 log_verbose("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber, i);
671 break;
672 }
673
674 if(visualMap1[i]!=visualMap2[i]) {
675 log_verbose("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber, i);
676 break;
677 }
678 if(visualMap1[i]!=visualMap3[i]) {
679 log_verbose("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber, i);
680 break;
681 }
682 if(visualMap1[i]!=visualMap4[i]) {
683 log_verbose("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber, i);
684 break;
685 }
686
687 if(logicalMap1[i]!=ubidi_getVisualIndex(pBiDi, i, &errorCode)) {
688 log_verbose("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber, i);
689 break;
690 }
691 if(U_FAILURE(errorCode)) {
692 log_verbose("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
693 break;
694 }
695 if(visualMap1[i]!=ubidi_getLogicalIndex(pBiDi, i, &errorCode)) {
696 log_verbose("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber, i);
697 break;
698 }
699 if(U_FAILURE(errorCode)) {
700 log_verbose("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
701 break;
702 }
703 }
704 }
705
706
707 /* inverse BiDi ------------------------------------------------------------- */
708
709 static const UChar
710 string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 },
711 string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 },
712 string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 },
713 string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 },
714 string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 };
715
716 #define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
717
718 static const struct {
719 const UChar *s;
720 int32_t length;
721 } testCases[]={
722 STRING_TEST_CASE(string0),
723 STRING_TEST_CASE(string1),
724 STRING_TEST_CASE(string2),
725 STRING_TEST_CASE(string3)
726 };
727
728 static int countRoundtrips=0, countNonRoundtrips=0;
729
730 static void
731 doInverseBiDiTest() {
732 UBiDi *pBiDi;
733 UErrorCode errorCode;
734 int i;
735
736 pBiDi=ubidi_open();
737 if(pBiDi==NULL) {
738 log_err("unable to open a UBiDi object (out of memory)\n");
739 return;
740 }
741
742 log_verbose("inverse BiDi: testInverseBiDi(L) with %u test cases ---\n", LENGTHOF(testCases));
743 for(i=0; i<LENGTHOF(testCases); ++i) {
744 errorCode=U_ZERO_ERROR;
745 testInverseBiDi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode);
746 }
747
748 log_verbose("inverse BiDi: testInverseBiDi(R) with %u test cases ---\n", LENGTHOF(testCases));
749 for(i=0; i<LENGTHOF(testCases); ++i) {
750 errorCode=U_ZERO_ERROR;
751 testInverseBiDi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode);
752 }
753
754 testManyInverseBiDi(pBiDi, 0);
755 testManyInverseBiDi(pBiDi, 1);
756
757 ubidi_close(pBiDi);
758
759 log_verbose("inverse BiDi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips);
760
761 testWriteReverse();
762 }
763
764 #define COUNT_REPEAT_SEGMENTS 6
765
766 static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={
767 { 0x61, 0x62 }, /* L */
768 { 0x5d0, 0x5d1 }, /* R */
769 { 0x627, 0x628 }, /* AL */
770 { 0x31, 0x32 }, /* EN */
771 { 0x661, 0x662 }, /* AN */
772 { 0x20, 0x20 } /* WS (N) */
773 };
774
775 static void
776 testManyInverseBiDi(UBiDi *pBiDi, UBiDiLevel direction) {
777 static UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
778 int i, j, k;
779 UErrorCode errorCode;
780
781 log_verbose("inverse BiDi: testManyInverseBiDi(%c) - test permutations of text snippets ---\n", direction==0 ? 'L' : 'R');
782 for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) {
783 text[0]=repeatSegments[i][0];
784 text[1]=repeatSegments[i][1];
785 for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) {
786 text[3]=repeatSegments[j][0];
787 text[4]=repeatSegments[j][1];
788 for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) {
789 text[6]=repeatSegments[k][0];
790 text[7]=repeatSegments[k][1];
791
792 errorCode=U_ZERO_ERROR;
793 log_verbose("inverse BiDi: testManyInverseBiDi()[%u %u %u]\n", i, j, k);
794 testInverseBiDi(pBiDi, text, 8, direction, &errorCode);
795 }
796 }
797 }
798 }
799
800 static void
801 testInverseBiDi(UBiDi *pBiDi, const UChar *src, int32_t srcLength, UBiDiLevel direction, UErrorCode *pErrorCode) {
802 static UChar visualLTR[200], logicalDest[200], visualDest[200];
803 int32_t ltrLength, logicalLength, visualLength;
804
805 if(direction==0) {
806 log_verbose("inverse BiDi: testInverseBiDi(L)\n");
807
808 /* convert visual to logical */
809 ubidi_setInverse(pBiDi, TRUE);
810 ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode);
811 logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
812 UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
813 log_verbose(" v ");
814 printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode));
815 log_verbose("\n");
816
817 /* convert back to visual LTR */
818 ubidi_setInverse(pBiDi, FALSE);
819 ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
820 visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
821 UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode);
822 } else {
823 log_verbose("inverse BiDi: testInverseBiDi(R)\n");
824
825 /* reverse visual from RTL to LTR */
826 ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, LENGTHOF(visualLTR), 0, pErrorCode);
827 log_verbose(" vr");
828 printUnicode(src, srcLength, NULL);
829 log_verbose("\n");
830
831 /* convert visual RTL to logical */
832 ubidi_setInverse(pBiDi, TRUE);
833 ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode);
834 logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
835 UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
836 log_verbose(" vl");
837 printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode));
838 log_verbose("\n");
839
840 /* convert back to visual RTL */
841 ubidi_setInverse(pBiDi, FALSE);
842 ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
843 visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
844 UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode);
845 }
846 log_verbose(" l ");
847 printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode));
848 log_verbose("\n");
849 log_verbose(" v ");
850 printUnicode(visualDest, visualLength, NULL);
851 log_verbose("\n");
852
853 /* check and print results */
854 if(U_FAILURE(*pErrorCode)) {
855 log_err("inverse BiDi: *** error %s\n"
856 " turn on verbose mode to see details\n", u_errorName(*pErrorCode));
857 } else if(srcLength==visualLength && uprv_memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) {
858 ++countRoundtrips;
859 log_verbose(" + roundtripped\n");
860 } else {
861 ++countNonRoundtrips;
862 log_verbose(" * did not roundtrip\n");
863 log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n"
864 " turn on verbose mode to see details\n");
865 }
866 }
867
868 static void
869 testWriteReverse() {
870 /* U+064e and U+0650 are combining marks (Mn) */
871 static const UChar forward[]={
872 0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29
873 }, reverseKeepCombining[]={
874 0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f
875 }, reverseRemoveControlsKeepCombiningDoMirror[]={
876 0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650
877 };
878 static UChar reverse[10];
879 UErrorCode errorCode;
880 int32_t length;
881
882 /* test ubidi_writeReverse() with "interesting" options */
883 errorCode=U_ZERO_ERROR;
884 length=ubidi_writeReverse(forward, LENGTHOF(forward),
885 reverse, LENGTHOF(reverse),
886 UBIDI_KEEP_BASE_COMBINING,
887 &errorCode);
888 if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseKeepCombining) || uprv_memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) {
889 log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n",
890 length, LENGTHOF(reverseKeepCombining), u_errorName(errorCode));
891 }
892
893 uprv_memset(reverse, 0xa5, LENGTHOF(reverse)*U_SIZEOF_UCHAR);
894 errorCode=U_ZERO_ERROR;
895 length=ubidi_writeReverse(forward, LENGTHOF(forward),
896 reverse, LENGTHOF(reverse),
897 UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING,
898 &errorCode);
899 if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || uprv_memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) {
900 log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n"
901 " length=%d (should be %d), error code %s\n",
902 length, LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode));
903 }
904 }
905
906 /* arabic shaping ----------------------------------------------------------- */
907
908 static void
909 doArabicShapingTest() {
910 static const UChar
911 source[]={
912 0x31, /* en:1 */
913 0x627, /* arabic:alef */
914 0x32, /* en:2 */
915 0x6f3, /* an:3 */
916 0x61, /* latin:a */
917 0x34, /* en:4 */
918 0
919 }, en2an[]={
920 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0
921 }, an2en[]={
922 0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0
923 }, logical_alen2an_init_lr[]={
924 0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0
925 }, logical_alen2an_init_al[]={
926 0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0
927 }, reverse_alen2an_init_lr[]={
928 0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0
929 }, reverse_alen2an_init_al[]={
930 0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0
931 };
932 UChar dest[8];
933 UErrorCode errorCode;
934 int32_t length;
935
936 /* test number shaping */
937
938 /* european->arabic */
939 errorCode=U_ZERO_ERROR;
940 length=u_shapeArabic(source, LENGTHOF(source),
941 dest, LENGTHOF(dest),
942 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
943 &errorCode);
944 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || uprv_memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) {
945 log_err("failure in u_shapeArabic(en2an)\n");
946 }
947
948 /* arabic->european */
949 errorCode=U_ZERO_ERROR;
950 length=u_shapeArabic(source, -1,
951 dest, LENGTHOF(dest),
952 U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
953 &errorCode);
954 if(U_FAILURE(errorCode) || length!=u_strlen(source) || uprv_memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) {
955 log_err("failure in u_shapeArabic(an2en)\n");
956 }
957
958 /* european->arabic with context, logical order, initial state not AL */
959 errorCode=U_ZERO_ERROR;
960 length=u_shapeArabic(source, LENGTHOF(source),
961 dest, LENGTHOF(dest),
962 U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN,
963 &errorCode);
964 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || uprv_memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
965 log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n");
966 }
967
968 /* european->arabic with context, logical order, initial state AL */
969 errorCode=U_ZERO_ERROR;
970 length=u_shapeArabic(source, LENGTHOF(source),
971 dest, LENGTHOF(dest),
972 U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
973 &errorCode);
974 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || uprv_memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
975 log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n");
976 }
977
978 /* european->arabic with context, reverse order, initial state not AL */
979 errorCode=U_ZERO_ERROR;
980 length=u_shapeArabic(source, LENGTHOF(source),
981 dest, LENGTHOF(dest),
982 U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
983 &errorCode);
984 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || uprv_memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
985 log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n");
986 }
987
988 /* european->arabic with context, reverse order, initial state AL */
989 errorCode=U_ZERO_ERROR;
990 length=u_shapeArabic(source, LENGTHOF(source),
991 dest, LENGTHOF(dest),
992 U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
993 &errorCode);
994 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || uprv_memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
995 log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n");
996 }
997
998 /* test noop */
999 errorCode=U_ZERO_ERROR;
1000 length=u_shapeArabic(source, LENGTHOF(source),
1001 dest, LENGTHOF(dest),
1002 0,
1003 &errorCode);
1004 if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || uprv_memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) {
1005 log_err("failure in u_shapeArabic(noop)\n");
1006 }
1007
1008 errorCode=U_ZERO_ERROR;
1009 length=u_shapeArabic(source, 0,
1010 dest, LENGTHOF(dest),
1011 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
1012 &errorCode);
1013 if(U_FAILURE(errorCode) || length!=0) {
1014 log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), LENGTHOF(source));
1015 }
1016
1017 /* preflight digit shaping */
1018 errorCode=U_ZERO_ERROR;
1019 length=u_shapeArabic(source, LENGTHOF(source),
1020 NULL, 0,
1021 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
1022 &errorCode);
1023 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=LENGTHOF(source)) {
1024 log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n",
1025 length, u_errorName(errorCode), LENGTHOF(source));
1026 }
1027
1028 /* test illegal arguments */
1029 errorCode=U_ZERO_ERROR;
1030 length=u_shapeArabic(NULL, LENGTHOF(source),
1031 dest, LENGTHOF(dest),
1032 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
1033 &errorCode);
1034 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
1035 log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
1036 }
1037
1038 errorCode=U_ZERO_ERROR;
1039 length=u_shapeArabic(source, -2,
1040 dest, LENGTHOF(dest),
1041 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
1042 &errorCode);
1043 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
1044 log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
1045 }
1046
1047 errorCode=U_ZERO_ERROR;
1048 length=u_shapeArabic(source, LENGTHOF(source),
1049 NULL, LENGTHOF(dest),
1050 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
1051 &errorCode);
1052 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
1053 log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
1054 }
1055
1056 errorCode=U_ZERO_ERROR;
1057 length=u_shapeArabic(source, LENGTHOF(source),
1058 dest, -1,
1059 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
1060 &errorCode);
1061 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
1062 log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
1063 }
1064
1065 errorCode=U_ZERO_ERROR;
1066 length=u_shapeArabic(source, LENGTHOF(source),
1067 dest, LENGTHOF(dest),
1068 U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN,
1069 &errorCode);
1070 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
1071 log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
1072 }
1073
1074 errorCode=U_ZERO_ERROR;
1075 length=u_shapeArabic(source, LENGTHOF(source),
1076 dest, LENGTHOF(dest),
1077 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED,
1078 &errorCode);
1079 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
1080 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
1081 }
1082
1083 errorCode=U_ZERO_ERROR;
1084 length=u_shapeArabic(source, LENGTHOF(source),
1085 (UChar *)(source+2), LENGTHOF(dest), /* overlap source and destination */
1086 U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
1087 &errorCode);
1088 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
1089 log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
1090 }
1091 }
1092
1093 static void
1094 doLamAlefSpecialVLTRArabicShapingTest() {
1095 static const UChar
1096 source[]={
1097 /*a*/ 0x20 ,0x646,0x622,0x644,0x627,0x20,
1098 /*b*/ 0x646,0x623,0x64E,0x644,0x627,0x20,
1099 /*c*/ 0x646,0x627,0x670,0x644,0x627,0x20,
1100 /*d*/ 0x646,0x622,0x653,0x644,0x627,0x20,
1101 /*e*/ 0x646,0x625,0x655,0x644,0x627,0x20,
1102 /*f*/ 0x646,0x622,0x654,0x644,0x627,0x20,
1103 /*g*/ 0xFEFC,0x639
1104 }, shape_near[]={
1105 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
1106 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
1107 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
1108 0xfefc,0xfecb
1109 }, shape_at_end[]={
1110 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
1111 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
1112 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20
1113 }, shape_at_begin[]={
1114 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
1115 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
1116 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
1117 }, shape_grow_shrink[]={
1118 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
1119 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
1120 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
1121 }, shape_excepttashkeel_near[]={
1122 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
1123 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
1124 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
1125 0xfefc,0xfecb
1126 }, shape_excepttashkeel_at_end[]={
1127 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
1128 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
1129 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,
1130 0x20,0x20,0x20
1131 }, shape_excepttashkeel_at_begin[]={
1132 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
1133 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
1134 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
1135 }, shape_excepttashkeel_grow_shrink[]={
1136 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
1137 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
1138 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
1139 };
1140
1141 UChar dest[38];
1142 UErrorCode errorCode;
1143 int32_t length;
1144
1145 errorCode=U_ZERO_ERROR;
1146
1147 length=u_shapeArabic(source, LENGTHOF(source),
1148 dest, LENGTHOF(dest),
1149 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
1150 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1151 &errorCode);
1152
1153 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || uprv_memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
1154 log_err("failure in u_shapeArabic(LAMALEF shape_near)\n");
1155 }
1156
1157 errorCode=U_ZERO_ERROR;
1158
1159 length=u_shapeArabic(source, LENGTHOF(source),
1160 dest, LENGTHOF(dest),
1161 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
1162 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1163 &errorCode);
1164
1165 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_end) || uprv_memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) {
1166 log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n");
1167 }
1168
1169 errorCode=U_ZERO_ERROR;
1170
1171 length=u_shapeArabic(source, LENGTHOF(source),
1172 dest, LENGTHOF(dest),
1173 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
1174 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1175 &errorCode);
1176
1177 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_begin) || uprv_memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
1178 log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n");
1179 }
1180
1181 errorCode=U_ZERO_ERROR;
1182
1183 length=u_shapeArabic(source, LENGTHOF(source),
1184 dest, LENGTHOF(dest),
1185 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
1186 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1187 &errorCode);
1188
1189 if(U_FAILURE(errorCode) || uprv_memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
1190 log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n");
1191 }
1192
1193 /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */
1194
1195 errorCode=U_ZERO_ERROR;
1196
1197 length=u_shapeArabic(source, LENGTHOF(source),
1198 dest, LENGTHOF(dest),
1199 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
1200 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1201 &errorCode);
1202
1203 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || uprv_memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
1204 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n");
1205 }
1206
1207 errorCode=U_ZERO_ERROR;
1208
1209 length=u_shapeArabic(source, LENGTHOF(source),
1210 dest, LENGTHOF(dest),
1211 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
1212 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1213 &errorCode);
1214
1215 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_end) || uprv_memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) {
1216 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n");
1217 }
1218
1219 errorCode=U_ZERO_ERROR;
1220
1221 length=u_shapeArabic(source, LENGTHOF(source),
1222 dest, LENGTHOF(dest),
1223 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
1224 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1225 &errorCode);
1226
1227 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_begin) || uprv_memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) {
1228 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n");
1229 }
1230
1231 errorCode=U_ZERO_ERROR;
1232
1233 length=u_shapeArabic(source, LENGTHOF(source),
1234 dest, LENGTHOF(dest),
1235 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK|
1236 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1237 &errorCode);
1238
1239 if(U_FAILURE(errorCode) || uprv_memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
1240 log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n");
1241 }
1242 }
1243
1244 static void
1245 doTashkeelSpecialVLTRArabicShapingTest() {
1246 static const UChar
1247 source[]={
1248 0x64A,0x628,0x631,0x639,0x20,
1249 0x64A,0x628,0x651,0x631,0x64E,0x639,0x20,
1250 0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20,
1251 0x628,0x670,0x631,0x670,0x639,0x20,
1252 0x628,0x653,0x631,0x653,0x639,0x20,
1253 0x628,0x654,0x631,0x654,0x639,0x20,
1254 0x628,0x655,0x631,0x655,0x639,0x20,
1255 }, shape_near[]={
1256 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb,
1257 0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,
1258 0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,
1259 0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
1260 }, shape_excepttashkeel_near[]={
1261 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20,
1262 0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb,
1263 0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20,
1264 0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
1265 };
1266
1267 UChar dest[43];
1268 UErrorCode errorCode;
1269 int32_t length;
1270
1271 errorCode=U_ZERO_ERROR;
1272
1273 length=u_shapeArabic(source, LENGTHOF(source),
1274 dest, LENGTHOF(dest),
1275 U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
1276 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1277 &errorCode);
1278
1279 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || uprv_memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
1280 log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n");
1281 }
1282
1283 errorCode=U_ZERO_ERROR;
1284
1285 length=u_shapeArabic(source, LENGTHOF(source),
1286 dest, LENGTHOF(dest),
1287 U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
1288 U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
1289 &errorCode);
1290
1291 if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || uprv_memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
1292 log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n");
1293 }
1294 }
1295
1296 static void
1297 doLOGICALArabicDeShapingTest() {
1298 static const UChar
1299 source[]={
1300 0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020,
1301 0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4,
1302 0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020
1303 }, unshape_near[]={
1304 0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627,
1305 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
1306 0x629,0x20,0x20,0x20,0x20
1307 }, unshape_at_end[]={
1308 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
1309 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
1310 0x644,0x62d,0x631,0x629,0x20
1311 }, unshape_at_begin[]={
1312 0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20,
1313 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
1314 0x629,0x20,0x20,0x20,0x20
1315 }, unshape_grow_shrink[]={
1316 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
1317 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
1318 0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20
1319 };
1320
1321 UChar dest[36];
1322 UErrorCode errorCode;
1323 int32_t length;
1324
1325 errorCode=U_ZERO_ERROR;
1326
1327 length=u_shapeArabic(source, LENGTHOF(source),
1328 dest, LENGTHOF(dest),
1329 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
1330 U_SHAPE_TEXT_DIRECTION_LOGICAL,
1331 &errorCode);
1332
1333 if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_near) || uprv_memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) {
1334 log_err("failure in u_shapeArabic(unshape_near)\n");
1335 }
1336
1337 errorCode=U_ZERO_ERROR;
1338
1339 length=u_shapeArabic(source, LENGTHOF(source),
1340 dest, LENGTHOF(dest),
1341 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
1342 U_SHAPE_TEXT_DIRECTION_LOGICAL,
1343 &errorCode);
1344
1345 if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_end) || uprv_memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) {
1346 log_err("failure in u_shapeArabic(unshape_at_end)\n");
1347 }
1348
1349 errorCode=U_ZERO_ERROR;
1350
1351 length=u_shapeArabic(source, LENGTHOF(source),
1352 dest, LENGTHOF(dest),
1353 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
1354 U_SHAPE_TEXT_DIRECTION_LOGICAL,
1355 &errorCode);
1356
1357 if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_begin) || uprv_memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
1358 log_err("failure in u_shapeArabic(unshape_at_begin)\n");
1359 }
1360
1361 errorCode=U_ZERO_ERROR;
1362
1363 length=u_shapeArabic(source, LENGTHOF(source),
1364 dest, LENGTHOF(dest),
1365 U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
1366 U_SHAPE_TEXT_DIRECTION_LOGICAL,
1367 &errorCode);
1368
1369 if(U_FAILURE(errorCode) || uprv_memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
1370 log_err("failure in u_shapeArabic(unshape_grow_shrink)\n");
1371 }
1372
1373 }
1374
1375 /* helpers ------------------------------------------------------------------ */
1376
1377 static void
1378 initCharFromDirProps() {
1379 static const UVersionInfo ucd401={ 4, 0, 1, 0 };
1380 static UVersionInfo ucdVersion={ 0, 0, 0, 0 };
1381
1382 /* lazy initialization */
1383 if(ucdVersion[0]>0) {
1384 return;
1385 }
1386
1387 u_getUnicodeVersion(ucdVersion);
1388 if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) {
1389 /* Unicode 4.0.1 changes bidi classes for +-/ */
1390 charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */
1391 }
1392 }
1393
1394 /* return a string with characters according to the desired directional properties */
1395 static UChar *
1396 getStringFromDirProps(const uint8_t *dirProps, int32_t length) {
1397 static UChar s[MAX_STRING_LENGTH];
1398 int32_t i;
1399
1400 initCharFromDirProps();
1401
1402 /* this part would have to be modified for UTF-x */
1403 for(i=0; i<length; ++i) {
1404 s[i]=charFromDirProp[dirProps[i]];
1405 }
1406 s[i]=0;
1407 return s;
1408 }
1409
1410 static void
1411 printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) {
1412 int32_t i;
1413
1414 log_verbose("{ ");
1415 for(i=0; i<length; ++i) {
1416 if(levels!=NULL) {
1417 log_verbose("%4x.%u ", s[i], levels[i]);
1418 } else {
1419 log_verbose("%4x ", s[i]);
1420 }
1421 }
1422 log_verbose(" }");
1423 }