1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 **********************************************************************
5 * Copyright (C) 2002-2015, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 **********************************************************************
8 * file name: ucnv_u16.c
10 * tab size: 8 (not used)
13 * created on: 2002jul01
14 * created by: Markus W. Scherer
16 * UTF-16 converter implementation. Used to be in ucnv_utf.c.
19 #include "unicode/utypes.h"
21 #if !UCONFIG_NO_CONVERSION
23 #include "unicode/ucnv.h"
29 UCNV_NEED_TO_WRITE_BOM=1
33 * The UTF-16 toUnicode implementation is also used for the Java-specific
34 * "with BOM" variants of UTF-16BE and UTF-16LE.
37 _UTF16ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
38 UErrorCode *pErrorCode);
40 /* UTF-16BE ----------------------------------------------------------------- */
43 # define _UTF16PEFromUnicodeWithOffsets _UTF16BEFromUnicodeWithOffsets
45 # define _UTF16PEFromUnicodeWithOffsets _UTF16LEFromUnicodeWithOffsets
50 _UTF16BEFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs,
51 UErrorCode *pErrorCode) {
57 uint32_t targetCapacity, length, sourceIndex;
62 length=(int32_t)(pArgs->sourceLimit-source);
64 /* no input, nothing to do */
70 /* write the BOM if necessary */
71 if(cnv->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) {
72 static const char bom[]={ (char)0xfe, (char)0xff };
73 ucnv_fromUWriteBytes(cnv,
75 &pArgs->target, pArgs->targetLimit,
78 cnv->fromUnicodeStatus=0;
82 if(target >= pArgs->targetLimit) {
83 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
87 targetCapacity=(uint32_t)(pArgs->targetLimit-target);
88 offsets=pArgs->offsets;
91 /* c!=0 indicates in several places outside the main loops that a surrogate was found */
93 if((c=(UChar)cnv->fromUChar32)!=0 && U16_IS_TRAIL(trail=*source) && targetCapacity>=4) {
94 /* the last buffer ended with a lead surrogate, output the surrogate pair */
97 target[0]=(uint8_t)(c>>8);
99 target[2]=(uint8_t)(trail>>8);
100 target[3]=(uint8_t)trail;
110 cnv->fromUChar32=c=0;
114 /* copy an even number of bytes for complete UChars */
115 uint32_t count=2*length;
116 if(count>targetCapacity) {
117 count=targetCapacity&~1;
120 targetCapacity-=count;
127 if(U16_IS_SINGLE(c)) {
128 target[0]=(uint8_t)(c>>8);
129 target[1]=(uint8_t)c;
131 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 && U16_IS_TRAIL(trail=*source)) {
134 target[0]=(uint8_t)(c>>8);
135 target[1]=(uint8_t)c;
136 target[2]=(uint8_t)(trail>>8);
137 target[3]=(uint8_t)trail;
147 if(U16_IS_SINGLE(c)) {
148 target[0]=(uint8_t)(c>>8);
149 target[1]=(uint8_t)c;
151 *offsets++=sourceIndex;
152 *offsets++=sourceIndex++;
153 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 && U16_IS_TRAIL(trail=*source)) {
156 target[0]=(uint8_t)(c>>8);
157 target[1]=(uint8_t)c;
158 target[2]=(uint8_t)(trail>>8);
159 target[3]=(uint8_t)trail;
161 *offsets++=sourceIndex;
162 *offsets++=sourceIndex;
163 *offsets++=sourceIndex;
164 *offsets++=sourceIndex;
174 /* done with the loop for complete UChars */
175 if(length>0 && targetCapacity>0) {
177 * there is more input and some target capacity -
178 * it must be targetCapacity==1 because otherwise
179 * the above would have copied more;
180 * prepare for overflow output
182 if(U16_IS_SINGLE(c=*source++)) {
183 overflow[0]=(char)(c>>8);
185 length=2; /* 2 bytes to output */
187 /* } else { keep c for surrogate handling, length will be set there */
194 /* keep c for surrogate handling, length will be set there */
195 targetCapacity+=2*count;
198 length=0; /* from here on, length counts the bytes in overflow[] */
203 * c is a surrogate, and
204 * - source or target too short
205 * - or the surrogate is unmatched
208 if(U16_IS_SURROGATE_LEAD(c)) {
209 if(source<pArgs->sourceLimit) {
210 if(U16_IS_TRAIL(trail=*source)) {
211 /* output the surrogate pair, will overflow (see conditions comment above) */
213 overflow[0]=(char)(c>>8);
215 overflow[2]=(char)(trail>>8);
216 overflow[3]=(char)trail;
217 length=4; /* 4 bytes to output */
220 /* unmatched lead surrogate */
221 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
224 /* see if the trail surrogate is in the next buffer */
227 /* unmatched trail surrogate */
228 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
234 /* output length bytes with overflow (length>targetCapacity>0) */
235 ucnv_fromUWriteBytes(cnv,
237 (char **)&target, pArgs->targetLimit,
238 &offsets, sourceIndex,
240 targetCapacity=(uint32_t)(pArgs->targetLimit-(char *)target);
243 if(U_SUCCESS(*pErrorCode) && source<pArgs->sourceLimit && targetCapacity==0) {
244 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
247 /* write back the updated pointers */
248 pArgs->source=source;
249 pArgs->target=(char *)target;
250 pArgs->offsets=offsets;
254 _UTF16BEToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
255 UErrorCode *pErrorCode) {
257 const uint8_t *source;
261 uint32_t targetCapacity, length, count, sourceIndex;
264 if(pArgs->converter->mode<8) {
265 _UTF16ToUnicodeWithOffsets(pArgs, pErrorCode);
269 cnv=pArgs->converter;
270 source=(const uint8_t *)pArgs->source;
271 length=(int32_t)((const uint8_t *)pArgs->sourceLimit-source);
272 if(length<=0 && cnv->toUnicodeStatus==0) {
273 /* no input, nothing to do */
277 target=pArgs->target;
278 if(target >= pArgs->targetLimit) {
279 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
283 targetCapacity=(uint32_t)(pArgs->targetLimit-target);
284 offsets=pArgs->offsets;
288 /* complete a partial UChar or pair from the last call */
289 if(cnv->toUnicodeStatus!=0) {
291 * special case: single byte from a previous buffer,
292 * where the byte turned out not to belong to a trail surrogate
293 * and the preceding, unmatched lead surrogate was put into toUBytes[]
296 cnv->toUBytes[0]=(uint8_t)cnv->toUnicodeStatus;
298 cnv->toUnicodeStatus=0;
300 if((count=cnv->toULength)!=0) {
301 uint8_t *p=cnv->toUBytes;
303 p[count++]=*source++;
307 c=((UChar)p[0]<<8)|p[1];
308 if(U16_IS_SINGLE(c)) {
309 /* output the BMP code point */
318 } else if(U16_IS_SURROGATE_LEAD(c)) {
319 /* continue collecting bytes for the trail surrogate */
320 c=0; /* avoid unnecessary surrogate handling below */
322 /* fall through to error handling for an unmatched trail surrogate */
325 } else if(count==4) {
326 c=((UChar)p[0]<<8)|p[1];
327 trail=((UChar)p[2]<<8)|p[3];
328 if(U16_IS_TRAIL(trail)) {
329 /* output the surrogate pair */
331 if(targetCapacity>=2) {
338 } else /* targetCapacity==1 */ {
340 cnv->UCharErrorBuffer[0]=trail;
341 cnv->UCharErrorBufferLength=1;
342 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
348 /* unmatched lead surrogate, handle here for consistent toUBytes[] */
349 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
351 /* back out reading the code unit after it */
352 if(((const uint8_t *)pArgs->source-source)>=2) {
356 * if the trail unit's first byte was in a previous buffer, then
357 * we need to put it into a special place because toUBytes[] will be
358 * used for the lead unit's bytes
360 cnv->toUnicodeStatus=0x100|p[2];
365 /* write back the updated pointers */
366 pArgs->source=(const char *)source;
367 pArgs->target=target;
368 pArgs->offsets=offsets;
373 cnv->toULength=(int8_t)count;
376 /* copy an even number of bytes for complete UChars */
377 count=2*targetCapacity;
381 if(c==0 && count>0) {
384 targetCapacity-=count;
387 c=((UChar)source[0]<<8)|source[1];
389 if(U16_IS_SINGLE(c)) {
391 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 &&
392 U16_IS_TRAIL(trail=((UChar)source[0]<<8)|source[1])
404 c=((UChar)source[0]<<8)|source[1];
406 if(U16_IS_SINGLE(c)) {
408 *offsets++=sourceIndex;
410 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 &&
411 U16_IS_TRAIL(trail=((UChar)source[0]<<8)|source[1])
417 *offsets++=sourceIndex;
418 *offsets++=sourceIndex;
427 /* done with the loop for complete UChars */
430 /* keep c for surrogate handling, trail will be set there */
431 length+=2*(count-1); /* one more byte pair was consumed than count decremented */
432 targetCapacity+=count;
438 * c is a surrogate, and
439 * - source or target too short
440 * - or the surrogate is unmatched
442 cnv->toUBytes[0]=(uint8_t)(c>>8);
443 cnv->toUBytes[1]=(uint8_t)c;
446 if(U16_IS_SURROGATE_LEAD(c)) {
448 if(U16_IS_TRAIL(trail=((UChar)source[0]<<8)|source[1])) {
449 /* output the surrogate pair, will overflow (see conditions comment above) */
454 *offsets++=sourceIndex;
456 cnv->UCharErrorBuffer[0]=trail;
457 cnv->UCharErrorBufferLength=1;
459 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
461 /* unmatched lead surrogate */
462 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
465 /* see if the trail surrogate is in the next buffer */
468 /* unmatched trail surrogate */
469 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
473 if(U_SUCCESS(*pErrorCode)) {
474 /* check for a remaining source byte */
476 if(targetCapacity==0) {
477 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
479 /* it must be length==1 because otherwise the above would have copied more */
480 cnv->toUBytes[cnv->toULength++]=*source++;
485 /* write back the updated pointers */
486 pArgs->source=(const char *)source;
487 pArgs->target=target;
488 pArgs->offsets=offsets;
492 _UTF16BEGetNextUChar(UConverterToUnicodeArgs *pArgs, UErrorCode *err) {
493 const uint8_t *s, *sourceLimit;
496 if(pArgs->converter->mode<8) {
497 return UCNV_GET_NEXT_UCHAR_USE_TO_U;
500 s=(const uint8_t *)pArgs->source;
501 sourceLimit=(const uint8_t *)pArgs->sourceLimit;
505 *err=U_INDEX_OUTOFBOUNDS_ERROR;
509 if(s+2>sourceLimit) {
510 /* only one byte: truncated UChar */
511 pArgs->converter->toUBytes[0]=*s++;
512 pArgs->converter->toULength=1;
513 pArgs->source=(const char *)s;
514 *err = U_TRUNCATED_CHAR_FOUND;
519 c=((UChar32)*s<<8)|s[1];
522 /* check for a surrogate pair */
523 if(U_IS_SURROGATE(c)) {
524 if(U16_IS_SURROGATE_LEAD(c)) {
525 if(s+2<=sourceLimit) {
528 /* get a second UChar and see if it is a trail surrogate */
529 trail=((UChar)*s<<8)|s[1];
530 if(U16_IS_TRAIL(trail)) {
531 c=U16_GET_SUPPLEMENTARY(c, trail);
534 /* unmatched lead surrogate */
538 /* too few (2 or 3) bytes for a surrogate pair: truncated code point */
539 uint8_t *bytes=pArgs->converter->toUBytes;
541 pArgs->converter->toULength=(int8_t)(sourceLimit-s);
544 } while(s<sourceLimit);
547 *err=U_TRUNCATED_CHAR_FOUND;
550 /* unmatched trail surrogate */
555 /* write the unmatched surrogate */
556 uint8_t *bytes=pArgs->converter->toUBytes;
557 pArgs->converter->toULength=2;
562 *err=U_ILLEGAL_CHAR_FOUND;
566 pArgs->source=(const char *)s;
571 _UTF16BEReset(UConverter *cnv, UConverterResetChoice choice) {
572 if(choice<=UCNV_RESET_TO_UNICODE) {
573 /* reset toUnicode state */
574 if(UCNV_GET_VERSION(cnv)==0) {
575 cnv->mode=8; /* no BOM handling */
577 cnv->mode=0; /* Java-specific "UnicodeBig" requires BE BOM or no BOM */
580 if(choice!=UCNV_RESET_TO_UNICODE && UCNV_GET_VERSION(cnv)==1) {
581 /* reset fromUnicode for "UnicodeBig": prepare to output the UTF-16BE BOM */
582 cnv->fromUnicodeStatus=UCNV_NEED_TO_WRITE_BOM;
587 _UTF16BEOpen(UConverter *cnv,
588 UConverterLoadArgs *pArgs,
589 UErrorCode *pErrorCode) {
590 if(UCNV_GET_VERSION(cnv)<=1) {
591 _UTF16BEReset(cnv, UCNV_RESET_BOTH);
593 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
598 _UTF16BEGetName(const UConverter *cnv) {
599 if(UCNV_GET_VERSION(cnv)==0) {
602 return "UTF-16BE,version=1";
606 static const UConverterImpl _UTF16BEImpl={
607 UCNV_UTF16_BigEndian,
616 _UTF16BEToUnicodeWithOffsets,
617 _UTF16BEToUnicodeWithOffsets,
618 _UTF16BEFromUnicodeWithOffsets,
619 _UTF16BEFromUnicodeWithOffsets,
620 _UTF16BEGetNextUChar,
626 ucnv_getNonSurrogateUnicodeSet,
632 static const UConverterStaticData _UTF16BEStaticData={
633 sizeof(UConverterStaticData),
635 1200, UCNV_IBM, UCNV_UTF16_BigEndian, 2, 2,
636 { 0xff, 0xfd, 0, 0 },2,FALSE,FALSE,
639 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
643 const UConverterSharedData _UTF16BEData=
644 UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16BEStaticData, &_UTF16BEImpl);
646 /* UTF-16LE ----------------------------------------------------------------- */
649 _UTF16LEFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs,
650 UErrorCode *pErrorCode) {
656 uint32_t targetCapacity, length, sourceIndex;
660 source=pArgs->source;
661 length=(int32_t)(pArgs->sourceLimit-source);
663 /* no input, nothing to do */
667 cnv=pArgs->converter;
669 /* write the BOM if necessary */
670 if(cnv->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) {
671 static const char bom[]={ (char)0xff, (char)0xfe };
672 ucnv_fromUWriteBytes(cnv,
674 &pArgs->target, pArgs->targetLimit,
677 cnv->fromUnicodeStatus=0;
680 target=pArgs->target;
681 if(target >= pArgs->targetLimit) {
682 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
686 targetCapacity=(uint32_t)(pArgs->targetLimit-pArgs->target);
687 offsets=pArgs->offsets;
690 /* c!=0 indicates in several places outside the main loops that a surrogate was found */
692 if((c=(UChar)cnv->fromUChar32)!=0 && U16_IS_TRAIL(trail=*source) && targetCapacity>=4) {
693 /* the last buffer ended with a lead surrogate, output the surrogate pair */
696 target[0]=(uint8_t)c;
697 target[1]=(uint8_t)(c>>8);
698 target[2]=(uint8_t)trail;
699 target[3]=(uint8_t)(trail>>8);
709 cnv->fromUChar32=c=0;
713 /* copy an even number of bytes for complete UChars */
714 uint32_t count=2*length;
715 if(count>targetCapacity) {
716 count=targetCapacity&~1;
719 targetCapacity-=count;
726 if(U16_IS_SINGLE(c)) {
727 target[0]=(uint8_t)c;
728 target[1]=(uint8_t)(c>>8);
730 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 && U16_IS_TRAIL(trail=*source)) {
733 target[0]=(uint8_t)c;
734 target[1]=(uint8_t)(c>>8);
735 target[2]=(uint8_t)trail;
736 target[3]=(uint8_t)(trail>>8);
746 if(U16_IS_SINGLE(c)) {
747 target[0]=(uint8_t)c;
748 target[1]=(uint8_t)(c>>8);
750 *offsets++=sourceIndex;
751 *offsets++=sourceIndex++;
752 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 && U16_IS_TRAIL(trail=*source)) {
755 target[0]=(uint8_t)c;
756 target[1]=(uint8_t)(c>>8);
757 target[2]=(uint8_t)trail;
758 target[3]=(uint8_t)(trail>>8);
760 *offsets++=sourceIndex;
761 *offsets++=sourceIndex;
762 *offsets++=sourceIndex;
763 *offsets++=sourceIndex;
773 /* done with the loop for complete UChars */
774 if(length>0 && targetCapacity>0) {
776 * there is more input and some target capacity -
777 * it must be targetCapacity==1 because otherwise
778 * the above would have copied more;
779 * prepare for overflow output
781 if(U16_IS_SINGLE(c=*source++)) {
783 overflow[1]=(char)(c>>8);
784 length=2; /* 2 bytes to output */
786 /* } else { keep c for surrogate handling, length will be set there */
793 /* keep c for surrogate handling, length will be set there */
794 targetCapacity+=2*count;
797 length=0; /* from here on, length counts the bytes in overflow[] */
802 * c is a surrogate, and
803 * - source or target too short
804 * - or the surrogate is unmatched
807 if(U16_IS_SURROGATE_LEAD(c)) {
808 if(source<pArgs->sourceLimit) {
809 if(U16_IS_TRAIL(trail=*source)) {
810 /* output the surrogate pair, will overflow (see conditions comment above) */
813 overflow[1]=(char)(c>>8);
814 overflow[2]=(char)trail;
815 overflow[3]=(char)(trail>>8);
816 length=4; /* 4 bytes to output */
819 /* unmatched lead surrogate */
820 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
823 /* see if the trail surrogate is in the next buffer */
826 /* unmatched trail surrogate */
827 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
833 /* output length bytes with overflow (length>targetCapacity>0) */
834 ucnv_fromUWriteBytes(cnv,
836 &target, pArgs->targetLimit,
837 &offsets, sourceIndex,
839 targetCapacity=(uint32_t)(pArgs->targetLimit-(char *)target);
842 if(U_SUCCESS(*pErrorCode) && source<pArgs->sourceLimit && targetCapacity==0) {
843 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
846 /* write back the updated pointers */
847 pArgs->source=source;
848 pArgs->target=target;
849 pArgs->offsets=offsets;
853 _UTF16LEToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
854 UErrorCode *pErrorCode) {
856 const uint8_t *source;
860 uint32_t targetCapacity, length, count, sourceIndex;
863 if(pArgs->converter->mode<8) {
864 _UTF16ToUnicodeWithOffsets(pArgs, pErrorCode);
868 cnv=pArgs->converter;
869 source=(const uint8_t *)pArgs->source;
870 length=(int32_t)((const uint8_t *)pArgs->sourceLimit-source);
871 if(length<=0 && cnv->toUnicodeStatus==0) {
872 /* no input, nothing to do */
876 target=pArgs->target;
877 if(target >= pArgs->targetLimit) {
878 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
882 targetCapacity=(uint32_t)(pArgs->targetLimit-pArgs->target);
883 offsets=pArgs->offsets;
887 /* complete a partial UChar or pair from the last call */
888 if(cnv->toUnicodeStatus!=0) {
890 * special case: single byte from a previous buffer,
891 * where the byte turned out not to belong to a trail surrogate
892 * and the preceding, unmatched lead surrogate was put into toUBytes[]
895 cnv->toUBytes[0]=(uint8_t)cnv->toUnicodeStatus;
897 cnv->toUnicodeStatus=0;
899 if((count=cnv->toULength)!=0) {
900 uint8_t *p=cnv->toUBytes;
902 p[count++]=*source++;
906 c=((UChar)p[1]<<8)|p[0];
907 if(U16_IS_SINGLE(c)) {
908 /* output the BMP code point */
917 } else if(U16_IS_SURROGATE_LEAD(c)) {
918 /* continue collecting bytes for the trail surrogate */
919 c=0; /* avoid unnecessary surrogate handling below */
921 /* fall through to error handling for an unmatched trail surrogate */
924 } else if(count==4) {
925 c=((UChar)p[1]<<8)|p[0];
926 trail=((UChar)p[3]<<8)|p[2];
927 if(U16_IS_TRAIL(trail)) {
928 /* output the surrogate pair */
930 if(targetCapacity>=2) {
937 } else /* targetCapacity==1 */ {
939 cnv->UCharErrorBuffer[0]=trail;
940 cnv->UCharErrorBufferLength=1;
941 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
947 /* unmatched lead surrogate, handle here for consistent toUBytes[] */
948 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
950 /* back out reading the code unit after it */
951 if(((const uint8_t *)pArgs->source-source)>=2) {
955 * if the trail unit's first byte was in a previous buffer, then
956 * we need to put it into a special place because toUBytes[] will be
957 * used for the lead unit's bytes
959 cnv->toUnicodeStatus=0x100|p[2];
964 /* write back the updated pointers */
965 pArgs->source=(const char *)source;
966 pArgs->target=target;
967 pArgs->offsets=offsets;
972 cnv->toULength=(int8_t)count;
975 /* copy an even number of bytes for complete UChars */
976 count=2*targetCapacity;
980 if(c==0 && count>0) {
983 targetCapacity-=count;
986 c=((UChar)source[1]<<8)|source[0];
988 if(U16_IS_SINGLE(c)) {
990 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 &&
991 U16_IS_TRAIL(trail=((UChar)source[1]<<8)|source[0])
1003 c=((UChar)source[1]<<8)|source[0];
1005 if(U16_IS_SINGLE(c)) {
1007 *offsets++=sourceIndex;
1009 } else if(U16_IS_SURROGATE_LEAD(c) && count>=2 &&
1010 U16_IS_TRAIL(trail=((UChar)source[1]<<8)|source[0])
1016 *offsets++=sourceIndex;
1017 *offsets++=sourceIndex;
1026 /* done with the loop for complete UChars */
1029 /* keep c for surrogate handling, trail will be set there */
1030 length+=2*(count-1); /* one more byte pair was consumed than count decremented */
1031 targetCapacity+=count;
1037 * c is a surrogate, and
1038 * - source or target too short
1039 * - or the surrogate is unmatched
1041 cnv->toUBytes[0]=(uint8_t)c;
1042 cnv->toUBytes[1]=(uint8_t)(c>>8);
1045 if(U16_IS_SURROGATE_LEAD(c)) {
1047 if(U16_IS_TRAIL(trail=((UChar)source[1]<<8)|source[0])) {
1048 /* output the surrogate pair, will overflow (see conditions comment above) */
1053 *offsets++=sourceIndex;
1055 cnv->UCharErrorBuffer[0]=trail;
1056 cnv->UCharErrorBufferLength=1;
1058 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
1060 /* unmatched lead surrogate */
1061 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
1064 /* see if the trail surrogate is in the next buffer */
1067 /* unmatched trail surrogate */
1068 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
1072 if(U_SUCCESS(*pErrorCode)) {
1073 /* check for a remaining source byte */
1075 if(targetCapacity==0) {
1076 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
1078 /* it must be length==1 because otherwise the above would have copied more */
1079 cnv->toUBytes[cnv->toULength++]=*source++;
1084 /* write back the updated pointers */
1085 pArgs->source=(const char *)source;
1086 pArgs->target=target;
1087 pArgs->offsets=offsets;
1091 _UTF16LEGetNextUChar(UConverterToUnicodeArgs *pArgs, UErrorCode *err) {
1092 const uint8_t *s, *sourceLimit;
1095 if(pArgs->converter->mode<8) {
1096 return UCNV_GET_NEXT_UCHAR_USE_TO_U;
1099 s=(const uint8_t *)pArgs->source;
1100 sourceLimit=(const uint8_t *)pArgs->sourceLimit;
1102 if(s>=sourceLimit) {
1104 *err=U_INDEX_OUTOFBOUNDS_ERROR;
1108 if(s+2>sourceLimit) {
1109 /* only one byte: truncated UChar */
1110 pArgs->converter->toUBytes[0]=*s++;
1111 pArgs->converter->toULength=1;
1112 pArgs->source=(const char *)s;
1113 *err = U_TRUNCATED_CHAR_FOUND;
1118 c=((UChar32)s[1]<<8)|*s;
1121 /* check for a surrogate pair */
1122 if(U_IS_SURROGATE(c)) {
1123 if(U16_IS_SURROGATE_LEAD(c)) {
1124 if(s+2<=sourceLimit) {
1127 /* get a second UChar and see if it is a trail surrogate */
1128 trail=((UChar)s[1]<<8)|*s;
1129 if(U16_IS_TRAIL(trail)) {
1130 c=U16_GET_SUPPLEMENTARY(c, trail);
1133 /* unmatched lead surrogate */
1137 /* too few (2 or 3) bytes for a surrogate pair: truncated code point */
1138 uint8_t *bytes=pArgs->converter->toUBytes;
1140 pArgs->converter->toULength=(int8_t)(sourceLimit-s);
1143 } while(s<sourceLimit);
1146 *err=U_TRUNCATED_CHAR_FOUND;
1149 /* unmatched trail surrogate */
1154 /* write the unmatched surrogate */
1155 uint8_t *bytes=pArgs->converter->toUBytes;
1156 pArgs->converter->toULength=2;
1161 *err=U_ILLEGAL_CHAR_FOUND;
1165 pArgs->source=(const char *)s;
1170 _UTF16LEReset(UConverter *cnv, UConverterResetChoice choice) {
1171 if(choice<=UCNV_RESET_TO_UNICODE) {
1172 /* reset toUnicode state */
1173 if(UCNV_GET_VERSION(cnv)==0) {
1174 cnv->mode=8; /* no BOM handling */
1176 cnv->mode=0; /* Java-specific "UnicodeLittle" requires LE BOM or no BOM */
1179 if(choice!=UCNV_RESET_TO_UNICODE && UCNV_GET_VERSION(cnv)==1) {
1180 /* reset fromUnicode for "UnicodeLittle": prepare to output the UTF-16LE BOM */
1181 cnv->fromUnicodeStatus=UCNV_NEED_TO_WRITE_BOM;
1186 _UTF16LEOpen(UConverter *cnv,
1187 UConverterLoadArgs *pArgs,
1188 UErrorCode *pErrorCode) {
1189 if(UCNV_GET_VERSION(cnv)<=1) {
1190 _UTF16LEReset(cnv, UCNV_RESET_BOTH);
1192 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1197 _UTF16LEGetName(const UConverter *cnv) {
1198 if(UCNV_GET_VERSION(cnv)==0) {
1201 return "UTF-16LE,version=1";
1205 static const UConverterImpl _UTF16LEImpl={
1206 UCNV_UTF16_LittleEndian,
1215 _UTF16LEToUnicodeWithOffsets,
1216 _UTF16LEToUnicodeWithOffsets,
1217 _UTF16LEFromUnicodeWithOffsets,
1218 _UTF16LEFromUnicodeWithOffsets,
1219 _UTF16LEGetNextUChar,
1225 ucnv_getNonSurrogateUnicodeSet,
1232 static const UConverterStaticData _UTF16LEStaticData={
1233 sizeof(UConverterStaticData),
1235 1202, UCNV_IBM, UCNV_UTF16_LittleEndian, 2, 2,
1236 { 0xfd, 0xff, 0, 0 },2,FALSE,FALSE,
1239 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
1243 const UConverterSharedData _UTF16LEData=
1244 UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16LEStaticData, &_UTF16LEImpl);
1246 /* UTF-16 (Detect BOM) ------------------------------------------------------ */
1249 * Detect a BOM at the beginning of the stream and select UTF-16BE or UTF-16LE
1251 * This is a simpler version of the UTF-32 converter, with
1252 * fewer states for shorter BOMs.
1258 * 6..7 see _UTF16ToUnicodeWithOffsets() comments in state 1
1262 * During detection: state==number of initial bytes seen so far.
1264 * On output, emit U+FEFF as the first code point.
1267 * - UTF-16,version=1 (Java "Unicode" encoding) treats a missing BOM as an error.
1268 * - UTF-16BE,version=1 (Java "UnicodeBig" encoding) and
1269 * UTF-16LE,version=1 (Java "UnicodeLittle" encoding) treat a reverse BOM as an error.
1273 _UTF16Reset(UConverter *cnv, UConverterResetChoice choice) {
1274 if(choice<=UCNV_RESET_TO_UNICODE) {
1275 /* reset toUnicode: state=0 */
1278 if(choice!=UCNV_RESET_TO_UNICODE) {
1279 /* reset fromUnicode: prepare to output the UTF-16PE BOM */
1280 cnv->fromUnicodeStatus=UCNV_NEED_TO_WRITE_BOM;
1284 static const UConverterSharedData _UTF16v2Data;
1287 _UTF16Open(UConverter *cnv,
1288 UConverterLoadArgs *pArgs,
1289 UErrorCode *pErrorCode) {
1290 if(UCNV_GET_VERSION(cnv)<=2) {
1291 if(UCNV_GET_VERSION(cnv)==2 && !pArgs->onlyTestIsLoadable) {
1293 * Switch implementation, and switch the staticData that's different
1294 * and was copied into the UConverter.
1295 * (See ucnv_createConverterFromSharedData() in ucnv_bld.c.)
1296 * UTF-16,version=2 fromUnicode() always writes a big-endian byte stream.
1298 cnv->sharedData=(UConverterSharedData*)&_UTF16v2Data;
1299 uprv_memcpy(cnv->subChars, _UTF16v2Data.staticData->subChar, UCNV_MAX_SUBCHAR_LEN);
1301 _UTF16Reset(cnv, UCNV_RESET_BOTH);
1303 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1308 _UTF16GetName(const UConverter *cnv) {
1309 if(UCNV_GET_VERSION(cnv)==0) {
1311 } else if(UCNV_GET_VERSION(cnv)==1) {
1312 return "UTF-16,version=1";
1314 return "UTF-16,version=2";
1318 const UConverterSharedData _UTF16Data;
1320 #define IS_UTF16BE(cnv) ((cnv)->sharedData==&_UTF16BEData)
1321 #define IS_UTF16LE(cnv) ((cnv)->sharedData==&_UTF16LEData)
1322 #define IS_UTF16(cnv) ((cnv)->sharedData==&_UTF16Data || (cnv)->sharedData==&_UTF16v2Data)
1325 _UTF16ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
1326 UErrorCode *pErrorCode) {
1327 UConverter *cnv=pArgs->converter;
1328 const char *source=pArgs->source;
1329 const char *sourceLimit=pArgs->sourceLimit;
1330 int32_t *offsets=pArgs->offsets;
1332 int32_t state, offsetDelta;
1338 * If we detect a BOM in this buffer, then we must add the BOM size to the
1339 * offsets because the actual converter function will not see and count the BOM.
1340 * offsetDelta will have the number of the BOM bytes that are in the current buffer.
1344 while(source<sourceLimit && U_SUCCESS(*pErrorCode)) {
1347 cnv->toUBytes[0]=(uint8_t)*source++;
1353 * Only inside this switch case can the state variable
1354 * temporarily take two additional values:
1355 * 6: BOM error, continue with BE
1356 * 7: BOM error, continue with LE
1359 if(cnv->toUBytes[0]==0xfe && b==0xff) {
1360 if(IS_UTF16LE(cnv)) {
1361 state=7; /* illegal reverse BOM for Java "UnicodeLittle" */
1363 state=8; /* detect UTF-16BE */
1365 } else if(cnv->toUBytes[0]==0xff && b==0xfe) {
1366 if(IS_UTF16BE(cnv)) {
1367 state=6; /* illegal reverse BOM for Java "UnicodeBig" */
1369 state=9; /* detect UTF-16LE */
1371 } else if((IS_UTF16(cnv) && UCNV_GET_VERSION(cnv)==1)) {
1372 state=6; /* illegal missing BOM for Java "Unicode" */
1375 /* BOM detected, consume it */
1378 offsetDelta=(int32_t)(source-pArgs->source);
1379 } else if(state<6) {
1380 /* ok: no BOM, and not a reverse BOM */
1381 if(source!=pArgs->source) {
1382 /* reset the source for a correct first offset */
1383 source=pArgs->source;
1386 if(IS_UTF16LE(cnv)) {
1387 /* Make Java "UnicodeLittle" default to LE. */
1390 /* Make standard UTF-16 and Java "UnicodeBig" default to BE. */
1395 * error: missing BOM, or reverse BOM
1396 * UTF-16,version=1: Java-specific "Unicode" requires a BOM.
1397 * UTF-16BE,version=1: Java-specific "UnicodeBig" requires a BE BOM or no BOM.
1398 * UTF-16LE,version=1: Java-specific "UnicodeLittle" requires an LE BOM or no BOM.
1400 /* report the non-BOM or reverse BOM as an illegal sequence */
1403 pArgs->source=source+1;
1404 /* continue with conversion if the callback resets the error */
1406 * Make Java "Unicode" default to BE like standard UTF-16.
1407 * Make Java "UnicodeBig" and "UnicodeLittle" default
1408 * to their normal endiannesses.
1411 *pErrorCode=U_ILLEGAL_ESCAPE_SEQUENCE;
1414 /* convert the rest of the stream */
1419 pArgs->source=source;
1420 _UTF16BEToUnicodeWithOffsets(pArgs, pErrorCode);
1421 source=pArgs->source;
1425 pArgs->source=source;
1426 _UTF16LEToUnicodeWithOffsets(pArgs, pErrorCode);
1427 source=pArgs->source;
1430 break; /* does not occur */
1434 /* add BOM size to offsets - see comment at offsetDelta declaration */
1435 if(offsets!=NULL && offsetDelta!=0) {
1436 int32_t *offsetsLimit=pArgs->offsets;
1437 while(offsets<offsetsLimit) {
1438 *offsets++ += offsetDelta;
1442 pArgs->source=source;
1444 if(source==sourceLimit && pArgs->flush) {
1445 /* handle truncated input */
1448 break; /* no input at all, nothing to do */
1450 _UTF16BEToUnicodeWithOffsets(pArgs, pErrorCode);
1453 _UTF16LEToUnicodeWithOffsets(pArgs, pErrorCode);
1456 /* 0<state<8: framework will report truncation, nothing to do here */
1465 _UTF16GetNextUChar(UConverterToUnicodeArgs *pArgs,
1466 UErrorCode *pErrorCode) {
1467 switch(pArgs->converter->mode) {
1469 return _UTF16BEGetNextUChar(pArgs, pErrorCode);
1471 return _UTF16LEGetNextUChar(pArgs, pErrorCode);
1473 return UCNV_GET_NEXT_UCHAR_USE_TO_U;
1477 static const UConverterImpl _UTF16Impl = {
1487 _UTF16ToUnicodeWithOffsets,
1488 _UTF16ToUnicodeWithOffsets,
1489 _UTF16PEFromUnicodeWithOffsets,
1490 _UTF16PEFromUnicodeWithOffsets,
1493 NULL, /* ### TODO implement getStarters for all Unicode encodings?! */
1497 ucnv_getNonSurrogateUnicodeSet,
1503 static const UConverterStaticData _UTF16StaticData = {
1504 sizeof(UConverterStaticData),
1506 1204, /* CCSID for BOM sensitive UTF-16 */
1507 UCNV_IBM, UCNV_UTF16, 2, 2,
1509 { 0xff, 0xfd, 0, 0 }, 2,
1511 { 0xfd, 0xff, 0, 0 }, 2,
1516 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
1519 const UConverterSharedData _UTF16Data =
1520 UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16StaticData, &_UTF16Impl);
1522 static const UConverterImpl _UTF16v2Impl = {
1532 _UTF16ToUnicodeWithOffsets,
1533 _UTF16ToUnicodeWithOffsets,
1534 _UTF16BEFromUnicodeWithOffsets,
1535 _UTF16BEFromUnicodeWithOffsets,
1538 NULL, /* ### TODO implement getStarters for all Unicode encodings?! */
1542 ucnv_getNonSurrogateUnicodeSet,
1548 static const UConverterStaticData _UTF16v2StaticData = {
1549 sizeof(UConverterStaticData),
1551 1204, /* CCSID for BOM sensitive UTF-16 */
1552 UCNV_IBM, UCNV_UTF16, 2, 2,
1553 { 0xff, 0xfd, 0, 0 }, 2,
1557 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
1560 static const UConverterSharedData _UTF16v2Data =
1561 UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16v2StaticData, &_UTF16v2Impl);