• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * COPYRIGHT:
5  * Copyright (c) 1998-2016, International Business Machines Corporation and
6  * others. All Rights Reserved.
7  ********************************************************************/
8 /*
9 * File test.c
10 *
11 * Modification History:
12 *
13 *   Date          Name        Description
14 *   05/01/2000    Madhu       Creation
15 *******************************************************************************
16 */
17 
18 #include "unicode/utypes.h"
19 #include "unicode/utf16.h"
20 #include "unicode/ustring.h"
21 #include "cmemory.h"
22 #include "cstring.h"
23 #include "cintltst.h"
24 #include <stdio.h>
25 
26 static void printUChars(const UChar *uchars);
27 
28 static void TestCodeUnitValues(void);
29 static void TestCharLength(void);
30 static void TestGetChar(void);
31 static void TestNextPrevChar(void);
32 static void TestNulTerminated(void);
33 static void TestFwdBack(void);
34 static void TestSetChar(void);
35 static void TestAppendChar(void);
36 static void TestAppend(void);
37 static void TestSurrogate(void);
38 
39 void addUTF16Test(TestNode** root);
40 
41 void
addUTF16Test(TestNode ** root)42 addUTF16Test(TestNode** root)
43 {
44     addTest(root, &TestCodeUnitValues,          "utf16tst/TestCodeUnitValues");
45     addTest(root, &TestCharLength,              "utf16tst/TestCharLength");
46     addTest(root, &TestGetChar,                 "utf16tst/TestGetChar");
47     addTest(root, &TestNextPrevChar,            "utf16tst/TestNextPrevChar");
48     addTest(root, &TestNulTerminated,           "utf16tst/TestNulTerminated");
49     addTest(root, &TestFwdBack,                 "utf16tst/TestFwdBack");
50     addTest(root, &TestSetChar,                 "utf16tst/TestSetChar");
51     addTest(root, &TestAppendChar,              "utf16tst/TestAppendChar");
52     addTest(root, &TestAppend,                  "utf16tst/TestAppend");
53     addTest(root, &TestSurrogate,               "utf16tst/TestSurrogate");
54 }
55 
TestCodeUnitValues()56 static void TestCodeUnitValues()
57 {
58     static uint16_t codeunit[]={0x0000,0xe065,0x20ac,0xd7ff,0xd800,0xd841,0xd905,0xdbff,0xdc00,0xdc02,0xddee,0xdfff,0};
59 
60     int16_t i;
61     for(i=0; i<UPRV_LENGTHOF(codeunit); i++){
62         UChar c=codeunit[i];
63         log_verbose("Testing code unit value of %x\n", c);
64         if(i<4){
65             if(!UTF16_IS_SINGLE(c) || UTF16_IS_LEAD(c) || UTF16_IS_TRAIL(c) || !U16_IS_SINGLE(c) || U16_IS_LEAD(c) || U16_IS_TRAIL(c)){
66                 log_err("ERROR: %x is a single character\n", c);
67             }
68         }
69         if(i >= 4 && i< 8){
70             if(!UTF16_IS_LEAD(c) || UTF16_IS_SINGLE(c) || UTF16_IS_TRAIL(c) || !U16_IS_LEAD(c) || U16_IS_SINGLE(c) || U16_IS_TRAIL(c)){
71                 log_err("ERROR: %x is a first surrogate\n", c);
72             }
73         }
74         if(i >= 8 && i< 12){
75             if(!UTF16_IS_TRAIL(c) || UTF16_IS_SINGLE(c) || UTF16_IS_LEAD(c) || !U16_IS_TRAIL(c) || U16_IS_SINGLE(c) || U16_IS_LEAD(c)){
76                 log_err("ERROR: %x is a second surrogate\n", c);
77             }
78         }
79     }
80 }
81 
TestCharLength()82 static void TestCharLength()
83 {
84     static uint32_t codepoint[]={
85         1, 0x0061,
86         1, 0xe065,
87         1, 0x20ac,
88         2, 0x20402,
89         2, 0x23456,
90         2, 0x24506,
91         2, 0x20402,
92         2, 0x10402,
93         1, 0xd7ff,
94         1, 0xe000
95     };
96 
97     int16_t i;
98     UBool multiple;
99     for(i=0; i<UPRV_LENGTHOF(codepoint); i=(int16_t)(i+2)){
100         UChar32 c=codepoint[i+1];
101         if(UTF16_CHAR_LENGTH(c) != (uint16_t)codepoint[i] || U16_LENGTH(c) != (uint16_t)codepoint[i]){
102               log_err("The no: of code units for %lx:- Expected: %d Got: %d\n", c, codepoint[i], UTF16_CHAR_LENGTH(c));
103         }else{
104               log_verbose("The no: of code units for %lx is %d\n",c, UTF16_CHAR_LENGTH(c) );
105         }
106         multiple=(UBool)(codepoint[i] == 1 ? FALSE : TRUE);
107         if(UTF16_NEED_MULTIPLE_UCHAR(c) != multiple){
108               log_err("ERROR: UTF16_NEED_MULTIPLE_UCHAR failed for %lx\n", c);
109         }
110     }
111 }
112 
TestGetChar()113 static void TestGetChar()
114 {
115     static UChar input[]={
116     /*  code unit,*/
117         0xdc00,
118         0x20ac,
119         0xd841,
120         0x61,
121         0xd841,
122         0xdc02,
123         0xd842,
124         0xdc06,
125         0,
126         0xd842,
127         0xd7ff,
128         0xdc41,
129         0xe000,
130         0xd800
131     };
132     static UChar32 result[]={
133      /*codepoint-unsafe,  codepoint-safe(not strict)  codepoint-safe(strict)*/
134         (UChar32)0xfca10000, 0xdc00,                  UTF_ERROR_VALUE,
135         0x20ac,           0x20ac,                     0x20ac,
136         0x12861,          0xd841,                     UTF_ERROR_VALUE,
137         0x61,             0x61,                       0x61,
138         0x20402,          0x20402,                    0x20402,
139         0x20402,          0x20402,                    0x20402,
140         0x20806,          0x20806,                    0x20806,
141         0x20806,          0x20806,                    0x20806,
142         0x00,             0x00,                       0x00,
143         0x203ff,          0xd842,                     UTF_ERROR_VALUE,
144         0xd7ff,           0xd7ff,                     0xd7ff,
145         0xfc41,           0xdc41,                     UTF_ERROR_VALUE,
146         0xe000,           0xe000,                     0xe000,
147         0x11734,          0xd800,                     UTF_ERROR_VALUE
148     };
149     uint16_t i=0;
150     UChar32 c;
151     uint16_t offset=0;
152     for(offset=0; offset<UPRV_LENGTHOF(input); offset++) {
153         if(0<offset && offset<UPRV_LENGTHOF(input)-1){
154             UTF16_GET_CHAR_UNSAFE(input, offset, c);
155             if(c != result[i]){
156                 log_err("ERROR: UTF16_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
157             }
158 
159             U16_GET_UNSAFE(input, offset, c);
160             if(c != result[i]){
161                 log_err("ERROR: U16_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
162             }
163         }
164 
165         UTF16_GET_CHAR_SAFE(input, 0, offset, UPRV_LENGTHOF(input), c, FALSE);
166         if(c != result[i+1]){
167             log_err("ERROR: UTF16_GET_CHAR_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
168         }
169 
170         U16_GET(input, 0, offset, UPRV_LENGTHOF(input), c);
171         if(c != result[i+1]){
172             log_err("ERROR: U16_GET failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
173         }
174 
175         UTF16_GET_CHAR_SAFE(input, 0, offset, UPRV_LENGTHOF(input), c, TRUE);
176         if(c != result[i+2]){
177             log_err("ERROR: UTF16_GET_CHAR_SAFE(strict) failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c);
178         }
179         i=(uint16_t)(i+3);
180     }
181 
182 }
183 
TestNextPrevChar()184 static void TestNextPrevChar(){
185 
186     static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
187     static UChar32 result[]={
188     /*next_unsafe    next_safe_ns  next_safe_s       prev_unsafe   prev_safe_ns     prev_safe_s*/
189         0x0061,        0x0061,       0x0061,           0x0000,       0x0000,          0x0000,
190         0x10000,       0x10000,      0x10000,          0x120400,     0xdc00,          UTF_ERROR_VALUE,
191         0xdc00,        0xdc00,       UTF_ERROR_VALUE,  0x20441,      0x20441,         0x20441,
192         0x10ffff,      0x10ffff,     0x10ffff,         0xd841,       0xd841,          UTF_ERROR_VALUE,
193         0xdfff,        0xdfff,       UTF_ERROR_VALUE,  0xd7ff,       0xd7ff,          0xd7ff,
194         0x0062,        0x0062,       0x0062,           0xd841,       0xd841,          UTF_ERROR_VALUE,
195         0x1ffff,       0xd841,       UTF_ERROR_VALUE,  0x0062,       0x0062,          0x0062,
196         0xd7ff,        0xd7ff,       0xd7ff,           0x10ffff,     0x10ffff,        0x10ffff,
197         0x20441,       0x20441,      0x20441,          0xdbff,       0xdbff,          UTF_ERROR_VALUE,
198         0xdc41,        0xdc41,       UTF_ERROR_VALUE,  0x10000,      0x10000,         0x10000,
199         0xdc00,        0xdc00,       UTF_ERROR_VALUE,  0xd800,       0xd800,          UTF_ERROR_VALUE,
200         0x0000,        0x0000,       0x0000,           0x0061,       0x0061,          0x0061
201     };
202     static uint16_t movedOffset[]={
203    /*next_unsafe    next_safe_ns  next_safe_s       prev_unsafe   prev_safe_ns     prev_safe_s*/
204         1,            1,           1,                11,           11,               11,
205         3,            3,           3,                9,            10 ,              10,
206         3,            3,           3,                8,            8,                8,
207         5,            5,           4,                8,            8,                8,
208         5,            5,           5,                7,            7,                7,
209         6,            6,           6,                6,            6,                6,
210         8,            7,           7,                5,            5,                5,
211         8,            8,           8,                3,            3,                3,
212         10,           10,          10,               3,            3,                3,
213         10,           10,          10,               1,            1,                1,
214         11,           11,          11,               1,            1,                1,
215         12,           12,          12,               0,            0,                0,
216     };
217 
218 
219     UChar32 c=0x0000;
220     uint16_t i=0;
221     uint16_t offset=0, setOffset=0;
222     for(offset=0; offset<UPRV_LENGTHOF(input); offset++){
223          setOffset=offset;
224          UTF16_NEXT_CHAR_UNSAFE(input, setOffset, c);
225          if(setOffset != movedOffset[i]){
226              log_err("ERROR: UTF16_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
227                  offset, movedOffset[i], setOffset);
228          }
229          if(c != result[i]){
230              log_err("ERROR: UTF16_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
231          }
232 
233          setOffset=offset;
234          U16_NEXT_UNSAFE(input, setOffset, c);
235          if(setOffset != movedOffset[i]){
236              log_err("ERROR: U16_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
237                  offset, movedOffset[i], setOffset);
238          }
239          if(c != result[i]){
240              log_err("ERROR: U16_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
241          }
242 
243          setOffset=offset;
244          UTF16_NEXT_CHAR_SAFE(input, setOffset, UPRV_LENGTHOF(input), c, FALSE);
245          if(setOffset != movedOffset[i+1]){
246              log_err("ERROR: UTF16_NEXT_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
247                  offset, movedOffset[i+1], setOffset);
248          }
249          if(c != result[i+1]){
250              log_err("ERROR: UTF16_NEXT_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
251          }
252 
253          setOffset=offset;
254          U16_NEXT(input, setOffset, UPRV_LENGTHOF(input), c);
255          if(setOffset != movedOffset[i+1]){
256              log_err("ERROR: U16_NEXT failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
257                  offset, movedOffset[i+1], setOffset);
258          }
259          if(c != result[i+1]){
260              log_err("ERROR: U16_NEXT failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
261          }
262 
263          setOffset=offset;
264          UTF16_NEXT_CHAR_SAFE(input, setOffset, UPRV_LENGTHOF(input), c, TRUE);
265          if(setOffset != movedOffset[i+1]){
266              log_err("ERROR: UTF16_NEXT_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
267                  offset, movedOffset[i+2], setOffset);
268          }
269          if(c != result[i+2]){
270              log_err("ERROR: UTF16_NEXT_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c);
271          }
272 
273          i=(uint16_t)(i+6);
274     }
275     i=0;
276     for(offset=(uint16_t)UPRV_LENGTHOF(input); offset > 0; --offset){
277          setOffset=offset;
278          UTF16_PREV_CHAR_UNSAFE(input, setOffset, c);
279          if(setOffset != movedOffset[i+3]){
280              log_err("ERROR: UTF16_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
281                  offset, movedOffset[i+3], setOffset);
282          }
283          if(c != result[i+3]){
284              log_err("ERROR: UTF16_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c);
285          }
286 
287          setOffset=offset;
288          U16_PREV_UNSAFE(input, setOffset, c);
289          if(setOffset != movedOffset[i+3]){
290              log_err("ERROR: U16_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
291                  offset, movedOffset[i+3], setOffset);
292          }
293          if(c != result[i+3]){
294              log_err("ERROR: U16_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c);
295          }
296 
297          setOffset=offset;
298          UTF16_PREV_CHAR_SAFE(input, 0, setOffset, c, FALSE);
299          if(setOffset != movedOffset[i+4]){
300              log_err("ERROR: UTF16_PREV_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
301                  offset, movedOffset[i+4], setOffset);
302          }
303          if(c != result[i+4]){
304              log_err("ERROR: UTF16_PREV_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c);
305          }
306 
307          setOffset=offset;
308          U16_PREV(input, 0, setOffset, c);
309          if(setOffset != movedOffset[i+4]){
310              log_err("ERROR: U16_PREV failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
311                  offset, movedOffset[i+4], setOffset);
312          }
313          if(c != result[i+4]){
314              log_err("ERROR: U16_PREV failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c);
315          }
316 
317          setOffset=offset;
318          UTF16_PREV_CHAR_SAFE(input, 0,  setOffset, c, TRUE);
319          if(setOffset != movedOffset[i+5]){
320              log_err("ERROR: UTF16_PREV_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
321                  offset, movedOffset[i+5], setOffset);
322          }
323          if(c != result[i+5]){
324              log_err("ERROR: UTF16_PREV_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+5], c);
325          }
326 
327          i=(uint16_t)(i+6);
328     }
329 
330 }
331 
332 /* keep this in sync with utf8tst.c's TestNulTerminated() */
TestNulTerminated()333 static void TestNulTerminated() {
334     static const UChar input[]={
335         /*  0 */  0x61,
336         /*  1 */  0xd801, 0xdc01,
337         /*  3 */  0xdc01,
338         /*  4 */  0x62,
339         /*  5 */  0xd801,
340         /*  6 */  0x00
341         /*  7 */
342     };
343     static const UChar32 result[]={
344         0x61,
345         0x10401,
346         0xdc01,
347         0x62,
348         0xd801,
349         0
350     };
351 
352     UChar32 c, c2;
353     int32_t i0, i=0, j, k, expectedIndex;
354     int32_t cpIndex=0;
355     do {
356         i0=i;
357         U16_NEXT(input, i, -1, c);
358         if(c!=result[cpIndex]) {
359             log_err("U16_NEXT(from %d)=U+%04x != U+%04x\n", i0, c, result[cpIndex]);
360         }
361         j=i0;
362         U16_FWD_1(input, j, -1);
363         if(j!=i) {
364             log_err("U16_FWD_1() moved to index %d but U16_NEXT() moved to %d\n", j, i);
365         }
366         ++cpIndex;
367         /*
368          * Move by this many code points from the start.
369          * U16_FWD_N() stops at the end of the string, that is, at the NUL if necessary.
370          */
371         expectedIndex= (c==0) ? i-1 : i;
372         k=0;
373         U16_FWD_N(input, k, -1, cpIndex);
374         if(k!=expectedIndex) {
375             log_err("U16_FWD_N(code points from 0) moved to index %d but expected %d\n", k, expectedIndex);
376         }
377     } while(c!=0);
378 
379     i=0;
380     do {
381         j=i0=i;
382         U16_NEXT(input, i, -1, c);
383         do {
384             U16_GET(input, 0, j, -1, c2);
385             if(c2!=c) {
386                 log_err("U16_NEXT(from %d)=U+%04x != U+%04x=U16_GET(at %d)\n", i0, c, c2, j);
387             }
388             /* U16_SET_CP_LIMIT moves from a non-lead byte to the limit of the code point */
389             k=j+1;
390             U16_SET_CP_LIMIT(input, 0, k, -1);
391             if(k!=i) {
392                 log_err("U16_NEXT() moved to %d but U16_SET_CP_LIMIT(%d) moved to %d\n", i, j+1, k);
393             }
394         } while(++j<i);
395     } while(c!=0);
396 }
397 
TestFwdBack()398 static void TestFwdBack(){
399     static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
400     static uint16_t fwd_unsafe[] ={1, 3, 5, 6,  8, 10, 11, 12};
401     static uint16_t fwd_safe[]   ={1, 3, 5, 6, 7, 8, 10, 11, 12};
402     static uint16_t back_unsafe[]={11, 9, 8, 7, 6, 5, 3, 1, 0};
403     static uint16_t back_safe[]  ={11, 10, 8, 7, 6, 5, 3, 1, 0};
404 
405     static uint16_t Nvalue[]= {0, 1, 2, 3, 1, 2, 1};
406     static uint16_t fwd_N_unsafe[] ={0, 1, 5, 10, 11};
407     static uint16_t fwd_N_safe[]   ={0, 1, 5, 8, 10, 12, 12}; /*safe macro keeps it at the end of the string */
408     static uint16_t back_N_unsafe[]={12, 11, 8, 5, 3};
409     static uint16_t back_N_safe[]  ={12, 11, 8, 5, 3, 0, 0};
410 
411     uint16_t offunsafe=0, offsafe=0;
412     uint16_t i=0;
413     while(offunsafe < UPRV_LENGTHOF(input)){
414         UTF16_FWD_1_UNSAFE(input, offunsafe);
415         if(offunsafe != fwd_unsafe[i]){
416             log_err("ERROR: Forward_unsafe offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
417         }
418         i++;
419     }
420 
421     offunsafe=0, offsafe=0;
422     i=0;
423     while(offunsafe < UPRV_LENGTHOF(input)){
424         U16_FWD_1_UNSAFE(input, offunsafe);
425         if(offunsafe != fwd_unsafe[i]){
426             log_err("ERROR: U16_FWD_1_UNSAFE offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
427         }
428         i++;
429     }
430 
431     i=0;
432     while(offsafe < UPRV_LENGTHOF(input)){
433         UTF16_FWD_1_SAFE(input, offsafe, UPRV_LENGTHOF(input));
434         if(offsafe != fwd_safe[i]){
435             log_err("ERROR: Forward_safe offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
436         }
437         i++;
438     }
439 
440     i=0;
441     while(offsafe < UPRV_LENGTHOF(input)){
442         U16_FWD_1(input, offsafe, UPRV_LENGTHOF(input));
443         if(offsafe != fwd_safe[i]){
444             log_err("ERROR: U16_FWD_1 offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
445         }
446         i++;
447     }
448 
449     offunsafe=UPRV_LENGTHOF(input);
450     offsafe=UPRV_LENGTHOF(input);
451     i=0;
452     while(offunsafe > 0){
453         UTF16_BACK_1_UNSAFE(input, offunsafe);
454         if(offunsafe != back_unsafe[i]){
455             log_err("ERROR: Backward_unsafe offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
456         }
457         i++;
458     }
459 
460     offunsafe=UPRV_LENGTHOF(input);
461     offsafe=UPRV_LENGTHOF(input);
462     i=0;
463     while(offunsafe > 0){
464         U16_BACK_1_UNSAFE(input, offunsafe);
465         if(offunsafe != back_unsafe[i]){
466             log_err("ERROR: U16_BACK_1_UNSAFE offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
467         }
468         i++;
469     }
470 
471     i=0;
472     while(offsafe > 0){
473         UTF16_BACK_1_SAFE(input,0,  offsafe);
474         if(offsafe != back_safe[i]){
475             log_err("ERROR: Backward_safe offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
476         }
477         i++;
478     }
479 
480     i=0;
481     while(offsafe > 0){
482         U16_BACK_1(input,0,  offsafe);
483         if(offsafe != back_safe[i]){
484             log_err("ERROR: U16_BACK_1 offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
485         }
486         i++;
487     }
488 
489     offunsafe=0;
490     offsafe=0;
491     for(i=0; i<UPRV_LENGTHOF(Nvalue)-2; i++){  /*didn't want it to fail(we assume 0<i<length)*/
492         UTF16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
493         if(offunsafe != fwd_N_unsafe[i]){
494             log_err("ERROR: Forward_N_unsafe offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe);
495         }
496     }
497 
498     offunsafe=0;
499     for(i=0; i<UPRV_LENGTHOF(Nvalue)-2; i++){  /*didn't want it to fail(we assume 0<i<length)*/
500         U16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
501         if(offunsafe != fwd_N_unsafe[i]){
502             log_err("ERROR: U16_FWD_N_UNSAFE offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe);
503         }
504     }
505 
506     offsafe=0;
507     for(i=0; i<UPRV_LENGTHOF(Nvalue); i++){
508         UTF16_FWD_N_SAFE(input, offsafe, UPRV_LENGTHOF(input), Nvalue[i]);
509         if(offsafe != fwd_N_safe[i]){
510             log_err("ERROR: Forward_N_safe offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe);
511         }
512 
513     }
514 
515     offsafe=0;
516     for(i=0; i<UPRV_LENGTHOF(Nvalue); i++){
517         U16_FWD_N(input, offsafe, UPRV_LENGTHOF(input), Nvalue[i]);
518         if(offsafe != fwd_N_safe[i]){
519             log_err("ERROR: U16_FWD_N offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe);
520         }
521 
522     }
523 
524     offunsafe=UPRV_LENGTHOF(input);
525     for(i=0; i<UPRV_LENGTHOF(Nvalue)-2; i++){
526         UTF16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
527         if(offunsafe != back_N_unsafe[i]){
528             log_err("ERROR: backward_N_unsafe offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe);
529         }
530     }
531 
532     offunsafe=UPRV_LENGTHOF(input);
533     for(i=0; i<UPRV_LENGTHOF(Nvalue)-2; i++){
534         U16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
535         if(offunsafe != back_N_unsafe[i]){
536             log_err("ERROR: U16_BACK_N_UNSAFE offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe);
537         }
538     }
539 
540     offsafe=UPRV_LENGTHOF(input);
541     for(i=0; i<UPRV_LENGTHOF(Nvalue); i++){
542         UTF16_BACK_N_SAFE(input, 0, offsafe, Nvalue[i]);
543         if(offsafe != back_N_safe[i]){
544             log_err("ERROR: backward_N_safe offset expected:%d, Got:%d\n", back_N_safe[i], offsafe);
545         }
546     }
547 
548     offsafe=UPRV_LENGTHOF(input);
549     for(i=0; i<UPRV_LENGTHOF(Nvalue); i++){
550         U16_BACK_N(input, 0, offsafe, Nvalue[i]);
551         if(offsafe != back_N_safe[i]){
552             log_err("ERROR: U16_BACK_N offset expected:%d, Got:%d\n", back_N_safe[i], offsafe);
553         }
554     }
555 }
556 
TestSetChar()557 static void TestSetChar(){
558     static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
559     static uint16_t start_unsafe[]={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 9, 11};
560     static uint16_t start_safe[]  ={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 10, 11};
561     static uint16_t limit_unsafe[]={0, 1, 3, 3, 5, 5, 6, 8, 8, 10, 10, 11};
562     static uint16_t limit_safe[]  ={0, 1, 3, 3, 5, 5, 6, 7, 8, 10, 10, 11};
563 
564     uint16_t i=0;
565     uint16_t offset=0, setOffset=0;
566     for(offset=0; offset<UPRV_LENGTHOF(input); offset++){
567          setOffset=offset;
568          UTF16_SET_CHAR_START_UNSAFE(input, setOffset);
569          if(setOffset != start_unsafe[i]){
570              log_err("ERROR: UTF16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset);
571          }
572 
573          setOffset=offset;
574          U16_SET_CP_START_UNSAFE(input, setOffset);
575          if(setOffset != start_unsafe[i]){
576              log_err("ERROR: U16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset);
577          }
578 
579          setOffset=offset;
580          UTF16_SET_CHAR_START_SAFE(input, 0, setOffset);
581          if(setOffset != start_safe[i]){
582              log_err("ERROR: UTF16_SET_CHAR_START_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset);
583          }
584 
585          setOffset=offset;
586          U16_SET_CP_START(input, 0, setOffset);
587          if(setOffset != start_safe[i]){
588              log_err("ERROR: U16_SET_CHAR_START failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset);
589          }
590 
591          if (offset > 0) {
592              setOffset=offset;
593              UTF16_SET_CHAR_LIMIT_UNSAFE(input, setOffset);
594              if(setOffset != limit_unsafe[i]){
595                  log_err("ERROR: UTF16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset);
596              }
597 
598              setOffset=offset;
599              U16_SET_CP_LIMIT_UNSAFE(input, setOffset);
600              if(setOffset != limit_unsafe[i]){
601                  log_err("ERROR: U16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset);
602              }
603          }
604 
605          setOffset=offset;
606          U16_SET_CP_LIMIT(input,0, setOffset, UPRV_LENGTHOF(input));
607          if(setOffset != limit_safe[i]){
608              log_err("ERROR: U16_SET_CHAR_LIMIT failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_safe[i], setOffset);
609          }
610 
611          i++;
612     }
613 }
614 
TestAppendChar()615 static void TestAppendChar(){
616     static UChar s[5]={0x0061, 0x0062, 0x0063, 0x0064, 0x0000};
617     static uint32_t test[]={
618      /*append-position(unsafe),  CHAR to be appended  */
619         0,                        0x20441,
620         2,                        0x0028,
621         2,                        0xdc00,
622         3,                        0xd800,
623         1,                        0x20402,
624 
625     /*append-position(safe),     CHAR to be appended */
626         0,                        0x20441,
627         2,                        0xdc00,
628         3,                        0xd800,
629         1,                        0x20402,
630         3,                        0x20402,
631         3,                        0x10402,
632         2,                        0x10402,
633 
634     };
635     static uint16_t movedOffset[]={
636         /*offset-moved-to(unsafe)*/
637           2,              /*for append-pos: 0 , CHAR 0x20441*/
638           3,
639           3,
640           4,
641           3,
642           /*offse-moved-to(safe)*/
643           2,              /*for append-pos: 0, CHAR  0x20441*/
644           3,
645           4,
646           3,
647           4,
648           4,
649           4
650     };
651 
652     static UChar result[][5]={
653         /*unsafe*/
654         {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000},
655         {0x0061, 0x0062, 0x0028, 0x0064, 0x0000},
656         {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000},
657         {0x0061, 0x0062, 0x0063, 0xd800, 0x0000},
658         {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000},
659 
660         /*safe*/
661         {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000},
662         {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000},
663         {0x0061, 0x0062, 0x0063, 0xd800, 0x0000},
664         {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000},
665         {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000},
666         {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000},
667         {0x0061, 0x0062, 0xd801, 0xdc02, 0x0000},
668 
669 
670     };
671     uint16_t i, count=0;
672     UChar *str=(UChar*)malloc(sizeof(UChar) * (u_strlen(s)+1));
673     uint16_t offset;
674     for(i=0; i<UPRV_LENGTHOF(test); i=(uint16_t)(i+2)){
675         if(count<5){
676             u_strcpy(str, s);
677             offset=(uint16_t)test[i];
678             UTF16_APPEND_CHAR_UNSAFE(str, offset, test[i+1]);
679             if(offset != movedOffset[count]){
680                 log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d  currentOffset=%d\n",
681                     count, movedOffset[count], offset);
682 
683             }
684             if(u_strcmp(str, result[count]) !=0){
685                 log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed for count=%d. Expected:", count);
686                 printUChars(result[count]);
687                 printf("\nGot:");
688                 printUChars(str);
689                 printf("\n");
690             }
691         }else{
692             u_strcpy(str, s);
693             offset=(uint16_t)test[i];
694             UTF16_APPEND_CHAR_SAFE(str, offset, (uint16_t)u_strlen(str), test[i+1]);
695             if(offset != movedOffset[count]){
696                 log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d  currentOffset=%d\n",
697                     count, movedOffset[count], offset);
698 
699             }
700             if(u_strcmp(str, result[count]) !=0){
701                 log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed for count=%d. Expected:", count);
702                 printUChars(result[count]);
703                 printf("\nGot:");
704                 printUChars(str);
705                 printf("\n");
706             }
707         }
708         count++;
709     }
710     free(str);
711 
712 }
713 
TestAppend()714 static void TestAppend() {
715     static const UChar32 codePoints[]={
716         0x61, 0xdf, 0x901, 0x3040,
717         0xac00, 0xd800, 0xdbff, 0xdcde,
718         0xdffd, 0xe000, 0xffff, 0x10000,
719         0x12345, 0xe0021, 0x10ffff, 0x110000,
720         0x234567, 0x7fffffff, -1, -1000,
721         0, 0x400
722     };
723     static const UChar expectUnsafe[]={
724         0x61, 0xdf, 0x901, 0x3040,
725         0xac00, 0xd800, 0xdbff, 0xdcde,
726         0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00,
727         0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */
728         /* none from this line */
729         0, 0x400
730     }, expectSafe[]={
731         0x61, 0xdf, 0x901, 0x3040,
732         0xac00, 0xd800, 0xdbff, 0xdcde,
733         0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00,
734         0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */
735         /* none from this line */
736         0, 0x400
737     };
738 
739     UChar buffer[100];
740     UChar32 c;
741     int32_t i, length;
742     UBool isError, expectIsError, wrongIsError;
743 
744     length=0;
745     for(i=0; i<UPRV_LENGTHOF(codePoints); ++i) {
746         c=codePoints[i];
747         if(c<0 || 0x10ffff<c) {
748             continue; /* skip non-code points for U16_APPEND_UNSAFE */
749         }
750 
751         U16_APPEND_UNSAFE(buffer, length, c);
752     }
753     if(length!=UPRV_LENGTHOF(expectUnsafe) || 0!=memcmp(buffer, expectUnsafe, length*U_SIZEOF_UCHAR)) {
754         log_err("U16_APPEND_UNSAFE did not generate the expected output\n");
755     }
756 
757     length=0;
758     wrongIsError=FALSE;
759     for(i=0; i<UPRV_LENGTHOF(codePoints); ++i) {
760         c=codePoints[i];
761         expectIsError= c<0 || 0x10ffff<c; /* || U_IS_SURROGATE(c); */ /* surrogates in UTF-32 shouldn't be used, but it's okay to pass them around internally. */
762         isError=FALSE;
763 
764         U16_APPEND(buffer, length, UPRV_LENGTHOF(buffer), c, isError);
765         wrongIsError|= isError!=expectIsError;
766     }
767     if(wrongIsError) {
768         log_err("U16_APPEND did not set isError correctly\n");
769     }
770     if(length!=UPRV_LENGTHOF(expectSafe) || 0!=memcmp(buffer, expectSafe, length*U_SIZEOF_UCHAR)) {
771         log_err("U16_APPEND did not generate the expected output\n");
772     }
773 }
774 
TestSurrogate()775 static void TestSurrogate(){
776     static UChar32 s[] = {0x10000, 0x10ffff, 0x50000, 0x100000, 0x1abcd};
777     int i = 0;
778     while (i < 5) {
779         UChar first  = UTF_FIRST_SURROGATE(s[i]);
780         UChar second = UTF_SECOND_SURROGATE(s[i]);
781         /* algorithm from the Unicode consortium */
782         UChar firstresult  = (UChar)(((s[i] - 0x10000) / 0x400) + 0xD800);
783         UChar secondresult = (UChar)(((s[i] - 0x10000) % 0x400) + 0xDC00);
784 
785         if (first != UTF16_LEAD(s[i]) || first != U16_LEAD(s[i]) || first != firstresult) {
786             log_err("Failure in first surrogate in 0x%x expected to be 0x%x\n",
787                     s[i], firstresult);
788         }
789         if (second != UTF16_TRAIL(s[i]) || second != U16_TRAIL(s[i]) || second != secondresult) {
790             log_err("Failure in second surrogate in 0x%x expected to be 0x%x\n",
791                     s[i], secondresult);
792         }
793         i ++;
794     }
795 }
796 
printUChars(const UChar * uchars)797 static void printUChars(const UChar *uchars){
798     int16_t i=0;
799     for(i=0; i<u_strlen(uchars); i++){
800         printf("%x ", *(uchars+i));
801     }
802 }
803