xref: /aosp_15_r20/external/icu/icu4c/source/common/ucnv_u8.cpp (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1*0e209d39SAndroid Build Coastguard Worker // © 2016 and later: Unicode, Inc. and others.
2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html
3*0e209d39SAndroid Build Coastguard Worker /*
4*0e209d39SAndroid Build Coastguard Worker **********************************************************************
5*0e209d39SAndroid Build Coastguard Worker *   Copyright (C) 2002-2016, International Business Machines
6*0e209d39SAndroid Build Coastguard Worker *   Corporation and others.  All Rights Reserved.
7*0e209d39SAndroid Build Coastguard Worker **********************************************************************
8*0e209d39SAndroid Build Coastguard Worker *   file name:  ucnv_u8.c
9*0e209d39SAndroid Build Coastguard Worker *   encoding:   UTF-8
10*0e209d39SAndroid Build Coastguard Worker *   tab size:   8 (not used)
11*0e209d39SAndroid Build Coastguard Worker *   indentation:4
12*0e209d39SAndroid Build Coastguard Worker *
13*0e209d39SAndroid Build Coastguard Worker *   created on: 2002jul01
14*0e209d39SAndroid Build Coastguard Worker *   created by: Markus W. Scherer
15*0e209d39SAndroid Build Coastguard Worker *
16*0e209d39SAndroid Build Coastguard Worker *   UTF-8 converter implementation. Used to be in ucnv_utf.c.
17*0e209d39SAndroid Build Coastguard Worker *
18*0e209d39SAndroid Build Coastguard Worker *   Also, CESU-8 implementation, see UTR 26.
19*0e209d39SAndroid Build Coastguard Worker *   The CESU-8 converter uses all the same functions as the
20*0e209d39SAndroid Build Coastguard Worker *   UTF-8 converter, with a branch for converting supplementary code points.
21*0e209d39SAndroid Build Coastguard Worker */
22*0e209d39SAndroid Build Coastguard Worker 
23*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h"
24*0e209d39SAndroid Build Coastguard Worker 
25*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_CONVERSION
26*0e209d39SAndroid Build Coastguard Worker 
27*0e209d39SAndroid Build Coastguard Worker #include "unicode/ucnv.h"
28*0e209d39SAndroid Build Coastguard Worker #include "unicode/utf.h"
29*0e209d39SAndroid Build Coastguard Worker #include "unicode/utf8.h"
30*0e209d39SAndroid Build Coastguard Worker #include "unicode/utf16.h"
31*0e209d39SAndroid Build Coastguard Worker #include "uassert.h"
32*0e209d39SAndroid Build Coastguard Worker #include "ucnv_bld.h"
33*0e209d39SAndroid Build Coastguard Worker #include "ucnv_cnv.h"
34*0e209d39SAndroid Build Coastguard Worker #include "cmemory.h"
35*0e209d39SAndroid Build Coastguard Worker #include "ustr_imp.h"
36*0e209d39SAndroid Build Coastguard Worker 
37*0e209d39SAndroid Build Coastguard Worker /* Prototypes --------------------------------------------------------------- */
38*0e209d39SAndroid Build Coastguard Worker 
39*0e209d39SAndroid Build Coastguard Worker /* Keep these here to make finicky compilers happy */
40*0e209d39SAndroid Build Coastguard Worker 
41*0e209d39SAndroid Build Coastguard Worker U_CFUNC void ucnv_fromUnicode_UTF8(UConverterFromUnicodeArgs *args,
42*0e209d39SAndroid Build Coastguard Worker                                            UErrorCode *err);
43*0e209d39SAndroid Build Coastguard Worker U_CFUNC void ucnv_fromUnicode_UTF8_OFFSETS_LOGIC(UConverterFromUnicodeArgs *args,
44*0e209d39SAndroid Build Coastguard Worker                                                         UErrorCode *err);
45*0e209d39SAndroid Build Coastguard Worker 
46*0e209d39SAndroid Build Coastguard Worker 
47*0e209d39SAndroid Build Coastguard Worker /* UTF-8 -------------------------------------------------------------------- */
48*0e209d39SAndroid Build Coastguard Worker 
49*0e209d39SAndroid Build Coastguard Worker #define MAXIMUM_UCS2            0x0000FFFF
50*0e209d39SAndroid Build Coastguard Worker 
51*0e209d39SAndroid Build Coastguard Worker static const uint32_t offsetsFromUTF8[5] = {0,
52*0e209d39SAndroid Build Coastguard Worker   (uint32_t) 0x00000000, (uint32_t) 0x00003080, (uint32_t) 0x000E2080,
53*0e209d39SAndroid Build Coastguard Worker   (uint32_t) 0x03C82080
54*0e209d39SAndroid Build Coastguard Worker };
55*0e209d39SAndroid Build Coastguard Worker 
hasCESU8Data(const UConverter * cnv)56*0e209d39SAndroid Build Coastguard Worker static UBool hasCESU8Data(const UConverter *cnv)
57*0e209d39SAndroid Build Coastguard Worker {
58*0e209d39SAndroid Build Coastguard Worker #if UCONFIG_ONLY_HTML_CONVERSION
59*0e209d39SAndroid Build Coastguard Worker     return false;
60*0e209d39SAndroid Build Coastguard Worker #else
61*0e209d39SAndroid Build Coastguard Worker     return (UBool)(cnv->sharedData == &_CESU8Data);
62*0e209d39SAndroid Build Coastguard Worker #endif
63*0e209d39SAndroid Build Coastguard Worker }
64*0e209d39SAndroid Build Coastguard Worker U_CDECL_BEGIN
ucnv_toUnicode_UTF8(UConverterToUnicodeArgs * args,UErrorCode * err)65*0e209d39SAndroid Build Coastguard Worker static void  U_CALLCONV ucnv_toUnicode_UTF8 (UConverterToUnicodeArgs * args,
66*0e209d39SAndroid Build Coastguard Worker                                   UErrorCode * err)
67*0e209d39SAndroid Build Coastguard Worker {
68*0e209d39SAndroid Build Coastguard Worker     UConverter *cnv = args->converter;
69*0e209d39SAndroid Build Coastguard Worker     const unsigned char *mySource = (unsigned char *) args->source;
70*0e209d39SAndroid Build Coastguard Worker     char16_t *myTarget = args->target;
71*0e209d39SAndroid Build Coastguard Worker     const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit;
72*0e209d39SAndroid Build Coastguard Worker     const char16_t *targetLimit = args->targetLimit;
73*0e209d39SAndroid Build Coastguard Worker     unsigned char *toUBytes = cnv->toUBytes;
74*0e209d39SAndroid Build Coastguard Worker     UBool isCESU8 = hasCESU8Data(cnv);
75*0e209d39SAndroid Build Coastguard Worker     uint32_t ch, ch2 = 0;
76*0e209d39SAndroid Build Coastguard Worker     int32_t i, inBytes;
77*0e209d39SAndroid Build Coastguard Worker 
78*0e209d39SAndroid Build Coastguard Worker     /* Restore size of current sequence */
79*0e209d39SAndroid Build Coastguard Worker     if (cnv->toULength > 0 && myTarget < targetLimit)
80*0e209d39SAndroid Build Coastguard Worker     {
81*0e209d39SAndroid Build Coastguard Worker         inBytes = cnv->mode;            /* restore # of bytes to consume */
82*0e209d39SAndroid Build Coastguard Worker         i = cnv->toULength;             /* restore # of bytes consumed */
83*0e209d39SAndroid Build Coastguard Worker         cnv->toULength = 0;
84*0e209d39SAndroid Build Coastguard Worker 
85*0e209d39SAndroid Build Coastguard Worker         ch = cnv->toUnicodeStatus;/*Stores the previously calculated ch from a previous call*/
86*0e209d39SAndroid Build Coastguard Worker         cnv->toUnicodeStatus = 0;
87*0e209d39SAndroid Build Coastguard Worker         goto morebytes;
88*0e209d39SAndroid Build Coastguard Worker     }
89*0e209d39SAndroid Build Coastguard Worker 
90*0e209d39SAndroid Build Coastguard Worker 
91*0e209d39SAndroid Build Coastguard Worker     while (mySource < sourceLimit && myTarget < targetLimit)
92*0e209d39SAndroid Build Coastguard Worker     {
93*0e209d39SAndroid Build Coastguard Worker         ch = *(mySource++);
94*0e209d39SAndroid Build Coastguard Worker         if (U8_IS_SINGLE(ch))        /* Simple case */
95*0e209d39SAndroid Build Coastguard Worker         {
96*0e209d39SAndroid Build Coastguard Worker             *(myTarget++) = (char16_t) ch;
97*0e209d39SAndroid Build Coastguard Worker         }
98*0e209d39SAndroid Build Coastguard Worker         else
99*0e209d39SAndroid Build Coastguard Worker         {
100*0e209d39SAndroid Build Coastguard Worker             /* store the first char */
101*0e209d39SAndroid Build Coastguard Worker             toUBytes[0] = (char)ch;
102*0e209d39SAndroid Build Coastguard Worker             inBytes = U8_COUNT_BYTES_NON_ASCII(ch); /* lookup current sequence length */
103*0e209d39SAndroid Build Coastguard Worker             i = 1;
104*0e209d39SAndroid Build Coastguard Worker 
105*0e209d39SAndroid Build Coastguard Worker morebytes:
106*0e209d39SAndroid Build Coastguard Worker             while (i < inBytes)
107*0e209d39SAndroid Build Coastguard Worker             {
108*0e209d39SAndroid Build Coastguard Worker                 if (mySource < sourceLimit)
109*0e209d39SAndroid Build Coastguard Worker                 {
110*0e209d39SAndroid Build Coastguard Worker                     toUBytes[i] = (char) (ch2 = *mySource);
111*0e209d39SAndroid Build Coastguard Worker                     if (!icu::UTF8::isValidTrail(ch, static_cast<uint8_t>(ch2), i, inBytes) &&
112*0e209d39SAndroid Build Coastguard Worker                             !(isCESU8 && i == 1 && ch == 0xed && U8_IS_TRAIL(ch2)))
113*0e209d39SAndroid Build Coastguard Worker                     {
114*0e209d39SAndroid Build Coastguard Worker                         break; /* i < inBytes */
115*0e209d39SAndroid Build Coastguard Worker                     }
116*0e209d39SAndroid Build Coastguard Worker                     ch = (ch << 6) + ch2;
117*0e209d39SAndroid Build Coastguard Worker                     ++mySource;
118*0e209d39SAndroid Build Coastguard Worker                     i++;
119*0e209d39SAndroid Build Coastguard Worker                 }
120*0e209d39SAndroid Build Coastguard Worker                 else
121*0e209d39SAndroid Build Coastguard Worker                 {
122*0e209d39SAndroid Build Coastguard Worker                     /* stores a partially calculated target*/
123*0e209d39SAndroid Build Coastguard Worker                     cnv->toUnicodeStatus = ch;
124*0e209d39SAndroid Build Coastguard Worker                     cnv->mode = inBytes;
125*0e209d39SAndroid Build Coastguard Worker                     cnv->toULength = (int8_t) i;
126*0e209d39SAndroid Build Coastguard Worker                     goto donefornow;
127*0e209d39SAndroid Build Coastguard Worker                 }
128*0e209d39SAndroid Build Coastguard Worker             }
129*0e209d39SAndroid Build Coastguard Worker 
130*0e209d39SAndroid Build Coastguard Worker             // In CESU-8, only surrogates, not supplementary code points, are encoded directly.
131*0e209d39SAndroid Build Coastguard Worker             if (i == inBytes && (!isCESU8 || i <= 3))
132*0e209d39SAndroid Build Coastguard Worker             {
133*0e209d39SAndroid Build Coastguard Worker                 /* Remove the accumulated high bits */
134*0e209d39SAndroid Build Coastguard Worker                 ch -= offsetsFromUTF8[inBytes];
135*0e209d39SAndroid Build Coastguard Worker 
136*0e209d39SAndroid Build Coastguard Worker                 /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */
137*0e209d39SAndroid Build Coastguard Worker                 if (ch <= MAXIMUM_UCS2)
138*0e209d39SAndroid Build Coastguard Worker                 {
139*0e209d39SAndroid Build Coastguard Worker                     /* fits in 16 bits */
140*0e209d39SAndroid Build Coastguard Worker                     *(myTarget++) = (char16_t) ch;
141*0e209d39SAndroid Build Coastguard Worker                 }
142*0e209d39SAndroid Build Coastguard Worker                 else
143*0e209d39SAndroid Build Coastguard Worker                 {
144*0e209d39SAndroid Build Coastguard Worker                     /* write out the surrogates */
145*0e209d39SAndroid Build Coastguard Worker                     *(myTarget++) = U16_LEAD(ch);
146*0e209d39SAndroid Build Coastguard Worker                     ch = U16_TRAIL(ch);
147*0e209d39SAndroid Build Coastguard Worker                     if (myTarget < targetLimit)
148*0e209d39SAndroid Build Coastguard Worker                     {
149*0e209d39SAndroid Build Coastguard Worker                         *(myTarget++) = (char16_t)ch;
150*0e209d39SAndroid Build Coastguard Worker                     }
151*0e209d39SAndroid Build Coastguard Worker                     else
152*0e209d39SAndroid Build Coastguard Worker                     {
153*0e209d39SAndroid Build Coastguard Worker                         /* Put in overflow buffer (not handled here) */
154*0e209d39SAndroid Build Coastguard Worker                         cnv->UCharErrorBuffer[0] = (char16_t) ch;
155*0e209d39SAndroid Build Coastguard Worker                         cnv->UCharErrorBufferLength = 1;
156*0e209d39SAndroid Build Coastguard Worker                         *err = U_BUFFER_OVERFLOW_ERROR;
157*0e209d39SAndroid Build Coastguard Worker                         break;
158*0e209d39SAndroid Build Coastguard Worker                     }
159*0e209d39SAndroid Build Coastguard Worker                 }
160*0e209d39SAndroid Build Coastguard Worker             }
161*0e209d39SAndroid Build Coastguard Worker             else
162*0e209d39SAndroid Build Coastguard Worker             {
163*0e209d39SAndroid Build Coastguard Worker                 cnv->toULength = (int8_t)i;
164*0e209d39SAndroid Build Coastguard Worker                 *err = U_ILLEGAL_CHAR_FOUND;
165*0e209d39SAndroid Build Coastguard Worker                 break;
166*0e209d39SAndroid Build Coastguard Worker             }
167*0e209d39SAndroid Build Coastguard Worker         }
168*0e209d39SAndroid Build Coastguard Worker     }
169*0e209d39SAndroid Build Coastguard Worker 
170*0e209d39SAndroid Build Coastguard Worker donefornow:
171*0e209d39SAndroid Build Coastguard Worker     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err))
172*0e209d39SAndroid Build Coastguard Worker     {
173*0e209d39SAndroid Build Coastguard Worker         /* End of target buffer */
174*0e209d39SAndroid Build Coastguard Worker         *err = U_BUFFER_OVERFLOW_ERROR;
175*0e209d39SAndroid Build Coastguard Worker     }
176*0e209d39SAndroid Build Coastguard Worker 
177*0e209d39SAndroid Build Coastguard Worker     args->target = myTarget;
178*0e209d39SAndroid Build Coastguard Worker     args->source = (const char *) mySource;
179*0e209d39SAndroid Build Coastguard Worker }
180*0e209d39SAndroid Build Coastguard Worker 
ucnv_toUnicode_UTF8_OFFSETS_LOGIC(UConverterToUnicodeArgs * args,UErrorCode * err)181*0e209d39SAndroid Build Coastguard Worker static void  U_CALLCONV ucnv_toUnicode_UTF8_OFFSETS_LOGIC (UConverterToUnicodeArgs * args,
182*0e209d39SAndroid Build Coastguard Worker                                                 UErrorCode * err)
183*0e209d39SAndroid Build Coastguard Worker {
184*0e209d39SAndroid Build Coastguard Worker     UConverter *cnv = args->converter;
185*0e209d39SAndroid Build Coastguard Worker     const unsigned char *mySource = (unsigned char *) args->source;
186*0e209d39SAndroid Build Coastguard Worker     char16_t *myTarget = args->target;
187*0e209d39SAndroid Build Coastguard Worker     int32_t *myOffsets = args->offsets;
188*0e209d39SAndroid Build Coastguard Worker     int32_t offsetNum = 0;
189*0e209d39SAndroid Build Coastguard Worker     const unsigned char *sourceLimit = (unsigned char *) args->sourceLimit;
190*0e209d39SAndroid Build Coastguard Worker     const char16_t *targetLimit = args->targetLimit;
191*0e209d39SAndroid Build Coastguard Worker     unsigned char *toUBytes = cnv->toUBytes;
192*0e209d39SAndroid Build Coastguard Worker     UBool isCESU8 = hasCESU8Data(cnv);
193*0e209d39SAndroid Build Coastguard Worker     uint32_t ch, ch2 = 0;
194*0e209d39SAndroid Build Coastguard Worker     int32_t i, inBytes;
195*0e209d39SAndroid Build Coastguard Worker 
196*0e209d39SAndroid Build Coastguard Worker     /* Restore size of current sequence */
197*0e209d39SAndroid Build Coastguard Worker     if (cnv->toULength > 0 && myTarget < targetLimit)
198*0e209d39SAndroid Build Coastguard Worker     {
199*0e209d39SAndroid Build Coastguard Worker         inBytes = cnv->mode;            /* restore # of bytes to consume */
200*0e209d39SAndroid Build Coastguard Worker         i = cnv->toULength;             /* restore # of bytes consumed */
201*0e209d39SAndroid Build Coastguard Worker         cnv->toULength = 0;
202*0e209d39SAndroid Build Coastguard Worker 
203*0e209d39SAndroid Build Coastguard Worker         ch = cnv->toUnicodeStatus;/*Stores the previously calculated ch from a previous call*/
204*0e209d39SAndroid Build Coastguard Worker         cnv->toUnicodeStatus = 0;
205*0e209d39SAndroid Build Coastguard Worker         goto morebytes;
206*0e209d39SAndroid Build Coastguard Worker     }
207*0e209d39SAndroid Build Coastguard Worker 
208*0e209d39SAndroid Build Coastguard Worker     while (mySource < sourceLimit && myTarget < targetLimit)
209*0e209d39SAndroid Build Coastguard Worker     {
210*0e209d39SAndroid Build Coastguard Worker         ch = *(mySource++);
211*0e209d39SAndroid Build Coastguard Worker         if (U8_IS_SINGLE(ch))        /* Simple case */
212*0e209d39SAndroid Build Coastguard Worker         {
213*0e209d39SAndroid Build Coastguard Worker             *(myTarget++) = (char16_t) ch;
214*0e209d39SAndroid Build Coastguard Worker             *(myOffsets++) = offsetNum++;
215*0e209d39SAndroid Build Coastguard Worker         }
216*0e209d39SAndroid Build Coastguard Worker         else
217*0e209d39SAndroid Build Coastguard Worker         {
218*0e209d39SAndroid Build Coastguard Worker             toUBytes[0] = (char)ch;
219*0e209d39SAndroid Build Coastguard Worker             inBytes = U8_COUNT_BYTES_NON_ASCII(ch);
220*0e209d39SAndroid Build Coastguard Worker             i = 1;
221*0e209d39SAndroid Build Coastguard Worker 
222*0e209d39SAndroid Build Coastguard Worker morebytes:
223*0e209d39SAndroid Build Coastguard Worker             while (i < inBytes)
224*0e209d39SAndroid Build Coastguard Worker             {
225*0e209d39SAndroid Build Coastguard Worker                 if (mySource < sourceLimit)
226*0e209d39SAndroid Build Coastguard Worker                 {
227*0e209d39SAndroid Build Coastguard Worker                     toUBytes[i] = (char) (ch2 = *mySource);
228*0e209d39SAndroid Build Coastguard Worker                     if (!icu::UTF8::isValidTrail(ch, static_cast<uint8_t>(ch2), i, inBytes) &&
229*0e209d39SAndroid Build Coastguard Worker                             !(isCESU8 && i == 1 && ch == 0xed && U8_IS_TRAIL(ch2)))
230*0e209d39SAndroid Build Coastguard Worker                     {
231*0e209d39SAndroid Build Coastguard Worker                         break; /* i < inBytes */
232*0e209d39SAndroid Build Coastguard Worker                     }
233*0e209d39SAndroid Build Coastguard Worker                     ch = (ch << 6) + ch2;
234*0e209d39SAndroid Build Coastguard Worker                     ++mySource;
235*0e209d39SAndroid Build Coastguard Worker                     i++;
236*0e209d39SAndroid Build Coastguard Worker                 }
237*0e209d39SAndroid Build Coastguard Worker                 else
238*0e209d39SAndroid Build Coastguard Worker                 {
239*0e209d39SAndroid Build Coastguard Worker                     cnv->toUnicodeStatus = ch;
240*0e209d39SAndroid Build Coastguard Worker                     cnv->mode = inBytes;
241*0e209d39SAndroid Build Coastguard Worker                     cnv->toULength = (int8_t)i;
242*0e209d39SAndroid Build Coastguard Worker                     goto donefornow;
243*0e209d39SAndroid Build Coastguard Worker                 }
244*0e209d39SAndroid Build Coastguard Worker             }
245*0e209d39SAndroid Build Coastguard Worker 
246*0e209d39SAndroid Build Coastguard Worker             // In CESU-8, only surrogates, not supplementary code points, are encoded directly.
247*0e209d39SAndroid Build Coastguard Worker             if (i == inBytes && (!isCESU8 || i <= 3))
248*0e209d39SAndroid Build Coastguard Worker             {
249*0e209d39SAndroid Build Coastguard Worker                 /* Remove the accumulated high bits */
250*0e209d39SAndroid Build Coastguard Worker                 ch -= offsetsFromUTF8[inBytes];
251*0e209d39SAndroid Build Coastguard Worker 
252*0e209d39SAndroid Build Coastguard Worker                 /* Normal valid byte when the loop has not prematurely terminated (i < inBytes) */
253*0e209d39SAndroid Build Coastguard Worker                 if (ch <= MAXIMUM_UCS2)
254*0e209d39SAndroid Build Coastguard Worker                 {
255*0e209d39SAndroid Build Coastguard Worker                     /* fits in 16 bits */
256*0e209d39SAndroid Build Coastguard Worker                     *(myTarget++) = (char16_t) ch;
257*0e209d39SAndroid Build Coastguard Worker                     *(myOffsets++) = offsetNum;
258*0e209d39SAndroid Build Coastguard Worker                 }
259*0e209d39SAndroid Build Coastguard Worker                 else
260*0e209d39SAndroid Build Coastguard Worker                 {
261*0e209d39SAndroid Build Coastguard Worker                     /* write out the surrogates */
262*0e209d39SAndroid Build Coastguard Worker                     *(myTarget++) = U16_LEAD(ch);
263*0e209d39SAndroid Build Coastguard Worker                     *(myOffsets++) = offsetNum;
264*0e209d39SAndroid Build Coastguard Worker                     ch = U16_TRAIL(ch);
265*0e209d39SAndroid Build Coastguard Worker                     if (myTarget < targetLimit)
266*0e209d39SAndroid Build Coastguard Worker                     {
267*0e209d39SAndroid Build Coastguard Worker                         *(myTarget++) = (char16_t)ch;
268*0e209d39SAndroid Build Coastguard Worker                         *(myOffsets++) = offsetNum;
269*0e209d39SAndroid Build Coastguard Worker                     }
270*0e209d39SAndroid Build Coastguard Worker                     else
271*0e209d39SAndroid Build Coastguard Worker                     {
272*0e209d39SAndroid Build Coastguard Worker                         cnv->UCharErrorBuffer[0] = (char16_t) ch;
273*0e209d39SAndroid Build Coastguard Worker                         cnv->UCharErrorBufferLength = 1;
274*0e209d39SAndroid Build Coastguard Worker                         *err = U_BUFFER_OVERFLOW_ERROR;
275*0e209d39SAndroid Build Coastguard Worker                     }
276*0e209d39SAndroid Build Coastguard Worker                 }
277*0e209d39SAndroid Build Coastguard Worker                 offsetNum += i;
278*0e209d39SAndroid Build Coastguard Worker             }
279*0e209d39SAndroid Build Coastguard Worker             else
280*0e209d39SAndroid Build Coastguard Worker             {
281*0e209d39SAndroid Build Coastguard Worker                 cnv->toULength = (int8_t)i;
282*0e209d39SAndroid Build Coastguard Worker                 *err = U_ILLEGAL_CHAR_FOUND;
283*0e209d39SAndroid Build Coastguard Worker                 break;
284*0e209d39SAndroid Build Coastguard Worker             }
285*0e209d39SAndroid Build Coastguard Worker         }
286*0e209d39SAndroid Build Coastguard Worker     }
287*0e209d39SAndroid Build Coastguard Worker 
288*0e209d39SAndroid Build Coastguard Worker donefornow:
289*0e209d39SAndroid Build Coastguard Worker     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err))
290*0e209d39SAndroid Build Coastguard Worker     {   /* End of target buffer */
291*0e209d39SAndroid Build Coastguard Worker         *err = U_BUFFER_OVERFLOW_ERROR;
292*0e209d39SAndroid Build Coastguard Worker     }
293*0e209d39SAndroid Build Coastguard Worker 
294*0e209d39SAndroid Build Coastguard Worker     args->target = myTarget;
295*0e209d39SAndroid Build Coastguard Worker     args->source = (const char *) mySource;
296*0e209d39SAndroid Build Coastguard Worker     args->offsets = myOffsets;
297*0e209d39SAndroid Build Coastguard Worker }
298*0e209d39SAndroid Build Coastguard Worker U_CDECL_END
299*0e209d39SAndroid Build Coastguard Worker 
ucnv_fromUnicode_UTF8(UConverterFromUnicodeArgs * args,UErrorCode * err)300*0e209d39SAndroid Build Coastguard Worker U_CFUNC void  U_CALLCONV ucnv_fromUnicode_UTF8 (UConverterFromUnicodeArgs * args,
301*0e209d39SAndroid Build Coastguard Worker                                     UErrorCode * err)
302*0e209d39SAndroid Build Coastguard Worker {
303*0e209d39SAndroid Build Coastguard Worker     UConverter *cnv = args->converter;
304*0e209d39SAndroid Build Coastguard Worker     const char16_t *mySource = args->source;
305*0e209d39SAndroid Build Coastguard Worker     const char16_t *sourceLimit = args->sourceLimit;
306*0e209d39SAndroid Build Coastguard Worker     uint8_t *myTarget = (uint8_t *) args->target;
307*0e209d39SAndroid Build Coastguard Worker     const uint8_t *targetLimit = (uint8_t *) args->targetLimit;
308*0e209d39SAndroid Build Coastguard Worker     uint8_t *tempPtr;
309*0e209d39SAndroid Build Coastguard Worker     UChar32 ch;
310*0e209d39SAndroid Build Coastguard Worker     uint8_t tempBuf[4];
311*0e209d39SAndroid Build Coastguard Worker     int32_t indexToWrite;
312*0e209d39SAndroid Build Coastguard Worker     UBool isNotCESU8 = !hasCESU8Data(cnv);
313*0e209d39SAndroid Build Coastguard Worker 
314*0e209d39SAndroid Build Coastguard Worker     if (cnv->fromUChar32 && myTarget < targetLimit)
315*0e209d39SAndroid Build Coastguard Worker     {
316*0e209d39SAndroid Build Coastguard Worker         ch = cnv->fromUChar32;
317*0e209d39SAndroid Build Coastguard Worker         cnv->fromUChar32 = 0;
318*0e209d39SAndroid Build Coastguard Worker         goto lowsurrogate;
319*0e209d39SAndroid Build Coastguard Worker     }
320*0e209d39SAndroid Build Coastguard Worker 
321*0e209d39SAndroid Build Coastguard Worker     while (mySource < sourceLimit && myTarget < targetLimit)
322*0e209d39SAndroid Build Coastguard Worker     {
323*0e209d39SAndroid Build Coastguard Worker         ch = *(mySource++);
324*0e209d39SAndroid Build Coastguard Worker 
325*0e209d39SAndroid Build Coastguard Worker         if (ch < 0x80)        /* Single byte */
326*0e209d39SAndroid Build Coastguard Worker         {
327*0e209d39SAndroid Build Coastguard Worker             *(myTarget++) = (uint8_t) ch;
328*0e209d39SAndroid Build Coastguard Worker         }
329*0e209d39SAndroid Build Coastguard Worker         else if (ch < 0x800)  /* Double byte */
330*0e209d39SAndroid Build Coastguard Worker         {
331*0e209d39SAndroid Build Coastguard Worker             *(myTarget++) = (uint8_t) ((ch >> 6) | 0xc0);
332*0e209d39SAndroid Build Coastguard Worker             if (myTarget < targetLimit)
333*0e209d39SAndroid Build Coastguard Worker             {
334*0e209d39SAndroid Build Coastguard Worker                 *(myTarget++) = (uint8_t) ((ch & 0x3f) | 0x80);
335*0e209d39SAndroid Build Coastguard Worker             }
336*0e209d39SAndroid Build Coastguard Worker             else
337*0e209d39SAndroid Build Coastguard Worker             {
338*0e209d39SAndroid Build Coastguard Worker                 cnv->charErrorBuffer[0] = (uint8_t) ((ch & 0x3f) | 0x80);
339*0e209d39SAndroid Build Coastguard Worker                 cnv->charErrorBufferLength = 1;
340*0e209d39SAndroid Build Coastguard Worker                 *err = U_BUFFER_OVERFLOW_ERROR;
341*0e209d39SAndroid Build Coastguard Worker             }
342*0e209d39SAndroid Build Coastguard Worker         }
343*0e209d39SAndroid Build Coastguard Worker         else {
344*0e209d39SAndroid Build Coastguard Worker             /* Check for surrogates */
345*0e209d39SAndroid Build Coastguard Worker             if(U16_IS_SURROGATE(ch) && isNotCESU8) {
346*0e209d39SAndroid Build Coastguard Worker lowsurrogate:
347*0e209d39SAndroid Build Coastguard Worker                 if (mySource < sourceLimit) {
348*0e209d39SAndroid Build Coastguard Worker                     /* test both code units */
349*0e209d39SAndroid Build Coastguard Worker                     if(U16_IS_SURROGATE_LEAD(ch) && U16_IS_TRAIL(*mySource)) {
350*0e209d39SAndroid Build Coastguard Worker                         /* convert and consume this supplementary code point */
351*0e209d39SAndroid Build Coastguard Worker                         ch=U16_GET_SUPPLEMENTARY(ch, *mySource);
352*0e209d39SAndroid Build Coastguard Worker                         ++mySource;
353*0e209d39SAndroid Build Coastguard Worker                         /* exit this condition tree */
354*0e209d39SAndroid Build Coastguard Worker                     }
355*0e209d39SAndroid Build Coastguard Worker                     else {
356*0e209d39SAndroid Build Coastguard Worker                         /* this is an unpaired trail or lead code unit */
357*0e209d39SAndroid Build Coastguard Worker                         /* callback(illegal) */
358*0e209d39SAndroid Build Coastguard Worker                         cnv->fromUChar32 = ch;
359*0e209d39SAndroid Build Coastguard Worker                         *err = U_ILLEGAL_CHAR_FOUND;
360*0e209d39SAndroid Build Coastguard Worker                         break;
361*0e209d39SAndroid Build Coastguard Worker                     }
362*0e209d39SAndroid Build Coastguard Worker                 }
363*0e209d39SAndroid Build Coastguard Worker                 else {
364*0e209d39SAndroid Build Coastguard Worker                     /* no more input */
365*0e209d39SAndroid Build Coastguard Worker                     cnv->fromUChar32 = ch;
366*0e209d39SAndroid Build Coastguard Worker                     break;
367*0e209d39SAndroid Build Coastguard Worker                 }
368*0e209d39SAndroid Build Coastguard Worker             }
369*0e209d39SAndroid Build Coastguard Worker 
370*0e209d39SAndroid Build Coastguard Worker             /* Do we write the buffer directly for speed,
371*0e209d39SAndroid Build Coastguard Worker             or do we have to be careful about target buffer space? */
372*0e209d39SAndroid Build Coastguard Worker             tempPtr = (((targetLimit - myTarget) >= 4) ? myTarget : tempBuf);
373*0e209d39SAndroid Build Coastguard Worker 
374*0e209d39SAndroid Build Coastguard Worker             if (ch <= MAXIMUM_UCS2) {
375*0e209d39SAndroid Build Coastguard Worker                 indexToWrite = 2;
376*0e209d39SAndroid Build Coastguard Worker                 tempPtr[0] = (uint8_t) ((ch >> 12) | 0xe0);
377*0e209d39SAndroid Build Coastguard Worker             }
378*0e209d39SAndroid Build Coastguard Worker             else {
379*0e209d39SAndroid Build Coastguard Worker                 indexToWrite = 3;
380*0e209d39SAndroid Build Coastguard Worker                 tempPtr[0] = (uint8_t) ((ch >> 18) | 0xf0);
381*0e209d39SAndroid Build Coastguard Worker                 tempPtr[1] = (uint8_t) (((ch >> 12) & 0x3f) | 0x80);
382*0e209d39SAndroid Build Coastguard Worker             }
383*0e209d39SAndroid Build Coastguard Worker             tempPtr[indexToWrite-1] = (uint8_t) (((ch >> 6) & 0x3f) | 0x80);
384*0e209d39SAndroid Build Coastguard Worker             tempPtr[indexToWrite] = (uint8_t) ((ch & 0x3f) | 0x80);
385*0e209d39SAndroid Build Coastguard Worker 
386*0e209d39SAndroid Build Coastguard Worker             if (tempPtr == myTarget) {
387*0e209d39SAndroid Build Coastguard Worker                 /* There was enough space to write the codepoint directly. */
388*0e209d39SAndroid Build Coastguard Worker                 myTarget += (indexToWrite + 1);
389*0e209d39SAndroid Build Coastguard Worker             }
390*0e209d39SAndroid Build Coastguard Worker             else {
391*0e209d39SAndroid Build Coastguard Worker                 /* We might run out of room soon. Write it slowly. */
392*0e209d39SAndroid Build Coastguard Worker                 for (; tempPtr <= (tempBuf + indexToWrite); tempPtr++) {
393*0e209d39SAndroid Build Coastguard Worker                     if (myTarget < targetLimit) {
394*0e209d39SAndroid Build Coastguard Worker                         *(myTarget++) = *tempPtr;
395*0e209d39SAndroid Build Coastguard Worker                     }
396*0e209d39SAndroid Build Coastguard Worker                     else {
397*0e209d39SAndroid Build Coastguard Worker                         cnv->charErrorBuffer[cnv->charErrorBufferLength++] = *tempPtr;
398*0e209d39SAndroid Build Coastguard Worker                         *err = U_BUFFER_OVERFLOW_ERROR;
399*0e209d39SAndroid Build Coastguard Worker                     }
400*0e209d39SAndroid Build Coastguard Worker                 }
401*0e209d39SAndroid Build Coastguard Worker             }
402*0e209d39SAndroid Build Coastguard Worker         }
403*0e209d39SAndroid Build Coastguard Worker     }
404*0e209d39SAndroid Build Coastguard Worker 
405*0e209d39SAndroid Build Coastguard Worker     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err))
406*0e209d39SAndroid Build Coastguard Worker     {
407*0e209d39SAndroid Build Coastguard Worker         *err = U_BUFFER_OVERFLOW_ERROR;
408*0e209d39SAndroid Build Coastguard Worker     }
409*0e209d39SAndroid Build Coastguard Worker 
410*0e209d39SAndroid Build Coastguard Worker     args->target = (char *) myTarget;
411*0e209d39SAndroid Build Coastguard Worker     args->source = mySource;
412*0e209d39SAndroid Build Coastguard Worker }
413*0e209d39SAndroid Build Coastguard Worker 
ucnv_fromUnicode_UTF8_OFFSETS_LOGIC(UConverterFromUnicodeArgs * args,UErrorCode * err)414*0e209d39SAndroid Build Coastguard Worker U_CFUNC void  U_CALLCONV ucnv_fromUnicode_UTF8_OFFSETS_LOGIC (UConverterFromUnicodeArgs * args,
415*0e209d39SAndroid Build Coastguard Worker                                                   UErrorCode * err)
416*0e209d39SAndroid Build Coastguard Worker {
417*0e209d39SAndroid Build Coastguard Worker     UConverter *cnv = args->converter;
418*0e209d39SAndroid Build Coastguard Worker     const char16_t *mySource = args->source;
419*0e209d39SAndroid Build Coastguard Worker     int32_t *myOffsets = args->offsets;
420*0e209d39SAndroid Build Coastguard Worker     const char16_t *sourceLimit = args->sourceLimit;
421*0e209d39SAndroid Build Coastguard Worker     uint8_t *myTarget = (uint8_t *) args->target;
422*0e209d39SAndroid Build Coastguard Worker     const uint8_t *targetLimit = (uint8_t *) args->targetLimit;
423*0e209d39SAndroid Build Coastguard Worker     uint8_t *tempPtr;
424*0e209d39SAndroid Build Coastguard Worker     UChar32 ch;
425*0e209d39SAndroid Build Coastguard Worker     int32_t offsetNum, nextSourceIndex;
426*0e209d39SAndroid Build Coastguard Worker     int32_t indexToWrite;
427*0e209d39SAndroid Build Coastguard Worker     uint8_t tempBuf[4];
428*0e209d39SAndroid Build Coastguard Worker     UBool isNotCESU8 = !hasCESU8Data(cnv);
429*0e209d39SAndroid Build Coastguard Worker 
430*0e209d39SAndroid Build Coastguard Worker     if (cnv->fromUChar32 && myTarget < targetLimit)
431*0e209d39SAndroid Build Coastguard Worker     {
432*0e209d39SAndroid Build Coastguard Worker         ch = cnv->fromUChar32;
433*0e209d39SAndroid Build Coastguard Worker         cnv->fromUChar32 = 0;
434*0e209d39SAndroid Build Coastguard Worker         offsetNum = -1;
435*0e209d39SAndroid Build Coastguard Worker         nextSourceIndex = 0;
436*0e209d39SAndroid Build Coastguard Worker         goto lowsurrogate;
437*0e209d39SAndroid Build Coastguard Worker     } else {
438*0e209d39SAndroid Build Coastguard Worker         offsetNum = 0;
439*0e209d39SAndroid Build Coastguard Worker     }
440*0e209d39SAndroid Build Coastguard Worker 
441*0e209d39SAndroid Build Coastguard Worker     while (mySource < sourceLimit && myTarget < targetLimit)
442*0e209d39SAndroid Build Coastguard Worker     {
443*0e209d39SAndroid Build Coastguard Worker         ch = *(mySource++);
444*0e209d39SAndroid Build Coastguard Worker 
445*0e209d39SAndroid Build Coastguard Worker         if (ch < 0x80)        /* Single byte */
446*0e209d39SAndroid Build Coastguard Worker         {
447*0e209d39SAndroid Build Coastguard Worker             *(myOffsets++) = offsetNum++;
448*0e209d39SAndroid Build Coastguard Worker             *(myTarget++) = (char) ch;
449*0e209d39SAndroid Build Coastguard Worker         }
450*0e209d39SAndroid Build Coastguard Worker         else if (ch < 0x800)  /* Double byte */
451*0e209d39SAndroid Build Coastguard Worker         {
452*0e209d39SAndroid Build Coastguard Worker             *(myOffsets++) = offsetNum;
453*0e209d39SAndroid Build Coastguard Worker             *(myTarget++) = (uint8_t) ((ch >> 6) | 0xc0);
454*0e209d39SAndroid Build Coastguard Worker             if (myTarget < targetLimit)
455*0e209d39SAndroid Build Coastguard Worker             {
456*0e209d39SAndroid Build Coastguard Worker                 *(myOffsets++) = offsetNum++;
457*0e209d39SAndroid Build Coastguard Worker                 *(myTarget++) = (uint8_t) ((ch & 0x3f) | 0x80);
458*0e209d39SAndroid Build Coastguard Worker             }
459*0e209d39SAndroid Build Coastguard Worker             else
460*0e209d39SAndroid Build Coastguard Worker             {
461*0e209d39SAndroid Build Coastguard Worker                 cnv->charErrorBuffer[0] = (uint8_t) ((ch & 0x3f) | 0x80);
462*0e209d39SAndroid Build Coastguard Worker                 cnv->charErrorBufferLength = 1;
463*0e209d39SAndroid Build Coastguard Worker                 *err = U_BUFFER_OVERFLOW_ERROR;
464*0e209d39SAndroid Build Coastguard Worker             }
465*0e209d39SAndroid Build Coastguard Worker         }
466*0e209d39SAndroid Build Coastguard Worker         else
467*0e209d39SAndroid Build Coastguard Worker         /* Check for surrogates */
468*0e209d39SAndroid Build Coastguard Worker         {
469*0e209d39SAndroid Build Coastguard Worker             nextSourceIndex = offsetNum + 1;
470*0e209d39SAndroid Build Coastguard Worker 
471*0e209d39SAndroid Build Coastguard Worker             if(U16_IS_SURROGATE(ch) && isNotCESU8) {
472*0e209d39SAndroid Build Coastguard Worker lowsurrogate:
473*0e209d39SAndroid Build Coastguard Worker                 if (mySource < sourceLimit) {
474*0e209d39SAndroid Build Coastguard Worker                     /* test both code units */
475*0e209d39SAndroid Build Coastguard Worker                     if(U16_IS_SURROGATE_LEAD(ch) && U16_IS_TRAIL(*mySource)) {
476*0e209d39SAndroid Build Coastguard Worker                         /* convert and consume this supplementary code point */
477*0e209d39SAndroid Build Coastguard Worker                         ch=U16_GET_SUPPLEMENTARY(ch, *mySource);
478*0e209d39SAndroid Build Coastguard Worker                         ++mySource;
479*0e209d39SAndroid Build Coastguard Worker                         ++nextSourceIndex;
480*0e209d39SAndroid Build Coastguard Worker                         /* exit this condition tree */
481*0e209d39SAndroid Build Coastguard Worker                     }
482*0e209d39SAndroid Build Coastguard Worker                     else {
483*0e209d39SAndroid Build Coastguard Worker                         /* this is an unpaired trail or lead code unit */
484*0e209d39SAndroid Build Coastguard Worker                         /* callback(illegal) */
485*0e209d39SAndroid Build Coastguard Worker                         cnv->fromUChar32 = ch;
486*0e209d39SAndroid Build Coastguard Worker                         *err = U_ILLEGAL_CHAR_FOUND;
487*0e209d39SAndroid Build Coastguard Worker                         break;
488*0e209d39SAndroid Build Coastguard Worker                     }
489*0e209d39SAndroid Build Coastguard Worker                 }
490*0e209d39SAndroid Build Coastguard Worker                 else {
491*0e209d39SAndroid Build Coastguard Worker                     /* no more input */
492*0e209d39SAndroid Build Coastguard Worker                     cnv->fromUChar32 = ch;
493*0e209d39SAndroid Build Coastguard Worker                     break;
494*0e209d39SAndroid Build Coastguard Worker                 }
495*0e209d39SAndroid Build Coastguard Worker             }
496*0e209d39SAndroid Build Coastguard Worker 
497*0e209d39SAndroid Build Coastguard Worker             /* Do we write the buffer directly for speed,
498*0e209d39SAndroid Build Coastguard Worker             or do we have to be careful about target buffer space? */
499*0e209d39SAndroid Build Coastguard Worker             tempPtr = (((targetLimit - myTarget) >= 4) ? myTarget : tempBuf);
500*0e209d39SAndroid Build Coastguard Worker 
501*0e209d39SAndroid Build Coastguard Worker             if (ch <= MAXIMUM_UCS2) {
502*0e209d39SAndroid Build Coastguard Worker                 indexToWrite = 2;
503*0e209d39SAndroid Build Coastguard Worker                 tempPtr[0] = (uint8_t) ((ch >> 12) | 0xe0);
504*0e209d39SAndroid Build Coastguard Worker             }
505*0e209d39SAndroid Build Coastguard Worker             else {
506*0e209d39SAndroid Build Coastguard Worker                 indexToWrite = 3;
507*0e209d39SAndroid Build Coastguard Worker                 tempPtr[0] = (uint8_t) ((ch >> 18) | 0xf0);
508*0e209d39SAndroid Build Coastguard Worker                 tempPtr[1] = (uint8_t) (((ch >> 12) & 0x3f) | 0x80);
509*0e209d39SAndroid Build Coastguard Worker             }
510*0e209d39SAndroid Build Coastguard Worker             tempPtr[indexToWrite-1] = (uint8_t) (((ch >> 6) & 0x3f) | 0x80);
511*0e209d39SAndroid Build Coastguard Worker             tempPtr[indexToWrite] = (uint8_t) ((ch & 0x3f) | 0x80);
512*0e209d39SAndroid Build Coastguard Worker 
513*0e209d39SAndroid Build Coastguard Worker             if (tempPtr == myTarget) {
514*0e209d39SAndroid Build Coastguard Worker                 /* There was enough space to write the codepoint directly. */
515*0e209d39SAndroid Build Coastguard Worker                 myTarget += (indexToWrite + 1);
516*0e209d39SAndroid Build Coastguard Worker                 myOffsets[0] = offsetNum;
517*0e209d39SAndroid Build Coastguard Worker                 myOffsets[1] = offsetNum;
518*0e209d39SAndroid Build Coastguard Worker                 myOffsets[2] = offsetNum;
519*0e209d39SAndroid Build Coastguard Worker                 if (indexToWrite >= 3) {
520*0e209d39SAndroid Build Coastguard Worker                     myOffsets[3] = offsetNum;
521*0e209d39SAndroid Build Coastguard Worker                 }
522*0e209d39SAndroid Build Coastguard Worker                 myOffsets += (indexToWrite + 1);
523*0e209d39SAndroid Build Coastguard Worker             }
524*0e209d39SAndroid Build Coastguard Worker             else {
525*0e209d39SAndroid Build Coastguard Worker                 /* We might run out of room soon. Write it slowly. */
526*0e209d39SAndroid Build Coastguard Worker                 for (; tempPtr <= (tempBuf + indexToWrite); tempPtr++) {
527*0e209d39SAndroid Build Coastguard Worker                     if (myTarget < targetLimit)
528*0e209d39SAndroid Build Coastguard Worker                     {
529*0e209d39SAndroid Build Coastguard Worker                         *(myOffsets++) = offsetNum;
530*0e209d39SAndroid Build Coastguard Worker                         *(myTarget++) = *tempPtr;
531*0e209d39SAndroid Build Coastguard Worker                     }
532*0e209d39SAndroid Build Coastguard Worker                     else
533*0e209d39SAndroid Build Coastguard Worker                     {
534*0e209d39SAndroid Build Coastguard Worker                         cnv->charErrorBuffer[cnv->charErrorBufferLength++] = *tempPtr;
535*0e209d39SAndroid Build Coastguard Worker                         *err = U_BUFFER_OVERFLOW_ERROR;
536*0e209d39SAndroid Build Coastguard Worker                     }
537*0e209d39SAndroid Build Coastguard Worker                 }
538*0e209d39SAndroid Build Coastguard Worker             }
539*0e209d39SAndroid Build Coastguard Worker             offsetNum = nextSourceIndex;
540*0e209d39SAndroid Build Coastguard Worker         }
541*0e209d39SAndroid Build Coastguard Worker     }
542*0e209d39SAndroid Build Coastguard Worker 
543*0e209d39SAndroid Build Coastguard Worker     if (mySource < sourceLimit && myTarget >= targetLimit && U_SUCCESS(*err))
544*0e209d39SAndroid Build Coastguard Worker     {
545*0e209d39SAndroid Build Coastguard Worker         *err = U_BUFFER_OVERFLOW_ERROR;
546*0e209d39SAndroid Build Coastguard Worker     }
547*0e209d39SAndroid Build Coastguard Worker 
548*0e209d39SAndroid Build Coastguard Worker     args->target = (char *) myTarget;
549*0e209d39SAndroid Build Coastguard Worker     args->source = mySource;
550*0e209d39SAndroid Build Coastguard Worker     args->offsets = myOffsets;
551*0e209d39SAndroid Build Coastguard Worker }
552*0e209d39SAndroid Build Coastguard Worker 
553*0e209d39SAndroid Build Coastguard Worker U_CDECL_BEGIN
ucnv_getNextUChar_UTF8(UConverterToUnicodeArgs * args,UErrorCode * err)554*0e209d39SAndroid Build Coastguard Worker static UChar32 U_CALLCONV ucnv_getNextUChar_UTF8(UConverterToUnicodeArgs *args,
555*0e209d39SAndroid Build Coastguard Worker                                                UErrorCode *err) {
556*0e209d39SAndroid Build Coastguard Worker     UConverter *cnv;
557*0e209d39SAndroid Build Coastguard Worker     const uint8_t *sourceInitial;
558*0e209d39SAndroid Build Coastguard Worker     const uint8_t *source;
559*0e209d39SAndroid Build Coastguard Worker     uint8_t myByte;
560*0e209d39SAndroid Build Coastguard Worker     UChar32 ch;
561*0e209d39SAndroid Build Coastguard Worker     int8_t i;
562*0e209d39SAndroid Build Coastguard Worker 
563*0e209d39SAndroid Build Coastguard Worker     /* UTF-8 only here, the framework handles CESU-8 to combine surrogate pairs */
564*0e209d39SAndroid Build Coastguard Worker 
565*0e209d39SAndroid Build Coastguard Worker     cnv = args->converter;
566*0e209d39SAndroid Build Coastguard Worker     sourceInitial = source = (const uint8_t *)args->source;
567*0e209d39SAndroid Build Coastguard Worker     if (source >= (const uint8_t *)args->sourceLimit)
568*0e209d39SAndroid Build Coastguard Worker     {
569*0e209d39SAndroid Build Coastguard Worker         /* no input */
570*0e209d39SAndroid Build Coastguard Worker         *err = U_INDEX_OUTOFBOUNDS_ERROR;
571*0e209d39SAndroid Build Coastguard Worker         return 0xffff;
572*0e209d39SAndroid Build Coastguard Worker     }
573*0e209d39SAndroid Build Coastguard Worker 
574*0e209d39SAndroid Build Coastguard Worker     myByte = (uint8_t)*(source++);
575*0e209d39SAndroid Build Coastguard Worker     if (U8_IS_SINGLE(myByte))
576*0e209d39SAndroid Build Coastguard Worker     {
577*0e209d39SAndroid Build Coastguard Worker         args->source = (const char *)source;
578*0e209d39SAndroid Build Coastguard Worker         return (UChar32)myByte;
579*0e209d39SAndroid Build Coastguard Worker     }
580*0e209d39SAndroid Build Coastguard Worker 
581*0e209d39SAndroid Build Coastguard Worker     uint16_t countTrailBytes = U8_COUNT_TRAIL_BYTES(myByte);
582*0e209d39SAndroid Build Coastguard Worker     if (countTrailBytes == 0) {
583*0e209d39SAndroid Build Coastguard Worker         cnv->toUBytes[0] = myByte;
584*0e209d39SAndroid Build Coastguard Worker         cnv->toULength = 1;
585*0e209d39SAndroid Build Coastguard Worker         *err = U_ILLEGAL_CHAR_FOUND;
586*0e209d39SAndroid Build Coastguard Worker         args->source = (const char *)source;
587*0e209d39SAndroid Build Coastguard Worker         return 0xffff;
588*0e209d39SAndroid Build Coastguard Worker     }
589*0e209d39SAndroid Build Coastguard Worker 
590*0e209d39SAndroid Build Coastguard Worker     /*The byte sequence is longer than the buffer area passed*/
591*0e209d39SAndroid Build Coastguard Worker     if (((const char *)source + countTrailBytes) > args->sourceLimit)
592*0e209d39SAndroid Build Coastguard Worker     {
593*0e209d39SAndroid Build Coastguard Worker         /* check if all of the remaining bytes are trail bytes */
594*0e209d39SAndroid Build Coastguard Worker         uint16_t extraBytesToWrite = countTrailBytes + 1;
595*0e209d39SAndroid Build Coastguard Worker         cnv->toUBytes[0] = myByte;
596*0e209d39SAndroid Build Coastguard Worker         i = 1;
597*0e209d39SAndroid Build Coastguard Worker         *err = U_TRUNCATED_CHAR_FOUND;
598*0e209d39SAndroid Build Coastguard Worker         while(source < (const uint8_t *)args->sourceLimit) {
599*0e209d39SAndroid Build Coastguard Worker             uint8_t b = *source;
600*0e209d39SAndroid Build Coastguard Worker             if(icu::UTF8::isValidTrail(myByte, b, i, extraBytesToWrite)) {
601*0e209d39SAndroid Build Coastguard Worker                 cnv->toUBytes[i++] = b;
602*0e209d39SAndroid Build Coastguard Worker                 ++source;
603*0e209d39SAndroid Build Coastguard Worker             } else {
604*0e209d39SAndroid Build Coastguard Worker                 /* error even before we run out of input */
605*0e209d39SAndroid Build Coastguard Worker                 *err = U_ILLEGAL_CHAR_FOUND;
606*0e209d39SAndroid Build Coastguard Worker                 break;
607*0e209d39SAndroid Build Coastguard Worker             }
608*0e209d39SAndroid Build Coastguard Worker         }
609*0e209d39SAndroid Build Coastguard Worker         cnv->toULength = i;
610*0e209d39SAndroid Build Coastguard Worker         args->source = (const char *)source;
611*0e209d39SAndroid Build Coastguard Worker         return 0xffff;
612*0e209d39SAndroid Build Coastguard Worker     }
613*0e209d39SAndroid Build Coastguard Worker 
614*0e209d39SAndroid Build Coastguard Worker     ch = myByte << 6;
615*0e209d39SAndroid Build Coastguard Worker     if(countTrailBytes == 2) {
616*0e209d39SAndroid Build Coastguard Worker         uint8_t t1 = *source, t2;
617*0e209d39SAndroid Build Coastguard Worker         if(U8_IS_VALID_LEAD3_AND_T1(myByte, t1) && U8_IS_TRAIL(t2 = *++source)) {
618*0e209d39SAndroid Build Coastguard Worker             args->source = (const char *)(source + 1);
619*0e209d39SAndroid Build Coastguard Worker             return (((ch + t1) << 6) + t2) - offsetsFromUTF8[3];
620*0e209d39SAndroid Build Coastguard Worker         }
621*0e209d39SAndroid Build Coastguard Worker     } else if(countTrailBytes == 1) {
622*0e209d39SAndroid Build Coastguard Worker         uint8_t t1 = *source;
623*0e209d39SAndroid Build Coastguard Worker         if(U8_IS_TRAIL(t1)) {
624*0e209d39SAndroid Build Coastguard Worker             args->source = (const char *)(source + 1);
625*0e209d39SAndroid Build Coastguard Worker             return (ch + t1) - offsetsFromUTF8[2];
626*0e209d39SAndroid Build Coastguard Worker         }
627*0e209d39SAndroid Build Coastguard Worker     } else {  // countTrailBytes == 3
628*0e209d39SAndroid Build Coastguard Worker         uint8_t t1 = *source, t2, t3;
629*0e209d39SAndroid Build Coastguard Worker         if(U8_IS_VALID_LEAD4_AND_T1(myByte, t1) && U8_IS_TRAIL(t2 = *++source) &&
630*0e209d39SAndroid Build Coastguard Worker                 U8_IS_TRAIL(t3 = *++source)) {
631*0e209d39SAndroid Build Coastguard Worker             args->source = (const char *)(source + 1);
632*0e209d39SAndroid Build Coastguard Worker             return (((((ch + t1) << 6) + t2) << 6) + t3) - offsetsFromUTF8[4];
633*0e209d39SAndroid Build Coastguard Worker         }
634*0e209d39SAndroid Build Coastguard Worker     }
635*0e209d39SAndroid Build Coastguard Worker     args->source = (const char *)source;
636*0e209d39SAndroid Build Coastguard Worker 
637*0e209d39SAndroid Build Coastguard Worker     for(i = 0; sourceInitial < source; ++i) {
638*0e209d39SAndroid Build Coastguard Worker         cnv->toUBytes[i] = *sourceInitial++;
639*0e209d39SAndroid Build Coastguard Worker     }
640*0e209d39SAndroid Build Coastguard Worker     cnv->toULength = i;
641*0e209d39SAndroid Build Coastguard Worker     *err = U_ILLEGAL_CHAR_FOUND;
642*0e209d39SAndroid Build Coastguard Worker     return 0xffff;
643*0e209d39SAndroid Build Coastguard Worker }
644*0e209d39SAndroid Build Coastguard Worker U_CDECL_END
645*0e209d39SAndroid Build Coastguard Worker 
646*0e209d39SAndroid Build Coastguard Worker /* UTF-8-from-UTF-8 conversion functions ------------------------------------ */
647*0e209d39SAndroid Build Coastguard Worker 
648*0e209d39SAndroid Build Coastguard Worker U_CDECL_BEGIN
649*0e209d39SAndroid Build Coastguard Worker /* "Convert" UTF-8 to UTF-8: Validate and copy. Modified from ucnv_DBCSFromUTF8(). */
650*0e209d39SAndroid Build Coastguard Worker static void U_CALLCONV
ucnv_UTF8FromUTF8(UConverterFromUnicodeArgs * pFromUArgs,UConverterToUnicodeArgs * pToUArgs,UErrorCode * pErrorCode)651*0e209d39SAndroid Build Coastguard Worker ucnv_UTF8FromUTF8(UConverterFromUnicodeArgs *pFromUArgs,
652*0e209d39SAndroid Build Coastguard Worker                   UConverterToUnicodeArgs *pToUArgs,
653*0e209d39SAndroid Build Coastguard Worker                   UErrorCode *pErrorCode) {
654*0e209d39SAndroid Build Coastguard Worker     UConverter *utf8;
655*0e209d39SAndroid Build Coastguard Worker     const uint8_t *source, *sourceLimit;
656*0e209d39SAndroid Build Coastguard Worker     uint8_t *target;
657*0e209d39SAndroid Build Coastguard Worker     int32_t targetCapacity;
658*0e209d39SAndroid Build Coastguard Worker     int32_t count;
659*0e209d39SAndroid Build Coastguard Worker 
660*0e209d39SAndroid Build Coastguard Worker     int8_t oldToULength, toULength, toULimit;
661*0e209d39SAndroid Build Coastguard Worker 
662*0e209d39SAndroid Build Coastguard Worker     UChar32 c;
663*0e209d39SAndroid Build Coastguard Worker     uint8_t b, t1, t2;
664*0e209d39SAndroid Build Coastguard Worker 
665*0e209d39SAndroid Build Coastguard Worker     /* set up the local pointers */
666*0e209d39SAndroid Build Coastguard Worker     utf8=pToUArgs->converter;
667*0e209d39SAndroid Build Coastguard Worker     source=(uint8_t *)pToUArgs->source;
668*0e209d39SAndroid Build Coastguard Worker     sourceLimit=(uint8_t *)pToUArgs->sourceLimit;
669*0e209d39SAndroid Build Coastguard Worker     target=(uint8_t *)pFromUArgs->target;
670*0e209d39SAndroid Build Coastguard Worker     targetCapacity=(int32_t)(pFromUArgs->targetLimit-pFromUArgs->target);
671*0e209d39SAndroid Build Coastguard Worker 
672*0e209d39SAndroid Build Coastguard Worker     /* get the converter state from the UTF-8 UConverter */
673*0e209d39SAndroid Build Coastguard Worker     if(utf8->toULength > 0) {
674*0e209d39SAndroid Build Coastguard Worker         toULength=oldToULength=utf8->toULength;
675*0e209d39SAndroid Build Coastguard Worker         toULimit=(int8_t)utf8->mode;
676*0e209d39SAndroid Build Coastguard Worker         c=(UChar32)utf8->toUnicodeStatus;
677*0e209d39SAndroid Build Coastguard Worker     } else {
678*0e209d39SAndroid Build Coastguard Worker         toULength=oldToULength=toULimit=0;
679*0e209d39SAndroid Build Coastguard Worker         c = 0;
680*0e209d39SAndroid Build Coastguard Worker     }
681*0e209d39SAndroid Build Coastguard Worker 
682*0e209d39SAndroid Build Coastguard Worker     count=(int32_t)(sourceLimit-source)+oldToULength;
683*0e209d39SAndroid Build Coastguard Worker     if(count<toULimit) {
684*0e209d39SAndroid Build Coastguard Worker         /*
685*0e209d39SAndroid Build Coastguard Worker          * Not enough input to complete the partial character.
686*0e209d39SAndroid Build Coastguard Worker          * Jump to moreBytes below - it will not output to target.
687*0e209d39SAndroid Build Coastguard Worker          */
688*0e209d39SAndroid Build Coastguard Worker     } else if(targetCapacity<toULimit) {
689*0e209d39SAndroid Build Coastguard Worker         /*
690*0e209d39SAndroid Build Coastguard Worker          * Not enough target capacity to output the partial character.
691*0e209d39SAndroid Build Coastguard Worker          * Let the standard converter handle this.
692*0e209d39SAndroid Build Coastguard Worker          */
693*0e209d39SAndroid Build Coastguard Worker         *pErrorCode=U_USING_DEFAULT_WARNING;
694*0e209d39SAndroid Build Coastguard Worker         return;
695*0e209d39SAndroid Build Coastguard Worker     } else {
696*0e209d39SAndroid Build Coastguard Worker         // Use a single counter for source and target, counting the minimum of
697*0e209d39SAndroid Build Coastguard Worker         // the source length and the target capacity.
698*0e209d39SAndroid Build Coastguard Worker         // Let the standard converter handle edge cases.
699*0e209d39SAndroid Build Coastguard Worker         if(count>targetCapacity) {
700*0e209d39SAndroid Build Coastguard Worker             count=targetCapacity;
701*0e209d39SAndroid Build Coastguard Worker         }
702*0e209d39SAndroid Build Coastguard Worker 
703*0e209d39SAndroid Build Coastguard Worker         // The conversion loop checks count>0 only once per character.
704*0e209d39SAndroid Build Coastguard Worker         // If the buffer ends with a truncated sequence,
705*0e209d39SAndroid Build Coastguard Worker         // then we reduce the count to stop before that,
706*0e209d39SAndroid Build Coastguard Worker         // and collect the remaining bytes after the conversion loop.
707*0e209d39SAndroid Build Coastguard Worker 
708*0e209d39SAndroid Build Coastguard Worker         // Do not go back into the bytes that will be read for finishing a partial
709*0e209d39SAndroid Build Coastguard Worker         // sequence from the previous buffer.
710*0e209d39SAndroid Build Coastguard Worker         int32_t length=count-toULength;
711*0e209d39SAndroid Build Coastguard Worker         U8_TRUNCATE_IF_INCOMPLETE(source, 0, length);
712*0e209d39SAndroid Build Coastguard Worker         count=toULength+length;
713*0e209d39SAndroid Build Coastguard Worker     }
714*0e209d39SAndroid Build Coastguard Worker 
715*0e209d39SAndroid Build Coastguard Worker     if(c!=0) {
716*0e209d39SAndroid Build Coastguard Worker         utf8->toUnicodeStatus=0;
717*0e209d39SAndroid Build Coastguard Worker         utf8->toULength=0;
718*0e209d39SAndroid Build Coastguard Worker         goto moreBytes;
719*0e209d39SAndroid Build Coastguard Worker         /* See note in ucnv_SBCSFromUTF8() about this goto. */
720*0e209d39SAndroid Build Coastguard Worker     }
721*0e209d39SAndroid Build Coastguard Worker 
722*0e209d39SAndroid Build Coastguard Worker     /* conversion loop */
723*0e209d39SAndroid Build Coastguard Worker     while(count>0) {
724*0e209d39SAndroid Build Coastguard Worker         b=*source++;
725*0e209d39SAndroid Build Coastguard Worker         if(U8_IS_SINGLE(b)) {
726*0e209d39SAndroid Build Coastguard Worker             /* convert ASCII */
727*0e209d39SAndroid Build Coastguard Worker             *target++=b;
728*0e209d39SAndroid Build Coastguard Worker             --count;
729*0e209d39SAndroid Build Coastguard Worker             continue;
730*0e209d39SAndroid Build Coastguard Worker         } else {
731*0e209d39SAndroid Build Coastguard Worker             if(b>=0xe0) {
732*0e209d39SAndroid Build Coastguard Worker                 if( /* handle U+0800..U+FFFF inline */
733*0e209d39SAndroid Build Coastguard Worker                     b<0xf0 &&
734*0e209d39SAndroid Build Coastguard Worker                     U8_IS_VALID_LEAD3_AND_T1(b, t1=source[0]) &&
735*0e209d39SAndroid Build Coastguard Worker                     U8_IS_TRAIL(t2=source[1])
736*0e209d39SAndroid Build Coastguard Worker                 ) {
737*0e209d39SAndroid Build Coastguard Worker                     source+=2;
738*0e209d39SAndroid Build Coastguard Worker                     *target++=b;
739*0e209d39SAndroid Build Coastguard Worker                     *target++=t1;
740*0e209d39SAndroid Build Coastguard Worker                     *target++=t2;
741*0e209d39SAndroid Build Coastguard Worker                     count-=3;
742*0e209d39SAndroid Build Coastguard Worker                     continue;
743*0e209d39SAndroid Build Coastguard Worker                 }
744*0e209d39SAndroid Build Coastguard Worker             } else {
745*0e209d39SAndroid Build Coastguard Worker                 if( /* handle U+0080..U+07FF inline */
746*0e209d39SAndroid Build Coastguard Worker                     b>=0xc2 &&
747*0e209d39SAndroid Build Coastguard Worker                     U8_IS_TRAIL(t1=*source)
748*0e209d39SAndroid Build Coastguard Worker                 ) {
749*0e209d39SAndroid Build Coastguard Worker                     ++source;
750*0e209d39SAndroid Build Coastguard Worker                     *target++=b;
751*0e209d39SAndroid Build Coastguard Worker                     *target++=t1;
752*0e209d39SAndroid Build Coastguard Worker                     count-=2;
753*0e209d39SAndroid Build Coastguard Worker                     continue;
754*0e209d39SAndroid Build Coastguard Worker                 }
755*0e209d39SAndroid Build Coastguard Worker             }
756*0e209d39SAndroid Build Coastguard Worker 
757*0e209d39SAndroid Build Coastguard Worker             /* handle "complicated" and error cases, and continuing partial characters */
758*0e209d39SAndroid Build Coastguard Worker             oldToULength=0;
759*0e209d39SAndroid Build Coastguard Worker             toULength=1;
760*0e209d39SAndroid Build Coastguard Worker             toULimit=U8_COUNT_BYTES_NON_ASCII(b);
761*0e209d39SAndroid Build Coastguard Worker             c=b;
762*0e209d39SAndroid Build Coastguard Worker moreBytes:
763*0e209d39SAndroid Build Coastguard Worker             while(toULength<toULimit) {
764*0e209d39SAndroid Build Coastguard Worker                 if(source<sourceLimit) {
765*0e209d39SAndroid Build Coastguard Worker                     b=*source;
766*0e209d39SAndroid Build Coastguard Worker                     if(icu::UTF8::isValidTrail(c, b, toULength, toULimit)) {
767*0e209d39SAndroid Build Coastguard Worker                         ++source;
768*0e209d39SAndroid Build Coastguard Worker                         ++toULength;
769*0e209d39SAndroid Build Coastguard Worker                         c=(c<<6)+b;
770*0e209d39SAndroid Build Coastguard Worker                     } else {
771*0e209d39SAndroid Build Coastguard Worker                         break; /* sequence too short, stop with toULength<toULimit */
772*0e209d39SAndroid Build Coastguard Worker                     }
773*0e209d39SAndroid Build Coastguard Worker                 } else {
774*0e209d39SAndroid Build Coastguard Worker                     /* store the partial UTF-8 character, compatible with the regular UTF-8 converter */
775*0e209d39SAndroid Build Coastguard Worker                     source-=(toULength-oldToULength);
776*0e209d39SAndroid Build Coastguard Worker                     while(oldToULength<toULength) {
777*0e209d39SAndroid Build Coastguard Worker                         utf8->toUBytes[oldToULength++]=*source++;
778*0e209d39SAndroid Build Coastguard Worker                     }
779*0e209d39SAndroid Build Coastguard Worker                     utf8->toUnicodeStatus=c;
780*0e209d39SAndroid Build Coastguard Worker                     utf8->toULength=toULength;
781*0e209d39SAndroid Build Coastguard Worker                     utf8->mode=toULimit;
782*0e209d39SAndroid Build Coastguard Worker                     pToUArgs->source=(char *)source;
783*0e209d39SAndroid Build Coastguard Worker                     pFromUArgs->target=(char *)target;
784*0e209d39SAndroid Build Coastguard Worker                     return;
785*0e209d39SAndroid Build Coastguard Worker                 }
786*0e209d39SAndroid Build Coastguard Worker             }
787*0e209d39SAndroid Build Coastguard Worker 
788*0e209d39SAndroid Build Coastguard Worker             if(toULength!=toULimit) {
789*0e209d39SAndroid Build Coastguard Worker                 /* error handling: illegal UTF-8 byte sequence */
790*0e209d39SAndroid Build Coastguard Worker                 source-=(toULength-oldToULength);
791*0e209d39SAndroid Build Coastguard Worker                 while(oldToULength<toULength) {
792*0e209d39SAndroid Build Coastguard Worker                     utf8->toUBytes[oldToULength++]=*source++;
793*0e209d39SAndroid Build Coastguard Worker                 }
794*0e209d39SAndroid Build Coastguard Worker                 utf8->toULength=toULength;
795*0e209d39SAndroid Build Coastguard Worker                 pToUArgs->source=(char *)source;
796*0e209d39SAndroid Build Coastguard Worker                 pFromUArgs->target=(char *)target;
797*0e209d39SAndroid Build Coastguard Worker                 *pErrorCode=U_ILLEGAL_CHAR_FOUND;
798*0e209d39SAndroid Build Coastguard Worker                 return;
799*0e209d39SAndroid Build Coastguard Worker             }
800*0e209d39SAndroid Build Coastguard Worker 
801*0e209d39SAndroid Build Coastguard Worker             /* copy the legal byte sequence to the target */
802*0e209d39SAndroid Build Coastguard Worker             {
803*0e209d39SAndroid Build Coastguard Worker                 int8_t i;
804*0e209d39SAndroid Build Coastguard Worker 
805*0e209d39SAndroid Build Coastguard Worker                 for(i=0; i<oldToULength; ++i) {
806*0e209d39SAndroid Build Coastguard Worker                     *target++=utf8->toUBytes[i];
807*0e209d39SAndroid Build Coastguard Worker                 }
808*0e209d39SAndroid Build Coastguard Worker                 source-=(toULength-oldToULength);
809*0e209d39SAndroid Build Coastguard Worker                 for(; i<toULength; ++i) {
810*0e209d39SAndroid Build Coastguard Worker                     *target++=*source++;
811*0e209d39SAndroid Build Coastguard Worker                 }
812*0e209d39SAndroid Build Coastguard Worker                 count-=toULength;
813*0e209d39SAndroid Build Coastguard Worker             }
814*0e209d39SAndroid Build Coastguard Worker         }
815*0e209d39SAndroid Build Coastguard Worker     }
816*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(count>=0);
817*0e209d39SAndroid Build Coastguard Worker 
818*0e209d39SAndroid Build Coastguard Worker     if(U_SUCCESS(*pErrorCode) && source<sourceLimit) {
819*0e209d39SAndroid Build Coastguard Worker         if(target==(const uint8_t *)pFromUArgs->targetLimit) {
820*0e209d39SAndroid Build Coastguard Worker             *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
821*0e209d39SAndroid Build Coastguard Worker         } else {
822*0e209d39SAndroid Build Coastguard Worker             b=*source;
823*0e209d39SAndroid Build Coastguard Worker             toULimit=U8_COUNT_BYTES(b);
824*0e209d39SAndroid Build Coastguard Worker             if(toULimit>(sourceLimit-source)) {
825*0e209d39SAndroid Build Coastguard Worker                 /* collect a truncated byte sequence */
826*0e209d39SAndroid Build Coastguard Worker                 toULength=0;
827*0e209d39SAndroid Build Coastguard Worker                 c=b;
828*0e209d39SAndroid Build Coastguard Worker                 for(;;) {
829*0e209d39SAndroid Build Coastguard Worker                     utf8->toUBytes[toULength++]=b;
830*0e209d39SAndroid Build Coastguard Worker                     if(++source==sourceLimit) {
831*0e209d39SAndroid Build Coastguard Worker                         /* partial byte sequence at end of source */
832*0e209d39SAndroid Build Coastguard Worker                         utf8->toUnicodeStatus=c;
833*0e209d39SAndroid Build Coastguard Worker                         utf8->toULength=toULength;
834*0e209d39SAndroid Build Coastguard Worker                         utf8->mode=toULimit;
835*0e209d39SAndroid Build Coastguard Worker                         break;
836*0e209d39SAndroid Build Coastguard Worker                     } else if(!icu::UTF8::isValidTrail(c, b=*source, toULength, toULimit)) {
837*0e209d39SAndroid Build Coastguard Worker                         utf8->toULength=toULength;
838*0e209d39SAndroid Build Coastguard Worker                         *pErrorCode=U_ILLEGAL_CHAR_FOUND;
839*0e209d39SAndroid Build Coastguard Worker                         break;
840*0e209d39SAndroid Build Coastguard Worker                     }
841*0e209d39SAndroid Build Coastguard Worker                     c=(c<<6)+b;
842*0e209d39SAndroid Build Coastguard Worker                 }
843*0e209d39SAndroid Build Coastguard Worker             } else {
844*0e209d39SAndroid Build Coastguard Worker                 /* partial-sequence target overflow: fall back to the pivoting implementation */
845*0e209d39SAndroid Build Coastguard Worker                 *pErrorCode=U_USING_DEFAULT_WARNING;
846*0e209d39SAndroid Build Coastguard Worker             }
847*0e209d39SAndroid Build Coastguard Worker         }
848*0e209d39SAndroid Build Coastguard Worker     }
849*0e209d39SAndroid Build Coastguard Worker 
850*0e209d39SAndroid Build Coastguard Worker     /* write back the updated pointers */
851*0e209d39SAndroid Build Coastguard Worker     pToUArgs->source=(char *)source;
852*0e209d39SAndroid Build Coastguard Worker     pFromUArgs->target=(char *)target;
853*0e209d39SAndroid Build Coastguard Worker }
854*0e209d39SAndroid Build Coastguard Worker 
855*0e209d39SAndroid Build Coastguard Worker U_CDECL_END
856*0e209d39SAndroid Build Coastguard Worker 
857*0e209d39SAndroid Build Coastguard Worker /* UTF-8 converter data ----------------------------------------------------- */
858*0e209d39SAndroid Build Coastguard Worker 
859*0e209d39SAndroid Build Coastguard Worker static const UConverterImpl _UTF8Impl={
860*0e209d39SAndroid Build Coastguard Worker     UCNV_UTF8,
861*0e209d39SAndroid Build Coastguard Worker 
862*0e209d39SAndroid Build Coastguard Worker     nullptr,
863*0e209d39SAndroid Build Coastguard Worker     nullptr,
864*0e209d39SAndroid Build Coastguard Worker 
865*0e209d39SAndroid Build Coastguard Worker     nullptr,
866*0e209d39SAndroid Build Coastguard Worker     nullptr,
867*0e209d39SAndroid Build Coastguard Worker     nullptr,
868*0e209d39SAndroid Build Coastguard Worker 
869*0e209d39SAndroid Build Coastguard Worker     ucnv_toUnicode_UTF8,
870*0e209d39SAndroid Build Coastguard Worker     ucnv_toUnicode_UTF8_OFFSETS_LOGIC,
871*0e209d39SAndroid Build Coastguard Worker     ucnv_fromUnicode_UTF8,
872*0e209d39SAndroid Build Coastguard Worker     ucnv_fromUnicode_UTF8_OFFSETS_LOGIC,
873*0e209d39SAndroid Build Coastguard Worker     ucnv_getNextUChar_UTF8,
874*0e209d39SAndroid Build Coastguard Worker 
875*0e209d39SAndroid Build Coastguard Worker     nullptr,
876*0e209d39SAndroid Build Coastguard Worker     nullptr,
877*0e209d39SAndroid Build Coastguard Worker     nullptr,
878*0e209d39SAndroid Build Coastguard Worker     nullptr,
879*0e209d39SAndroid Build Coastguard Worker     ucnv_getNonSurrogateUnicodeSet,
880*0e209d39SAndroid Build Coastguard Worker 
881*0e209d39SAndroid Build Coastguard Worker     ucnv_UTF8FromUTF8,
882*0e209d39SAndroid Build Coastguard Worker     ucnv_UTF8FromUTF8
883*0e209d39SAndroid Build Coastguard Worker };
884*0e209d39SAndroid Build Coastguard Worker 
885*0e209d39SAndroid Build Coastguard Worker /* The 1208 CCSID refers to any version of Unicode of UTF-8 */
886*0e209d39SAndroid Build Coastguard Worker static const UConverterStaticData _UTF8StaticData={
887*0e209d39SAndroid Build Coastguard Worker     sizeof(UConverterStaticData),
888*0e209d39SAndroid Build Coastguard Worker     "UTF-8",
889*0e209d39SAndroid Build Coastguard Worker     1208, UCNV_IBM, UCNV_UTF8,
890*0e209d39SAndroid Build Coastguard Worker     1, 3, /* max 3 bytes per char16_t from UTF-8 (4 bytes from surrogate _pair_) */
891*0e209d39SAndroid Build Coastguard Worker     { 0xef, 0xbf, 0xbd, 0 },3,false,false,
892*0e209d39SAndroid Build Coastguard Worker     0,
893*0e209d39SAndroid Build Coastguard Worker     0,
894*0e209d39SAndroid Build Coastguard Worker     { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
895*0e209d39SAndroid Build Coastguard Worker };
896*0e209d39SAndroid Build Coastguard Worker 
897*0e209d39SAndroid Build Coastguard Worker 
898*0e209d39SAndroid Build Coastguard Worker const UConverterSharedData _UTF8Data=
899*0e209d39SAndroid Build Coastguard Worker         UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF8StaticData, &_UTF8Impl);
900*0e209d39SAndroid Build Coastguard Worker 
901*0e209d39SAndroid Build Coastguard Worker /* CESU-8 converter data ---------------------------------------------------- */
902*0e209d39SAndroid Build Coastguard Worker 
903*0e209d39SAndroid Build Coastguard Worker static const UConverterImpl _CESU8Impl={
904*0e209d39SAndroid Build Coastguard Worker     UCNV_CESU8,
905*0e209d39SAndroid Build Coastguard Worker 
906*0e209d39SAndroid Build Coastguard Worker     nullptr,
907*0e209d39SAndroid Build Coastguard Worker     nullptr,
908*0e209d39SAndroid Build Coastguard Worker 
909*0e209d39SAndroid Build Coastguard Worker     nullptr,
910*0e209d39SAndroid Build Coastguard Worker     nullptr,
911*0e209d39SAndroid Build Coastguard Worker     nullptr,
912*0e209d39SAndroid Build Coastguard Worker 
913*0e209d39SAndroid Build Coastguard Worker     ucnv_toUnicode_UTF8,
914*0e209d39SAndroid Build Coastguard Worker     ucnv_toUnicode_UTF8_OFFSETS_LOGIC,
915*0e209d39SAndroid Build Coastguard Worker     ucnv_fromUnicode_UTF8,
916*0e209d39SAndroid Build Coastguard Worker     ucnv_fromUnicode_UTF8_OFFSETS_LOGIC,
917*0e209d39SAndroid Build Coastguard Worker     nullptr,
918*0e209d39SAndroid Build Coastguard Worker 
919*0e209d39SAndroid Build Coastguard Worker     nullptr,
920*0e209d39SAndroid Build Coastguard Worker     nullptr,
921*0e209d39SAndroid Build Coastguard Worker     nullptr,
922*0e209d39SAndroid Build Coastguard Worker     nullptr,
923*0e209d39SAndroid Build Coastguard Worker     ucnv_getCompleteUnicodeSet,
924*0e209d39SAndroid Build Coastguard Worker 
925*0e209d39SAndroid Build Coastguard Worker     nullptr,
926*0e209d39SAndroid Build Coastguard Worker     nullptr
927*0e209d39SAndroid Build Coastguard Worker };
928*0e209d39SAndroid Build Coastguard Worker 
929*0e209d39SAndroid Build Coastguard Worker static const UConverterStaticData _CESU8StaticData={
930*0e209d39SAndroid Build Coastguard Worker     sizeof(UConverterStaticData),
931*0e209d39SAndroid Build Coastguard Worker     "CESU-8",
932*0e209d39SAndroid Build Coastguard Worker     9400, /* CCSID for CESU-8 */
933*0e209d39SAndroid Build Coastguard Worker     UCNV_UNKNOWN, UCNV_CESU8, 1, 3,
934*0e209d39SAndroid Build Coastguard Worker     { 0xef, 0xbf, 0xbd, 0 },3,false,false,
935*0e209d39SAndroid Build Coastguard Worker     0,
936*0e209d39SAndroid Build Coastguard Worker     0,
937*0e209d39SAndroid Build Coastguard Worker     { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
938*0e209d39SAndroid Build Coastguard Worker };
939*0e209d39SAndroid Build Coastguard Worker 
940*0e209d39SAndroid Build Coastguard Worker 
941*0e209d39SAndroid Build Coastguard Worker const UConverterSharedData _CESU8Data=
942*0e209d39SAndroid Build Coastguard Worker         UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_CESU8StaticData, &_CESU8Impl);
943*0e209d39SAndroid Build Coastguard Worker 
944*0e209d39SAndroid Build Coastguard Worker #endif
945