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