]> git.saurik.com Git - apple/icu.git/blame - icuSources/common/ucnv_u16.c
ICU-57163.0.1.tar.gz
[apple/icu.git] / icuSources / common / ucnv_u16.c
CommitLineData
b75a7d8f
A
1/*
2**********************************************************************
2ca993e8 3* Copyright (C) 2002-2015, International Business Machines
b75a7d8f
A
4* Corporation and others. All Rights Reserved.
5**********************************************************************
6* file name: ucnv_u16.c
7* encoding: US-ASCII
8* tab size: 8 (not used)
9* indentation:4
10*
11* created on: 2002jul01
12* created by: Markus W. Scherer
13*
14* UTF-16 converter implementation. Used to be in ucnv_utf.c.
15*/
16
17#include "unicode/utypes.h"
374ca955
A
18
19#if !UCONFIG_NO_CONVERSION
20
b75a7d8f 21#include "unicode/ucnv.h"
b75a7d8f
A
22#include "ucnv_bld.h"
23#include "ucnv_cnv.h"
24#include "cmemory.h"
25
73c04bcf
A
26enum {
27 UCNV_NEED_TO_WRITE_BOM=1
28};
29
729e4ab9
A
30/*
31 * The UTF-16 toUnicode implementation is also used for the Java-specific
32 * "with BOM" variants of UTF-16BE and UTF-16LE.
33 */
34static void
35_UTF16ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
36 UErrorCode *pErrorCode);
37
374ca955
A
38/* UTF-16BE ----------------------------------------------------------------- */
39
40#if U_IS_BIG_ENDIAN
41# define _UTF16PEFromUnicodeWithOffsets _UTF16BEFromUnicodeWithOffsets
42#else
43# define _UTF16PEFromUnicodeWithOffsets _UTF16LEFromUnicodeWithOffsets
44#endif
b75a7d8f 45
73c04bcf 46
b75a7d8f 47static void
374ca955
A
48_UTF16BEFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs,
49 UErrorCode *pErrorCode) {
50 UConverter *cnv;
51 const UChar *source;
73c04bcf 52 char *target;
374ca955
A
53 int32_t *offsets;
54
73c04bcf 55 uint32_t targetCapacity, length, sourceIndex;
374ca955
A
56 UChar c, trail;
57 char overflow[4];
58
59 source=pArgs->source;
73c04bcf 60 length=(int32_t)(pArgs->sourceLimit-source);
374ca955 61 if(length<=0) {
b75a7d8f
A
62 /* no input, nothing to do */
63 return;
64 }
65
73c04bcf
A
66 cnv=pArgs->converter;
67
68 /* write the BOM if necessary */
69 if(cnv->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) {
70 static const char bom[]={ (char)0xfe, (char)0xff };
71 ucnv_fromUWriteBytes(cnv,
72 bom, 2,
73 &pArgs->target, pArgs->targetLimit,
74 &pArgs->offsets, -1,
75 pErrorCode);
76 cnv->fromUnicodeStatus=0;
77 }
78
79 target=pArgs->target;
80 if(target >= pArgs->targetLimit) {
b75a7d8f
A
81 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
82 return;
83 }
84
73c04bcf 85 targetCapacity=(uint32_t)(pArgs->targetLimit-target);
374ca955
A
86 offsets=pArgs->offsets;
87 sourceIndex=0;
88
89 /* c!=0 indicates in several places outside the main loops that a surrogate was found */
90
91 if((c=(UChar)cnv->fromUChar32)!=0 && U16_IS_TRAIL(trail=*source) && targetCapacity>=4) {
92 /* the last buffer ended with a lead surrogate, output the surrogate pair */
93 ++source;
b75a7d8f 94 --length;
374ca955
A
95 target[0]=(uint8_t)(c>>8);
96 target[1]=(uint8_t)c;
97 target[2]=(uint8_t)(trail>>8);
98 target[3]=(uint8_t)trail;
99 target+=4;
100 targetCapacity-=4;
101 if(offsets!=NULL) {
102 *offsets++=-1;
103 *offsets++=-1;
104 *offsets++=-1;
105 *offsets++=-1;
b75a7d8f 106 }
374ca955
A
107 sourceIndex=1;
108 cnv->fromUChar32=c=0;
b75a7d8f
A
109 }
110
374ca955 111 if(c==0) {
73c04bcf
A
112 /* copy an even number of bytes for complete UChars */
113 uint32_t count=2*length;
114 if(count>targetCapacity) {
115 count=targetCapacity&~1;
116 }
117 /* count is even */
374ca955
A
118 targetCapacity-=count;
119 count>>=1;
120 length-=count;
121
122 if(offsets==NULL) {
123 while(count>0) {
124 c=*source++;
125 if(U16_IS_SINGLE(c)) {
126 target[0]=(uint8_t)(c>>8);
127 target[1]=(uint8_t)c;
128 target+=2;
129 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 && U16_IS_TRAIL(trail=*source)) {
130 ++source;
131 --count;
132 target[0]=(uint8_t)(c>>8);
133 target[1]=(uint8_t)c;
134 target[2]=(uint8_t)(trail>>8);
135 target[3]=(uint8_t)trail;
136 target+=4;
137 } else {
138 break;
139 }
140 --count;
141 }
142 } else {
143 while(count>0) {
144 c=*source++;
145 if(U16_IS_SINGLE(c)) {
146 target[0]=(uint8_t)(c>>8);
147 target[1]=(uint8_t)c;
148 target+=2;
149 *offsets++=sourceIndex;
150 *offsets++=sourceIndex++;
151 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 && U16_IS_TRAIL(trail=*source)) {
152 ++source;
153 --count;
154 target[0]=(uint8_t)(c>>8);
155 target[1]=(uint8_t)c;
156 target[2]=(uint8_t)(trail>>8);
157 target[3]=(uint8_t)trail;
158 target+=4;
159 *offsets++=sourceIndex;
160 *offsets++=sourceIndex;
161 *offsets++=sourceIndex;
162 *offsets++=sourceIndex;
163 sourceIndex+=2;
164 } else {
165 break;
166 }
b75a7d8f
A
167 --count;
168 }
169 }
b75a7d8f 170
374ca955
A
171 if(count==0) {
172 /* done with the loop for complete UChars */
173 if(length>0 && targetCapacity>0) {
174 /*
175 * there is more input and some target capacity -
176 * it must be targetCapacity==1 because otherwise
177 * the above would have copied more;
178 * prepare for overflow output
179 */
180 if(U16_IS_SINGLE(c=*source++)) {
181 overflow[0]=(char)(c>>8);
182 overflow[1]=(char)c;
183 length=2; /* 2 bytes to output */
184 c=0;
185 /* } else { keep c for surrogate handling, length will be set there */
186 }
187 } else {
188 length=0;
189 c=0;
190 }
b75a7d8f 191 } else {
374ca955
A
192 /* keep c for surrogate handling, length will be set there */
193 targetCapacity+=2*count;
b75a7d8f 194 }
374ca955
A
195 } else {
196 length=0; /* from here on, length counts the bytes in overflow[] */
b75a7d8f 197 }
374ca955
A
198
199 if(c!=0) {
200 /*
201 * c is a surrogate, and
202 * - source or target too short
203 * - or the surrogate is unmatched
204 */
205 length=0;
206 if(U16_IS_SURROGATE_LEAD(c)) {
207 if(source<pArgs->sourceLimit) {
208 if(U16_IS_TRAIL(trail=*source)) {
209 /* output the surrogate pair, will overflow (see conditions comment above) */
210 ++source;
211 overflow[0]=(char)(c>>8);
212 overflow[1]=(char)c;
213 overflow[2]=(char)(trail>>8);
214 overflow[3]=(char)trail;
215 length=4; /* 4 bytes to output */
216 c=0;
217 } else {
218 /* unmatched lead surrogate */
219 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
220 }
221 } else {
222 /* see if the trail surrogate is in the next buffer */
223 }
224 } else {
225 /* unmatched trail surrogate */
226 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
b75a7d8f 227 }
374ca955 228 cnv->fromUChar32=c;
b75a7d8f
A
229 }
230
374ca955
A
231 if(length>0) {
232 /* output length bytes with overflow (length>targetCapacity>0) */
233 ucnv_fromUWriteBytes(cnv,
234 overflow, length,
235 (char **)&target, pArgs->targetLimit,
236 &offsets, sourceIndex,
237 pErrorCode);
73c04bcf 238 targetCapacity=(uint32_t)(pArgs->targetLimit-(char *)target);
b75a7d8f
A
239 }
240
374ca955
A
241 if(U_SUCCESS(*pErrorCode) && source<pArgs->sourceLimit && targetCapacity==0) {
242 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
b75a7d8f
A
243 }
244
245 /* write back the updated pointers */
374ca955
A
246 pArgs->source=source;
247 pArgs->target=(char *)target;
248 pArgs->offsets=offsets;
b75a7d8f
A
249}
250
b75a7d8f 251static void
374ca955 252_UTF16BEToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
b75a7d8f 253 UErrorCode *pErrorCode) {
374ca955
A
254 UConverter *cnv;
255 const uint8_t *source;
256 UChar *target;
257 int32_t *offsets;
258
73c04bcf 259 uint32_t targetCapacity, length, count, sourceIndex;
374ca955
A
260 UChar c, trail;
261
729e4ab9
A
262 if(pArgs->converter->mode<8) {
263 _UTF16ToUnicodeWithOffsets(pArgs, pErrorCode);
264 return;
265 }
266
374ca955
A
267 cnv=pArgs->converter;
268 source=(const uint8_t *)pArgs->source;
73c04bcf 269 length=(int32_t)((const uint8_t *)pArgs->sourceLimit-source);
374ca955 270 if(length<=0 && cnv->toUnicodeStatus==0) {
b75a7d8f
A
271 /* no input, nothing to do */
272 return;
273 }
274
73c04bcf
A
275 target=pArgs->target;
276 if(target >= pArgs->targetLimit) {
374ca955 277 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
b75a7d8f
A
278 return;
279 }
280
73c04bcf 281 targetCapacity=(uint32_t)(pArgs->targetLimit-target);
374ca955
A
282 offsets=pArgs->offsets;
283 sourceIndex=0;
284 c=0;
285
286 /* complete a partial UChar or pair from the last call */
287 if(cnv->toUnicodeStatus!=0) {
b75a7d8f 288 /*
374ca955
A
289 * special case: single byte from a previous buffer,
290 * where the byte turned out not to belong to a trail surrogate
291 * and the preceding, unmatched lead surrogate was put into toUBytes[]
292 * for error handling
b75a7d8f 293 */
374ca955
A
294 cnv->toUBytes[0]=(uint8_t)cnv->toUnicodeStatus;
295 cnv->toULength=1;
296 cnv->toUnicodeStatus=0;
b75a7d8f 297 }
374ca955
A
298 if((count=cnv->toULength)!=0) {
299 uint8_t *p=cnv->toUBytes;
300 do {
301 p[count++]=*source++;
302 ++sourceIndex;
303 --length;
304 if(count==2) {
305 c=((UChar)p[0]<<8)|p[1];
306 if(U16_IS_SINGLE(c)) {
307 /* output the BMP code point */
308 *target++=c;
309 if(offsets!=NULL) {
310 *offsets++=-1;
311 }
312 --targetCapacity;
313 count=0;
314 c=0;
315 break;
316 } else if(U16_IS_SURROGATE_LEAD(c)) {
317 /* continue collecting bytes for the trail surrogate */
318 c=0; /* avoid unnecessary surrogate handling below */
319 } else {
320 /* fall through to error handling for an unmatched trail surrogate */
321 break;
322 }
323 } else if(count==4) {
324 c=((UChar)p[0]<<8)|p[1];
325 trail=((UChar)p[2]<<8)|p[3];
326 if(U16_IS_TRAIL(trail)) {
327 /* output the surrogate pair */
328 *target++=c;
329 if(targetCapacity>=2) {
330 *target++=trail;
331 if(offsets!=NULL) {
332 *offsets++=-1;
333 *offsets++=-1;
334 }
335 targetCapacity-=2;
336 } else /* targetCapacity==1 */ {
337 targetCapacity=0;
338 cnv->UCharErrorBuffer[0]=trail;
339 cnv->UCharErrorBufferLength=1;
340 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
341 }
342 count=0;
343 c=0;
344 break;
345 } else {
346 /* unmatched lead surrogate, handle here for consistent toUBytes[] */
347 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
348
349 /* back out reading the code unit after it */
350 if(((const uint8_t *)pArgs->source-source)>=2) {
351 source-=2;
352 } else {
353 /*
354 * if the trail unit's first byte was in a previous buffer, then
355 * we need to put it into a special place because toUBytes[] will be
356 * used for the lead unit's bytes
357 */
358 cnv->toUnicodeStatus=0x100|p[2];
359 --source;
360 }
361 cnv->toULength=2;
362
363 /* write back the updated pointers */
364 pArgs->source=(const char *)source;
365 pArgs->target=target;
366 pArgs->offsets=offsets;
367 return;
368 }
b75a7d8f 369 }
374ca955
A
370 } while(length>0);
371 cnv->toULength=(int8_t)count;
b75a7d8f
A
372 }
373
374ca955
A
374 /* copy an even number of bytes for complete UChars */
375 count=2*targetCapacity;
376 if(count>length) {
377 count=length&~1;
378 }
379 if(c==0 && count>0) {
380 length-=count;
381 count>>=1;
382 targetCapacity-=count;
383 if(offsets==NULL) {
384 do {
385 c=((UChar)source[0]<<8)|source[1];
386 source+=2;
387 if(U16_IS_SINGLE(c)) {
388 *target++=c;
389 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 &&
390 U16_IS_TRAIL(trail=((UChar)source[0]<<8)|source[1])
391 ) {
392 source+=2;
393 --count;
394 *target++=c;
395 *target++=trail;
396 } else {
397 break;
398 }
399 } while(--count>0);
b75a7d8f 400 } else {
374ca955
A
401 do {
402 c=((UChar)source[0]<<8)|source[1];
403 source+=2;
404 if(U16_IS_SINGLE(c)) {
405 *target++=c;
406 *offsets++=sourceIndex;
407 sourceIndex+=2;
408 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 &&
409 U16_IS_TRAIL(trail=((UChar)source[0]<<8)|source[1])
410 ) {
411 source+=2;
412 --count;
413 *target++=c;
414 *target++=trail;
415 *offsets++=sourceIndex;
416 *offsets++=sourceIndex;
417 sourceIndex+=4;
418 } else {
419 break;
420 }
421 } while(--count>0);
b75a7d8f 422 }
b75a7d8f 423
374ca955
A
424 if(count==0) {
425 /* done with the loop for complete UChars */
426 c=0;
427 } else {
428 /* keep c for surrogate handling, trail will be set there */
429 length+=2*(count-1); /* one more byte pair was consumed than count decremented */
430 targetCapacity+=count;
b75a7d8f
A
431 }
432 }
433
374ca955
A
434 if(c!=0) {
435 /*
436 * c is a surrogate, and
437 * - source or target too short
438 * - or the surrogate is unmatched
439 */
440 cnv->toUBytes[0]=(uint8_t)(c>>8);
441 cnv->toUBytes[1]=(uint8_t)c;
442 cnv->toULength=2;
443
444 if(U16_IS_SURROGATE_LEAD(c)) {
445 if(length>=2) {
446 if(U16_IS_TRAIL(trail=((UChar)source[0]<<8)|source[1])) {
447 /* output the surrogate pair, will overflow (see conditions comment above) */
448 source+=2;
449 length-=2;
450 *target++=c;
451 if(offsets!=NULL) {
452 *offsets++=sourceIndex;
453 }
454 cnv->UCharErrorBuffer[0]=trail;
455 cnv->UCharErrorBufferLength=1;
456 cnv->toULength=0;
457 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
458 } else {
459 /* unmatched lead surrogate */
460 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
461 }
462 } else {
463 /* see if the trail surrogate is in the next buffer */
b75a7d8f
A
464 }
465 } else {
374ca955
A
466 /* unmatched trail surrogate */
467 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
b75a7d8f 468 }
b75a7d8f
A
469 }
470
374ca955
A
471 if(U_SUCCESS(*pErrorCode)) {
472 /* check for a remaining source byte */
473 if(length>0) {
474 if(targetCapacity==0) {
475 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
476 } else {
477 /* it must be length==1 because otherwise the above would have copied more */
478 cnv->toUBytes[cnv->toULength++]=*source++;
b75a7d8f
A
479 }
480 }
481 }
482
483 /* write back the updated pointers */
374ca955
A
484 pArgs->source=(const char *)source;
485 pArgs->target=target;
486 pArgs->offsets=offsets;
b75a7d8f
A
487}
488
374ca955
A
489static UChar32
490_UTF16BEGetNextUChar(UConverterToUnicodeArgs *pArgs, UErrorCode *err) {
491 const uint8_t *s, *sourceLimit;
492 UChar32 c;
b75a7d8f 493
729e4ab9
A
494 if(pArgs->converter->mode<8) {
495 return UCNV_GET_NEXT_UCHAR_USE_TO_U;
496 }
497
374ca955
A
498 s=(const uint8_t *)pArgs->source;
499 sourceLimit=(const uint8_t *)pArgs->sourceLimit;
b75a7d8f 500
374ca955
A
501 if(s>=sourceLimit) {
502 /* no input */
503 *err=U_INDEX_OUTOFBOUNDS_ERROR;
b75a7d8f
A
504 return 0xffff;
505 }
506
374ca955
A
507 if(s+2>sourceLimit) {
508 /* only one byte: truncated UChar */
509 pArgs->converter->toUBytes[0]=*s++;
510 pArgs->converter->toULength=1;
511 pArgs->source=(const char *)s;
512 *err = U_TRUNCATED_CHAR_FOUND;
513 return 0xffff;
514 }
b75a7d8f 515
374ca955
A
516 /* get one UChar */
517 c=((UChar32)*s<<8)|s[1];
518 s+=2;
519
520 /* check for a surrogate pair */
521 if(U_IS_SURROGATE(c)) {
522 if(U16_IS_SURROGATE_LEAD(c)) {
523 if(s+2<=sourceLimit) {
524 UChar trail;
525
526 /* get a second UChar and see if it is a trail surrogate */
527 trail=((UChar)*s<<8)|s[1];
528 if(U16_IS_TRAIL(trail)) {
529 c=U16_GET_SUPPLEMENTARY(c, trail);
530 s+=2;
531 } else {
532 /* unmatched lead surrogate */
533 c=-2;
534 }
535 } else {
536 /* too few (2 or 3) bytes for a surrogate pair: truncated code point */
537 uint8_t *bytes=pArgs->converter->toUBytes;
538 s-=2;
539 pArgs->converter->toULength=(int8_t)(sourceLimit-s);
540 do {
541 *bytes++=*s++;
542 } while(s<sourceLimit);
543
544 c=0xffff;
545 *err=U_TRUNCATED_CHAR_FOUND;
546 }
547 } else {
548 /* unmatched trail surrogate */
549 c=-2;
b75a7d8f
A
550 }
551
374ca955
A
552 if(c<0) {
553 /* write the unmatched surrogate */
554 uint8_t *bytes=pArgs->converter->toUBytes;
555 pArgs->converter->toULength=2;
556 *bytes=*(s-2);
557 bytes[1]=*(s-1);
b75a7d8f 558
374ca955
A
559 c=0xffff;
560 *err=U_ILLEGAL_CHAR_FOUND;
b75a7d8f
A
561 }
562 }
563
374ca955
A
564 pArgs->source=(const char *)s;
565 return c;
b75a7d8f
A
566}
567
729e4ab9
A
568static void
569_UTF16BEReset(UConverter *cnv, UConverterResetChoice choice) {
570 if(choice<=UCNV_RESET_TO_UNICODE) {
571 /* reset toUnicode state */
572 if(UCNV_GET_VERSION(cnv)==0) {
573 cnv->mode=8; /* no BOM handling */
574 } else {
575 cnv->mode=0; /* Java-specific "UnicodeBig" requires BE BOM or no BOM */
576 }
577 }
578 if(choice!=UCNV_RESET_TO_UNICODE && UCNV_GET_VERSION(cnv)==1) {
579 /* reset fromUnicode for "UnicodeBig": prepare to output the UTF-16BE BOM */
580 cnv->fromUnicodeStatus=UCNV_NEED_TO_WRITE_BOM;
581 }
582}
583
584static void
585_UTF16BEOpen(UConverter *cnv,
586 UConverterLoadArgs *pArgs,
587 UErrorCode *pErrorCode) {
588 if(UCNV_GET_VERSION(cnv)<=1) {
589 _UTF16BEReset(cnv, UCNV_RESET_BOTH);
590 } else {
591 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
592 }
593}
594
595static const char *
596_UTF16BEGetName(const UConverter *cnv) {
597 if(UCNV_GET_VERSION(cnv)==0) {
598 return "UTF-16BE";
599 } else {
600 return "UTF-16BE,version=1";
601 }
602}
603
b75a7d8f
A
604static const UConverterImpl _UTF16BEImpl={
605 UCNV_UTF16_BigEndian,
606
607 NULL,
608 NULL,
609
729e4ab9 610 _UTF16BEOpen,
b75a7d8f 611 NULL,
729e4ab9 612 _UTF16BEReset,
b75a7d8f
A
613
614 _UTF16BEToUnicodeWithOffsets,
615 _UTF16BEToUnicodeWithOffsets,
616 _UTF16BEFromUnicodeWithOffsets,
617 _UTF16BEFromUnicodeWithOffsets,
374ca955 618 _UTF16BEGetNextUChar,
b75a7d8f
A
619
620 NULL,
729e4ab9 621 _UTF16BEGetName,
b75a7d8f
A
622 NULL,
623 NULL,
73c04bcf 624 ucnv_getNonSurrogateUnicodeSet
b75a7d8f
A
625};
626
b75a7d8f
A
627static const UConverterStaticData _UTF16BEStaticData={
628 sizeof(UConverterStaticData),
629 "UTF-16BE",
729e4ab9 630 1200, UCNV_IBM, UCNV_UTF16_BigEndian, 2, 2,
b75a7d8f
A
631 { 0xff, 0xfd, 0, 0 },2,FALSE,FALSE,
632 0,
633 0,
634 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
635};
636
637
2ca993e8
A
638const UConverterSharedData _UTF16BEData=
639 UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16BEStaticData, &_UTF16BEImpl);
b75a7d8f
A
640
641/* UTF-16LE ----------------------------------------------------------------- */
642
374ca955
A
643static void
644_UTF16LEFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs,
645 UErrorCode *pErrorCode) {
646 UConverter *cnv;
647 const UChar *source;
73c04bcf 648 char *target;
374ca955
A
649 int32_t *offsets;
650
73c04bcf 651 uint32_t targetCapacity, length, sourceIndex;
374ca955
A
652 UChar c, trail;
653 char overflow[4];
654
655 source=pArgs->source;
73c04bcf 656 length=(int32_t)(pArgs->sourceLimit-source);
374ca955
A
657 if(length<=0) {
658 /* no input, nothing to do */
659 return;
660 }
661
73c04bcf
A
662 cnv=pArgs->converter;
663
664 /* write the BOM if necessary */
665 if(cnv->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) {
666 static const char bom[]={ (char)0xff, (char)0xfe };
667 ucnv_fromUWriteBytes(cnv,
668 bom, 2,
669 &pArgs->target, pArgs->targetLimit,
670 &pArgs->offsets, -1,
671 pErrorCode);
672 cnv->fromUnicodeStatus=0;
673 }
674
675 target=pArgs->target;
676 if(target >= pArgs->targetLimit) {
374ca955
A
677 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
678 return;
679 }
680
73c04bcf 681 targetCapacity=(uint32_t)(pArgs->targetLimit-pArgs->target);
374ca955
A
682 offsets=pArgs->offsets;
683 sourceIndex=0;
684
685 /* c!=0 indicates in several places outside the main loops that a surrogate was found */
686
687 if((c=(UChar)cnv->fromUChar32)!=0 && U16_IS_TRAIL(trail=*source) && targetCapacity>=4) {
688 /* the last buffer ended with a lead surrogate, output the surrogate pair */
689 ++source;
690 --length;
691 target[0]=(uint8_t)c;
692 target[1]=(uint8_t)(c>>8);
693 target[2]=(uint8_t)trail;
694 target[3]=(uint8_t)(trail>>8);
695 target+=4;
696 targetCapacity-=4;
697 if(offsets!=NULL) {
698 *offsets++=-1;
699 *offsets++=-1;
700 *offsets++=-1;
701 *offsets++=-1;
b75a7d8f 702 }
374ca955
A
703 sourceIndex=1;
704 cnv->fromUChar32=c=0;
705 }
706
374ca955 707 if(c==0) {
73c04bcf
A
708 /* copy an even number of bytes for complete UChars */
709 uint32_t count=2*length;
710 if(count>targetCapacity) {
711 count=targetCapacity&~1;
712 }
713 /* count is even */
374ca955
A
714 targetCapacity-=count;
715 count>>=1;
716 length-=count;
717
718 if(offsets==NULL) {
719 while(count>0) {
720 c=*source++;
721 if(U16_IS_SINGLE(c)) {
722 target[0]=(uint8_t)c;
723 target[1]=(uint8_t)(c>>8);
724 target+=2;
725 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 && U16_IS_TRAIL(trail=*source)) {
726 ++source;
727 --count;
728 target[0]=(uint8_t)c;
729 target[1]=(uint8_t)(c>>8);
730 target[2]=(uint8_t)trail;
731 target[3]=(uint8_t)(trail>>8);
732 target+=4;
733 } else {
734 break;
735 }
736 --count;
737 }
738 } else {
739 while(count>0) {
740 c=*source++;
741 if(U16_IS_SINGLE(c)) {
742 target[0]=(uint8_t)c;
743 target[1]=(uint8_t)(c>>8);
744 target+=2;
745 *offsets++=sourceIndex;
746 *offsets++=sourceIndex++;
747 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 && U16_IS_TRAIL(trail=*source)) {
748 ++source;
749 --count;
750 target[0]=(uint8_t)c;
751 target[1]=(uint8_t)(c>>8);
752 target[2]=(uint8_t)trail;
753 target[3]=(uint8_t)(trail>>8);
754 target+=4;
755 *offsets++=sourceIndex;
756 *offsets++=sourceIndex;
757 *offsets++=sourceIndex;
758 *offsets++=sourceIndex;
759 sourceIndex+=2;
760 } else {
761 break;
762 }
763 --count;
764 }
b75a7d8f
A
765 }
766
374ca955
A
767 if(count==0) {
768 /* done with the loop for complete UChars */
769 if(length>0 && targetCapacity>0) {
770 /*
771 * there is more input and some target capacity -
772 * it must be targetCapacity==1 because otherwise
773 * the above would have copied more;
774 * prepare for overflow output
775 */
776 if(U16_IS_SINGLE(c=*source++)) {
777 overflow[0]=(char)c;
778 overflow[1]=(char)(c>>8);
779 length=2; /* 2 bytes to output */
780 c=0;
781 /* } else { keep c for surrogate handling, length will be set there */
782 }
783 } else {
784 length=0;
785 c=0;
786 }
787 } else {
788 /* keep c for surrogate handling, length will be set there */
789 targetCapacity+=2*count;
790 }
791 } else {
792 length=0; /* from here on, length counts the bytes in overflow[] */
793 }
794
795 if(c!=0) {
796 /*
797 * c is a surrogate, and
798 * - source or target too short
799 * - or the surrogate is unmatched
800 */
801 length=0;
802 if(U16_IS_SURROGATE_LEAD(c)) {
803 if(source<pArgs->sourceLimit) {
804 if(U16_IS_TRAIL(trail=*source)) {
805 /* output the surrogate pair, will overflow (see conditions comment above) */
806 ++source;
807 overflow[0]=(char)c;
808 overflow[1]=(char)(c>>8);
809 overflow[2]=(char)trail;
810 overflow[3]=(char)(trail>>8);
811 length=4; /* 4 bytes to output */
812 c=0;
813 } else {
814 /* unmatched lead surrogate */
815 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
816 }
817 } else {
818 /* see if the trail surrogate is in the next buffer */
819 }
820 } else {
821 /* unmatched trail surrogate */
822 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
823 }
824 cnv->fromUChar32=c;
b75a7d8f
A
825 }
826
374ca955
A
827 if(length>0) {
828 /* output length bytes with overflow (length>targetCapacity>0) */
829 ucnv_fromUWriteBytes(cnv,
830 overflow, length,
73c04bcf 831 &target, pArgs->targetLimit,
374ca955
A
832 &offsets, sourceIndex,
833 pErrorCode);
73c04bcf 834 targetCapacity=(uint32_t)(pArgs->targetLimit-(char *)target);
374ca955 835 }
b75a7d8f 836
374ca955
A
837 if(U_SUCCESS(*pErrorCode) && source<pArgs->sourceLimit && targetCapacity==0) {
838 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
839 }
840
841 /* write back the updated pointers */
842 pArgs->source=source;
73c04bcf 843 pArgs->target=target;
374ca955
A
844 pArgs->offsets=offsets;
845}
b75a7d8f 846
374ca955
A
847static void
848_UTF16LEToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
849 UErrorCode *pErrorCode) {
850 UConverter *cnv;
851 const uint8_t *source;
852 UChar *target;
853 int32_t *offsets;
854
73c04bcf 855 uint32_t targetCapacity, length, count, sourceIndex;
374ca955
A
856 UChar c, trail;
857
729e4ab9
A
858 if(pArgs->converter->mode<8) {
859 _UTF16ToUnicodeWithOffsets(pArgs, pErrorCode);
860 return;
861 }
862
374ca955
A
863 cnv=pArgs->converter;
864 source=(const uint8_t *)pArgs->source;
73c04bcf 865 length=(int32_t)((const uint8_t *)pArgs->sourceLimit-source);
374ca955
A
866 if(length<=0 && cnv->toUnicodeStatus==0) {
867 /* no input, nothing to do */
868 return;
869 }
870
73c04bcf
A
871 target=pArgs->target;
872 if(target >= pArgs->targetLimit) {
374ca955
A
873 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
874 return;
875 }
876
73c04bcf 877 targetCapacity=(uint32_t)(pArgs->targetLimit-pArgs->target);
374ca955
A
878 offsets=pArgs->offsets;
879 sourceIndex=0;
880 c=0;
881
882 /* complete a partial UChar or pair from the last call */
883 if(cnv->toUnicodeStatus!=0) {
884 /*
885 * special case: single byte from a previous buffer,
886 * where the byte turned out not to belong to a trail surrogate
887 * and the preceding, unmatched lead surrogate was put into toUBytes[]
888 * for error handling
889 */
890 cnv->toUBytes[0]=(uint8_t)cnv->toUnicodeStatus;
891 cnv->toULength=1;
892 cnv->toUnicodeStatus=0;
893 }
894 if((count=cnv->toULength)!=0) {
895 uint8_t *p=cnv->toUBytes;
896 do {
897 p[count++]=*source++;
898 ++sourceIndex;
899 --length;
900 if(count==2) {
901 c=((UChar)p[1]<<8)|p[0];
902 if(U16_IS_SINGLE(c)) {
903 /* output the BMP code point */
904 *target++=c;
905 if(offsets!=NULL) {
906 *offsets++=-1;
907 }
908 --targetCapacity;
909 count=0;
910 c=0;
911 break;
912 } else if(U16_IS_SURROGATE_LEAD(c)) {
913 /* continue collecting bytes for the trail surrogate */
914 c=0; /* avoid unnecessary surrogate handling below */
915 } else {
916 /* fall through to error handling for an unmatched trail surrogate */
917 break;
918 }
919 } else if(count==4) {
920 c=((UChar)p[1]<<8)|p[0];
921 trail=((UChar)p[3]<<8)|p[2];
922 if(U16_IS_TRAIL(trail)) {
923 /* output the surrogate pair */
924 *target++=c;
925 if(targetCapacity>=2) {
926 *target++=trail;
927 if(offsets!=NULL) {
928 *offsets++=-1;
929 *offsets++=-1;
930 }
931 targetCapacity-=2;
932 } else /* targetCapacity==1 */ {
933 targetCapacity=0;
934 cnv->UCharErrorBuffer[0]=trail;
935 cnv->UCharErrorBufferLength=1;
936 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
937 }
938 count=0;
939 c=0;
940 break;
941 } else {
942 /* unmatched lead surrogate, handle here for consistent toUBytes[] */
943 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
944
945 /* back out reading the code unit after it */
946 if(((const uint8_t *)pArgs->source-source)>=2) {
947 source-=2;
948 } else {
949 /*
950 * if the trail unit's first byte was in a previous buffer, then
951 * we need to put it into a special place because toUBytes[] will be
952 * used for the lead unit's bytes
953 */
954 cnv->toUnicodeStatus=0x100|p[2];
955 --source;
956 }
957 cnv->toULength=2;
958
959 /* write back the updated pointers */
960 pArgs->source=(const char *)source;
961 pArgs->target=target;
962 pArgs->offsets=offsets;
963 return;
964 }
965 }
966 } while(length>0);
967 cnv->toULength=(int8_t)count;
968 }
969
970 /* copy an even number of bytes for complete UChars */
971 count=2*targetCapacity;
972 if(count>length) {
973 count=length&~1;
974 }
975 if(c==0 && count>0) {
976 length-=count;
977 count>>=1;
978 targetCapacity-=count;
979 if(offsets==NULL) {
980 do {
981 c=((UChar)source[1]<<8)|source[0];
982 source+=2;
983 if(U16_IS_SINGLE(c)) {
984 *target++=c;
985 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 &&
986 U16_IS_TRAIL(trail=((UChar)source[1]<<8)|source[0])
987 ) {
988 source+=2;
989 --count;
990 *target++=c;
991 *target++=trail;
992 } else {
993 break;
994 }
995 } while(--count>0);
996 } else {
997 do {
998 c=((UChar)source[1]<<8)|source[0];
999 source+=2;
1000 if(U16_IS_SINGLE(c)) {
1001 *target++=c;
1002 *offsets++=sourceIndex;
1003 sourceIndex+=2;
1004 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 &&
1005 U16_IS_TRAIL(trail=((UChar)source[1]<<8)|source[0])
1006 ) {
1007 source+=2;
1008 --count;
1009 *target++=c;
1010 *target++=trail;
1011 *offsets++=sourceIndex;
1012 *offsets++=sourceIndex;
1013 sourceIndex+=4;
1014 } else {
1015 break;
1016 }
1017 } while(--count>0);
b75a7d8f
A
1018 }
1019
374ca955
A
1020 if(count==0) {
1021 /* done with the loop for complete UChars */
1022 c=0;
1023 } else {
1024 /* keep c for surrogate handling, trail will be set there */
1025 length+=2*(count-1); /* one more byte pair was consumed than count decremented */
1026 targetCapacity+=count;
1027 }
1028 }
b75a7d8f 1029
374ca955
A
1030 if(c!=0) {
1031 /*
1032 * c is a surrogate, and
1033 * - source or target too short
1034 * - or the surrogate is unmatched
1035 */
1036 cnv->toUBytes[0]=(uint8_t)c;
1037 cnv->toUBytes[1]=(uint8_t)(c>>8);
1038 cnv->toULength=2;
1039
1040 if(U16_IS_SURROGATE_LEAD(c)) {
1041 if(length>=2) {
1042 if(U16_IS_TRAIL(trail=((UChar)source[1]<<8)|source[0])) {
1043 /* output the surrogate pair, will overflow (see conditions comment above) */
1044 source+=2;
1045 length-=2;
1046 *target++=c;
1047 if(offsets!=NULL) {
1048 *offsets++=sourceIndex;
1049 }
1050 cnv->UCharErrorBuffer[0]=trail;
1051 cnv->UCharErrorBufferLength=1;
1052 cnv->toULength=0;
1053 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
1054 } else {
1055 /* unmatched lead surrogate */
1056 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
1057 }
1058 } else {
1059 /* see if the trail surrogate is in the next buffer */
1060 }
1061 } else {
1062 /* unmatched trail surrogate */
1063 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
b75a7d8f
A
1064 }
1065 }
1066
374ca955
A
1067 if(U_SUCCESS(*pErrorCode)) {
1068 /* check for a remaining source byte */
1069 if(length>0) {
1070 if(targetCapacity==0) {
1071 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
1072 } else {
1073 /* it must be length==1 because otherwise the above would have copied more */
1074 cnv->toUBytes[cnv->toULength++]=*source++;
1075 }
1076 }
1077 }
1078
1079 /* write back the updated pointers */
1080 pArgs->source=(const char *)source;
1081 pArgs->target=target;
1082 pArgs->offsets=offsets;
1083}
1084
1085static UChar32
1086_UTF16LEGetNextUChar(UConverterToUnicodeArgs *pArgs, UErrorCode *err) {
1087 const uint8_t *s, *sourceLimit;
1088 UChar32 c;
1089
729e4ab9
A
1090 if(pArgs->converter->mode<8) {
1091 return UCNV_GET_NEXT_UCHAR_USE_TO_U;
1092 }
1093
374ca955
A
1094 s=(const uint8_t *)pArgs->source;
1095 sourceLimit=(const uint8_t *)pArgs->sourceLimit;
1096
1097 if(s>=sourceLimit) {
1098 /* no input */
1099 *err=U_INDEX_OUTOFBOUNDS_ERROR;
1100 return 0xffff;
1101 }
1102
1103 if(s+2>sourceLimit) {
1104 /* only one byte: truncated UChar */
1105 pArgs->converter->toUBytes[0]=*s++;
1106 pArgs->converter->toULength=1;
1107 pArgs->source=(const char *)s;
1108 *err = U_TRUNCATED_CHAR_FOUND;
1109 return 0xffff;
1110 }
1111
1112 /* get one UChar */
1113 c=((UChar32)s[1]<<8)|*s;
1114 s+=2;
1115
1116 /* check for a surrogate pair */
1117 if(U_IS_SURROGATE(c)) {
1118 if(U16_IS_SURROGATE_LEAD(c)) {
1119 if(s+2<=sourceLimit) {
1120 UChar trail;
1121
1122 /* get a second UChar and see if it is a trail surrogate */
1123 trail=((UChar)s[1]<<8)|*s;
1124 if(U16_IS_TRAIL(trail)) {
1125 c=U16_GET_SUPPLEMENTARY(c, trail);
1126 s+=2;
1127 } else {
1128 /* unmatched lead surrogate */
1129 c=-2;
1130 }
1131 } else {
1132 /* too few (2 or 3) bytes for a surrogate pair: truncated code point */
1133 uint8_t *bytes=pArgs->converter->toUBytes;
1134 s-=2;
1135 pArgs->converter->toULength=(int8_t)(sourceLimit-s);
1136 do {
1137 *bytes++=*s++;
1138 } while(s<sourceLimit);
1139
1140 c=0xffff;
1141 *err=U_TRUNCATED_CHAR_FOUND;
1142 }
1143 } else {
1144 /* unmatched trail surrogate */
1145 c=-2;
1146 }
1147
1148 if(c<0) {
1149 /* write the unmatched surrogate */
1150 uint8_t *bytes=pArgs->converter->toUBytes;
1151 pArgs->converter->toULength=2;
1152 *bytes=*(s-2);
1153 bytes[1]=*(s-1);
1154
1155 c=0xffff;
1156 *err=U_ILLEGAL_CHAR_FOUND;
1157 }
1158 }
1159
1160 pArgs->source=(const char *)s;
1161 return c;
b75a7d8f
A
1162}
1163
729e4ab9
A
1164static void
1165_UTF16LEReset(UConverter *cnv, UConverterResetChoice choice) {
1166 if(choice<=UCNV_RESET_TO_UNICODE) {
1167 /* reset toUnicode state */
1168 if(UCNV_GET_VERSION(cnv)==0) {
1169 cnv->mode=8; /* no BOM handling */
1170 } else {
1171 cnv->mode=0; /* Java-specific "UnicodeLittle" requires LE BOM or no BOM */
1172 }
1173 }
1174 if(choice!=UCNV_RESET_TO_UNICODE && UCNV_GET_VERSION(cnv)==1) {
1175 /* reset fromUnicode for "UnicodeLittle": prepare to output the UTF-16LE BOM */
1176 cnv->fromUnicodeStatus=UCNV_NEED_TO_WRITE_BOM;
1177 }
1178}
1179
1180static void
1181_UTF16LEOpen(UConverter *cnv,
1182 UConverterLoadArgs *pArgs,
1183 UErrorCode *pErrorCode) {
1184 if(UCNV_GET_VERSION(cnv)<=1) {
1185 _UTF16LEReset(cnv, UCNV_RESET_BOTH);
1186 } else {
1187 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1188 }
1189}
1190
1191static const char *
1192_UTF16LEGetName(const UConverter *cnv) {
1193 if(UCNV_GET_VERSION(cnv)==0) {
1194 return "UTF-16LE";
1195 } else {
1196 return "UTF-16LE,version=1";
1197 }
1198}
1199
b75a7d8f
A
1200static const UConverterImpl _UTF16LEImpl={
1201 UCNV_UTF16_LittleEndian,
1202
1203 NULL,
1204 NULL,
1205
729e4ab9 1206 _UTF16LEOpen,
b75a7d8f 1207 NULL,
729e4ab9 1208 _UTF16LEReset,
b75a7d8f
A
1209
1210 _UTF16LEToUnicodeWithOffsets,
1211 _UTF16LEToUnicodeWithOffsets,
1212 _UTF16LEFromUnicodeWithOffsets,
1213 _UTF16LEFromUnicodeWithOffsets,
374ca955 1214 _UTF16LEGetNextUChar,
b75a7d8f
A
1215
1216 NULL,
729e4ab9 1217 _UTF16LEGetName,
b75a7d8f
A
1218 NULL,
1219 NULL,
73c04bcf 1220 ucnv_getNonSurrogateUnicodeSet
b75a7d8f
A
1221};
1222
1223
b75a7d8f
A
1224static const UConverterStaticData _UTF16LEStaticData={
1225 sizeof(UConverterStaticData),
1226 "UTF-16LE",
729e4ab9 1227 1202, UCNV_IBM, UCNV_UTF16_LittleEndian, 2, 2,
b75a7d8f
A
1228 { 0xfd, 0xff, 0, 0 },2,FALSE,FALSE,
1229 0,
1230 0,
1231 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
1232};
1233
1234
2ca993e8
A
1235const UConverterSharedData _UTF16LEData=
1236 UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16LEStaticData, &_UTF16LEImpl);
b75a7d8f
A
1237
1238/* UTF-16 (Detect BOM) ------------------------------------------------------ */
1239
1240/*
1241 * Detect a BOM at the beginning of the stream and select UTF-16BE or UTF-16LE
1242 * accordingly.
729e4ab9 1243 * This is a simpler version of the UTF-32 converter, with
b75a7d8f
A
1244 * fewer states for shorter BOMs.
1245 *
1246 * State values:
1247 * 0 initial state
729e4ab9
A
1248 * 1 saw first byte
1249 * 2..5 -
1250 * 6..7 see _UTF16ToUnicodeWithOffsets() comments in state 1
b75a7d8f
A
1251 * 8 UTF-16BE mode
1252 * 9 UTF-16LE mode
1253 *
729e4ab9 1254 * During detection: state==number of initial bytes seen so far.
b75a7d8f
A
1255 *
1256 * On output, emit U+FEFF as the first code point.
729e4ab9
A
1257 *
1258 * Variants:
1259 * - UTF-16,version=1 (Java "Unicode" encoding) treats a missing BOM as an error.
1260 * - UTF-16BE,version=1 (Java "UnicodeBig" encoding) and
1261 * UTF-16LE,version=1 (Java "UnicodeLittle" encoding) treat a reverse BOM as an error.
b75a7d8f
A
1262 */
1263
1264static void
1265_UTF16Reset(UConverter *cnv, UConverterResetChoice choice) {
1266 if(choice<=UCNV_RESET_TO_UNICODE) {
1267 /* reset toUnicode: state=0 */
1268 cnv->mode=0;
1269 }
1270 if(choice!=UCNV_RESET_TO_UNICODE) {
1271 /* reset fromUnicode: prepare to output the UTF-16PE BOM */
73c04bcf 1272 cnv->fromUnicodeStatus=UCNV_NEED_TO_WRITE_BOM;
b75a7d8f
A
1273 }
1274}
1275
729e4ab9
A
1276static const UConverterSharedData _UTF16v2Data;
1277
b75a7d8f
A
1278static void
1279_UTF16Open(UConverter *cnv,
729e4ab9 1280 UConverterLoadArgs *pArgs,
b75a7d8f 1281 UErrorCode *pErrorCode) {
729e4ab9
A
1282 if(UCNV_GET_VERSION(cnv)<=2) {
1283 if(UCNV_GET_VERSION(cnv)==2 && !pArgs->onlyTestIsLoadable) {
1284 /*
1285 * Switch implementation, and switch the staticData that's different
1286 * and was copied into the UConverter.
1287 * (See ucnv_createConverterFromSharedData() in ucnv_bld.c.)
1288 * UTF-16,version=2 fromUnicode() always writes a big-endian byte stream.
1289 */
1290 cnv->sharedData=(UConverterSharedData*)&_UTF16v2Data;
1291 uprv_memcpy(cnv->subChars, _UTF16v2Data.staticData->subChar, UCNV_MAX_SUBCHAR_LEN);
1292 }
1293 _UTF16Reset(cnv, UCNV_RESET_BOTH);
1294 } else {
1295 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1296 }
b75a7d8f
A
1297}
1298
729e4ab9
A
1299static const char *
1300_UTF16GetName(const UConverter *cnv) {
1301 if(UCNV_GET_VERSION(cnv)==0) {
1302 return "UTF-16";
1303 } else if(UCNV_GET_VERSION(cnv)==1) {
1304 return "UTF-16,version=1";
1305 } else {
1306 return "UTF-16,version=2";
1307 }
1308}
1309
1310const UConverterSharedData _UTF16Data;
1311
1312#define IS_UTF16BE(cnv) ((cnv)->sharedData==&_UTF16BEData)
1313#define IS_UTF16LE(cnv) ((cnv)->sharedData==&_UTF16LEData)
1314#define IS_UTF16(cnv) ((cnv)->sharedData==&_UTF16Data || (cnv)->sharedData==&_UTF16v2Data)
b75a7d8f
A
1315
1316static void
1317_UTF16ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
1318 UErrorCode *pErrorCode) {
1319 UConverter *cnv=pArgs->converter;
1320 const char *source=pArgs->source;
1321 const char *sourceLimit=pArgs->sourceLimit;
1322 int32_t *offsets=pArgs->offsets;
1323
1324 int32_t state, offsetDelta;
729e4ab9 1325 uint8_t b;
b75a7d8f
A
1326
1327 state=cnv->mode;
1328
1329 /*
1330 * If we detect a BOM in this buffer, then we must add the BOM size to the
1331 * offsets because the actual converter function will not see and count the BOM.
1332 * offsetDelta will have the number of the BOM bytes that are in the current buffer.
1333 */
1334 offsetDelta=0;
1335
1336 while(source<sourceLimit && U_SUCCESS(*pErrorCode)) {
1337 switch(state) {
1338 case 0:
729e4ab9
A
1339 cnv->toUBytes[0]=(uint8_t)*source++;
1340 cnv->toULength=1;
1341 state=1;
b75a7d8f
A
1342 break;
1343 case 1:
729e4ab9
A
1344 /*
1345 * Only inside this switch case can the state variable
1346 * temporarily take two additional values:
1347 * 6: BOM error, continue with BE
1348 * 7: BOM error, continue with LE
1349 */
1350 b=*source;
1351 if(cnv->toUBytes[0]==0xfe && b==0xff) {
1352 if(IS_UTF16LE(cnv)) {
1353 state=7; /* illegal reverse BOM for Java "UnicodeLittle" */
1354 } else {
b75a7d8f 1355 state=8; /* detect UTF-16BE */
729e4ab9
A
1356 }
1357 } else if(cnv->toUBytes[0]==0xff && b==0xfe) {
1358 if(IS_UTF16BE(cnv)) {
1359 state=6; /* illegal reverse BOM for Java "UnicodeBig" */
1360 } else {
b75a7d8f 1361 state=9; /* detect UTF-16LE */
b75a7d8f 1362 }
729e4ab9
A
1363 } else if((IS_UTF16(cnv) && UCNV_GET_VERSION(cnv)==1)) {
1364 state=6; /* illegal missing BOM for Java "Unicode" */
1365 }
1366 if(state>=8) {
1367 /* BOM detected, consume it */
1368 ++source;
1369 cnv->toULength=0;
1370 offsetDelta=(int32_t)(source-pArgs->source);
1371 } else if(state<6) {
1372 /* ok: no BOM, and not a reverse BOM */
b75a7d8f 1373 if(source!=pArgs->source) {
729e4ab9 1374 /* reset the source for a correct first offset */
b75a7d8f 1375 source=pArgs->source;
729e4ab9
A
1376 cnv->toULength=0;
1377 }
1378 if(IS_UTF16LE(cnv)) {
1379 /* Make Java "UnicodeLittle" default to LE. */
1380 state=9;
b75a7d8f 1381 } else {
729e4ab9
A
1382 /* Make standard UTF-16 and Java "UnicodeBig" default to BE. */
1383 state=8;
b75a7d8f 1384 }
729e4ab9
A
1385 } else {
1386 /*
1387 * error: missing BOM, or reverse BOM
1388 * UTF-16,version=1: Java-specific "Unicode" requires a BOM.
1389 * UTF-16BE,version=1: Java-specific "UnicodeBig" requires a BE BOM or no BOM.
1390 * UTF-16LE,version=1: Java-specific "UnicodeLittle" requires an LE BOM or no BOM.
1391 */
1392 /* report the non-BOM or reverse BOM as an illegal sequence */
1393 cnv->toUBytes[1]=b;
1394 cnv->toULength=2;
1395 pArgs->source=source+1;
1396 /* continue with conversion if the callback resets the error */
1397 /*
1398 * Make Java "Unicode" default to BE like standard UTF-16.
1399 * Make Java "UnicodeBig" and "UnicodeLittle" default
1400 * to their normal endiannesses.
1401 */
1402 cnv->mode=state+2;
1403 *pErrorCode=U_ILLEGAL_ESCAPE_SEQUENCE;
1404 return;
b75a7d8f 1405 }
729e4ab9
A
1406 /* convert the rest of the stream */
1407 cnv->mode=state;
1408 continue;
b75a7d8f
A
1409 case 8:
1410 /* call UTF-16BE */
1411 pArgs->source=source;
1412 _UTF16BEToUnicodeWithOffsets(pArgs, pErrorCode);
1413 source=pArgs->source;
1414 break;
1415 case 9:
1416 /* call UTF-16LE */
1417 pArgs->source=source;
1418 _UTF16LEToUnicodeWithOffsets(pArgs, pErrorCode);
1419 source=pArgs->source;
1420 break;
1421 default:
1422 break; /* does not occur */
1423 }
1424 }
1425
1426 /* add BOM size to offsets - see comment at offsetDelta declaration */
1427 if(offsets!=NULL && offsetDelta!=0) {
1428 int32_t *offsetsLimit=pArgs->offsets;
1429 while(offsets<offsetsLimit) {
1430 *offsets++ += offsetDelta;
1431 }
1432 }
1433
1434 pArgs->source=source;
1435
1436 if(source==sourceLimit && pArgs->flush) {
1437 /* handle truncated input */
1438 switch(state) {
1439 case 0:
1440 break; /* no input at all, nothing to do */
1441 case 8:
1442 _UTF16BEToUnicodeWithOffsets(pArgs, pErrorCode);
1443 break;
1444 case 9:
1445 _UTF16LEToUnicodeWithOffsets(pArgs, pErrorCode);
1446 break;
1447 default:
729e4ab9 1448 /* 0<state<8: framework will report truncation, nothing to do here */
b75a7d8f
A
1449 break;
1450 }
b75a7d8f 1451 }
374ca955
A
1452
1453 cnv->mode=state;
b75a7d8f
A
1454}
1455
1456static UChar32
1457_UTF16GetNextUChar(UConverterToUnicodeArgs *pArgs,
1458 UErrorCode *pErrorCode) {
1459 switch(pArgs->converter->mode) {
1460 case 8:
374ca955 1461 return _UTF16BEGetNextUChar(pArgs, pErrorCode);
b75a7d8f 1462 case 9:
374ca955 1463 return _UTF16LEGetNextUChar(pArgs, pErrorCode);
b75a7d8f 1464 default:
374ca955 1465 return UCNV_GET_NEXT_UCHAR_USE_TO_U;
b75a7d8f
A
1466 }
1467}
1468
1469static const UConverterImpl _UTF16Impl = {
1470 UCNV_UTF16,
1471
1472 NULL,
1473 NULL,
1474
1475 _UTF16Open,
1476 NULL,
1477 _UTF16Reset,
1478
1479 _UTF16ToUnicodeWithOffsets,
1480 _UTF16ToUnicodeWithOffsets,
1481 _UTF16PEFromUnicodeWithOffsets,
1482 _UTF16PEFromUnicodeWithOffsets,
1483 _UTF16GetNextUChar,
1484
1485 NULL, /* ### TODO implement getStarters for all Unicode encodings?! */
729e4ab9 1486 _UTF16GetName,
b75a7d8f
A
1487 NULL,
1488 NULL,
73c04bcf 1489 ucnv_getNonSurrogateUnicodeSet
b75a7d8f
A
1490};
1491
1492static const UConverterStaticData _UTF16StaticData = {
1493 sizeof(UConverterStaticData),
1494 "UTF-16",
73c04bcf 1495 1204, /* CCSID for BOM sensitive UTF-16 */
729e4ab9 1496 UCNV_IBM, UCNV_UTF16, 2, 2,
b75a7d8f
A
1497#if U_IS_BIG_ENDIAN
1498 { 0xff, 0xfd, 0, 0 }, 2,
1499#else
1500 { 0xfd, 0xff, 0, 0 }, 2,
1501#endif
1502 FALSE, FALSE,
1503 0,
1504 0,
1505 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
1506};
1507
2ca993e8
A
1508const UConverterSharedData _UTF16Data =
1509 UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16StaticData, &_UTF16Impl);
374ca955 1510
729e4ab9
A
1511static const UConverterImpl _UTF16v2Impl = {
1512 UCNV_UTF16,
1513
1514 NULL,
1515 NULL,
1516
1517 _UTF16Open,
1518 NULL,
1519 _UTF16Reset,
1520
1521 _UTF16ToUnicodeWithOffsets,
1522 _UTF16ToUnicodeWithOffsets,
1523 _UTF16BEFromUnicodeWithOffsets,
1524 _UTF16BEFromUnicodeWithOffsets,
1525 _UTF16GetNextUChar,
1526
1527 NULL, /* ### TODO implement getStarters for all Unicode encodings?! */
1528 _UTF16GetName,
1529 NULL,
1530 NULL,
1531 ucnv_getNonSurrogateUnicodeSet
1532};
1533
1534static const UConverterStaticData _UTF16v2StaticData = {
1535 sizeof(UConverterStaticData),
1536 "UTF-16,version=2",
1537 1204, /* CCSID for BOM sensitive UTF-16 */
1538 UCNV_IBM, UCNV_UTF16, 2, 2,
1539 { 0xff, 0xfd, 0, 0 }, 2,
1540 FALSE, FALSE,
1541 0,
1542 0,
1543 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
1544};
1545
2ca993e8
A
1546static const UConverterSharedData _UTF16v2Data =
1547 UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16v2StaticData, &_UTF16v2Impl);
729e4ab9 1548
374ca955 1549#endif