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