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